4 #include <arch/console.h>
18 /* These are the stacks the kernel will load when it receives a trap from user
19 * space. The deal is that they get set right away in entry.S, and can always
20 * be used for finding the top of the stack (from which you should subtract the
21 * sizeof the trapframe. Note, we need to have a junk value in the array so
22 * that this is NOT part of the BSS. If it is in the BSS, it will get 0'd in
23 * kernel_init(), which is after these values get set.
25 * TODO: if these end up becoming contended cache lines, move this to
27 uintptr_t core_stacktops[MAX_NUM_CPUS] = {0xcafebabe, 0};
30 advance_pc(struct hw_trapframe *state)
35 /* Set stacktop for the current core to be the stack the kernel will start on
36 * when trapping/interrupting from userspace */
37 void set_stack_top(uintptr_t stacktop)
39 core_stacktops[core_id()] = stacktop;
42 /* Note the assertion assumes we are in the top page of the stack. */
43 uintptr_t get_stack_top(void)
45 register uintptr_t sp asm ("sp");
46 uintptr_t stacktop = core_stacktops[core_id()];
47 assert(ROUNDUP(sp, PGSIZE) == stacktop);
56 /* Helper. For now, this copies out the TF to pcpui, and sets cur_ctx to point
58 static void set_current_ctx_hw(struct per_cpu_info *pcpui,
59 struct hw_trapframe *hw_tf)
62 warn("Turn off IRQs until cur_ctx is set!");
63 assert(!pcpui->cur_ctx);
64 pcpui->actual_ctx.type = ROS_HW_CTX;
65 pcpui->actual_ctx.tf.hw_tf = *hw_tf;
66 pcpui->cur_ctx = &pcpui->actual_ctx;
69 static void set_current_ctx_sw(struct per_cpu_info *pcpui,
70 struct sw_trapframe *sw_tf)
73 warn("Turn off IRQs until cur_ctx is set!");
74 assert(!pcpui->cur_ctx);
75 pcpui->actual_ctx.type = ROS_SW_CTX;
76 pcpui->actual_ctx.tf.sw_tf = *sw_tf;
77 pcpui->cur_ctx = &pcpui->actual_ctx;
81 format_trapframe(struct hw_trapframe *hw_tf, char* buf, int bufsz)
83 // slightly hackish way to read out the instruction that faulted.
84 // not guaranteed to be right 100% of the time
86 if(!(current && !memcpy_from_user(current,&insn,(void*)hw_tf->epc,4)))
89 int len = snprintf(buf,bufsz,"TRAP frame at %p on core %d\n",
91 static const char* regnames[] = {
92 "z ", "ra", "s0", "s1", "s2", "s3", "s4", "s5",
93 "s6", "s7", "s8", "s9", "sA", "sB", "sp", "tp",
94 "v0", "v1", "a0", "a1", "a2", "a3", "a4", "a5",
95 "a6", "a7", "a8", "a9", "aA", "aB", "aC", "aD"
100 for(int i = 0; i < 32; i+=4)
102 for(int j = 0; j < 4; j++)
103 len += snprintf(buf+len, bufsz-len,
104 "%s %016lx%c", regnames[i+j], hw_tf->gpr[i+j],
107 len += snprintf(buf+len, bufsz-len,
108 "sr %016lx pc %016lx va %016lx insn %08x\n",
109 hw_tf->sr, hw_tf->epc, hw_tf->badvaddr, insn);
116 print_trapframe(struct hw_trapframe *hw_tf)
119 int len = format_trapframe(hw_tf, buf, sizeof(buf));
123 static void exit_halt_loop(struct hw_trapframe *hw_tf)
125 extern char after_cpu_halt;
126 if ((char*)hw_tf->epc >= (char*)&cpu_halt &&
127 (char*)hw_tf->epc < &after_cpu_halt)
128 hw_tf->epc = hw_tf->gpr[GPR_RA];
131 static void handle_keypress(char c)
133 /* brho: not sure if this will work on riscv or not... */
134 #define capchar2ctl(x) ((x) - '@')
135 amr_t handler = c == capchar2ctl('G') ? __run_mon : __cons_add_char;
136 send_kernel_message(core_id(), handler, (long)&cons_buf, (long)c, 0,
141 static void handle_host_interrupt(struct hw_trapframe *hw_tf)
143 uintptr_t fh = mtpcr(PCR_FROMHOST, 0);
147 case 0x01: handle_keypress(fh); return;
152 static void handle_timer_interrupt(struct hw_trapframe *hw_tf)
154 timer_interrupt(hw_tf, NULL);
157 /* Assumes that any IPI you get is really a kernel message */
158 static void handle_interprocessor_interrupt(struct hw_trapframe *hw_tf)
161 handle_kmsg_ipi(hw_tf, 0);
165 unhandled_trap(struct hw_trapframe *state, const char* name)
167 static spinlock_t screwup_lock = SPINLOCK_INITIALIZER;
168 spin_lock(&screwup_lock);
172 print_trapframe(state);
173 panic("Unhandled trap in kernel!\nTrap type: %s", name);
178 format_trapframe(state, tf_buf, sizeof(tf_buf));
180 warn("Unhandled trap in user!\nTrap type: %s\n%s", name, tf_buf);
182 spin_unlock(&screwup_lock);
186 proc_destroy(current);
191 handle_misaligned_fetch(struct hw_trapframe *state)
193 unhandled_trap(state, "Misaligned Fetch");
197 handle_misaligned_load(struct hw_trapframe *state)
199 unhandled_trap(state, "Misaligned Load");
203 handle_misaligned_store(struct hw_trapframe *state)
205 unhandled_trap(state, "Misaligned Store");
209 handle_fault_fetch(struct hw_trapframe *state)
213 print_trapframe(state);
214 panic("Instruction Page Fault in the Kernel at %p!", state->epc);
217 set_current_ctx_hw(&per_cpu_info[core_id()], state);
219 #warning "returns EAGAIN if you should reflect the fault"
220 if(handle_page_fault(current, state->epc, PROT_EXEC))
221 unhandled_trap(state, "Instruction Page Fault");
225 handle_fault_load(struct hw_trapframe *state)
229 print_trapframe(state);
230 panic("Load Page Fault in the Kernel at %p!", state->badvaddr);
233 set_current_ctx_hw(&per_cpu_info[core_id()], state);
235 #warning "returns EAGAIN if you should reflect the fault"
236 if(handle_page_fault(current, state->badvaddr, PROT_READ))
237 unhandled_trap(state, "Load Page Fault");
241 handle_fault_store(struct hw_trapframe *state)
245 print_trapframe(state);
246 panic("Store Page Fault in the Kernel at %p!", state->badvaddr);
249 set_current_ctx_hw(&per_cpu_info[core_id()], state);
251 if(handle_page_fault(current, state->badvaddr, PROT_WRITE))
252 unhandled_trap(state, "Store Page Fault");
256 handle_illegal_instruction(struct hw_trapframe *state)
258 assert(!in_kernel(state));
260 struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
261 set_current_ctx_hw(pcpui, state);
262 if (emulate_fpu(state) == 0)
264 advance_pc(&pcpui->cur_ctx->tf.hw_tf);
268 unhandled_trap(state, "Illegal Instruction");
272 handle_syscall(struct hw_trapframe *state)
274 uintptr_t a0 = state->gpr[GPR_A0];
275 uintptr_t a1 = state->gpr[GPR_A1];
278 set_current_ctx_hw(&per_cpu_info[core_id()], state);
280 prep_syscalls(current, (struct syscall*)a0, a1);
284 handle_breakpoint(struct hw_trapframe *state)
291 handle_trap(struct hw_trapframe *hw_tf)
293 static void (*const trap_handlers[])(struct hw_trapframe *) = {
294 [CAUSE_MISALIGNED_FETCH] = handle_misaligned_fetch,
295 [CAUSE_FAULT_FETCH] = handle_fault_fetch,
296 [CAUSE_ILLEGAL_INSTRUCTION] = handle_illegal_instruction,
297 [CAUSE_PRIVILEGED_INSTRUCTION] = handle_illegal_instruction,
298 [CAUSE_SYSCALL] = handle_syscall,
299 [CAUSE_BREAKPOINT] = handle_breakpoint,
300 [CAUSE_MISALIGNED_LOAD] = handle_misaligned_load,
301 [CAUSE_MISALIGNED_STORE] = handle_misaligned_store,
302 [CAUSE_FAULT_LOAD] = handle_fault_load,
303 [CAUSE_FAULT_STORE] = handle_fault_store,
306 static void (*const irq_handlers[])(struct hw_trapframe *) = {
307 [IRQ_TIMER] = handle_timer_interrupt,
308 [IRQ_HOST] = handle_host_interrupt,
309 [IRQ_IPI] = handle_interprocessor_interrupt,
312 struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
313 if (hw_tf->cause < 0)
315 uint8_t irq = hw_tf->cause;
316 assert(irq < sizeof(irq_handlers)/sizeof(irq_handlers[0]) &&
319 if (in_kernel(hw_tf))
320 exit_halt_loop(hw_tf);
322 set_current_ctx_hw(&per_cpu_info[core_id()], hw_tf);
324 inc_irq_depth(pcpui);
325 irq_handlers[irq](hw_tf);
326 dec_irq_depth(pcpui);
330 assert(hw_tf->cause < sizeof(trap_handlers)/sizeof(trap_handlers[0]) &&
331 trap_handlers[hw_tf->cause]);
332 if (in_kernel(hw_tf)) {
333 inc_ktrap_depth(pcpui);
334 trap_handlers[hw_tf->cause](hw_tf);
335 dec_ktrap_depth(pcpui);
337 trap_handlers[hw_tf->cause](hw_tf);
339 #warning "if a trap wasn't handled fully, like an MCP pf, reflect it
340 reflect_unhandled_trap(hw_tf->tf_trapno, hw_tf->tf_err, aux);
343 extern void pop_hw_tf(struct hw_trapframe *tf); /* in asm */
344 /* Return to the current process, which should be runnable. If we're the
345 * kernel, we should just return naturally. Note that current and tf need
346 * to still be okay (might not be after blocking) */
347 if (in_kernel(hw_tf))
353 /* We don't have NMIs now. */
354 void send_nmi(uint32_t os_coreid)
356 printk("%s not implemented\n", __FUNCTION);
359 int register_irq(int irq, isr_t handler, void *irq_arg, uint32_t tbdf)
361 printk("%s not implemented\n", __FUNCTION);
365 int route_irqs(int cpu_vec, int coreid)
367 printk("%s not implemented\n", __FUNCTION);
371 void __arch_reflect_trap_hwtf(struct hw_trapframe *hw_tf, unsigned int trap_nr,
372 unsigned int err, unsigned long aux)
374 printk("%s not implemented\n", __FUNCTION);