From 18a2b08e65278fc88d171baa7bb1728cf53a11ae Mon Sep 17 00:00:00 2001 From: Neel Natu Date: Sat, 14 Mar 2015 02:32:08 +0000 Subject: [PATCH] Use lapic_ipi_alloc() to dynamically allocate IPI slots needed by bhyve when vmm.ko is loaded. Also relocate the 'justreturn' IPI handler to be alongside all other handlers. Requested by: kib --- sys/amd64/amd64/apic_vector.S | 31 ++++++++++++ sys/amd64/include/smp.h | 1 + sys/amd64/vmm/intel/ept.c | 1 - sys/amd64/vmm/intel/vmx.c | 11 ++--- sys/amd64/vmm/io/vlapic.c | 1 - sys/amd64/vmm/vmm.c | 7 ++- sys/amd64/vmm/vmm_ipi.c | 93 ----------------------------------- sys/amd64/vmm/vmm_ipi.h | 35 ------------- sys/amd64/vmm/vmm_lapic.c | 1 - sys/amd64/vmm/vmm_support.S | 43 ---------------- sys/modules/vmm/Makefile | 4 +- 11 files changed, 41 insertions(+), 187 deletions(-) delete mode 100644 sys/amd64/vmm/vmm_ipi.c delete mode 100644 sys/amd64/vmm/vmm_ipi.h delete mode 100644 sys/amd64/vmm/vmm_support.S diff --git a/sys/amd64/amd64/apic_vector.S b/sys/amd64/amd64/apic_vector.S index d9f272439654..c3aac336a506 100644 --- a/sys/amd64/amd64/apic_vector.S +++ b/sys/amd64/amd64/apic_vector.S @@ -301,4 +301,35 @@ IDTVEC(rendezvous) call smp_rendezvous_action call as_lapic_eoi jmp doreti + +/* + * IPI handler whose purpose is to interrupt the CPU with minimum overhead. + * This is used by bhyve to force a host cpu executing in guest context to + * trap into the hypervisor. + * + * This handler is different from other IPI handlers in the following aspects: + * + * 1. It doesn't push a trapframe on the stack. + * + * This implies that a DDB backtrace involving 'justreturn' will skip the + * function that was interrupted by this handler. + * + * 2. It doesn't 'swapgs' when userspace is interrupted. + * + * The 'justreturn' handler does not access any pcpu data so it is not an + * issue. Moreover the 'justreturn' handler can only be interrupted by an NMI + * whose handler already doesn't trust GS.base when kernel code is interrupted. + */ + .text + SUPERALIGN_TEXT +IDTVEC(justreturn) + pushq %rax + pushq %rcx + pushq %rdx + call as_lapic_eoi + popq %rdx + popq %rcx + popq %rax + jmp doreti_iret + #endif /* SMP */ diff --git a/sys/amd64/include/smp.h b/sys/amd64/include/smp.h index 99bf1e454736..3a4b6b329c94 100644 --- a/sys/amd64/include/smp.h +++ b/sys/amd64/include/smp.h @@ -54,6 +54,7 @@ inthand_t IDTVEC(ipi_intr_bitmap_handler), /* Bitmap based IPIs */ IDTVEC(cpustop), /* CPU stops & waits to be restarted */ IDTVEC(cpususpend), /* CPU suspends & waits to be resumed */ + IDTVEC(justreturn), /* interrupt CPU with minimum overhead */ IDTVEC(rendezvous); /* handle CPU rendezvous */ struct pmap; diff --git a/sys/amd64/vmm/intel/ept.c b/sys/amd64/vmm/intel/ept.c index 13c9788842ef..54320cb36bd1 100644 --- a/sys/amd64/vmm/intel/ept.c +++ b/sys/amd64/vmm/intel/ept.c @@ -43,7 +43,6 @@ __FBSDID("$FreeBSD$"); #include #include "vmx_cpufunc.h" -#include "vmm_ipi.h" #include "ept.h" #define EPT_SUPPORTS_EXEC_ONLY(cap) ((cap) & (1UL << 0)) diff --git a/sys/amd64/vmm/intel/vmx.c b/sys/amd64/vmm/intel/vmx.c index b81e48b05f91..6dbf38aeb106 100644 --- a/sys/amd64/vmm/intel/vmx.c +++ b/sys/amd64/vmm/intel/vmx.c @@ -55,7 +55,6 @@ __FBSDID("$FreeBSD$"); #include "vmm_lapic.h" #include "vmm_host.h" #include "vmm_ioport.h" -#include "vmm_ipi.h" #include "vmm_ktr.h" #include "vmm_stat.h" #include "vatpic.h" @@ -175,7 +174,7 @@ static int posted_interrupts; SYSCTL_INT(_hw_vmm_vmx_cap, OID_AUTO, posted_interrupts, CTLFLAG_RD, &posted_interrupts, 0, "APICv posted interrupt support"); -static int pirvec; +static int pirvec = -1; SYSCTL_INT(_hw_vmm_vmx, OID_AUTO, posted_interrupt_vector, CTLFLAG_RD, &pirvec, 0, "APICv posted interrupt vector"); @@ -485,8 +484,8 @@ static int vmx_cleanup(void) { - if (pirvec != 0) - vmm_ipi_free(pirvec); + if (pirvec >= 0) + lapic_ipi_free(pirvec); if (vpid_unr != NULL) { delete_unrhdr(vpid_unr); @@ -694,8 +693,8 @@ vmx_init(int ipinum) MSR_VMX_TRUE_PINBASED_CTLS, PINBASED_POSTED_INTERRUPT, 0, &tmp); if (error == 0) { - pirvec = vmm_ipi_alloc(); - if (pirvec == 0) { + pirvec = lapic_ipi_alloc(&IDTVEC(justreturn)); + if (pirvec < 0) { if (bootverbose) { printf("vmx_init: unable to allocate " "posted interrupt vector\n"); diff --git a/sys/amd64/vmm/io/vlapic.c b/sys/amd64/vmm/io/vlapic.c index b192735981b6..70972487753b 100644 --- a/sys/amd64/vmm/io/vlapic.c +++ b/sys/amd64/vmm/io/vlapic.c @@ -45,7 +45,6 @@ __FBSDID("$FreeBSD$"); #include -#include "vmm_ipi.h" #include "vmm_lapic.h" #include "vmm_ktr.h" #include "vmm_stat.h" diff --git a/sys/amd64/vmm/vmm.c b/sys/amd64/vmm/vmm.c index 9e44549b32ff..7e72b028a3e2 100644 --- a/sys/amd64/vmm/vmm.c +++ b/sys/amd64/vmm/vmm.c @@ -76,7 +76,6 @@ __FBSDID("$FreeBSD$"); #include "vlapic.h" #include "vpmtmr.h" #include "vrtc.h" -#include "vmm_ipi.h" #include "vmm_stat.h" #include "vmm_lapic.h" @@ -298,8 +297,8 @@ vmm_init(void) vmm_host_state_init(); - vmm_ipinum = vmm_ipi_alloc(); - if (vmm_ipinum == 0) + vmm_ipinum = lapic_ipi_alloc(&IDTVEC(justreturn)); + if (vmm_ipinum < 0) vmm_ipinum = IPI_AST; error = vmm_mem_init(); @@ -338,7 +337,7 @@ vmm_handler(module_t mod, int what, void *arg) vmm_resume_p = NULL; iommu_cleanup(); if (vmm_ipinum != IPI_AST) - vmm_ipi_free(vmm_ipinum); + lapic_ipi_free(vmm_ipinum); error = VMM_CLEANUP(); /* * Something bad happened - prevent new diff --git a/sys/amd64/vmm/vmm_ipi.c b/sys/amd64/vmm/vmm_ipi.c deleted file mode 100644 index aefa3ba7790d..000000000000 --- a/sys/amd64/vmm/vmm_ipi.c +++ /dev/null @@ -1,93 +0,0 @@ -/*- - * Copyright (c) 2011 NetApp, Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include "vmm_ipi.h" - -extern inthand_t IDTVEC(rsvd), IDTVEC(justreturn); - -CTASSERT(APIC_SPURIOUS_INT == 255); - -int -vmm_ipi_alloc(void) -{ - int idx; - uintptr_t func; - struct gate_descriptor *ip; - - /* - * Search backwards from the highest IDT vector available for use - * as our IPI vector. We install the 'justreturn' handler at that - * vector and use it to interrupt the vcpus. - * - * We do this because the IPI_AST is heavyweight and saves all - * registers in the trapframe. This is overkill for our use case - * which is simply to EOI the interrupt and return. - */ - idx = APIC_SPURIOUS_INT; - while (--idx >= APIC_IPI_INTS) { - ip = &idt[idx]; - func = ((long)ip->gd_hioffset << 16 | ip->gd_looffset); - if (func == (uintptr_t)&IDTVEC(rsvd)) { - setidt(idx , IDTVEC(justreturn), SDT_SYSIGT, - SEL_KPL, 0); - return (idx); - } - } - return (0); -} - -void -vmm_ipi_free(int ipinum) -{ - uintptr_t func; - struct gate_descriptor *ip; - - KASSERT(ipinum >= APIC_IPI_INTS && ipinum < APIC_SPURIOUS_INT, - ("invalid ipi %d", ipinum)); - - ip = &idt[ipinum]; - func = ((long)ip->gd_hioffset << 16 | ip->gd_looffset); - KASSERT(func == (uintptr_t)&IDTVEC(justreturn), - ("invalid ipi %d", ipinum)); - - setidt(ipinum, IDTVEC(rsvd), SDT_SYSIGT, SEL_KPL, 0); -} diff --git a/sys/amd64/vmm/vmm_ipi.h b/sys/amd64/vmm/vmm_ipi.h deleted file mode 100644 index 679d1839fcad..000000000000 --- a/sys/amd64/vmm/vmm_ipi.h +++ /dev/null @@ -1,35 +0,0 @@ -/*- - * Copyright (c) 2011 NetApp, Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#ifndef _VMM_IPI_H_ -#define _VMM_IPI_H_ - -int vmm_ipi_alloc(void); -void vmm_ipi_free(int num); - -#endif diff --git a/sys/amd64/vmm/vmm_lapic.c b/sys/amd64/vmm/vmm_lapic.c index fa9832e09d15..15a995e9823d 100644 --- a/sys/amd64/vmm/vmm_lapic.c +++ b/sys/amd64/vmm/vmm_lapic.c @@ -37,7 +37,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include "vmm_ipi.h" #include "vmm_ktr.h" #include "vmm_lapic.h" #include "vlapic.h" diff --git a/sys/amd64/vmm/vmm_support.S b/sys/amd64/vmm/vmm_support.S deleted file mode 100644 index 7919511c3eab..000000000000 --- a/sys/amd64/vmm/vmm_support.S +++ /dev/null @@ -1,43 +0,0 @@ -/*- - * Copyright (c) 2011 NetApp, Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#define LOCORE - -#include - - .text - SUPERALIGN_TEXT -IDTVEC(justreturn) - pushq %rdx - pushq %rax - pushq %rcx - call as_lapic_eoi - popq %rcx - popq %rax - popq %rdx - jmp doreti_iret diff --git a/sys/modules/vmm/Makefile b/sys/modules/vmm/Makefile index e81c2438b357..d94ceba7e2f5 100644 --- a/sys/modules/vmm/Makefile +++ b/sys/modules/vmm/Makefile @@ -19,13 +19,11 @@ SRCS+= vmm.c \ vmm_host.c \ vmm_instruction_emul.c \ vmm_ioport.c \ - vmm_ipi.c \ vmm_lapic.c \ vmm_mem.c \ vmm_stat.c \ vmm_util.c \ - x86.c \ - vmm_support.S + x86.c .PATH: ${.CURDIR}/../../amd64/vmm/io SRCS+= iommu.c \