aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>2012-07-26 12:00:56 -0400
committerKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>2012-08-23 11:52:12 -0400
commit488f046df922af992c1a718eff276529c0510885 (patch)
treeb577a74f3a076aa933cecf5a4d849407266fdc8c
parentcaaf9ecf16feffa4f1a5a0d617bc78906a114514 (diff)
xen/mmu: Recycle the Xen provided L4, L3, and L2 pages
As we are not using them. We end up only using the L1 pagetables and grafting those to our page-tables. [v1: Per Stefano's suggestion squashed two commits] [v2: Per Stefano's suggestion simplified loop] [v3: Fix smatch warnings] [v4: Add more comments] Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
-rw-r--r--arch/x86/xen/mmu.c42
1 files changed, 35 insertions, 7 deletions
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
index a59070b09055..b44e6a88ea74 100644
--- a/arch/x86/xen/mmu.c
+++ b/arch/x86/xen/mmu.c
@@ -1708,7 +1708,20 @@ static void convert_pfn_mfn(void *v)
1708 for (i = 0; i < PTRS_PER_PTE; i++) 1708 for (i = 0; i < PTRS_PER_PTE; i++)
1709 pte[i] = xen_make_pte(pte[i].pte); 1709 pte[i] = xen_make_pte(pte[i].pte);
1710} 1710}
1711 1711static void __init check_pt_base(unsigned long *pt_base, unsigned long *pt_end,
1712 unsigned long addr)
1713{
1714 if (*pt_base == PFN_DOWN(__pa(addr))) {
1715 set_page_prot((void *)addr, PAGE_KERNEL);
1716 clear_page((void *)addr);
1717 (*pt_base)++;
1718 }
1719 if (*pt_end == PFN_DOWN(__pa(addr))) {
1720 set_page_prot((void *)addr, PAGE_KERNEL);
1721 clear_page((void *)addr);
1722 (*pt_end)--;
1723 }
1724}
1712/* 1725/*
1713 * Set up the initial kernel pagetable. 1726 * Set up the initial kernel pagetable.
1714 * 1727 *
@@ -1724,6 +1737,9 @@ void __init xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn)
1724{ 1737{
1725 pud_t *l3; 1738 pud_t *l3;
1726 pmd_t *l2; 1739 pmd_t *l2;
1740 unsigned long addr[3];
1741 unsigned long pt_base, pt_end;
1742 unsigned i;
1727 1743
1728 /* max_pfn_mapped is the last pfn mapped in the initial memory 1744 /* max_pfn_mapped is the last pfn mapped in the initial memory
1729 * mappings. Considering that on Xen after the kernel mappings we 1745 * mappings. Considering that on Xen after the kernel mappings we
@@ -1731,6 +1747,9 @@ void __init xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn)
1731 * set max_pfn_mapped to the last real pfn mapped. */ 1747 * set max_pfn_mapped to the last real pfn mapped. */
1732 max_pfn_mapped = PFN_DOWN(__pa(xen_start_info->mfn_list)); 1748 max_pfn_mapped = PFN_DOWN(__pa(xen_start_info->mfn_list));
1733 1749
1750 pt_base = PFN_DOWN(__pa(xen_start_info->pt_base));
1751 pt_end = pt_base + xen_start_info->nr_pt_frames;
1752
1734 /* Zap identity mapping */ 1753 /* Zap identity mapping */
1735 init_level4_pgt[0] = __pgd(0); 1754 init_level4_pgt[0] = __pgd(0);
1736 1755
@@ -1749,6 +1768,9 @@ void __init xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn)
1749 l3 = m2v(pgd[pgd_index(__START_KERNEL_map)].pgd); 1768 l3 = m2v(pgd[pgd_index(__START_KERNEL_map)].pgd);
1750 l2 = m2v(l3[pud_index(__START_KERNEL_map)].pud); 1769 l2 = m2v(l3[pud_index(__START_KERNEL_map)].pud);
1751 1770
1771 addr[0] = (unsigned long)pgd;
1772 addr[1] = (unsigned long)l3;
1773 addr[2] = (unsigned long)l2;
1752 /* Graft it onto L4[272][0]. Note that we creating an aliasing problem: 1774 /* Graft it onto L4[272][0]. Note that we creating an aliasing problem:
1753 * Both L4[272][0] and L4[511][511] have entries that point to the same 1775 * Both L4[272][0] and L4[511][511] have entries that point to the same
1754 * L2 (PMD) tables. Meaning that if you modify it in __va space 1776 * L2 (PMD) tables. Meaning that if you modify it in __va space
@@ -1782,20 +1804,26 @@ void __init xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn)
1782 /* Unpin Xen-provided one */ 1804 /* Unpin Xen-provided one */
1783 pin_pagetable_pfn(MMUEXT_UNPIN_TABLE, PFN_DOWN(__pa(pgd))); 1805 pin_pagetable_pfn(MMUEXT_UNPIN_TABLE, PFN_DOWN(__pa(pgd)));
1784 1806
1785 /* Switch over */
1786 pgd = init_level4_pgt;
1787
1788 /* 1807 /*
1789 * At this stage there can be no user pgd, and no page 1808 * At this stage there can be no user pgd, and no page
1790 * structure to attach it to, so make sure we just set kernel 1809 * structure to attach it to, so make sure we just set kernel
1791 * pgd. 1810 * pgd.
1792 */ 1811 */
1793 xen_mc_batch(); 1812 xen_mc_batch();
1794 __xen_write_cr3(true, __pa(pgd)); 1813 __xen_write_cr3(true, __pa(init_level4_pgt));
1795 xen_mc_issue(PARAVIRT_LAZY_CPU); 1814 xen_mc_issue(PARAVIRT_LAZY_CPU);
1796 1815
1797 memblock_reserve(__pa(xen_start_info->pt_base), 1816 /* We can't that easily rip out L3 and L2, as the Xen pagetables are
1798 xen_start_info->nr_pt_frames * PAGE_SIZE); 1817 * set out this way: [L4], [L1], [L2], [L3], [L1], [L1] ... for
1818 * the initial domain. For guests using the toolstack, they are in:
1819 * [L4], [L3], [L2], [L1], [L1], order .. So for dom0 we can only
1820 * rip out the [L4] (pgd), but for guests we shave off three pages.
1821 */
1822 for (i = 0; i < ARRAY_SIZE(addr); i++)
1823 check_pt_base(&pt_base, &pt_end, addr[i]);
1824
1825 /* Our (by three pages) smaller Xen pagetable that we are using */
1826 memblock_reserve(PFN_PHYS(pt_base), (pt_end - pt_base) * PAGE_SIZE);
1799} 1827}
1800#else /* !CONFIG_X86_64 */ 1828#else /* !CONFIG_X86_64 */
1801static RESERVE_BRK_ARRAY(pmd_t, initial_kernel_pmd, PTRS_PER_PMD); 1829static RESERVE_BRK_ARRAY(pmd_t, initial_kernel_pmd, PTRS_PER_PMD);