Use the MI macro TRAPF_USERMODE() instead of open-coded checks for
SEL_UPL and sometimes PSL_VM. This is just a style change on amd64, but on i386 it fixes 1 unimportant place where the PSL_VM check was missing and starts fixing 1 important place where the PSL_VM check had a logic error. Fix logic errors in treating vm86 bioscall mode as kernel mode. The main place checked all the necessary flags, but put the necessary parentheses for the PSL_VM and PCB_VM86CALL checks in the wrong place. The broken case is only reached if a vm86 bioscall uses a %cs which is nonzero mod 4, but that is unusual -- most bios calls start with %cs = 0xc000 or 0xf000 and rarely change it. Another place was missing the check for PCB_VM86CALL, but was only reachable if there are bugs virtualizing PSL_I. Add a macro TF_HAS_STACKREGS() and use this instead of converting open-coded checks of SEL_UPL, etc. to TRAPF_USERMODE() when we only care about whether the frame has stack registers. This fixes 3 places in my recent fix for register variables in vm86 mode where I messed up the PSL_VM check and cleans up other places.
This commit is contained in:
parent
0eb8d46232
commit
701ac88055
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=305807
@ -236,7 +236,7 @@ trap(struct trapframe *frame)
|
|||||||
* interrupts disabled until they are accidentally
|
* interrupts disabled until they are accidentally
|
||||||
* enabled later.
|
* enabled later.
|
||||||
*/
|
*/
|
||||||
if (ISPL(frame->tf_cs) == SEL_UPL)
|
if (TRAPF_USERMODE(frame))
|
||||||
uprintf(
|
uprintf(
|
||||||
"pid %ld (%s): trap %d with interrupts disabled\n",
|
"pid %ld (%s): trap %d with interrupts disabled\n",
|
||||||
(long)curproc->p_pid, curthread->td_name, type);
|
(long)curproc->p_pid, curthread->td_name, type);
|
||||||
@ -260,7 +260,7 @@ trap(struct trapframe *frame)
|
|||||||
|
|
||||||
code = frame->tf_err;
|
code = frame->tf_err;
|
||||||
|
|
||||||
if (ISPL(frame->tf_cs) == SEL_UPL) {
|
if (TRAPF_USERMODE(frame)) {
|
||||||
/* user trap */
|
/* user trap */
|
||||||
|
|
||||||
td->td_pticks = 0;
|
td->td_pticks = 0;
|
||||||
@ -787,7 +787,7 @@ trap_fatal(frame, eva)
|
|||||||
else
|
else
|
||||||
msg = "UNKNOWN";
|
msg = "UNKNOWN";
|
||||||
printf("\n\nFatal trap %d: %s while in %s mode\n", type, msg,
|
printf("\n\nFatal trap %d: %s while in %s mode\n", type, msg,
|
||||||
ISPL(frame->tf_cs) == SEL_UPL ? "user" : "kernel");
|
TRAPF_USERMODE(frame) ? "user" : "kernel");
|
||||||
#ifdef SMP
|
#ifdef SMP
|
||||||
/* two separate prints in case of a trap on an unmapped page */
|
/* two separate prints in case of a trap on an unmapped page */
|
||||||
printf("cpuid = %d; ", PCPU_GET(cpuid));
|
printf("cpuid = %d; ", PCPU_GET(cpuid));
|
||||||
@ -804,7 +804,7 @@ trap_fatal(frame, eva)
|
|||||||
}
|
}
|
||||||
printf("instruction pointer = 0x%lx:0x%lx\n",
|
printf("instruction pointer = 0x%lx:0x%lx\n",
|
||||||
frame->tf_cs & 0xffff, frame->tf_rip);
|
frame->tf_cs & 0xffff, frame->tf_rip);
|
||||||
if (ISPL(frame->tf_cs) == SEL_UPL) {
|
if (TF_HAS_STACKREGS(frame)) {
|
||||||
ss = frame->tf_ss & 0xffff;
|
ss = frame->tf_ss & 0xffff;
|
||||||
esp = frame->tf_rsp;
|
esp = frame->tf_rsp;
|
||||||
} else {
|
} else {
|
||||||
@ -934,7 +934,7 @@ amd64_syscall(struct thread *td, int traced)
|
|||||||
ksiginfo_t ksi;
|
ksiginfo_t ksi;
|
||||||
|
|
||||||
#ifdef DIAGNOSTIC
|
#ifdef DIAGNOSTIC
|
||||||
if (ISPL(td->td_frame->tf_cs) != SEL_UPL) {
|
if (!TRAPF_USERMODE(frame)) {
|
||||||
panic("syscall");
|
panic("syscall");
|
||||||
/* NOT REACHED */
|
/* NOT REACHED */
|
||||||
}
|
}
|
||||||
|
@ -82,8 +82,7 @@ struct db_variable *db_eregs = db_regs + nitems(db_regs);
|
|||||||
static __inline int
|
static __inline int
|
||||||
get_esp(struct trapframe *tf)
|
get_esp(struct trapframe *tf)
|
||||||
{
|
{
|
||||||
return ((ISPL(tf->tf_cs) || kdb_frame->tf_eflags & PSL_VM) ?
|
return (TF_HAS_STACKREGS(tf) ? tf->tf_esp : (intptr_t)&tf->tf_esp);
|
||||||
tf->tf_esp : (intptr_t)&tf->tf_esp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -147,7 +146,7 @@ db_esp(struct db_variable *vp, db_expr_t *valuep, int op)
|
|||||||
|
|
||||||
if (op == DB_VAR_GET)
|
if (op == DB_VAR_GET)
|
||||||
*valuep = get_esp(kdb_frame);
|
*valuep = get_esp(kdb_frame);
|
||||||
else if (ISPL(kdb_frame->tf_cs))
|
else if (TF_HAS_STACKREGS(kdb_frame))
|
||||||
kdb_frame->tf_esp = *valuep;
|
kdb_frame->tf_esp = *valuep;
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
@ -180,9 +179,9 @@ db_ss(struct db_variable *vp, db_expr_t *valuep, int op)
|
|||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
if (op == DB_VAR_GET)
|
if (op == DB_VAR_GET)
|
||||||
*valuep = (ISPL(kdb_frame->tf_cs) ||
|
*valuep = TF_HAS_STACKREGS(kdb_frame) ? kdb_frame->tf_ss :
|
||||||
kdb_frame->tf_eflags & PSL_VM) ? kdb_frame->tf_ss : rss();
|
rss();
|
||||||
else if (ISPL(kdb_frame->tf_cs) || kdb_frame->tf_eflags & PSL_VM)
|
else if (TF_HAS_STACKREGS(kdb_frame))
|
||||||
kdb_frame->tf_ss = *valuep;
|
kdb_frame->tf_ss = *valuep;
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
@ -439,7 +438,7 @@ db_backtrace(struct thread *td, struct trapframe *tf, struct i386_frame *frame,
|
|||||||
* Find where the trap frame actually ends.
|
* Find where the trap frame actually ends.
|
||||||
* It won't contain tf_esp or tf_ss unless crossing rings.
|
* It won't contain tf_esp or tf_ss unless crossing rings.
|
||||||
*/
|
*/
|
||||||
if (ISPL(kdb_frame->tf_cs))
|
if (TF_HAS_STACKREGS(kdb_frame))
|
||||||
instr = (int)(kdb_frame + 1);
|
instr = (int)(kdb_frame + 1);
|
||||||
else
|
else
|
||||||
instr = (int)&kdb_frame->tf_esp;
|
instr = (int)&kdb_frame->tf_esp;
|
||||||
|
@ -267,7 +267,8 @@ trap(struct trapframe *frame)
|
|||||||
* interrupts disabled until they are accidentally
|
* interrupts disabled until they are accidentally
|
||||||
* enabled later.
|
* enabled later.
|
||||||
*/
|
*/
|
||||||
if (ISPL(frame->tf_cs) == SEL_UPL || (frame->tf_eflags & PSL_VM))
|
if (TRAPF_USERMODE(frame) &&
|
||||||
|
(curpcb->pcb_flags & PCB_VM86CALL) == 0)
|
||||||
uprintf(
|
uprintf(
|
||||||
"pid %ld (%s): trap %d with interrupts disabled\n",
|
"pid %ld (%s): trap %d with interrupts disabled\n",
|
||||||
(long)curproc->p_pid, curthread->td_name, type);
|
(long)curproc->p_pid, curthread->td_name, type);
|
||||||
@ -307,9 +308,7 @@ trap(struct trapframe *frame)
|
|||||||
enable_intr();
|
enable_intr();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ISPL(frame->tf_cs) == SEL_UPL) ||
|
if (TRAPF_USERMODE(frame) && (curpcb->pcb_flags & PCB_VM86CALL) == 0) {
|
||||||
((frame->tf_eflags & PSL_VM) &&
|
|
||||||
!(curpcb->pcb_flags & PCB_VM86CALL))) {
|
|
||||||
/* user trap */
|
/* user trap */
|
||||||
|
|
||||||
td->td_pticks = 0;
|
td->td_pticks = 0;
|
||||||
@ -963,7 +962,7 @@ trap_fatal(frame, eva)
|
|||||||
}
|
}
|
||||||
printf("instruction pointer = 0x%x:0x%x\n",
|
printf("instruction pointer = 0x%x:0x%x\n",
|
||||||
frame->tf_cs & 0xffff, frame->tf_eip);
|
frame->tf_cs & 0xffff, frame->tf_eip);
|
||||||
if ((ISPL(frame->tf_cs) == SEL_UPL) || (frame->tf_eflags & PSL_VM)) {
|
if (TF_HAS_STACKREGS(frame)) {
|
||||||
ss = frame->tf_ss & 0xffff;
|
ss = frame->tf_ss & 0xffff;
|
||||||
esp = frame->tf_esp;
|
esp = frame->tf_esp;
|
||||||
} else {
|
} else {
|
||||||
@ -1117,7 +1116,8 @@ syscall(struct trapframe *frame)
|
|||||||
ksiginfo_t ksi;
|
ksiginfo_t ksi;
|
||||||
|
|
||||||
#ifdef DIAGNOSTIC
|
#ifdef DIAGNOSTIC
|
||||||
if (ISPL(frame->tf_cs) != SEL_UPL) {
|
if (!(TRAPF_USERMODE(frame) &&
|
||||||
|
(curpcb->pcb_flags & PCB_VM86CALL) == 0)) {
|
||||||
panic("syscall");
|
panic("syscall");
|
||||||
/* NOT REACHED */
|
/* NOT REACHED */
|
||||||
}
|
}
|
||||||
|
@ -64,7 +64,7 @@ struct trapframe {
|
|||||||
int tf_eip;
|
int tf_eip;
|
||||||
int tf_cs;
|
int tf_cs;
|
||||||
int tf_eflags;
|
int tf_eflags;
|
||||||
/* below only when crossing rings (e.g. user to kernel) */
|
/* below only when crossing rings (user to kernel) */
|
||||||
int tf_esp;
|
int tf_esp;
|
||||||
int tf_ss;
|
int tf_ss;
|
||||||
};
|
};
|
||||||
@ -89,10 +89,10 @@ struct trapframe_vm86 {
|
|||||||
int tf_eip;
|
int tf_eip;
|
||||||
int tf_cs;
|
int tf_cs;
|
||||||
int tf_eflags;
|
int tf_eflags;
|
||||||
/* below only when crossing rings (e.g. user to kernel) */
|
/* below only when crossing rings (user (including vm86) to kernel) */
|
||||||
int tf_esp;
|
int tf_esp;
|
||||||
int tf_ss;
|
int tf_ss;
|
||||||
/* below only when switching out of VM86 mode */
|
/* below only when crossing from vm86 mode to kernel */
|
||||||
int tf_vm86_es;
|
int tf_vm86_es;
|
||||||
int tf_vm86_ds;
|
int tf_vm86_ds;
|
||||||
int tf_vm86_fs;
|
int tf_vm86_fs;
|
||||||
@ -136,6 +136,7 @@ struct trapframe {
|
|||||||
register_t tf_rip;
|
register_t tf_rip;
|
||||||
register_t tf_cs;
|
register_t tf_cs;
|
||||||
register_t tf_rflags;
|
register_t tf_rflags;
|
||||||
|
/* below only when crossing rings (user to kernel) */
|
||||||
register_t tf_rsp;
|
register_t tf_rsp;
|
||||||
register_t tf_ss;
|
register_t tf_ss;
|
||||||
};
|
};
|
||||||
@ -145,4 +146,13 @@ struct trapframe {
|
|||||||
#define TF_HASFPXSTATE 0x4
|
#define TF_HASFPXSTATE 0x4
|
||||||
#endif /* __amd64__ */
|
#endif /* __amd64__ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This alias for the MI TRAPF_USERMODE() should be used when we don't
|
||||||
|
* care about user mode itself, but need to know if a frame has stack
|
||||||
|
* registers. The difference is only logical, but on i386 the logic
|
||||||
|
* for using TRAPF_USERMODE() is complicated by sometimes treating vm86
|
||||||
|
* bioscall mode (which is a special ring 3 user mode) as kernel mode.
|
||||||
|
*/
|
||||||
|
#define TF_HAS_STACKREGS(tf) TRAPF_USERMODE(tf)
|
||||||
|
|
||||||
#endif /* _MACHINE_FRAME_H_ */
|
#endif /* _MACHINE_FRAME_H_ */
|
||||||
|
Loading…
Reference in New Issue
Block a user