Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/sys ksyms: Use pserialize(9) for kernel access to ksyms.



details:   https://anonhg.NetBSD.org/src/rev/ffe34a5990a7
branches:  trunk
changeset: 985853:ffe34a5990a7
user:      riastradh <riastradh%NetBSD.org@localhost>
date:      Sat Sep 11 10:09:55 2021 +0000

description:
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.

diffstat:

 sys/arch/sparc64/sparc64/machdep.c |  14 ++++-
 sys/kern/kern_ksyms.c              |  92 +++++++++++++++++++++++++++----------
 sys/kern/subr_csan.c               |   8 ++-
 sys/kern/subr_msan.c               |  10 +++-
 sys/sys/ksyms.h                    |  10 +++-
 5 files changed, 99 insertions(+), 35 deletions(-)

diffs (truncated from 446 to 300 lines):

diff -r 959582aab10b -r ffe34a5990a7 sys/arch/sparc64/sparc64/machdep.c
--- a/sys/arch/sparc64/sparc64/machdep.c        Sat Sep 11 10:09:31 2021 +0000
+++ b/sys/arch/sparc64/sparc64/machdep.c        Sat Sep 11 10:09:55 2021 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: machdep.c,v 1.302 2021/09/07 16:56:13 riastradh Exp $ */
+/*     $NetBSD: machdep.c,v 1.303 2021/09/11 10:09:55 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.302 2021/09/07 16:56:13 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.303 2021/09/11 10:09:55 riastradh Exp $");
 
 #include "opt_ddb.h"
 #include "opt_multiprocessor.h"
@@ -102,6 +102,7 @@
 #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 @@
 {
        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);
diff -r 959582aab10b -r ffe34a5990a7 sys/kern/kern_ksyms.c
--- a/sys/kern/kern_ksyms.c     Sat Sep 11 10:09:31 2021 +0000
+++ b/sys/kern/kern_ksyms.c     Sat Sep 11 10:09:55 2021 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: kern_ksyms.c,v 1.103 2021/09/11 10:09:31 riastradh Exp $       */
+/*     $NetBSD: kern_ksyms.c,v 1.104 2021/09/11 10:09:55 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.103 2021/09/11 10:09:31 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_ksyms.c,v 1.104 2021/09/11 10:09:55 riastradh Exp $");
 
 #if defined(_KERNEL) && defined(_KERNEL_OPT)
 #include "opt_copy_symtab.h"
@@ -97,6 +97,7 @@
 #include <sys/ksyms.h>
 #include <sys/kernel.h>
 #include <sys/intr.h>
+#include <sys/pserialize.h>
 #include <sys/stat.h>
 
 #include <uvm/uvm_extern.h>
@@ -135,6 +136,7 @@
 static struct lwp *ksyms_snapshotting;
 static struct ksyms_snapshot *ksyms_snapshot;
 static uint64_t ksyms_snapshot_gen;
+static pserialize_t ksyms_psz __read_mostly;
 
 static void ksyms_hdr_init(const void *);
 static void ksyms_sizes_calc(void);
@@ -165,6 +167,7 @@
 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)
@@ -266,6 +269,7 @@
        if (!ksyms_initted) {
                mutex_init(&ksyms_lock, MUTEX_DEFAULT, IPL_NONE);
                cv_init(&ksyms_cv, "ksyms");
+               ksyms_psz = pserialize_create();
                ksyms_initted = true;
        }
 }
@@ -468,9 +472,19 @@
        /*
         * 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);
 
@@ -612,7 +626,9 @@
  * "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,
@@ -620,51 +636,61 @@
 {
        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;
 }
@@ -720,7 +746,9 @@
  * 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)
@@ -735,7 +763,8 @@
        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);
@@ -822,12 +851,21 @@
        /*
         * 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();
 
@@ -1431,7 +1469,7 @@
        unsigned long val;
        int error = 0;
        char *str = NULL;
-       int len;
+       int len, s;
 
        /* Read cached ksyms_maxlen.  */
        len = ks->ks_maxlen;
@@ -1462,8 +1500,9 @@
                 * 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
@@ -1477,10 +1516,10 @@
                }
                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);
@@ -1502,8 +1541,9 @@
                 * 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
@@ -1520,7 +1560,7 @@
                } else {
                        error = ENOENT;
                }



Home | Main Index | Thread Index | Old Index