};
struct sigcontext {
+ int trap_style; /* how should context be restored? KTS_* */
int sc_flags; /* sigstack state to restore (including
* MF_FPU_INITIALIZED)
*/
pr->p_reg.psr = INIT_PSR;
}
-void arch_proc_setcontext(struct proc *p, struct stackframe_s *state, int isuser)
+void arch_proc_setcontext(struct proc *p, struct stackframe_s *state,
+ int isuser, int trapstyle)
{
}
pr->p_reg.ds = USER_DS_SELECTOR;
/* set full context and make sure it gets restored */
- arch_proc_setcontext(pr, ®, 0);
+ arch_proc_setcontext(pr, ®, 0, KTS_FULLCONTEXT);
}
void arch_set_secondary_ipc_return(struct proc *p, u32_t val)
*((reg_t *)stk) = (reg_t) p;
/* make sure IF is on in FLAGS so that interrupts won't be disabled
- * once p's context is restored. this should not be possible.
+ * once p's context is restored.
*/
- assert(p->p_reg.psw & (1L << 9));
+ p->p_reg.psw |= IF_MASK;
+
+ /* Set TRACEBIT state properly. */
+ if(p->p_misc_flags & MF_STEP)
+ p->p_reg.psw |= TRACEBIT;
+ else
+ p->p_reg.psw &= ~TRACEBIT;
return p;
}
-void arch_proc_setcontext(struct proc *p, struct stackframe_s *state, int isuser)
+void arch_proc_setcontext(struct proc *p, struct stackframe_s *state,
+ int isuser, int trap_style)
{
if(isuser) {
/* Restore user bits of psw from sc, maintain system bits
}
if(p->p_seg.p_kern_trap_style == KTS_NONE)
printf("WARNINIG: setting full context of out-of-kernel process\n");
- p->p_seg.p_kern_trap_style = KTS_FULLCONTEXT;
+ p->p_seg.p_kern_trap_style = trap_style;
}
void restore_user_context(struct proc *p)
outb(COM1_LCR, lcr);
}
#endif
-
frame->eip = (reg_t) __frstor_failure;
return;
}
+
+ if(frame->vector == DEBUG_VECTOR
+ && (saved_proc->p_reg.psw & TRACEBIT)
+ && (saved_proc->p_seg.p_kern_trap_style == KTS_NONE)) {
+ /* Getting a debug trap in the kernel is legitimate
+ * if a traced process entered the kernel using sysenter
+ * or syscall; the trap flag is not cleared then.
+ *
+ * It triggers on the first kernel entry so the trap
+ * style is still KTS_NONE.
+ */
+
+ frame->eflags &= ~TRACEBIT;
+
+ return;
+
+ /* If control passes, this case is not recognized as legitimate
+ * and we panic later on after all.
+ */
+ }
}
if(frame->vector == PAGE_FAULT_VECTOR) {
mov %esi, SPREG(%ebp) /* esi is return esp */
mov %edx, PCREG(%ebp) /* edx is return eip */
+ /* save PSW */
+ pushf
+ pop %edx
+ mov %edx, PSWREG(%ebp)
+
/* check for call type; do_ipc? */
cmp $IPCVEC_UM, %edi
jz ipc_entry_common
mov SPREG(%ebp), %ecx /* sysexit restores ESP using ECX */
mov AXREG(%ebp), %eax /* trap return value */
mov BXREG(%ebp), %ebx /* secondary return value */
+ movl PSWREG(%ebp), %edi /* load desired PSW to EDI */
sti /* enable interrupts */
sysexit /* jump to EIP in user */
mov SPREG(%ebp), %esp /* restore ESP directly */
mov AXREG(%ebp), %eax /* trap return value */
mov BXREG(%ebp), %ebx /* secondary return value */
+ movl PSWREG(%ebp), %edi /* load desired PSW to EDI */
sysret /* jump to EIP in user */
ENTRY(restore_user_context_int)
SETARGS /* call-specific register setup */ ;\
sysenter /* disappear into kernel */ ;\
0: ;\
+ push %edi /* kernel has desired PSW in %edi */ ;\
+ popf /* set PSW kernel wants us to have */ ;\
mov %ebx, %ecx /* return w. state mangled; save %ebx */;\
pop %edi ;\
pop %esi ;\
SETARGS /* call-specific register setup */ ;\
movl %ecx, %edx /* %ecx is clobbered by SYSCALL */ ;\
syscall /* disappear into kernel */ ;\
+ push %edi /* kernel has desired PSW in %edi */ ;\
+ popf /* set PSW kernel wants us to have */ ;\
mov %ebx, %ecx /* return w. state mangled; save %ebx */;\
pop %edi ;\
pop %esi ;\
message from this sender but could not
because of VM modifying the sender's address
space*/
+#define MF_STEP 0x40000 /* Single-step process */
/* Magic process table addresses. */
#define BEG_PROC_ADDR (&proc[0])
void dequeue(struct proc *rp);
void switch_to_user(void);
void arch_proc_reset(struct proc *rp);
-void arch_proc_setcontext(struct proc *rp, struct stackframe_s *state, int user);
+void arch_proc_setcontext(struct proc *rp, struct stackframe_s *state,
+ int user, int restorestyle);
struct proc * arch_finish_switch_to_user(void);
struct proc *endpoint_lookup(endpoint_t ep);
#if DEBUG_ENABLE_IPC_WARNINGS
rpc->p_user_time = 0; /* set all the accounting times to 0 */
rpc->p_sys_time = 0;
-#if defined(__i386__)
- rpc->p_reg.psw &= ~TRACEBIT; /* clear trace bit */
-#endif
rpc->p_misc_flags &=
- ~(MF_VIRT_TIMER | MF_PROF_TIMER | MF_SC_TRACE | MF_SPROF_SEEN);
+ ~(MF_VIRT_TIMER | MF_PROF_TIMER | MF_SC_TRACE | MF_SPROF_SEEN | MF_STEP);
rpc->p_virt_left = 0; /* disable, clear the process-virtual timers */
rpc->p_prof_left = 0;
#endif
/* Restore the registers. */
- arch_proc_setcontext(rp, &sc.sc_regs, 1);
+ arch_proc_setcontext(rp, &sc.sc_regs, 1, sc.trap_style);
#if defined(__i386__)
if(sc.sc_flags & MF_FPU_INITIALIZED)
{
/* Copy the registers to the sigcontext structure. */
memcpy(&sc.sc_regs, (char *) &rp->p_reg, sizeof(sigregs));
- #if defined(__i386__)
+
+#if defined(__i386__)
+ sc.trap_style = rp->p_seg.p_kern_trap_style;
+
+ if(sc.trap_style == KTS_NONE) {
+ printf("do_sigsend: sigsend an unsaved process\n");
+ return EINVAL;
+ }
+
if(proc_used_fpu(rp)) {
/* save the FPU context before saving it to the sig context */
save_fpu(rp);
memcpy(&sc.sc_fpu_state, rp->p_seg.fpu_state, FPU_XFP_SIZE);
}
- #endif
+#endif
/* Finish the sigcontext initialization. */
sc.sc_mask = smsg.sm_mask;
switch (tr_request) {
case T_STOP: /* stop process */
RTS_SET(rp, RTS_P_STOP);
-#if defined(__i386__)
- rp->p_reg.psw &= ~TRACEBIT; /* clear trace bit */
-#endif
- rp->p_misc_flags &= ~MF_SC_TRACE; /* clear syscall trace flag */
+ /* clear syscall trace and single step flags */
+ rp->p_misc_flags &= ~(MF_SC_TRACE | MF_STEP);
return(OK);
case T_GETINS: /* return value from instruction space */
break;
case T_STEP: /* set trace bit */
-#if defined(__i386__)
- rp->p_reg.psw |= TRACEBIT;
-#endif
+ rp->p_misc_flags |= MF_STEP;
RTS_UNSET(rp, RTS_P_STOP);
m_ptr->CTL_DATA = 0;
break;