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
This commit is contained in:
parent
cc68614da8
commit
2450da6776
@ -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)
|
||||
{
|
||||
|
@ -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"));
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user