diff options
-rw-r--r-- | arch/x86/xen/enlighten.c | 2 | ||||
-rw-r--r-- | arch/x86/xen/mmu.c | 69 |
2 files changed, 56 insertions, 15 deletions
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 4a5973abefc8..0db7303bccb6 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c | |||
@@ -1187,8 +1187,6 @@ asmlinkage void __init xen_start_kernel(void) | |||
1187 | /* Allocate and initialize top and mid mfn levels for p2m structure */ | 1187 | /* Allocate and initialize top and mid mfn levels for p2m structure */ |
1188 | xen_build_mfn_list_list(); | 1188 | xen_build_mfn_list_list(); |
1189 | 1189 | ||
1190 | init_mm.pgd = pgd; | ||
1191 | |||
1192 | /* keep using Xen gdt for now; no urgent need to change it */ | 1190 | /* keep using Xen gdt for now; no urgent need to change it */ |
1193 | 1191 | ||
1194 | #ifdef CONFIG_X86_32 | 1192 | #ifdef CONFIG_X86_32 |
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index 21ed8d7f75a5..c9cf23e17440 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c | |||
@@ -2119,44 +2119,83 @@ __init pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd, | |||
2119 | return pgd; | 2119 | return pgd; |
2120 | } | 2120 | } |
2121 | #else /* !CONFIG_X86_64 */ | 2121 | #else /* !CONFIG_X86_64 */ |
2122 | static RESERVE_BRK_ARRAY(pmd_t, level2_kernel_pgt, PTRS_PER_PMD); | 2122 | static RESERVE_BRK_ARRAY(pmd_t, initial_kernel_pmd, PTRS_PER_PMD); |
2123 | static RESERVE_BRK_ARRAY(pmd_t, swapper_kernel_pmd, PTRS_PER_PMD); | ||
2124 | |||
2125 | static __init void xen_write_cr3_init(unsigned long cr3) | ||
2126 | { | ||
2127 | unsigned long pfn = PFN_DOWN(__pa(swapper_pg_dir)); | ||
2128 | |||
2129 | BUG_ON(read_cr3() != __pa(initial_page_table)); | ||
2130 | BUG_ON(cr3 != __pa(swapper_pg_dir)); | ||
2131 | |||
2132 | /* | ||
2133 | * We are switching to swapper_pg_dir for the first time (from | ||
2134 | * initial_page_table) and therefore need to mark that page | ||
2135 | * read-only and then pin it. | ||
2136 | * | ||
2137 | * Xen disallows sharing of kernel PMDs for PAE | ||
2138 | * guests. Therefore we must copy the kernel PMD from | ||
2139 | * initial_page_table into a new kernel PMD to be used in | ||
2140 | * swapper_pg_dir. | ||
2141 | */ | ||
2142 | swapper_kernel_pmd = | ||
2143 | extend_brk(sizeof(pmd_t) * PTRS_PER_PMD, PAGE_SIZE); | ||
2144 | memcpy(swapper_kernel_pmd, initial_kernel_pmd, | ||
2145 | sizeof(pmd_t) * PTRS_PER_PMD); | ||
2146 | swapper_pg_dir[KERNEL_PGD_BOUNDARY] = | ||
2147 | __pgd(__pa(swapper_kernel_pmd) | _PAGE_PRESENT); | ||
2148 | set_page_prot(swapper_kernel_pmd, PAGE_KERNEL_RO); | ||
2149 | |||
2150 | set_page_prot(swapper_pg_dir, PAGE_KERNEL_RO); | ||
2151 | xen_write_cr3(cr3); | ||
2152 | pin_pagetable_pfn(MMUEXT_PIN_L3_TABLE, pfn); | ||
2153 | |||
2154 | pin_pagetable_pfn(MMUEXT_UNPIN_TABLE, | ||
2155 | PFN_DOWN(__pa(initial_page_table))); | ||
2156 | set_page_prot(initial_page_table, PAGE_KERNEL); | ||
2157 | set_page_prot(initial_kernel_pmd, PAGE_KERNEL); | ||
2158 | |||
2159 | pv_mmu_ops.write_cr3 = &xen_write_cr3; | ||
2160 | } | ||
2123 | 2161 | ||
2124 | __init pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd, | 2162 | __init pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd, |
2125 | unsigned long max_pfn) | 2163 | unsigned long max_pfn) |
2126 | { | 2164 | { |
2127 | pmd_t *kernel_pmd; | 2165 | pmd_t *kernel_pmd; |
2128 | 2166 | ||
2129 | level2_kernel_pgt = extend_brk(sizeof(pmd_t) * PTRS_PER_PMD, PAGE_SIZE); | 2167 | initial_kernel_pmd = |
2168 | extend_brk(sizeof(pmd_t) * PTRS_PER_PMD, PAGE_SIZE); | ||
2130 | 2169 | ||
2131 | max_pfn_mapped = PFN_DOWN(__pa(xen_start_info->pt_base) + | 2170 | max_pfn_mapped = PFN_DOWN(__pa(xen_start_info->pt_base) + |
2132 | xen_start_info->nr_pt_frames * PAGE_SIZE + | 2171 | xen_start_info->nr_pt_frames * PAGE_SIZE + |
2133 | 512*1024); | 2172 | 512*1024); |
2134 | 2173 | ||
2135 | kernel_pmd = m2v(pgd[KERNEL_PGD_BOUNDARY].pgd); | 2174 | kernel_pmd = m2v(pgd[KERNEL_PGD_BOUNDARY].pgd); |
2136 | memcpy(level2_kernel_pgt, kernel_pmd, sizeof(pmd_t) * PTRS_PER_PMD); | 2175 | memcpy(initial_kernel_pmd, kernel_pmd, sizeof(pmd_t) * PTRS_PER_PMD); |
2137 | 2176 | ||
2138 | xen_map_identity_early(level2_kernel_pgt, max_pfn); | 2177 | xen_map_identity_early(initial_kernel_pmd, max_pfn); |
2139 | 2178 | ||
2140 | memcpy(swapper_pg_dir, pgd, sizeof(pgd_t) * PTRS_PER_PGD); | 2179 | memcpy(initial_page_table, pgd, sizeof(pgd_t) * PTRS_PER_PGD); |
2141 | set_pgd(&swapper_pg_dir[KERNEL_PGD_BOUNDARY], | 2180 | initial_page_table[KERNEL_PGD_BOUNDARY] = |
2142 | __pgd(__pa(level2_kernel_pgt) | _PAGE_PRESENT)); | 2181 | __pgd(__pa(initial_kernel_pmd) | _PAGE_PRESENT); |
2143 | 2182 | ||
2144 | set_page_prot(level2_kernel_pgt, PAGE_KERNEL_RO); | 2183 | set_page_prot(initial_kernel_pmd, PAGE_KERNEL_RO); |
2145 | set_page_prot(swapper_pg_dir, PAGE_KERNEL_RO); | 2184 | set_page_prot(initial_page_table, PAGE_KERNEL_RO); |
2146 | set_page_prot(empty_zero_page, PAGE_KERNEL_RO); | 2185 | set_page_prot(empty_zero_page, PAGE_KERNEL_RO); |
2147 | 2186 | ||
2148 | pin_pagetable_pfn(MMUEXT_UNPIN_TABLE, PFN_DOWN(__pa(pgd))); | 2187 | pin_pagetable_pfn(MMUEXT_UNPIN_TABLE, PFN_DOWN(__pa(pgd))); |
2149 | 2188 | ||
2150 | xen_write_cr3(__pa(swapper_pg_dir)); | 2189 | pin_pagetable_pfn(MMUEXT_PIN_L3_TABLE, |
2151 | 2190 | PFN_DOWN(__pa(initial_page_table))); | |
2152 | pin_pagetable_pfn(MMUEXT_PIN_L3_TABLE, PFN_DOWN(__pa(swapper_pg_dir))); | 2191 | xen_write_cr3(__pa(initial_page_table)); |
2153 | 2192 | ||
2154 | memblock_x86_reserve_range(__pa(xen_start_info->pt_base), | 2193 | memblock_x86_reserve_range(__pa(xen_start_info->pt_base), |
2155 | __pa(xen_start_info->pt_base + | 2194 | __pa(xen_start_info->pt_base + |
2156 | xen_start_info->nr_pt_frames * PAGE_SIZE), | 2195 | xen_start_info->nr_pt_frames * PAGE_SIZE), |
2157 | "XEN PAGETABLES"); | 2196 | "XEN PAGETABLES"); |
2158 | 2197 | ||
2159 | return swapper_pg_dir; | 2198 | return initial_page_table; |
2160 | } | 2199 | } |
2161 | #endif /* CONFIG_X86_64 */ | 2200 | #endif /* CONFIG_X86_64 */ |
2162 | 2201 | ||
@@ -2290,7 +2329,11 @@ static const struct pv_mmu_ops xen_mmu_ops __initdata = { | |||
2290 | .write_cr2 = xen_write_cr2, | 2329 | .write_cr2 = xen_write_cr2, |
2291 | 2330 | ||
2292 | .read_cr3 = xen_read_cr3, | 2331 | .read_cr3 = xen_read_cr3, |
2332 | #ifdef CONFIG_X86_32 | ||
2333 | .write_cr3 = xen_write_cr3_init, | ||
2334 | #else | ||
2293 | .write_cr3 = xen_write_cr3, | 2335 | .write_cr3 = xen_write_cr3, |
2336 | #endif | ||
2294 | 2337 | ||
2295 | .flush_tlb_user = xen_flush_tlb, | 2338 | .flush_tlb_user = xen_flush_tlb, |
2296 | .flush_tlb_kernel = xen_flush_tlb, | 2339 | .flush_tlb_kernel = xen_flush_tlb, |