xref: /onnv-gate/usr/src/uts/intel/ia32/os/desctbls.c (revision 1217:f95ffdc997b7)
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