summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authordg <dg@FreeBSD.org>1995-12-19 14:30:50 +0000
committerdg <dg@FreeBSD.org>1995-12-19 14:30:50 +0000
commit95d4407d256f0ffa1815a33f1ecbb69af4758281 (patch)
tree0f3a6a4cd34125a3b374024be9001afc03573a4c /sys
parent655b27e73b172bddc17c1c8cef53b4cdb00537d9 (diff)
downloadFreeBSD-src-95d4407d256f0ffa1815a33f1ecbb69af4758281.zip
FreeBSD-src-95d4407d256f0ffa1815a33f1ecbb69af4758281.tar.gz
Implemented a (sorely needed for years) double fault handler to catch stack
overflows. It sure would be nice if there was an unmapped page between the PCB and the stack (and that the size of the stack was configurable!). With the way things are now, the PCB will get clobbered before the double fault handler gets control, making somewhat of a mess of things. Despite this, it is still fairly easy to poke around in the overflowed stack to figure out the cause.
Diffstat (limited to 'sys')
-rw-r--r--sys/amd64/amd64/exception.S4
-rw-r--r--sys/amd64/amd64/exception.s4
-rw-r--r--sys/amd64/amd64/fpu.c6
-rw-r--r--sys/amd64/amd64/machdep.c73
-rw-r--r--sys/amd64/amd64/trap.c34
-rw-r--r--sys/amd64/include/cpufunc.h4
-rw-r--r--sys/amd64/isa/isa.c7
-rw-r--r--sys/amd64/isa/npx.c6
-rw-r--r--sys/i386/i386/exception.s4
-rw-r--r--sys/i386/i386/machdep.c73
-rw-r--r--sys/i386/i386/trap.c34
-rw-r--r--sys/i386/include/cpufunc.h4
-rw-r--r--sys/i386/isa/isa.c7
-rw-r--r--sys/i386/isa/npx.c6
-rw-r--r--sys/kern/subr_trap.c34
15 files changed, 205 insertions, 95 deletions
diff --git a/sys/amd64/amd64/exception.S b/sys/amd64/amd64/exception.S
index bba2272..e7b44be 100644
--- a/sys/amd64/amd64/exception.S
+++ b/sys/amd64/amd64/exception.S
@@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: exception.s,v 1.11 1995/09/07 21:36:17 davidg Exp $
+ * $Id: exception.s,v 1.12 1995/12/14 14:35:33 peter Exp $
*/
#include "npx.h" /* NNPX */
@@ -105,8 +105,6 @@ IDTVEC(ill)
pushl $0; TRAP(T_PRIVINFLT)
IDTVEC(dna)
pushl $0; TRAP(T_DNA)
-IDTVEC(dble)
- TRAP(T_DOUBLEFLT)
IDTVEC(fpusegm)
pushl $0; TRAP(T_FPOPFLT)
IDTVEC(tss)
diff --git a/sys/amd64/amd64/exception.s b/sys/amd64/amd64/exception.s
index bba2272..e7b44be 100644
--- a/sys/amd64/amd64/exception.s
+++ b/sys/amd64/amd64/exception.s
@@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: exception.s,v 1.11 1995/09/07 21:36:17 davidg Exp $
+ * $Id: exception.s,v 1.12 1995/12/14 14:35:33 peter Exp $
*/
#include "npx.h" /* NNPX */
@@ -105,8 +105,6 @@ IDTVEC(ill)
pushl $0; TRAP(T_PRIVINFLT)
IDTVEC(dna)
pushl $0; TRAP(T_DNA)
-IDTVEC(dble)
- TRAP(T_DOUBLEFLT)
IDTVEC(fpusegm)
pushl $0; TRAP(T_FPOPFLT)
IDTVEC(tss)
diff --git a/sys/amd64/amd64/fpu.c b/sys/amd64/amd64/fpu.c
index 54cb5bf..8f274db 100644
--- a/sys/amd64/amd64/fpu.c
+++ b/sys/amd64/amd64/fpu.c
@@ -32,7 +32,7 @@
* SUCH DAMAGE.
*
* from: @(#)npx.c 7.2 (Berkeley) 5/12/91
- * $Id: npx.c,v 1.25 1995/10/28 13:07:21 phk Exp $
+ * $Id: npx.c,v 1.26 1995/12/10 13:39:02 phk Exp $
*/
#include "npx.h"
@@ -212,8 +212,8 @@ npxprobe(dvp)
save_idt_npxtrap = idt[16];
outb(IO_ICU1 + 1, ~(IRQ_SLAVE | dvp->id_irq));
outb(IO_ICU2 + 1, ~(dvp->id_irq >> 8));
- setidt(16, probetrap, SDT_SYS386TGT, SEL_KPL);
- setidt(npx_intrno, probeintr, SDT_SYS386IGT, SEL_KPL);
+ setidt(16, probetrap, SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
+ setidt(npx_intrno, probeintr, SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
npx_idt_probeintr = idt[npx_intrno];
enable_intr();
result = npxprobe1(dvp);
diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c
index f95285d..947200e 100644
--- a/sys/amd64/amd64/machdep.c
+++ b/sys/amd64/amd64/machdep.c
@@ -35,7 +35,7 @@
* SUCH DAMAGE.
*
* from: @(#)machdep.c 7.4 (Berkeley) 6/3/91
- * $Id: machdep.c,v 1.159 1995/12/14 14:35:34 peter Exp $
+ * $Id: machdep.c,v 1.160 1995/12/16 18:52:08 peter Exp $
*/
#include "npx.h"
@@ -115,6 +115,7 @@ extern void init386 __P((int first));
extern int ptrace_set_pc __P((struct proc *p, unsigned int addr));
extern int ptrace_single_step __P((struct proc *p));
extern int ptrace_write_u __P((struct proc *p, vm_offset_t off, int data));
+extern void dblfault_handler __P((void));
static void cpu_startup __P((void *));
SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL)
@@ -1066,7 +1067,8 @@ union descriptor gdt[NGDT]; /* global descriptor table */
struct gate_descriptor idt[NIDT]; /* interrupt descriptor table */
union descriptor ldt[NLDT]; /* local descriptor table */
-static struct i386tss tss, panic_tss;
+static struct i386tss dblfault_tss;
+static char dblfault_stack[512];
extern struct user *proc0paddr;
@@ -1118,8 +1120,8 @@ struct soft_segment_descriptor gdt_segs[] = {
0, /* default 32 vs 16 bit size */
0 /* limit granularity (byte/page units)*/ },
/* GPANIC_SEL 5 Panic Tss Descriptor */
-{ (int) &panic_tss, /* segment base address */
- sizeof(tss)-1, /* length - all address space */
+{ (int) &dblfault_tss, /* segment base address */
+ sizeof(struct i386tss)-1,/* length - all address space */
SDT_SYS386TSS, /* segment type */
0, /* segment descriptor priority level */
1, /* segment descriptor present */
@@ -1128,7 +1130,7 @@ struct soft_segment_descriptor gdt_segs[] = {
0 /* limit granularity (byte/page units)*/ },
/* GPROC0_SEL 6 Proc 0 Tss Descriptor */
{ (int) kstack, /* segment base address */
- sizeof(tss)-1, /* length - all address space */
+ sizeof(struct i386tss)-1,/* length - all address space */
SDT_SYS386TSS, /* segment type */
0, /* segment descriptor priority level */
1, /* segment descriptor present */
@@ -1222,16 +1224,17 @@ static struct soft_segment_descriptor ldt_segs[] = {
};
void
-setidt(idx, func, typ, dpl)
+setidt(idx, func, typ, dpl, selec)
int idx;
inthand_t *func;
int typ;
int dpl;
+ int selec;
{
struct gate_descriptor *ip = idt + idx;
ip->gd_looffset = (int)func;
- ip->gd_selector = 8;
+ ip->gd_selector = selec;
ip->gd_stkcpy = 0;
ip->gd_xx = 0;
ip->gd_type = typ;
@@ -1244,7 +1247,7 @@ setidt(idx, func, typ, dpl)
extern inthand_t
IDTVEC(div), IDTVEC(dbg), IDTVEC(nmi), IDTVEC(bpt), IDTVEC(ofl),
- IDTVEC(bnd), IDTVEC(ill), IDTVEC(dna), IDTVEC(dble), IDTVEC(fpusegm),
+ IDTVEC(bnd), IDTVEC(ill), IDTVEC(dna), IDTVEC(fpusegm),
IDTVEC(tss), IDTVEC(missing), IDTVEC(stk), IDTVEC(prot),
IDTVEC(page), IDTVEC(rsvd), IDTVEC(fpu), IDTVEC(align),
IDTVEC(syscall);
@@ -1329,27 +1332,27 @@ init386(first)
/* exceptions */
for (x = 0; x < NIDT; x++)
- setidt(x, &IDTVEC(rsvd), SDT_SYS386TGT, SEL_KPL);
- setidt(0, &IDTVEC(div), SDT_SYS386TGT, SEL_KPL);
- setidt(1, &IDTVEC(dbg), SDT_SYS386TGT, SEL_KPL);
- setidt(2, &IDTVEC(nmi), SDT_SYS386TGT, SEL_KPL);
- setidt(3, &IDTVEC(bpt), SDT_SYS386TGT, SEL_UPL);
- setidt(4, &IDTVEC(ofl), SDT_SYS386TGT, SEL_UPL);
- setidt(5, &IDTVEC(bnd), SDT_SYS386TGT, SEL_KPL);
- setidt(6, &IDTVEC(ill), SDT_SYS386TGT, SEL_KPL);
- setidt(7, &IDTVEC(dna), SDT_SYS386TGT, SEL_KPL);
- setidt(8, &IDTVEC(dble), SDT_SYS386TGT, SEL_KPL);
- setidt(9, &IDTVEC(fpusegm), SDT_SYS386TGT, SEL_KPL);
- setidt(10, &IDTVEC(tss), SDT_SYS386TGT, SEL_KPL);
- setidt(11, &IDTVEC(missing), SDT_SYS386TGT, SEL_KPL);
- setidt(12, &IDTVEC(stk), SDT_SYS386TGT, SEL_KPL);
- setidt(13, &IDTVEC(prot), SDT_SYS386TGT, SEL_KPL);
- setidt(14, &IDTVEC(page), SDT_SYS386TGT, SEL_KPL);
- setidt(15, &IDTVEC(rsvd), SDT_SYS386TGT, SEL_KPL);
- setidt(16, &IDTVEC(fpu), SDT_SYS386TGT, SEL_KPL);
- setidt(17, &IDTVEC(align), SDT_SYS386TGT, SEL_KPL);
+ setidt(x, &IDTVEC(rsvd), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
+ setidt(0, &IDTVEC(div), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
+ setidt(1, &IDTVEC(dbg), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
+ setidt(2, &IDTVEC(nmi), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
+ setidt(3, &IDTVEC(bpt), SDT_SYS386TGT, SEL_UPL, GSEL(GCODE_SEL, SEL_KPL));
+ setidt(4, &IDTVEC(ofl), SDT_SYS386TGT, SEL_UPL, GSEL(GCODE_SEL, SEL_KPL));
+ setidt(5, &IDTVEC(bnd), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
+ setidt(6, &IDTVEC(ill), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
+ setidt(7, &IDTVEC(dna), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
+ setidt(8, 0, SDT_SYSTASKGT, SEL_KPL, GSEL(GPANIC_SEL, SEL_KPL));
+ setidt(9, &IDTVEC(fpusegm), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
+ setidt(10, &IDTVEC(tss), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
+ 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(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));
#if defined(COMPAT_LINUX) || defined(LINUX)
- setidt(0x80, &IDTVEC(linux_syscall), SDT_SYS386TGT, SEL_UPL);
+ setidt(0x80, &IDTVEC(linux_syscall), SDT_SYS386TGT, SEL_UPL, GSEL(GCODE_SEL, SEL_KPL));
#endif
#include "isa.h"
@@ -1569,8 +1572,20 @@ init386(first)
proc0.p_addr->u_pcb.pcb_tss.tss_ss0 = GSEL(GDATA_SEL, SEL_KPL) ;
gsel_tss = GSEL(GPROC0_SEL, SEL_KPL);
+ dblfault_tss.tss_esp = dblfault_tss.tss_esp0 = dblfault_tss.tss_esp1 =
+ dblfault_tss.tss_esp2 = (int) &dblfault_stack[sizeof(dblfault_stack)];
+ dblfault_tss.tss_ss = dblfault_tss.tss_ss0 = dblfault_tss.tss_ss1 =
+ dblfault_tss.tss_ss2 = GSEL(GDATA_SEL, SEL_KPL);
+ dblfault_tss.tss_cr3 = IdlePTD;
+ dblfault_tss.tss_eip = (int) dblfault_handler;
+ dblfault_tss.tss_eflags = PSL_KERNEL;
+ dblfault_tss.tss_ds = dblfault_tss.tss_es = dblfault_tss.tss_fs = dblfault_tss.tss_gs =
+ GSEL(GDATA_SEL, SEL_KPL);
+ dblfault_tss.tss_cs = GSEL(GCODE_SEL, SEL_KPL);
+ dblfault_tss.tss_ldt = GSEL(GLDT_SEL, SEL_KPL);
+
((struct i386tss *)gdt_segs[GPROC0_SEL].ssd_base)->tss_ioopt =
- (sizeof(tss))<<16;
+ (sizeof(struct i386tss))<<16;
ltr(gsel_tss);
diff --git a/sys/amd64/amd64/trap.c b/sys/amd64/amd64/trap.c
index 21f1f8e..acee977 100644
--- a/sys/amd64/amd64/trap.c
+++ b/sys/amd64/amd64/trap.c
@@ -35,7 +35,7 @@
* SUCH DAMAGE.
*
* from: @(#)trap.c 7.4 (Berkeley) 5/13/91
- * $Id: trap.c,v 1.65 1995/12/14 08:21:29 phk Exp $
+ * $Id: trap.c,v 1.66 1995/12/14 14:35:36 peter Exp $
*/
/*
@@ -89,8 +89,9 @@ extern int trapwrite __P((unsigned addr));
extern void syscall __P((struct trapframe frame));
extern void linux_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));
+static void trap_fatal __P((struct trapframe *));
+void dblfault_handler __P((void));
extern inthand_t IDTVEC(syscall);
@@ -756,6 +757,33 @@ trap_fatal(frame)
}
/*
+ * Double fault handler. Called when a fault occurs while writing
+ * a frame for a trap/exception onto the stack. This usually occurs
+ * when the stack overflows (such is the case with infinite recursion,
+ * for example).
+ *
+ * XXX Note that the current PTD gets replaced by IdlePTD when the
+ * task switch occurs. This means that the stack that was active at
+ * the time of the double fault is not available at <kstack> unless
+ * the machine was idlewhen the double fault occurred. This downside
+ * of this is that "trace <ebp>" in ddb won't work.
+ */
+void
+dblfault_handler()
+{
+ struct pcb *pcb = curpcb;
+
+ if (pcb != NULL) {
+ printf("\nFatal double fault:\n");
+ printf("eip = 0x%x\n", pcb->pcb_tss.tss_eip);
+ printf("esp = 0x%x\n", pcb->pcb_tss.tss_esp);
+ printf("ebp = 0x%x\n", pcb->pcb_tss.tss_ebp);
+ }
+
+ panic("double fault");
+}
+
+/*
* Compensate for 386 brain damage (missing URKR).
* This is a little simpler than the pagefault handler in trap() because
* it the page tables have already been faulted in and high addresses
diff --git a/sys/amd64/include/cpufunc.h b/sys/amd64/include/cpufunc.h
index 11774bf..e82b4f0 100644
--- a/sys/amd64/include/cpufunc.h
+++ b/sys/amd64/include/cpufunc.h
@@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: cpufunc.h,v 1.41 1995/10/05 10:32:47 phk Exp $
+ * $Id: cpufunc.h,v 1.42 1995/12/03 13:45:27 bde Exp $
*/
/*
@@ -412,6 +412,6 @@ u_long kvtop __P((void *addr));
typedef void alias_for_inthand_t __P((u_int cs, u_int ef, u_int esp,
u_int ss));
void setidt __P((int idx, alias_for_inthand_t *func, int typ,
- int dpl));
+ int dpl, int selec));
#endif /* !_MACHINE_CPUFUNC_H_ */
diff --git a/sys/amd64/isa/isa.c b/sys/amd64/isa/isa.c
index e04a500..54a11e1 100644
--- a/sys/amd64/isa/isa.c
+++ b/sys/amd64/isa/isa.c
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* from: @(#)isa.c 7.2 (Berkeley) 5/13/91
- * $Id: isa.c,v 1.57 1995/11/20 13:24:18 bde Exp $
+ * $Id: isa.c,v 1.58 1995/12/07 12:46:01 davidg Exp $
*/
/*
@@ -936,7 +936,7 @@ register_intr(intr, device_id, flags, handler, maskptr, unit)
intr_unit[intr] = unit;
setidt(ICU_OFFSET + intr,
flags & RI_FAST ? fastintr[intr] : slowintr[intr],
- SDT_SYS386IGT, SEL_KPL);
+ SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
write_eflags(ef);
for (cp = intrnames, id = 0; id <= device_id; id++)
while (*cp++ != '\0')
@@ -983,7 +983,8 @@ unregister_intr(intr, handler)
intr_mptr[intr] = NULL;
intr_mask[intr] = HWI_MASK | SWI_MASK;
intr_unit[intr] = intr;
- setidt(ICU_OFFSET + intr, slowintr[intr], SDT_SYS386IGT, SEL_KPL);
+ setidt(ICU_OFFSET + intr, slowintr[intr], SDT_SYS386IGT, SEL_KPL,
+ GSEL(GCODE_SEL, SEL_KPL));
write_eflags(ef);
return (0);
}
diff --git a/sys/amd64/isa/npx.c b/sys/amd64/isa/npx.c
index 54cb5bf..8f274db 100644
--- a/sys/amd64/isa/npx.c
+++ b/sys/amd64/isa/npx.c
@@ -32,7 +32,7 @@
* SUCH DAMAGE.
*
* from: @(#)npx.c 7.2 (Berkeley) 5/12/91
- * $Id: npx.c,v 1.25 1995/10/28 13:07:21 phk Exp $
+ * $Id: npx.c,v 1.26 1995/12/10 13:39:02 phk Exp $
*/
#include "npx.h"
@@ -212,8 +212,8 @@ npxprobe(dvp)
save_idt_npxtrap = idt[16];
outb(IO_ICU1 + 1, ~(IRQ_SLAVE | dvp->id_irq));
outb(IO_ICU2 + 1, ~(dvp->id_irq >> 8));
- setidt(16, probetrap, SDT_SYS386TGT, SEL_KPL);
- setidt(npx_intrno, probeintr, SDT_SYS386IGT, SEL_KPL);
+ setidt(16, probetrap, SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
+ setidt(npx_intrno, probeintr, SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
npx_idt_probeintr = idt[npx_intrno];
enable_intr();
result = npxprobe1(dvp);
diff --git a/sys/i386/i386/exception.s b/sys/i386/i386/exception.s
index bba2272..e7b44be 100644
--- a/sys/i386/i386/exception.s
+++ b/sys/i386/i386/exception.s
@@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: exception.s,v 1.11 1995/09/07 21:36:17 davidg Exp $
+ * $Id: exception.s,v 1.12 1995/12/14 14:35:33 peter Exp $
*/
#include "npx.h" /* NNPX */
@@ -105,8 +105,6 @@ IDTVEC(ill)
pushl $0; TRAP(T_PRIVINFLT)
IDTVEC(dna)
pushl $0; TRAP(T_DNA)
-IDTVEC(dble)
- TRAP(T_DOUBLEFLT)
IDTVEC(fpusegm)
pushl $0; TRAP(T_FPOPFLT)
IDTVEC(tss)
diff --git a/sys/i386/i386/machdep.c b/sys/i386/i386/machdep.c
index f95285d..947200e 100644
--- a/sys/i386/i386/machdep.c
+++ b/sys/i386/i386/machdep.c
@@ -35,7 +35,7 @@
* SUCH DAMAGE.
*
* from: @(#)machdep.c 7.4 (Berkeley) 6/3/91
- * $Id: machdep.c,v 1.159 1995/12/14 14:35:34 peter Exp $
+ * $Id: machdep.c,v 1.160 1995/12/16 18:52:08 peter Exp $
*/
#include "npx.h"
@@ -115,6 +115,7 @@ extern void init386 __P((int first));
extern int ptrace_set_pc __P((struct proc *p, unsigned int addr));
extern int ptrace_single_step __P((struct proc *p));
extern int ptrace_write_u __P((struct proc *p, vm_offset_t off, int data));
+extern void dblfault_handler __P((void));
static void cpu_startup __P((void *));
SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL)
@@ -1066,7 +1067,8 @@ union descriptor gdt[NGDT]; /* global descriptor table */
struct gate_descriptor idt[NIDT]; /* interrupt descriptor table */
union descriptor ldt[NLDT]; /* local descriptor table */
-static struct i386tss tss, panic_tss;
+static struct i386tss dblfault_tss;
+static char dblfault_stack[512];
extern struct user *proc0paddr;
@@ -1118,8 +1120,8 @@ struct soft_segment_descriptor gdt_segs[] = {
0, /* default 32 vs 16 bit size */
0 /* limit granularity (byte/page units)*/ },
/* GPANIC_SEL 5 Panic Tss Descriptor */
-{ (int) &panic_tss, /* segment base address */
- sizeof(tss)-1, /* length - all address space */
+{ (int) &dblfault_tss, /* segment base address */
+ sizeof(struct i386tss)-1,/* length - all address space */
SDT_SYS386TSS, /* segment type */
0, /* segment descriptor priority level */
1, /* segment descriptor present */
@@ -1128,7 +1130,7 @@ struct soft_segment_descriptor gdt_segs[] = {
0 /* limit granularity (byte/page units)*/ },
/* GPROC0_SEL 6 Proc 0 Tss Descriptor */
{ (int) kstack, /* segment base address */
- sizeof(tss)-1, /* length - all address space */
+ sizeof(struct i386tss)-1,/* length - all address space */
SDT_SYS386TSS, /* segment type */
0, /* segment descriptor priority level */
1, /* segment descriptor present */
@@ -1222,16 +1224,17 @@ static struct soft_segment_descriptor ldt_segs[] = {
};
void
-setidt(idx, func, typ, dpl)
+setidt(idx, func, typ, dpl, selec)
int idx;
inthand_t *func;
int typ;
int dpl;
+ int selec;
{
struct gate_descriptor *ip = idt + idx;
ip->gd_looffset = (int)func;
- ip->gd_selector = 8;
+ ip->gd_selector = selec;
ip->gd_stkcpy = 0;
ip->gd_xx = 0;
ip->gd_type = typ;
@@ -1244,7 +1247,7 @@ setidt(idx, func, typ, dpl)
extern inthand_t
IDTVEC(div), IDTVEC(dbg), IDTVEC(nmi), IDTVEC(bpt), IDTVEC(ofl),
- IDTVEC(bnd), IDTVEC(ill), IDTVEC(dna), IDTVEC(dble), IDTVEC(fpusegm),
+ IDTVEC(bnd), IDTVEC(ill), IDTVEC(dna), IDTVEC(fpusegm),
IDTVEC(tss), IDTVEC(missing), IDTVEC(stk), IDTVEC(prot),
IDTVEC(page), IDTVEC(rsvd), IDTVEC(fpu), IDTVEC(align),
IDTVEC(syscall);
@@ -1329,27 +1332,27 @@ init386(first)
/* exceptions */
for (x = 0; x < NIDT; x++)
- setidt(x, &IDTVEC(rsvd), SDT_SYS386TGT, SEL_KPL);
- setidt(0, &IDTVEC(div), SDT_SYS386TGT, SEL_KPL);
- setidt(1, &IDTVEC(dbg), SDT_SYS386TGT, SEL_KPL);
- setidt(2, &IDTVEC(nmi), SDT_SYS386TGT, SEL_KPL);
- setidt(3, &IDTVEC(bpt), SDT_SYS386TGT, SEL_UPL);
- setidt(4, &IDTVEC(ofl), SDT_SYS386TGT, SEL_UPL);
- setidt(5, &IDTVEC(bnd), SDT_SYS386TGT, SEL_KPL);
- setidt(6, &IDTVEC(ill), SDT_SYS386TGT, SEL_KPL);
- setidt(7, &IDTVEC(dna), SDT_SYS386TGT, SEL_KPL);
- setidt(8, &IDTVEC(dble), SDT_SYS386TGT, SEL_KPL);
- setidt(9, &IDTVEC(fpusegm), SDT_SYS386TGT, SEL_KPL);
- setidt(10, &IDTVEC(tss), SDT_SYS386TGT, SEL_KPL);
- setidt(11, &IDTVEC(missing), SDT_SYS386TGT, SEL_KPL);
- setidt(12, &IDTVEC(stk), SDT_SYS386TGT, SEL_KPL);
- setidt(13, &IDTVEC(prot), SDT_SYS386TGT, SEL_KPL);
- setidt(14, &IDTVEC(page), SDT_SYS386TGT, SEL_KPL);
- setidt(15, &IDTVEC(rsvd), SDT_SYS386TGT, SEL_KPL);
- setidt(16, &IDTVEC(fpu), SDT_SYS386TGT, SEL_KPL);
- setidt(17, &IDTVEC(align), SDT_SYS386TGT, SEL_KPL);
+ setidt(x, &IDTVEC(rsvd), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
+ setidt(0, &IDTVEC(div), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
+ setidt(1, &IDTVEC(dbg), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
+ setidt(2, &IDTVEC(nmi), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
+ setidt(3, &IDTVEC(bpt), SDT_SYS386TGT, SEL_UPL, GSEL(GCODE_SEL, SEL_KPL));
+ setidt(4, &IDTVEC(ofl), SDT_SYS386TGT, SEL_UPL, GSEL(GCODE_SEL, SEL_KPL));
+ setidt(5, &IDTVEC(bnd), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
+ setidt(6, &IDTVEC(ill), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
+ setidt(7, &IDTVEC(dna), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
+ setidt(8, 0, SDT_SYSTASKGT, SEL_KPL, GSEL(GPANIC_SEL, SEL_KPL));
+ setidt(9, &IDTVEC(fpusegm), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
+ setidt(10, &IDTVEC(tss), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
+ 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(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));
#if defined(COMPAT_LINUX) || defined(LINUX)
- setidt(0x80, &IDTVEC(linux_syscall), SDT_SYS386TGT, SEL_UPL);
+ setidt(0x80, &IDTVEC(linux_syscall), SDT_SYS386TGT, SEL_UPL, GSEL(GCODE_SEL, SEL_KPL));
#endif
#include "isa.h"
@@ -1569,8 +1572,20 @@ init386(first)
proc0.p_addr->u_pcb.pcb_tss.tss_ss0 = GSEL(GDATA_SEL, SEL_KPL) ;
gsel_tss = GSEL(GPROC0_SEL, SEL_KPL);
+ dblfault_tss.tss_esp = dblfault_tss.tss_esp0 = dblfault_tss.tss_esp1 =
+ dblfault_tss.tss_esp2 = (int) &dblfault_stack[sizeof(dblfault_stack)];
+ dblfault_tss.tss_ss = dblfault_tss.tss_ss0 = dblfault_tss.tss_ss1 =
+ dblfault_tss.tss_ss2 = GSEL(GDATA_SEL, SEL_KPL);
+ dblfault_tss.tss_cr3 = IdlePTD;
+ dblfault_tss.tss_eip = (int) dblfault_handler;
+ dblfault_tss.tss_eflags = PSL_KERNEL;
+ dblfault_tss.tss_ds = dblfault_tss.tss_es = dblfault_tss.tss_fs = dblfault_tss.tss_gs =
+ GSEL(GDATA_SEL, SEL_KPL);
+ dblfault_tss.tss_cs = GSEL(GCODE_SEL, SEL_KPL);
+ dblfault_tss.tss_ldt = GSEL(GLDT_SEL, SEL_KPL);
+
((struct i386tss *)gdt_segs[GPROC0_SEL].ssd_base)->tss_ioopt =
- (sizeof(tss))<<16;
+ (sizeof(struct i386tss))<<16;
ltr(gsel_tss);
diff --git a/sys/i386/i386/trap.c b/sys/i386/i386/trap.c
index 21f1f8e..acee977 100644
--- a/sys/i386/i386/trap.c
+++ b/sys/i386/i386/trap.c
@@ -35,7 +35,7 @@
* SUCH DAMAGE.
*
* from: @(#)trap.c 7.4 (Berkeley) 5/13/91
- * $Id: trap.c,v 1.65 1995/12/14 08:21:29 phk Exp $
+ * $Id: trap.c,v 1.66 1995/12/14 14:35:36 peter Exp $
*/
/*
@@ -89,8 +89,9 @@ extern int trapwrite __P((unsigned addr));
extern void syscall __P((struct trapframe frame));
extern void linux_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));
+static void trap_fatal __P((struct trapframe *));
+void dblfault_handler __P((void));
extern inthand_t IDTVEC(syscall);
@@ -756,6 +757,33 @@ trap_fatal(frame)
}
/*
+ * Double fault handler. Called when a fault occurs while writing
+ * a frame for a trap/exception onto the stack. This usually occurs
+ * when the stack overflows (such is the case with infinite recursion,
+ * for example).
+ *
+ * XXX Note that the current PTD gets replaced by IdlePTD when the
+ * task switch occurs. This means that the stack that was active at
+ * the time of the double fault is not available at <kstack> unless
+ * the machine was idlewhen the double fault occurred. This downside
+ * of this is that "trace <ebp>" in ddb won't work.
+ */
+void
+dblfault_handler()
+{
+ struct pcb *pcb = curpcb;
+
+ if (pcb != NULL) {
+ printf("\nFatal double fault:\n");
+ printf("eip = 0x%x\n", pcb->pcb_tss.tss_eip);
+ printf("esp = 0x%x\n", pcb->pcb_tss.tss_esp);
+ printf("ebp = 0x%x\n", pcb->pcb_tss.tss_ebp);
+ }
+
+ panic("double fault");
+}
+
+/*
* Compensate for 386 brain damage (missing URKR).
* This is a little simpler than the pagefault handler in trap() because
* it the page tables have already been faulted in and high addresses
diff --git a/sys/i386/include/cpufunc.h b/sys/i386/include/cpufunc.h
index 11774bf..e82b4f0 100644
--- a/sys/i386/include/cpufunc.h
+++ b/sys/i386/include/cpufunc.h
@@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: cpufunc.h,v 1.41 1995/10/05 10:32:47 phk Exp $
+ * $Id: cpufunc.h,v 1.42 1995/12/03 13:45:27 bde Exp $
*/
/*
@@ -412,6 +412,6 @@ u_long kvtop __P((void *addr));
typedef void alias_for_inthand_t __P((u_int cs, u_int ef, u_int esp,
u_int ss));
void setidt __P((int idx, alias_for_inthand_t *func, int typ,
- int dpl));
+ int dpl, int selec));
#endif /* !_MACHINE_CPUFUNC_H_ */
diff --git a/sys/i386/isa/isa.c b/sys/i386/isa/isa.c
index e04a500..54a11e1 100644
--- a/sys/i386/isa/isa.c
+++ b/sys/i386/isa/isa.c
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* from: @(#)isa.c 7.2 (Berkeley) 5/13/91
- * $Id: isa.c,v 1.57 1995/11/20 13:24:18 bde Exp $
+ * $Id: isa.c,v 1.58 1995/12/07 12:46:01 davidg Exp $
*/
/*
@@ -936,7 +936,7 @@ register_intr(intr, device_id, flags, handler, maskptr, unit)
intr_unit[intr] = unit;
setidt(ICU_OFFSET + intr,
flags & RI_FAST ? fastintr[intr] : slowintr[intr],
- SDT_SYS386IGT, SEL_KPL);
+ SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
write_eflags(ef);
for (cp = intrnames, id = 0; id <= device_id; id++)
while (*cp++ != '\0')
@@ -983,7 +983,8 @@ unregister_intr(intr, handler)
intr_mptr[intr] = NULL;
intr_mask[intr] = HWI_MASK | SWI_MASK;
intr_unit[intr] = intr;
- setidt(ICU_OFFSET + intr, slowintr[intr], SDT_SYS386IGT, SEL_KPL);
+ setidt(ICU_OFFSET + intr, slowintr[intr], SDT_SYS386IGT, SEL_KPL,
+ GSEL(GCODE_SEL, SEL_KPL));
write_eflags(ef);
return (0);
}
diff --git a/sys/i386/isa/npx.c b/sys/i386/isa/npx.c
index 54cb5bf..8f274db 100644
--- a/sys/i386/isa/npx.c
+++ b/sys/i386/isa/npx.c
@@ -32,7 +32,7 @@
* SUCH DAMAGE.
*
* from: @(#)npx.c 7.2 (Berkeley) 5/12/91
- * $Id: npx.c,v 1.25 1995/10/28 13:07:21 phk Exp $
+ * $Id: npx.c,v 1.26 1995/12/10 13:39:02 phk Exp $
*/
#include "npx.h"
@@ -212,8 +212,8 @@ npxprobe(dvp)
save_idt_npxtrap = idt[16];
outb(IO_ICU1 + 1, ~(IRQ_SLAVE | dvp->id_irq));
outb(IO_ICU2 + 1, ~(dvp->id_irq >> 8));
- setidt(16, probetrap, SDT_SYS386TGT, SEL_KPL);
- setidt(npx_intrno, probeintr, SDT_SYS386IGT, SEL_KPL);
+ setidt(16, probetrap, SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
+ setidt(npx_intrno, probeintr, SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
npx_idt_probeintr = idt[npx_intrno];
enable_intr();
result = npxprobe1(dvp);
diff --git a/sys/kern/subr_trap.c b/sys/kern/subr_trap.c
index 21f1f8e..acee977 100644
--- a/sys/kern/subr_trap.c
+++ b/sys/kern/subr_trap.c
@@ -35,7 +35,7 @@
* SUCH DAMAGE.
*
* from: @(#)trap.c 7.4 (Berkeley) 5/13/91
- * $Id: trap.c,v 1.65 1995/12/14 08:21:29 phk Exp $
+ * $Id: trap.c,v 1.66 1995/12/14 14:35:36 peter Exp $
*/
/*
@@ -89,8 +89,9 @@ extern int trapwrite __P((unsigned addr));
extern void syscall __P((struct trapframe frame));
extern void linux_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));
+static void trap_fatal __P((struct trapframe *));
+void dblfault_handler __P((void));
extern inthand_t IDTVEC(syscall);
@@ -756,6 +757,33 @@ trap_fatal(frame)
}
/*
+ * Double fault handler. Called when a fault occurs while writing
+ * a frame for a trap/exception onto the stack. This usually occurs
+ * when the stack overflows (such is the case with infinite recursion,
+ * for example).
+ *
+ * XXX Note that the current PTD gets replaced by IdlePTD when the
+ * task switch occurs. This means that the stack that was active at
+ * the time of the double fault is not available at <kstack> unless
+ * the machine was idlewhen the double fault occurred. This downside
+ * of this is that "trace <ebp>" in ddb won't work.
+ */
+void
+dblfault_handler()
+{
+ struct pcb *pcb = curpcb;
+
+ if (pcb != NULL) {
+ printf("\nFatal double fault:\n");
+ printf("eip = 0x%x\n", pcb->pcb_tss.tss_eip);
+ printf("esp = 0x%x\n", pcb->pcb_tss.tss_esp);
+ printf("ebp = 0x%x\n", pcb->pcb_tss.tss_ebp);
+ }
+
+ panic("double fault");
+}
+
+/*
* Compensate for 386 brain damage (missing URKR).
* This is a little simpler than the pagefault handler in trap() because
* it the page tables have already been faulted in and high addresses
OpenPOWER on IntegriCloud