Low-level stack frame changes.

This commit is contained in:
Geoffrey Challen 2017-02-09 09:47:06 -05:00
parent 5f172878dd
commit 5f8b9f7ff4
5 changed files with 81 additions and 54 deletions

View File

@ -69,8 +69,6 @@ struct trapframe {
uint32_t tf_s7; uint32_t tf_s7;
uint32_t tf_t8; uint32_t tf_t8;
uint32_t tf_t9; uint32_t tf_t9;
uint32_t tf_k0; /* dummy (see exception-mips1.S comments) */
uint32_t tf_k1; /* dummy */
uint32_t tf_gp; uint32_t tf_gp;
uint32_t tf_sp; uint32_t tf_sp;
uint32_t tf_s8; uint32_t tf_s8;

View File

@ -101,6 +101,8 @@ mips_general_end:
.text .text
.type common_exception,@function .type common_exception,@function
.ent common_exception .ent common_exception
.cfi_startproc
.cfi_signal_frame
common_exception: common_exception:
mfc0 k0, c0_status /* Get status register */ mfc0 k0, c0_status /* Get status register */
andi k0, k0, CST_KUp /* Check the we-were-in-user-mode bit */ andi k0, k0, CST_KUp /* Check the we-were-in-user-mode bit */
@ -130,11 +132,12 @@ common_exception:
*/ */
/* /*
* Allocate stack space for 37 words to hold the trap frame, * Allocate stack space for 35 words to hold the trap frame,
* plus four more words for a minimal argument block, plus * plus four more words for a minimal argument block, plus
* one more for proper (64-bit) stack alignment. * one more for proper (64-bit) stack alignment.
*/ */
addi sp, sp, -168 addi sp, sp, -160
.cfi_def_cfa sp, 0
/* /*
* Save general registers. * Save general registers.
@ -143,70 +146,89 @@ common_exception:
* *
* The order here must match mips/include/trapframe.h. * The order here must match mips/include/trapframe.h.
* *
* gdb disassembles this code to try to figure out what registers * gdb uses the .cfi_offset assembler directives inserted below to
* are where, and it isn't very bright. So in order to make gdb be * to figure out where each register is stored. Since we've marked
* able to trace the stack back through here, we play some silly * this function as a "signal handler" with the .cfi_signal_frame
* games. * directive, gdb won't complain about the fact that the stack
* is noncontiguous (if we're coming from userland).
* *
* In particular: * We also play a trick with the return address: we mark the ra
* (1) We store the return address register into the epc slot, * register as stored to the stack normally and then mark the
* which makes gdb think it's the return address slot. Then * return address for *this* function as being in the k1 register
* we store the real epc value over that. * using the .cfi_return_column directive. gdb is then able to
* (2) We store the current sp into the sp slot, which makes gdb * recognize that the ra we've stored here is the return address
* think it's the stack pointer slot. Then we store the real * for the function that was executing when this exception was
* value. * taken.
* (3) gdb also assumes that saved registers in a function are
* saved in order. This is why we put epc where it is, and
* handle the real value of ra afterwards.
* (4) Because gdb will think we're saving k0 and k1, we need to
* leave slots for them in the trap frame, even though the
* stuff we save there is useless.
* *
* This logic has not been tested against a recent gdb and has * All of the cfi (call frame information) material is compiled
* probably bitrotted. Someone(TM) should figure out what gdb * into the .eh_frame section of the compiled kernel.
* currently expects -- or maybe even patch gdb to understand a
* better form of this that doesn't waste so many cycles.
*/ */
sw ra, 160(sp) /* dummy for gdb */ sw s8, 148(sp) /* save s8 */
sw s8, 156(sp) /* save s8 */ .cfi_offset s8, 148
sw sp, 152(sp) /* dummy for gdb */ sw k1, 144(sp) /* real saved sp */
sw gp, 148(sp) /* save gp */ .cfi_offset sp, 144
sw k1, 144(sp) /* dummy for gdb */ sw gp, 140(sp) /* save gp */
sw k0, 140(sp) /* dummy for gdb */
sw k1, 152(sp) /* real saved sp */
nop /* delay slot for store */ nop /* delay slot for store */
.cfi_offset gp, 140
.cfi_return_column k1
mfc0 k1, c0_epc /* Copr.0 reg 13 == PC for exception */ mfc0 k1, c0_epc /* Copr.0 reg 13 == PC for exception */
sw k1, 160(sp) /* real saved PC */ sw k1, 152(sp) /* real saved PC */
.cfi_offset k1, 152
sw t9, 136(sp) sw t9, 136(sp)
.cfi_offset t9, 136
sw t8, 132(sp) sw t8, 132(sp)
.cfi_offset t8, 132
sw s7, 128(sp) sw s7, 128(sp)
.cfi_offset s7, 128
sw s6, 124(sp) sw s6, 124(sp)
.cfi_offset s6, 124
sw s5, 120(sp) sw s5, 120(sp)
.cfi_offset s5, 120
sw s4, 116(sp) sw s4, 116(sp)
.cfi_offset s4, 116
sw s3, 112(sp) sw s3, 112(sp)
.cfi_offset s3, 112
sw s2, 108(sp) sw s2, 108(sp)
.cfi_offset s2, 108
sw s1, 104(sp) sw s1, 104(sp)
.cfi_offset s1, 104
sw s0, 100(sp) sw s0, 100(sp)
.cfi_offset s0, 100
sw t7, 96(sp) sw t7, 96(sp)
.cfi_offset t7, 96
sw t6, 92(sp) sw t6, 92(sp)
.cfi_offset t6, 92
sw t5, 88(sp) sw t5, 88(sp)
.cfi_offset t5, 88
sw t4, 84(sp) sw t4, 84(sp)
.cfi_offset t4, 84
sw t3, 80(sp) sw t3, 80(sp)
.cfi_offset t3, 80
sw t2, 76(sp) sw t2, 76(sp)
.cfi_offset t2, 76
sw t1, 72(sp) sw t1, 72(sp)
.cfi_offset t1, 72
sw t0, 68(sp) sw t0, 68(sp)
.cfi_offset t0, 68
sw a3, 64(sp) sw a3, 64(sp)
.cfi_offset a3, 64
sw a2, 60(sp) sw a2, 60(sp)
.cfi_offset a2, 60
sw a1, 56(sp) sw a1, 56(sp)
.cfi_offset a1, 56
sw a0, 52(sp) sw a0, 52(sp)
.cfi_offset a0, 52
sw v1, 48(sp) sw v1, 48(sp)
.cfi_offset v1, 48
sw v0, 44(sp) sw v0, 44(sp)
.cfi_offset v0, 44
sw AT, 40(sp) sw AT, 40(sp)
.cfi_offset AT, 40
sw ra, 36(sp) sw ra, 36(sp)
.cfi_offset ra, 36
/* /*
* Save special registers. * Save special registers.
@ -227,11 +249,6 @@ common_exception:
mfc0 t4, c0_cause mfc0 t4, c0_cause
sw t4, 24(sp) /* Copr.0 reg 13 == exception cause */ sw t4, 24(sp) /* Copr.0 reg 13 == exception cause */
/*
* Pretend to save $0 for gdb's benefit.
*/
sw $0, 12(sp)
/* /*
* Load the curthread register if coming from user mode. * Load the curthread register if coming from user mode.
*/ */
@ -260,9 +277,6 @@ common_exception:
jal mips_trap /* call it */ jal mips_trap /* call it */
nop /* delay slot */ nop /* delay slot */
/* Something must be here or gdb doesn't find the stack frame. */
nop
/* /*
* Now restore stuff and return from the exception. * Now restore stuff and return from the exception.
* Interrupts should be off. * Interrupts should be off.
@ -309,20 +323,17 @@ exception_return:
lw s7, 128(sp) lw s7, 128(sp)
lw t8, 132(sp) lw t8, 132(sp)
lw t9, 136(sp) lw t9, 136(sp)
lw gp, 140(sp) /* restore gp */
/* 144(sp) stack pointer - below */
lw s8, 148(sp) /* restore s8 */
lw k1, 152(sp) /* fetch exception return PC into k1 */
/* 140(sp) "saved" k0 was dummy garbage anyway */ lw sp, 144(sp) /* fetch saved sp (must be last) */
/* 144(sp) "saved" k1 was dummy garbage anyway */
lw gp, 148(sp) /* restore gp */
/* 152(sp) stack pointer - below */
lw s8, 156(sp) /* restore s8 */
lw k0, 160(sp) /* fetch exception return PC into k0 */
lw sp, 152(sp) /* fetch saved sp (must be last) */
/* done */ /* done */
jr k0 /* jump back */ jr k1 /* jump back */
rfe /* in delay slot */ rfe /* in delay slot */
.cfi_endproc
.end common_exception .end common_exception
/* /*

View File

@ -130,8 +130,8 @@ mips_trap(struct trapframe *tf)
bool iskern; bool iskern;
int spl; int spl;
/* The trap frame is supposed to be 37 registers long. */ /* The trap frame is supposed to be 35 registers long. */
KASSERT(sizeof(struct trapframe)==(37*4)); KASSERT(sizeof(struct trapframe)==(35*4));
/* /*
* Extract the exception code info from the register fields. * Extract the exception code info from the register fields.

View File

@ -54,6 +54,14 @@
* *
* These arrays are also used to start up new CPUs, for roughly the * These arrays are also used to start up new CPUs, for roughly the
* same reasons. * same reasons.
*
* The values in the current cpu's slots in these arrays are updated
* with the current thread's information in trap.c before heading to
* userlevel, as well as being initialized in cpu_machdep_init below.
* This means that (unless something really horrible happens) on entry
* to the kernel, and when a new CPU starts up in cpu_start_secondary,
* they will have the information needed to figure out who we are and
* proceed.
*/ */
vaddr_t cpustacks[MAXCPUS]; vaddr_t cpustacks[MAXCPUS];

View File

@ -42,6 +42,7 @@
#include <mainbus.h> #include <mainbus.h>
#include <sys161/bus.h> #include <sys161/bus.h>
#include <lamebus/lamebus.h> #include <lamebus/lamebus.h>
#include <lamebus/ltrace.h>
#include "autoconf.h" #include "autoconf.h"
/* /*
@ -275,6 +276,15 @@ mainbus_send_ipi(struct cpu *target)
lamebus_assert_ipi(lamebus, target); lamebus_assert_ipi(lamebus, target);
} }
/*
* Trigger the debugger.
*/
void
mainbus_debugger(void)
{
ltrace_stop(0);
}
/* /*
* Interrupt dispatcher. * Interrupt dispatcher.
*/ */