- Expand struct trapframe to 256 bytes, make all fields fixed width and the
same size. Add some fields that previously overlapped with something else or were missing. - Make struct regs and struct mcontext (minus floating point) the same as struct trapframe so converting between them is easy (null). - Add space for saving floating point state to struct mcontext. This requires that it be 64 byte aligned. - Add assertions that none of these structures change size, as they are part of the ABI. - Remove some dead code in sendsig(). - Save and restore %gsr in struct trapframe. Remember to restore %fsr. - Add some comments to exception.S.
This commit is contained in:
parent
6856844ba3
commit
9130753f7b
@ -33,25 +33,29 @@
|
||||
#define SPOFF 2047
|
||||
#define BIAS SPOFF /* XXX - open/netbsd compat */
|
||||
|
||||
/*
|
||||
* NOTE: keep this structure in sync with struct reg and struct mcontext.
|
||||
*/
|
||||
struct trapframe {
|
||||
u_long tf_global[8];
|
||||
u_long tf_out[8];
|
||||
u_long tf_fsr;
|
||||
u_long tf_sfar;
|
||||
u_long tf_tar;
|
||||
u_long tf_tnpc;
|
||||
u_long tf_tpc;
|
||||
u_long tf_tstate;
|
||||
u_int tf_sfsr;
|
||||
u_int tf_type;
|
||||
u_int tf_y;
|
||||
u_char tf_fprs;
|
||||
u_char tf_pil;
|
||||
u_char tf_wstate;
|
||||
u_char tf_pad[1];
|
||||
uint64_t tf_global[8];
|
||||
uint64_t tf_out[8];
|
||||
uint64_t tf_fprs;
|
||||
uint64_t tf_fsr;
|
||||
uint64_t tf_gsr;
|
||||
uint64_t tf_level;
|
||||
uint64_t tf_pil;
|
||||
uint64_t tf_sfar;
|
||||
uint64_t tf_sfsr;
|
||||
uint64_t tf_tar;
|
||||
uint64_t tf_tnpc;
|
||||
uint64_t tf_tpc;
|
||||
uint64_t tf_tstate;
|
||||
uint64_t tf_type;
|
||||
uint64_t tf_y;
|
||||
uint64_t tf_wstate;
|
||||
uint64_t tf_pad[2];
|
||||
};
|
||||
#define tf_level tf_sfsr
|
||||
#define tf_sp tf_out[6]
|
||||
#define tf_sp tf_out[6]
|
||||
|
||||
#define TF_DONE(tf) do { \
|
||||
tf->tf_tpc = tf->tf_tnpc; \
|
||||
@ -74,7 +78,7 @@ struct frame {
|
||||
#define v9next_frame(fp) ((struct frame *)(fp->fr_fp + BIAS))
|
||||
|
||||
/*
|
||||
* Frame used for pcb_wscratch.
|
||||
* Frame used for pcb_rw.
|
||||
*/
|
||||
struct rwindow {
|
||||
u_long rw_local[8];
|
||||
|
@ -43,31 +43,63 @@
|
||||
|
||||
/*
|
||||
* Register set accessible via /proc/$pid/regs and PT_{SET,GET}REGS.
|
||||
*
|
||||
* NOTE: DO NOT CHANGE THESE STRUCTURES. The offsets of the fields are
|
||||
* hardcoded in gdb. Changing them and recompiling doesn't help, the
|
||||
* constants in nm-fbsd.h must also be updated.
|
||||
*/
|
||||
|
||||
struct reg32 {
|
||||
uint32_t r_global[8];
|
||||
uint32_t r_out[8];
|
||||
uint32_t r_npc;
|
||||
uint32_t r_pc;
|
||||
uint32_t r_psr;
|
||||
uint32_t r_wim;
|
||||
uint32_t r_pad[4];
|
||||
};
|
||||
|
||||
struct reg {
|
||||
u_long r_tstate;
|
||||
u_long r_pc;
|
||||
u_long r_npc;
|
||||
u_int r_y;
|
||||
u_long r_global[8];
|
||||
u_long r_out[8];
|
||||
u_long r_local[8];
|
||||
u_long r_in[8];
|
||||
uint64_t r_global[8];
|
||||
uint64_t r_out[8];
|
||||
uint64_t r_fprs;
|
||||
uint64_t r_fsr;
|
||||
uint64_t r_gsr;
|
||||
uint64_t r_level;
|
||||
uint64_t r_pil;
|
||||
uint64_t r_sfar;
|
||||
uint64_t r_sfsr;
|
||||
uint64_t r_tar;
|
||||
uint64_t r_tnpc;
|
||||
uint64_t r_tpc;
|
||||
uint64_t r_tstate;
|
||||
uint64_t r_type;
|
||||
uint64_t r_y;
|
||||
uint64_t r_wstate;
|
||||
uint64_t r_pad[2];
|
||||
};
|
||||
|
||||
/*
|
||||
* Register set accessible via /proc/$pid/fpregs.
|
||||
*/
|
||||
|
||||
struct fpreg32 {
|
||||
uint32_t fr_regs[32];
|
||||
uint32_t fr_fsr;
|
||||
};
|
||||
|
||||
struct fpreg {
|
||||
u_int fr_regs[64]; /* our view is 64 32-bit registers */
|
||||
u_long fr_fsr; /* %fsr */
|
||||
u_long fr_fprs;
|
||||
uint32_t fr_regs[64]; /* our view is 64 32-bit registers */
|
||||
int64_t fr_fsr; /* %fsr */
|
||||
int32_t fr_gsr; /* %gsr */
|
||||
int32_t fr_pad[1];
|
||||
};
|
||||
|
||||
/*
|
||||
* Register set accessible via /proc/$pid/dbregs.
|
||||
*/
|
||||
struct dbreg {
|
||||
int dummy;
|
||||
};
|
||||
|
||||
#ifdef _KERNEL
|
||||
|
@ -32,14 +32,32 @@
|
||||
#ifndef _MACHINE_UCONTEXT_H_
|
||||
#define _MACHINE_UCONTEXT_H_
|
||||
|
||||
typedef struct __mcontext {
|
||||
long mc_global[8];
|
||||
long mc_out[8];
|
||||
long mc_onstack;
|
||||
long mc_tpc;
|
||||
long mc_tnpc;
|
||||
long mc_tstate;
|
||||
long mc_spare[2];
|
||||
} mcontext_t;
|
||||
struct __mcontext {
|
||||
uint64_t mc_global[8];
|
||||
uint64_t mc_out[8];
|
||||
uint64_t mc_local[8];
|
||||
uint64_t mc_in[8];
|
||||
uint32_t mc_fp[64];
|
||||
} __aligned(64);
|
||||
|
||||
typedef struct __mcontext mcontext_t;
|
||||
|
||||
#define mc_flags mc_global[0]
|
||||
#define mc_sp mc_out[6]
|
||||
#define mc_fprs mc_local[0]
|
||||
#define mc_fsr mc_local[1]
|
||||
#define mc_gsr mc_local[2]
|
||||
#define mc_tnpc mc_in[0]
|
||||
#define mc_tpc mc_in[1]
|
||||
#define mc_tstate mc_in[2]
|
||||
#define mc_y mc_in[4]
|
||||
|
||||
#define _MC_VERSION_SHIFT 0
|
||||
#define _MC_VERSION_BITS 32
|
||||
#define _MC_VERSION 1L
|
||||
|
||||
#define _MC_FLAGS_SHIFT 32
|
||||
#define _MC_FLAGS_BITS 32
|
||||
#define _MC_VOLUNTARY ((1L << 0) << _MC_FLAGS_SHIFT)
|
||||
|
||||
#endif /* !_MACHINE_UCONTEXT_H_ */
|
||||
|
@ -2163,20 +2163,23 @@ ENTRY(tl0_trap)
|
||||
|
||||
sub PCB_REG, SPOFF + CCFSZ + TF_SIZEOF, %sp
|
||||
|
||||
stw %o0, [%sp + SPOFF + CCFSZ + TF_TYPE]
|
||||
stx %o0, [%sp + SPOFF + CCFSZ + TF_TYPE]
|
||||
stx %o1, [%sp + SPOFF + CCFSZ + TF_LEVEL]
|
||||
stx %o3, [%sp + SPOFF + CCFSZ + TF_TAR]
|
||||
stx %o4, [%sp + SPOFF + CCFSZ + TF_SFAR]
|
||||
stw %o5, [%sp + SPOFF + CCFSZ + TF_SFSR]
|
||||
stx %o5, [%sp + SPOFF + CCFSZ + TF_SFSR]
|
||||
|
||||
stx %l0, [%sp + SPOFF + CCFSZ + TF_TSTATE]
|
||||
stx %l1, [%sp + SPOFF + CCFSZ + TF_TPC]
|
||||
stx %l2, [%sp + SPOFF + CCFSZ + TF_TNPC]
|
||||
stw %l3, [%sp + SPOFF + CCFSZ + TF_Y]
|
||||
stb %l4, [%sp + SPOFF + CCFSZ + TF_FPRS]
|
||||
stb %l5, [%sp + SPOFF + CCFSZ + TF_WSTATE]
|
||||
stx %l3, [%sp + SPOFF + CCFSZ + TF_Y]
|
||||
stx %l4, [%sp + SPOFF + CCFSZ + TF_FPRS]
|
||||
stx %l5, [%sp + SPOFF + CCFSZ + TF_WSTATE]
|
||||
|
||||
wr %g0, FPRS_FEF, %fprs
|
||||
stx %fsr, [%sp + SPOFF + CCFSZ + TF_FSR]
|
||||
rd %asr19, %l6
|
||||
stx %l6, [%sp + SPOFF + CCFSZ + TF_GSR]
|
||||
wr %g0, 0, %fprs
|
||||
|
||||
mov PCB_REG, %l0
|
||||
@ -2255,19 +2258,21 @@ ENTRY(tl0_intr)
|
||||
stx %l0, [%sp + SPOFF + CCFSZ + TF_TSTATE]
|
||||
stx %l1, [%sp + SPOFF + CCFSZ + TF_TPC]
|
||||
stx %l2, [%sp + SPOFF + CCFSZ + TF_TNPC]
|
||||
stw %l3, [%sp + SPOFF + CCFSZ + TF_Y]
|
||||
stb %l4, [%sp + SPOFF + CCFSZ + TF_FPRS]
|
||||
stb %l5, [%sp + SPOFF + CCFSZ + TF_WSTATE]
|
||||
stx %l3, [%sp + SPOFF + CCFSZ + TF_Y]
|
||||
stx %l4, [%sp + SPOFF + CCFSZ + TF_FPRS]
|
||||
stx %l5, [%sp + SPOFF + CCFSZ + TF_WSTATE]
|
||||
|
||||
wr %g0, FPRS_FEF, %fprs
|
||||
stx %fsr, [%sp + SPOFF + CCFSZ + TF_FSR]
|
||||
rd %asr19, %l6
|
||||
stx %l6, [%sp + SPOFF + CCFSZ + TF_GSR]
|
||||
wr %g0, 0, %fprs
|
||||
|
||||
mov %o0, %l3
|
||||
mov T_INTERRUPT, %o1
|
||||
|
||||
stw %o0, [%sp + SPOFF + CCFSZ + TF_LEVEL]
|
||||
stw %o1, [%sp + SPOFF + CCFSZ + TF_TYPE]
|
||||
stx %o0, [%sp + SPOFF + CCFSZ + TF_LEVEL]
|
||||
stx %o1, [%sp + SPOFF + CCFSZ + TF_TYPE]
|
||||
|
||||
mov PCB_REG, %l0
|
||||
mov PCPU_REG, %l1
|
||||
@ -2314,6 +2319,16 @@ ENTRY(tl0_intr)
|
||||
nop
|
||||
END(tl0_intr)
|
||||
|
||||
/*
|
||||
* Initiate return to usermode.
|
||||
*
|
||||
* Called with a trapframe on the stack. The window that was setup in
|
||||
* tl0_trap may have been used by "fast" trap handlers that pretend to be
|
||||
* leaf functions, so all ins and locals may have been clobbered since
|
||||
* then.
|
||||
*
|
||||
* This code is rather long and complicated.
|
||||
*/
|
||||
ENTRY(tl0_ret)
|
||||
/*
|
||||
* Check for pending asts atomically with returning. We must raise
|
||||
@ -2329,6 +2344,11 @@ ENTRY(tl0_ret)
|
||||
and %l2, KEF_ASTPENDING | KEF_NEEDRESCHED, %l2
|
||||
brz,a,pt %l2, 1f
|
||||
nop
|
||||
|
||||
/*
|
||||
* We have an ast. Re-enable interrupts and handle it, then restart
|
||||
* the return sequence.
|
||||
*/
|
||||
wrpr %g0, 0, %pil
|
||||
call ast
|
||||
add %sp, CCFSZ + SPOFF, %o0
|
||||
@ -2348,12 +2368,16 @@ ENTRY(tl0_ret)
|
||||
nop
|
||||
wrpr %g0, 0, %pil
|
||||
mov T_SPILL, %o0
|
||||
stw %o0, [%sp + SPOFF + CCFSZ + TF_TYPE]
|
||||
stx %o0, [%sp + SPOFF + CCFSZ + TF_TYPE]
|
||||
call trap
|
||||
add %sp, SPOFF + CCFSZ, %o0
|
||||
ba,a %xcc, tl0_ret
|
||||
nop
|
||||
|
||||
/*
|
||||
* Restore the out registers from the trapframe. These are ins
|
||||
* now, they will become the outs when we restore below.
|
||||
*/
|
||||
2: ldx [%sp + SPOFF + CCFSZ + TF_O0], %i0
|
||||
ldx [%sp + SPOFF + CCFSZ + TF_O1], %i1
|
||||
ldx [%sp + SPOFF + CCFSZ + TF_O2], %i2
|
||||
@ -2363,13 +2387,24 @@ ENTRY(tl0_ret)
|
||||
ldx [%sp + SPOFF + CCFSZ + TF_O6], %i6
|
||||
ldx [%sp + SPOFF + CCFSZ + TF_O7], %i7
|
||||
|
||||
ldx [%sp + SPOFF + CCFSZ + TF_TSTATE], %l0
|
||||
ldx [%sp + SPOFF + CCFSZ + TF_TPC], %l1
|
||||
/*
|
||||
* Load everything we need to restore below before disabling
|
||||
* interrupts.
|
||||
*/
|
||||
ldx [%sp + SPOFF + CCFSZ + TF_FPRS], %l0
|
||||
ldx [%sp + SPOFF + CCFSZ + TF_GSR], %l1
|
||||
ldx [%sp + SPOFF + CCFSZ + TF_TNPC], %l2
|
||||
lduw [%sp + SPOFF + CCFSZ + TF_Y], %l3
|
||||
ldub [%sp + SPOFF + CCFSZ + TF_FPRS], %l4
|
||||
ldub [%sp + SPOFF + CCFSZ + TF_WSTATE], %l5
|
||||
ldx [%sp + SPOFF + CCFSZ + TF_TPC], %l3
|
||||
ldx [%sp + SPOFF + CCFSZ + TF_TSTATE], %l4
|
||||
ldx [%sp + SPOFF + CCFSZ + TF_Y], %l5
|
||||
ldx [%sp + SPOFF + CCFSZ + TF_WSTATE], %l6
|
||||
|
||||
/*
|
||||
* Disable interrupts to restore the globals. We need to restore
|
||||
* %g6 and %g7 which are used as global variables in the kernel.
|
||||
* They are not saved and restored for kernel traps, so an interrupt
|
||||
* at the wrong time would clobber them.
|
||||
*/
|
||||
wrpr %g0, PSTATE_NORMAL, %pstate
|
||||
|
||||
ldx [%sp + SPOFF + CCFSZ + TF_G1], %g1
|
||||
@ -2380,34 +2415,109 @@ ENTRY(tl0_ret)
|
||||
ldx [%sp + SPOFF + CCFSZ + TF_G6], %g6
|
||||
ldx [%sp + SPOFF + CCFSZ + TF_G7], %g7
|
||||
|
||||
/*
|
||||
* Switch to alternate globals. This frees up some registers we
|
||||
* can use after the restore changes our window.
|
||||
*/
|
||||
wrpr %g0, PSTATE_ALT, %pstate
|
||||
|
||||
/*
|
||||
* Drop %pil to zero. It must have been zero at the time of the
|
||||
* trap, since we were in usermode, but it was raised above in
|
||||
* order to check for asts atomically. We have interrupts disabled
|
||||
* so any interrupts will not be serviced until we complete the
|
||||
* return to usermode.
|
||||
*/
|
||||
wrpr %g0, 0, %pil
|
||||
wrpr %l1, 0, %tpc
|
||||
|
||||
/*
|
||||
* Save %fprs in an alternate global so it can be restored after the
|
||||
* restore instruction below. If we restore it before the restore,
|
||||
* and the restore traps we may run for a while with floating point
|
||||
* enabled in the kernel, which we want to avoid.
|
||||
*/
|
||||
mov %l0, %g1
|
||||
|
||||
/*
|
||||
* Restore %fsr and %gsr. These need floating point enabled in %fprs,
|
||||
* so we set it temporarily and then clear it.
|
||||
* XXX %asr19 should be %gsr but gas is invoked incorrectly.
|
||||
*/
|
||||
wr %g0, FPRS_FEF, %fprs
|
||||
ldx [%sp + SPOFF + CCFSZ + TF_FSR], %fsr
|
||||
wr %l1, 0, %asr19
|
||||
wr %g0, 0, %fprs
|
||||
|
||||
/*
|
||||
* Restore program counters. This could be done after the restore
|
||||
* but we're out of alternate globals to store them in...
|
||||
*/
|
||||
wrpr %l2, 0, %tnpc
|
||||
wr %l3, 0, %y
|
||||
wrpr %l3, 0, %tpc
|
||||
|
||||
andn %l0, TSTATE_CWP_MASK, %g1
|
||||
mov %l4, %g2
|
||||
/*
|
||||
* Save %tstate in an alternate global and clear the %cwp field. %cwp
|
||||
* will be affected by the restore below and we need to make sure it
|
||||
* points to the current window at that time, not the window that was
|
||||
* active at the time of the trap.
|
||||
*/
|
||||
andn %l4, TSTATE_CWP_MASK, %g2
|
||||
|
||||
srlx %l5, WSTATE_OTHER_SHIFT, %g3
|
||||
/*
|
||||
* Restore %y. Could also be below if we had more alternate globals.
|
||||
*/
|
||||
wr %l5, 0, %y
|
||||
|
||||
/*
|
||||
* Setup %wstate for return. We need to restore the user window state
|
||||
* which we saved in wstate.other when we trapped. We also need to
|
||||
* set the transition bit so the restore will be handled specially
|
||||
* if it traps, use the xor feature of wrpr to do that.
|
||||
*/
|
||||
srlx %l6, WSTATE_OTHER_SHIFT, %g3
|
||||
wrpr %g3, WSTATE_TRANSITION, %wstate
|
||||
|
||||
/*
|
||||
* Setup window management registers for return. If not all user
|
||||
* windows were spilled in the kernel %otherwin will be non-zero,
|
||||
* so we need to transfer it to %canrestore to correctly restore
|
||||
* those windows. Otherwise everything gets set to zero and the
|
||||
* restore below will fill a window directly from the user stack.
|
||||
*/
|
||||
rdpr %otherwin, %o0
|
||||
wrpr %o0, 0, %canrestore
|
||||
wrpr %g0, 0, %otherwin
|
||||
wrpr %o0, 0, %cleanwin
|
||||
|
||||
/*
|
||||
* If this instruction causes a fill trap which fails to fill a window
|
||||
* from the user stack, we will resume at tl0_ret_fill_end and call
|
||||
* back into the kernel.
|
||||
* Now do the restore. If this instruction causes a fill trap which
|
||||
* fails to fill a window from the user stack, we will resume at
|
||||
* tl0_ret_fill_end and call back into the kernel.
|
||||
*/
|
||||
restore
|
||||
tl0_ret_fill:
|
||||
|
||||
/*
|
||||
* We made it. We're back in the window that was active at the time
|
||||
* of the trap, and ready to return to usermode.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Restore %frps. This was saved in an alternate global above.
|
||||
*/
|
||||
wr %g1, 0, %fprs
|
||||
|
||||
/*
|
||||
* Fixup %tstate so the saved %cwp points to the current window and
|
||||
* restore it.
|
||||
*/
|
||||
rdpr %cwp, %g4
|
||||
wrpr %g1, %g4, %tstate
|
||||
wr %g2, 0, %fprs
|
||||
wrpr %g2, %g4, %tstate
|
||||
|
||||
/*
|
||||
* Restore the user window state. The transition bit was set above
|
||||
* for special handling of the restore, this clears it.
|
||||
*/
|
||||
wrpr %g3, 0, %wstate
|
||||
|
||||
#if KTR_COMPILE & KTR_TRAP
|
||||
@ -2425,6 +2535,9 @@ tl0_ret_fill:
|
||||
9:
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Return to usermode.
|
||||
*/
|
||||
retry
|
||||
tl0_ret_fill_end:
|
||||
|
||||
@ -2439,10 +2552,28 @@ tl0_ret_fill_end:
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The fill failed and magic has been performed. Call trap again,
|
||||
* which will copyin the window on the user's behalf.
|
||||
* The restore above caused a fill trap and the fill handler was
|
||||
* unable to fill a window from the user stack. The special fill
|
||||
* handler recognized this and punted, sending us here. We need
|
||||
* to carefully undo any state that was restored before the restore
|
||||
* was executed and call trap again. Trap will copyin a window
|
||||
* from the user stack which will fault in the page we need so the
|
||||
* restore above will succeed when we try again. If this fails
|
||||
* the process has trashed its stack, so we kill it.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Restore the kernel window state. This was saved in %l6 above, and
|
||||
* since the restore failed we're back in the same window.
|
||||
*/
|
||||
wrpr %l6, 0, %wstate
|
||||
|
||||
/*
|
||||
* Restore the normal globals which have predefined values in the
|
||||
* kernel. We clobbered them above restoring the user's globals
|
||||
* so this is very important.
|
||||
* XXX PSTATE_ALT must already be set.
|
||||
*/
|
||||
wrpr %l5, 0, %wstate
|
||||
wrpr %g0, PSTATE_ALT, %pstate
|
||||
mov PCB_REG, %o0
|
||||
mov PCPU_REG, %o1
|
||||
@ -2450,8 +2581,16 @@ tl0_ret_fill_end:
|
||||
mov %o0, PCB_REG
|
||||
mov %o1, PCPU_REG
|
||||
wrpr %g0, PSTATE_KERNEL, %pstate
|
||||
|
||||
/*
|
||||
* Simulate a fill trap and then start the whole return sequence over
|
||||
* again. This is special because it only copies in 1 window, not 2
|
||||
* as we would for a normal failed fill. This may be the first time
|
||||
* the process has been run, so there may not be 2 windows worth of
|
||||
* stack to copyin.
|
||||
*/
|
||||
mov T_FILL_RET, %o0
|
||||
stw %o0, [%sp + SPOFF + CCFSZ + TF_TYPE]
|
||||
stx %o0, [%sp + SPOFF + CCFSZ + TF_TYPE]
|
||||
call trap
|
||||
add %sp, SPOFF + CCFSZ, %o0
|
||||
ba,a %xcc, tl0_ret
|
||||
@ -2493,16 +2632,17 @@ ENTRY(tl1_trap)
|
||||
and %l5, WSTATE_OTHER_MASK, %l5
|
||||
wrpr %l5, WSTATE_KERNEL, %wstate
|
||||
|
||||
stw %o0, [%sp + SPOFF + CCFSZ + TF_TYPE]
|
||||
stx %o0, [%sp + SPOFF + CCFSZ + TF_TYPE]
|
||||
stx %o1, [%sp + SPOFF + CCFSZ + TF_LEVEL]
|
||||
stx %o3, [%sp + SPOFF + CCFSZ + TF_TAR]
|
||||
stx %o4, [%sp + SPOFF + CCFSZ + TF_SFAR]
|
||||
stw %o5, [%sp + SPOFF + CCFSZ + TF_SFSR]
|
||||
stx %o5, [%sp + SPOFF + CCFSZ + TF_SFSR]
|
||||
|
||||
stx %l0, [%sp + SPOFF + CCFSZ + TF_TSTATE]
|
||||
stx %l1, [%sp + SPOFF + CCFSZ + TF_TPC]
|
||||
stx %l2, [%sp + SPOFF + CCFSZ + TF_TNPC]
|
||||
stb %l3, [%sp + SPOFF + CCFSZ + TF_PIL]
|
||||
stw %l4, [%sp + SPOFF + CCFSZ + TF_Y]
|
||||
stx %l3, [%sp + SPOFF + CCFSZ + TF_PIL]
|
||||
stx %l4, [%sp + SPOFF + CCFSZ + TF_Y]
|
||||
|
||||
mov PCB_REG, %l0
|
||||
mov PCPU_REG, %l1
|
||||
@ -2545,8 +2685,8 @@ ENTRY(tl1_ret)
|
||||
ldx [%sp + SPOFF + CCFSZ + TF_TSTATE], %l0
|
||||
ldx [%sp + SPOFF + CCFSZ + TF_TPC], %l1
|
||||
ldx [%sp + SPOFF + CCFSZ + TF_TNPC], %l2
|
||||
ldub [%sp + SPOFF + CCFSZ + TF_PIL], %l3
|
||||
lduw [%sp + SPOFF + CCFSZ + TF_Y], %l4
|
||||
ldx [%sp + SPOFF + CCFSZ + TF_PIL], %l3
|
||||
ldx [%sp + SPOFF + CCFSZ + TF_Y], %l4
|
||||
|
||||
ldx [%sp + SPOFF + CCFSZ + TF_G1], %g1
|
||||
ldx [%sp + SPOFF + CCFSZ + TF_G2], %g2
|
||||
@ -2625,14 +2765,14 @@ ENTRY(tl1_intr)
|
||||
stx %l0, [%sp + SPOFF + CCFSZ + TF_TSTATE]
|
||||
stx %l1, [%sp + SPOFF + CCFSZ + TF_TPC]
|
||||
stx %l2, [%sp + SPOFF + CCFSZ + TF_TNPC]
|
||||
stb %l3, [%sp + SPOFF + CCFSZ + TF_PIL]
|
||||
stw %l4, [%sp + SPOFF + CCFSZ + TF_Y]
|
||||
stx %l3, [%sp + SPOFF + CCFSZ + TF_PIL]
|
||||
stx %l4, [%sp + SPOFF + CCFSZ + TF_Y]
|
||||
|
||||
mov %o0, %l7
|
||||
mov T_INTERRUPT | T_KERNEL, %o1
|
||||
|
||||
stw %o0, [%sp + SPOFF + CCFSZ + TF_LEVEL]
|
||||
stw %o1, [%sp + SPOFF + CCFSZ + TF_TYPE]
|
||||
stx %o0, [%sp + SPOFF + CCFSZ + TF_LEVEL]
|
||||
stx %o1, [%sp + SPOFF + CCFSZ + TF_TYPE]
|
||||
|
||||
stx %i6, [%sp + SPOFF + CCFSZ + TF_O6]
|
||||
stx %i7, [%sp + SPOFF + CCFSZ + TF_O7]
|
||||
@ -2667,7 +2807,7 @@ ENTRY(tl1_intr)
|
||||
call critical_exit
|
||||
nop
|
||||
|
||||
lduw [%sp + SPOFF + CCFSZ + TF_Y], %l4
|
||||
ldx [%sp + SPOFF + CCFSZ + TF_Y], %l4
|
||||
|
||||
ldx [%sp + SPOFF + CCFSZ + TF_G1], %g1
|
||||
ldx [%sp + SPOFF + CCFSZ + TF_G2], %g2
|
||||
|
@ -287,18 +287,19 @@ ASSYM(TF_O4, offsetof(struct trapframe, tf_out[4]));
|
||||
ASSYM(TF_O5, offsetof(struct trapframe, tf_out[5]));
|
||||
ASSYM(TF_O6, offsetof(struct trapframe, tf_out[6]));
|
||||
ASSYM(TF_O7, offsetof(struct trapframe, tf_out[7]));
|
||||
ASSYM(TF_FPRS, offsetof(struct trapframe, tf_fprs));
|
||||
ASSYM(TF_FSR, offsetof(struct trapframe, tf_fsr));
|
||||
ASSYM(TF_SFAR, offsetof(struct trapframe, tf_sfar));
|
||||
ASSYM(TF_GSR, offsetof(struct trapframe, tf_gsr));
|
||||
ASSYM(TF_LEVEL, offsetof(struct trapframe, tf_level));
|
||||
ASSYM(TF_PIL, offsetof(struct trapframe, tf_pil));
|
||||
ASSYM(TF_SFAR, offsetof(struct trapframe, tf_sfar));
|
||||
ASSYM(TF_SFSR, offsetof(struct trapframe, tf_sfsr));
|
||||
ASSYM(TF_TAR, offsetof(struct trapframe, tf_tar));
|
||||
ASSYM(TF_TNPC, offsetof(struct trapframe, tf_tnpc));
|
||||
ASSYM(TF_TPC, offsetof(struct trapframe, tf_tpc));
|
||||
ASSYM(TF_TSTATE, offsetof(struct trapframe, tf_tstate));
|
||||
ASSYM(TF_SFSR, offsetof(struct trapframe, tf_sfsr));
|
||||
ASSYM(TF_TYPE, offsetof(struct trapframe, tf_type));
|
||||
ASSYM(TF_Y, offsetof(struct trapframe, tf_y));
|
||||
ASSYM(TF_FPRS, offsetof(struct trapframe, tf_fprs));
|
||||
ASSYM(TF_PIL, offsetof(struct trapframe, tf_pil));
|
||||
ASSYM(TF_WSTATE, offsetof(struct trapframe, tf_wstate));
|
||||
ASSYM(TF_SIZEOF, sizeof(struct trapframe));
|
||||
|
||||
|
@ -111,7 +111,7 @@ intr_setup(int pri, ih_func_t *ihf, int vec, iv_func_t *ivf, void *iva)
|
||||
static void
|
||||
intr_stray_level(struct trapframe *tf)
|
||||
{
|
||||
printf("stray level interrupt %d\n", tf->tf_level);
|
||||
printf("stray level interrupt %ld\n", tf->tf_level);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -140,6 +140,10 @@ SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL);
|
||||
CTASSERT((1 << INT_SHIFT) == sizeof(int));
|
||||
CTASSERT((1 << PTR_SHIFT) == sizeof(char *));
|
||||
|
||||
CTASSERT(sizeof(struct reg) == 256);
|
||||
CTASSERT(sizeof(struct fpreg) == 272);
|
||||
CTASSERT(sizeof(struct __mcontext) == 512);
|
||||
|
||||
CTASSERT(sizeof(struct pcpu) <= ((PCPU_PAGES * PAGE_SIZE) / 2));
|
||||
|
||||
static void
|
||||
@ -163,8 +167,6 @@ cpu_startup(void *arg)
|
||||
bufinit();
|
||||
vm_pager_bufferinit();
|
||||
|
||||
tick_start(clock, tick_hardclock);
|
||||
|
||||
EVENTHANDLER_REGISTER(shutdown_final, sparc64_shutdown_final, NULL,
|
||||
SHUTDOWN_PRI_LAST);
|
||||
}
|
||||
@ -394,22 +396,13 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
|
||||
sf.sf_uc.uc_stack = p->p_sigstk;
|
||||
sf.sf_uc.uc_stack.ss_flags = (p->p_flag & P_ALTSTACK)
|
||||
? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE;
|
||||
sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0;
|
||||
bcopy(tf->tf_global, sf.sf_uc.uc_mcontext.mc_global,
|
||||
sizeof (tf->tf_global));
|
||||
bcopy(tf->tf_out, sf.sf_uc.uc_mcontext.mc_out, sizeof (tf->tf_out));
|
||||
sf.sf_uc.uc_mcontext.mc_tpc = tf->tf_tpc;
|
||||
sf.sf_uc.uc_mcontext.mc_tnpc = tf->tf_tnpc;
|
||||
sf.sf_uc.uc_mcontext.mc_tstate = tf->tf_tstate;
|
||||
bcopy(tf, &sf.sf_uc.uc_mcontext, sizeof(*tf));
|
||||
|
||||
/* Allocate and validate space for the signal handler context. */
|
||||
if ((p->p_flag & P_ALTSTACK) != 0 && !oonstack &&
|
||||
SIGISMEMBER(psp->ps_sigonstack, sig)) {
|
||||
sfp = (struct sigframe *)(p->p_sigstk.ss_sp +
|
||||
p->p_sigstk.ss_size - sizeof(struct sigframe));
|
||||
#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
|
||||
p->p_sigstk.ss_flags |= SS_ONSTACK;
|
||||
#endif
|
||||
} else
|
||||
sfp = (struct sigframe *)sp - 1;
|
||||
PROC_UNLOCK(p);
|
||||
@ -422,25 +415,15 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
|
||||
|
||||
/* Build the argument list for the signal handler. */
|
||||
tf->tf_out[0] = sig;
|
||||
tf->tf_out[1] = (register_t)&sfp->sf_si;
|
||||
tf->tf_out[2] = (register_t)&sfp->sf_uc;
|
||||
tf->tf_out[3] = tf->tf_type;
|
||||
tf->tf_out[4] = (register_t)catcher;
|
||||
PROC_LOCK(p);
|
||||
if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) {
|
||||
/* Signal handler installed with SA_SIGINFO. */
|
||||
tf->tf_out[1] = (register_t)&sfp->sf_si;
|
||||
|
||||
/* Fill siginfo structure. */
|
||||
sf.sf_si.si_signo = sig;
|
||||
sf.sf_si.si_code = code;
|
||||
sf.sf_si.si_addr = (void *)tf->tf_sfar;
|
||||
sf.sf_si.si_pid = p->p_pid;
|
||||
sf.sf_si.si_uid = p->p_ucred->cr_uid;
|
||||
} else {
|
||||
/* Old FreeBSD-style arguments. */
|
||||
tf->tf_out[1] = code;
|
||||
}
|
||||
PROC_UNLOCK(p);
|
||||
/* Fill siginfo structure. */
|
||||
sf.sf_si.si_signo = sig;
|
||||
sf.sf_si.si_code = code;
|
||||
sf.sf_si.si_addr = (void *)tf->tf_sfar;
|
||||
sf.sf_si.si_pid = p->p_pid;
|
||||
sf.sf_si.si_uid = td->td_ucred->cr_uid;
|
||||
|
||||
/* Copy the sigframe out to the user's stack. */
|
||||
if (rwindow_save(td) != 0 || copyout(&sf, sfp, sizeof(*sfp)) != 0 ||
|
||||
@ -491,7 +474,6 @@ struct sigreturn_args {
|
||||
int
|
||||
sigreturn(struct thread *td, struct sigreturn_args *uap)
|
||||
{
|
||||
struct trapframe *tf;
|
||||
struct proc *p;
|
||||
ucontext_t uc;
|
||||
|
||||
@ -507,32 +489,19 @@ sigreturn(struct thread *td, struct sigreturn_args *uap)
|
||||
return (EFAULT);
|
||||
}
|
||||
|
||||
if (((uc.uc_mcontext.mc_tpc | uc.uc_mcontext.mc_tnpc) & 3) != 0)
|
||||
return (EINVAL);
|
||||
if (!TSTATE_SECURE(uc.uc_mcontext.mc_tstate))
|
||||
return (EINVAL);
|
||||
bcopy(&uc.uc_mcontext, td->td_frame, sizeof(*td->td_frame));
|
||||
|
||||
tf = td->td_frame;
|
||||
bcopy(uc.uc_mcontext.mc_global, tf->tf_global,
|
||||
sizeof(tf->tf_global));
|
||||
bcopy(uc.uc_mcontext.mc_out, tf->tf_out, sizeof(tf->tf_out));
|
||||
tf->tf_tpc = uc.uc_mcontext.mc_tpc;
|
||||
tf->tf_tnpc = uc.uc_mcontext.mc_tnpc;
|
||||
tf->tf_tstate = uc.uc_mcontext.mc_tstate;
|
||||
PROC_LOCK(p);
|
||||
#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
|
||||
if (uc.uc_mcontext.mc_onstack & 1)
|
||||
p->p_sigstk.ss_flags |= SS_ONSTACK;
|
||||
else
|
||||
p->p_sigstk.ss_flags &= ~SS_ONSTACK;
|
||||
#endif
|
||||
|
||||
p->p_sigmask = uc.uc_sigmask;
|
||||
SIG_CANTMASK(p->p_sigmask);
|
||||
signotify(p);
|
||||
PROC_UNLOCK(p);
|
||||
|
||||
CTR4(KTR_SIG, "sigreturn: return td=%p pc=%#lx sp=%#lx tstate=%#lx",
|
||||
td, tf->tf_tpc, tf->tf_sp, tf->tf_tstate);
|
||||
td, td->td_frame->tf_tpc, td->td_frame->tf_sp,
|
||||
td->td_frame->tf_tstate);
|
||||
return (EJUSTRETURN);
|
||||
}
|
||||
|
||||
@ -656,37 +625,18 @@ Debugger(const char *msg)
|
||||
int
|
||||
fill_regs(struct thread *td, struct reg *regs)
|
||||
{
|
||||
struct trapframe *tf;
|
||||
|
||||
tf = td->td_frame;
|
||||
regs->r_tstate = tf->tf_tstate;
|
||||
regs->r_pc = tf->tf_tpc;
|
||||
regs->r_npc = tf->tf_tnpc;
|
||||
regs->r_y = tf->tf_y;
|
||||
bcopy(tf->tf_global, regs->r_global, sizeof(tf->tf_global));
|
||||
bcopy(tf->tf_out, regs->r_out, sizeof(tf->tf_out));
|
||||
/* XXX - these are a pain to get at */
|
||||
bzero(regs->r_in, sizeof(regs->r_in));
|
||||
bzero(regs->r_local, sizeof(regs->r_local));
|
||||
bcopy(td->td_frame, regs, sizeof(*regs));
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
set_regs(struct thread *td, struct reg *regs)
|
||||
{
|
||||
struct trapframe *tf;
|
||||
|
||||
tf = td->td_frame;
|
||||
if (((regs->r_pc | regs->r_npc) & 3) != 0)
|
||||
return (EINVAL);
|
||||
if (!TSTATE_SECURE(regs->r_tstate))
|
||||
return (EINVAL);
|
||||
tf->tf_tstate = regs->r_tstate;
|
||||
tf->tf_tpc = regs->r_pc;
|
||||
tf->tf_tnpc = regs->r_npc;
|
||||
tf->tf_y = regs->r_y;
|
||||
bcopy(regs->r_global, tf->tf_global, sizeof(regs->r_global));
|
||||
bcopy(regs->r_out, tf->tf_out, sizeof(regs->r_out));
|
||||
bcopy(regs, td->td_frame, sizeof(*regs));
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -714,8 +664,8 @@ fill_fpregs(struct thread *td, struct fpreg *fpregs)
|
||||
tf = td->td_frame;
|
||||
bcopy(pcb->pcb_fpstate.fp_fb, fpregs->fr_regs,
|
||||
sizeof(pcb->pcb_fpstate.fp_fb));
|
||||
fpregs->fr_fprs = tf->tf_fprs;
|
||||
fpregs->fr_fsr = tf->tf_fsr;
|
||||
fpregs->fr_gsr = tf->tf_gsr;
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -729,7 +679,7 @@ set_fpregs(struct thread *td, struct fpreg *fpregs)
|
||||
tf = td->td_frame;
|
||||
bcopy(fpregs->fr_regs, pcb->pcb_fpstate.fp_fb,
|
||||
sizeof(fpregs->fr_regs));
|
||||
tf->tf_fprs = fpregs->fr_fprs;
|
||||
tf->tf_fsr = fpregs->fr_fsr;
|
||||
tf->tf_gsr = fpregs->fr_gsr;
|
||||
return (0);
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ ENTRY(cpu_switch)
|
||||
* If the current thread was using floating point, save its context.
|
||||
*/
|
||||
ldx [%l0 + TD_FRAME], %l2
|
||||
ldub [%l2 + TF_FPRS], %l3
|
||||
ldx [%l2 + TF_FPRS], %l3
|
||||
andcc %l3, FPRS_FEF, %g0
|
||||
bz,a,pt %xcc, 1f
|
||||
nop
|
||||
@ -75,7 +75,7 @@ ENTRY(cpu_switch)
|
||||
membar #Sync
|
||||
wr %g0, 0, %fprs
|
||||
andn %l3, FPRS_FEF, %l3
|
||||
stb %l3, [%l2 + TF_FPRS]
|
||||
stx %l3, [%l2 + TF_FPRS]
|
||||
|
||||
/*
|
||||
* Flush the windows out to the stack and save the current frame
|
||||
|
@ -158,6 +158,8 @@ const char *trap_msg[] = {
|
||||
"kernel stack fault",
|
||||
};
|
||||
|
||||
CTASSERT(sizeof(struct trapframe) == 256);
|
||||
|
||||
int debugger_on_signal = 0;
|
||||
SYSCTL_INT(_debug, OID_AUTO, debugger_on_signal, CTLFLAG_RW,
|
||||
&debugger_on_signal, 0, "");
|
||||
|
Loading…
Reference in New Issue
Block a user