On Tue, Mar 08 2022, Visa Hankala <[email protected]> wrote:
> This patch adds kernel stack trace saving for riscv64, for the benefit
> of dt(4) and witness(4).

Nice!

> The unwinder is slow because of the symbol
> lookup, but this can be tweaked later.

A dumb approach that appears to work: add
cpu_exception_handler_supervisor_end and cpu_exception_handler_user_end
symbols, and perform a range check.

> The limit variable prevents the unwinder from using user-controllable
> register values. The limit has to reflect the kernel stack setup in
> cpu_fork(). To ensure consistency, the stack start address is stored
> in a variable in struct pcb.
>
> OK?

Works for me on the Unmatched with dt(4), thanks.  ok jca@ fwiw

> Index: arch/riscv64/include/pcb.h
> ===================================================================
> RCS file: src/sys/arch/riscv64/include/pcb.h,v
> retrieving revision 1.3
> diff -u -p -r1.3 pcb.h
> --- arch/riscv64/include/pcb.h        30 Jun 2021 22:20:56 -0000      1.3
> +++ arch/riscv64/include/pcb.h        8 Mar 2022 16:54:58 -0000
> @@ -39,5 +39,6 @@ struct pcb {
>  
>       caddr_t         pcb_onfault;    // On fault handler
>       struct fpreg    pcb_fpstate;    // Floating Point state */
> +     register_t      pcb_kstack;     /* kernel stack address */
>  };
>  #endif       /* _MACHINE_PCB_H_ */
> Index: arch/riscv64/riscv64/db_trace.c
> ===================================================================
> RCS file: src/sys/arch/riscv64/riscv64/db_trace.c,v
> retrieving revision 1.5
> diff -u -p -r1.5 db_trace.c
> --- arch/riscv64/riscv64/db_trace.c   22 Feb 2022 07:46:04 -0000      1.5
> +++ arch/riscv64/riscv64/db_trace.c   8 Mar 2022 16:54:58 -0000
> @@ -141,3 +141,56 @@ db_stack_trace_print(db_expr_t addr, int
>       }
>       (*pr)("end trace frame: 0x%lx, count: %d\n", frame, count);
>  }
> +
> +void
> +stacktrace_save_at(struct stacktrace *st, unsigned int skip)
> +{
> +     struct callframe *frame, *lastframe, *limit;
> +     struct pcb *pcb = curpcb;
> +     Elf_Sym *sym;
> +     db_expr_t diff;
> +     vaddr_t ra, subr;
> +
> +     st->st_count = 0;
> +
> +     if (pcb == NULL)
> +             return;
> +
> +     ra = (vaddr_t)__builtin_return_address(0);
> +     frame = (struct callframe *)__builtin_frame_address(0);
> +     KASSERT(INKERNEL(frame));
> +     limit = (struct callframe *)((struct trapframe *)pcb->pcb_kstack - 1);
> +
> +     while (st->st_count < STACKTRACE_MAX) {
> +             if (skip == 0)
> +                     st->st_pc[st->st_count++] = ra;
> +             else
> +                     skip--;
> +
> +             sym = db_search_symbol(ra, DB_STGY_PROC, &diff);
> +             if (sym == NULL)
> +                     break;
> +             subr = ra - (vaddr_t)diff;
> +
> +             lastframe = frame;
> +             if (subr == (vaddr_t)cpu_exception_handler_supervisor ||
> +                 subr == (vaddr_t)cpu_exception_handler_user) {
> +                     struct trapframe *tf = (struct trapframe *)frame;
> +
> +                     frame = (struct callframe *)tf->tf_s[0];
> +                     ra = tf->tf_ra;
> +             } else {
> +                     frame = frame[-1].f_frame;
> +                     if (frame == NULL)
> +                             break;
> +                     ra = frame[-1].f_ra;
> +             }
> +
> +             if (frame <= lastframe)
> +                     break;
> +             if (frame >= limit)
> +                     break;
> +             if (!INKERNEL(ra))
> +                     break;
> +     }
> +}
> Index: arch/riscv64/riscv64/vm_machdep.c
> ===================================================================
> RCS file: src/sys/arch/riscv64/riscv64/vm_machdep.c,v
> retrieving revision 1.10
> diff -u -p -r1.10 vm_machdep.c
> --- arch/riscv64/riscv64/vm_machdep.c 24 Feb 2022 14:19:10 -0000      1.10
> +++ arch/riscv64/riscv64/vm_machdep.c 8 Mar 2022 16:54:58 -0000
> @@ -75,13 +75,12 @@ cpu_fork(struct proc *p1, struct proc *p
>  
>       pmap_activate(p2);
>  
> -     tf = (struct trapframe *)((u_long)p2->p_addr
> +     pcb->pcb_kstack = STACKALIGN((u_long)p2->p_addr
>           + USPACE
> -         - sizeof(struct trapframe)
>           - sizeof(register_t)        /* for holding curcpu */
>           - 0x10);
>  
> -     tf = (struct trapframe *)STACKALIGN(tf);
> +     tf = (struct trapframe *)pcb->pcb_kstack - 1;
>       pcb->pcb_tf = tf;
>       *tf = *p1->p_addr->u_pcb.pcb_tf;
>  
>

-- 
jca | PGP : 0x1524E7EE / 5135 92C1 AD36 5293 2BDF  DDCC 0DFA 74AE 1524 E7EE

Reply via email to