aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/xen/enlighten.c2
-rw-r--r--arch/x86/xen/mmu.c69
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 */
2122static RESERVE_BRK_ARRAY(pmd_t, level2_kernel_pgt, PTRS_PER_PMD); 2122static RESERVE_BRK_ARRAY(pmd_t, initial_kernel_pmd, PTRS_PER_PMD);
2123static RESERVE_BRK_ARRAY(pmd_t, swapper_kernel_pmd, PTRS_PER_PMD);
2124
2125static __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,