v9dep.c revision a859926565cb356b64ec9747a88da4ff003ad4f8
* He's not currently using the FPU but wants to in his * new context - arrange for this on return to userland. * Get setfpregs to restore fpu_en to zero * (pfp->fp_fprs & FPRS_FEF) == FPRS_FEF). * Load up a user's floating point context. * For v9 kernel, copy all of the fp regs. * For v8 kernel, copy v8 fp regs (lower half of v9 fp regs). * Restore entire fsr for v9, only lower half for v8. /* FSR ignores these bits on load, so they can not be set */ * If not the current process then resume() will handle it. /* force resume to reload fp regs */ * Load up FPU with new floating point context. "setfpregs with fp disabled!\n");
* Load all fp regs for v9 user programs, but only * load the lower half for v8[plus] programs. * Currently the lwp has floating point enabled. * Turn off FPRS_FEF in user's fprs, saved and #
endif /* _SYSCALL32_IMPL */ * NOTE: 'lwp' might not correspond to 'curthread' since this is * called from code in /proc to set the registers of another lwp. * If the context being loaded up includes a floating queue, * we need to simulate those instructions (since we can't reload * the fpu) and pass the process any appropriate signals * Get floating-point registers. * NOTE: 'lwp' might not correspond to 'curthread' since this is * called from code in /proc to set the registers of another lwp. * First check the fpu_en case, for normal fp programs. * Force setfpregs to restore the fp context in * setfpregs for the memcpy and threads cases (where * pfp->fpu_en == 0 && (pfp->fp_fprs & FPRS_FEF) == FPRS_FEF). * If we have an fpu and the current thread owns the fp * context, flush fp * registers into the pcb. Save all * the fp regs for v9, xregs_getfpregs saves the upper half * for v8plus. Save entire fsr for v9, only lower half for v8. "getfpregs with fp disabled!\n");
for (i = 0; i <
32; i++)
/* NaN */ for (i =
16; i <
32; i++)
/* NaN */ #
endif /* _SYSCALL32_IMPL */ * NOTE: 'lwp' might not correspond to 'curthread' since this is * called from code in /proc to set the registers of another lwp. * pc and npc must be 4-byte aligned on sparc. * We silently make it so to avoid a watchdog reset. * This was called from a system call, but we * do not want to return via the shared window; * restoring the CPU context changes everything. * Return the general registers. * NOTE: 'lwp' might not correspond to 'curthread' since this is * called from code in /proc to get the registers of another lwp. * Return the user-level PC. * If in a system call, return the address of the syscall trap. for (i = 0; i <
wbcnt; i++) {
for (i = 0; i <
wbcnt; i++) {
* NOTE: 'lwp' might not correspond to 'curthread' since this is * called from code in /proc to set the registers of another lwp. for (i = 0; i <
wbcnt; i++) {
for (i = 0; i <
wbcnt; i++) {
* For things that depend on register state being on the stack, * copy any register windows that get saved into the window buffer * (in the pcb) onto the stack. This normally gets fixed up * before returning to a user program. Callers of this routine * require this to happen immediately because a later kernel * operation depends on window state (like instruction simulation). * Reduce sp to a 32 bit value. This was originally * done by casting down to uint32_t and back up to * caddr_t, but one compiler didn't like that, so the * uintptr_t casts were added. The temporary 32 bit * variable was introduced to avoid depending on all * compilers to generate the desired assembly code for a * quadruple cast in a single expression. * Determine the offending address. * It may not be the stack pointer itself. * stack was aligned and copyout succeeded; * move other windows down. }
/* while there are windows in the wbuf */ * Reduce r_sp to a 32 bit value before storing it in sp1. This * was originally done by casting down to uint32_t and back up * to caddr_t, but that generated complaints under one compiler. * The uintptr_t cast was added to address that, and the * temporary 32 bit variable was introduced to avoid depending * on all compilers to generate the desired assembly code for a * triple cast in a single expression. * Clear registers on exec(2). * Initialize user registers. * Clear the fixalignment flag * Throw out old user windows, init window buf. * Here we initialize minimal fpu state. * The rest is done at the first floating * point instruction that a process executes * or by the lib_psr memcpy routines. * Construct the execution environment for the user's signal * handler and arrange for control to be given to it on return * to userland. The library code now calls setcontext() to * clean up after the signal handler, so sigret() is no longer * 'volatile' is needed to ensure that values are * correct on the error return from on_fault(). volatile int minstacksz;
/* min stack required to catch signal */ int newstack = 0;
/* if true, switching to altstack */ * Make sure the current last user window has been flushed to * the stack save area before we change the sp. * Restore register window if a debugger modified it. * Clear the watchpoint return stack pointers. * We know that sizeof (siginfo_t) is stack-aligned: * 128 bytes for ILP32, 256 bytes for LP64. * These two fields are pointed to by ABI structures and may * be of arbitrary length. Size them now so we know how big * the signal frame has to be. * Extra registers, if support by this platform, may be of arbitrary * length. Size them now so we know how big the signal frame has to be. * For sparcv9 _LP64 user programs, use asrs instead of the xregs. * Figure out whether we will be handling this signal on * an alternate stack specified by the user. Then allocate * and validate the stack requirements for the signal handler * context. on_fault will catch any faults. * Force proper stack pointer alignment, even in the face of a * misaligned stack pointer from user-level before the signal. * Don't use the SA() macro because that rounds up, not down. * If we were unable to flush all register windows to * the stack and we are not now on an alternate stack, * just dump core with a SIGSEGV back in psig(). * Could call grow here, but stack growth now handled below * in code protected by on_fault(). * Make sure process hasn't trashed its stack. printf(
"sendsig: bad signal stack cmd=%s, pid=%d, sig=%d\n",
printf(
"sigsp = 0x%p, action = 0x%p, upc = 0x%lx\n",
printf(
"fp above USRSTACK\n");
* save extra register state if it exists * We stand on our head to deal with * the real time profiling signal. * Fill in the stuff that doesn't fit * in a normal k_siginfo structure. * When flush_user_windows_to_stack() can't save all the * windows to the stack, it puts them in the lwp's pcb. * forget the fp queue so that the signal handler can run * without being harrassed--it will do a setcontext that will * re-establish the queue if there still is one * NOTE: fp_runq() relies on the qcnt field being zeroed here * to terminate its processing of the queue after signal /* Also, syscall needs to know about this */ * Since we flushed the user's windows and we are changing his * stack pointer, the window that the user will return to will * be restored from the save area in the frame we are setting up. * We copy in save area for old stack pointer so that debuggers * can do a proper stack backtrace from the signal handler. * Set up user registers for execution of signal handler. /* make sure %asi is ASI_PNF */ * Don't set lwp_eosys here. sendsig() is called via psig() after * lwp_eosys is handled, so setting it here would affect the next printf(
"sendsig: bad signal stack cmd=%s, pid=%d, sig=%d\n",
printf(
"on fault, sigsp = %p, action = %p, upc = 0x%lx\n",
* Construct the execution environment for the user's signal * handler and arrange for control to be given to it on return * to userland. The library code now calls setcontext() to * clean up after the signal handler, so sigret() is no longer * 'volatile' is needed to ensure that values are * correct on the error return from on_fault(). volatile int minstacksz;
/* min stack required to catch signal */ int newstack = 0;
/* if true, switching to altstack */ * Make sure the current last user window has been flushed to * the stack save area before we change the sp. * Restore register window if a debugger modified it. * Clear the watchpoint return stack pointers. * These two fields are pointed to by ABI structures and may * be of arbitrary length. Size them now so we know how big * the signal frame has to be. * Extra registers, if supported by this platform, may be of arbitrary * length. Size them now so we know how big the signal frame has to be. * Figure out whether we will be handling this signal on * an alternate stack specified by the user. Then allocate * and validate the stack requirements for the signal handler * context. on_fault will catch any faults. * Force proper stack pointer alignment, even in the face of a * misaligned stack pointer from user-level before the signal. * Don't use the SA32() macro because that rounds up, not down. * If we were unable to flush all register windows to * the stack and we are not now on an alternate stack, * just dump core with a SIGSEGV back in psig(). * Could call grow here, but stack growth now handled below * in code protected by on_fault(). * Make sure process hasn't trashed its stack. printf(
"sendsig32: bad signal stack cmd=%s, pid=%d, sig=%d\n",
printf(
"sigsp = 0x%p, action = 0x%p, upc = 0x%lx\n",
printf(
"fp above USRSTACK32\n");
* save extra register state if it exists * We stand on our head to deal with * the real time profiling signal. * Fill in the stuff that doesn't fit * in a normal k_siginfo structure. * When flush_user_windows_to_stack() can't save all the * windows to the stack, it puts them in the lwp's pcb. * Update the (already copied out) fpu32.fpu_q pointer * from NULL to the 32-bit address on the user's stack * where we then copyout the fq32 to. * forget the fp queue so that the signal handler can run * without being harrassed--it will do a setcontext that will * re-establish the queue if there still is one * NOTE: fp_runq() relies on the qcnt field being zeroed here * to terminate its processing of the queue after signal /* Also, syscall needs to know about this */ * Since we flushed the user's windows and we are changing his * stack pointer, the window that the user will return to will * be restored from the save area in the frame we are setting up. * We copy in save area for old stack pointer so that debuggers * can do a proper stack backtrace from the signal handler. * Set up user registers for execution of signal handler. /* make sure %asi is ASI_PNF */ * Don't set lwp_eosys here. sendsig() is called via psig() after * lwp_eosys is handled, so setting it here would affect the next printf(
"sendsig32: bad signal stack cmd=%s, pid=%d, sig=%d\n",
printf(
"on fault, sigsp = 0x%p, action = 0x%p, upc = 0x%lx\n",
#
endif /* _SYSCALL32_IMPL */ * load user registers into lwp. * thrptr ignored for sparc. * set syscall()'s return values for a lwp. * set stack pointer for a lwp * Take any PCB specific actions that are required or flagged in the PCB. * Invalidate the saved user register windows in the pcb struct * for the current thread. They will no longer be preserved. * This has the effect of invalidating all (any) of the * user level windows that are currently sitting in the * Copy the floating point queue if and only if there is a queue and a place * to copy it to. Let xregs take care of the other fp regs, for v8plus. * The issue is that while we are handling the fq32 in sendsig, we * still need a 64-bit pointer to it, and the caddr32_t in fpregset32_t * will not suffice, so we have the third parameter to this function. * Copy the floating point queue if and only if there is a queue and a place * to copy it to. Let xregs take care of the other fp regs, for v8plus. * The *dfq is required to escape the bzero in both this function and in * ucontext_32ton. The *sfq is required because once the fq32 is copied * into the kernel, in setcontext, then we need a 64-bit pointer to it. for (i = 0; i <
4; i++) {
/* REG_CCR is 0, skip over it and handle it after this loop */ * A valid fpregs is only copied in if (uc.uc_flags & UC_FPU), * otherwise there is no guarantee that anything in fpregs is valid. #
endif /* _SYSCALL32_IMPL */ * The panic code invokes panic_saveregs() to record the contents of a * regs structure into the specified panic_data structure for debuggers.