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_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;
|
||||||
|
@ -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
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -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.
|
||||||
|
@ -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];
|
||||||
|
@ -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.
|
||||||
*/
|
*/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user