/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * * Copyright 2018 Joyent, Inc. * Copyright 2020 OmniOS Community Edition (OmniOSce) Association. */ /* * Companion to kdi_asm.s - the implementation of the trap and interrupt * handlers. For the most part, these handlers do the same thing - they * push a trap number onto the stack, followed by a jump to kdi_cmnint. * Each trap and interrupt has its own handler because each one pushes a * different number. */ #include #include #include #include #include #include #include #include #include /* * The default ASM_ENTRY_ALIGN (16) wastes far too much space. */ #undef ASM_ENTRY_ALIGN #define ASM_ENTRY_ALIGN 8 /* * Generic trap and interrupt handlers. */ #if defined(__xpv) #define INTERRUPT_TRAMPOLINE #else /* * If we're !xpv, then we will need to support KPTI (kernel page table * isolation), where we have separate page tables for user and kernel modes. * There's more detail about this in kpti_trampolines.s and hat_i86.c */ #define INTERRUPT_TRAMPOLINE \ pushq %r13; \ pushq %r14; \ subq $KPTI_R14, %rsp; \ /* Check for clobbering */ \ cmpq $0, KPTI_FLAG(%rsp); \ je 1f; \ /* Don't worry, this totally works */ \ int $8; \ 1: \ movq $1, KPTI_FLAG(%rsp); \ /* Save current %cr3. */ \ mov %cr3, %r14; \ mov %r14, KPTI_TR_CR3(%rsp); \ /* Switch to paranoid %cr3. */ \ mov kpti_safe_cr3, %r14; \ mov %r14, %cr3; \ \ cmpw $KCS_SEL, KPTI_CS(%rsp); \ je 3f; \ 2: \ /* Get our cpu_t in %r13 */ \ mov %rsp, %r13; \ and $(~(MMU_PAGESIZE - 1)), %r13; \ subq $CPU_KPTI_START, %r13; \ /* Use top of the kthread stk */ \ mov CPU_THREAD(%r13), %r14; \ mov T_STACK(%r14), %r14; \ addq $REGSIZE+MINFRAME, %r14; \ jmp 5f; \ 3: \ /* Check the %rsp in the frame. */ \ /* Is it above kernel base? */ \ mov kpti_kbase, %r14; \ cmp %r14, KPTI_RSP(%rsp); \ jb 2b; \ /* Is it within the kpti_frame page? */ \ mov %rsp, %r13; \ and $(~(MMU_PAGESIZE - 1)), %r13; \ mov KPTI_RSP(%rsp), %r14; \ and $(~(MMU_PAGESIZE - 1)), %r14; \ cmp %r13, %r14; \ je 2b; \ /* Use the %rsp from the trap frame. */ \ /* We already did %cr3. */ \ mov KPTI_RSP(%rsp), %r14; \ and $(~0xf), %r14; \ 5: \ mov %rsp, %r13; \ /* %r14 contains our destination stk */ \ mov %r14, %rsp; \ pushq KPTI_SS(%r13); \ pushq KPTI_RSP(%r13); \ pushq KPTI_RFLAGS(%r13); \ pushq KPTI_CS(%r13); \ pushq KPTI_RIP(%r13); \ pushq KPTI_ERR(%r13); \ mov KPTI_R14(%r13), %r14; \ movq $0, KPTI_FLAG(%r13); \ mov KPTI_R13(%r13), %r13 #endif /* !__xpv */ #define MKIVCT(n) \ ENTRY_NP(kdi_ivct##n); \ XPV_TRAP_POP; \ push $0; /* err */ \ INTERRUPT_TRAMPOLINE; \ push $n; \ jmp kdi_cmnint; \ SET_SIZE(kdi_ivct##n) #define MKTRAPHDLR(n) \ ENTRY_NP(kdi_trap##n); \ XPV_TRAP_POP; \ push $0; /* err */ \ INTERRUPT_TRAMPOLINE; \ push $n; \ jmp kdi_cmnint; \ SET_SIZE(kdi_trap##n) #define MKTRAPERRHDLR(n) \ ENTRY_NP(kdi_traperr##n); \ XPV_TRAP_POP; \ INTERRUPT_TRAMPOLINE; \ push $n; \ jmp kdi_cmnint; \ SET_SIZE(kdi_traperr##n) #if !defined(__xpv) #define MKNMIHDLR \ ENTRY_NP(kdi_int2); \ push $0; \ push $2; \ pushq %r13; \ mov kpti_safe_cr3, %r13; \ mov %r13, %cr3; \ popq %r13; \ jmp kdi_nmiint; \ SET_SIZE(kdi_int2) #define MKMCEHDLR \ ENTRY_NP(kdi_trap18); \ push $0; \ push $18; \ pushq %r13; \ mov kpti_safe_cr3, %r13; \ mov %r13, %cr3; \ popq %r13; \ jmp kdi_cmnint; \ SET_SIZE(kdi_trap18) #else #define MKNMIHDLR \ ENTRY_NP(kdi_int2); \ push $0; \ push $2; \ jmp kdi_nmiint; \ SET_SIZE(kdi_int2) #define MKMCEHDLR \ ENTRY_NP(kdi_trap18); \ push $0; \ push $18; \ jmp kdi_cmnint; \ SET_SIZE(kdi_trap18) #endif /* * The only way we should reach here is by an explicit "int 0x.." which is * defined not to push an error code. */ #define MKINVALHDLR \ ENTRY_NP(kdi_invaltrap); \ XPV_TRAP_POP; \ push $0; /* err */ \ INTERRUPT_TRAMPOLINE; \ push $255; \ jmp kdi_cmnint; \ SET_SIZE(kdi_invaltrap) .data DGDEF3(kdi_idt, 16 * NIDT, MMU_PAGESIZE) .fill MMU_PAGESIZE, 1, 0 #if !defined(__xpv) .section ".text" .align MMU_PAGESIZE .global kdi_isr_start kdi_isr_start: nop .global kpti_safe_cr3 .global kpti_kbase #endif /* * The handlers themselves */ MKINVALHDLR MKTRAPHDLR(0) MKTRAPHDLR(1) MKNMIHDLR/*2*/ MKTRAPHDLR(3) MKTRAPHDLR(4) MKTRAPHDLR(5) MKTRAPHDLR(6) MKTRAPHDLR(7) MKTRAPHDLR(9) MKTRAPHDLR(15) MKTRAPHDLR(16) MKMCEHDLR/*18*/ MKTRAPHDLR(19) MKTRAPHDLR(20) MKTRAPERRHDLR(8) MKTRAPERRHDLR(10) MKTRAPERRHDLR(11) MKTRAPERRHDLR(12) MKTRAPERRHDLR(13) MKTRAPERRHDLR(14) MKTRAPERRHDLR(17) .globl kdi_ivct_size kdi_ivct_size: .NWORD [kdi_ivct33-kdi_ivct32] /* 10 billion and one interrupt handlers */ kdi_ivct_base: MKIVCT(32); MKIVCT(33); MKIVCT(34); MKIVCT(35); MKIVCT(36); MKIVCT(37); MKIVCT(38); MKIVCT(39); MKIVCT(40); MKIVCT(41); MKIVCT(42); MKIVCT(43); MKIVCT(44); MKIVCT(45); MKIVCT(46); MKIVCT(47); MKIVCT(48); MKIVCT(49); MKIVCT(50); MKIVCT(51); MKIVCT(52); MKIVCT(53); MKIVCT(54); MKIVCT(55); MKIVCT(56); MKIVCT(57); MKIVCT(58); MKIVCT(59); MKIVCT(60); MKIVCT(61); MKIVCT(62); MKIVCT(63); MKIVCT(64); MKIVCT(65); MKIVCT(66); MKIVCT(67); MKIVCT(68); MKIVCT(69); MKIVCT(70); MKIVCT(71); MKIVCT(72); MKIVCT(73); MKIVCT(74); MKIVCT(75); MKIVCT(76); MKIVCT(77); MKIVCT(78); MKIVCT(79); MKIVCT(80); MKIVCT(81); MKIVCT(82); MKIVCT(83); MKIVCT(84); MKIVCT(85); MKIVCT(86); MKIVCT(87); MKIVCT(88); MKIVCT(89); MKIVCT(90); MKIVCT(91); MKIVCT(92); MKIVCT(93); MKIVCT(94); MKIVCT(95); MKIVCT(96); MKIVCT(97); MKIVCT(98); MKIVCT(99); MKIVCT(100); MKIVCT(101); MKIVCT(102); MKIVCT(103); MKIVCT(104); MKIVCT(105); MKIVCT(106); MKIVCT(107); MKIVCT(108); MKIVCT(109); MKIVCT(110); MKIVCT(111); MKIVCT(112); MKIVCT(113); MKIVCT(114); MKIVCT(115); MKIVCT(116); MKIVCT(117); MKIVCT(118); MKIVCT(119); MKIVCT(120); MKIVCT(121); MKIVCT(122); MKIVCT(123); MKIVCT(124); MKIVCT(125); MKIVCT(126); MKIVCT(127); MKIVCT(128); MKIVCT(129); MKIVCT(130); MKIVCT(131); MKIVCT(132); MKIVCT(133); MKIVCT(134); MKIVCT(135); MKIVCT(136); MKIVCT(137); MKIVCT(138); MKIVCT(139); MKIVCT(140); MKIVCT(141); MKIVCT(142); MKIVCT(143); MKIVCT(144); MKIVCT(145); MKIVCT(146); MKIVCT(147); MKIVCT(148); MKIVCT(149); MKIVCT(150); MKIVCT(151); MKIVCT(152); MKIVCT(153); MKIVCT(154); MKIVCT(155); MKIVCT(156); MKIVCT(157); MKIVCT(158); MKIVCT(159); MKIVCT(160); MKIVCT(161); MKIVCT(162); MKIVCT(163); MKIVCT(164); MKIVCT(165); MKIVCT(166); MKIVCT(167); MKIVCT(168); MKIVCT(169); MKIVCT(170); MKIVCT(171); MKIVCT(172); MKIVCT(173); MKIVCT(174); MKIVCT(175); MKIVCT(176); MKIVCT(177); MKIVCT(178); MKIVCT(179); MKIVCT(180); MKIVCT(181); MKIVCT(182); MKIVCT(183); MKIVCT(184); MKIVCT(185); MKIVCT(186); MKIVCT(187); MKIVCT(188); MKIVCT(189); MKIVCT(190); MKIVCT(191); MKIVCT(192); MKIVCT(193); MKIVCT(194); MKIVCT(195); MKIVCT(196); MKIVCT(197); MKIVCT(198); MKIVCT(199); MKIVCT(200); MKIVCT(201); MKIVCT(202); MKIVCT(203); MKIVCT(204); MKIVCT(205); MKIVCT(206); MKIVCT(207); MKIVCT(208); MKIVCT(209); MKIVCT(210); MKIVCT(211); MKIVCT(212); MKIVCT(213); MKIVCT(214); MKIVCT(215); MKIVCT(216); MKIVCT(217); MKIVCT(218); MKIVCT(219); MKIVCT(220); MKIVCT(221); MKIVCT(222); MKIVCT(223); MKIVCT(224); MKIVCT(225); MKIVCT(226); MKIVCT(227); MKIVCT(228); MKIVCT(229); MKIVCT(230); MKIVCT(231); MKIVCT(232); MKIVCT(233); MKIVCT(234); MKIVCT(235); MKIVCT(236); MKIVCT(237); MKIVCT(238); MKIVCT(239); MKIVCT(240); MKIVCT(241); MKIVCT(242); MKIVCT(243); MKIVCT(244); MKIVCT(245); MKIVCT(246); MKIVCT(247); MKIVCT(248); MKIVCT(249); MKIVCT(250); MKIVCT(251); MKIVCT(252); MKIVCT(253); MKIVCT(254); MKIVCT(255); #if !defined(__xpv) .section ".text" .align MMU_PAGESIZE .global kdi_isr_end kdi_isr_end: nop #endif