Module Name:    src
Committed By:   riastradh
Date:           Tue Sep  7 11:00:02 UTC 2021

Modified Files:
        src/sys/arch/sparc64/sparc64: machdep.c
        src/sys/kern: kern_ksyms.c subr_csan.c subr_msan.c
        src/sys/sys: ksyms.h

Log Message:
ksyms: Use pserialize(9) for kernel access to ksyms.

This makes it available in interrupt context, e.g. for printing
messages with kernel symbol names for return addresses as drm wants
to do.


To generate a diff of this commit:
cvs rdiff -u -r1.300 -r1.301 src/sys/arch/sparc64/sparc64/machdep.c
cvs rdiff -u -r1.99 -r1.100 src/sys/kern/kern_ksyms.c
cvs rdiff -u -r1.10 -r1.11 src/sys/kern/subr_csan.c
cvs rdiff -u -r1.14 -r1.15 src/sys/kern/subr_msan.c
cvs rdiff -u -r1.39 -r1.40 src/sys/sys/ksyms.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/sparc64/sparc64/machdep.c
diff -u src/sys/arch/sparc64/sparc64/machdep.c:1.300 src/sys/arch/sparc64/sparc64/machdep.c:1.301
--- src/sys/arch/sparc64/sparc64/machdep.c:1.300	Mon Aug  9 21:08:06 2021
+++ src/sys/arch/sparc64/sparc64/machdep.c	Tue Sep  7 11:00:02 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: machdep.c,v 1.300 2021/08/09 21:08:06 andvar Exp $ */
+/*	$NetBSD: machdep.c,v 1.301 2021/09/07 11:00:02 riastradh Exp $ */
 
 /*-
  * Copyright (c) 1996, 1997, 1998, 2019 The NetBSD Foundation, Inc.
@@ -71,7 +71,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.300 2021/08/09 21:08:06 andvar Exp $");
+__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.301 2021/09/07 11:00:02 riastradh Exp $");
 
 #include "opt_ddb.h"
 #include "opt_multiprocessor.h"
@@ -102,6 +102,7 @@ __KERNEL_RCSID(0, "$NetBSD: machdep.c,v 
 #include <sys/cpu.h>
 #include <sys/module.h>
 #include <sys/ksyms.h>
+#include <sys/pserialize.h>
 
 #include <sys/exec_aout.h>
 
@@ -836,17 +837,22 @@ get_symbol_and_offset(const char **mod, 
 {
 	static char symbuf[256];
 	unsigned long symaddr;
+	int s, error;
 
 #if NKSYMS || defined(DDB) || defined(MODULAR)
+	s = pserialize_read_enter();
 	if (ksyms_getname(mod, sym, pc,
 			  KSYMS_CLOSEST|KSYMS_PROC|KSYMS_ANY) == 0) {
-		if (ksyms_getval(*mod, *sym, &symaddr,
-				 KSYMS_CLOSEST|KSYMS_PROC|KSYMS_ANY) != 0)
+		error = ksyms_getval(*mod, *sym, &symaddr,
+		    KSYMS_CLOSEST|KSYMS_PROC|KSYMS_ANY);
+		pserialize_read_exit(s);
+		if (error)
 			goto failed;
 
 		*offset = (vaddr_t)(pc - symaddr);
 		return;
 	}
+	pserialize_read_exit(s);
 #endif
  failed:
 	snprintf(symbuf, sizeof symbuf, "%llx", (unsigned long long)pc);

Index: src/sys/kern/kern_ksyms.c
diff -u src/sys/kern/kern_ksyms.c:1.99 src/sys/kern/kern_ksyms.c:1.100
--- src/sys/kern/kern_ksyms.c:1.99	Tue Sep  7 10:59:46 2021
+++ src/sys/kern/kern_ksyms.c	Tue Sep  7 11:00:02 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_ksyms.c,v 1.99 2021/09/07 10:59:46 riastradh Exp $	*/
+/*	$NetBSD: kern_ksyms.c,v 1.100 2021/09/07 11:00:02 riastradh Exp $	*/
 
 /*-
  * Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -73,7 +73,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_ksyms.c,v 1.99 2021/09/07 10:59:46 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_ksyms.c,v 1.100 2021/09/07 11:00:02 riastradh Exp $");
 
 #if defined(_KERNEL) && defined(_KERNEL_OPT)
 #include "opt_copy_symtab.h"
@@ -94,6 +94,7 @@ __KERNEL_RCSID(0, "$NetBSD: kern_ksyms.c
 #include <sys/ksyms.h>
 #include <sys/kernel.h>
 #include <sys/intr.h>
+#include <sys/pserialize.h>
 
 #ifdef DDB
 #include <ddb/db_output.h>
@@ -118,6 +119,7 @@ static bool ksyms_initted;
 static bool ksyms_loaded;
 static kmutex_t ksyms_lock __cacheline_aligned;
 static kcondvar_t ksyms_cv;
+static pserialize_t ksyms_psz __read_mostly;
 static struct ksyms_symtab kernel_symtab;
 
 static void ksyms_hdr_init(const void *);
@@ -146,6 +148,7 @@ int ksyms_strsz;
 int ksyms_ctfsz;	/* this is not currently used by savecore(8) */
 TAILQ_HEAD(ksyms_symtab_queue, ksyms_symtab) ksyms_symtabs =
     TAILQ_HEAD_INITIALIZER(ksyms_symtabs);
