Skip to content

Commit

Permalink
MFC r328083,328096,328116,328119,328120,328128,328135,328153,328157,
Browse files Browse the repository at this point in the history
328166,328177,328199,328202,328205,328468,328470,328624,328625,328627,
328628,329214,329297,329365:

Meltdown mitigation by PTI, PCID optimization of PTI, and kernel use of IBRS
for some mitigations of Spectre.

Tested by:      emaste, Arshan Khanifar <arshankhanifar@gmail.com>
Discussed with:	jkim
Sponsored by:	The FreeBSD Foundation
  • Loading branch information
kostikbel committed Feb 17, 2018
1 parent ebe022b commit 6dd025b
Show file tree
Hide file tree
Showing 47 changed files with 1,913 additions and 514 deletions.
172 changes: 74 additions & 98 deletions sys/amd64/amd64/apic_vector.S
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@
* Copyright (c) 1989, 1990 William F. Jolitz.
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 2014-2018 The FreeBSD Foundation
* All rights reserved.
*
* Portions of this software were developed by
* Konstantin Belousov <kib@FreeBSD.org> under sponsorship from
* the FreeBSD Foundation.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
Expand Down Expand Up @@ -38,12 +44,12 @@

#include "opt_smp.h"

#include "assym.s"

#include <machine/asmacros.h>
#include <machine/specialreg.h>
#include <x86/apicreg.h>

#include "assym.s"

#ifdef SMP
#define LK lock ;
#else
Expand Down Expand Up @@ -73,30 +79,28 @@ as_lapic_eoi:
* translates that into a vector, and passes the vector to the
* lapic_handle_intr() function.
*/
#define ISR_VEC(index, vec_name) \
.text ; \
SUPERALIGN_TEXT ; \
IDTVEC(vec_name) ; \
PUSH_FRAME ; \
FAKE_MCOUNT(TF_RIP(%rsp)) ; \
cmpl $0,x2apic_mode ; \
je 1f ; \
movl $(MSR_APIC_ISR0 + index),%ecx ; \
rdmsr ; \
jmp 2f ; \
1: ; \
movq lapic_map, %rdx ; /* pointer to local APIC */ \
movl LA_ISR + 16 * (index)(%rdx), %eax ; /* load ISR */ \
2: ; \
bsrl %eax, %eax ; /* index of highest set bit in ISR */ \
jz 3f ; \
addl $(32 * index),%eax ; \
movq %rsp, %rsi ; \
movl %eax, %edi ; /* pass the IRQ */ \
call lapic_handle_intr ; \
3: ; \
MEXITCOUNT ; \
.macro ISR_VEC index, vec_name
INTR_HANDLER \vec_name
FAKE_MCOUNT(TF_RIP(%rsp))
cmpl $0,x2apic_mode
je 1f
movl $(MSR_APIC_ISR0 + \index),%ecx
rdmsr
jmp 2f
1:
movq lapic_map, %rdx /* pointer to local APIC */
movl LA_ISR + 16 * (\index)(%rdx), %eax /* load ISR */
2:
bsrl %eax, %eax /* index of highest set bit in ISR */
jz 3f
addl $(32 * \index),%eax
movq %rsp, %rsi
movl %eax, %edi /* pass the IRQ */
call lapic_handle_intr
3:
MEXITCOUNT
jmp doreti
.endm

/*
* Handle "spurious INTerrupts".
Expand All @@ -108,26 +112,21 @@ IDTVEC(vec_name) ; \
.text
SUPERALIGN_TEXT
IDTVEC(spuriousint)

/* No EOI cycle used here */

jmp doreti_iret

ISR_VEC(1, apic_isr1)
ISR_VEC(2, apic_isr2)
ISR_VEC(3, apic_isr3)
ISR_VEC(4, apic_isr4)
ISR_VEC(5, apic_isr5)
ISR_VEC(6, apic_isr6)
ISR_VEC(7, apic_isr7)
ISR_VEC 1, apic_isr1
ISR_VEC 2, apic_isr2
ISR_VEC 3, apic_isr3
ISR_VEC 4, apic_isr4
ISR_VEC 5, apic_isr5
ISR_VEC 6, apic_isr6
ISR_VEC 7, apic_isr7

