aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoger Pau Monné <royger@FreeBSD.org>2022-01-13 13:57:07 +0000
committerRoger Pau Monné <royger@FreeBSD.org>2022-01-18 09:18:22 +0000
commit2450da67764c975868167db49106fb335af19f0d (patch)
tree3ae6fb43de7918b43f35221b9f290ee5c4838f4e
parentcc68614da8232d8baaca0ae0d0dd8f890f06623e (diff)
downloadsrc-2450da67764c975868167db49106fb335af19f0d.tar.gz
src-2450da67764c975868167db49106fb335af19f0d.zip
x86/xen: use x{2}APIC if virtualized by hardware
Instead of using event channels or hypercalls to deal with IPIs and NMIs. Using a hardware virtualized APIC should be faster than using any PV interface, since the VM exit can be avoided. Xen exposes whether the domain is using hardware assisted x{2}APIC emulation in a CPUID bit. Sponsored by: Citrix Systems R&D
-rw-r--r--sys/x86/include/xen/xen-os.h2
-rw-r--r--sys/x86/xen/hvm.c16
-rw-r--r--sys/x86/xen/xen_apic.c13
3 files changed, 23 insertions, 8 deletions
diff --git a/sys/x86/include/xen/xen-os.h b/sys/x86/include/xen/xen-os.h
index 655961da22fd..4d4aa64955ba 100644
--- a/sys/x86/include/xen/xen-os.h
+++ b/sys/x86/include/xen/xen-os.h
@@ -49,6 +49,8 @@ extern int xen_disable_pv_disks;
/* tunable for disabling PV nics */
extern int xen_disable_pv_nics;
+extern uint32_t xen_cpuid_base;
+
static inline bool
xen_has_percpu_evtchn(void)
{
diff --git a/sys/x86/xen/hvm.c b/sys/x86/xen/hvm.c
index 569b113364b1..6eb16c3098fd 100644
--- a/sys/x86/xen/hvm.c
+++ b/sys/x86/xen/hvm.c
@@ -110,7 +110,7 @@ TUNABLE_INT("hw.xen.disable_pv_nics", &xen_disable_pv_nics);
/*---------------------- XEN Hypervisor Probe and Setup ----------------------*/
-static uint32_t cpuid_base;
+uint32_t xen_cpuid_base;
static uint32_t
xen_hvm_cpuid_base(void)
@@ -153,7 +153,7 @@ hypervisor_version(void)
uint32_t regs[4];
int major, minor;
- do_cpuid(cpuid_base + 1, regs);
+ do_cpuid(xen_cpuid_base + 1, regs);
major = regs[0] >> 16;
minor = regs[0] & 0xffff;
@@ -171,9 +171,9 @@ xen_hvm_init_hypercall_stubs(enum xen_hvm_init_type init_type)
uint32_t regs[4];
/* Legacy PVH will get here without the cpuid leaf being set. */
- if (cpuid_base == 0)
- cpuid_base = xen_hvm_cpuid_base();
- if (cpuid_base == 0)
+ if (xen_cpuid_base == 0)
+ xen_cpuid_base = xen_hvm_cpuid_base();
+ if (xen_cpuid_base == 0)
return (ENXIO);
if (xen_domain() && init_type == XEN_HVM_INIT_LATE) {
@@ -192,7 +192,7 @@ xen_hvm_init_hypercall_stubs(enum xen_hvm_init_type init_type)
/*
* Find the hypercall pages.
*/
- do_cpuid(cpuid_base + 2, regs);
+ do_cpuid(xen_cpuid_base + 2, regs);
if (regs[0] != 1)
return (EINVAL);
@@ -448,8 +448,8 @@ xen_hvm_cpu_init(void)
* Set vCPU ID. If available fetch the ID from CPUID, if not just use
* the ACPI ID.
*/
- KASSERT(cpuid_base != 0, ("Invalid base Xen CPUID leaf"));
- cpuid_count(cpuid_base + 4, 0, regs);
+ KASSERT(xen_cpuid_base != 0, ("Invalid base Xen CPUID leaf"));
+ cpuid_count(xen_cpuid_base + 4, 0, regs);
KASSERT((regs[0] & XEN_HVM_CPUID_VCPU_ID_PRESENT) ||
!xen_pv_domain(),
("Xen PV domain without vcpu_id in cpuid"));
diff --git a/sys/x86/xen/xen_apic.c b/sys/x86/xen/xen_apic.c
index 2efa5a3c2345..c268e747f44a 100644
--- a/sys/x86/xen/xen_apic.c
+++ b/sys/x86/xen/xen_apic.c
@@ -54,6 +54,7 @@ __FBSDID("$FreeBSD$");
#include <xen/hvm.h>
#include <xen/xen_intr.h>
+#include <xen/interface/arch-x86/cpuid.h>
#include <xen/interface/vcpu.h>
/*--------------------------------- Macros -----------------------------------*/
@@ -601,11 +602,23 @@ xen_cpu_ipi_init(int cpu)
static void
xen_setup_cpus(void)
{
+ uint32_t regs[4];
int i;
if (!xen_vector_callback_enabled)
return;
+ /*
+ * Check whether the APIC virtualization is hardware assisted, as
+ * that's faster than using event channels because it avoids the VM
+ * exit.
+ */
+ KASSERT(xen_cpuid_base != 0, ("Invalid base Xen CPUID leaf"));
+ cpuid_count(xen_cpuid_base + 4, 0, regs);
+ if ((x2apic_mode && (regs[0] & XEN_HVM_CPUID_X2APIC_VIRT)) ||
+ (!x2apic_mode && (regs[0] & XEN_HVM_CPUID_APIC_ACCESS_VIRT)))
+ return;
+
CPU_FOREACH(i)
xen_cpu_ipi_init(i);