diff options
| -rw-r--r-- | arch/x86/xen/enlighten.c | 46 |
1 files changed, 36 insertions, 10 deletions
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 87d36044054d..f64b8729cd07 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c | |||
| @@ -57,6 +57,18 @@ DEFINE_PER_CPU(struct vcpu_info *, xen_vcpu); | |||
| 57 | DEFINE_PER_CPU(struct vcpu_info, xen_vcpu_info); | 57 | DEFINE_PER_CPU(struct vcpu_info, xen_vcpu_info); |
| 58 | 58 | ||
| 59 | /* | 59 | /* |
| 60 | * Identity map, in addition to plain kernel map. This needs to be | ||
| 61 | * large enough to allocate page table pages to allocate the rest. | ||
| 62 | * Each page can map 2MB. | ||
| 63 | */ | ||
| 64 | static pte_t level1_ident_pgt[PTRS_PER_PTE * 4] __page_aligned_bss; | ||
| 65 | |||
| 66 | #ifdef CONFIG_X86_64 | ||
| 67 | /* l3 pud for userspace vsyscall mapping */ | ||
| 68 | static pud_t level3_user_vsyscall[PTRS_PER_PUD] __page_aligned_bss; | ||
| 69 | #endif /* CONFIG_X86_64 */ | ||
| 70 | |||
| 71 | /* | ||
| 60 | * Note about cr3 (pagetable base) values: | 72 | * Note about cr3 (pagetable base) values: |
| 61 | * | 73 | * |
| 62 | * xen_cr3 contains the current logical cr3 value; it contains the | 74 | * xen_cr3 contains the current logical cr3 value; it contains the |
| @@ -831,12 +843,20 @@ static int xen_pgd_alloc(struct mm_struct *mm) | |||
| 831 | #ifdef CONFIG_X86_64 | 843 | #ifdef CONFIG_X86_64 |
| 832 | { | 844 | { |
| 833 | struct page *page = virt_to_page(pgd); | 845 | struct page *page = virt_to_page(pgd); |
| 846 | pgd_t *user_pgd; | ||
| 834 | 847 | ||
| 835 | BUG_ON(page->private != 0); | 848 | BUG_ON(page->private != 0); |
| 836 | 849 | ||
| 837 | page->private = __get_free_page(GFP_KERNEL | __GFP_ZERO); | 850 | ret = -ENOMEM; |
| 838 | if (page->private == 0) | 851 | |
| 839 | ret = -ENOMEM; | 852 | user_pgd = (pgd_t *)__get_free_page(GFP_KERNEL | __GFP_ZERO); |
| 853 | page->private = (unsigned long)user_pgd; | ||
| 854 | |||
| 855 | if (user_pgd != NULL) { | ||
| 856 | user_pgd[pgd_index(VSYSCALL_START)] = | ||
| 857 | __pgd(__pa(level3_user_vsyscall) | _PAGE_TABLE); | ||
| 858 | ret = 0; | ||
| 859 | } | ||
| 840 | 860 | ||
| 841 | BUG_ON(PagePinned(virt_to_page(xen_get_user_pgd(pgd)))); | 861 | BUG_ON(PagePinned(virt_to_page(xen_get_user_pgd(pgd)))); |
| 842 | } | 862 | } |
| @@ -977,6 +997,9 @@ static __init void xen_post_allocator_init(void) | |||
| 977 | pv_mmu_ops.release_pud = xen_release_pud; | 997 | pv_mmu_ops.release_pud = xen_release_pud; |
| 978 | #endif | 998 | #endif |
| 979 | 999 | ||
| 1000 | #ifdef CONFIG_X86_64 | ||
| 1001 | SetPagePinned(virt_to_page(level3_user_vsyscall)); | ||
| 1002 | #endif | ||
| 980 | xen_mark_init_mm_pinned(); | 1003 | xen_mark_init_mm_pinned(); |
| 981 | } | 1004 | } |
| 982 | 1005 | ||
| @@ -1088,6 +1111,15 @@ static void xen_set_fixmap(unsigned idx, unsigned long phys, pgprot_t prot) | |||
| 1088 | } | 1111 | } |
| 1089 | 1112 | ||
| 1090 | __native_set_fixmap(idx, pte); | 1113 | __native_set_fixmap(idx, pte); |
| 1114 | |||
| 1115 | #ifdef CONFIG_X86_64 | ||
| 1116 | /* Replicate changes to map the vsyscall page into the user | ||
| 1117 | pagetable vsyscall mapping. */ | ||
| 1118 | if (idx >= VSYSCALL_LAST_PAGE && idx <= VSYSCALL_FIRST_PAGE) { | ||
| 1119 | unsigned long vaddr = __fix_to_virt(idx); | ||
| 1120 | set_pte_vaddr_pud(level3_user_vsyscall, vaddr, pte); | ||
| 1121 | } | ||
| 1122 | #endif | ||
| 1091 | } | 1123 | } |
| 1092 | 1124 | ||
| 1093 | static const struct pv_info xen_info __initdata = { | 1125 | static const struct pv_info xen_info __initdata = { |
| @@ -1427,13 +1459,6 @@ static void set_page_prot(void *addr, pgprot_t prot) | |||
| 1427 | BUG(); | 1459 | BUG(); |
| 1428 | } | 1460 | } |
| 1429 | 1461 | ||
| 1430 | /* | ||
| 1431 | * Identity map, in addition to plain kernel map. This needs to be | ||
| 1432 | * large enough to allocate page table pages to allocate the rest. | ||
| 1433 | * Each page can map 2MB. | ||
| 1434 | */ | ||
| 1435 | static pte_t level1_ident_pgt[PTRS_PER_PTE * 4] __page_aligned_bss; | ||
| 1436 | |||
| 1437 | static __init void xen_map_identity_early(pmd_t *pmd, unsigned long max_pfn) | 1462 | static __init void xen_map_identity_early(pmd_t *pmd, unsigned long max_pfn) |
| 1438 | { | 1463 | { |
| 1439 | unsigned pmdidx, pteidx; | 1464 | unsigned pmdidx, pteidx; |
| @@ -1533,6 +1558,7 @@ static __init pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pf | |||
| 1533 | set_page_prot(init_level4_pgt, PAGE_KERNEL_RO); | 1558 | set_page_prot(init_level4_pgt, PAGE_KERNEL_RO); |
| 1534 | set_page_prot(level3_ident_pgt, PAGE_KERNEL_RO); | 1559 | set_page_prot(level3_ident_pgt, PAGE_KERNEL_RO); |
| 1535 | set_page_prot(level3_kernel_pgt, PAGE_KERNEL_RO); | 1560 | set_page_prot(level3_kernel_pgt, PAGE_KERNEL_RO); |
| 1561 | set_page_prot(level3_user_vsyscall, PAGE_KERNEL_RO); | ||
| 1536 | set_page_prot(level2_kernel_pgt, PAGE_KERNEL_RO); | 1562 | set_page_prot(level2_kernel_pgt, PAGE_KERNEL_RO); |
| 1537 | set_page_prot(level2_fixmap_pgt, PAGE_KERNEL_RO); | 1563 | set_page_prot(level2_fixmap_pgt, PAGE_KERNEL_RO); |
| 1538 | 1564 | ||