/*
* Local APIC periodic timer handler.
*/
.text
SUPERALIGN_TEXT
IDTVEC(timerint)
PUSH_FRAME
INTR_HANDLER timerint
FAKE_MCOUNT(TF_RIP(%rsp))
movq %rsp, %rdi
call lapic_handle_timer
Expand All @@ -137,10 +136,7 @@ IDTVEC(timerint)
/*
* Local APIC CMCI handler.
*/
.text
SUPERALIGN_TEXT
IDTVEC(cmcint)
PUSH_FRAME
INTR_HANDLER cmcint
FAKE_MCOUNT(TF_RIP(%rsp))
call lapic_handle_cmc
MEXITCOUNT
Expand All @@ -149,10 +145,7 @@ IDTVEC(cmcint)
/*
* Local APIC error interrupt handler.
*/
.text
SUPERALIGN_TEXT
IDTVEC(errorint)
PUSH_FRAME
INTR_HANDLER errorint
FAKE_MCOUNT(TF_RIP(%rsp))
call lapic_handle_error
MEXITCOUNT
Expand All @@ -163,10 +156,7 @@ IDTVEC(errorint)
* Xen event channel upcall interrupt handler.
* Only used when the hypervisor supports direct vector callbacks.
*/
.text
SUPERALIGN_TEXT
IDTVEC(xen_intr_upcall)
PUSH_FRAME
INTR_HANDLER xen_intr_upcall
FAKE_MCOUNT(TF_RIP(%rsp))
movq %rsp, %rdi
call xen_intr_handle_upcall
Expand All @@ -183,99 +173,84 @@ IDTVEC(xen_intr_upcall)
SUPERALIGN_TEXT
invltlb_ret:
call as_lapic_eoi
POP_FRAME
jmp doreti_iret
jmp ld_regs

SUPERALIGN_TEXT
IDTVEC(invltlb)
PUSH_FRAME

INTR_HANDLER invltlb
call invltlb_handler
jmp invltlb_ret

IDTVEC(invltlb_pcid)
PUSH_FRAME

INTR_HANDLER invltlb_pcid
call invltlb_pcid_handler
jmp invltlb_ret

IDTVEC(invltlb_invpcid)
PUSH_FRAME

INTR_HANDLER invltlb_invpcid_nopti
call invltlb_invpcid_handler
jmp invltlb_ret

INTR_HANDLER invltlb_invpcid_pti
call invltlb_invpcid_pti_handler
jmp invltlb_ret

/*
* Single page TLB shootdown
*/
.text
INTR_HANDLER invlpg
call invlpg_handler
jmp invltlb_ret

SUPERALIGN_TEXT
IDTVEC(invlpg)
PUSH_FRAME
INTR_HANDLER invlpg_invpcid
call invlpg_invpcid_handler
jmp invltlb_ret

call invlpg_handler
INTR_HANDLER invlpg_pcid
call invlpg_pcid_handler
jmp invltlb_ret

/*
* Page range TLB shootdown.
*/
.text
SUPERALIGN_TEXT
IDTVEC(invlrng)
PUSH_FRAME

INTR_HANDLER invlrng
call invlrng_handler
jmp invltlb_ret

INTR_HANDLER invlrng_invpcid
call invlrng_invpcid_handler
jmp invltlb_ret

INTR_HANDLER invlrng_pcid
call invlrng_pcid_handler
jmp invltlb_ret

/*
* Invalidate cache.
*/
.text
SUPERALIGN_TEXT
IDTVEC(invlcache)
PUSH_FRAME

INTR_HANDLER invlcache
call invlcache_handler
jmp invltlb_ret

/*
* Handler for IPIs sent via the per-cpu IPI bitmap.
*/
.text
SUPERALIGN_TEXT
IDTVEC(ipi_intr_bitmap_handler)
PUSH_FRAME

INTR_HANDLER ipi_intr_bitmap_handler
call as_lapic_eoi

FAKE_MCOUNT(TF_RIP(%rsp))

call ipi_bitmap_handler
MEXITCOUNT
jmp doreti

/*
* Executed by a CPU when it receives an IPI_STOP from another CPU.
*/
.text
SUPERALIGN_TEXT
IDTVEC(cpustop)
PUSH_FRAME

INTR_HANDLER cpustop
call as_lapic_eoi

call cpustop_handler
jmp doreti

/*
* Executed by a CPU when it receives an IPI_SUSPEND from another CPU.
*/
.text
SUPERALIGN_TEXT
IDTVEC(cpususpend)
PUSH_FRAME

INTR_HANDLER cpususpend
call cpususpend_handler
call as_lapic_eoi
jmp doreti
Expand All @@ -285,10 +260,7 @@ IDTVEC(cpususpend)
*
* - Calls the generic rendezvous action function.
*/
.text
SUPERALIGN_TEXT
IDTVEC(rendezvous)
PUSH_FRAME
INTR_HANDLER rendezvous
#ifdef COUNT_IPIS
movl PCPU(CPUID), %eax
movq ipi_rendezvous_counts(,%rax,8), %rax
Expand Down Expand Up @@ -328,4 +300,8 @@ IDTVEC(justreturn)
popq %rax
jmp doreti_iret

