|
@@ -35,6 +35,7 @@
|
|
|
#include <xen/interface/version.h>
|
|
|
#include <xen/interface/physdev.h>
|
|
|
#include <xen/interface/vcpu.h>
|
|
|
+#include <xen/interface/memory.h>
|
|
|
#include <xen/features.h>
|
|
|
#include <xen/page.h>
|
|
|
#include <xen/hvc-console.h>
|
|
@@ -55,7 +56,9 @@
|
|
|
#include <asm/pgtable.h>
|
|
|
#include <asm/tlbflush.h>
|
|
|
#include <asm/reboot.h>
|
|
|
+#include <asm/setup.h>
|
|
|
#include <asm/stackprotector.h>
|
|
|
+#include <asm/hypervisor.h>
|
|
|
|
|
|
#include "xen-ops.h"
|
|
|
#include "mmu.h"
|
|
@@ -76,6 +79,8 @@ struct shared_info xen_dummy_shared_info;
|
|
|
|
|
|
void *xen_initial_gdt;
|
|
|
|
|
|
+RESERVE_BRK(shared_info_page_brk, PAGE_SIZE);
|
|
|
+
|
|
|
/*
|
|
|
* Point at some empty memory to start with. We map the real shared_info
|
|
|
* page as soon as fixmap is up and running.
|
|
@@ -1206,3 +1211,98 @@ asmlinkage void __init xen_start_kernel(void)
|
|
|
x86_64_start_reservations((char *)__pa_symbol(&boot_params));
|
|
|
#endif
|
|
|
}
|
|
|
+
|
|
|
+static uint32_t xen_cpuid_base(void)
|
|
|
+{
|
|
|
+ uint32_t base, eax, ebx, ecx, edx;
|
|
|
+ char signature[13];
|
|
|
+
|
|
|
+ for (base = 0x40000000; base < 0x40010000; base += 0x100) {
|
|
|
+ cpuid(base, &eax, &ebx, &ecx, &edx);
|
|
|
+ *(uint32_t *)(signature + 0) = ebx;
|
|
|
+ *(uint32_t *)(signature + 4) = ecx;
|
|
|
+ *(uint32_t *)(signature + 8) = edx;
|
|
|
+ signature[12] = 0;
|
|
|
+
|
|
|
+ if (!strcmp("XenVMMXenVMM", signature) && ((eax - base) >= 2))
|
|
|
+ return base;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int init_hvm_pv_info(int *major, int *minor)
|
|
|
+{
|
|
|
+ uint32_t eax, ebx, ecx, edx, pages, msr, base;
|
|
|
+ u64 pfn;
|
|
|
+
|
|
|
+ base = xen_cpuid_base();
|
|
|
+ cpuid(base + 1, &eax, &ebx, &ecx, &edx);
|
|
|
+
|
|
|
+ *major = eax >> 16;
|
|
|
+ *minor = eax & 0xffff;
|
|
|
+ printk(KERN_INFO "Xen version %d.%d.\n", *major, *minor);
|
|
|
+
|
|
|
+ cpuid(base + 2, &pages, &msr, &ecx, &edx);
|
|
|
+
|
|
|
+ pfn = __pa(hypercall_page);
|
|
|
+ wrmsr_safe(msr, (u32)pfn, (u32)(pfn >> 32));
|
|
|
+
|
|
|
+ xen_setup_features();
|
|
|
+
|
|
|
+ pv_info = xen_info;
|
|
|
+ pv_info.kernel_rpl = 0;
|
|
|
+
|
|
|
+ xen_domain_type = XEN_HVM_DOMAIN;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static void __init init_shared_info(void)
|
|
|
+{
|
|
|
+ struct xen_add_to_physmap xatp;
|
|
|
+ struct shared_info *shared_info_page;
|
|
|
+
|
|
|
+ shared_info_page = (struct shared_info *)
|
|
|
+ extend_brk(PAGE_SIZE, PAGE_SIZE);
|
|
|
+ xatp.domid = DOMID_SELF;
|
|
|
+ xatp.idx = 0;
|
|
|
+ xatp.space = XENMAPSPACE_shared_info;
|
|
|
+ xatp.gpfn = __pa(shared_info_page) >> PAGE_SHIFT;
|
|
|
+ if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp))
|
|
|
+ BUG();
|
|
|
+
|
|
|
+ HYPERVISOR_shared_info = (struct shared_info *)shared_info_page;
|
|
|
+
|
|
|
+ per_cpu(xen_vcpu, 0) = &HYPERVISOR_shared_info->vcpu_info[0];
|
|
|
+}
|
|
|
+
|
|
|
+static void __init xen_hvm_guest_init(void)
|
|
|
+{
|
|
|
+ int r;
|
|
|
+ int major, minor;
|
|
|
+
|
|
|
+ r = init_hvm_pv_info(&major, &minor);
|
|
|
+ if (r < 0)
|
|
|
+ return;
|
|
|
+
|
|
|
+ init_shared_info();
|
|
|
+}
|
|
|
+
|
|
|
+static bool __init xen_hvm_platform(void)
|
|
|
+{
|
|
|
+ if (xen_pv_domain())
|
|
|
+ return false;
|
|
|
+
|
|
|
+ if (!xen_cpuid_base())
|
|
|
+ return false;
|
|
|
+
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
+const __refconst struct hypervisor_x86 x86_hyper_xen_hvm = {
|
|
|
+ .name = "Xen HVM",
|
|
|
+ .detect = xen_hvm_platform,
|
|
|
+ .init_platform = xen_hvm_guest_init,
|
|
|
+};
|
|
|
+EXPORT_SYMBOL(x86_hyper_xen_hvm);
|