diff options
author | Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> | 2012-07-26 12:00:56 -0400 |
---|---|---|
committer | Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> | 2012-08-23 11:52:12 -0400 |
commit | 488f046df922af992c1a718eff276529c0510885 (patch) | |
tree | b577a74f3a076aa933cecf5a4d849407266fdc8c | |
parent | caaf9ecf16feffa4f1a5a0d617bc78906a114514 (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.c | 42 |
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 | 1711 | static 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 */ |
1801 | static RESERVE_BRK_ARRAY(pmd_t, initial_kernel_pmd, PTRS_PER_PMD); | 1829 | static RESERVE_BRK_ARRAY(pmd_t, initial_kernel_pmd, PTRS_PER_PMD); |