- For some old Cyrix CPUs, %cr2 is clobbered by interrupts. This
problem is worked around by using an interrupt gate for the page fault handler. This code was originally made for NetBSD/pc98 by Naofumi Honda <honda@kururu.math.sci.hokudai.ac.jp> and has already been in PC98 tree. Because of this bug, trap_fatal cannot show correct page fault address if %cr2 is obtained in this function. Therefore, trap_fatal uses the value from trap() function. - The trap handler always enables interruption when buggy application or kernel code has disabled interrupts and then trapped. This code was prepared by Bruce Evans <bde@FreeBSD.org>. Submitted by: Bruce Evans <bde@FreeBSD.org> Naofumi Honda <honda@kururu.math.sci.hokudai.ac.jp>
This commit is contained in:
parent
2992cdbc3f
commit
9ad861edee
@ -35,7 +35,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: @(#)machdep.c 7.4 (Berkeley) 6/3/91
|
||||
* $Id: machdep.c,v 1.315 1998/11/03 21:07:50 msmith Exp $
|
||||
* $Id: machdep.c,v 1.316 1998/11/26 18:50:22 eivind Exp $
|
||||
*/
|
||||
|
||||
#include "apm.h"
|
||||
@ -1224,7 +1224,7 @@ init386(first)
|
||||
setidt(11, &IDTVEC(missing), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
|
||||
setidt(12, &IDTVEC(stk), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
|
||||
setidt(13, &IDTVEC(prot), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
|
||||
setidt(14, &IDTVEC(page), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
|
||||
setidt(14, &IDTVEC(page), SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
|
||||
setidt(15, &IDTVEC(rsvd), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
|
||||
setidt(16, &IDTVEC(fpu), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
|
||||
setidt(17, &IDTVEC(align), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
|
||||
|
@ -35,7 +35,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: @(#)trap.c 7.4 (Berkeley) 5/13/91
|
||||
* $Id: trap.c,v 1.127 1998/04/28 18:15:04 eivind Exp $
|
||||
* $Id: trap.c,v 1.128 1998/08/23 10:16:26 bde Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -104,8 +104,8 @@ extern void trap __P((struct trapframe frame));
|
||||
extern int trapwrite __P((unsigned addr));
|
||||
extern void syscall __P((struct trapframe frame));
|
||||
|
||||
static int trap_pfault __P((struct trapframe *, int));
|
||||
static void trap_fatal __P((struct trapframe *));
|
||||
static int trap_pfault __P((struct trapframe *, int, vm_offset_t));
|
||||
static void trap_fatal __P((struct trapframe *, vm_offset_t));
|
||||
void dblfault_handler __P((void));
|
||||
|
||||
extern inthand_t IDTVEC(syscall);
|
||||
@ -216,9 +216,46 @@ trap(frame)
|
||||
struct proc *p = curproc;
|
||||
u_quad_t sticks = 0;
|
||||
int i = 0, ucode = 0, type, code;
|
||||
#ifdef DEBUG
|
||||
u_long eva;
|
||||
#endif
|
||||
vm_offset_t eva;
|
||||
|
||||
if (!(frame.tf_eflags & PSL_I)) {
|
||||
/*
|
||||
* Buggy application or kernel code has disabled interrupts
|
||||
* and then trapped. Enabling interrupts now is wrong, but
|
||||
* it is better than running with interrupts disabled until
|
||||
* they are accidentally enabled later.
|
||||
*/
|
||||
type = frame.tf_trapno;
|
||||
if (ISPL(frame.tf_cs) == SEL_UPL || (frame.tf_eflags & PSL_VM))
|
||||
printf(
|
||||
"pid %ld (%s): trap %d with interrupts disabled\n",
|
||||
(long)curproc->p_pid, curproc->p_comm, type);
|
||||
else if (type != T_BPTFLT && type != T_TRCTRAP)
|
||||
/*
|
||||
* XXX not quite right, since this may be for a
|
||||
* multiple fault in user mode.
|
||||
*/
|
||||
printf("kernel trap %d with interrupts disabled\n",
|
||||
type);
|
||||
enable_intr();
|
||||
}
|
||||
|
||||
eva = 0;
|
||||
if (frame.tf_trapno == T_PAGEFLT) {
|
||||
/*
|
||||
* For some Cyrix CPUs, %cr2 is clobbered by interrupts.
|
||||
* This problem is worked around by using an interrupt
|
||||
* gate for the pagefault handler. We are finally ready
|
||||
* to read %cr2 and then must reenable interrupts.
|
||||
*
|
||||
* XXX this should be in the switch statement, but the
|
||||
* NO_FOOF_HACK and VM86 goto and ifdefs obfuscate the
|
||||
* flow of control too much for this to be obviously
|
||||
* correct.
|
||||
*/
|
||||
eva = rcr2();
|
||||
enable_intr();
|
||||
}
|
||||
|
||||
#if defined(I586_CPU) && !defined(NO_F00F_HACK)
|
||||
restart:
|
||||
@ -245,7 +282,7 @@ restart:
|
||||
*/
|
||||
case T_PROTFLT:
|
||||
case T_SEGNPFLT:
|
||||
trap_fatal(&frame);
|
||||
trap_fatal(&frame, eva);
|
||||
return;
|
||||
case T_TRCTRAP:
|
||||
type = T_BPTFLT; /* kernel breakpoint */
|
||||
@ -314,7 +351,7 @@ restart:
|
||||
break;
|
||||
|
||||
case T_PAGEFLT: /* page fault */
|
||||
i = trap_pfault(&frame, TRUE);
|
||||
i = trap_pfault(&frame, TRUE, eva);
|
||||
if (i == -1)
|
||||
return;
|
||||
#if defined(I586_CPU) && !defined(NO_F00F_HACK)
|
||||
@ -393,7 +430,7 @@ kernel_trap:
|
||||
|
||||
switch (type) {
|
||||
case T_PAGEFLT: /* page fault */
|
||||
(void) trap_pfault(&frame, FALSE);
|
||||
(void) trap_pfault(&frame, FALSE, eva);
|
||||
return;
|
||||
|
||||
case T_DNA:
|
||||
@ -541,7 +578,7 @@ kernel_trap:
|
||||
#endif /* NISA > 0 */
|
||||
}
|
||||
|
||||
trap_fatal(&frame);
|
||||
trap_fatal(&frame, eva);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -552,7 +589,6 @@ kernel_trap:
|
||||
trapsignal(p, i, ucode);
|
||||
|
||||
#ifdef DEBUG
|
||||
eva = rcr2();
|
||||
if (type <= MAX_TRAP_MSG) {
|
||||
uprintf("fatal process exception: %s",
|
||||
trap_msg[type]);
|
||||
@ -575,16 +611,16 @@ out:
|
||||
* debugging code.
|
||||
*/
|
||||
static int
|
||||
trap_pfault(frame, usermode)
|
||||
trap_pfault(frame, usermode, eva)
|
||||
struct trapframe *frame;
|
||||
int usermode;
|
||||
vm_offset_t eva;
|
||||
{
|
||||
vm_offset_t va;
|
||||
struct vmspace *vm = NULL;
|
||||
vm_map_t map = 0;
|
||||
int rv = 0;
|
||||
vm_prot_t ftype;
|
||||
int eva;
|
||||
struct proc *p = curproc;
|
||||
|
||||
if (frame->tf_err & PGEX_W)
|
||||
@ -592,9 +628,7 @@ trap_pfault(frame, usermode)
|
||||
else
|
||||
ftype = VM_PROT_READ;
|
||||
|
||||
eva = rcr2();
|
||||
va = trunc_page((vm_offset_t)eva);
|
||||
|
||||
va = trunc_page(eva);
|
||||
if (va < VM_MIN_KERNEL_ADDRESS) {
|
||||
vm_offset_t v;
|
||||
vm_page_t mpte;
|
||||
@ -603,7 +637,7 @@ trap_pfault(frame, usermode)
|
||||
(!usermode && va < VM_MAXUSER_ADDRESS &&
|
||||
(intr_nesting_level != 0 || curpcb == NULL ||
|
||||
curpcb->pcb_onfault == NULL))) {
|
||||
trap_fatal(frame);
|
||||
trap_fatal(frame, eva);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
@ -664,7 +698,7 @@ nogo:
|
||||
frame->tf_eip = (int)curpcb->pcb_onfault;
|
||||
return (0);
|
||||
}
|
||||
trap_fatal(frame);
|
||||
trap_fatal(frame, eva);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
@ -676,21 +710,19 @@ nogo:
|
||||
#endif
|
||||
|
||||
int
|
||||
trap_pfault(frame, usermode)
|
||||
trap_pfault(frame, usermode, eva)
|
||||
struct trapframe *frame;
|
||||
int usermode;
|
||||
vm_offset_t eva;
|
||||
{
|
||||
vm_offset_t va;
|
||||
struct vmspace *vm = NULL;
|
||||
vm_map_t map = 0;
|
||||
int rv = 0;
|
||||
vm_prot_t ftype;
|
||||
int eva;
|
||||
struct proc *p = curproc;
|
||||
|
||||
eva = rcr2();
|
||||
va = trunc_page((vm_offset_t)eva);
|
||||
|
||||
va = trunc_page(eva);
|
||||
if (va >= KERNBASE) {
|
||||
/*
|
||||
* Don't allow user-mode faults in kernel address space.
|
||||
@ -769,7 +801,7 @@ nogo:
|
||||
frame->tf_eip = (int)curpcb->pcb_onfault;
|
||||
return (0);
|
||||
}
|
||||
trap_fatal(frame);
|
||||
trap_fatal(frame, eva);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
@ -780,15 +812,15 @@ nogo:
|
||||
}
|
||||
|
||||
static void
|
||||
trap_fatal(frame)
|
||||
trap_fatal(frame, eva)
|
||||
struct trapframe *frame;
|
||||
vm_offset_t eva;
|
||||
{
|
||||
int code, type, eva, ss, esp;
|
||||
int code, type, ss, esp;
|
||||
struct soft_segment_descriptor softseg;
|
||||
|
||||
code = frame->tf_err;
|
||||
type = frame->tf_trapno;
|
||||
eva = rcr2();
|
||||
sdtossd(&gdt[IDXSEL(frame->tf_cs & 0xffff)].sd, &softseg);
|
||||
|
||||
if (type <= MAX_TRAP_MSG)
|
||||
|
@ -3,7 +3,7 @@
|
||||
#
|
||||
# modified for PC-9801
|
||||
#
|
||||
# $Id: files.pc98,v 1.71 1998/09/20 10:50:18 kato Exp $
|
||||
# $Id: files.pc98,v 1.72 1998/10/11 15:02:49 kato Exp $
|
||||
#
|
||||
# The long compile-with and dependency lines are required because of
|
||||
# limitations in config: backslash-newline doesn't work in strings, and
|
||||
@ -71,7 +71,7 @@ i386/i386/simplelock.s optional smp
|
||||
i386/i386/support.s standard
|
||||
i386/i386/swtch.s standard
|
||||
i386/i386/sys_machdep.c standard
|
||||
pc98/i386/trap.c standard
|
||||
i386/i386/trap.c standard
|
||||
pc98/i386/userconfig.c optional userconfig
|
||||
i386/i386/vm_machdep.c standard
|
||||
i386/i386/vm86.c optional vm86
|
||||
|
@ -35,7 +35,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: @(#)machdep.c 7.4 (Berkeley) 6/3/91
|
||||
* $Id: machdep.c,v 1.315 1998/11/03 21:07:50 msmith Exp $
|
||||
* $Id: machdep.c,v 1.316 1998/11/26 18:50:22 eivind Exp $
|
||||
*/
|
||||
|
||||
#include "apm.h"
|
||||
@ -1224,7 +1224,7 @@ init386(first)
|
||||
setidt(11, &IDTVEC(missing), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
|
||||
setidt(12, &IDTVEC(stk), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
|
||||
setidt(13, &IDTVEC(prot), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
|
||||
setidt(14, &IDTVEC(page), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
|
||||
setidt(14, &IDTVEC(page), SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
|
||||
setidt(15, &IDTVEC(rsvd), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
|
||||
setidt(16, &IDTVEC(fpu), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
|
||||
setidt(17, &IDTVEC(align), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
|
||||
|
@ -35,7 +35,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: @(#)trap.c 7.4 (Berkeley) 5/13/91
|
||||
* $Id: trap.c,v 1.127 1998/04/28 18:15:04 eivind Exp $
|
||||
* $Id: trap.c,v 1.128 1998/08/23 10:16:26 bde Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -104,8 +104,8 @@ extern void trap __P((struct trapframe frame));
|
||||
extern int trapwrite __P((unsigned addr));
|
||||
extern void syscall __P((struct trapframe frame));
|
||||
|
||||
static int trap_pfault __P((struct trapframe *, int));
|
||||
static void trap_fatal __P((struct trapframe *));
|
||||
static int trap_pfault __P((struct trapframe *, int, vm_offset_t));
|
||||
static void trap_fatal __P((struct trapframe *, vm_offset_t));
|
||||
void dblfault_handler __P((void));
|
||||
|
||||
extern inthand_t IDTVEC(syscall);
|
||||
@ -216,9 +216,46 @@ trap(frame)
|
||||
struct proc *p = curproc;
|
||||
u_quad_t sticks = 0;
|
||||
int i = 0, ucode = 0, type, code;
|
||||
#ifdef DEBUG
|
||||
u_long eva;
|
||||
#endif
|
||||
vm_offset_t eva;
|
||||
|
||||
if (!(frame.tf_eflags & PSL_I)) {
|
||||
/*
|
||||
* Buggy application or kernel code has disabled interrupts
|
||||
* and then trapped. Enabling interrupts now is wrong, but
|
||||
* it is better than running with interrupts disabled until
|
||||
* they are accidentally enabled later.
|
||||
*/
|
||||
type = frame.tf_trapno;
|
||||
if (ISPL(frame.tf_cs) == SEL_UPL || (frame.tf_eflags & PSL_VM))
|
||||
printf(
|
||||
"pid %ld (%s): trap %d with interrupts disabled\n",
|
||||
(long)curproc->p_pid, curproc->p_comm, type);
|
||||
else if (type != T_BPTFLT && type != T_TRCTRAP)
|
||||
/*
|
||||
* XXX not quite right, since this may be for a
|
||||
* multiple fault in user mode.
|
||||
*/
|
||||
printf("kernel trap %d with interrupts disabled\n",
|
||||
type);
|
||||
enable_intr();
|
||||
}
|
||||
|
||||
eva = 0;
|
||||
if (frame.tf_trapno == T_PAGEFLT) {
|
||||
/*
|
||||
* For some Cyrix CPUs, %cr2 is clobbered by interrupts.
|
||||
* This problem is worked around by using an interrupt
|
||||
* gate for the pagefault handler. We are finally ready
|
||||
* to read %cr2 and then must reenable interrupts.
|
||||
*
|
||||
* XXX this should be in the switch statement, but the
|
||||
* NO_FOOF_HACK and VM86 goto and ifdefs obfuscate the
|
||||
* flow of control too much for this to be obviously
|
||||
* correct.
|
||||
*/
|
||||
eva = rcr2();
|
||||
enable_intr();
|
||||
}
|
||||
|
||||
#if defined(I586_CPU) && !defined(NO_F00F_HACK)
|
||||
restart:
|
||||
@ -245,7 +282,7 @@ restart:
|
||||
*/
|
||||
case T_PROTFLT:
|
||||
case T_SEGNPFLT:
|
||||
trap_fatal(&frame);
|
||||
trap_fatal(&frame, eva);
|
||||
return;
|
||||
case T_TRCTRAP:
|
||||
type = T_BPTFLT; /* kernel breakpoint */
|
||||
@ -314,7 +351,7 @@ restart:
|
||||
break;
|
||||
|
||||
case T_PAGEFLT: /* page fault */
|
||||
i = trap_pfault(&frame, TRUE);
|
||||
i = trap_pfault(&frame, TRUE, eva);
|
||||
if (i == -1)
|
||||
return;
|
||||
#if defined(I586_CPU) && !defined(NO_F00F_HACK)
|
||||
@ -393,7 +430,7 @@ kernel_trap:
|
||||
|
||||
switch (type) {
|
||||
case T_PAGEFLT: /* page fault */
|
||||
(void) trap_pfault(&frame, FALSE);
|
||||
(void) trap_pfault(&frame, FALSE, eva);
|
||||
return;
|
||||
|
||||
case T_DNA:
|
||||
@ -541,7 +578,7 @@ kernel_trap:
|
||||
#endif /* NISA > 0 */
|
||||
}
|
||||
|
||||
trap_fatal(&frame);
|
||||
trap_fatal(&frame, eva);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -552,7 +589,6 @@ kernel_trap:
|
||||
trapsignal(p, i, ucode);
|
||||
|
||||
#ifdef DEBUG
|
||||
eva = rcr2();
|
||||
if (type <= MAX_TRAP_MSG) {
|
||||
uprintf("fatal process exception: %s",
|
||||
trap_msg[type]);
|
||||
@ -575,16 +611,16 @@ out:
|
||||
* debugging code.
|
||||
*/
|
||||
static int
|
||||
trap_pfault(frame, usermode)
|
||||
trap_pfault(frame, usermode, eva)
|
||||
struct trapframe *frame;
|
||||
int usermode;
|
||||
vm_offset_t eva;
|
||||
{
|
||||
vm_offset_t va;
|
||||
struct vmspace *vm = NULL;
|
||||
vm_map_t map = 0;
|
||||
int rv = 0;
|
||||
vm_prot_t ftype;
|
||||
int eva;
|
||||
struct proc *p = curproc;
|
||||
|
||||
if (frame->tf_err & PGEX_W)
|
||||
@ -592,9 +628,7 @@ trap_pfault(frame, usermode)
|
||||
else
|
||||
ftype = VM_PROT_READ;
|
||||
|
||||
eva = rcr2();
|
||||
va = trunc_page((vm_offset_t)eva);
|
||||
|
||||
va = trunc_page(eva);
|
||||
if (va < VM_MIN_KERNEL_ADDRESS) {
|
||||
vm_offset_t v;
|
||||
vm_page_t mpte;
|
||||
@ -603,7 +637,7 @@ trap_pfault(frame, usermode)
|
||||
(!usermode && va < VM_MAXUSER_ADDRESS &&
|
||||
(intr_nesting_level != 0 || curpcb == NULL ||
|
||||
curpcb->pcb_onfault == NULL))) {
|
||||
trap_fatal(frame);
|
||||
trap_fatal(frame, eva);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
@ -664,7 +698,7 @@ nogo:
|
||||
frame->tf_eip = (int)curpcb->pcb_onfault;
|
||||
return (0);
|
||||
}
|
||||
trap_fatal(frame);
|
||||
trap_fatal(frame, eva);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
@ -676,21 +710,19 @@ nogo:
|
||||
#endif
|
||||
|
||||
int
|
||||
trap_pfault(frame, usermode)
|
||||
trap_pfault(frame, usermode, eva)
|
||||
struct trapframe *frame;
|
||||
int usermode;
|
||||
vm_offset_t eva;
|
||||
{
|
||||
vm_offset_t va;
|
||||
struct vmspace *vm = NULL;
|
||||
vm_map_t map = 0;
|
||||
int rv = 0;
|
||||
vm_prot_t ftype;
|
||||
int eva;
|
||||
struct proc *p = curproc;
|
||||
|
||||
eva = rcr2();
|
||||
va = trunc_page((vm_offset_t)eva);
|
||||
|
||||
va = trunc_page(eva);
|
||||
if (va >= KERNBASE) {
|
||||
/*
|
||||
* Don't allow user-mode faults in kernel address space.
|
||||
@ -769,7 +801,7 @@ nogo:
|
||||
frame->tf_eip = (int)curpcb->pcb_onfault;
|
||||
return (0);
|
||||
}
|
||||
trap_fatal(frame);
|
||||
trap_fatal(frame, eva);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
@ -780,15 +812,15 @@ nogo:
|
||||
}
|
||||
|
||||
static void
|
||||
trap_fatal(frame)
|
||||
trap_fatal(frame, eva)
|
||||
struct trapframe *frame;
|
||||
vm_offset_t eva;
|
||||
{
|
||||
int code, type, eva, ss, esp;
|
||||
int code, type, ss, esp;
|
||||
struct soft_segment_descriptor softseg;
|
||||
|
||||
code = frame->tf_err;
|
||||
type = frame->tf_trapno;
|
||||
eva = rcr2();
|
||||
sdtossd(&gdt[IDXSEL(frame->tf_cs & 0xffff)].sd, &softseg);
|
||||
|
||||
if (type <= MAX_TRAP_MSG)
|
||||
|
@ -35,7 +35,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: @(#)trap.c 7.4 (Berkeley) 5/13/91
|
||||
* $Id: trap.c,v 1.127 1998/04/28 18:15:04 eivind Exp $
|
||||
* $Id: trap.c,v 1.128 1998/08/23 10:16:26 bde Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -104,8 +104,8 @@ extern void trap __P((struct trapframe frame));
|
||||
extern int trapwrite __P((unsigned addr));
|
||||
extern void syscall __P((struct trapframe frame));
|
||||
|
||||
static int trap_pfault __P((struct trapframe *, int));
|
||||
static void trap_fatal __P((struct trapframe *));
|
||||
static int trap_pfault __P((struct trapframe *, int, vm_offset_t));
|
||||
static void trap_fatal __P((struct trapframe *, vm_offset_t));
|
||||
void dblfault_handler __P((void));
|
||||
|
||||
extern inthand_t IDTVEC(syscall);
|
||||
@ -216,9 +216,46 @@ trap(frame)
|
||||
struct proc *p = curproc;
|
||||
u_quad_t sticks = 0;
|
||||
int i = 0, ucode = 0, type, code;
|
||||
#ifdef DEBUG
|
||||
u_long eva;
|
||||
#endif
|
||||
vm_offset_t eva;
|
||||
|
||||
if (!(frame.tf_eflags & PSL_I)) {
|
||||
/*
|
||||
* Buggy application or kernel code has disabled interrupts
|
||||
* and then trapped. Enabling interrupts now is wrong, but
|
||||
* it is better than running with interrupts disabled until
|
||||
* they are accidentally enabled later.
|
||||
*/
|
||||
type = frame.tf_trapno;
|
||||
if (ISPL(frame.tf_cs) == SEL_UPL || (frame.tf_eflags & PSL_VM))
|
||||
printf(
|
||||
"pid %ld (%s): trap %d with interrupts disabled\n",
|
||||
(long)curproc->p_pid, curproc->p_comm, type);
|
||||
else if (type != T_BPTFLT && type != T_TRCTRAP)
|
||||
/*
|
||||
* XXX not quite right, since this may be for a
|
||||
* multiple fault in user mode.
|
||||
*/
|
||||
printf("kernel trap %d with interrupts disabled\n",
|
||||
type);
|
||||
enable_intr();
|
||||
}
|
||||
|
||||
eva = 0;
|
||||
if (frame.tf_trapno == T_PAGEFLT) {
|
||||
/*
|
||||
* For some Cyrix CPUs, %cr2 is clobbered by interrupts.
|
||||
* This problem is worked around by using an interrupt
|
||||
* gate for the pagefault handler. We are finally ready
|
||||
* to read %cr2 and then must reenable interrupts.
|
||||
*
|
||||
* XXX this should be in the switch statement, but the
|
||||
* NO_FOOF_HACK and VM86 goto and ifdefs obfuscate the
|
||||
* flow of control too much for this to be obviously
|
||||
* correct.
|
||||
*/
|
||||
eva = rcr2();
|
||||
enable_intr();
|
||||
}
|
||||
|
||||
#if defined(I586_CPU) && !defined(NO_F00F_HACK)
|
||||
restart:
|
||||
@ -245,7 +282,7 @@ restart:
|
||||
*/
|
||||
case T_PROTFLT:
|
||||
case T_SEGNPFLT:
|
||||
trap_fatal(&frame);
|
||||
trap_fatal(&frame, eva);
|
||||
return;
|
||||
case T_TRCTRAP:
|
||||
type = T_BPTFLT; /* kernel breakpoint */
|
||||
@ -314,7 +351,7 @@ restart:
|
||||
break;
|
||||
|
||||
case T_PAGEFLT: /* page fault */
|
||||
i = trap_pfault(&frame, TRUE);
|
||||
i = trap_pfault(&frame, TRUE, eva);
|
||||
if (i == -1)
|
||||
return;
|
||||
#if defined(I586_CPU) && !defined(NO_F00F_HACK)
|
||||
@ -393,7 +430,7 @@ kernel_trap:
|
||||
|
||||
switch (type) {
|
||||
case T_PAGEFLT: /* page fault */
|
||||
(void) trap_pfault(&frame, FALSE);
|
||||
(void) trap_pfault(&frame, FALSE, eva);
|
||||
return;
|
||||
|
||||
case T_DNA:
|
||||
@ -541,7 +578,7 @@ kernel_trap:
|
||||
#endif /* NISA > 0 */
|
||||
}
|
||||
|
||||
trap_fatal(&frame);
|
||||
trap_fatal(&frame, eva);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -552,7 +589,6 @@ kernel_trap:
|
||||
trapsignal(p, i, ucode);
|
||||
|
||||
#ifdef DEBUG
|
||||
eva = rcr2();
|
||||
if (type <= MAX_TRAP_MSG) {
|
||||
uprintf("fatal process exception: %s",
|
||||
trap_msg[type]);
|
||||
@ -575,16 +611,16 @@ out:
|
||||
* debugging code.
|
||||
*/
|
||||
static int
|
||||
trap_pfault(frame, usermode)
|
||||
trap_pfault(frame, usermode, eva)
|
||||
struct trapframe *frame;
|
||||
int usermode;
|
||||
vm_offset_t eva;
|
||||
{
|
||||
vm_offset_t va;
|
||||
struct vmspace *vm = NULL;
|
||||
vm_map_t map = 0;
|
||||
int rv = 0;
|
||||
vm_prot_t ftype;
|
||||
int eva;
|
||||
struct proc *p = curproc;
|
||||
|
||||
if (frame->tf_err & PGEX_W)
|
||||
@ -592,9 +628,7 @@ trap_pfault(frame, usermode)
|
||||
else
|
||||
ftype = VM_PROT_READ;
|
||||
|
||||
eva = rcr2();
|
||||
va = trunc_page((vm_offset_t)eva);
|
||||
|
||||
va = trunc_page(eva);
|
||||
if (va < VM_MIN_KERNEL_ADDRESS) {
|
||||
vm_offset_t v;
|
||||
vm_page_t mpte;
|
||||
@ -603,7 +637,7 @@ trap_pfault(frame, usermode)
|
||||
(!usermode && va < VM_MAXUSER_ADDRESS &&
|
||||
(intr_nesting_level != 0 || curpcb == NULL ||
|
||||
curpcb->pcb_onfault == NULL))) {
|
||||
trap_fatal(frame);
|
||||
trap_fatal(frame, eva);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
@ -664,7 +698,7 @@ nogo:
|
||||
frame->tf_eip = (int)curpcb->pcb_onfault;
|
||||
return (0);
|
||||
}
|
||||
trap_fatal(frame);
|
||||
trap_fatal(frame, eva);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
@ -676,21 +710,19 @@ nogo:
|
||||
#endif
|
||||
|
||||
int
|
||||
trap_pfault(frame, usermode)
|
||||
trap_pfault(frame, usermode, eva)
|
||||
struct trapframe *frame;
|
||||
int usermode;
|
||||
vm_offset_t eva;
|
||||
{
|
||||
vm_offset_t va;
|
||||
struct vmspace *vm = NULL;
|
||||
vm_map_t map = 0;
|
||||
int rv = 0;
|
||||
vm_prot_t ftype;
|
||||
int eva;
|
||||
struct proc *p = curproc;
|
||||
|
||||
eva = rcr2();
|
||||
va = trunc_page((vm_offset_t)eva);
|
||||
|
||||
va = trunc_page(eva);
|
||||
if (va >= KERNBASE) {
|
||||
/*
|
||||
* Don't allow user-mode faults in kernel address space.
|
||||
@ -769,7 +801,7 @@ nogo:
|
||||
frame->tf_eip = (int)curpcb->pcb_onfault;
|
||||
return (0);
|
||||
}
|
||||
trap_fatal(frame);
|
||||
trap_fatal(frame, eva);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
@ -780,15 +812,15 @@ nogo:
|
||||
}
|
||||
|
||||
static void
|
||||
trap_fatal(frame)
|
||||
trap_fatal(frame, eva)
|
||||
struct trapframe *frame;
|
||||
vm_offset_t eva;
|
||||
{
|
||||
int code, type, eva, ss, esp;
|
||||
int code, type, ss, esp;
|
||||
struct soft_segment_descriptor softseg;
|
||||
|
||||
code = frame->tf_err;
|
||||
type = frame->tf_trapno;
|
||||
eva = rcr2();
|
||||
sdtossd(&gdt[IDXSEL(frame->tf_cs & 0xffff)].sd, &softseg);
|
||||
|
||||
if (type <= MAX_TRAP_MSG)
|
||||
|
@ -3,7 +3,7 @@
|
||||
#
|
||||
# modified for PC-9801
|
||||
#
|
||||
# $Id: files.pc98,v 1.71 1998/09/20 10:50:18 kato Exp $
|
||||
# $Id: files.pc98,v 1.72 1998/10/11 15:02:49 kato Exp $
|
||||
#
|
||||
# The long compile-with and dependency lines are required because of
|
||||
# limitations in config: backslash-newline doesn't work in strings, and
|
||||
@ -71,7 +71,7 @@ i386/i386/simplelock.s optional smp
|
||||
i386/i386/support.s standard
|
||||
i386/i386/swtch.s standard
|
||||
i386/i386/sys_machdep.c standard
|
||||
pc98/i386/trap.c standard
|
||||
i386/i386/trap.c standard
|
||||
pc98/i386/userconfig.c optional userconfig
|
||||
i386/i386/vm_machdep.c standard
|
||||
i386/i386/vm86.c optional vm86
|
||||
|
@ -35,7 +35,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: @(#)machdep.c 7.4 (Berkeley) 6/3/91
|
||||
* $Id: machdep.c,v 1.99 1998/10/11 15:04:38 kato Exp $
|
||||
* $Id: machdep.c,v 1.100 1998/11/06 08:07:32 kato Exp $
|
||||
*/
|
||||
|
||||
#include "apm.h"
|
||||
@ -1244,11 +1244,7 @@ init386(first)
|
||||
setidt(11, &IDTVEC(missing), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
|
||||
setidt(12, &IDTVEC(stk), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
|
||||
setidt(13, &IDTVEC(prot), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
|
||||
#ifdef CPU_BUGGY_CYRIX
|
||||
setidt(14, &IDTVEC(page), SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
|
||||
#else
|
||||
setidt(14, &IDTVEC(page), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
|
||||
#endif
|
||||
setidt(15, &IDTVEC(rsvd), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
|
||||
setidt(16, &IDTVEC(fpu), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
|
||||
setidt(17, &IDTVEC(align), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
|
||||
|
1159
sys/pc98/i386/trap.c
1159
sys/pc98/i386/trap.c
File diff suppressed because it is too large
Load Diff
@ -35,7 +35,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: @(#)machdep.c 7.4 (Berkeley) 6/3/91
|
||||
* $Id: machdep.c,v 1.99 1998/10/11 15:04:38 kato Exp $
|
||||
* $Id: machdep.c,v 1.100 1998/11/06 08:07:32 kato Exp $
|
||||
*/
|
||||
|
||||
#include "apm.h"
|
||||
@ -1244,11 +1244,7 @@ init386(first)
|
||||
setidt(11, &IDTVEC(missing), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
|
||||
setidt(12, &IDTVEC(stk), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
|
||||
setidt(13, &IDTVEC(prot), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
|
||||
#ifdef CPU_BUGGY_CYRIX
|
||||
setidt(14, &IDTVEC(page), SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
|
||||
#else
|
||||
setidt(14, &IDTVEC(page), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
|
||||
#endif
|
||||
setidt(15, &IDTVEC(rsvd), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
|
||||
setidt(16, &IDTVEC(fpu), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
|
||||
setidt(17, &IDTVEC(align), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
|
||||
|
Loading…
x
Reference in New Issue
Block a user