INTR_HANDLER justreturn1
call as_lapic_eoi
jmp doreti

#endif /* SMP */
53 changes: 25 additions & 28 deletions sys/amd64/amd64/atpic_vector.S
Original file line number Diff line number Diff line change
Expand Up @@ -36,38 +36,35 @@
* master and slave interrupt controllers.
*/

#include <machine/asmacros.h>

#include "assym.s"
#include <machine/asmacros.h>

/*
* Macros for interrupt entry, call to handler, and exit.
*/
#define INTR(irq_num, vec_name) \
.text ; \
SUPERALIGN_TEXT ; \
IDTVEC(vec_name) ; \
PUSH_FRAME ; \
FAKE_MCOUNT(TF_RIP(%rsp)) ; \
movq %rsp, %rsi ; \
movl $irq_num, %edi; /* pass the IRQ */ \
call atpic_handle_intr ; \
MEXITCOUNT ; \
.macro INTR irq_num, vec_name
INTR_HANDLER \vec_name
FAKE_MCOUNT(TF_RIP(%rsp))
movq %rsp, %rsi
movl $\irq_num, %edi /* pass the IRQ */
call atpic_handle_intr
MEXITCOUNT
jmp doreti
.endm

INTR(0, atpic_intr0)
INTR(1, atpic_intr1)
INTR(2, atpic_intr2)
INTR(3, atpic_intr3)
INTR(4, atpic_intr4)
INTR(5, atpic_intr5)
INTR(6, atpic_intr6)
INTR(7, atpic_intr7)
INTR(8, atpic_intr8)
INTR(9, atpic_intr9)
INTR(10, atpic_intr10)
INTR(11, atpic_intr11)
INTR(12, atpic_intr12)
INTR(13, atpic_intr13)
INTR(14, atpic_intr14)
INTR(15, atpic_intr15)
INTR 0, atpic_intr0
INTR 1, atpic_intr1
INTR 2, atpic_intr2
INTR 3, atpic_intr3
INTR 4, atpic_intr4
INTR 5, atpic_intr5
INTR 6, atpic_intr6
INTR 7, atpic_intr7
INTR 8, atpic_intr8
INTR 9, atpic_intr9
INTR 10, atpic_intr10
INTR 11, atpic_intr11
INTR 12, atpic_intr12
INTR 13, atpic_intr13
INTR 14, atpic_intr14
INTR 15, atpic_intr15
11 changes: 9 additions & 2 deletions sys/amd64/amd64/cpu_switch.S
Original file line number Diff line number Diff line change
Expand Up @@ -215,8 +215,10 @@ done_tss:
movq %r8,PCPU(RSP0)
movq %r8,PCPU(CURPCB)
/* Update the TSS_RSP0 pointer for the next interrupt */
cmpb $0,pti(%rip)
jne 1f
movq %r8,TSS_RSP0(%rdx)
movq %r12,PCPU(CURTHREAD) /* into next thread */
1: movq %r12,PCPU(CURTHREAD) /* into next thread */

/* Test if debug registers should be restored. */
testl $PCB_DBREGS,PCB_FLAGS(%r8)
Expand Down Expand Up @@ -293,7 +295,12 @@ do_tss: movq %rdx,PCPU(TSSP)
shrq $8,%rcx
movl %ecx,8(%rax)
movb $0x89,5(%rax) /* unset busy */
movl $TSSSEL,%eax
cmpb $0,pti(%rip)
je 1f
movq PCPU(PRVSPACE),%rax
addq $PC_PTI_STACK+PC_PTI_STACK_SZ*8,%rax
movq %rax,TSS_RSP0(%rdx)
1: movl $TSSSEL,%eax
ltr %ax
jmp done_tss

Expand Down
1 change: 1 addition & 0 deletions sys/amd64/amd64/db_trace.c
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ db_nextframe(struct amd64_frame **fp, db_addr_t *ip, struct thread *td)
if (name != NULL) {
if (strcmp(name, "calltrap") == 0 ||
strcmp(name, "fork_trampoline") == 0 ||
strcmp(name, "mchk_calltrap") == 0 ||
strcmp(name, "nmi_calltrap") == 0 ||
strcmp(name, "Xdblfault") == 0)
frame_type = TRAP;
Expand Down
Loading

0 comments on commit 6dd025b

Please sign in to comment.