kernel: trap-dependent state restore, trace fixes
. restore state depends on how saving of state was done; also remember trap style in sig context . actually set and restore TRACEBIT with new trap styles; have to remove it once process enters kernel though, done in debug trap exception handler . introduce MF_STEP that makes arch-specific code turn on trace bit instead of setting TRACEBIT directly, a bit more arch-friendly and avoids keeping precious state in per-process PSW arch-dependently
This commit is contained in:
@@ -48,7 +48,8 @@ void arch_proc_reset(struct proc *pr)
|
||||
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)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -182,7 +182,7 @@ void arch_proc_reset(struct proc *pr)
|
||||
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)
|
||||
@@ -511,14 +511,21 @@ struct proc * arch_finish_switch_to_user(void)
|
||||
*((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
|
||||
@@ -555,7 +562,7 @@ void arch_proc_setcontext(struct proc *p, struct stackframe_s *state, int isuser
|
||||
}
|
||||
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)
|
||||
@@ -666,4 +673,3 @@ static void ser_init(void)
|
||||
outb(COM1_LCR, lcr);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -228,6 +228,26 @@ void exception_handler(int is_nested, struct exception_frame * frame)
|
||||
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) {
|
||||
|
||||
@@ -240,6 +240,11 @@ syscall_sysenter_common:
|
||||
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
|
||||
@@ -396,6 +401,7 @@ ENTRY(restore_user_context_sysenter)
|
||||
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 */
|
||||
|
||||
@@ -410,6 +416,7 @@ ENTRY(restore_user_context_syscall)
|
||||
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)
|
||||
|
||||
@@ -35,6 +35,8 @@ ENTRY(usermapped_ ## name ## _sysenter) ;\
|
||||
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 ;\
|
||||
@@ -59,6 +61,8 @@ ENTRY(usermapped_ ## name ## _syscall) ;\
|
||||
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 ;\
|
||||
|
||||
Reference in New Issue
Block a user