aboutsummaryrefslogtreecommitdiff
path: root/sys/x86/xen
diff options
context:
space:
mode:
authorRoger Pau Monné <royger@FreeBSD.org>2018-07-19 08:13:41 +0000
committerRoger Pau Monné <royger@FreeBSD.org>2018-07-19 08:13:41 +0000
commit07c2711fbf96d1b070b319b2d7f331430fc5ec2d (patch)
tree0077aac8ca27df706485441b6a90a37bd0406b86 /sys/x86/xen
parent3653af112f73318b7bcf37c54a79120b5d6f33c1 (diff)
downloadsrc-07c2711fbf96d1b070b319b2d7f331430fc5ec2d.tar.gz
src-07c2711fbf96d1b070b319b2d7f331430fc5ec2d.zip
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
Notes
Notes: svn path=/head/; revision=336473
Diffstat (limited to 'sys/x86/xen')
-rw-r--r--sys/x86/xen/hvm.c94
1 files changed, 53 insertions, 41 deletions
diff --git a/sys/x86/xen/hvm.c b/sys/x86/xen/hvm.c
index 1b98ab61e429..f8c886ec0fab 100644
--- a/sys/x86/xen/hvm.c
+++ b/sys/x86/xen/hvm.c
@@ -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);