aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/xen/enlighten.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/xen/enlighten.c')
-rw-r--r--arch/x86/xen/enlighten.c138
1 files changed, 118 insertions, 20 deletions
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index fa6ade76ef3f..201d09a7c46b 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -262,8 +262,9 @@ static void __init xen_banner(void)
262 struct xen_extraversion extra; 262 struct xen_extraversion extra;
263 HYPERVISOR_xen_version(XENVER_extraversion, &extra); 263 HYPERVISOR_xen_version(XENVER_extraversion, &extra);
264 264
265 printk(KERN_INFO "Booting paravirtualized kernel on %s\n", 265 pr_info("Booting paravirtualized kernel %son %s\n",
266 pv_info.name); 266 xen_feature(XENFEAT_auto_translated_physmap) ?
267 "with PVH extensions " : "", pv_info.name);
267 printk(KERN_INFO "Xen version: %d.%d%s%s\n", 268 printk(KERN_INFO "Xen version: %d.%d%s%s\n",
268 version >> 16, version & 0xffff, extra.extraversion, 269 version >> 16, version & 0xffff, extra.extraversion,
269 xen_feature(XENFEAT_mmu_pt_update_preserve_ad) ? " (preserve-AD)" : ""); 270 xen_feature(XENFEAT_mmu_pt_update_preserve_ad) ? " (preserve-AD)" : "");
@@ -433,7 +434,7 @@ static void __init xen_init_cpuid_mask(void)
433 434
434 ax = 1; 435 ax = 1;
435 cx = 0; 436 cx = 0;
436 xen_cpuid(&ax, &bx, &cx, &dx); 437 cpuid(1, &ax, &bx, &cx, &dx);
437 438
438 xsave_mask = 439 xsave_mask =
439 (1 << (X86_FEATURE_XSAVE % 32)) | 440 (1 << (X86_FEATURE_XSAVE % 32)) |
@@ -1142,8 +1143,9 @@ void xen_setup_vcpu_info_placement(void)
1142 xen_vcpu_setup(cpu); 1143 xen_vcpu_setup(cpu);
1143 1144
1144 /* xen_vcpu_setup managed to place the vcpu_info within the 1145 /* xen_vcpu_setup managed to place the vcpu_info within the
1145 percpu area for all cpus, so make use of it */ 1146 * percpu area for all cpus, so make use of it. Note that for
1146 if (have_vcpu_info_placement) { 1147 * PVH we want to use native IRQ mechanism. */
1148 if (have_vcpu_info_placement && !xen_pvh_domain()) {
1147 pv_irq_ops.save_fl = __PV_IS_CALLEE_SAVE(xen_save_fl_direct); 1149 pv_irq_ops.save_fl = __PV_IS_CALLEE_SAVE(xen_save_fl_direct);
1148 pv_irq_ops.restore_fl = __PV_IS_CALLEE_SAVE(xen_restore_fl_direct); 1150 pv_irq_ops.restore_fl = __PV_IS_CALLEE_SAVE(xen_restore_fl_direct);
1149 pv_irq_ops.irq_disable = __PV_IS_CALLEE_SAVE(xen_irq_disable_direct); 1151 pv_irq_ops.irq_disable = __PV_IS_CALLEE_SAVE(xen_irq_disable_direct);
@@ -1407,9 +1409,49 @@ static void __init xen_boot_params_init_edd(void)
1407 * Set up the GDT and segment registers for -fstack-protector. Until 1409 * Set up the GDT and segment registers for -fstack-protector. Until
1408 * we do this, we have to be careful not to call any stack-protected 1410 * we do this, we have to be careful not to call any stack-protected
1409 * function, which is most of the kernel. 1411 * function, which is most of the kernel.
1412 *
1413 * Note, that it is __ref because the only caller of this after init
1414 * is PVH which is not going to use xen_load_gdt_boot or other
1415 * __init functions.
1410 */ 1416 */
1411static void __init xen_setup_stackprotector(void) 1417static void __ref xen_setup_gdt(int cpu)
1412{ 1418{
1419 if (xen_feature(XENFEAT_auto_translated_physmap)) {
1420#ifdef CONFIG_X86_64
1421 unsigned long dummy;
1422
1423 load_percpu_segment(cpu); /* We need to access per-cpu area */
1424 switch_to_new_gdt(cpu); /* GDT and GS set */
1425
1426 /* We are switching of the Xen provided GDT to our HVM mode
1427 * GDT. The new GDT has __KERNEL_CS with CS.L = 1
1428 * and we are jumping to reload it.
1429 */
1430 asm volatile ("pushq %0\n"
1431 "leaq 1f(%%rip),%0\n"
1432 "pushq %0\n"
1433 "lretq\n"
1434 "1:\n"
1435 : "=&r" (dummy) : "0" (__KERNEL_CS));
1436
1437 /*
1438 * While not needed, we also set the %es, %ds, and %fs
1439 * to zero. We don't care about %ss as it is NULL.
1440 * Strictly speaking this is not needed as Xen zeros those
1441 * out (and also MSR_FS_BASE, MSR_GS_BASE, MSR_KERNEL_GS_BASE)
1442 *
1443 * Linux zeros them in cpu_init() and in secondary_startup_64
1444 * (for BSP).
1445 */
1446 loadsegment(es, 0);
1447 loadsegment(ds, 0);
1448 loadsegment(fs, 0);
1449#else
1450 /* PVH: TODO Implement. */
1451 BUG();
1452#endif
1453 return; /* PVH does not need any PV GDT ops. */
1454 }
1413 pv_cpu_ops.write_gdt_entry = xen_write_gdt_entry_boot; 1455 pv_cpu_ops.write_gdt_entry = xen_write_gdt_entry_boot;
1414 pv_cpu_ops.load_gdt = xen_load_gdt_boot; 1456 pv_cpu_ops.load_gdt = xen_load_gdt_boot;
1415 1457
@@ -1420,6 +1462,58 @@ static void __init xen_setup_stackprotector(void)
1420 pv_cpu_ops.load_gdt = xen_load_gdt; 1462 pv_cpu_ops.load_gdt = xen_load_gdt;
1421} 1463}
1422 1464
1465/*
1466 * A PV guest starts with default flags that are not set for PVH, set them
1467 * here asap.
1468 */
1469static void xen_pvh_set_cr_flags(int cpu)
1470{
1471
1472 /* Some of these are setup in 'secondary_startup_64'. The others:
1473 * X86_CR0_TS, X86_CR0_PE, X86_CR0_ET are set by Xen for HVM guests
1474 * (which PVH shared codepaths), while X86_CR0_PG is for PVH. */
1475 write_cr0(read_cr0() | X86_CR0_MP | X86_CR0_NE | X86_CR0_WP | X86_CR0_AM);
1476
1477 if (!cpu)
1478 return;
1479 /*
1480 * For BSP, PSE PGE are set in probe_page_size_mask(), for APs
1481 * set them here. For all, OSFXSR OSXMMEXCPT are set in fpu_init.
1482 */
1483 if (cpu_has_pse)
1484 set_in_cr4(X86_CR4_PSE);
1485
1486 if (cpu_has_pge)
1487 set_in_cr4(X86_CR4_PGE);
1488}
1489
1490/*
1491 * Note, that it is ref - because the only caller of this after init
1492 * is PVH which is not going to use xen_load_gdt_boot or other
1493 * __init functions.
1494 */
1495void __ref xen_pvh_secondary_vcpu_init(int cpu)
1496{
1497 xen_setup_gdt(cpu);
1498 xen_pvh_set_cr_flags(cpu);
1499}
1500
1501static void __init xen_pvh_early_guest_init(void)
1502{
1503 if (!xen_feature(XENFEAT_auto_translated_physmap))
1504 return;
1505
1506 if (!xen_feature(XENFEAT_hvm_callback_vector))
1507 return;
1508
1509 xen_have_vector_callback = 1;
1510 xen_pvh_set_cr_flags(0);
1511
1512#ifdef CONFIG_X86_32
1513 BUG(); /* PVH: Implement proper support. */
1514#endif
1515}
1516
1423/* First C function to be called on Xen boot */ 1517/* First C function to be called on Xen boot */
1424asmlinkage void __init xen_start_kernel(void) 1518asmlinkage void __init xen_start_kernel(void)
1425{ 1519{
@@ -1431,13 +1525,16 @@ asmlinkage void __init xen_start_kernel(void)
1431 1525
1432 xen_domain_type = XEN_PV_DOMAIN; 1526 xen_domain_type = XEN_PV_DOMAIN;
1433 1527
1528 xen_setup_features();
1529 xen_pvh_early_guest_init();
1434 xen_setup_machphys_mapping(); 1530 xen_setup_machphys_mapping();
1435 1531
1436 /* Install Xen paravirt ops */ 1532 /* Install Xen paravirt ops */
1437 pv_info = xen_info; 1533 pv_info = xen_info;
1438 pv_init_ops = xen_init_ops; 1534 pv_init_ops = xen_init_ops;
1439 pv_cpu_ops = xen_cpu_ops;
1440 pv_apic_ops = xen_apic_ops; 1535 pv_apic_ops = xen_apic_ops;
1536 if (!xen_pvh_domain())
1537 pv_cpu_ops = xen_cpu_ops;
1441 1538
1442 x86_init.resources.memory_setup = xen_memory_setup; 1539 x86_init.resources.memory_setup = xen_memory_setup;
1443 x86_init.oem.arch_setup = xen_arch_setup; 1540 x86_init.oem.arch_setup = xen_arch_setup;
@@ -1469,17 +1566,14 @@ asmlinkage void __init xen_start_kernel(void)
1469 /* Work out if we support NX */ 1566 /* Work out if we support NX */
1470 x86_configure_nx(); 1567 x86_configure_nx();
1471 1568
1472 xen_setup_features();
1473
1474 /* Get mfn list */ 1569 /* Get mfn list */
1475 if (!xen_feature(XENFEAT_auto_translated_physmap)) 1570 xen_build_dynamic_phys_to_machine();
1476 xen_build_dynamic_phys_to_machine();
1477 1571
1478 /* 1572 /*
1479 * Set up kernel GDT and segment registers, mainly so that 1573 * Set up kernel GDT and segment registers, mainly so that
1480 * -fstack-protector code can be executed. 1574 * -fstack-protector code can be executed.
1481 */ 1575 */
1482 xen_setup_stackprotector(); 1576 xen_setup_gdt(0);
1483 1577
1484 xen_init_irq_ops(); 1578 xen_init_irq_ops();
1485 xen_init_cpuid_mask(); 1579 xen_init_cpuid_mask();
@@ -1548,14 +1642,18 @@ asmlinkage void __init xen_start_kernel(void)
1548 /* set the limit of our address space */ 1642 /* set the limit of our address space */
1549 xen_reserve_top(); 1643 xen_reserve_top();
1550 1644
1551 /* We used to do this in xen_arch_setup, but that is too late on AMD 1645 /* PVH: runs at default kernel iopl of 0 */
1552 * were early_cpu_init (run before ->arch_setup()) calls early_amd_init 1646 if (!xen_pvh_domain()) {
1553 * which pokes 0xcf8 port. 1647 /*
1554 */ 1648 * We used to do this in xen_arch_setup, but that is too late
1555 set_iopl.iopl = 1; 1649 * on AMD were early_cpu_init (run before ->arch_setup()) calls
1556 rc = HYPERVISOR_physdev_op(PHYSDEVOP_set_iopl, &set_iopl); 1650 * early_amd_init which pokes 0xcf8 port.
1557 if (rc != 0) 1651 */
1558 xen_raw_printk("physdev_op failed %d\n", rc); 1652 set_iopl.iopl = 1;
1653 rc = HYPERVISOR_physdev_op(PHYSDEVOP_set_iopl, &set_iopl);
1654 if (rc != 0)
1655 xen_raw_printk("physdev_op failed %d\n", rc);
1656 }
1559 1657
1560#ifdef CONFIG_X86_32 1658#ifdef CONFIG_X86_32
1561 /* set up basic CPUID stuff */ 1659 /* set up basic CPUID stuff */