diff options
| author | Seth Goldberg <Seth.Goldberg@Sun.COM> | 2009-02-02 16:25:54 -0800 |
|---|---|---|
| committer | Seth Goldberg <Seth.Goldberg@Sun.COM> | 2009-02-02 16:25:54 -0800 |
| commit | 9844da31e6f9a1bffcbbb9ec7926f759ee04c460 (patch) | |
| tree | c0caeedeb1fd510907033032a24e1f2976affd10 /usr/src | |
| parent | 6bdf0ab58e83f1eea3ec057b462223bbab57e454 (diff) | |
| download | illumos-joyent-9844da31e6f9a1bffcbbb9ec7926f759ee04c460.tar.gz | |
6625634 double fault handler no longer switches stacks on 64-bit kernel
6652275 32bit #df double fault traps broken, after 6624280
Diffstat (limited to 'usr/src')
| -rw-r--r-- | usr/src/uts/i86pc/os/fakebop.c | 9 | ||||
| -rw-r--r-- | usr/src/uts/i86pc/os/startup.c | 2 | ||||
| -rw-r--r-- | usr/src/uts/i86xpv/os/xpv_panic.c | 46 | ||||
| -rw-r--r-- | usr/src/uts/intel/ia32/os/desctbls.c | 93 | ||||
| -rw-r--r-- | usr/src/uts/intel/kdi/kdi_idt.c | 8 | ||||
| -rw-r--r-- | usr/src/uts/intel/sys/segments.h | 6 |
6 files changed, 96 insertions, 68 deletions
diff --git a/usr/src/uts/i86pc/os/fakebop.c b/usr/src/uts/i86pc/os/fakebop.c index 0bc06115fd..bbb85856e7 100644 --- a/usr/src/uts/i86pc/os/fakebop.c +++ b/usr/src/uts/i86pc/os/fakebop.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -1571,8 +1571,13 @@ bop_idt_init(void) do_bsys_alloc(NULL, NULL, MMU_PAGESIZE, MMU_PAGESIZE); bzero(bop_idt, MMU_PAGESIZE); for (t = 0; t < NIDT; ++t) { + /* + * Note that since boot runs without a TSS, the + * double fault handler cannot use an alternate stack + * (64-bit) or a task gate (32-bit). + */ set_gatesegd(&bop_idt[t], &bop_trap_handler, bcode_sel, - SDT_SYSIGT, TRP_KPL); + SDT_SYSIGT, TRP_KPL, 0); } bop_idt_info.dtr_limit = (NIDT * sizeof (gate_desc_t)) - 1; bop_idt_info.dtr_base = (uintptr_t)bop_idt; diff --git a/usr/src/uts/i86pc/os/startup.c b/usr/src/uts/i86pc/os/startup.c index 29a7fe21f9..58bc3416f1 100644 --- a/usr/src/uts/i86pc/os/startup.c +++ b/usr/src/uts/i86pc/os/startup.c @@ -1897,7 +1897,7 @@ startup_vm(void) bcopy(idt0, newidt, NIDT * sizeof (*idt0)); set_gatesegd(&newidt[T_PGFLT], &pentium_pftrap, - KCS_SEL, SDT_SYSIGT, TRP_KPL); + KCS_SEL, SDT_SYSIGT, TRP_KPL, 0); (void) as_setprot(&kas, (caddr_t)newidt, MMU_PAGESIZE, PROT_READ | PROT_EXEC); diff --git a/usr/src/uts/i86xpv/os/xpv_panic.c b/usr/src/uts/i86xpv/os/xpv_panic.c index 25a7e6da26..731de9036d 100644 --- a/usr/src/uts/i86xpv/os/xpv_panic.c +++ b/usr/src/uts/i86xpv/os/xpv_panic.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -501,24 +501,32 @@ switch_to_xpv_panic_idt() selector_t cs = get_cs_register(); for (i = 0; i < 32; i++) - set_gatesegd(&idt[i], &xpv_invaltrap, cs, SDT_SYSIGT, TRP_XPL); + set_gatesegd(&idt[i], &xpv_invaltrap, cs, SDT_SYSIGT, TRP_XPL, + 0); - set_gatesegd(&idt[T_ZERODIV], &xpv_div0trap, cs, SDT_SYSIGT, TRP_XPL); - set_gatesegd(&idt[T_SGLSTP], &xpv_dbgtrap, cs, SDT_SYSIGT, TRP_XPL); - set_gatesegd(&idt[T_NMIFLT], &xpv_nmiint, cs, SDT_SYSIGT, TRP_XPL); + set_gatesegd(&idt[T_ZERODIV], &xpv_div0trap, cs, SDT_SYSIGT, TRP_XPL, + 0); + set_gatesegd(&idt[T_SGLSTP], &xpv_dbgtrap, cs, SDT_SYSIGT, TRP_XPL, 0); + set_gatesegd(&idt[T_NMIFLT], &xpv_nmiint, cs, SDT_SYSIGT, TRP_XPL, 0); set_gatesegd(&idt[T_BOUNDFLT], &xpv_boundstrap, cs, SDT_SYSIGT, - TRP_XPL); - set_gatesegd(&idt[T_ILLINST], &xpv_invoptrap, cs, SDT_SYSIGT, TRP_XPL); - set_gatesegd(&idt[T_NOEXTFLT], &xpv_ndptrap, cs, SDT_SYSIGT, TRP_XPL); - set_gatesegd(&idt[T_TSSFLT], &xpv_invtsstrap, cs, SDT_SYSIGT, TRP_XPL); - set_gatesegd(&idt[T_SEGFLT], &xpv_segnptrap, cs, SDT_SYSIGT, TRP_XPL); - set_gatesegd(&idt[T_STKFLT], &xpv_stktrap, cs, SDT_SYSIGT, TRP_XPL); - set_gatesegd(&idt[T_GPFLT], &xpv_gptrap, cs, SDT_SYSIGT, TRP_XPL); - set_gatesegd(&idt[T_PGFLT], &xpv_pftrap, cs, SDT_SYSIGT, TRP_XPL); - set_gatesegd(&idt[T_EXTERRFLT], &xpv_ndperr, cs, SDT_SYSIGT, TRP_XPL); - set_gatesegd(&idt[T_ALIGNMENT], &xpv_achktrap, cs, SDT_SYSIGT, TRP_XPL); - set_gatesegd(&idt[T_MCE], &xpv_mcetrap, cs, SDT_SYSIGT, TRP_XPL); - set_gatesegd(&idt[T_SIMDFPE], &xpv_xmtrap, cs, SDT_SYSIGT, TRP_XPL); + TRP_XPL, 0); + set_gatesegd(&idt[T_ILLINST], &xpv_invoptrap, cs, SDT_SYSIGT, TRP_XPL, + 0); + set_gatesegd(&idt[T_NOEXTFLT], &xpv_ndptrap, cs, SDT_SYSIGT, TRP_XPL, + 0); + set_gatesegd(&idt[T_TSSFLT], &xpv_invtsstrap, cs, SDT_SYSIGT, TRP_XPL, + 0); + set_gatesegd(&idt[T_SEGFLT], &xpv_segnptrap, cs, SDT_SYSIGT, TRP_XPL, + 0); + set_gatesegd(&idt[T_STKFLT], &xpv_stktrap, cs, SDT_SYSIGT, TRP_XPL, 0); + set_gatesegd(&idt[T_GPFLT], &xpv_gptrap, cs, SDT_SYSIGT, TRP_XPL, 0); + set_gatesegd(&idt[T_PGFLT], &xpv_pftrap, cs, SDT_SYSIGT, TRP_XPL, 0); + set_gatesegd(&idt[T_EXTERRFLT], &xpv_ndperr, cs, SDT_SYSIGT, TRP_XPL, + 0); + set_gatesegd(&idt[T_ALIGNMENT], &xpv_achktrap, cs, SDT_SYSIGT, TRP_XPL, + 0); + set_gatesegd(&idt[T_MCE], &xpv_mcetrap, cs, SDT_SYSIGT, TRP_XPL, 0); + set_gatesegd(&idt[T_SIMDFPE], &xpv_xmtrap, cs, SDT_SYSIGT, TRP_XPL, 0); /* * We have no double fault handler. Any single fault represents a @@ -534,11 +542,11 @@ switch_to_xpv_panic_idt() */ for (i = 33; i < NIDT; i++) set_gatesegd(&idt[i], &xpv_surprise_intr, cs, SDT_SYSIGT, - TRP_XPL); + TRP_XPL, 0); /* The one interrupt we expect to get is from the APIC timer. */ set_gatesegd(&idt[T_XPV_TIMER], &xpv_timer_trap, cs, SDT_SYSIGT, - TRP_XPL); + TRP_XPL, 0); idtr.dtr_base = (uintptr_t)xpv_panic_idt; idtr.dtr_limit = sizeof (xpv_panic_idt) - 1; diff --git a/usr/src/uts/intel/ia32/os/desctbls.c b/usr/src/uts/intel/ia32/os/desctbls.c index 8ae845b7e6..8344f20a03 100644 --- a/usr/src/uts/intel/ia32/os/desctbls.c +++ b/usr/src/uts/intel/ia32/os/desctbls.c @@ -20,12 +20,10 @@ */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - /* * Copyright (c) 1992 Terrence R. Lambert. * Copyright (c) 1990 The Regents of the University of California. @@ -313,9 +311,10 @@ get_ssd_base(system_desc_t *dp) #if defined(__amd64) +/*ARGSUSED*/ void set_gatesegd(gate_desc_t *dp, void (*func)(void), selector_t sel, - uint_t type, uint_t dpl) + uint_t type, uint_t dpl, uint_t vector) { dp->sgd_looffset = (uintptr_t)func; dp->sgd_hioffset = (uintptr_t)func >> 16; @@ -329,7 +328,7 @@ set_gatesegd(gate_desc_t *dp, void (*func)(void), selector_t sel, * (tss_rsp0) stack. */ #if !defined(__xpv) - if (type == T_DBLFLT) + if (vector == T_DBLFLT) dp->sgd_ist = 1; else #endif @@ -342,9 +341,10 @@ set_gatesegd(gate_desc_t *dp, void (*func)(void), selector_t sel, #elif defined(__i386) +/*ARGSUSED*/ void set_gatesegd(gate_desc_t *dp, void (*func)(void), selector_t sel, - uint_t type, uint_t dpl) + uint_t type, uint_t dpl, uint_t unused) { dp->sgd_looffset = (uintptr_t)func; dp->sgd_hioffset = (uintptr_t)func >> 16; @@ -914,15 +914,22 @@ init_gdt(void) static void init_idt_common(gate_desc_t *idt) { - set_gatesegd(&idt[T_ZERODIV], &div0trap, KCS_SEL, SDT_SYSIGT, TRP_KPL); - set_gatesegd(&idt[T_SGLSTP], &dbgtrap, KCS_SEL, SDT_SYSIGT, TRP_KPL); - set_gatesegd(&idt[T_NMIFLT], &nmiint, KCS_SEL, SDT_SYSIGT, TRP_KPL); - set_gatesegd(&idt[T_BPTFLT], &brktrap, KCS_SEL, SDT_SYSIGT, TRP_UPL); - set_gatesegd(&idt[T_OVFLW], &ovflotrap, KCS_SEL, SDT_SYSIGT, TRP_UPL); + set_gatesegd(&idt[T_ZERODIV], &div0trap, KCS_SEL, SDT_SYSIGT, TRP_KPL, + 0); + set_gatesegd(&idt[T_SGLSTP], &dbgtrap, KCS_SEL, SDT_SYSIGT, TRP_KPL, + 0); + set_gatesegd(&idt[T_NMIFLT], &nmiint, KCS_SEL, SDT_SYSIGT, TRP_KPL, + 0); + set_gatesegd(&idt[T_BPTFLT], &brktrap, KCS_SEL, SDT_SYSIGT, TRP_UPL, + 0); + set_gatesegd(&idt[T_OVFLW], &ovflotrap, KCS_SEL, SDT_SYSIGT, TRP_UPL, + 0); set_gatesegd(&idt[T_BOUNDFLT], &boundstrap, KCS_SEL, SDT_SYSIGT, - TRP_KPL); - set_gatesegd(&idt[T_ILLINST], &invoptrap, KCS_SEL, SDT_SYSIGT, TRP_KPL); - set_gatesegd(&idt[T_NOEXTFLT], &ndptrap, KCS_SEL, SDT_SYSIGT, TRP_KPL); + TRP_KPL, 0); + set_gatesegd(&idt[T_ILLINST], &invoptrap, KCS_SEL, SDT_SYSIGT, TRP_KPL, + 0); + set_gatesegd(&idt[T_NOEXTFLT], &ndptrap, KCS_SEL, SDT_SYSIGT, TRP_KPL, + 0); /* * double fault handler. @@ -934,14 +941,16 @@ init_idt_common(gate_desc_t *idt) #if !defined(__xpv) #if defined(__amd64) - set_gatesegd(&idt[T_DBLFLT], &syserrtrap, KCS_SEL, SDT_SYSIGT, TRP_KPL); + set_gatesegd(&idt[T_DBLFLT], &syserrtrap, KCS_SEL, SDT_SYSIGT, TRP_KPL, + T_DBLFLT); #elif defined(__i386) /* * task gate required. */ - set_gatesegd(&idt[T_DBLFLT], NULL, DFTSS_SEL, SDT_SYSTASKGT, TRP_KPL); + set_gatesegd(&idt[T_DBLFLT], NULL, DFTSS_SEL, SDT_SYSTASKGT, TRP_KPL, + 0); #endif /* __i386 */ #endif /* !__xpv */ @@ -950,44 +959,49 @@ init_idt_common(gate_desc_t *idt) * T_EXTOVRFLT coprocessor-segment-overrun not supported. */ - set_gatesegd(&idt[T_TSSFLT], &invtsstrap, KCS_SEL, SDT_SYSIGT, TRP_KPL); - set_gatesegd(&idt[T_SEGFLT], &segnptrap, KCS_SEL, SDT_SYSIGT, TRP_KPL); - set_gatesegd(&idt[T_STKFLT], &stktrap, KCS_SEL, SDT_SYSIGT, TRP_KPL); - set_gatesegd(&idt[T_GPFLT], &gptrap, KCS_SEL, SDT_SYSIGT, TRP_KPL); - set_gatesegd(&idt[T_PGFLT], &pftrap, KCS_SEL, SDT_SYSIGT, TRP_KPL); - set_gatesegd(&idt[T_EXTERRFLT], &ndperr, KCS_SEL, SDT_SYSIGT, TRP_KPL); + set_gatesegd(&idt[T_TSSFLT], &invtsstrap, KCS_SEL, SDT_SYSIGT, TRP_KPL, + 0); + set_gatesegd(&idt[T_SEGFLT], &segnptrap, KCS_SEL, SDT_SYSIGT, TRP_KPL, + 0); + set_gatesegd(&idt[T_STKFLT], &stktrap, KCS_SEL, SDT_SYSIGT, TRP_KPL, 0); + set_gatesegd(&idt[T_GPFLT], &gptrap, KCS_SEL, SDT_SYSIGT, TRP_KPL, 0); + set_gatesegd(&idt[T_PGFLT], &pftrap, KCS_SEL, SDT_SYSIGT, TRP_KPL, 0); + set_gatesegd(&idt[T_EXTERRFLT], &ndperr, KCS_SEL, SDT_SYSIGT, TRP_KPL, + 0); set_gatesegd(&idt[T_ALIGNMENT], &achktrap, KCS_SEL, SDT_SYSIGT, - TRP_KPL); - set_gatesegd(&idt[T_MCE], &mcetrap, KCS_SEL, SDT_SYSIGT, TRP_KPL); - set_gatesegd(&idt[T_SIMDFPE], &xmtrap, KCS_SEL, SDT_SYSIGT, TRP_KPL); + TRP_KPL, 0); + set_gatesegd(&idt[T_MCE], &mcetrap, KCS_SEL, SDT_SYSIGT, TRP_KPL, 0); + set_gatesegd(&idt[T_SIMDFPE], &xmtrap, KCS_SEL, SDT_SYSIGT, TRP_KPL, 0); /* * install "int80" handler at, well, 0x80. */ - set_gatesegd(&idt0[T_INT80], &sys_int80, KCS_SEL, SDT_SYSIGT, TRP_UPL); + set_gatesegd(&idt0[T_INT80], &sys_int80, KCS_SEL, SDT_SYSIGT, TRP_UPL, + 0); /* * install fast trap handler at 210. */ - set_gatesegd(&idt[T_FASTTRAP], &fasttrap, KCS_SEL, SDT_SYSIGT, TRP_UPL); + set_gatesegd(&idt[T_FASTTRAP], &fasttrap, KCS_SEL, SDT_SYSIGT, TRP_UPL, + 0); /* * System call handler. */ #if defined(__amd64) set_gatesegd(&idt[T_SYSCALLINT], &sys_syscall_int, KCS_SEL, SDT_SYSIGT, - TRP_UPL); + TRP_UPL, 0); #elif defined(__i386) set_gatesegd(&idt[T_SYSCALLINT], &sys_call, KCS_SEL, SDT_SYSIGT, - TRP_UPL); + TRP_UPL, 0); #endif /* __i386 */ /* * Install the DTrace interrupt handler for the pid provider. */ set_gatesegd(&idt[T_DTRACE_RET], &dtrace_ret, KCS_SEL, - SDT_SYSIGT, TRP_UPL); + SDT_SYSIGT, TRP_UPL, 0); /* * Prepare interposing descriptors for the branded "int80" @@ -997,17 +1011,17 @@ init_idt_common(gate_desc_t *idt) brand_tbl[0].ih_inum = T_INT80; brand_tbl[0].ih_default_desc = idt0[T_INT80]; set_gatesegd(&(brand_tbl[0].ih_interp_desc), &brand_sys_int80, KCS_SEL, - SDT_SYSIGT, TRP_UPL); + SDT_SYSIGT, TRP_UPL, 0); brand_tbl[1].ih_inum = T_SYSCALLINT; brand_tbl[1].ih_default_desc = idt0[T_SYSCALLINT]; #if defined(__amd64) set_gatesegd(&(brand_tbl[1].ih_interp_desc), &brand_sys_syscall_int, - KCS_SEL, SDT_SYSIGT, TRP_UPL); + KCS_SEL, SDT_SYSIGT, TRP_UPL, 0); #elif defined(__i386) set_gatesegd(&(brand_tbl[1].ih_interp_desc), &brand_sys_call, - KCS_SEL, SDT_SYSIGT, TRP_UPL); + KCS_SEL, SDT_SYSIGT, TRP_UPL, 0); #endif /* __i386 */ brand_tbl[2].ih_inum = 0; @@ -1018,7 +1032,6 @@ init_idt_common(gate_desc_t *idt) static void init_idt(gate_desc_t *idt) { - bzero(idt, sizeof (*idt) * NIDT); init_idt_common(idt); } @@ -1038,13 +1051,15 @@ init_idt(gate_desc_t *idt) * unsupported and reserved. */ for (i = 0; i < NIDT; i++) - set_gatesegd(&idt[i], &resvtrap, KCS_SEL, SDT_SYSIGT, TRP_KPL); + set_gatesegd(&idt[i], &resvtrap, KCS_SEL, SDT_SYSIGT, TRP_KPL, + 0); /* * 20-31 reserved */ for (i = 20; i < 32; i++) - set_gatesegd(&idt[i], &invaltrap, KCS_SEL, SDT_SYSIGT, TRP_KPL); + set_gatesegd(&idt[i], &invaltrap, KCS_SEL, SDT_SYSIGT, TRP_KPL, + 0); /* * interrupts 32 - 255 @@ -1055,7 +1070,7 @@ init_idt(gate_desc_t *idt) if (ivctptr == NULL) panic("kobj_getsymvalue(%s) failed", ivctname); - set_gatesegd(&idt[i], ivctptr, KCS_SEL, SDT_SYSIGT, TRP_KPL); + set_gatesegd(&idt[i], ivctptr, KCS_SEL, SDT_SYSIGT, TRP_KPL, 0); } /* @@ -1191,6 +1206,7 @@ init_desctbls(void) #endif idt0 = (gate_desc_t *)BOP_ALLOC(bootops, (caddr_t)IDT_VA, PAGESIZE, PAGESIZE); + bzero(idt0, PAGESIZE); init_idt(idt0); for (vec = 0; vec < NIDT; vec++) xen_idt_write(&idt0[vec], vec); @@ -1225,11 +1241,13 @@ init_desctbls(void) #endif idt0 = (gate_desc_t *)BOP_ALLOC(bootops, (caddr_t)IDT_VA, PAGESIZE, PAGESIZE); + bzero(idt0, PAGESIZE); #if !defined(__lint) ASSERT(sizeof (*ktss0) <= PAGESIZE); #endif ktss0 = (struct tss *)BOP_ALLOC(bootops, (caddr_t)KTSS_VA, PAGESIZE, PAGESIZE); + bzero(ktss0, PAGESIZE); #if defined(__i386) #if !defined(__lint) @@ -1237,6 +1255,7 @@ init_desctbls(void) #endif dftss0 = (struct tss *)BOP_ALLOC(bootops, (caddr_t)DFTSS_VA, PAGESIZE, PAGESIZE); + bzero(dftss0, PAGESIZE); #endif /* diff --git a/usr/src/uts/intel/kdi/kdi_idt.c b/usr/src/uts/intel/kdi/kdi_idt.c index d2c7caca13..25e2509a1a 100644 --- a/usr/src/uts/intel/kdi/kdi_idt.c +++ b/usr/src/uts/intel/kdi/kdi_idt.c @@ -19,12 +19,10 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - /* * Management of KMDB's IDT, which is installed upon KMDB activation. * @@ -191,7 +189,7 @@ kdi_idt_init(selector_t sel) caddr_t hdlr = (caddr_t)id->id_basehdlr + incr * (i - id->id_low); set_gatesegd(&kdi_idt[i], (void (*)())hdlr, sel, - SDT_SYSIGT, TRP_KPL); + SDT_SYSIGT, TRP_KPL, i); } } } @@ -247,7 +245,7 @@ kdi_idt_gates_install(selector_t sel, int saveold) const kdi_gate_spec_t *gs = &kdi_gate_specs[i]; uintptr_t func = GATESEG_GETOFFSET(&kdi_idt[gs->kgs_vec]); set_gatesegd(&gates[i], (void (*)())func, sel, SDT_SYSIGT, - gs->kgs_dpl); + gs->kgs_dpl, gs->kgs_vec); } for (i = 0; i < KDI_GATE_NVECS; i++) { diff --git a/usr/src/uts/intel/sys/segments.h b/usr/src/uts/intel/sys/segments.h index 7e91e966e1..874364d203 100644 --- a/usr/src/uts/intel/sys/segments.h +++ b/usr/src/uts/intel/sys/segments.h @@ -1,13 +1,11 @@ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _SYS_SEGMENTS_H #define _SYS_SEGMENTS_H -#pragma ident "%Z%%M% %I% %E% SMI" - #ifdef __cplusplus extern "C" { #endif @@ -402,7 +400,7 @@ extern void set_usegd(user_desc_t *, void *, size_t, uint_t, uint_t, #endif /* __i386 */ extern void set_gatesegd(gate_desc_t *, void (*)(void), selector_t, - uint_t, uint_t); + uint_t, uint_t, uint_t); extern void set_syssegd(system_desc_t *, void *, size_t, uint_t, uint_t); |
