aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/include/asm/hypervisor.h1
-rw-r--r--arch/x86/kernel/cpu/hypervisor.c1
-rw-r--r--arch/x86/xen/enlighten.c100
3 files changed, 102 insertions, 0 deletions
diff --git a/arch/x86/include/asm/hypervisor.h b/arch/x86/include/asm/hypervisor.h
index 70abda7058c8..ff2546ce7178 100644
--- a/arch/x86/include/asm/hypervisor.h
+++ b/arch/x86/include/asm/hypervisor.h
@@ -45,5 +45,6 @@ extern const struct hypervisor_x86 *x86_hyper;
45/* Recognized hypervisors */ 45/* Recognized hypervisors */
46extern const struct hypervisor_x86 x86_hyper_vmware; 46extern const struct hypervisor_x86 x86_hyper_vmware;
47extern const struct hypervisor_x86 x86_hyper_ms_hyperv; 47extern const struct hypervisor_x86 x86_hyper_ms_hyperv;
48extern const struct hypervisor_x86 x86_hyper_xen_hvm;
48 49
49#endif 50#endif
diff --git a/arch/x86/kernel/cpu/hypervisor.c b/arch/x86/kernel/cpu/hypervisor.c
index dd531cc56a8f..bffd47c10fed 100644
--- a/arch/x86/kernel/cpu/hypervisor.c
+++ b/arch/x86/kernel/cpu/hypervisor.c
@@ -34,6 +34,7 @@ static const __initconst struct hypervisor_x86 * const hypervisors[] =
34{ 34{
35 &x86_hyper_vmware, 35 &x86_hyper_vmware,
36 &x86_hyper_ms_hyperv, 36 &x86_hyper_ms_hyperv,
37 &x86_hyper_xen_hvm,
37}; 38};
38 39
39const struct hypervisor_x86 *x86_hyper; 40const struct hypervisor_x86 *x86_hyper;
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index 65d8d79b46a8..09b36e9d507a 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -35,6 +35,7 @@
35#include <xen/interface/version.h> 35#include <xen/interface/version.h>
36#include <xen/interface/physdev.h> 36#include <xen/interface/physdev.h>
37#include <xen/interface/vcpu.h> 37#include <xen/interface/vcpu.h>
38#include <xen/interface/memory.h>
38#include <xen/features.h> 39#include <xen/features.h>
39#include <xen/page.h> 40#include <xen/page.h>
40#include <xen/hvc-console.h> 41#include <xen/hvc-console.h>
@@ -55,7 +56,9 @@
55#include <asm/pgtable.h> 56#include <asm/pgtable.h>
56#include <asm/tlbflush.h> 57#include <asm/tlbflush.h>
57#include <asm/reboot.h> 58#include <asm/reboot.h>
59#include <asm/setup.h>
58#include <asm/stackprotector.h> 60#include <asm/stackprotector.h>
61#include <asm/hypervisor.h>
59 62
60#include "xen-ops.h" 63#include "xen-ops.h"
61#include "mmu.h" 64#include "mmu.h"
@@ -76,6 +79,8 @@ struct shared_info xen_dummy_shared_info;
76 79
77void *xen_initial_gdt; 80void *xen_initial_gdt;
78 81
82RESERVE_BRK(shared_info_page_brk, PAGE_SIZE);
83
79/* 84/*
80 * Point at some empty memory to start with. We map the real shared_info 85 * Point at some empty memory to start with. We map the real shared_info
81 * page as soon as fixmap is up and running. 86 * page as soon as fixmap is up and running.
@@ -1206,3 +1211,98 @@ asmlinkage void __init xen_start_kernel(void)
1206 x86_64_start_reservations((char *)__pa_symbol(&boot_params)); 1211 x86_64_start_reservations((char *)__pa_symbol(&boot_params));
1207#endif 1212#endif
1208} 1213}
1214
1215static uint32_t xen_cpuid_base(void)
1216{
1217 uint32_t base, eax, ebx, ecx, edx;
1218 char signature[13];
1219
1220 for (base = 0x40000000; base < 0x40010000; base += 0x100) {
1221 cpuid(base, &eax, &ebx, &ecx, &edx);
1222 *(uint32_t *)(signature + 0) = ebx;
1223 *(uint32_t *)(signature + 4) = ecx;
1224 *(uint32_t *)(signature + 8) = edx;
1225 signature[12] = 0;
1226
1227 if (!strcmp("XenVMMXenVMM", signature) && ((eax - base) >= 2))
1228 return base;
1229 }
1230
1231 return 0;
1232}
1233
1234static int init_hvm_pv_info(int *major, int *minor)
1235{
1236 uint32_t eax, ebx, ecx, edx, pages, msr, base;
1237 u64 pfn;
1238
1239 base = xen_cpuid_base();
1240 cpuid(base + 1, &eax, &ebx, &ecx, &edx);
1241
1242 *major = eax >> 16;
1243 *minor = eax & 0xffff;
1244 printk(KERN_INFO "Xen version %d.%d.\n", *major, *minor);
1245
1246 cpuid(base + 2, &pages, &msr, &ecx, &edx);
1247
1248 pfn = __pa(hypercall_page);
1249 wrmsr_safe(msr, (u32)pfn, (u32)(pfn >> 32));
1250
1251 xen_setup_features();
1252
1253 pv_info = xen_info;
1254 pv_info.kernel_rpl = 0;
1255
1256 xen_domain_type = XEN_HVM_DOMAIN;
1257
1258 return 0;
1259}
1260
1261static void __init init_shared_info(void)
1262{
1263 struct xen_add_to_physmap xatp;
1264 struct shared_info *shared_info_page;
1265
1266 shared_info_page = (struct shared_info *)
1267 extend_brk(PAGE_SIZE, PAGE_SIZE);
1268 xatp.domid = DOMID_SELF;
1269 xatp.idx = 0;
1270 xatp.space = XENMAPSPACE_shared_info;
1271 xatp.gpfn = __pa(shared_info_page) >> PAGE_SHIFT;
1272 if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp))
1273 BUG();
1274
1275 HYPERVISOR_shared_info = (struct shared_info *)shared_info_page;
1276
1277 per_cpu(xen_vcpu, 0) = &HYPERVISOR_shared_info->vcpu_info[0];
1278}
1279
1280static void __init xen_hvm_guest_init(void)
1281{
1282 int r;
1283 int major, minor;
1284
1285 r = init_hvm_pv_info(&major, &minor);
1286 if (r < 0)
1287 return;
1288
1289 init_shared_info();
1290}
1291
1292static bool __init xen_hvm_platform(void)
1293{
1294 if (xen_pv_domain())
1295 return false;
1296
1297 if (!xen_cpuid_base())
1298 return false;
1299
1300 return true;
1301}
1302
1303const __refconst struct hypervisor_x86 x86_hyper_xen_hvm = {
1304 .name = "Xen HVM",
1305 .detect = xen_hvm_platform,
1306 .init_platform = xen_hvm_guest_init,
1307};
1308EXPORT_SYMBOL(x86_hyper_xen_hvm);