diff options
author | Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> | 2012-09-12 11:14:33 -0400 |
---|---|---|
committer | Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> | 2012-09-12 11:14:33 -0400 |
commit | 25a765b7f05cb8460fa01b54568894b20e184862 (patch) | |
tree | 0b56db57b4d9f912393ab303c269e0fe6cdf8635 /arch/x86/xen/enlighten.c | |
parent | 9d2be9287107695708e6aae5105a8a518a6cb4d0 (diff) | |
parent | 64282278989d5b0398dcb3ba7904cb00c621dc35 (diff) |
Merge branch 'x86/platform' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip into stable/for-linus-3.7
* 'x86/platform' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (9690 commits)
x86: Document x86_init.paging.pagetable_init()
x86: xen: Cleanup and remove x86_init.paging.pagetable_setup_done()
x86: Move paging_init() call to x86_init.paging.pagetable_init()
x86: Rename pagetable_setup_start() to pagetable_init()
x86: Remove base argument from x86_init.paging.pagetable_setup_start
Linux 3.6-rc5
HID: tpkbd: work even if the new Lenovo Keyboard driver is not configured
Remove user-triggerable BUG from mpol_to_str
xen/pciback: Fix proper FLR steps.
uml: fix compile error in deliver_alarm()
dj: memory scribble in logi_dj
Fix order of arguments to compat_put_time[spec|val]
xen: Use correct masking in xen_swiotlb_alloc_coherent.
xen: fix logical error in tlb flushing
xen/p2m: Fix one-off error in checking the P2M tree directory.
powerpc: Don't use __put_user() in patch_instruction
powerpc: Make sure IPI handlers see data written by IPI senders
powerpc: Restore correct DSCR in context switch
powerpc: Fix DSCR inheritance in copy_thread()
powerpc: Keep thread.dscr and thread.dscr_inherit in sync
...
Diffstat (limited to 'arch/x86/xen/enlighten.c')
-rw-r--r-- | arch/x86/xen/enlighten.c | 112 |
1 files changed, 68 insertions, 44 deletions
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index cb1b1914dbd3..2766746de274 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <xen/interface/physdev.h> | 38 | #include <xen/interface/physdev.h> |
39 | #include <xen/interface/vcpu.h> | 39 | #include <xen/interface/vcpu.h> |
40 | #include <xen/interface/memory.h> | 40 | #include <xen/interface/memory.h> |
41 | #include <xen/interface/xen-mca.h> | ||
41 | #include <xen/features.h> | 42 | #include <xen/features.h> |
42 | #include <xen/page.h> | 43 | #include <xen/page.h> |
43 | #include <xen/hvm.h> | 44 | #include <xen/hvm.h> |
@@ -109,7 +110,7 @@ EXPORT_SYMBOL_GPL(xen_have_vector_callback); | |||
109 | * Point at some empty memory to start with. We map the real shared_info | 110 | * Point at some empty memory to start with. We map the real shared_info |
110 | * page as soon as fixmap is up and running. | 111 | * page as soon as fixmap is up and running. |
111 | */ | 112 | */ |
112 | struct shared_info *HYPERVISOR_shared_info = (void *)&xen_dummy_shared_info; | 113 | struct shared_info *HYPERVISOR_shared_info = &xen_dummy_shared_info; |
113 | 114 | ||
114 | /* | 115 | /* |
115 | * Flag to determine whether vcpu info placement is available on all | 116 | * Flag to determine whether vcpu info placement is available on all |
@@ -126,6 +127,19 @@ struct shared_info *HYPERVISOR_shared_info = (void *)&xen_dummy_shared_info; | |||
126 | */ | 127 | */ |
127 | static int have_vcpu_info_placement = 1; | 128 | static int have_vcpu_info_placement = 1; |
128 | 129 | ||
130 | struct tls_descs { | ||
131 | struct desc_struct desc[3]; | ||
132 | }; | ||
133 | |||
134 | /* | ||
135 | * Updating the 3 TLS descriptors in the GDT on every task switch is | ||
136 | * surprisingly expensive so we avoid updating them if they haven't | ||
137 | * changed. Since Xen writes different descriptors than the one | ||
138 | * passed in the update_descriptor hypercall we keep shadow copies to | ||
139 | * compare against. | ||
140 | */ | ||
141 | static DEFINE_PER_CPU(struct tls_descs, shadow_tls_desc); | ||
142 | |||
129 | static void clamp_max_cpus(void) | 143 | static void clamp_max_cpus(void) |
130 | { | 144 | { |
131 | #ifdef CONFIG_SMP | 145 | #ifdef CONFIG_SMP |
@@ -343,9 +357,7 @@ static void __init xen_init_cpuid_mask(void) | |||
343 | unsigned int xsave_mask; | 357 | unsigned int xsave_mask; |
344 | 358 | ||
345 | cpuid_leaf1_edx_mask = | 359 | cpuid_leaf1_edx_mask = |
346 | ~((1 << X86_FEATURE_MCE) | /* disable MCE */ | 360 | ~((1 << X86_FEATURE_MTRR) | /* disable MTRR */ |
347 | (1 << X86_FEATURE_MCA) | /* disable MCA */ | ||
348 | (1 << X86_FEATURE_MTRR) | /* disable MTRR */ | ||
349 | (1 << X86_FEATURE_ACC)); /* thermal monitoring */ | 361 | (1 << X86_FEATURE_ACC)); /* thermal monitoring */ |
350 | 362 | ||
351 | if (!xen_initial_domain()) | 363 | if (!xen_initial_domain()) |
@@ -542,12 +554,28 @@ static void __init xen_load_gdt_boot(const struct desc_ptr *dtr) | |||
542 | BUG(); | 554 | BUG(); |
543 | } | 555 | } |
544 | 556 | ||
557 | static inline bool desc_equal(const struct desc_struct *d1, | ||
558 | const struct desc_struct *d2) | ||
559 | { | ||
560 | return d1->a == d2->a && d1->b == d2->b; | ||
561 | } | ||
562 | |||
545 | static void load_TLS_descriptor(struct thread_struct *t, | 563 | static void load_TLS_descriptor(struct thread_struct *t, |
546 | unsigned int cpu, unsigned int i) | 564 | unsigned int cpu, unsigned int i) |
547 | { | 565 | { |
548 | struct desc_struct *gdt = get_cpu_gdt_table(cpu); | 566 | struct desc_struct *shadow = &per_cpu(shadow_tls_desc, cpu).desc[i]; |
549 | xmaddr_t maddr = arbitrary_virt_to_machine(&gdt[GDT_ENTRY_TLS_MIN+i]); | 567 | struct desc_struct *gdt; |
550 | struct multicall_space mc = __xen_mc_entry(0); | 568 | xmaddr_t maddr; |
569 | struct multicall_space mc; | ||
570 | |||
571 | if (desc_equal(shadow, &t->tls_array[i])) | ||
572 | return; | ||
573 | |||
574 | *shadow = t->tls_array[i]; | ||
575 | |||
576 | gdt = get_cpu_gdt_table(cpu); | ||
577 | maddr = arbitrary_virt_to_machine(&gdt[GDT_ENTRY_TLS_MIN+i]); | ||
578 | mc = __xen_mc_entry(0); | ||
551 | 579 | ||
552 | MULTI_update_descriptor(mc.mc, maddr.maddr, t->tls_array[i]); | 580 | MULTI_update_descriptor(mc.mc, maddr.maddr, t->tls_array[i]); |
553 | } | 581 | } |
@@ -629,8 +657,8 @@ static int cvt_gate_to_trap(int vector, const gate_desc *val, | |||
629 | /* | 657 | /* |
630 | * Look for known traps using IST, and substitute them | 658 | * Look for known traps using IST, and substitute them |
631 | * appropriately. The debugger ones are the only ones we care | 659 | * appropriately. The debugger ones are the only ones we care |
632 | * about. Xen will handle faults like double_fault and | 660 | * about. Xen will handle faults like double_fault, |
633 | * machine_check, so we should never see them. Warn if | 661 | * so we should never see them. Warn if |
634 | * there's an unexpected IST-using fault handler. | 662 | * there's an unexpected IST-using fault handler. |
635 | */ | 663 | */ |
636 | if (addr == (unsigned long)debug) | 664 | if (addr == (unsigned long)debug) |
@@ -645,7 +673,11 @@ static int cvt_gate_to_trap(int vector, const gate_desc *val, | |||
645 | return 0; | 673 | return 0; |
646 | #ifdef CONFIG_X86_MCE | 674 | #ifdef CONFIG_X86_MCE |
647 | } else if (addr == (unsigned long)machine_check) { | 675 | } else if (addr == (unsigned long)machine_check) { |
648 | return 0; | 676 | /* |
677 | * when xen hypervisor inject vMCE to guest, | ||
678 | * use native mce handler to handle it | ||
679 | */ | ||
680 | ; | ||
649 | #endif | 681 | #endif |
650 | } else { | 682 | } else { |
651 | /* Some other trap using IST? */ | 683 | /* Some other trap using IST? */ |
@@ -1126,9 +1158,7 @@ static const struct pv_cpu_ops xen_cpu_ops __initconst = { | |||
1126 | .wbinvd = native_wbinvd, | 1158 | .wbinvd = native_wbinvd, |
1127 | 1159 | ||
1128 | .read_msr = native_read_msr_safe, | 1160 | .read_msr = native_read_msr_safe, |
1129 | .rdmsr_regs = native_rdmsr_safe_regs, | ||
1130 | .write_msr = xen_write_msr_safe, | 1161 | .write_msr = xen_write_msr_safe, |
1131 | .wrmsr_regs = native_wrmsr_safe_regs, | ||
1132 | 1162 | ||
1133 | .read_tsc = native_read_tsc, | 1163 | .read_tsc = native_read_tsc, |
1134 | .read_pmc = native_read_pmc, | 1164 | .read_pmc = native_read_pmc, |
@@ -1441,32 +1471,6 @@ asmlinkage void __init xen_start_kernel(void) | |||
1441 | #endif | 1471 | #endif |
1442 | } | 1472 | } |
1443 | 1473 | ||
1444 | static int init_hvm_pv_info(int *major, int *minor) | ||
1445 | { | ||
1446 | uint32_t eax, ebx, ecx, edx, pages, msr, base; | ||
1447 | u64 pfn; | ||
1448 | |||
1449 | base = xen_cpuid_base(); | ||
1450 | cpuid(base + 1, &eax, &ebx, &ecx, &edx); | ||
1451 | |||
1452 | *major = eax >> 16; | ||
1453 | *minor = eax & 0xffff; | ||
1454 | printk(KERN_INFO "Xen version %d.%d.\n", *major, *minor); | ||
1455 | |||
1456 | cpuid(base + 2, &pages, &msr, &ecx, &edx); | ||
1457 | |||
1458 | pfn = __pa(hypercall_page); | ||
1459 | wrmsr_safe(msr, (u32)pfn, (u32)(pfn >> 32)); | ||
1460 | |||
1461 | xen_setup_features(); | ||
1462 | |||
1463 | pv_info.name = "Xen HVM"; | ||
1464 | |||
1465 | xen_domain_type = XEN_HVM_DOMAIN; | ||
1466 | |||
1467 | return 0; | ||
1468 | } | ||
1469 | |||
1470 | void __ref xen_hvm_init_shared_info(void) | 1474 | void __ref xen_hvm_init_shared_info(void) |
1471 | { | 1475 | { |
1472 | int cpu; | 1476 | int cpu; |
@@ -1499,6 +1503,31 @@ void __ref xen_hvm_init_shared_info(void) | |||
1499 | } | 1503 | } |
1500 | 1504 | ||
1501 | #ifdef CONFIG_XEN_PVHVM | 1505 | #ifdef CONFIG_XEN_PVHVM |
1506 | static void __init init_hvm_pv_info(void) | ||
1507 | { | ||
1508 | int major, minor; | ||
1509 | uint32_t eax, ebx, ecx, edx, pages, msr, base; | ||
1510 | u64 pfn; | ||
1511 | |||
1512 | base = xen_cpuid_base(); | ||
1513 | cpuid(base + 1, &eax, &ebx, &ecx, &edx); | ||
1514 | |||
1515 | major = eax >> 16; | ||
1516 | minor = eax & 0xffff; | ||
1517 | printk(KERN_INFO "Xen version %d.%d.\n", major, minor); | ||
1518 | |||
1519 | cpuid(base + 2, &pages, &msr, &ecx, &edx); | ||
1520 | |||
1521 | pfn = __pa(hypercall_page); | ||
1522 | wrmsr_safe(msr, (u32)pfn, (u32)(pfn >> 32)); | ||
1523 | |||
1524 | xen_setup_features(); | ||
1525 | |||
1526 | pv_info.name = "Xen HVM"; | ||
1527 | |||
1528 | xen_domain_type = XEN_HVM_DOMAIN; | ||
1529 | } | ||
1530 | |||
1502 | static int __cpuinit xen_hvm_cpu_notify(struct notifier_block *self, | 1531 | static int __cpuinit xen_hvm_cpu_notify(struct notifier_block *self, |
1503 | unsigned long action, void *hcpu) | 1532 | unsigned long action, void *hcpu) |
1504 | { | 1533 | { |
@@ -1521,12 +1550,7 @@ static struct notifier_block xen_hvm_cpu_notifier __cpuinitdata = { | |||
1521 | 1550 | ||
1522 | static void __init xen_hvm_guest_init(void) | 1551 | static void __init xen_hvm_guest_init(void) |
1523 | { | 1552 | { |
1524 | int r; | 1553 | init_hvm_pv_info(); |
1525 | int major, minor; | ||
1526 | |||
1527 | r = init_hvm_pv_info(&major, &minor); | ||
1528 | if (r < 0) | ||
1529 | return; | ||
1530 | 1554 | ||
1531 | xen_hvm_init_shared_info(); | 1555 | xen_hvm_init_shared_info(); |
1532 | 1556 | ||