diff options
Diffstat (limited to 'arch/x86/xen/enlighten.c')
-rw-r--r-- | arch/x86/xen/enlighten.c | 138 |
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 | */ |
1411 | static void __init xen_setup_stackprotector(void) | 1417 | static 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 | */ | ||
1469 | static 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 | */ | ||
1495 | void __ref xen_pvh_secondary_vcpu_init(int cpu) | ||
1496 | { | ||
1497 | xen_setup_gdt(cpu); | ||
1498 | xen_pvh_set_cr_flags(cpu); | ||
1499 | } | ||
1500 | |||
1501 | static 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 */ |
1424 | asmlinkage void __init xen_start_kernel(void) | 1518 | asmlinkage 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 */ |