10Sstevel@tonic-gate /* 2*1217Srab * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 30Sstevel@tonic-gate * Use is subject to license terms. 40Sstevel@tonic-gate */ 50Sstevel@tonic-gate 60Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 70Sstevel@tonic-gate 80Sstevel@tonic-gate /* 90Sstevel@tonic-gate * Copyright (c) 1992 Terrence R. Lambert. 100Sstevel@tonic-gate * Copyright (c) 1990 The Regents of the University of California. 110Sstevel@tonic-gate * All rights reserved. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * This code is derived from software contributed to Berkeley by 140Sstevel@tonic-gate * William Jolitz. 150Sstevel@tonic-gate * 160Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without 170Sstevel@tonic-gate * modification, are permitted provided that the following conditions 180Sstevel@tonic-gate * are met: 190Sstevel@tonic-gate * 1. Redistributions of source code must retain the above copyright 200Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer. 210Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright 220Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in the 230Sstevel@tonic-gate * documentation and/or other materials provided with the distribution. 240Sstevel@tonic-gate * 3. All advertising materials mentioning features or use of this software 250Sstevel@tonic-gate * must display the following acknowledgement: 260Sstevel@tonic-gate * This product includes software developed by the University of 270Sstevel@tonic-gate * California, Berkeley and its contributors. 280Sstevel@tonic-gate * 4. Neither the name of the University nor the names of its contributors 290Sstevel@tonic-gate * may be used to endorse or promote products derived from this software 300Sstevel@tonic-gate * without specific prior written permission. 310Sstevel@tonic-gate * 320Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 330Sstevel@tonic-gate * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 340Sstevel@tonic-gate * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 350Sstevel@tonic-gate * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 360Sstevel@tonic-gate * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 370Sstevel@tonic-gate * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 380Sstevel@tonic-gate * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 390Sstevel@tonic-gate * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 400Sstevel@tonic-gate * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 410Sstevel@tonic-gate * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 420Sstevel@tonic-gate * SUCH DAMAGE. 430Sstevel@tonic-gate * 440Sstevel@tonic-gate * from: @(#)machdep.c 7.4 (Berkeley) 6/3/91 450Sstevel@tonic-gate */ 460Sstevel@tonic-gate 470Sstevel@tonic-gate #include <sys/types.h> 480Sstevel@tonic-gate #include <sys/tss.h> 490Sstevel@tonic-gate #include <sys/segments.h> 500Sstevel@tonic-gate #include <sys/trap.h> 510Sstevel@tonic-gate #include <sys/cpuvar.h> 520Sstevel@tonic-gate #include <sys/x86_archext.h> 530Sstevel@tonic-gate #include <sys/archsystm.h> 540Sstevel@tonic-gate #include <sys/machsystm.h> 550Sstevel@tonic-gate #include <sys/kobj.h> 560Sstevel@tonic-gate #include <sys/cmn_err.h> 570Sstevel@tonic-gate #include <sys/reboot.h> 580Sstevel@tonic-gate #include <sys/kdi.h> 59*1217Srab #include <sys/systm.h> 600Sstevel@tonic-gate 610Sstevel@tonic-gate extern void syscall_int(void); 620Sstevel@tonic-gate 630Sstevel@tonic-gate /* 640Sstevel@tonic-gate * cpu0 and default tables and structures. 650Sstevel@tonic-gate */ 660Sstevel@tonic-gate #pragma align 16(gdt0) 670Sstevel@tonic-gate user_desc_t gdt0[NGDT]; /* global descriptor table */ 680Sstevel@tonic-gate desctbr_t gdt0_default_r; 690Sstevel@tonic-gate 700Sstevel@tonic-gate #pragma align 16(idt0) 710Sstevel@tonic-gate gate_desc_t idt0[NIDT]; /* interrupt descriptor table */ 720Sstevel@tonic-gate desctbr_t idt0_default_r; /* describes idt0 in IDTR format */ 730Sstevel@tonic-gate 740Sstevel@tonic-gate #pragma align 16(ktss0) 750Sstevel@tonic-gate struct tss ktss0; /* kernel task state structure */ 760Sstevel@tonic-gate 770Sstevel@tonic-gate #if defined(__i386) 780Sstevel@tonic-gate #pragma align 16(dftss0) 790Sstevel@tonic-gate struct tss dftss0; /* #DF double-fault exception */ 800Sstevel@tonic-gate #endif /* __i386 */ 810Sstevel@tonic-gate 820Sstevel@tonic-gate user_desc_t zero_udesc; /* base zero user desc native procs */ 83*1217Srab system_desc_t zero_sdesc; 840Sstevel@tonic-gate 850Sstevel@tonic-gate #if defined(__amd64) 860Sstevel@tonic-gate user_desc_t zero_u32desc; /* 32-bit compatibility procs */ 870Sstevel@tonic-gate #endif /* __amd64 */ 880Sstevel@tonic-gate 890Sstevel@tonic-gate #pragma align 16(dblfault_stack0) 900Sstevel@tonic-gate char dblfault_stack0[DEFAULTSTKSZ]; 910Sstevel@tonic-gate 920Sstevel@tonic-gate extern void fast_null(void); 930Sstevel@tonic-gate extern hrtime_t get_hrtime(void); 940Sstevel@tonic-gate extern hrtime_t gethrvtime(void); 950Sstevel@tonic-gate extern hrtime_t get_hrestime(void); 960Sstevel@tonic-gate extern uint64_t getlgrp(void); 970Sstevel@tonic-gate 980Sstevel@tonic-gate void (*(fasttable[]))(void) = { 990Sstevel@tonic-gate fast_null, /* T_FNULL routine */ 1000Sstevel@tonic-gate fast_null, /* T_FGETFP routine (initially null) */ 1010Sstevel@tonic-gate fast_null, /* T_FSETFP routine (initially null) */ 1020Sstevel@tonic-gate (void (*)())get_hrtime, /* T_GETHRTIME */ 1030Sstevel@tonic-gate (void (*)())gethrvtime, /* T_GETHRVTIME */ 1040Sstevel@tonic-gate (void (*)())get_hrestime, /* T_GETHRESTIME */ 1050Sstevel@tonic-gate (void (*)())getlgrp /* T_GETLGRP */ 1060Sstevel@tonic-gate }; 1070Sstevel@tonic-gate 1080Sstevel@tonic-gate /* 1090Sstevel@tonic-gate * software prototypes for default local descriptor table 1100Sstevel@tonic-gate */ 1110Sstevel@tonic-gate 1120Sstevel@tonic-gate /* 1130Sstevel@tonic-gate * Routines for loading segment descriptors in format the hardware 1140Sstevel@tonic-gate * can understand. 1150Sstevel@tonic-gate */ 1160Sstevel@tonic-gate 1170Sstevel@tonic-gate #if defined(__amd64) 1180Sstevel@tonic-gate 1190Sstevel@tonic-gate /* 1200Sstevel@tonic-gate * In long mode we have the new L or long mode attribute bit 1210Sstevel@tonic-gate * for code segments. Only the conforming bit in type is used along 1220Sstevel@tonic-gate * with descriptor priority and present bits. Default operand size must 1230Sstevel@tonic-gate * be zero when in long mode. In 32-bit compatibility mode all fields 1240Sstevel@tonic-gate * are treated as in legacy mode. For data segments while in long mode 1250Sstevel@tonic-gate * only the present bit is loaded. 1260Sstevel@tonic-gate */ 1270Sstevel@tonic-gate void 1280Sstevel@tonic-gate set_usegd(user_desc_t *dp, uint_t lmode, void *base, size_t size, 1290Sstevel@tonic-gate uint_t type, uint_t dpl, uint_t gran, uint_t defopsz) 1300Sstevel@tonic-gate { 1310Sstevel@tonic-gate ASSERT(lmode == SDP_SHORT || lmode == SDP_LONG); 1320Sstevel@tonic-gate 1330Sstevel@tonic-gate /* 1340Sstevel@tonic-gate * 64-bit long mode. 1350Sstevel@tonic-gate */ 1360Sstevel@tonic-gate if (lmode == SDP_LONG) 1370Sstevel@tonic-gate dp->usd_def32 = 0; /* 32-bit operands only */ 1380Sstevel@tonic-gate else 1390Sstevel@tonic-gate /* 1400Sstevel@tonic-gate * 32-bit compatibility mode. 1410Sstevel@tonic-gate */ 1420Sstevel@tonic-gate dp->usd_def32 = defopsz; /* 0 = 16, 1 = 32-bit ops */ 1430Sstevel@tonic-gate 1440Sstevel@tonic-gate dp->usd_long = lmode; /* 64-bit mode */ 1450Sstevel@tonic-gate dp->usd_type = type; 1460Sstevel@tonic-gate dp->usd_dpl = dpl; 1470Sstevel@tonic-gate dp->usd_p = 1; 1480Sstevel@tonic-gate dp->usd_gran = gran; /* 0 = bytes, 1 = pages */ 1490Sstevel@tonic-gate 1500Sstevel@tonic-gate dp->usd_lobase = (uintptr_t)base; 1510Sstevel@tonic-gate dp->usd_midbase = (uintptr_t)base >> 16; 1520Sstevel@tonic-gate dp->usd_hibase = (uintptr_t)base >> (16 + 8); 1530Sstevel@tonic-gate dp->usd_lolimit = size; 1540Sstevel@tonic-gate dp->usd_hilimit = (uintptr_t)size >> 16; 1550Sstevel@tonic-gate } 1560Sstevel@tonic-gate 1570Sstevel@tonic-gate #elif defined(__i386) 1580Sstevel@tonic-gate 1590Sstevel@tonic-gate /* 1600Sstevel@tonic-gate * Install user segment descriptor for code and data. 1610Sstevel@tonic-gate */ 1620Sstevel@tonic-gate void 1630Sstevel@tonic-gate set_usegd(user_desc_t *dp, void *base, size_t size, uint_t type, 1640Sstevel@tonic-gate uint_t dpl, uint_t gran, uint_t defopsz) 1650Sstevel@tonic-gate { 1660Sstevel@tonic-gate dp->usd_lolimit = size; 1670Sstevel@tonic-gate dp->usd_hilimit = (uintptr_t)size >> 16; 1680Sstevel@tonic-gate 1690Sstevel@tonic-gate dp->usd_lobase = (uintptr_t)base; 1700Sstevel@tonic-gate dp->usd_midbase = (uintptr_t)base >> 16; 1710Sstevel@tonic-gate dp->usd_hibase = (uintptr_t)base >> (16 + 8); 1720Sstevel@tonic-gate 1730Sstevel@tonic-gate dp->usd_type = type; 1740Sstevel@tonic-gate dp->usd_dpl = dpl; 1750Sstevel@tonic-gate dp->usd_p = 1; 1760Sstevel@tonic-gate dp->usd_def32 = defopsz; /* 0 = 16, 1 = 32 bit operands */ 1770Sstevel@tonic-gate dp->usd_gran = gran; /* 0 = bytes, 1 = pages */ 1780Sstevel@tonic-gate } 1790Sstevel@tonic-gate 1800Sstevel@tonic-gate #endif /* __i386 */ 1810Sstevel@tonic-gate 1820Sstevel@tonic-gate /* 1830Sstevel@tonic-gate * Install system segment descriptor for LDT and TSS segments. 1840Sstevel@tonic-gate */ 1850Sstevel@tonic-gate 1860Sstevel@tonic-gate #if defined(__amd64) 1870Sstevel@tonic-gate 1880Sstevel@tonic-gate void 1890Sstevel@tonic-gate set_syssegd(system_desc_t *dp, void *base, size_t size, uint_t type, 1900Sstevel@tonic-gate uint_t dpl) 1910Sstevel@tonic-gate { 1920Sstevel@tonic-gate dp->ssd_lolimit = size; 1930Sstevel@tonic-gate dp->ssd_hilimit = (uintptr_t)size >> 16; 1940Sstevel@tonic-gate 1950Sstevel@tonic-gate dp->ssd_lobase = (uintptr_t)base; 1960Sstevel@tonic-gate dp->ssd_midbase = (uintptr_t)base >> 16; 1970Sstevel@tonic-gate dp->ssd_hibase = (uintptr_t)base >> (16 + 8); 1980Sstevel@tonic-gate dp->ssd_hi64base = (uintptr_t)base >> (16 + 8 + 8); 1990Sstevel@tonic-gate 2000Sstevel@tonic-gate dp->ssd_type = type; 2010Sstevel@tonic-gate dp->ssd_zero1 = 0; /* must be zero */ 2020Sstevel@tonic-gate dp->ssd_zero2 = 0; 2030Sstevel@tonic-gate dp->ssd_dpl = dpl; 2040Sstevel@tonic-gate dp->ssd_p = 1; 2050Sstevel@tonic-gate dp->ssd_gran = 0; /* force byte units */ 2060Sstevel@tonic-gate } 2070Sstevel@tonic-gate 2080Sstevel@tonic-gate #elif defined(__i386) 2090Sstevel@tonic-gate 2100Sstevel@tonic-gate void 2110Sstevel@tonic-gate set_syssegd(system_desc_t *dp, void *base, size_t size, uint_t type, 2120Sstevel@tonic-gate uint_t dpl) 2130Sstevel@tonic-gate { 2140Sstevel@tonic-gate dp->ssd_lolimit = size; 2150Sstevel@tonic-gate dp->ssd_hilimit = (uintptr_t)size >> 16; 2160Sstevel@tonic-gate 2170Sstevel@tonic-gate dp->ssd_lobase = (uintptr_t)base; 2180Sstevel@tonic-gate dp->ssd_midbase = (uintptr_t)base >> 16; 2190Sstevel@tonic-gate dp->ssd_hibase = (uintptr_t)base >> (16 + 8); 2200Sstevel@tonic-gate 2210Sstevel@tonic-gate dp->ssd_type = type; 2220Sstevel@tonic-gate dp->ssd_zero = 0; /* must be zero */ 2230Sstevel@tonic-gate dp->ssd_dpl = dpl; 2240Sstevel@tonic-gate dp->ssd_p = 1; 2250Sstevel@tonic-gate dp->ssd_gran = 0; /* force byte units */ 2260Sstevel@tonic-gate } 2270Sstevel@tonic-gate 2280Sstevel@tonic-gate #endif /* __i386 */ 2290Sstevel@tonic-gate 2300Sstevel@tonic-gate /* 2310Sstevel@tonic-gate * Install gate segment descriptor for interrupt, trap, call and task gates. 2320Sstevel@tonic-gate */ 2330Sstevel@tonic-gate 2340Sstevel@tonic-gate #if defined(__amd64) 2350Sstevel@tonic-gate 2360Sstevel@tonic-gate /* 2370Sstevel@tonic-gate * Note stkcpy is replaced with ist. Read the PRM for details on this. 2380Sstevel@tonic-gate */ 2390Sstevel@tonic-gate void 2400Sstevel@tonic-gate set_gatesegd(gate_desc_t *dp, void (*func)(void), selector_t sel, uint_t ist, 2410Sstevel@tonic-gate uint_t type, uint_t dpl) 2420Sstevel@tonic-gate { 2430Sstevel@tonic-gate dp->sgd_looffset = (uintptr_t)func; 2440Sstevel@tonic-gate dp->sgd_hioffset = (uintptr_t)func >> 16; 2450Sstevel@tonic-gate dp->sgd_hi64offset = (uintptr_t)func >> (16 + 16); 2460Sstevel@tonic-gate 2470Sstevel@tonic-gate dp->sgd_selector = (uint16_t)sel; 2480Sstevel@tonic-gate dp->sgd_ist = ist; 2490Sstevel@tonic-gate dp->sgd_type = type; 2500Sstevel@tonic-gate dp->sgd_dpl = dpl; 2510Sstevel@tonic-gate dp->sgd_p = 1; 2520Sstevel@tonic-gate } 2530Sstevel@tonic-gate 2540Sstevel@tonic-gate #elif defined(__i386) 2550Sstevel@tonic-gate 2560Sstevel@tonic-gate void 2570Sstevel@tonic-gate set_gatesegd(gate_desc_t *dp, void (*func)(void), selector_t sel, 2580Sstevel@tonic-gate uint_t wcount, uint_t type, uint_t dpl) 2590Sstevel@tonic-gate { 2600Sstevel@tonic-gate dp->sgd_looffset = (uintptr_t)func; 2610Sstevel@tonic-gate dp->sgd_hioffset = (uintptr_t)func >> 16; 2620Sstevel@tonic-gate 2630Sstevel@tonic-gate dp->sgd_selector = (uint16_t)sel; 2640Sstevel@tonic-gate dp->sgd_stkcpy = wcount; 2650Sstevel@tonic-gate dp->sgd_type = type; 2660Sstevel@tonic-gate dp->sgd_dpl = dpl; 2670Sstevel@tonic-gate dp->sgd_p = 1; 2680Sstevel@tonic-gate } 2690Sstevel@tonic-gate 2700Sstevel@tonic-gate #endif /* __i386 */ 2710Sstevel@tonic-gate 2720Sstevel@tonic-gate /* 2730Sstevel@tonic-gate * Build kernel GDT. 2740Sstevel@tonic-gate */ 2750Sstevel@tonic-gate 2760Sstevel@tonic-gate #if defined(__amd64) 2770Sstevel@tonic-gate 2780Sstevel@tonic-gate static void 2790Sstevel@tonic-gate init_gdt(void) 2800Sstevel@tonic-gate { 2810Sstevel@tonic-gate desctbr_t r_bgdt, r_gdt; 2820Sstevel@tonic-gate user_desc_t *bgdt; 2830Sstevel@tonic-gate size_t alen = 0xfffff; /* entire 32-bit address space */ 2840Sstevel@tonic-gate 2850Sstevel@tonic-gate /* 2860Sstevel@tonic-gate * Copy in from boot's gdt to our gdt entries 1 - 4. 2870Sstevel@tonic-gate * Entry 0 is the null descriptor by definition. 2880Sstevel@tonic-gate */ 2890Sstevel@tonic-gate rd_gdtr(&r_bgdt); 2900Sstevel@tonic-gate bgdt = (user_desc_t *)r_bgdt.dtr_base; 2910Sstevel@tonic-gate if (bgdt == NULL) 2920Sstevel@tonic-gate panic("null boot gdt"); 2930Sstevel@tonic-gate 2940Sstevel@tonic-gate gdt0[GDT_B32DATA] = bgdt[GDT_B32DATA]; 2950Sstevel@tonic-gate gdt0[GDT_B32CODE] = bgdt[GDT_B32CODE]; 2960Sstevel@tonic-gate gdt0[GDT_B64DATA] = bgdt[GDT_B64DATA]; 2970Sstevel@tonic-gate gdt0[GDT_B64CODE] = bgdt[GDT_B64CODE]; 2980Sstevel@tonic-gate 2990Sstevel@tonic-gate /* 3000Sstevel@tonic-gate * 64-bit kernel code segment. 3010Sstevel@tonic-gate */ 3020Sstevel@tonic-gate set_usegd(&gdt0[GDT_KCODE], SDP_LONG, NULL, 0, SDT_MEMERA, SEL_KPL, 3030Sstevel@tonic-gate SDP_PAGES, SDP_OP32); 3040Sstevel@tonic-gate 3050Sstevel@tonic-gate /* 3060Sstevel@tonic-gate * 64-bit kernel data segment. The limit attribute is ignored in 64-bit 3070Sstevel@tonic-gate * mode, but we set it here to 0xFFFF so that we can use the SYSRET 3080Sstevel@tonic-gate * instruction to return from system calls back to 32-bit applications. 3090Sstevel@tonic-gate * SYSRET doesn't update the base, limit, or attributes of %ss or %ds 3100Sstevel@tonic-gate * descriptors. We therefore must ensure that the kernel uses something, 3110Sstevel@tonic-gate * though it will be ignored by hardware, that is compatible with 32-bit 3120Sstevel@tonic-gate * apps. For the same reason we must set the default op size of this 3130Sstevel@tonic-gate * descriptor to 32-bit operands. 3140Sstevel@tonic-gate */ 3150Sstevel@tonic-gate set_usegd(&gdt0[GDT_KDATA], SDP_LONG, NULL, alen, SDT_MEMRWA, 3160Sstevel@tonic-gate SEL_KPL, SDP_PAGES, SDP_OP32); 3170Sstevel@tonic-gate gdt0[GDT_KDATA].usd_def32 = 1; 3180Sstevel@tonic-gate 3190Sstevel@tonic-gate /* 3200Sstevel@tonic-gate * 64-bit user code segment. 3210Sstevel@tonic-gate */ 3220Sstevel@tonic-gate set_usegd(&gdt0[GDT_UCODE], SDP_LONG, NULL, 0, SDT_MEMERA, SEL_UPL, 3230Sstevel@tonic-gate SDP_PAGES, SDP_OP32); 3240Sstevel@tonic-gate 3250Sstevel@tonic-gate /* 3260Sstevel@tonic-gate * 32-bit user code segment. 3270Sstevel@tonic-gate */ 3280Sstevel@tonic-gate set_usegd(&gdt0[GDT_U32CODE], SDP_SHORT, NULL, alen, SDT_MEMERA, 3290Sstevel@tonic-gate SEL_UPL, SDP_PAGES, SDP_OP32); 3300Sstevel@tonic-gate 3310Sstevel@tonic-gate /* 3320Sstevel@tonic-gate * 32 and 64 bit data segments can actually share the same descriptor. 3330Sstevel@tonic-gate * In long mode only the present bit is checked but all other fields 3340Sstevel@tonic-gate * are loaded. But in compatibility mode all fields are interpreted 3350Sstevel@tonic-gate * as in legacy mode so they must be set correctly for a 32-bit data 3360Sstevel@tonic-gate * segment. 3370Sstevel@tonic-gate */ 3380Sstevel@tonic-gate set_usegd(&gdt0[GDT_UDATA], SDP_SHORT, NULL, alen, SDT_MEMRWA, SEL_UPL, 3390Sstevel@tonic-gate SDP_PAGES, SDP_OP32); 3400Sstevel@tonic-gate 3410Sstevel@tonic-gate /* 342*1217Srab * The 64-bit kernel has no default LDT. By default, the LDT descriptor 343*1217Srab * in the GDT is 0. 3440Sstevel@tonic-gate */ 3450Sstevel@tonic-gate 3460Sstevel@tonic-gate /* 3470Sstevel@tonic-gate * Kernel TSS 3480Sstevel@tonic-gate */ 3490Sstevel@tonic-gate set_syssegd((system_desc_t *)&gdt0[GDT_KTSS], &ktss0, 3500Sstevel@tonic-gate sizeof (ktss0) - 1, SDT_SYSTSS, SEL_KPL); 3510Sstevel@tonic-gate 3520Sstevel@tonic-gate /* 3530Sstevel@tonic-gate * Initialize fs and gs descriptors for 32 bit processes. 3540Sstevel@tonic-gate * Only attributes and limits are initialized, the effective 3550Sstevel@tonic-gate * base address is programmed via fsbase/gsbase. 3560Sstevel@tonic-gate */ 3570Sstevel@tonic-gate set_usegd(&gdt0[GDT_LWPFS], SDP_SHORT, NULL, alen, SDT_MEMRWA, 3580Sstevel@tonic-gate SEL_UPL, SDP_PAGES, SDP_OP32); 3590Sstevel@tonic-gate set_usegd(&gdt0[GDT_LWPGS], SDP_SHORT, NULL, alen, SDT_MEMRWA, 3600Sstevel@tonic-gate SEL_UPL, SDP_PAGES, SDP_OP32); 3610Sstevel@tonic-gate 3620Sstevel@tonic-gate /* 3630Sstevel@tonic-gate * Install our new GDT 3640Sstevel@tonic-gate */ 3650Sstevel@tonic-gate r_gdt.dtr_limit = sizeof (gdt0) - 1; 3660Sstevel@tonic-gate r_gdt.dtr_base = (uintptr_t)gdt0; 3670Sstevel@tonic-gate wr_gdtr(&r_gdt); 3680Sstevel@tonic-gate 3690Sstevel@tonic-gate /* 3700Sstevel@tonic-gate * Initialize convenient zero base user descriptors for clearing 3710Sstevel@tonic-gate * lwp private %fs and %gs descriptors in GDT. See setregs() for 3720Sstevel@tonic-gate * an example. 3730Sstevel@tonic-gate */ 3740Sstevel@tonic-gate set_usegd(&zero_udesc, SDP_LONG, 0, 0, SDT_MEMRWA, SEL_UPL, 3750Sstevel@tonic-gate SDP_BYTES, SDP_OP32); 3760Sstevel@tonic-gate set_usegd(&zero_u32desc, SDP_SHORT, 0, -1, SDT_MEMRWA, SEL_UPL, 3770Sstevel@tonic-gate SDP_PAGES, SDP_OP32); 3780Sstevel@tonic-gate } 3790Sstevel@tonic-gate 3800Sstevel@tonic-gate #elif defined(__i386) 3810Sstevel@tonic-gate 3820Sstevel@tonic-gate static void 3830Sstevel@tonic-gate init_gdt(void) 3840Sstevel@tonic-gate { 3850Sstevel@tonic-gate desctbr_t r_bgdt, r_gdt; 3860Sstevel@tonic-gate user_desc_t *bgdt; 3870Sstevel@tonic-gate 3880Sstevel@tonic-gate /* 3890Sstevel@tonic-gate * Copy in from boot's gdt to our gdt entries 1 - 4. 3900Sstevel@tonic-gate * Entry 0 is null descriptor by definition. 3910Sstevel@tonic-gate */ 3920Sstevel@tonic-gate rd_gdtr(&r_bgdt); 3930Sstevel@tonic-gate bgdt = (user_desc_t *)r_bgdt.dtr_base; 3940Sstevel@tonic-gate if (bgdt == NULL) 3950Sstevel@tonic-gate panic("null boot gdt"); 3960Sstevel@tonic-gate 3970Sstevel@tonic-gate gdt0[GDT_BOOTFLAT] = bgdt[GDT_BOOTFLAT]; 3980Sstevel@tonic-gate gdt0[GDT_BOOTCODE] = bgdt[GDT_BOOTCODE]; 3990Sstevel@tonic-gate gdt0[GDT_BOOTCODE16] = bgdt[GDT_BOOTCODE16]; 4000Sstevel@tonic-gate gdt0[GDT_BOOTDATA] = bgdt[GDT_BOOTDATA]; 4010Sstevel@tonic-gate 4020Sstevel@tonic-gate /* 4030Sstevel@tonic-gate * Text and data for both kernel and user span entire 32 bit 4040Sstevel@tonic-gate * address space. 4050Sstevel@tonic-gate */ 4060Sstevel@tonic-gate 4070Sstevel@tonic-gate /* 4080Sstevel@tonic-gate * kernel code segment. 4090Sstevel@tonic-gate */ 4100Sstevel@tonic-gate set_usegd(&gdt0[GDT_KCODE], NULL, -1, SDT_MEMERA, SEL_KPL, SDP_PAGES, 4110Sstevel@tonic-gate SDP_OP32); 4120Sstevel@tonic-gate 4130Sstevel@tonic-gate /* 4140Sstevel@tonic-gate * kernel data segment. 4150Sstevel@tonic-gate */ 4160Sstevel@tonic-gate set_usegd(&gdt0[GDT_KDATA], NULL, -1, SDT_MEMRWA, SEL_KPL, SDP_PAGES, 4170Sstevel@tonic-gate SDP_OP32); 4180Sstevel@tonic-gate 4190Sstevel@tonic-gate /* 4200Sstevel@tonic-gate * user code segment. 4210Sstevel@tonic-gate */ 4220Sstevel@tonic-gate set_usegd(&gdt0[GDT_UCODE], NULL, -1, SDT_MEMERA, SEL_UPL, SDP_PAGES, 4230Sstevel@tonic-gate SDP_OP32); 4240Sstevel@tonic-gate 4250Sstevel@tonic-gate /* 4260Sstevel@tonic-gate * user data segment. 4270Sstevel@tonic-gate */ 4280Sstevel@tonic-gate set_usegd(&gdt0[GDT_UDATA], NULL, -1, SDT_MEMRWA, SEL_UPL, SDP_PAGES, 4290Sstevel@tonic-gate SDP_OP32); 4300Sstevel@tonic-gate 4310Sstevel@tonic-gate /* 4320Sstevel@tonic-gate * TSS for T_DBLFLT (double fault) handler 4330Sstevel@tonic-gate */ 4340Sstevel@tonic-gate set_syssegd((system_desc_t *)&gdt0[GDT_DBFLT], &dftss0, 4350Sstevel@tonic-gate sizeof (dftss0) - 1, SDT_SYSTSS, SEL_KPL); 4360Sstevel@tonic-gate 4370Sstevel@tonic-gate /* 4380Sstevel@tonic-gate * TSS for kernel 4390Sstevel@tonic-gate */ 4400Sstevel@tonic-gate set_syssegd((system_desc_t *)&gdt0[GDT_KTSS], &ktss0, 4410Sstevel@tonic-gate sizeof (ktss0) - 1, SDT_SYSTSS, SEL_KPL); 4420Sstevel@tonic-gate 4430Sstevel@tonic-gate /* 4440Sstevel@tonic-gate * %gs selector for kernel 4450Sstevel@tonic-gate */ 4460Sstevel@tonic-gate set_usegd(&gdt0[GDT_GS], &cpus[0], sizeof (struct cpu) -1, SDT_MEMRWA, 4470Sstevel@tonic-gate SEL_KPL, SDP_BYTES, SDP_OP32); 4480Sstevel@tonic-gate 4490Sstevel@tonic-gate /* 4500Sstevel@tonic-gate * Initialize lwp private descriptors. 4510Sstevel@tonic-gate * Only attributes and limits are initialized, the effective 4520Sstevel@tonic-gate * base address is programmed via fsbase/gsbase. 4530Sstevel@tonic-gate */ 4540Sstevel@tonic-gate set_usegd(&gdt0[GDT_LWPFS], NULL, (size_t)-1, SDT_MEMRWA, SEL_UPL, 4550Sstevel@tonic-gate SDP_PAGES, SDP_OP32); 4560Sstevel@tonic-gate set_usegd(&gdt0[GDT_LWPGS], NULL, (size_t)-1, SDT_MEMRWA, SEL_UPL, 4570Sstevel@tonic-gate SDP_PAGES, SDP_OP32); 4580Sstevel@tonic-gate 4590Sstevel@tonic-gate /* 4600Sstevel@tonic-gate * Install our new GDT 4610Sstevel@tonic-gate */ 4620Sstevel@tonic-gate r_gdt.dtr_limit = sizeof (gdt0) - 1; 4630Sstevel@tonic-gate r_gdt.dtr_base = (uintptr_t)gdt0; 4640Sstevel@tonic-gate wr_gdtr(&r_gdt); 4650Sstevel@tonic-gate 4660Sstevel@tonic-gate /* 4670Sstevel@tonic-gate * Initialize convenient zero base user descriptors for clearing 4680Sstevel@tonic-gate * lwp private %fs and %gs descriptors in GDT. See setregs() for 4690Sstevel@tonic-gate * an example. 4700Sstevel@tonic-gate */ 4710Sstevel@tonic-gate set_usegd(&zero_udesc, 0, -1, SDT_MEMRWA, SEL_UPL, SDP_PAGES, SDP_OP32); 4720Sstevel@tonic-gate } 4730Sstevel@tonic-gate 4740Sstevel@tonic-gate #endif /* __i386 */ 4750Sstevel@tonic-gate 4760Sstevel@tonic-gate #if defined(__amd64) 4770Sstevel@tonic-gate 4780Sstevel@tonic-gate /* 4790Sstevel@tonic-gate * Build kernel IDT. 4800Sstevel@tonic-gate * 4810Sstevel@tonic-gate * Note that we pretty much require every gate to be an interrupt gate; 4820Sstevel@tonic-gate * that's because of our dependency on using 'swapgs' every time we come 4830Sstevel@tonic-gate * into the kernel to find the cpu structure - if we get interrupted just 4840Sstevel@tonic-gate * before doing that, so that %cs is in kernel mode (so that the trap prolog 4850Sstevel@tonic-gate * doesn't do a swapgs), but %gsbase is really still pointing at something 4860Sstevel@tonic-gate * in userland, bad things ensue. 4870Sstevel@tonic-gate * 4880Sstevel@tonic-gate * Perhaps they should have invented a trap gate that does an atomic swapgs? 4890Sstevel@tonic-gate * 4900Sstevel@tonic-gate * XX64 We do need to think further about the follow-on impact of this. 4910Sstevel@tonic-gate * Most of the kernel handlers re-enable interrupts as soon as they've 4920Sstevel@tonic-gate * saved register state and done the swapgs, but there may be something 4930Sstevel@tonic-gate * more subtle going on. 4940Sstevel@tonic-gate */ 4950Sstevel@tonic-gate static void 4960Sstevel@tonic-gate init_idt(void) 4970Sstevel@tonic-gate { 4980Sstevel@tonic-gate char ivctname[80]; 4990Sstevel@tonic-gate void (*ivctptr)(void); 5000Sstevel@tonic-gate int i; 5010Sstevel@tonic-gate 5020Sstevel@tonic-gate /* 5030Sstevel@tonic-gate * Initialize entire table with 'reserved' trap and then overwrite 5040Sstevel@tonic-gate * specific entries. T_EXTOVRFLT (9) is unsupported and reserved 5050Sstevel@tonic-gate * since it can only be generated on a 386 processor. 15 is also 5060Sstevel@tonic-gate * unsupported and reserved. 5070Sstevel@tonic-gate */ 5080Sstevel@tonic-gate for (i = 0; i < NIDT; i++) 5090Sstevel@tonic-gate set_gatesegd(&idt0[i], &resvtrap, KCS_SEL, 0, SDT_SYSIGT, 5100Sstevel@tonic-gate SEL_KPL); 5110Sstevel@tonic-gate 5120Sstevel@tonic-gate set_gatesegd(&idt0[T_ZERODIV], &div0trap, KCS_SEL, 0, SDT_SYSIGT, 5130Sstevel@tonic-gate SEL_KPL); 5140Sstevel@tonic-gate set_gatesegd(&idt0[T_SGLSTP], &dbgtrap, KCS_SEL, 0, SDT_SYSIGT, 5150Sstevel@tonic-gate SEL_KPL); 5160Sstevel@tonic-gate set_gatesegd(&idt0[T_NMIFLT], &nmiint, KCS_SEL, 0, SDT_SYSIGT, 5170Sstevel@tonic-gate SEL_KPL); 5180Sstevel@tonic-gate set_gatesegd(&idt0[T_BPTFLT], &brktrap, KCS_SEL, 0, SDT_SYSIGT, 5190Sstevel@tonic-gate SEL_UPL); 5200Sstevel@tonic-gate set_gatesegd(&idt0[T_OVFLW], &ovflotrap, KCS_SEL, 0, SDT_SYSIGT, 5210Sstevel@tonic-gate SEL_UPL); 5220Sstevel@tonic-gate set_gatesegd(&idt0[T_BOUNDFLT], &boundstrap, KCS_SEL, 0, SDT_SYSIGT, 5230Sstevel@tonic-gate SEL_KPL); 5240Sstevel@tonic-gate set_gatesegd(&idt0[T_ILLINST], &invoptrap, KCS_SEL, 0, SDT_SYSIGT, 5250Sstevel@tonic-gate SEL_KPL); 5260Sstevel@tonic-gate set_gatesegd(&idt0[T_NOEXTFLT], &ndptrap, KCS_SEL, 0, SDT_SYSIGT, 5270Sstevel@tonic-gate SEL_KPL); 5280Sstevel@tonic-gate 5290Sstevel@tonic-gate /* 5300Sstevel@tonic-gate * double fault handler. 5310Sstevel@tonic-gate */ 5320Sstevel@tonic-gate set_gatesegd(&idt0[T_DBLFLT], &syserrtrap, KCS_SEL, 1, SDT_SYSIGT, 5330Sstevel@tonic-gate SEL_KPL); 5340Sstevel@tonic-gate 5350Sstevel@tonic-gate /* 5360Sstevel@tonic-gate * T_EXTOVRFLT coprocessor-segment-overrun not supported. 5370Sstevel@tonic-gate */ 5380Sstevel@tonic-gate 5390Sstevel@tonic-gate set_gatesegd(&idt0[T_TSSFLT], &invtsstrap, KCS_SEL, 0, SDT_SYSIGT, 5400Sstevel@tonic-gate SEL_KPL); 5410Sstevel@tonic-gate set_gatesegd(&idt0[T_SEGFLT], &segnptrap, KCS_SEL, 0, SDT_SYSIGT, 5420Sstevel@tonic-gate SEL_KPL); 5430Sstevel@tonic-gate set_gatesegd(&idt0[T_STKFLT], &stktrap, KCS_SEL, 0, SDT_SYSIGT, 5440Sstevel@tonic-gate SEL_KPL); 5450Sstevel@tonic-gate set_gatesegd(&idt0[T_GPFLT], &gptrap, KCS_SEL, 0, SDT_SYSIGT, 5460Sstevel@tonic-gate SEL_KPL); 5470Sstevel@tonic-gate set_gatesegd(&idt0[T_PGFLT], &pftrap, KCS_SEL, 0, SDT_SYSIGT, 5480Sstevel@tonic-gate SEL_KPL); 5490Sstevel@tonic-gate 5500Sstevel@tonic-gate /* 5510Sstevel@tonic-gate * 15 reserved. 5520Sstevel@tonic-gate */ 5530Sstevel@tonic-gate set_gatesegd(&idt0[15], &resvtrap, KCS_SEL, 0, SDT_SYSIGT, SEL_KPL); 5540Sstevel@tonic-gate 5550Sstevel@tonic-gate set_gatesegd(&idt0[T_EXTERRFLT], &ndperr, KCS_SEL, 0, SDT_SYSIGT, 5560Sstevel@tonic-gate SEL_KPL); 5570Sstevel@tonic-gate set_gatesegd(&idt0[T_ALIGNMENT], &achktrap, KCS_SEL, 0, SDT_SYSIGT, 5580Sstevel@tonic-gate SEL_KPL); 5590Sstevel@tonic-gate set_gatesegd(&idt0[T_MCE], &mcetrap, KCS_SEL, 0, SDT_SYSIGT, 5600Sstevel@tonic-gate SEL_KPL); 5610Sstevel@tonic-gate set_gatesegd(&idt0[T_SIMDFPE], &xmtrap, KCS_SEL, 0, SDT_SYSIGT, 5620Sstevel@tonic-gate SEL_KPL); 5630Sstevel@tonic-gate 5640Sstevel@tonic-gate /* 5650Sstevel@tonic-gate * 20-31 reserved 5660Sstevel@tonic-gate */ 5670Sstevel@tonic-gate for (i = 20; i < 32; i++) 5680Sstevel@tonic-gate set_gatesegd(&idt0[i], &invaltrap, KCS_SEL, 0, SDT_SYSIGT, 5690Sstevel@tonic-gate SEL_KPL); 5700Sstevel@tonic-gate 5710Sstevel@tonic-gate /* 5720Sstevel@tonic-gate * interrupts 32 - 255 5730Sstevel@tonic-gate */ 5740Sstevel@tonic-gate for (i = 32; i < 256; i++) { 5750Sstevel@tonic-gate (void) snprintf(ivctname, sizeof (ivctname), "ivct%d", i); 5760Sstevel@tonic-gate ivctptr = (void (*)(void))kobj_getsymvalue(ivctname, 0); 5770Sstevel@tonic-gate if (ivctptr == NULL) 5780Sstevel@tonic-gate panic("kobj_getsymvalue(%s) failed", ivctname); 5790Sstevel@tonic-gate 5800Sstevel@tonic-gate set_gatesegd(&idt0[i], ivctptr, KCS_SEL, 0, SDT_SYSIGT, 5810Sstevel@tonic-gate SEL_KPL); 5820Sstevel@tonic-gate } 5830Sstevel@tonic-gate 5840Sstevel@tonic-gate /* 5850Sstevel@tonic-gate * install fast trap handler at 210. 5860Sstevel@tonic-gate */ 5870Sstevel@tonic-gate set_gatesegd(&idt0[T_FASTTRAP], &fasttrap, KCS_SEL, 0, 5880Sstevel@tonic-gate SDT_SYSIGT, SEL_UPL); 5890Sstevel@tonic-gate 5900Sstevel@tonic-gate /* 5910Sstevel@tonic-gate * System call handler. 5920Sstevel@tonic-gate */ 5930Sstevel@tonic-gate set_gatesegd(&idt0[T_SYSCALLINT], &sys_syscall_int, KCS_SEL, 0, 5940Sstevel@tonic-gate SDT_SYSIGT, SEL_UPL); 5950Sstevel@tonic-gate 5960Sstevel@tonic-gate /* 5970Sstevel@tonic-gate * Install the DTrace interrupt handlers for the fasttrap provider. 5980Sstevel@tonic-gate */ 5990Sstevel@tonic-gate set_gatesegd(&idt0[T_DTRACE_PROBE], &dtrace_fasttrap, KCS_SEL, 0, 6000Sstevel@tonic-gate SDT_SYSIGT, SEL_UPL); 6010Sstevel@tonic-gate set_gatesegd(&idt0[T_DTRACE_RET], &dtrace_ret, KCS_SEL, 0, 6020Sstevel@tonic-gate SDT_SYSIGT, SEL_UPL); 6030Sstevel@tonic-gate 6040Sstevel@tonic-gate if (boothowto & RB_DEBUG) 6050Sstevel@tonic-gate kdi_dvec_idt_sync(idt0); 6060Sstevel@tonic-gate 6070Sstevel@tonic-gate /* 6080Sstevel@tonic-gate * We must maintain a description of idt0 in convenient IDTR format 6090Sstevel@tonic-gate * for use by T_NMIFLT and T_PGFLT (nmiint() and pentium_pftrap()) 6100Sstevel@tonic-gate * handlers. 6110Sstevel@tonic-gate */ 6120Sstevel@tonic-gate idt0_default_r.dtr_limit = sizeof (idt0) - 1; 6130Sstevel@tonic-gate idt0_default_r.dtr_base = (uintptr_t)idt0; 6140Sstevel@tonic-gate wr_idtr(&idt0_default_r); 6150Sstevel@tonic-gate } 6160Sstevel@tonic-gate 6170Sstevel@tonic-gate #elif defined(__i386) 6180Sstevel@tonic-gate 6190Sstevel@tonic-gate /* 6200Sstevel@tonic-gate * Build kernel IDT. 6210Sstevel@tonic-gate */ 6220Sstevel@tonic-gate static void 6230Sstevel@tonic-gate init_idt(void) 6240Sstevel@tonic-gate { 6250Sstevel@tonic-gate char ivctname[80]; 6260Sstevel@tonic-gate void (*ivctptr)(void); 6270Sstevel@tonic-gate int i; 6280Sstevel@tonic-gate 6290Sstevel@tonic-gate /* 6300Sstevel@tonic-gate * Initialize entire table with 'reserved' trap and then overwrite 6310Sstevel@tonic-gate * specific entries. T_EXTOVRFLT (9) is unsupported and reserved 6320Sstevel@tonic-gate * since it can only be generated on a 386 processor. 15 is also 6330Sstevel@tonic-gate * unsupported and reserved. 6340Sstevel@tonic-gate */ 6350Sstevel@tonic-gate for (i = 0; i < NIDT; i++) 6360Sstevel@tonic-gate set_gatesegd(&idt0[i], &resvtrap, KCS_SEL, 0, SDT_SYSTGT, 6370Sstevel@tonic-gate SEL_KPL); 6380Sstevel@tonic-gate 6390Sstevel@tonic-gate set_gatesegd(&idt0[T_ZERODIV], &div0trap, KCS_SEL, 0, SDT_SYSTGT, 6400Sstevel@tonic-gate SEL_KPL); 6410Sstevel@tonic-gate set_gatesegd(&idt0[T_SGLSTP], &dbgtrap, KCS_SEL, 0, SDT_SYSIGT, 6420Sstevel@tonic-gate SEL_KPL); 6430Sstevel@tonic-gate set_gatesegd(&idt0[T_NMIFLT], &nmiint, KCS_SEL, 0, SDT_SYSIGT, 6440Sstevel@tonic-gate SEL_KPL); 6450Sstevel@tonic-gate set_gatesegd(&idt0[T_BPTFLT], &brktrap, KCS_SEL, 0, SDT_SYSTGT, 6460Sstevel@tonic-gate SEL_UPL); 6470Sstevel@tonic-gate set_gatesegd(&idt0[T_OVFLW], &ovflotrap, KCS_SEL, 0, SDT_SYSTGT, 6480Sstevel@tonic-gate SEL_UPL); 6490Sstevel@tonic-gate set_gatesegd(&idt0[T_BOUNDFLT], &boundstrap, KCS_SEL, 0, SDT_SYSTGT, 6500Sstevel@tonic-gate SEL_KPL); 6510Sstevel@tonic-gate set_gatesegd(&idt0[T_ILLINST], &invoptrap, KCS_SEL, 0, SDT_SYSIGT, 6520Sstevel@tonic-gate SEL_KPL); 6530Sstevel@tonic-gate set_gatesegd(&idt0[T_NOEXTFLT], &ndptrap, KCS_SEL, 0, SDT_SYSIGT, 6540Sstevel@tonic-gate SEL_KPL); 6550Sstevel@tonic-gate 6560Sstevel@tonic-gate /* 6570Sstevel@tonic-gate * Install TSS for T_DBLFLT handler. 6580Sstevel@tonic-gate */ 6590Sstevel@tonic-gate set_gatesegd(&idt0[T_DBLFLT], NULL, DFTSS_SEL, 0, SDT_SYSTASKGT, 6600Sstevel@tonic-gate SEL_KPL); 6610Sstevel@tonic-gate 6620Sstevel@tonic-gate /* 6630Sstevel@tonic-gate * T_EXTOVRFLT coprocessor-segment-overrun not supported. 6640Sstevel@tonic-gate */ 6650Sstevel@tonic-gate 6660Sstevel@tonic-gate set_gatesegd(&idt0[T_TSSFLT], &invtsstrap, KCS_SEL, 0, SDT_SYSTGT, 6670Sstevel@tonic-gate SEL_KPL); 6680Sstevel@tonic-gate set_gatesegd(&idt0[T_SEGFLT], &segnptrap, KCS_SEL, 0, SDT_SYSTGT, 6690Sstevel@tonic-gate SEL_KPL); 6700Sstevel@tonic-gate set_gatesegd(&idt0[T_STKFLT], &stktrap, KCS_SEL, 0, SDT_SYSTGT, 6710Sstevel@tonic-gate SEL_KPL); 6720Sstevel@tonic-gate set_gatesegd(&idt0[T_GPFLT], &gptrap, KCS_SEL, 0, SDT_SYSTGT, 6730Sstevel@tonic-gate SEL_KPL); 6740Sstevel@tonic-gate set_gatesegd(&idt0[T_PGFLT], &pftrap, KCS_SEL, 0, SDT_SYSIGT, 6750Sstevel@tonic-gate SEL_KPL); 6760Sstevel@tonic-gate 6770Sstevel@tonic-gate /* 6780Sstevel@tonic-gate * 15 reserved. 6790Sstevel@tonic-gate */ 6800Sstevel@tonic-gate set_gatesegd(&idt0[15], &resvtrap, KCS_SEL, 0, SDT_SYSTGT, SEL_KPL); 6810Sstevel@tonic-gate 6820Sstevel@tonic-gate set_gatesegd(&idt0[T_EXTERRFLT], &ndperr, KCS_SEL, 0, SDT_SYSIGT, 6830Sstevel@tonic-gate SEL_KPL); 6840Sstevel@tonic-gate set_gatesegd(&idt0[T_ALIGNMENT], &achktrap, KCS_SEL, 0, SDT_SYSTGT, 6850Sstevel@tonic-gate SEL_KPL); 6860Sstevel@tonic-gate set_gatesegd(&idt0[T_MCE], &mcetrap, KCS_SEL, 0, SDT_SYSIGT, 6870Sstevel@tonic-gate SEL_KPL); 6880Sstevel@tonic-gate set_gatesegd(&idt0[T_SIMDFPE], &xmtrap, KCS_SEL, 0, SDT_SYSTGT, 6890Sstevel@tonic-gate SEL_KPL); 6900Sstevel@tonic-gate 6910Sstevel@tonic-gate /* 6920Sstevel@tonic-gate * 20-31 reserved 6930Sstevel@tonic-gate */ 6940Sstevel@tonic-gate for (i = 20; i < 32; i++) 6950Sstevel@tonic-gate set_gatesegd(&idt0[i], &invaltrap, KCS_SEL, 0, SDT_SYSTGT, 6960Sstevel@tonic-gate SEL_KPL); 6970Sstevel@tonic-gate 6980Sstevel@tonic-gate /* 6990Sstevel@tonic-gate * interrupts 32 - 255 7000Sstevel@tonic-gate */ 7010Sstevel@tonic-gate for (i = 32; i < 256; i++) { 7020Sstevel@tonic-gate (void) snprintf(ivctname, sizeof (ivctname), "ivct%d", i); 7030Sstevel@tonic-gate ivctptr = (void (*)(void))kobj_getsymvalue(ivctname, 0); 7040Sstevel@tonic-gate if (ivctptr == NULL) 7050Sstevel@tonic-gate panic("kobj_getsymvalue(%s) failed", ivctname); 7060Sstevel@tonic-gate 7070Sstevel@tonic-gate set_gatesegd(&idt0[i], ivctptr, KCS_SEL, 0, SDT_SYSIGT, 7080Sstevel@tonic-gate SEL_KPL); 7090Sstevel@tonic-gate } 7100Sstevel@tonic-gate 7110Sstevel@tonic-gate /* 7120Sstevel@tonic-gate * install fast trap handler at 210. 7130Sstevel@tonic-gate */ 7140Sstevel@tonic-gate set_gatesegd(&idt0[T_FASTTRAP], &fasttrap, KCS_SEL, 0, 7150Sstevel@tonic-gate SDT_SYSIGT, SEL_UPL); 7160Sstevel@tonic-gate 7170Sstevel@tonic-gate /* 7180Sstevel@tonic-gate * System call handler. Note that we don't use the hardware's parameter 7190Sstevel@tonic-gate * copying mechanism here; see the comment above sys_call() for details. 7200Sstevel@tonic-gate */ 7210Sstevel@tonic-gate set_gatesegd(&idt0[T_SYSCALLINT], &sys_call, KCS_SEL, 0, 7220Sstevel@tonic-gate SDT_SYSIGT, SEL_UPL); 7230Sstevel@tonic-gate 7240Sstevel@tonic-gate /* 7250Sstevel@tonic-gate * Install the DTrace interrupt handlers for the fasttrap provider. 7260Sstevel@tonic-gate */ 7270Sstevel@tonic-gate set_gatesegd(&idt0[T_DTRACE_PROBE], &dtrace_fasttrap, KCS_SEL, 0, 7280Sstevel@tonic-gate SDT_SYSIGT, SEL_UPL); 7290Sstevel@tonic-gate set_gatesegd(&idt0[T_DTRACE_RET], &dtrace_ret, KCS_SEL, 0, 7300Sstevel@tonic-gate SDT_SYSIGT, SEL_UPL); 7310Sstevel@tonic-gate 7320Sstevel@tonic-gate if (boothowto & RB_DEBUG) 7330Sstevel@tonic-gate kdi_dvec_idt_sync(idt0); 7340Sstevel@tonic-gate 7350Sstevel@tonic-gate /* 7360Sstevel@tonic-gate * We must maintain a description of idt0 in convenient IDTR format 7370Sstevel@tonic-gate * for use by T_NMIFLT and T_PGFLT (nmiint() and pentium_pftrap()) 7380Sstevel@tonic-gate * handlers. 7390Sstevel@tonic-gate */ 7400Sstevel@tonic-gate idt0_default_r.dtr_limit = sizeof (idt0) - 1; 7410Sstevel@tonic-gate idt0_default_r.dtr_base = (uintptr_t)idt0; 7420Sstevel@tonic-gate wr_idtr(&idt0_default_r); 7430Sstevel@tonic-gate } 7440Sstevel@tonic-gate 7450Sstevel@tonic-gate #endif /* __i386 */ 7460Sstevel@tonic-gate 7470Sstevel@tonic-gate /* 748*1217Srab * The kernel does not deal with LDTs unless a user explicitly creates 749*1217Srab * one. Under normal circumstances, the LDTR contains 0. Any process attempting 750*1217Srab * to reference the LDT will therefore cause a #gp. System calls made via the 751*1217Srab * obsolete lcall mechanism are emulated by the #gp fault handler. 7520Sstevel@tonic-gate */ 7530Sstevel@tonic-gate static void 7540Sstevel@tonic-gate init_ldt(void) 7550Sstevel@tonic-gate { 756*1217Srab wr_ldtr(0); 7570Sstevel@tonic-gate } 7580Sstevel@tonic-gate 7590Sstevel@tonic-gate #if defined(__amd64) 7600Sstevel@tonic-gate 7610Sstevel@tonic-gate static void 7620Sstevel@tonic-gate init_tss(void) 7630Sstevel@tonic-gate { 7640Sstevel@tonic-gate /* 7650Sstevel@tonic-gate * tss_rsp0 is dynamically filled in by resume() on each context switch. 7660Sstevel@tonic-gate * All exceptions but #DF will run on the thread stack. 7670Sstevel@tonic-gate * Set up the double fault stack here. 7680Sstevel@tonic-gate */ 7690Sstevel@tonic-gate ktss0.tss_ist1 = 7700Sstevel@tonic-gate (uint64_t)&dblfault_stack0[sizeof (dblfault_stack0)]; 7710Sstevel@tonic-gate 7720Sstevel@tonic-gate /* 7730Sstevel@tonic-gate * Set I/O bit map offset equal to size of TSS segment limit 7740Sstevel@tonic-gate * for no I/O permission map. This will force all user I/O 7750Sstevel@tonic-gate * instructions to generate #gp fault. 7760Sstevel@tonic-gate */ 7770Sstevel@tonic-gate ktss0.tss_bitmapbase = sizeof (ktss0); 7780Sstevel@tonic-gate 7790Sstevel@tonic-gate /* 7800Sstevel@tonic-gate * Point %tr to descriptor for ktss0 in gdt. 7810Sstevel@tonic-gate */ 7820Sstevel@tonic-gate wr_tsr(KTSS_SEL); 7830Sstevel@tonic-gate } 7840Sstevel@tonic-gate 7850Sstevel@tonic-gate #elif defined(__i386) 7860Sstevel@tonic-gate 7870Sstevel@tonic-gate static void 7880Sstevel@tonic-gate init_tss(void) 7890Sstevel@tonic-gate { 7900Sstevel@tonic-gate /* 7910Sstevel@tonic-gate * ktss0.tss_esp dynamically filled in by resume() on each 7920Sstevel@tonic-gate * context switch. 7930Sstevel@tonic-gate */ 7940Sstevel@tonic-gate ktss0.tss_ss0 = KDS_SEL; 7950Sstevel@tonic-gate ktss0.tss_eip = (uint32_t)_start; 7960Sstevel@tonic-gate ktss0.tss_ds = ktss0.tss_es = ktss0.tss_ss = KDS_SEL; 7970Sstevel@tonic-gate ktss0.tss_cs = KCS_SEL; 7980Sstevel@tonic-gate ktss0.tss_fs = KFS_SEL; 7990Sstevel@tonic-gate ktss0.tss_gs = KGS_SEL; 8000Sstevel@tonic-gate ktss0.tss_ldt = ULDT_SEL; 8010Sstevel@tonic-gate 8020Sstevel@tonic-gate /* 8030Sstevel@tonic-gate * Initialize double fault tss. 8040Sstevel@tonic-gate */ 8050Sstevel@tonic-gate dftss0.tss_esp0 = (uint32_t)&dblfault_stack0[sizeof (dblfault_stack0)]; 8060Sstevel@tonic-gate dftss0.tss_ss0 = KDS_SEL; 8070Sstevel@tonic-gate 8080Sstevel@tonic-gate /* 8090Sstevel@tonic-gate * tss_cr3 will get initialized in hat_kern_setup() once our page 8100Sstevel@tonic-gate * tables have been setup. 8110Sstevel@tonic-gate */ 8120Sstevel@tonic-gate dftss0.tss_eip = (uint32_t)syserrtrap; 8130Sstevel@tonic-gate dftss0.tss_esp = (uint32_t)&dblfault_stack0[sizeof (dblfault_stack0)]; 8140Sstevel@tonic-gate dftss0.tss_cs = KCS_SEL; 8150Sstevel@tonic-gate dftss0.tss_ds = KDS_SEL; 8160Sstevel@tonic-gate dftss0.tss_es = KDS_SEL; 8170Sstevel@tonic-gate dftss0.tss_ss = KDS_SEL; 8180Sstevel@tonic-gate dftss0.tss_fs = KFS_SEL; 8190Sstevel@tonic-gate dftss0.tss_gs = KGS_SEL; 8200Sstevel@tonic-gate 8210Sstevel@tonic-gate /* 8220Sstevel@tonic-gate * Set I/O bit map offset equal to size of TSS segment limit 8230Sstevel@tonic-gate * for no I/O permission map. This will force all user I/O 8240Sstevel@tonic-gate * instructions to generate #gp fault. 8250Sstevel@tonic-gate */ 8260Sstevel@tonic-gate ktss0.tss_bitmapbase = sizeof (ktss0); 8270Sstevel@tonic-gate 8280Sstevel@tonic-gate /* 8290Sstevel@tonic-gate * Point %tr to descriptor for ktss0 in gdt. 8300Sstevel@tonic-gate */ 8310Sstevel@tonic-gate wr_tsr(KTSS_SEL); 8320Sstevel@tonic-gate } 8330Sstevel@tonic-gate 8340Sstevel@tonic-gate #endif /* __i386 */ 8350Sstevel@tonic-gate 8360Sstevel@tonic-gate void 8370Sstevel@tonic-gate init_tables(void) 8380Sstevel@tonic-gate { 8390Sstevel@tonic-gate init_gdt(); 8400Sstevel@tonic-gate init_tss(); 8410Sstevel@tonic-gate init_idt(); 8420Sstevel@tonic-gate init_ldt(); 8430Sstevel@tonic-gate } 844