Low-level stack frame changes.
This commit is contained in:
parent
5f172878dd
commit
5f8b9f7ff4
@ -69,8 +69,6 @@ struct trapframe {
|
||||
uint32_t tf_s7;
|
||||
uint32_t tf_t8;
|
||||
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_sp;
|
||||
uint32_t tf_s8;
|
||||
|
@ -101,6 +101,8 @@ mips_general_end:
|
||||
.text
|
||||
.type common_exception,@function
|
||||
.ent common_exception
|
||||
.cfi_startproc
|
||||
.cfi_signal_frame
|
||||
common_exception:
|
||||
mfc0 k0, c0_status /* Get status register */
|
||||
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
|
||||
* one more for proper (64-bit) stack alignment.
|
||||
*/
|
||||
addi sp, sp, -168
|
||||
addi sp, sp, -160
|
||||
.cfi_def_cfa sp, 0
|
||||
|
||||
/*
|
||||
* Save general registers.
|
||||
@ -143,70 +146,89 @@ common_exception:
|
||||
*
|
||||
* The order here must match mips/include/trapframe.h.
|
||||
*
|
||||
* gdb disassembles this code to try to figure out what registers
|
||||
* are where, and it isn't very bright. So in order to make gdb be
|
||||
* able to trace the stack back through here, we play some silly
|
||||
* games.
|
||||
* gdb uses the .cfi_offset assembler directives inserted below to
|
||||
* to figure out where each register is stored. Since we've marked
|
||||
* this function as a "signal handler" with the .cfi_signal_frame
|
||||
* directive, gdb won't complain about the fact that the stack
|
||||
* is noncontiguous (if we're coming from userland).
|
||||
*
|
||||
* In particular:
|
||||
* (1) We store the return address register into the epc slot,
|
||||
* which makes gdb think it's the return address slot. Then
|
||||
* we store the real epc value over that.
|
||||
* (2) We store the current sp into the sp slot, which makes gdb
|
||||
* think it's the stack pointer slot. Then we store the real
|
||||
* value.
|
||||
* (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.
|
||||
* We also play a trick with the return address: we mark the ra
|
||||
* register as stored to the stack normally and then mark the
|
||||
* return address for *this* function as being in the k1 register
|
||||
* using the .cfi_return_column directive. gdb is then able to
|
||||
* recognize that the ra we've stored here is the return address
|
||||
* for the function that was executing when this exception was
|
||||
* taken.
|
||||
*
|
||||
* This logic has not been tested against a recent gdb and has
|
||||
* probably bitrotted. Someone(TM) should figure out what gdb
|
||||
* currently expects -- or maybe even patch gdb to understand a
|
||||
* better form of this that doesn't waste so many cycles.
|
||||
* All of the cfi (call frame information) material is compiled
|
||||
* into the .eh_frame section of the compiled kernel.
|
||||
*/
|
||||
sw ra, 160(sp) /* dummy for gdb */
|
||||
sw s8, 156(sp) /* save s8 */
|
||||
sw sp, 152(sp) /* dummy for gdb */
|
||||
sw gp, 148(sp) /* save gp */
|
||||
sw k1, 144(sp) /* dummy for gdb */
|
||||
sw k0, 140(sp) /* dummy for gdb */
|
||||
|
||||
sw k1, 152(sp) /* real saved sp */
|
||||
sw s8, 148(sp) /* save s8 */
|
||||
.cfi_offset s8, 148
|
||||
sw k1, 144(sp) /* real saved sp */
|
||||
.cfi_offset sp, 144
|
||||
sw gp, 140(sp) /* save gp */
|
||||
nop /* delay slot for store */
|
||||
.cfi_offset gp, 140
|
||||
|
||||
.cfi_return_column k1
|
||||
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)
|
||||
.cfi_offset t9, 136
|
||||
sw t8, 132(sp)
|
||||
.cfi_offset t8, 132
|
||||
sw s7, 128(sp)
|
||||
.cfi_offset s7, 128
|
||||
sw s6, 124(sp)
|
||||
.cfi_offset s6, 124
|
||||
sw s5, 120(sp)
|
||||
.cfi_offset s5, 120
|
||||
sw s4, 116(sp)
|
||||
.cfi_offset s4, 116
|
||||
sw s3, 112(sp)
|
||||
.cfi_offset s3, 112
|
||||
sw s2, 108(sp)
|
||||
.cfi_offset s2, 108
|
||||
sw s1, 104(sp)
|
||||
.cfi_offset s1, 104
|
||||
sw s0, 100(sp)
|
||||
.cfi_offset s0, 100
|
||||
sw t7, 96(sp)
|
||||
.cfi_offset t7, 96
|
||||
sw t6, 92(sp)
|
||||
.cfi_offset t6, 92
|
||||
sw t5, 88(sp)
|
||||
.cfi_offset t5, 88
|
||||
sw t4, 84(sp)
|
||||
.cfi_offset t4, 84
|
||||
sw t3, 80(sp)
|
||||
.cfi_offset t3, 80
|
||||
sw t2, 76(sp)
|
||||
.cfi_offset t2, 76
|
||||
sw t1, 72(sp)
|
||||
.cfi_offset t1, 72
|
||||
sw t0, 68(sp)
|
||||
.cfi_offset t0, 68
|
||||
sw a3, 64(sp)
|
||||
.cfi_offset a3, 64
|
||||
sw a2, 60(sp)
|
||||
.cfi_offset a2, 60
|
||||
sw a1, 56(sp)
|
||||
.cfi_offset a1, 56
|
||||
sw a0, 52(sp)
|
||||
.cfi_offset a0, 52
|
||||
sw v1, 48(sp)
|
||||
.cfi_offset v1, 48
|
||||
sw v0, 44(sp)
|
||||
.cfi_offset v0, 44
|
||||
sw AT, 40(sp)
|
||||
.cfi_offset AT, 40
|
||||
|
||||
sw ra, 36(sp)
|
||||
.cfi_offset ra, 36
|
||||
|
||||
/*
|
||||
* Save special registers.
|
||||
@ -227,11 +249,6 @@ common_exception:
|
||||
mfc0 t4, c0_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.
|
||||
*/
|
||||
@ -260,9 +277,6 @@ common_exception:
|
||||
jal mips_trap /* call it */
|
||||
nop /* delay slot */
|
||||
|
||||
/* Something must be here or gdb doesn't find the stack frame. */
|
||||
nop
|
||||
|
||||
/*
|
||||
* Now restore stuff and return from the exception.
|
||||
* Interrupts should be off.
|
||||
@ -309,20 +323,17 @@ exception_return:
|
||||
lw s7, 128(sp)
|
||||
lw t8, 132(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 */
|
||||
/* 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) */
|
||||
lw sp, 144(sp) /* fetch saved sp (must be last) */
|
||||
|
||||
/* done */
|
||||
jr k0 /* jump back */
|
||||
jr k1 /* jump back */
|
||||
rfe /* in delay slot */
|
||||
.cfi_endproc
|
||||
.end common_exception
|
||||
|
||||
/*
|
||||
|
@ -130,8 +130,8 @@ mips_trap(struct trapframe *tf)
|
||||
bool iskern;
|
||||
int spl;
|
||||
|
||||
/* The trap frame is supposed to be 37 registers long. */
|
||||
KASSERT(sizeof(struct trapframe)==(37*4));
|
||||
/* The trap frame is supposed to be 35 registers long. */
|
||||
KASSERT(sizeof(struct trapframe)==(35*4));
|
||||
|
||||
/*
|
||||
* Extract the exception code info from the register fields.
|
||||
|
@ -54,6 +54,14 @@
|
||||
*
|
||||
* These arrays are also used to start up new CPUs, for roughly the
|
||||
* 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];
|
||||
|
@ -42,6 +42,7 @@
|
||||
#include <mainbus.h>
|
||||
#include <sys161/bus.h>
|
||||
#include <lamebus/lamebus.h>
|
||||
#include <lamebus/ltrace.h>
|
||||
#include "autoconf.h"
|
||||
|
||||
/*
|
||||
@ -275,6 +276,15 @@ mainbus_send_ipi(struct cpu *target)
|
||||
lamebus_assert_ipi(lamebus, target);
|
||||
}
|
||||
|
||||
/*
|
||||
* Trigger the debugger.
|
||||
*/
|
||||
void
|
||||
mainbus_debugger(void)
|
||||
{
|
||||
ltrace_stop(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Interrupt dispatcher.
|
||||
*/
|
||||
|
Loading…
x
Reference in New Issue
Block a user