Source-Changes-HG archive

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

[src/netbsd-9]: src Pull up following revision(s) (requested by riastradh in ...



details:   https://anonhg.NetBSD.org/src/rev/0d540c963a7e
branches:  netbsd-9
changeset: 744785:0d540c963a7e
user:      martin <martin%NetBSD.org@localhost>
date:      Wed Feb 12 19:55:56 2020 +0000

description:
Pull up following revision(s) (requested by riastradh in ticket #701):

        external/cddl/osnet/dev/dtrace/aarch64/dtrace_isa.c: revision 1.2
        external/cddl/osnet/dist/lib/libdtrace/common/dt_open.c: revision 1.17
        external/cddl/osnet/dist/lib/libdtrace/common/dt_module.c: revision 1.18
        sys/modules/cyclic/Makefile: revision 1.5
        external/cddl/osnet/dev/dtrace/aarch64/dtrace_subr.c: revision 1.2
        external/cddl/osnet/dev/dtrace/aarch64/dtrace_subr.c: revision 1.3
        sys/arch/aarch64/aarch64/vectors.S: revision 1.10
        external/cddl/osnet/dev/fbt/aarch64/fbt_isa.c: revision 1.2
        external/cddl/osnet/dev/fbt/aarch64/fbt_isa.c: revision 1.3
        external/cddl/osnet/dev/fbt/aarch64/fbt_isa.c: revision 1.4
        external/cddl/osnet/dev/fbt/aarch64/fbt_isa.c: revision 1.5
        external/cddl/osnet/dev/fbt/aarch64/fbt_isa.c: revision 1.6
        sys/arch/aarch64/include/cpu.h: revision 1.20
        external/cddl/osnet/dist/lib/libdtrace/common/dt_impl.h: revision 1.9

Create a buffer space of 512 bytes before the trapframe.

dtrace fbt needs enough space to emulate an

        stp     x29, x30, [sp,#-FRAMESIZE]!

instruction in a function prologue.  In the aarch64 instruction
encoding, FRAMESIZE can be as large as 512 bytes, so reserve this
much space when KDTRACE_HOOKS is enabled.

Use db_write_bytes to overwrite kernel text.

Tidy up a bit.  No functional change intended.

aarch64 fbt_invop doesn't actually use the argument, but it would
make more sense for it to be the return value and/or first argument
register.  Certainly it's not `eax'!

Tidy up a bit: don't set things we won't use; assert nonzeroness.

Use /dev/ksyms, not /netbsd, for the running kernel's symbols.

Teach dtrace about el1_trap_exit frames on aarch64.

Implement dtrace_getarg and dtrace_getreg while here.

Count the number of artificial frames in aarch64 fbt probe correctly.

Change the address ranges that aarch64 considers toxic for dtrace.
`Toxic' means dtrace forbids D scripts from even attempting to read
or write at them.

Previously we considered [0, VM_MIN_KERNEL_ADDRESS) toxic, but
VM_MIN_KERNEL_ADDRESS is only the minimum address of the kernel map;
the direct-mapped region lies below it, and with PMAP_MAP_POOLPAGE we
allocate virtual pages for pool backing directly from physical pages
through the direct-mapped region.  Also, this did not consider I/O
mappings to be toxic, which they probably should be.

Instead, treat:

[0, AARCH64_KSEG_START)
and
[VM_KERNEL_IO_ADDRESS, 0xfff...ff)

as toxic.  (The upper bound for 0xfff...ff ought to be inclusive, not
exclusive, but I think we'll need another mechanism for expressing
that to dtrace!)

Switch from db_write_bytes to using direct-mapping.

This way there's no dependency on ddb.

Define the MULTIPROCESSOR cpu_number() for modules too.
Modules should work whether the main kernel is multiprocessor or not.
In particular, dtrace should not think cpu_number() is 0 while
cpu_index(curcpu()) and curcpu()->ci_index are nonzero, leading to
rather spectacularly bogus results...

cyclic.kmod needs -Wno-sign-compare for aarch64 CPU_INFO_FOREACH.
Provisional workaround; feel free to fix.

diffstat:

 external/cddl/osnet/dev/dtrace/aarch64/dtrace_isa.c       |  170 ++++++++-----
 external/cddl/osnet/dev/dtrace/aarch64/dtrace_subr.c      |   11 +-
 external/cddl/osnet/dev/fbt/aarch64/fbt_isa.c             |   43 ++-
 external/cddl/osnet/dist/lib/libdtrace/common/dt_impl.h   |    2 -
 external/cddl/osnet/dist/lib/libdtrace/common/dt_module.c |    5 +-
 external/cddl/osnet/dist/lib/libdtrace/common/dt_open.c   |   20 +-
 sys/arch/aarch64/aarch64/vectors.S                        |   18 +-
 sys/arch/aarch64/include/cpu.h                            |    4 +-
 sys/modules/cyclic/Makefile                               |    2 +-
 9 files changed, 166 insertions(+), 109 deletions(-)

diffs (truncated from 524 to 300 lines):

diff -r 587cea43e0c9 -r 0d540c963a7e external/cddl/osnet/dev/dtrace/aarch64/dtrace_isa.c
--- a/external/cddl/osnet/dev/dtrace/aarch64/dtrace_isa.c       Wed Feb 12 19:44:27 2020 +0000
+++ b/external/cddl/osnet/dev/dtrace/aarch64/dtrace_isa.c       Wed Feb 12 19:55:56 2020 +0000
@@ -89,52 +89,60 @@
 dtrace_getpcstack(pc_t *pcstack, int pcstack_limit, int aframes,
     uint32_t *intrpc)
 {
-       struct unwind_state state;
-       int scp_offset;
-       register_t sp, fp;
-       int depth;
+       extern const char el1_trap_exit[];
+       const register_t *fp;
+       int i = 0;
 
-       depth = 0;
-
-       if (intrpc != 0) {
-               pcstack[depth++] = (pc_t) intrpc;
+       if (intrpc) {
+               if (i < pcstack_limit)
+                       pcstack[i++] = (pc_t)intrpc;
        }
 
-       aframes++;
-
-       __asm __volatile("mov %0, sp" : "=&r" (sp));
-
-       state.fp = (uint64_t)__builtin_frame_address(0);
-       state.sp = sp;
-       state.pc = (uint64_t)dtrace_getpcstack;
-
-       while (depth < pcstack_limit) {
-               if (!INKERNEL(state.pc) || !INKERNEL(state.fp))
-                       break;
+       /*
+        * fp[0] = x29 (saved frame pointer)
+        * fp[1] = x30 (saved link register == return address)
+        */
+       fp = __builtin_frame_address(0);
+       while (i < pcstack_limit && INKERNEL(fp[0]) && INKERNEL(fp[1])) {
+               /* Skip the specified number of artificial frames.  */
+               if (aframes > 0)
+                       aframes--;
+               else
+                       pcstack[i++] = fp[1];
 
-               fp = state.fp;
-               state.sp = fp + 0x10;
-               /* FP to previous frame (X29) */
-               state.fp = *(register_t *)(fp);
-               /* LR (X30) */
-               state.pc = *(register_t *)(fp + 8) - 4;
-
-               /*
-                * NB: Unlike some other architectures, we don't need to
-                * explicitly insert cpu_dtrace_caller as it appears in the
-                * normal kernel stack trace rather than a special trap frame.
-                */
-               if (aframes > 0) {
-                       aframes--;
+               /* Check whether this frame is handling a trap.  */
+               if (fp[1] == (register_t)el1_trap_exit) {
+                       /*
+                        * Trap from kernel.  The trapframe is the
+                        * saved frame pointer of the call to the trap
+                        * handler whose return address is
+                        * el1_trap_exit.  The frame pointer of the
+                        * interrupted code is in x29 stashed in the
+                        * trapframe, alongside its pc.
+                        */
+                       const struct trapframe *tf = (const void *)fp[0];
+                       /* x29 = frame pointer */
+                       fp = (const void *)tf->tf_regs.r_reg[29];
+                       if (INKERNEL(tf->tf_pc)) {
+                               if (i >= pcstack_limit)
+                                       break;
+                               if (aframes > 0)
+                                       aframes--;
+                               else
+                                       pcstack[i++] = tf->tf_pc;
+                       }
                } else {
-                       pcstack[depth++] = state.pc;
+                       /*
+                        * Not a trap.  Keep going with fp[0] as the
+                        * parent frame pointer.
+                        */
+                       fp = (const void *)fp[0];
                }
-
        }
 
-       for (; depth < pcstack_limit; depth++) {
-               pcstack[depth] = 0;
-       }
+       /* Zero the rest of the return address stack.  (Paranoia?)  */
+       while (i < pcstack_limit)
+               pcstack[i++] = 0;
 }
 
 static int
@@ -282,48 +290,78 @@
 uint64_t
 dtrace_getarg(int arg, int aframes)
 {
+       extern const char el1_trap_exit[];
+       const register_t *fp;
+       const struct trapframe *tf = NULL;
+       int i = 0;
 
-       printf("IMPLEMENT ME: %s\n", __func__);
+       /*
+        * The first arguments are passed in x0,...,x7.  The rest are
+        * on the stack, too much trouble to figure out.
+        *
+        * XXX Shouldn't we ask ctf or dwarf or something to figure
+        * this stuff out for us?
+        */
+       KASSERT(arg >= 0);
+       if (arg >= 8)
+               return 0;
 
-       return (0);
+       fp = __builtin_frame_address(0);
+       while (i < 1000 && INKERNEL(fp[0]) && INKERNEL(fp[1])) {
+               if (aframes > 0)
+                       aframes--;
+               else
+                       i++;
+               if (fp[1] == (register_t)el1_trap_exit) {
+                       tf = (const void *)fp[0];
+                       break;
+               } else {
+                       fp = (const void *)fp[0];
+               }
+       }
+
+       /* If we didn't find a trap frame, give up.  */
+       if (tf == NULL)
+               return 0;
+
+       /* Arg0, arg1, ..., arg7 are in registers x0, x1, ..., x7.  */
+       return tf->tf_regs.r_reg[arg];
 }
 
 int
 dtrace_getstackdepth(int aframes)
 {
-       struct unwind_state state;
-       int scp_offset;
-       register_t sp;
-       int depth;
-       int done;
-
-       depth = 1;
-       done = 0;
-
-       __asm __volatile("mov %0, sp" : "=&r" (sp));
+       extern const char el1_trap_exit[];
+       const register_t *fp;
+       int i = 0;
 
-       state.fp = (uint64_t)__builtin_frame_address(0);
-       state.sp = sp;
-       state.pc = (uint64_t)dtrace_getstackdepth;
+       fp = __builtin_frame_address(0);
+       while (i < 1000 && INKERNEL(fp[0]) && INKERNEL(fp[1])) {
+               if (aframes > 0)
+                       aframes--;
+               else
+                       i++;
+               if (fp[1] == (register_t)el1_trap_exit) {
+                       const struct trapframe *tf = (const void *)fp[0];
+                       fp = (const void *)tf->tf_regs.r_reg[29];
+                       if (aframes > 0)
+                               aframes--;
+                       else
+                               i++;
+               } else {
+                       fp = (const void *)fp[0];
+               }
+       }
 
-       do {
-               done = unwind_frame(&state);
-               if (!INKERNEL(state.pc) || !INKERNEL(state.fp))
-                       break;
-               depth++;
-       } while (!done);
-
-       if (depth < aframes)
-               return (0);
-       else
-               return (depth - aframes);
+       return i;
 }
 
 ulong_t
-dtrace_getreg(struct trapframe *rp, uint_t reg)
+dtrace_getreg(struct trapframe *tf, uint_t reg)
 {
 
-       printf("IMPLEMENT ME: %s\n", __func__);
+       if (reg < 32)
+               return tf->tf_regs.r_reg[reg];
 
        return (0);
 }
diff -r 587cea43e0c9 -r 0d540c963a7e external/cddl/osnet/dev/dtrace/aarch64/dtrace_subr.c
--- a/external/cddl/osnet/dev/dtrace/aarch64/dtrace_subr.c      Wed Feb 12 19:44:27 2020 +0000
+++ b/external/cddl/osnet/dev/dtrace/aarch64/dtrace_subr.c      Wed Feb 12 19:55:56 2020 +0000
@@ -28,7 +28,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: dtrace_subr.c,v 1.1.2.2 2019/12/09 15:19:30 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: dtrace_subr.c,v 1.1.2.3 2020/02/12 19:55:56 martin Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -69,13 +69,13 @@
 dtrace_invop_hdlr_t *dtrace_invop_hdlr;
 
 int
-dtrace_invop(uintptr_t addr, struct trapframe *frame, uintptr_t eax)
+dtrace_invop(uintptr_t addr, struct trapframe *frame, uintptr_t r0)
 {
        dtrace_invop_hdlr_t *hdlr;
        int rval;
 
        for (hdlr = dtrace_invop_hdlr; hdlr != NULL; hdlr = hdlr->dtih_next)
-               if ((rval = hdlr->dtih_func(addr, frame, eax)) != 0)
+               if ((rval = hdlr->dtih_func(addr, frame, r0)) != 0)
                        return (rval);
 
        return (0);
@@ -128,7 +128,8 @@
 dtrace_toxic_ranges(void (*func)(uintptr_t base, uintptr_t limit))
 {
 
-       (*func)(0, (uintptr_t)VM_MIN_KERNEL_ADDRESS);
+       (*func)(0, (uintptr_t)AARCH64_KSEG_START);
+       (*func)((uintptr_t)VM_KERNEL_IO_ADDRESS, ~(uintptr_t)0);
 }
 
 static void
@@ -263,7 +264,7 @@
        int tmp;
        int i;
 
-       invop = dtrace_invop(frame->tf_pc, frame, frame->tf_pc);
+       invop = dtrace_invop(frame->tf_pc, frame, frame->tf_regs.r_reg[0]);
 
        tmp = (invop & LDP_STP_MASK);
        if (tmp == STP_64 || tmp == LDP_64) {
diff -r 587cea43e0c9 -r 0d540c963a7e external/cddl/osnet/dev/fbt/aarch64/fbt_isa.c
--- a/external/cddl/osnet/dev/fbt/aarch64/fbt_isa.c     Wed Feb 12 19:44:27 2020 +0000
+++ b/external/cddl/osnet/dev/fbt/aarch64/fbt_isa.c     Wed Feb 12 19:55:56 2020 +0000
@@ -36,6 +36,11 @@
 #include <sys/cpu.h>
 #include <sys/module.h>
 #include <sys/kmem.h>
+
+#include <uvm/uvm_extern.h>
+
+#include <dev/mm.h>
+
 #include <machine/cpufunc.h>
 
 #include <sys/dtrace.h>
@@ -49,8 +54,19 @@
 #define        FBT_ENTRY       "entry"
 #define        FBT_RETURN      "return"
 
+/*
+ * How many artificial frames appear between dtrace_probe and the
+ * interrupted function call?
+ *
+ *     fbt_invop
+ *     dtrace_invop
+ *     dtrace_invop_start
+ *     el1_trap_exit
+ */
+#define        FBT_AFRAMES     4
+
 int
-fbt_invop(uintptr_t addr, struct trapframe *frame, uintptr_t rval)
+fbt_invop(uintptr_t addr, struct trapframe *frame, uintptr_t r0)
 {
        solaris_cpu_t *cpu;
        fbt_probe_t *fbt;
@@ -67,6 +83,7 @@
                            frame->tf_regs.r_reg[3], frame->tf_regs.r_reg[4]);
 
                        cpu->cpu_dtrace_caller = 0;
+                       KASSERT(fbt->fbtp_savedval != 0);
                        return (fbt->fbtp_savedval);
                }
        }



Home | Main Index | Thread Index | Old Index