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 */
|
/* tunable for disabling PV nics */
|
||||||
extern int xen_disable_pv_nics;
|
extern int xen_disable_pv_nics;
|
||||||
|
|
||||||
|
extern uint32_t xen_cpuid_base;
|
||||||
|
|
||||||
static inline bool
|
static inline bool
|
||||||
xen_has_percpu_evtchn(void)
|
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 ----------------------*/
|
/*---------------------- XEN Hypervisor Probe and Setup ----------------------*/
|
||||||
|
|
||||||
static uint32_t cpuid_base;
|
uint32_t xen_cpuid_base;
|
||||||
|
|
||||||
static uint32_t
|
static uint32_t
|
||||||
xen_hvm_cpuid_base(void)
|
xen_hvm_cpuid_base(void)
|
||||||
@ -153,7 +153,7 @@ hypervisor_version(void)
|
|||||||
uint32_t regs[4];
|
uint32_t regs[4];
|
||||||
int major, minor;
|
int major, minor;
|
||||||
|
|
||||||
do_cpuid(cpuid_base + 1, regs);
|
do_cpuid(xen_cpuid_base + 1, regs);
|
||||||
|
|
||||||
major = regs[0] >> 16;
|
major = regs[0] >> 16;
|
||||||
minor = regs[0] & 0xffff;
|
minor = regs[0] & 0xffff;
|
||||||
@ -171,9 +171,9 @@ xen_hvm_init_hypercall_stubs(enum xen_hvm_init_type init_type)
|
|||||||
uint32_t regs[4];
|
uint32_t regs[4];
|
||||||
|
|
||||||
/* Legacy PVH will get here without the cpuid leaf being set. */
|
/* Legacy PVH will get here without the cpuid leaf being set. */
|
||||||
if (cpuid_base == 0)
|
if (xen_cpuid_base == 0)
|
||||||
cpuid_base = xen_hvm_cpuid_base();
|
xen_cpuid_base = xen_hvm_cpuid_base();
|
||||||
if (cpuid_base == 0)
|
if (xen_cpuid_base == 0)
|
||||||
return (ENXIO);
|
return (ENXIO);
|
||||||
|
|
||||||
if (xen_domain() && init_type == XEN_HVM_INIT_LATE) {
|
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.
|
* Find the hypercall pages.
|
||||||
*/
|
*/
|
||||||
do_cpuid(cpuid_base + 2, regs);
|
do_cpuid(xen_cpuid_base + 2, regs);
|
||||||
if (regs[0] != 1)
|
if (regs[0] != 1)
|
||||||
return (EINVAL);
|
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
|
* Set vCPU ID. If available fetch the ID from CPUID, if not just use
|
||||||
* the ACPI ID.
|
* the ACPI ID.
|
||||||
*/
|
*/
|
||||||
KASSERT(cpuid_base != 0, ("Invalid base Xen CPUID leaf"));
|
KASSERT(xen_cpuid_base != 0, ("Invalid base Xen CPUID leaf"));
|
||||||
cpuid_count(cpuid_base + 4, 0, regs);
|
cpuid_count(xen_cpuid_base + 4, 0, regs);
|
||||||
KASSERT((regs[0] & XEN_HVM_CPUID_VCPU_ID_PRESENT) ||
|
KASSERT((regs[0] & XEN_HVM_CPUID_VCPU_ID_PRESENT) ||
|
||||||
!xen_pv_domain(),
|
!xen_pv_domain(),
|
||||||
("Xen PV domain without vcpu_id in cpuid"));
|
("Xen PV domain without vcpu_id in cpuid"));
|
||||||
|
@ -54,6 +54,7 @@ __FBSDID("$FreeBSD$");
|
|||||||
#include <xen/hvm.h>
|
#include <xen/hvm.h>
|
||||||
#include <xen/xen_intr.h>
|
#include <xen/xen_intr.h>
|
||||||
|
|
||||||
|
#include <xen/interface/arch-x86/cpuid.h>
|
||||||
#include <xen/interface/vcpu.h>
|
#include <xen/interface/vcpu.h>
|
||||||
|
|
||||||
/*--------------------------------- Macros -----------------------------------*/
|
/*--------------------------------- Macros -----------------------------------*/
|
||||||
@ -601,11 +602,23 @@ xen_cpu_ipi_init(int cpu)
|
|||||||
static void
|
static void
|
||||||
xen_setup_cpus(void)
|
xen_setup_cpus(void)
|
||||||
{
|
{
|
||||||
|
uint32_t regs[4];
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (!xen_vector_callback_enabled)
|
if (!xen_vector_callback_enabled)
|
||||||
return;
|
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)
|
CPU_FOREACH(i)
|
||||||
xen_cpu_ipi_init(i);
|
xen_cpu_ipi_init(i);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user