Print this page
8956 Implement KPTI
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: Robert Mustacchi <rm@joyent.com>


   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright (c) 2012, Joyent, Inc.  All rights reserverd.
  25  */
  26 
  27 /*
  28  * To understand the present state of interrupt handling on i86pc, we must
  29  * first consider the history of interrupt controllers and our way of handling
  30  * interrupts.
  31  *
  32  * History of Interrupt Controllers on i86pc
  33  * -----------------------------------------
  34  *
  35  *    Intel 8259 and 8259A
  36  *
  37  * The first interrupt controller that attained widespread use on i86pc was
  38  * the Intel 8259(A) Programmable Interrupt Controller that first saw use with
  39  * the 8086. It took up to 8 interrupt sources and combined them into one
  40  * output wire. Up to 8 8259s could be slaved together providing up to 64 IRQs.
  41  * With the switch to the 8259A, level mode interrupts became possible. For a
  42  * long time on i86pc the 8259A was the only way to handle interrupts and it
  43  * had its own set of quirks. The 8259A and its corresponding interval timer
  44  * the 8254 are programmed using outb and inb instructions.


 454 #include <sys/disp.h>
 455 #include <vm/seg_kp.h>
 456 #include <sys/stack.h>
 457 #include <sys/sysmacros.h>
 458 #include <sys/cmn_err.h>
 459 #include <sys/kstat.h>
 460 #include <sys/smp_impldefs.h>
 461 #include <sys/pool_pset.h>
 462 #include <sys/zone.h>
 463 #include <sys/bitmap.h>
 464 #include <sys/archsystm.h>
 465 #include <sys/machsystm.h>
 466 #include <sys/ontrap.h>
 467 #include <sys/x86_archext.h>
 468 #include <sys/promif.h>
 469 #include <vm/hat_i86.h>
 470 #if defined(__xpv)
 471 #include <sys/hypervisor.h>
 472 #endif
 473 















 474 
 475 #if defined(__xpv) && defined(DEBUG)
 476 
 477 /*
 478  * This panic message is intended as an aid to interrupt debugging.
 479  *
 480  * The associated assertion tests the condition of enabling
 481  * events when events are already enabled.  The implication
 482  * being that whatever code the programmer thought was
 483  * protected by having events disabled until the second
 484  * enable happened really wasn't protected at all ..
 485  */
 486 
 487 int stistipanic = 1;    /* controls the debug panic check */
 488 const char *stistimsg = "stisti";
 489 ulong_t laststi[NCPU];
 490 
 491 /*
 492  * This variable tracks the last place events were disabled on each cpu
 493  * it assists in debugging when asserts that interrupts are enabled trip.


1456                         /*
1457                          * 1 or more of the selectors is bad.
1458                          * Deliver a SIGSEGV.
1459                          */
1460                         proc_t *p = ttoproc(tp);
1461 
1462                         sti();
1463                         mutex_enter(&p->p_lock);
1464                         tp->t_lwp->lwp_cursig = SIGSEGV;
1465                         mutex_exit(&p->p_lock);
1466                         psig();
1467                         tp->t_sig_check = 1;
1468                         cli();
1469                 }
1470                 tp->t_lwp->lwp_pcb.pcb_rupdate = 0;
1471 
1472 #endif  /* __amd64 */
1473                 return (1);
1474         }
1475 

