diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/include/asm/hypervisor.h | 1 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/hypervisor.c | 1 | ||||
-rw-r--r-- | arch/x86/xen/enlighten.c | 100 |
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 */ |
46 | extern const struct hypervisor_x86 x86_hyper_vmware; | 46 | extern const struct hypervisor_x86 x86_hyper_vmware; |
47 | extern const struct hypervisor_x86 x86_hyper_ms_hyperv; | 47 | extern const struct hypervisor_x86 x86_hyper_ms_hyperv; |
48 | extern 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 | ||
39 | const struct hypervisor_x86 *x86_hyper; | 40 | const 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 | ||
77 | void *xen_initial_gdt; | 80 | void *xen_initial_gdt; |
78 | 81 | ||
82 | RESERVE_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 | |||
1215 | static 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 | |||
1234 | static 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 | |||
1261 | static 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 | |||
1280 | static 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 | |||
1292 | static 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 | |||
1303 | const __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 | }; | ||
1308 | EXPORT_SYMBOL(x86_hyper_xen_hvm); | ||