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);