1476         /*














1477          * Here if we are returning to supervisor mode.
1478          * Check for a kernel preemption request.
1479          */
1480         if (CPU->cpu_kprunrun && (rp->r_ps & PS_IE)) {
1481 
1482                 /*
1483                  * Do nothing if already in kpreempt
1484                  */
1485                 if (!tp->t_preempt_lk) {
1486                         tp->t_preempt_lk = 1;
1487                         sti();
1488                         kpreempt(1); /* asynchronous kpreempt call */
1489                         cli();
1490                         tp->t_preempt_lk = 0;
1491                 }
1492         }
1493 
1494         /*
1495          * If we interrupted the mutex_exit() critical region we must
1496          * reset the PC back to the beginning to prevent missed wakeups




   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright (c) 2018 Joyent, Inc.  All rights reserverd.
  25  */
  26 
  27 /*
  28  * To understand the present state of interrupt handling on i86pc, we must
  29  * first consider the history of interrupt controllers and our way of handling
  30  * interrupts.
  31  *
  32  * History of Interrupt Controllers on i86pc
  33  * -----------------------------------------
  34  *
  35  *    Intel 8259 and 8259A
  36  *
  37  * The first interrupt controller that attained widespread use on i86pc was
  38  * the Intel 8259(A) Programmable Interrupt Controller that first saw use with
  39  * the 8086. It took up to 8 interrupt sources and combined them into one
  40  * output wire. Up to 8 8259s could be slaved together providing up to 64 IRQs.
  41  * With the switch to the 8259A, level mode interrupts became possible. For a
  42  * long time on i86pc the 8259A was the only way to handle interrupts and it
  43  * had its own set of quirks. The 8259A and its corresponding interval timer
  44  * the 8254 are programmed using outb and inb instructions.


 454 #include <sys/disp.h>
 455 #include <vm/seg_kp.h>
 456 #include <sys/stack.h>
 457 #include <sys/sysmacros.h>
 458 #include <sys/cmn_err.h>
 459 #include <sys/kstat.h>
 460 #include <sys/smp_impldefs.h>
 461 #include <sys/pool_pset.h>
 462 #include <sys/zone.h>
 463 #include <sys/bitmap.h>
 464 #include <sys/archsystm.h>
 465 #include <sys/machsystm.h>
 466 #include <sys/ontrap.h>
 467 #include <sys/x86_archext.h>
 468 #include <sys/promif.h>
 469 #include <vm/hat_i86.h>
 470 #if defined(__xpv)
 471 #include <sys/hypervisor.h>
 472 #endif
 473 
 474 #if defined(__amd64) && !defined(__xpv)
 475 /* If this fails, then the padding numbers in machcpuvar.h are wrong. */
 476 CTASSERT((offsetof(cpu_t, cpu_m) + offsetof(struct machcpu, mcpu_pad))
 477     < MMU_PAGESIZE);
 478 CTASSERT((offsetof(cpu_t, cpu_m) + offsetof(struct machcpu, mcpu_kpti))
 479     >= MMU_PAGESIZE);
 480 CTASSERT((offsetof(cpu_t, cpu_m) + offsetof(struct machcpu, mcpu_kpti_dbg))
 481     < 2 * MMU_PAGESIZE);
 482 CTASSERT((offsetof(cpu_t, cpu_m) + offsetof(struct machcpu, mcpu_pad2))
 483     < 2 * MMU_PAGESIZE);
 484 CTASSERT(((sizeof (struct kpti_frame)) & 0xF) == 0);
 485 CTASSERT(((offsetof(cpu_t, cpu_m) + offsetof(struct machcpu, mcpu_kpti_dbg))
 486     & 0xF) == 0);
 487 CTASSERT((offsetof(struct kpti_frame, kf_tr_rsp) & 0xF) == 0);
 488 #endif
 489 
 490 #if defined(__xpv) && defined(DEBUG)
 491 
 492 /*
 493  * This panic message is intended as an aid to interrupt debugging.
 494  *
 495  * The associated assertion tests the condition of enabling
 496  * events when events are already enabled.  The implication
 497  * being that whatever code the programmer thought was
 498  * protected by having events disabled until the second
 499  * enable happened really wasn't protected at all ..
 500  */
 501 
 502 int stistipanic = 1;    /* controls the debug panic check */
 503 const char *stistimsg = "stisti";
 504 ulong_t laststi[NCPU];
 505 
 506 /*
 507  * This variable tracks the last place events were disabled on each cpu
 508  * it assists in debugging when asserts that interrupts are enabled trip.


1471                         /*
1472                          * 1 or more of the selectors is bad.
1473                          * Deliver a SIGSEGV.
1474                          */
1475                         proc_t *p = ttoproc(tp);
1476 
1477                         sti();
1478                         mutex_enter(&p->p_lock);
1479                         tp->t_lwp->lwp_cursig = SIGSEGV;
1480                         mutex_exit(&p->p_lock);
1481                         psig();
1482                         tp->t_sig_check = 1;
1483                         cli();
1484                 }
1485                 tp->t_lwp->lwp_pcb.pcb_rupdate = 0;
1486 
1487 #endif  /* __amd64 */
1488                 return (1);
1489         }
1490 
1491 #if !defined(__xpv)
1492         /*
1493          * Assert that we're not trying to return into the syscall return
1494          * trampolines. Things will go baaaaad if we try to do that.
1495          *
1496          * Note that none of these run with interrupts on, so this should
1497          * never happen (even in the sysexit case the STI doesn't take effect
1498          * until after sysexit finishes).
1499          */
1500         extern void tr_sysc_ret_start();
1501         extern void tr_sysc_ret_end();
1502         ASSERT(!(rp->r_pc >= (uintptr_t)tr_sysc_ret_start &&
1503             rp->r_pc <= (uintptr_t)tr_sysc_ret_end));
1504 #endif
1505 
1506         /*
1507          * Here if we are returning to supervisor mode.
1508          * Check for a kernel preemption request.
1509          */
1510         if (CPU->cpu_kprunrun && (rp->r_ps & PS_IE)) {
1511 
1512                 /*
1513                  * Do nothing if already in kpreempt
1514                  */
1515                 if (!tp->t_preempt_lk) {
1516                         tp->t_preempt_lk = 1;
1517                         sti();
1518                         kpreempt(1); /* asynchronous kpreempt call */
1519                         cli();
1520                         tp->t_preempt_lk = 0;
1521                 }
1522         }
1523 
1524         /*
1525          * If we interrupted the mutex_exit() critical region we must
1526          * reset the PC back to the beginning to prevent missed wakeups