Merge Xen PVHVM support into the GENERIC kernel config for both
amd64 and i386. Submitted by: Roger Pau Monné Sponsored by: Citrix Systems R&D Reviewed by: gibbs Approved by: re (blanket Xen) MFC after: 2 weeks sys/amd64/amd64/mp_machdep.c: sys/amd64/include/cpu.h: sys/i386/i386/mp_machdep.c: sys/i386/include/cpu.h: - Introduce two new CPU hooks for initialization and resume purposes. This allows us to get rid of the XENHVM ifdefs in mp_machdep, and also sets some hooks into common code that can be used by other hypervisor implementations. sys/amd64/conf/XENHVM: sys/i386/conf/XENHVM: - Remove these configs now that GENERIC has builtin support for Xen HVM. sys/kern/subr_smp.c: - Make sure there are no pending IPIs when suspending a system. sys/x86/xen/hvm.c: - Add cpu init and resume vectors that are called from mp_machdep using the new hooks. - Only clear the vcpu_info mapping data on resume. It is already clear for the BSP on a cold boot and is set correctly as APs are started. - Gate xen_hvm_init_cpu only to systems running under Xen. sys/x86/xen/xen_intr.c: - Gate the setup of event channels only to systems running under Xen.
This commit is contained in:
parent
ac873bb350
commit
566a5f5020
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=255744
@ -71,10 +71,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <machine/tss.h>
|
||||
#include <machine/cpu.h>
|
||||
|
||||
#ifdef XENHVM
|
||||
#include <xen/hvm.h>
|
||||
#endif
|
||||
|
||||
#define WARMBOOT_TARGET 0
|
||||
#define WARMBOOT_OFF (KERNBASE + 0x0467)
|
||||
#define WARMBOOT_SEG (KERNBASE + 0x0469)
|
||||
@ -161,7 +157,7 @@ int cpu_apic_ids[MAXCPU];
|
||||
int apic_cpuids[MAX_APIC_ID + 1];
|
||||
|
||||
/* Holds pending bitmap based IPIs per CPU */
|
||||
static volatile u_int cpu_ipi_pending[MAXCPU];
|
||||
volatile u_int cpu_ipi_pending[MAXCPU];
|
||||
|
||||
static u_int boot_address;
|
||||
static int cpu_logical; /* logical cpus per core */
|
||||
@ -732,10 +728,8 @@ init_secondary(void)
|
||||
/* set up FPU state on the AP */
|
||||
fpuinit();
|
||||
|
||||
#ifdef XENHVM
|
||||
/* register vcpu_info area */
|
||||
xen_hvm_init_cpu();
|
||||
#endif
|
||||
if (cpu_ops.cpu_init)
|
||||
cpu_ops.cpu_init();
|
||||
|
||||
/* A quick check from sanity claus */
|
||||
cpuid = PCPU_GET(cpuid);
|
||||
@ -1466,12 +1460,9 @@ cpususpend_handler(void)
|
||||
{
|
||||
u_int cpu;
|
||||
|
||||
cpu = PCPU_GET(cpuid);
|
||||
|
||||
#ifdef XENHVM
|
||||
mtx_assert(&smp_ipi_mtx, MA_NOTOWNED);
|
||||
#endif
|
||||
|
||||
cpu = PCPU_GET(cpuid);
|
||||
if (savectx(susppcbs[cpu])) {
|
||||
ctx_fpusave(susppcbs[cpu]->pcb_fpususpend);
|
||||
wbinvd();
|
||||
@ -1490,15 +1481,8 @@ cpususpend_handler(void)
|
||||
while (!CPU_ISSET(cpu, &started_cpus))
|
||||
ia32_pause();
|
||||
|
||||
#ifdef XENHVM
|
||||
/*
|
||||
* Reset pending bitmap IPIs, because Xen doesn't preserve pending
|
||||
* event channels on migration.
|
||||
*/
|
||||
cpu_ipi_pending[cpu] = 0;
|
||||
/* register vcpu_info area */
|
||||
xen_hvm_init_cpu();
|
||||
#endif
|
||||
if (cpu_ops.cpu_resume)
|
||||
cpu_ops.cpu_resume();
|
||||
|
||||
/* Resume MCA and local APIC */
|
||||
mca_resume();
|
||||
|
@ -72,6 +72,7 @@ options KDTRACE_FRAME # Ensure frames are compiled in
|
||||
options KDTRACE_HOOKS # Kernel DTrace hooks
|
||||
options DDB_CTF # Kernel ELF linker loads CTF data
|
||||
options INCLUDE_CONFIG_FILE # Include this file in kernel
|
||||
options XENHVM # Include Xen support
|
||||
|
||||
# Debugging support. Always need this:
|
||||
options KDB # Enable kernel debugger support.
|
||||
@ -341,5 +342,8 @@ device virtio_blk # VirtIO Block device
|
||||
device virtio_scsi # VirtIO SCSI device
|
||||
device virtio_balloon # VirtIO Memory Balloon device
|
||||
|
||||
# Xen support
|
||||
device xenpci # Generic Xen bus
|
||||
|
||||
# VMware support
|
||||
device vmx # VMware VMXNET3 Ethernet
|
||||
|
@ -1,22 +0,0 @@
|
||||
#
|
||||
# XENHVM -- Xen HVM kernel configuration file for FreeBSD/amd64
|
||||
#
|
||||
# $FreeBSD$
|
||||
#
|
||||
include GENERIC
|
||||
ident XENHVM
|
||||
|
||||
#
|
||||
# Adaptive locks rely on a lock-free pointer read to determine the run state
|
||||
# of the thread holding a lock when under contention; under a virtualisation
|
||||
# system, the thread run state may not accurately reflect whether the thread
|
||||
# (or rather its host VCPU) is actually executing. As such, disable this
|
||||
# optimisation.
|
||||
#
|
||||
options NO_ADAPTIVE_MUTEXES
|
||||
options NO_ADAPTIVE_RWLOCKS
|
||||
options NO_ADAPTIVE_SX
|
||||
|
||||
# Xen HVM support
|
||||
options XENHVM
|
||||
device xenpci
|
@ -61,6 +61,8 @@
|
||||
* hypervisor environment.
|
||||
*/
|
||||
struct cpu_ops {
|
||||
void (*cpu_init)(void);
|
||||
void (*cpu_resume)(void);
|
||||
void (*ipi_vectored)(u_int, int);
|
||||
};
|
||||
|
||||
|
@ -72,6 +72,7 @@ options MAC # TrustedBSD MAC Framework
|
||||
options KDTRACE_HOOKS # Kernel DTrace hooks
|
||||
options DDB_CTF # Kernel ELF linker loads CTF data
|
||||
options INCLUDE_CONFIG_FILE # Include this file in kernel
|
||||
options XENHVM # Include Xen support
|
||||
|
||||
# Debugging support. Always need this:
|
||||
options KDB # Enable kernel debugger support.
|
||||
@ -355,5 +356,8 @@ device virtio_blk # VirtIO Block device
|
||||
device virtio_scsi # VirtIO SCSI device
|
||||
device virtio_balloon # VirtIO Memory Balloon device
|
||||
|
||||
# Xen support
|
||||
device xenpci # Generic Xen bus
|
||||
|
||||
# VMware support
|
||||
device vmx # VMware VMXNET3 Ethernet
|
||||
|
@ -1,22 +0,0 @@
|
||||
#
|
||||
# XENHVM -- Xen HVM kernel configuration file for FreeBSD/i386
|
||||
#
|
||||
# $FreeBSD$
|
||||
#
|
||||
include GENERIC
|
||||
ident XENHVM
|
||||
|
||||
#
|
||||
# Adaptive locks rely on a lock-free pointer read to determine the run state
|
||||
# of the thread holding a lock when under contention; under a virtualisation
|
||||
# system, the thread run state may not accurately reflect whether the thread
|
||||
# (or rather its host VCPU) is actually executing. As such, disable this
|
||||
# optimisation.
|
||||
#
|
||||
options NO_ADAPTIVE_MUTEXES
|
||||
options NO_ADAPTIVE_RWLOCKS
|
||||
options NO_ADAPTIVE_SX
|
||||
|
||||
# Xen HVM support
|
||||
options XENHVM
|
||||
device xenpci
|
@ -83,10 +83,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <machine/specialreg.h>
|
||||
#include <machine/cpu.h>
|
||||
|
||||
#ifdef XENHVM
|
||||
#include <xen/hvm.h>
|
||||
#endif
|
||||
|
||||
#define WARMBOOT_TARGET 0
|
||||
#define WARMBOOT_OFF (KERNBASE + 0x0467)
|
||||
#define WARMBOOT_SEG (KERNBASE + 0x0469)
|
||||
@ -202,7 +198,7 @@ int cpu_apic_ids[MAXCPU];
|
||||
int apic_cpuids[MAX_APIC_ID + 1];
|
||||
|
||||
/* Holds pending bitmap based IPIs per CPU */
|
||||
static volatile u_int cpu_ipi_pending[MAXCPU];
|
||||
volatile u_int cpu_ipi_pending[MAXCPU];
|
||||
|
||||
static u_int boot_address;
|
||||
static int cpu_logical; /* logical cpus per core */
|
||||
@ -757,10 +753,8 @@ init_secondary(void)
|
||||
/* set up SSE registers */
|
||||
enable_sse();
|
||||
|
||||
#ifdef XENHVM
|
||||
/* register vcpu_info area */
|
||||
xen_hvm_init_cpu();
|
||||
#endif
|
||||
if (cpu_ops.cpu_init)
|
||||
cpu_ops.cpu_init();
|
||||
|
||||
#ifdef PAE
|
||||
/* Enable the PTE no-execute bit. */
|
||||
@ -1527,12 +1521,9 @@ cpususpend_handler(void)
|
||||
{
|
||||
u_int cpu;
|
||||
|
||||
cpu = PCPU_GET(cpuid);
|
||||
|
||||
#ifdef XENHVM
|
||||
mtx_assert(&smp_ipi_mtx, MA_NOTOWNED);
|
||||
#endif
|
||||
|
||||
cpu = PCPU_GET(cpuid);
|
||||
if (savectx(susppcbs[cpu])) {
|
||||
wbinvd();
|
||||
CPU_SET_ATOMIC(cpu, &suspended_cpus);
|
||||
@ -1549,15 +1540,8 @@ cpususpend_handler(void)
|
||||
while (!CPU_ISSET(cpu, &started_cpus))
|
||||
ia32_pause();
|
||||
|
||||
#ifdef XENHVM
|
||||
/*
|
||||
* Reset pending bitmap IPIs, because Xen doesn't preserve pending
|
||||
* event channels on migration.
|
||||
*/
|
||||
cpu_ipi_pending[cpu] = 0;
|
||||
/* register vcpu_info area */
|
||||
xen_hvm_init_cpu();
|
||||
#endif
|
||||
if (cpu_ops.cpu_resume)
|
||||
cpu_ops.cpu_resume();
|
||||
|
||||
/* Resume MCA and local APIC */
|
||||
mca_resume();
|
||||
|
@ -61,6 +61,8 @@
|
||||
* hypervisor environment.
|
||||
*/
|
||||
struct cpu_ops {
|
||||
void (*cpu_init)(void);
|
||||
void (*cpu_resume)(void);
|
||||
void (*ipi_vectored)(u_int, int);
|
||||
};
|
||||
|
||||
|
@ -225,17 +225,15 @@ generic_stop_cpus(cpuset_t map, u_int type)
|
||||
CTR2(KTR_SMP, "stop_cpus(%s) with %u type",
|
||||
cpusetobj_strprint(cpusetbuf, &map), type);
|
||||
|
||||
#ifdef XENHVM
|
||||
/*
|
||||
* When migrating a PVHVM domain we need to make sure there are
|
||||
* no IPIs in progress. IPIs that have been issued, but not
|
||||
* yet delivered (not pending on a vCPU) will be lost in the
|
||||
* IPI rebinding process, violating FreeBSD's assumption of
|
||||
* reliable IPI delivery.
|
||||
* When suspending, ensure there are are no IPIs in progress.
|
||||
* IPIs that have been issued, but not yet delivered (e.g.
|
||||
* not pending on a vCPU when running under virtualization)
|
||||
* will be lost, violating FreeBSD's assumption of reliable
|
||||
* IPI delivery.
|
||||
*/
|
||||
if (type == IPI_SUSPEND)
|
||||
mtx_lock_spin(&smp_ipi_mtx);
|
||||
#endif
|
||||
|
||||
if (stopping_cpu != PCPU_GET(cpuid))
|
||||
while (atomic_cmpset_int(&stopping_cpu, NOCPU,
|
||||
@ -264,10 +262,8 @@ generic_stop_cpus(cpuset_t map, u_int type)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef XENHVM
|
||||
if (type == IPI_SUSPEND)
|
||||
mtx_unlock_spin(&smp_ipi_mtx);
|
||||
#endif
|
||||
|
||||
stopping_cpu = NOCPU;
|
||||
return (1);
|
||||
|
@ -72,6 +72,9 @@ static driver_filter_t xen_cpustop_handler;
|
||||
static driver_filter_t xen_cpususpend_handler;
|
||||
static driver_filter_t xen_cpustophard_handler;
|
||||
#endif
|
||||
static void xen_ipi_vectored(u_int vector, int dest);
|
||||
static void xen_hvm_cpu_resume(void);
|
||||
static void xen_hvm_cpu_init(void);
|
||||
|
||||
/*---------------------------- Extern Declarations ---------------------------*/
|
||||
/* Variables used by mp_machdep to perform the MMU related IPIs */
|
||||
@ -91,6 +94,9 @@ extern pmap_t smp_tlb_pmap;
|
||||
extern void pmap_lazyfix_action(void);
|
||||
#endif
|
||||
|
||||
/* Variables used by mp_machdep to perform the bitmap IPI */
|
||||
extern volatile u_int cpu_ipi_pending[MAXCPU];
|
||||
|
||||
/*---------------------------------- Macros ----------------------------------*/
|
||||
#define IPI_TO_IDX(ipi) ((ipi) - APIC_IPI_INTS)
|
||||
|
||||
@ -110,6 +116,12 @@ struct xen_ipi_handler
|
||||
/*-------------------------------- Global Data -------------------------------*/
|
||||
enum xen_domain_type xen_domain_type = XEN_NATIVE;
|
||||
|
||||
struct cpu_ops xen_hvm_cpu_ops = {
|
||||
.ipi_vectored = xen_ipi_vectored,
|
||||
.cpu_init = xen_hvm_cpu_init,
|
||||
.cpu_resume = xen_hvm_cpu_resume
|
||||
};
|
||||
|
||||
static MALLOC_DEFINE(M_XENHVM, "xen_hvm", "Xen HVM PV Support");
|
||||
|
||||
#ifdef SMP
|
||||
@ -462,6 +474,22 @@ xen_ipi_vectored(u_int vector, int dest)
|
||||
}
|
||||
}
|
||||
|
||||
/* XEN diverged cpu operations */
|
||||
static void
|
||||
xen_hvm_cpu_resume(void)
|
||||
{
|
||||
u_int cpuid = PCPU_GET(cpuid);
|
||||
|
||||
/*
|
||||
* Reset pending bitmap IPIs, because Xen doesn't preserve pending
|
||||
* event channels on migration.
|
||||
*/
|
||||
cpu_ipi_pending[cpuid] = 0;
|
||||
|
||||
/* register vcpu_info area */
|
||||
xen_hvm_cpu_init();
|
||||
}
|
||||
|
||||
static void
|
||||
xen_cpu_ipi_init(int cpu)
|
||||
{
|
||||
@ -490,7 +518,7 @@ xen_cpu_ipi_init(int cpu)
|
||||
}
|
||||
|
||||
static void
|
||||
xen_init_ipis(void)
|
||||
xen_setup_cpus(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
@ -507,7 +535,7 @@ xen_init_ipis(void)
|
||||
xen_cpu_ipi_init(i);
|
||||
|
||||
/* Set the xen pv ipi ops to replace the native ones */
|
||||
cpu_ops.ipi_vectored = xen_ipi_vectored;
|
||||
cpu_ops = xen_hvm_cpu_ops;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -675,15 +703,15 @@ xen_hvm_init(enum xen_hvm_init_type init_type)
|
||||
case XEN_HVM_INIT_RESUME:
|
||||
if (error != 0)
|
||||
panic("Unable to init Xen hypercall stubs on resume");
|
||||
|
||||
/* Clear stale vcpu_info. */
|
||||
CPU_FOREACH(i)
|
||||
DPCPU_ID_SET(i, vcpu_info, NULL);
|
||||
break;
|
||||
default:
|
||||
panic("Unsupported HVM initialization type");
|
||||
}
|
||||
|
||||
/* Clear any stale vcpu_info. */
|
||||
CPU_FOREACH(i)
|
||||
DPCPU_ID_SET(i, vcpu_info, NULL);
|
||||
|
||||
xen_vector_callback_enabled = 0;
|
||||
xen_domain_type = XEN_HVM_DOMAIN;
|
||||
xen_hvm_init_shared_info_page();
|
||||
@ -704,7 +732,7 @@ xen_hvm_resume(bool suspend_cancelled)
|
||||
XEN_HVM_INIT_CANCELLED_SUSPEND : XEN_HVM_INIT_RESUME);
|
||||
|
||||
/* Register vcpu_info area for CPU#0. */
|
||||
xen_hvm_init_cpu();
|
||||
xen_hvm_cpu_init();
|
||||
}
|
||||
|
||||
static void
|
||||
@ -713,13 +741,16 @@ xen_hvm_sysinit(void *arg __unused)
|
||||
xen_hvm_init(XEN_HVM_INIT_COLD);
|
||||
}
|
||||
|
||||
void
|
||||
xen_hvm_init_cpu(void)
|
||||
static void
|
||||
xen_hvm_cpu_init(void)
|
||||
{
|
||||
struct vcpu_register_vcpu_info info;
|
||||
struct vcpu_info *vcpu_info;
|
||||
int cpu, rc;
|
||||
|
||||
if (!xen_domain())
|
||||
return;
|
||||
|
||||
if (DPCPU_GET(vcpu_info) != NULL) {
|
||||
/*
|
||||
* vcpu_info is already set. We're resuming
|
||||
@ -743,6 +774,6 @@ xen_hvm_init_cpu(void)
|
||||
|
||||
SYSINIT(xen_hvm_init, SI_SUB_HYPERVISOR, SI_ORDER_FIRST, xen_hvm_sysinit, NULL);
|
||||
#ifdef SMP
|
||||
SYSINIT(xen_init_ipis, SI_SUB_SMP, SI_ORDER_FIRST, xen_init_ipis, NULL);
|
||||
SYSINIT(xen_setup_cpus, SI_SUB_SMP, SI_ORDER_FIRST, xen_setup_cpus, NULL);
|
||||
#endif
|
||||
SYSINIT(xen_hvm_init_cpu, SI_SUB_INTR, SI_ORDER_FIRST, xen_hvm_init_cpu, NULL);
|
||||
SYSINIT(xen_hvm_cpu_init, SI_SUB_INTR, SI_ORDER_FIRST, xen_hvm_cpu_init, NULL);
|
||||
|
@ -94,5 +94,4 @@ enum {
|
||||
void xen_hvm_set_callback(device_t);
|
||||
void xen_hvm_suspend(void);
|
||||
void xen_hvm_resume(bool suspend_cancelled);
|
||||
void xen_hvm_init_cpu(void);
|
||||
#endif /* __XEN_HVM_H__ */
|
||||
|
Loading…
Reference in New Issue
Block a user