diff options
Diffstat (limited to 'sys/riscv')
-rw-r--r-- | sys/riscv/include/pcpu.h | 2 | ||||
-rw-r--r-- | sys/riscv/include/pcpu_aux.h | 3 | ||||
-rw-r--r-- | sys/riscv/include/stack.h | 6 | ||||
-rw-r--r-- | sys/riscv/riscv/db_trace.c | 18 | ||||
-rw-r--r-- | sys/riscv/riscv/locore.S | 23 | ||||
-rw-r--r-- | sys/riscv/riscv/stack_machdep.c | 19 | ||||
-rw-r--r-- | sys/riscv/riscv/trap.c | 23 | ||||
-rw-r--r-- | sys/riscv/riscv/unwind.c | 6 |
8 files changed, 61 insertions, 39 deletions
diff --git a/sys/riscv/include/pcpu.h b/sys/riscv/include/pcpu.h index 46b258380a105..5068596462fc3 100644 --- a/sys/riscv/include/pcpu.h +++ b/sys/riscv/include/pcpu.h @@ -48,7 +48,7 @@ struct pmap *pc_curpmap; /* Currently active pmap */ \ uint32_t pc_pending_ipis; /* IPIs pending to this CPU */ \ uint32_t pc_hart; /* Hart ID */ \ - char __pad[49] + char __pad[56] /* Pad to factor of PAGE_SIZE */ #ifdef _KERNEL diff --git a/sys/riscv/include/pcpu_aux.h b/sys/riscv/include/pcpu_aux.h index 3d4c70c491d62..9fecd25c67cbc 100644 --- a/sys/riscv/include/pcpu_aux.h +++ b/sys/riscv/include/pcpu_aux.h @@ -46,6 +46,9 @@ * be a multiple of the size of struct pcpu. */ _Static_assert(PAGE_SIZE % sizeof(struct pcpu) == 0, "fix pcpu size"); +_Static_assert(offsetof(struct pcpu, __pad) + + sizeof(((struct pcpu *)0)->__pad) == sizeof(struct pcpu), + "fix pcpu padding"); extern struct pcpu __pcpu[]; diff --git a/sys/riscv/include/stack.h b/sys/riscv/include/stack.h index 7f4be068ec273..40183afb9f4d6 100644 --- a/sys/riscv/include/stack.h +++ b/sys/riscv/include/stack.h @@ -41,9 +41,9 @@ (va) <= VM_MAX_KERNEL_ADDRESS) struct unwind_state { - uint64_t fp; - uint64_t sp; - uint64_t pc; + uintptr_t fp; + uintptr_t sp; + uintptr_t pc; }; int unwind_frame(struct unwind_state *); diff --git a/sys/riscv/riscv/db_trace.c b/sys/riscv/riscv/db_trace.c index 2a783b2ed0f02..6d7b6b934d43e 100644 --- a/sys/riscv/riscv/db_trace.c +++ b/sys/riscv/riscv/db_trace.c @@ -108,9 +108,9 @@ db_stack_trace_cmd(struct unwind_state *frame) db_printf("--- exception %ld, tval = %#lx\n", tf->tf_scause & EXCP_MASK, tf->tf_stval); - frame->sp = (uint64_t)tf->tf_sp; - frame->fp = (uint64_t)tf->tf_s[0]; - frame->pc = (uint64_t)tf->tf_sepc; + frame->sp = tf->tf_sp; + frame->fp = tf->tf_s[0]; + frame->pc = tf->tf_sepc; if (!INKERNEL(frame->fp)) break; continue; @@ -132,9 +132,9 @@ db_trace_thread(struct thread *thr, int count) ctx = kdb_thr_ctx(thr); - frame.sp = (uint64_t)ctx->pcb_sp; - frame.fp = (uint64_t)ctx->pcb_s[0]; - frame.pc = (uint64_t)ctx->pcb_ra; + frame.sp = ctx->pcb_sp; + frame.fp = ctx->pcb_s[0]; + frame.pc = ctx->pcb_ra; db_stack_trace_cmd(&frame); return (0); } @@ -143,12 +143,12 @@ void db_trace_self(void) { struct unwind_state frame; - uint64_t sp; + uintptr_t sp; __asm __volatile("mv %0, sp" : "=&r" (sp)); frame.sp = sp; - frame.fp = (uint64_t)__builtin_frame_address(0); - frame.pc = (uint64_t)db_trace_self; + frame.fp = (uintptr_t)__builtin_frame_address(0); + frame.pc = (uintptr_t)db_trace_self; db_stack_trace_cmd(&frame); } diff --git a/sys/riscv/riscv/locore.S b/sys/riscv/riscv/locore.S index 4a5b01df85b76..86eaab6d533b6 100644 --- a/sys/riscv/riscv/locore.S +++ b/sys/riscv/riscv/locore.S @@ -223,19 +223,21 @@ va: csrw sscratch, t0 /* Initialize stack pointer */ - la s3, initstack_end - mv sp, s3 + la sp, initstack_end + + /* Clear frame pointer */ + mv s0, zero /* Allocate space for thread0 PCB and riscv_bootparams */ addi sp, sp, -(PCB_SIZE + RISCV_BOOTPARAMS_SIZE) & ~STACKALIGNBYTES /* Clear BSS */ - la s0, _C_LABEL(__bss_start) - la s1, _C_LABEL(_end) + la t0, _C_LABEL(__bss_start) + la t1, _C_LABEL(_end) 1: - sd zero, 0(s0) - addi s0, s0, 8 - bltu s0, s1, 1b + sd zero, 0(t0) + addi t0, t0, 8 + bltu t0, t1, 1b /* Fill riscv_bootparams */ la t0, pagetable_l1 @@ -259,6 +261,11 @@ va: call _C_LABEL(initriscv) /* Off we go */ call _C_LABEL(mi_startup) + /* We should never reach here, but if so just hang. */ +2: + wfi + j 2b + /* * Get the physical address the kernel is loaded to. Returned in s9. */ @@ -350,7 +357,7 @@ ENTRY(mpentry) ld sp, 0(t0) /* Get the kernel's load address */ - jal get_physmem + jal get_physmem /* Setup supervisor trap vector */ lla t0, mpva diff --git a/sys/riscv/riscv/stack_machdep.c b/sys/riscv/riscv/stack_machdep.c index 2e016f537f91c..d4939dbda0418 100644 --- a/sys/riscv/riscv/stack_machdep.c +++ b/sys/riscv/riscv/stack_machdep.c @@ -47,15 +47,18 @@ __FBSDID("$FreeBSD$"); #include <machine/stack.h> static void -stack_capture(struct stack *st, struct unwind_state *frame) +stack_capture(struct thread *td, struct stack *st, struct unwind_state *frame) { stack_zero(st); while (1) { + if ((vm_offset_t)frame->fp < td->td_kstack || + (vm_offset_t)frame->fp >= td->td_kstack + + td->td_kstack_pages * PAGE_SIZE) + break; unwind_frame(frame); - if (!INKERNEL((vm_offset_t)frame->fp) || - !INKERNEL((vm_offset_t)frame->pc)) + if (!INKERNEL((vm_offset_t)frame->pc)) break; if (stack_put(st, frame->pc) == -1) break; @@ -78,7 +81,7 @@ stack_save_td(struct stack *st, struct thread *td) frame.fp = td->td_pcb->pcb_s[0]; frame.pc = td->td_pcb->pcb_ra; - stack_capture(st, &frame); + stack_capture(td, st, &frame); return (0); } @@ -86,13 +89,13 @@ void stack_save(struct stack *st) { struct unwind_state frame; - uint64_t sp; + uintptr_t sp; __asm __volatile("mv %0, sp" : "=&r" (sp)); frame.sp = sp; - frame.fp = (uint64_t)__builtin_frame_address(0); - frame.pc = (uint64_t)stack_save; + frame.fp = (uintptr_t)__builtin_frame_address(0); + frame.pc = (uintptr_t)stack_save; - stack_capture(st, &frame); + stack_capture(curthread, st, &frame); } diff --git a/sys/riscv/riscv/trap.c b/sys/riscv/riscv/trap.c index aa9ec534669d3..dabd84e822e94 100644 --- a/sys/riscv/riscv/trap.c +++ b/sys/riscv/riscv/trap.c @@ -198,14 +198,22 @@ data_abort(struct trapframe *frame, int usermode) "Kernel page fault") != 0) goto fatal; - if (usermode) - map = &td->td_proc->p_vmspace->vm_map; - else if (stval >= VM_MAX_USER_ADDRESS) - map = kernel_map; - else { - if (pcb->pcb_onfault == 0) - goto fatal; + if (usermode) { map = &td->td_proc->p_vmspace->vm_map; + } else { + /* + * Enable interrupts for the duration of the page fault. For + * user faults this was done already in do_trap_user(). + */ + intr_enable(); + + if (stval >= VM_MAX_USER_ADDRESS) { + map = kernel_map; + } else { + if (pcb->pcb_onfault == 0) + goto fatal; + map = &td->td_proc->p_vmspace->vm_map; + } } va = trunc_page(stval); @@ -324,6 +332,7 @@ do_trap_user(struct trapframe *frame) riscv_cpu_intr(frame); return; } + intr_enable(); CTR3(KTR_TRAP, "do_trap_user: curthread: %p, sepc: %lx, frame: %p", curthread, frame->tf_sepc, frame); diff --git a/sys/riscv/riscv/unwind.c b/sys/riscv/riscv/unwind.c index 18fc1e250c9b5..8b0cdeca29034 100644 --- a/sys/riscv/riscv/unwind.c +++ b/sys/riscv/riscv/unwind.c @@ -42,7 +42,7 @@ __FBSDID("$FreeBSD$"); int unwind_frame(struct unwind_state *frame) { - uint64_t fp; + uintptr_t fp; fp = frame->fp; @@ -50,8 +50,8 @@ unwind_frame(struct unwind_state *frame) return (-1); frame->sp = fp; - frame->fp = *(uint64_t *)(fp - 16); - frame->pc = *(uint64_t *)(fp - 8) - 4; + frame->fp = ((uintptr_t *)fp)[-2]; + frame->pc = ((uintptr_t *)fp)[-1] - 4; return (0); } |