+static struct pslist_head ksyms_symtabs_psz = PSLIST_INITIALIZER;
 
 static int
 ksyms_verify(const void *symstart, const void *strstart)
@@ -247,6 +250,7 @@ ksyms_init(void)
 	if (!ksyms_initted) {
 		mutex_init(&ksyms_lock, MUTEX_DEFAULT, IPL_NONE);
 		cv_init(&ksyms_cv, "ksyms");
+		ksyms_psz = pserialize_create();
 		ksyms_initted = true;
 	}
 }
@@ -449,9 +453,19 @@ addsymtab(const char *name, void *symsta
 	/*
 	 * Publish the symtab.  Do this at splhigh to ensure ddb never
 	 * witnesses an inconsistent state of the queue, unless memory
-	 * is so corrupt that we crash in TAILQ_INSERT_TAIL.
+	 * is so corrupt that we crash in PSLIST_WRITER_INSERT_AFTER or
+	 * TAILQ_INSERT_TAIL.
 	 */
+	PSLIST_ENTRY_INIT(tab, sd_pslist);
 	s = splhigh();
+	if (TAILQ_EMPTY(&ksyms_symtabs)) {
+		PSLIST_WRITER_INSERT_HEAD(&ksyms_symtabs_psz, tab, sd_pslist);
+	} else {
+		struct ksyms_symtab *last;
+
+		last = TAILQ_LAST(&ksyms_symtabs, ksyms_symtab_queue);
+		PSLIST_WRITER_INSERT_AFTER(last, tab, sd_pslist);
+	}
 	TAILQ_INSERT_TAIL(&ksyms_symtabs, tab, sd_queue);
 	splx(s);
 
@@ -587,7 +601,9 @@ ksyms_addsyms_explicit(void *ehdr, void 
  * "val" is a pointer to the corresponding value, if call succeeded.
  * Returns 0 if success or ENOENT if no such entry.
  *
- * Call with ksyms_lock, unless known that the symbol table can't change.
+ * If symp is nonnull, caller must hold ksyms_lock or module_lock, have
+ * ksyms_opencnt nonzero, be in a pserialize read section, be in ddb
+ * with all other CPUs quiescent.
  */
 int
 ksyms_getval_unlocked(const char *mod, const char *sym, Elf_Sym **symp,
@@ -595,51 +611,61 @@ ksyms_getval_unlocked(const char *mod, c
 {
 	struct ksyms_symtab *st;
 	Elf_Sym *es;
+	int s, error = ENOENT;
 
 #ifdef KSYMS_DEBUG
 	if (ksyms_debug & FOLLOW_CALLS)
 		printf("%s: mod %s sym %s valp %p\n", __func__, mod, sym, val);
 #endif
 
-	TAILQ_FOREACH(st, &ksyms_symtabs, sd_queue) {
+	s = pserialize_read_enter();
+	PSLIST_READER_FOREACH(st, &ksyms_symtabs_psz, struct ksyms_symtab,
+	    sd_pslist) {
 		if (mod != NULL && strcmp(st->sd_name, mod))
 			continue;
 		if ((es = findsym(sym, st, type)) != NULL) {
 			*val = es->st_value;
 			if (symp)
 				*symp = es;
-			return 0;
+			error = 0;
+			break;
 		}
 	}
-	return ENOENT;
+	pserialize_read_exit(s);
+	return error;
 }
 
 int
 ksyms_getval(const char *mod, const char *sym, unsigned long *val, int type)
 {
-	int rc;
 
 	if (!ksyms_loaded)
 		return ENOENT;
 
-	mutex_enter(&ksyms_lock);
-	rc = ksyms_getval_unlocked(mod, sym, NULL, val, type);
-	mutex_exit(&ksyms_lock);
-	return rc;
+	/* No locking needed -- we read the table pserialized.  */
+	return ksyms_getval_unlocked(mod, sym, NULL, val, type);
 }
 
+/*
+ * ksyms_get_mod(mod)
+ *
+ * Return the symtab for the given module name.  Caller must ensure
+ * that the module cannot be unloaded until after this returns.
+ */
 struct ksyms_symtab *
 ksyms_get_mod(const char *mod)
 {
 	struct ksyms_symtab *st;
+	int s;
 
-	mutex_enter(&ksyms_lock);
-	TAILQ_FOREACH(st, &ksyms_symtabs, sd_queue) {
+	s = pserialize_read_enter();
+	PSLIST_READER_FOREACH(st, &ksyms_symtabs_psz, struct ksyms_symtab,
+	    sd_pslist) {
 		if (mod != NULL && strcmp(st->sd_name, mod))
 			continue;
 		break;
 	}
-	mutex_exit(&ksyms_lock);
+	pserialize_read_exit(s);
 
 	return st;
 }
@@ -695,7 +721,9 @@ ksyms_mod_foreach(const char *mod, ksyms
  * Get "mod" and "symbol" associated with an address.
  * Returns 0 if success or ENOENT if no such entry.
  *
- * Call with ksyms_lock, unless known that the symbol table can't change.
+ * Caller must hold ksyms_lock or module_lock, have ksyms_opencnt
+ * nonzero, be in a pserialize read section, or be in ddb with all
+ * other CPUs quiescent.
  */
 int
 ksyms_getname(const char **mod, const char **sym, vaddr_t v, int f)
@@ -710,7 +738,8 @@ ksyms_getname(const char **mod, const ch
 	if (!ksyms_loaded)
 		return ENOENT;
 
-	TAILQ_FOREACH(st, &ksyms_symtabs, sd_queue) {
+	PSLIST_READER_FOREACH(st, &ksyms_symtabs_psz, struct ksyms_symtab,
+	    sd_pslist) {
 		if (v < st->sd_minsym || v > st->sd_maxsym)
 			continue;
 		sz = st->sd_symsize/sizeof(Elf_Sym);
@@ -795,12 +824,21 @@ ksyms_modunload(const char *name)
 	/*
 	 * Remove the symtab.  Do this at splhigh to ensure ddb never
 	 * witnesses an inconsistent state of the queue, unless memory
-	 * is so corrupt that we crash in TAILQ_REMOVE.
+	 * is so corrupt that we crash in TAILQ_REMOVE or
+	 * PSLIST_WRITER_REMOVE.
 	 */
 	s = splhigh();
 	TAILQ_REMOVE(&ksyms_symtabs, st, sd_queue);
+	PSLIST_WRITER_REMOVE(st, sd_pslist);
 	splx(s);
 
+	/*
+	 * And wait a grace period, in case there are any pserialized
+	 * readers in flight.
+	 */
+	pserialize_perform(ksyms_psz);
+	PSLIST_ENTRY_DESTROY(st, sd_pslist);
+
 	/* Recompute the ksyms sizes now that we've removed st.  */
 	ksyms_sizes_calc();
 	mutex_exit(&ksyms_lock);
@@ -1142,7 +1180,7 @@ ksymsioctl(dev_t dev, u_long cmd, void *
 	unsigned long val;
 	int error = 0;
 	char *str = NULL;
-	int len;
+	int len, s;
 
 	/* Read ksyms_maxlen only once while not holding the lock. */
 	len = ksyms_maxlen;
@@ -1173,8 +1211,9 @@ ksymsioctl(dev_t dev, u_long cmd, void *
 		 * Use the in-kernel symbol lookup code for fast
 		 * retreival of a symbol.
 		 */
-		mutex_enter(&ksyms_lock);
-		TAILQ_FOREACH(st, &ksyms_symtabs, sd_queue) {
+		s = pserialize_read_enter();
+		PSLIST_READER_FOREACH(st, &ksyms_symtabs_psz,
+		    struct ksyms_symtab, sd_pslist) {
 			if ((sym = findsym(str, st, KSYMS_ANY)) == NULL)
 				continue;
 #ifdef notdef
@@ -1188,10 +1227,10 @@ ksymsioctl(dev_t dev, u_long cmd, void *
 		}
 		if (sym != NULL) {
 			memcpy(&copy, sym, sizeof(copy));
-			mutex_exit(&ksyms_lock);
+			pserialize_read_exit(s);
 			error = copyout(&copy, okg->kg_sym, sizeof(Elf_Sym));
 		} else {
-			mutex_exit(&ksyms_lock);
+			pserialize_read_exit(s);
 			error = ENOENT;
 		}
 		kmem_free(str, len);
@@ -1213,8 +1252,9 @@ ksymsioctl(dev_t dev, u_long cmd, void *
 		 * Use the in-kernel symbol lookup code for fast
 		 * retreival of a symbol.
 		 */
-		mutex_enter(&ksyms_lock);
-		TAILQ_FOREACH(st, &ksyms_symtabs, sd_queue) {
+		s = pserialize_read_enter();
+		PSLIST_READER_FOREACH(st, &ksyms_symtabs_psz,
+		    struct ksyms_symtab, sd_pslist) {
 			if ((sym = findsym(str, st, KSYMS_ANY)) == NULL)
 				continue;
 #ifdef notdef
@@ -1231,7 +1271,7 @@ ksymsioctl(dev_t dev, u_long cmd, void *
 		} else {
 			error = ENOENT;
 		}
-		mutex_exit(&ksyms_lock);
+		pserialize_read_exit(s);
 		kmem_free(str, len);
 		break;
 

Index: src/sys/kern/subr_csan.c
diff -u src/sys/kern/subr_csan.c:1.10 src/sys/kern/subr_csan.c:1.11
--- src/sys/kern/subr_csan.c:1.10	Thu Sep 10 14:04:45 2020
+++ src/sys/kern/subr_csan.c	Tue Sep  7 11:00:02 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: subr_csan.c,v 1.10 2020/09/10 14:04:45 maxv Exp $	*/
+/*	$NetBSD: subr_csan.c,v 1.11 2021/09/07 11:00:02 riastradh Exp $	*/
 
 /*
  * Copyright (c) 2019-2020 Maxime Villard, m00nbsd.net
@@ -29,7 +29,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: subr_csan.c,v 1.10 2020/09/10 14:04:45 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: subr_csan.c,v 1.11 2021/09/07 11:00:02 riastradh Exp $");
 
 #include <sys/param.h>
 #include <sys/device.h>
@@ -40,6 +40,7 @@ __KERNEL_RCSID(0, "$NetBSD: subr_csan.c,
 #include <sys/types.h>
 #include <sys/csan.h>
 #include <sys/cpu.h>
+#include <sys/pserialize.h>
 
 #ifdef KCSAN_PANIC
 #define REPORT panic
@@ -94,7 +95,9 @@ static inline void
 kcsan_report(csan_cell_t *new, cpuid_t newcpu, csan_cell_t *old, cpuid_t oldcpu)
 {
 	const char *newsym, *oldsym;
+	int s;
 
+	s = pserialize_read_enter();
 	if (ksyms_getname(NULL, &newsym, (vaddr_t)new->pc, KSYMS_PROC) != 0) {
 		newsym = "Unknown";
 	}
@@ -110,6 +113,7 @@ kcsan_report(csan_cell_t *new, cpuid_t n
 	    oldcpu,
 	    (old->atomic ? "Atomic " : ""), (old->write ? "Write" : "Read"),
 	    (void *)old->addr, old->size, (void *)old->pc, oldsym);
+	pserialize_read_exit(s);
 	kcsan_md_unwind();
 }
 

Index: src/sys/kern/subr_msan.c
diff -u src/sys/kern/subr_msan.c:1.14 src/sys/kern/subr_msan.c:1.15
--- src/sys/kern/subr_msan.c:1.14	Wed Sep  9 16:29:59 2020
+++ src/sys/kern/subr_msan.c	Tue Sep  7 11:00:02 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: subr_msan.c,v 1.14 2020/09/09 16:29:59 maxv Exp $	*/
+/*	$NetBSD: subr_msan.c,v 1.15 2021/09/07 11:00:02 riastradh Exp $	*/
 
 /*
  * Copyright (c) 2019-2020 Maxime Villard, m00nbsd.net
@@ -29,7 +29,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: subr_msan.c,v 1.14 2020/09/09 16:29:59 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: subr_msan.c,v 1.15 2021/09/07 11:00:02 riastradh Exp $");
 
 #include <sys/param.h>
 #include <sys/device.h>
@@ -152,6 +152,7 @@ kmsan_report_hook(const void *addr, size
 	uintptr_t ptr;
 	char buf[128];
 	int type;
+	int s;
 
 	if (__predict_false(panicstr != NULL || db_active || kmsan_reporting))
 		return;
@@ -172,6 +173,7 @@ kmsan_report_hook(const void *addr, size
 	typename = kmsan_orig_name(type);
 
 	if (kmsan_md_is_pc(ptr)) {
+		s = pserialize_read_enter();
 		if (ksyms_getname(&mod, &sym, (vaddr_t)ptr, KSYMS_PROC)) {
 			REPORT("MSan: Uninitialized %s Memory In %s "
 			    "At Offset %zu/%zu, IP %p\n", typename, hook, off,
@@ -181,6 +183,7 @@ kmsan_report_hook(const void *addr, size
 			    "At Offset %zu/%zu, From %s()\n", typename, hook,
 			    off, size, sym);
 		}
+		pserialize_read_exit(s);
 	} else {
 		var = (char *)ptr + 4;
 		strlcpy(buf, var, sizeof(buf));
@@ -208,6 +211,7 @@ kmsan_report_inline(msan_orig_t orig, un
 	uintptr_t ptr;
 	char buf[128];
 	int type;
+	int s;
 
 	if (__predict_false(panicstr != NULL || db_active || kmsan_reporting))
 		return;
@@ -225,6 +229,7 @@ kmsan_report_inline(msan_orig_t orig, un
 	typename = kmsan_orig_name(type);
 
 	if (kmsan_md_is_pc(ptr)) {
+		s = pserialize_read_enter();
 		if (ksyms_getname(&mod, &sym, (vaddr_t)ptr, KSYMS_PROC)) {
 			REPORT("MSan: Uninitialized %s Memory, "
 			    "Origin %x\n", typename, orig);
@@ -232,6 +237,7 @@ kmsan_report_inline(msan_orig_t orig, un
 			REPORT("MSan: Uninitialized %s Memory "
 			    "From %s()\n", typename, sym);
 		}
+		pserialize_read_exit(s);
 	} else {
 		var = (char *)ptr + 4;
 		strlcpy(buf, var, sizeof(buf));

Index: src/sys/sys/ksyms.h
diff -u src/sys/sys/ksyms.h:1.39 src/sys/sys/ksyms.h:1.40
--- src/sys/sys/ksyms.h:1.39	Thu Sep 24 09:37:07 2020
+++ src/sys/sys/ksyms.h	Tue Sep  7 11:00:02 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: ksyms.h,v 1.39 2020/09/24 09:37:07 mrg Exp $	*/
+/*	$NetBSD: ksyms.h,v 1.40 2021/09/07 11:00:02 riastradh Exp $	*/
 
 /*
  * Copyright (c) 2001, 2003 Anders Magnusson (ra...@ludd.luth.se).
@@ -39,6 +39,10 @@
 #include <sys/ioccom.h>
 #include <sys/queue.h>
 
+#ifdef _KERNEL
+#include <sys/pslist.h>
+#endif
+
 struct ksyms_symtab {
 	TAILQ_ENTRY(ksyms_symtab) sd_queue; /* All active tables */
 	const char *sd_name;	/* Name of this table */
@@ -55,6 +59,10 @@ struct ksyms_symtab {
 	int sd_ctfsize;		/* Size in bytes of CTF contents */
 	uint32_t *sd_nmap;	/* Name map for sorted symbols */
 	int sd_nmapsize;	/* Total span of map */
+
+#ifdef _KERNEL
+	struct pslist_entry sd_pslist;
+#endif
 };
 
 /*

Reply via email to