aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/xen/enlighten.c79
1 files changed, 69 insertions, 10 deletions
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index 392450787aa9..e9e3bafe48cf 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -1382,6 +1382,61 @@ static void convert_pfn_mfn(void *v)
1382} 1382}
1383 1383
1384/* 1384/*
1385 * Identity map, in addition to plain kernel map. This needs to be
1386 * large enough to allocate page table pages to allocate the rest.
1387 * Each page can map 2MB.
1388 */
1389static pte_t level1_ident_pgt[PTRS_PER_PTE * 4] __page_aligned_bss;
1390
1391static __init void xen_map_identity_early(unsigned long max_pfn)
1392{
1393 unsigned pmdidx, pteidx;
1394 unsigned ident_pte;
1395 unsigned long pfn;
1396
1397 ident_pte = 0;
1398 pfn = 0;
1399 for(pmdidx = 0; pmdidx < PTRS_PER_PMD && pfn < max_pfn; pmdidx++) {
1400 pte_t *pte_page;
1401
1402 BUG_ON(level2_ident_pgt[pmdidx].pmd != level2_kernel_pgt[pmdidx].pmd);
1403
1404 /* Reuse or allocate a page of ptes */
1405 if (pmd_present(level2_ident_pgt[pmdidx]))
1406 pte_page = m2v(level2_ident_pgt[pmdidx].pmd);
1407 else {
1408 /* Check for free pte pages */
1409 if (ident_pte == ARRAY_SIZE(level1_ident_pgt))
1410 break;
1411
1412 pte_page = &level1_ident_pgt[ident_pte];
1413 ident_pte += PTRS_PER_PTE;
1414
1415 /* Install new l1 in l2(s) */
1416 level2_ident_pgt[pmdidx] = __pmd(__pa(pte_page) | _PAGE_TABLE);
1417 level2_kernel_pgt[pmdidx] = level2_ident_pgt[pmdidx];
1418 }
1419
1420 /* Install mappings */
1421 for(pteidx = 0; pteidx < PTRS_PER_PTE; pteidx++, pfn++) {
1422 pte_t pte;
1423
1424 if (pfn > max_pfn_mapped)
1425 max_pfn_mapped = pfn;
1426
1427 if (!pte_none(pte_page[pteidx]))
1428 continue;
1429
1430 pte = pfn_pte(pfn, PAGE_KERNEL_EXEC);
1431 pte_page[pteidx] = pte;
1432 }
1433 }
1434
1435 for(pteidx = 0; pteidx < ident_pte; pteidx += PTRS_PER_PTE)
1436 set_page_prot(&level1_ident_pgt[pteidx], PAGE_KERNEL_RO);
1437}
1438
1439/*
1385 * Set up the inital kernel pagetable. 1440 * Set up the inital kernel pagetable.
1386 * 1441 *
1387 * We can construct this by grafting the Xen provided pagetable into 1442 * We can construct this by grafting the Xen provided pagetable into
@@ -1392,7 +1447,7 @@ static void convert_pfn_mfn(void *v)
1392 * of the physical mapping once some sort of allocator has been set 1447 * of the physical mapping once some sort of allocator has been set
1393 * up. 1448 * up.
1394 */ 1449 */
1395static __init pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd) 1450static __init pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn)
1396{ 1451{
1397 pud_t *l3; 1452 pud_t *l3;
1398 pmd_t *l2; 1453 pmd_t *l2;
@@ -1415,6 +1470,9 @@ static __init pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd)
1415 l2 = m2v(l3[pud_index(__START_KERNEL_map + PMD_SIZE)].pud); 1470 l2 = m2v(l3[pud_index(__START_KERNEL_map + PMD_SIZE)].pud);
1416 memcpy(level2_fixmap_pgt, l2, sizeof(pmd_t) * PTRS_PER_PMD); 1471 memcpy(level2_fixmap_pgt, l2, sizeof(pmd_t) * PTRS_PER_PMD);
1417 1472
1473 /* Set up identity map */
1474 xen_map_identity_early(max_pfn);
1475
1418 /* Make pagetable pieces RO */ 1476 /* Make pagetable pieces RO */
1419 set_page_prot(init_level4_pgt, PAGE_KERNEL_RO); 1477 set_page_prot(init_level4_pgt, PAGE_KERNEL_RO);
1420 set_page_prot(level3_ident_pgt, PAGE_KERNEL_RO); 1478 set_page_prot(level3_ident_pgt, PAGE_KERNEL_RO);
@@ -1424,7 +1482,7 @@ static __init pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd)
1424 set_page_prot(level2_fixmap_pgt, PAGE_KERNEL_RO); 1482 set_page_prot(level2_fixmap_pgt, PAGE_KERNEL_RO);
1425 1483
1426 /* Pin down new L4 */ 1484 /* Pin down new L4 */
1427 pin_pagetable_pfn(MMUEXT_PIN_L4_TABLE, PFN_DOWN(__pa(init_level4_pgt))); 1485 pin_pagetable_pfn(MMUEXT_PIN_L4_TABLE, PFN_DOWN(__pa_symbol(init_level4_pgt)));
1428 1486
1429 /* Unpin Xen-provided one */ 1487 /* Unpin Xen-provided one */
1430 pin_pagetable_pfn(MMUEXT_UNPIN_TABLE, PFN_DOWN(__pa(pgd))); 1488 pin_pagetable_pfn(MMUEXT_UNPIN_TABLE, PFN_DOWN(__pa(pgd)));
@@ -1433,19 +1491,23 @@ static __init pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd)
1433 pgd = init_level4_pgt; 1491 pgd = init_level4_pgt;
1434 xen_write_cr3(__pa(pgd)); 1492 xen_write_cr3(__pa(pgd));
1435 1493
1436 max_pfn_mapped = PFN_DOWN(__pa(pgd) + 1494 reserve_early(__pa(xen_start_info->pt_base),
1437 xen_start_info->nr_pt_frames*PAGE_SIZE + 1495 __pa(xen_start_info->pt_base +
1438 512*1024); 1496 xen_start_info->nr_pt_frames * PAGE_SIZE),
1497 "XEN PAGETABLES");
1439 1498
1440 return pgd; 1499 return pgd;
1441} 1500}
1442#else 1501#else
1443static __init pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd) 1502static __init pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn)
1444{ 1503{
1445 init_pg_tables_start = __pa(pgd); 1504 init_pg_tables_start = __pa(pgd);
1446 init_pg_tables_end = __pa(pgd) + xen_start_info->nr_pt_frames*PAGE_SIZE; 1505 init_pg_tables_end = __pa(pgd) + xen_start_info->nr_pt_frames*PAGE_SIZE;
1447 max_pfn_mapped = PFN_DOWN(init_pg_tables_end + 512*1024); 1506 max_pfn_mapped = PFN_DOWN(init_pg_tables_end + 512*1024);
1448 1507
1508 x86_write_percpu(xen_cr3, __pa(pgd));
1509 x86_write_percpu(xen_current_cr3, __pa(pgd));
1510
1449 return pgd; 1511 return pgd;
1450} 1512}
1451#endif /* CONFIG_X86_64 */ 1513#endif /* CONFIG_X86_64 */
@@ -1502,15 +1564,12 @@ asmlinkage void __init xen_start_kernel(void)
1502 per_cpu(xen_vcpu, 0) = &HYPERVISOR_shared_info->vcpu_info[0]; 1564 per_cpu(xen_vcpu, 0) = &HYPERVISOR_shared_info->vcpu_info[0];
1503 1565
1504 xen_raw_console_write("mapping kernel into physical memory\n"); 1566 xen_raw_console_write("mapping kernel into physical memory\n");
1505 pgd = xen_setup_kernel_pagetable(pgd); 1567 pgd = xen_setup_kernel_pagetable(pgd, xen_start_info->nr_pages);
1506 1568
1507 init_mm.pgd = pgd; 1569 init_mm.pgd = pgd;
1508 1570
1509 /* keep using Xen gdt for now; no urgent need to change it */ 1571 /* keep using Xen gdt for now; no urgent need to change it */
1510 1572
1511 x86_write_percpu(xen_cr3, __pa(pgd));
1512 x86_write_percpu(xen_current_cr3, __pa(pgd));
1513
1514 pv_info.kernel_rpl = 1; 1573 pv_info.kernel_rpl = 1;
1515 if (xen_feature(XENFEAT_supervisor_mode_kernel)) 1574 if (xen_feature(XENFEAT_supervisor_mode_kernel))
1516 pv_info.kernel_rpl = 0; 1575 pv_info.kernel_rpl = 0;