xen: allow very early initialization of the hypercall page
Allow the hypercall page to be initialized very early, even before vtophys is functional. Also make the function global so it can be called by other files. This will be needed in order to perform the early bringup on PVHv2 guests. Sponsored by: Citrix Systems R&D
This commit is contained in:
parent
3653af112f
commit
07c2711fbf
@ -40,6 +40,7 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include <vm/vm.h>
|
||||
#include <vm/pmap.h>
|
||||
#include <vm/vm_param.h>
|
||||
|
||||
#include <dev/pci/pcivar.h>
|
||||
|
||||
@ -63,13 +64,6 @@ __FBSDID("$FreeBSD$");
|
||||
/*--------------------------- Forward Declarations ---------------------------*/
|
||||
static void xen_hvm_cpu_init(void);
|
||||
|
||||
/*-------------------------------- Local Types -------------------------------*/
|
||||
enum xen_hvm_init_type {
|
||||
XEN_HVM_INIT_COLD,
|
||||
XEN_HVM_INIT_CANCELLED_SUSPEND,
|
||||
XEN_HVM_INIT_RESUME
|
||||
};
|
||||
|
||||
/*-------------------------------- Global Data -------------------------------*/
|
||||
enum xen_domain_type xen_domain_type = XEN_NATIVE;
|
||||
|
||||
@ -119,50 +113,66 @@ xen_hvm_cpuid_base(void)
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
hypervisor_quirks(unsigned int major, unsigned int minor)
|
||||
{
|
||||
#ifdef SMP
|
||||
if (((major < 4) || (major == 4 && minor <= 5)) &&
|
||||
msix_disable_migration == -1) {
|
||||
/*
|
||||
* Xen hypervisors prior to 4.6.0 do not properly
|
||||
* handle updates to enabled MSI-X table entries,
|
||||
* so disable MSI-X interrupt migration in that
|
||||
* case.
|
||||
*/
|
||||
if (bootverbose)
|
||||
printf(
|
||||
"Disabling MSI-X interrupt migration due to Xen hypervisor bug.\n"
|
||||
"Set machdep.msix_disable_migration=0 to forcefully enable it.\n");
|
||||
msix_disable_migration = 1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
hypervisor_version(void)
|
||||
{
|
||||
uint32_t regs[4];
|
||||
int major, minor;
|
||||
|
||||
do_cpuid(cpuid_base + 1, regs);
|
||||
|
||||
major = regs[0] >> 16;
|
||||
minor = regs[0] & 0xffff;
|
||||
printf("XEN: Hypervisor version %d.%d detected.\n", major, minor);
|
||||
|
||||
hypervisor_quirks(major, minor);
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate and fill in the hypcall page.
|
||||
*/
|
||||
static int
|
||||
int
|
||||
xen_hvm_init_hypercall_stubs(enum xen_hvm_init_type init_type)
|
||||
{
|
||||
uint32_t regs[4];
|
||||
|
||||
if (xen_pv_domain()) {
|
||||
/* hypercall page is already set in the PV case */
|
||||
return (0);
|
||||
if (xen_domain() && init_type == XEN_HVM_INIT_LATE) {
|
||||
/*
|
||||
* If the domain type is already set we can assume that the
|
||||
* hypercall page has been populated too, so just print the
|
||||
* version (and apply any quirks) and exit.
|
||||
*/
|
||||
hypervisor_version();
|
||||
return 0;
|
||||
}
|
||||
|
||||
cpuid_base = xen_hvm_cpuid_base();
|
||||
if (cpuid_base == 0)
|
||||
return (ENXIO);
|
||||
|
||||
if (init_type == XEN_HVM_INIT_COLD) {
|
||||
int major, minor;
|
||||
|
||||
do_cpuid(cpuid_base + 1, regs);
|
||||
|
||||
major = regs[0] >> 16;
|
||||
minor = regs[0] & 0xffff;
|
||||
printf("XEN: Hypervisor version %d.%d detected.\n", major,
|
||||
minor);
|
||||
|
||||
#ifdef SMP
|
||||
if (((major < 4) || (major == 4 && minor <= 5)) &&
|
||||
msix_disable_migration == -1) {
|
||||
/*
|
||||
* Xen hypervisors prior to 4.6.0 do not properly
|
||||
* handle updates to enabled MSI-X table entries,
|
||||
* so disable MSI-X interrupt migration in that
|
||||
* case.
|
||||
*/
|
||||
if (bootverbose)
|
||||
printf(
|
||||
"Disabling MSI-X interrupt migration due to Xen hypervisor bug.\n"
|
||||
"Set machdep.msix_disable_migration=0 to forcefully enable it.\n");
|
||||
msix_disable_migration = 1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if (init_type == XEN_HVM_INIT_LATE)
|
||||
hypervisor_version();
|
||||
|
||||
/*
|
||||
* Find the hypercall pages.
|
||||
@ -171,7 +181,9 @@ xen_hvm_init_hypercall_stubs(enum xen_hvm_init_type init_type)
|
||||
if (regs[0] != 1)
|
||||
return (EINVAL);
|
||||
|
||||
wrmsr(regs[1], vtophys(&hypercall_page));
|
||||
wrmsr(regs[1], (init_type == XEN_HVM_INIT_EARLY)
|
||||
? ((vm_paddr_t)&hypercall_page - KERNBASE)
|
||||
: vtophys(&hypercall_page));
|
||||
|
||||
return (0);
|
||||
}
|
||||
@ -307,7 +319,7 @@ xen_hvm_init(enum xen_hvm_init_type init_type)
|
||||
error = xen_hvm_init_hypercall_stubs(init_type);
|
||||
|
||||
switch (init_type) {
|
||||
case XEN_HVM_INIT_COLD:
|
||||
case XEN_HVM_INIT_LATE:
|
||||
if (error != 0)
|
||||
return;
|
||||
|
||||
@ -371,7 +383,7 @@ xen_hvm_resume(bool suspend_cancelled)
|
||||
static void
|
||||
xen_hvm_sysinit(void *arg __unused)
|
||||
{
|
||||
xen_hvm_init(XEN_HVM_INIT_COLD);
|
||||
xen_hvm_init(XEN_HVM_INIT_LATE);
|
||||
}
|
||||
SYSINIT(xen_hvm_init, SI_SUB_HYPERVISOR, SI_ORDER_FIRST, xen_hvm_sysinit, NULL);
|
||||
|
||||
|
@ -91,6 +91,14 @@ enum {
|
||||
(((uint64_t)HVM_CB_TYPE_VECTOR << HVM_CB_TYPE_SHIFT) \
|
||||
| (((vector) & HVM_CB_GSI_GSI_MASK) << HVM_CB_GSI_GSI_SHIFT))
|
||||
|
||||
enum xen_hvm_init_type {
|
||||
XEN_HVM_INIT_EARLY,
|
||||
XEN_HVM_INIT_LATE,
|
||||
XEN_HVM_INIT_CANCELLED_SUSPEND,
|
||||
XEN_HVM_INIT_RESUME,
|
||||
};
|
||||
|
||||
int xen_hvm_init_hypercall_stubs(enum xen_hvm_init_type);
|
||||
void xen_hvm_set_callback(device_t);
|
||||
void xen_hvm_suspend(void);
|
||||
void xen_hvm_resume(bool suspend_cancelled);
|
||||
|
Loading…
Reference in New Issue
Block a user