- 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:
jake 2002-10-22 18:03:15 +00:00
parent 6856844ba3
commit 9130753f7b
9 changed files with 303 additions and 156 deletions

View File

@ -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];

View File

@ -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

View File

@ -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_ */

View File

@ -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

View File

@ -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));

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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, "");