aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/xen/enlighten.c
diff options
context:
space:
mode:
authorJeremy Fitzhardinge <jeremy@goop.org>2008-07-08 18:06:53 -0400
committerIngo Molnar <mingo@elte.hu>2008-07-16 05:00:49 -0400
commit39dbc5bd345ebf93e066dde7f8e29467eb61b42e (patch)
treee86122d1ce65d152b6d2c523e052e16f06ae72fb /arch/x86/xen/enlighten.c
parentd114e1981cc1a51131230993a082c27c79ab370a (diff)
xen32: create initial mappings like 64-bit
Rearrange the pagetable initialization to share code with the 64-bit kernel. Rather than deferring anything to pagetable_setup_start, just set up an initial pagetable in swapper_pg_dir early at startup, and create an additional 8MB of physical memory mappings. This matches the native head_32.S mappings to a large degree, and allows the rest of the pagetable setup to continue without much Xen vs. native difference. Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com> Cc: Stephen Tweedie <sct@redhat.com> Cc: Eduardo Habkost <ehabkost@redhat.com> Cc: Mark McLoughlin <markmc@redhat.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/xen/enlighten.c')
-rw-r--r--arch/x86/xen/enlighten.c130
1 files changed, 52 insertions, 78 deletions
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index e9e3bafe48cf..19c12a6c7311 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -854,50 +854,6 @@ static __init void xen_set_pte_init(pte_t *ptep, pte_t pte)
854 854
855static __init void xen_pagetable_setup_start(pgd_t *base) 855static __init void xen_pagetable_setup_start(pgd_t *base)
856{ 856{
857#ifdef CONFIG_X86_32
858 pgd_t *xen_pgd = (pgd_t *)xen_start_info->pt_base;
859 int i;
860
861 init_mm.pgd = base;
862 /*
863 * copy top-level of Xen-supplied pagetable into place. This
864 * is a stand-in while we copy the pmd pages.
865 */
866 memcpy(base, xen_pgd, PTRS_PER_PGD * sizeof(pgd_t));
867
868 /*
869 * For PAE, need to allocate new pmds, rather than
870 * share Xen's, since Xen doesn't like pmd's being
871 * shared between address spaces.
872 */
873 for (i = 0; i < PTRS_PER_PGD; i++) {
874 if (pgd_val_ma(xen_pgd[i]) & _PAGE_PRESENT) {
875 pmd_t *pmd = (pmd_t *)alloc_bootmem_low_pages(PAGE_SIZE);
876
877 memcpy(pmd, (void *)pgd_page_vaddr(xen_pgd[i]),
878 PAGE_SIZE);
879
880 make_lowmem_page_readonly(pmd);
881
882 set_pgd(&base[i], __pgd(1 + __pa(pmd)));
883 } else
884 pgd_clear(&base[i]);
885 }
886
887 /* make sure zero_page is mapped RO so we can use it in pagetables */
888 make_lowmem_page_readonly(empty_zero_page);
889 make_lowmem_page_readonly(base);
890 /*
891 * Switch to new pagetable. This is done before
892 * pagetable_init has done anything so that the new pages
893 * added to the table can be prepared properly for Xen.
894 */
895 xen_write_cr3(__pa(base));
896
897 /* Unpin initial Xen pagetable */
898 pin_pagetable_pfn(MMUEXT_UNPIN_TABLE,
899 PFN_DOWN(__pa(xen_start_info->pt_base)));
900#endif /* CONFIG_X86_32 */
901} 857}
902 858
903void xen_setup_shared_info(void) 859void xen_setup_shared_info(void)
@@ -936,12 +892,6 @@ static __init void xen_pagetable_setup_done(pgd_t *base)
936 pv_mmu_ops.set_pte = xen_set_pte; 892 pv_mmu_ops.set_pte = xen_set_pte;
937 893
938 xen_setup_shared_info(); 894 xen_setup_shared_info();
939
940#ifdef CONFIG_X86_32
941 /* Actually pin the pagetable down, but we can't set PG_pinned
942 yet because the page structures don't exist yet. */
943 pin_pagetable_pfn(MMUEXT_PIN_L3_TABLE, PFN_DOWN(__pa(base)));
944#endif
945} 895}
946 896
947static __init void xen_post_allocator_init(void) 897static __init void xen_post_allocator_init(void)
@@ -1299,14 +1249,17 @@ static void __init xen_reserve_top(void)
1299#endif /* CONFIG_X86_32 */ 1249#endif /* CONFIG_X86_32 */
1300} 1250}
1301 1251
1302#ifdef CONFIG_X86_64
1303/* 1252/*
1304 * Like __va(), but returns address in the kernel mapping (which is 1253 * Like __va(), but returns address in the kernel mapping (which is
1305 * all we have until the physical memory mapping has been set up. 1254 * all we have until the physical memory mapping has been set up.
1306 */ 1255 */
1307static void *__ka(phys_addr_t paddr) 1256static void *__ka(phys_addr_t paddr)
1308{ 1257{
1258#ifdef CONFIG_X86_64
1309 return (void *)(paddr + __START_KERNEL_map); 1259 return (void *)(paddr + __START_KERNEL_map);
1260#else
1261 return __va(paddr);
1262#endif
1310} 1263}
1311 1264
1312/* Convert a machine address to physical address */ 1265/* Convert a machine address to physical address */
@@ -1326,6 +1279,7 @@ static void *m2v(phys_addr_t maddr)
1326 return __ka(m2p(maddr)); 1279 return __ka(m2p(maddr));
1327} 1280}
1328 1281
1282#ifdef CONFIG_X86_64
1329static void walk(pgd_t *pgd, unsigned long addr) 1283static void walk(pgd_t *pgd, unsigned long addr)
1330{ 1284{
1331 unsigned l4idx = pgd_index(addr); 1285 unsigned l4idx = pgd_index(addr);
@@ -1356,13 +1310,14 @@ static void walk(pgd_t *pgd, unsigned long addr)
1356 xen_raw_printk(" l1: %016lx\n", l1.pte); 1310 xen_raw_printk(" l1: %016lx\n", l1.pte);
1357 xen_raw_printk(" %016lx\n", pte_val(l1)); 1311 xen_raw_printk(" %016lx\n", pte_val(l1));
1358} 1312}
1313#endif
1359 1314
1360static void set_page_prot(void *addr, pgprot_t prot) 1315static void set_page_prot(void *addr, pgprot_t prot)
1361{ 1316{
1362 unsigned long pfn = __pa(addr) >> PAGE_SHIFT; 1317 unsigned long pfn = __pa(addr) >> PAGE_SHIFT;
1363 pte_t pte = pfn_pte(pfn, prot); 1318 pte_t pte = pfn_pte(pfn, prot);
1364 1319
1365 xen_raw_printk("addr=%p pfn=%lx mfn=%lx prot=%016x pte=%016x\n", 1320 xen_raw_printk("addr=%p pfn=%lx mfn=%lx prot=%016llx pte=%016llx\n",
1366 addr, pfn, get_phys_to_machine(pfn), 1321 addr, pfn, get_phys_to_machine(pfn),
1367 pgprot_val(prot), pte.pte); 1322 pgprot_val(prot), pte.pte);
1368 1323
@@ -1370,17 +1325,6 @@ static void set_page_prot(void *addr, pgprot_t prot)
1370 BUG(); 1325 BUG();
1371} 1326}
1372 1327
1373static void convert_pfn_mfn(void *v)
1374{
1375 pte_t *pte = v;
1376 int i;
1377
1378 /* All levels are converted the same way, so just treat them
1379 as ptes. */
1380 for(i = 0; i < PTRS_PER_PTE; i++)
1381 pte[i] = xen_make_pte(pte[i].pte);
1382}
1383
1384/* 1328/*
1385 * Identity map, in addition to plain kernel map. This needs to be 1329 * Identity map, in addition to plain kernel map. This needs to be
1386 * large enough to allocate page table pages to allocate the rest. 1330 * large enough to allocate page table pages to allocate the rest.
@@ -1388,7 +1332,7 @@ static void convert_pfn_mfn(void *v)
1388 */ 1332 */
1389static pte_t level1_ident_pgt[PTRS_PER_PTE * 4] __page_aligned_bss; 1333static pte_t level1_ident_pgt[PTRS_PER_PTE * 4] __page_aligned_bss;
1390 1334
1391static __init void xen_map_identity_early(unsigned long max_pfn) 1335static __init void xen_map_identity_early(pmd_t *pmd, unsigned long max_pfn)
1392{ 1336{
1393 unsigned pmdidx, pteidx; 1337 unsigned pmdidx, pteidx;
1394 unsigned ident_pte; 1338 unsigned ident_pte;
@@ -1399,11 +1343,9 @@ static __init void xen_map_identity_early(unsigned long max_pfn)
1399 for(pmdidx = 0; pmdidx < PTRS_PER_PMD && pfn < max_pfn; pmdidx++) { 1343 for(pmdidx = 0; pmdidx < PTRS_PER_PMD && pfn < max_pfn; pmdidx++) {
1400 pte_t *pte_page; 1344 pte_t *pte_page;
1401 1345
1402 BUG_ON(level2_ident_pgt[pmdidx].pmd != level2_kernel_pgt[pmdidx].pmd);
1403
1404 /* Reuse or allocate a page of ptes */ 1346 /* Reuse or allocate a page of ptes */
1405 if (pmd_present(level2_ident_pgt[pmdidx])) 1347 if (pmd_present(pmd[pmdidx]))
1406 pte_page = m2v(level2_ident_pgt[pmdidx].pmd); 1348 pte_page = m2v(pmd[pmdidx].pmd);
1407 else { 1349 else {
1408 /* Check for free pte pages */ 1350 /* Check for free pte pages */
1409 if (ident_pte == ARRAY_SIZE(level1_ident_pgt)) 1351 if (ident_pte == ARRAY_SIZE(level1_ident_pgt))
@@ -1412,9 +1354,7 @@ static __init void xen_map_identity_early(unsigned long max_pfn)
1412 pte_page = &level1_ident_pgt[ident_pte]; 1354 pte_page = &level1_ident_pgt[ident_pte];
1413 ident_pte += PTRS_PER_PTE; 1355 ident_pte += PTRS_PER_PTE;
1414 1356
1415 /* Install new l1 in l2(s) */ 1357 pmd[pmdidx] = __pmd(__pa(pte_page) | _PAGE_TABLE);
1416 level2_ident_pgt[pmdidx] = __pmd(__pa(pte_page) | _PAGE_TABLE);
1417 level2_kernel_pgt[pmdidx] = level2_ident_pgt[pmdidx];
1418 } 1358 }
1419 1359
1420 /* Install mappings */ 1360 /* Install mappings */
@@ -1434,6 +1374,20 @@ static __init void xen_map_identity_early(unsigned long max_pfn)
1434 1374
1435 for(pteidx = 0; pteidx < ident_pte; pteidx += PTRS_PER_PTE) 1375 for(pteidx = 0; pteidx < ident_pte; pteidx += PTRS_PER_PTE)
1436 set_page_prot(&level1_ident_pgt[pteidx], PAGE_KERNEL_RO); 1376 set_page_prot(&level1_ident_pgt[pteidx], PAGE_KERNEL_RO);
1377
1378 set_page_prot(pmd, PAGE_KERNEL_RO);
1379}
1380
1381#ifdef CONFIG_X86_64
1382static void convert_pfn_mfn(void *v)
1383{
1384 pte_t *pte = v;
1385 int i;
1386
1387 /* All levels are converted the same way, so just treat them
1388 as ptes. */
1389 for(i = 0; i < PTRS_PER_PTE; i++)
1390 pte[i] = xen_make_pte(pte[i].pte);
1437} 1391}
1438 1392
1439/* 1393/*
@@ -1471,18 +1425,18 @@ static __init pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pf
1471 memcpy(level2_fixmap_pgt, l2, sizeof(pmd_t) * PTRS_PER_PMD); 1425 memcpy(level2_fixmap_pgt, l2, sizeof(pmd_t) * PTRS_PER_PMD);
1472 1426
1473 /* Set up identity map */ 1427 /* Set up identity map */
1474 xen_map_identity_early(max_pfn); 1428 xen_map_identity_early(level2_ident_pgt, max_pfn);
1475 1429
1476 /* Make pagetable pieces RO */ 1430 /* Make pagetable pieces RO */
1477 set_page_prot(init_level4_pgt, PAGE_KERNEL_RO); 1431 set_page_prot(init_level4_pgt, PAGE_KERNEL_RO);
1478 set_page_prot(level3_ident_pgt, PAGE_KERNEL_RO); 1432 set_page_prot(level3_ident_pgt, PAGE_KERNEL_RO);
1479 set_page_prot(level3_kernel_pgt, PAGE_KERNEL_RO); 1433 set_page_prot(level3_kernel_pgt, PAGE_KERNEL_RO);
1480 set_page_prot(level2_ident_pgt, PAGE_KERNEL_RO);
1481 set_page_prot(level2_kernel_pgt, PAGE_KERNEL_RO); 1434 set_page_prot(level2_kernel_pgt, PAGE_KERNEL_RO);
1482 set_page_prot(level2_fixmap_pgt, PAGE_KERNEL_RO); 1435 set_page_prot(level2_fixmap_pgt, PAGE_KERNEL_RO);
1483 1436
1484 /* Pin down new L4 */ 1437 /* Pin down new L4 */
1485 pin_pagetable_pfn(MMUEXT_PIN_L4_TABLE, PFN_DOWN(__pa_symbol(init_level4_pgt))); 1438 pin_pagetable_pfn(MMUEXT_PIN_L4_TABLE,
1439 PFN_DOWN(__pa_symbol(init_level4_pgt)));
1486 1440
1487 /* Unpin Xen-provided one */ 1441 /* Unpin Xen-provided one */
1488 pin_pagetable_pfn(MMUEXT_UNPIN_TABLE, PFN_DOWN(__pa(pgd))); 1442 pin_pagetable_pfn(MMUEXT_UNPIN_TABLE, PFN_DOWN(__pa(pgd)));
@@ -1498,17 +1452,37 @@ static __init pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pf
1498 1452
1499 return pgd; 1453 return pgd;
1500} 1454}
1501#else 1455#else /* !CONFIG_X86_64 */
1456static pmd_t level2_kernel_pgt[PTRS_PER_PMD] __page_aligned_bss;
1457
1502static __init pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn) 1458static __init pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn)
1503{ 1459{
1460 pmd_t *kernel_pmd;
1461
1504 init_pg_tables_start = __pa(pgd); 1462 init_pg_tables_start = __pa(pgd);
1505 init_pg_tables_end = __pa(pgd) + xen_start_info->nr_pt_frames*PAGE_SIZE; 1463 init_pg_tables_end = __pa(pgd) + xen_start_info->nr_pt_frames*PAGE_SIZE;
1506 max_pfn_mapped = PFN_DOWN(init_pg_tables_end + 512*1024); 1464 max_pfn_mapped = PFN_DOWN(init_pg_tables_end + 512*1024);
1507 1465
1508 x86_write_percpu(xen_cr3, __pa(pgd)); 1466 kernel_pmd = m2v(pgd[KERNEL_PGD_BOUNDARY].pgd);
1509 x86_write_percpu(xen_current_cr3, __pa(pgd)); 1467 memcpy(level2_kernel_pgt, kernel_pmd, sizeof(pmd_t) * PTRS_PER_PMD);
1510 1468
1511 return pgd; 1469 xen_map_identity_early(level2_kernel_pgt, max_pfn);
1470
1471 memcpy(swapper_pg_dir, pgd, sizeof(pgd_t) * PTRS_PER_PGD);
1472 set_pgd(&swapper_pg_dir[KERNEL_PGD_BOUNDARY],
1473 __pgd(__pa(level2_kernel_pgt) | _PAGE_PRESENT));
1474
1475 set_page_prot(level2_kernel_pgt, PAGE_KERNEL_RO);
1476 set_page_prot(swapper_pg_dir, PAGE_KERNEL_RO);
1477 set_page_prot(empty_zero_page, PAGE_KERNEL_RO);
1478
1479 pin_pagetable_pfn(MMUEXT_UNPIN_TABLE, PFN_DOWN(__pa(pgd)));
1480
1481 xen_write_cr3(__pa(swapper_pg_dir));
1482
1483 pin_pagetable_pfn(MMUEXT_PIN_L3_TABLE, PFN_DOWN(__pa(swapper_pg_dir)));
1484
1485 return swapper_pg_dir;
1512} 1486}
1513#endif /* CONFIG_X86_64 */ 1487#endif /* CONFIG_X86_64 */
1514 1488