aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/xen/mmu.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/xen/mmu.c')
-rw-r--r--arch/x86/xen/mmu.c124
1 files changed, 90 insertions, 34 deletions
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
index db3802fb7b84..fba55b1a4021 100644
--- a/arch/x86/xen/mmu.c
+++ b/arch/x86/xen/mmu.c
@@ -42,6 +42,7 @@
42#include <linux/highmem.h> 42#include <linux/highmem.h>
43#include <linux/debugfs.h> 43#include <linux/debugfs.h>
44#include <linux/bug.h> 44#include <linux/bug.h>
45#include <linux/module.h>
45 46
46#include <asm/pgtable.h> 47#include <asm/pgtable.h>
47#include <asm/tlbflush.h> 48#include <asm/tlbflush.h>
@@ -184,7 +185,7 @@ static inline unsigned p2m_index(unsigned long pfn)
184} 185}
185 186
186/* Build the parallel p2m_top_mfn structures */ 187/* Build the parallel p2m_top_mfn structures */
187void xen_setup_mfn_list_list(void) 188static void __init xen_build_mfn_list_list(void)
188{ 189{
189 unsigned pfn, idx; 190 unsigned pfn, idx;
190 191
@@ -198,7 +199,10 @@ void xen_setup_mfn_list_list(void)
198 unsigned topidx = idx * P2M_ENTRIES_PER_PAGE; 199 unsigned topidx = idx * P2M_ENTRIES_PER_PAGE;
199 p2m_top_mfn_list[idx] = virt_to_mfn(&p2m_top_mfn[topidx]); 200 p2m_top_mfn_list[idx] = virt_to_mfn(&p2m_top_mfn[topidx]);
200 } 201 }
202}
201 203
204void xen_setup_mfn_list_list(void)
205{
202 BUG_ON(HYPERVISOR_shared_info == &xen_dummy_shared_info); 206 BUG_ON(HYPERVISOR_shared_info == &xen_dummy_shared_info);
203 207
204 HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list = 208 HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list =
@@ -218,6 +222,8 @@ void __init xen_build_dynamic_phys_to_machine(void)
218 222
219 p2m_top[topidx] = &mfn_list[pfn]; 223 p2m_top[topidx] = &mfn_list[pfn];
220 } 224 }
225
226 xen_build_mfn_list_list();
221} 227}
222 228
223unsigned long get_phys_to_machine(unsigned long pfn) 229unsigned long get_phys_to_machine(unsigned long pfn)
@@ -233,47 +239,74 @@ unsigned long get_phys_to_machine(unsigned long pfn)
233} 239}
234EXPORT_SYMBOL_GPL(get_phys_to_machine); 240EXPORT_SYMBOL_GPL(get_phys_to_machine);
235 241
236static void alloc_p2m(unsigned long **pp, unsigned long *mfnp) 242/* install a new p2m_top page */
243bool install_p2mtop_page(unsigned long pfn, unsigned long *p)
237{ 244{
238 unsigned long *p; 245 unsigned topidx = p2m_top_index(pfn);
246 unsigned long **pfnp, *mfnp;
239 unsigned i; 247 unsigned i;
240 248
241 p = (void *)__get_free_page(GFP_KERNEL | __GFP_NOFAIL); 249 pfnp = &p2m_top[topidx];
242 BUG_ON(p == NULL); 250 mfnp = &p2m_top_mfn[topidx];
243 251
244 for (i = 0; i < P2M_ENTRIES_PER_PAGE; i++) 252 for (i = 0; i < P2M_ENTRIES_PER_PAGE; i++)
245 p[i] = INVALID_P2M_ENTRY; 253 p[i] = INVALID_P2M_ENTRY;
246 254
247 if (cmpxchg(pp, p2m_missing, p) != p2m_missing) 255 if (cmpxchg(pfnp, p2m_missing, p) == p2m_missing) {
248 free_page((unsigned long)p);
249 else
250 *mfnp = virt_to_mfn(p); 256 *mfnp = virt_to_mfn(p);
257 return true;
258 }
259
260 return false;
251} 261}
252 262
253void set_phys_to_machine(unsigned long pfn, unsigned long mfn) 263static void alloc_p2m(unsigned long pfn)
254{ 264{
255 unsigned topidx, idx; 265 unsigned long *p;
256 266
257 if (unlikely(xen_feature(XENFEAT_auto_translated_physmap))) { 267 p = (void *)__get_free_page(GFP_KERNEL | __GFP_NOFAIL);
258 BUG_ON(pfn != mfn && mfn != INVALID_P2M_ENTRY); 268 BUG_ON(p == NULL);
259 return; 269
260 } 270 if (!install_p2mtop_page(pfn, p))
271 free_page((unsigned long)p);
272}
273
274/* Try to install p2m mapping; fail if intermediate bits missing */
275bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn)
276{
277 unsigned topidx, idx;
261 278
262 if (unlikely(pfn >= MAX_DOMAIN_PAGES)) { 279 if (unlikely(pfn >= MAX_DOMAIN_PAGES)) {
263 BUG_ON(mfn != INVALID_P2M_ENTRY); 280 BUG_ON(mfn != INVALID_P2M_ENTRY);
264 return; 281 return true;
265 } 282 }
266 283
267 topidx = p2m_top_index(pfn); 284 topidx = p2m_top_index(pfn);
268 if (p2m_top[topidx] == p2m_missing) { 285 if (p2m_top[topidx] == p2m_missing) {
269 /* no need to allocate a page to store an invalid entry */
270 if (mfn == INVALID_P2M_ENTRY) 286 if (mfn == INVALID_P2M_ENTRY)
271 return; 287 return true;
272 alloc_p2m(&p2m_top[topidx], &p2m_top_mfn[topidx]); 288 return false;
273 } 289 }
274 290
275 idx = p2m_index(pfn); 291 idx = p2m_index(pfn);
276 p2m_top[topidx][idx] = mfn; 292 p2m_top[topidx][idx] = mfn;
293
294 return true;
295}
296
297void set_phys_to_machine(unsigned long pfn, unsigned long mfn)
298{
299 if (unlikely(xen_feature(XENFEAT_auto_translated_physmap))) {
300 BUG_ON(pfn != mfn && mfn != INVALID_P2M_ENTRY);
301 return;
302 }
303
304 if (unlikely(!__set_phys_to_machine(pfn, mfn))) {
305 alloc_p2m(pfn);
306
307 if (!__set_phys_to_machine(pfn, mfn))
308 BUG();
309 }
277} 310}
278 311
279unsigned long arbitrary_virt_to_mfn(void *vaddr) 312unsigned long arbitrary_virt_to_mfn(void *vaddr)
@@ -987,7 +1020,7 @@ static __init int xen_mark_pinned(struct mm_struct *mm, struct page *page,
987 return 0; 1020 return 0;
988} 1021}
989 1022
990void __init xen_mark_init_mm_pinned(void) 1023static void __init xen_mark_init_mm_pinned(void)
991{ 1024{
992 xen_pgd_walk(&init_mm, xen_mark_pinned, FIXADDR_TOP); 1025 xen_pgd_walk(&init_mm, xen_mark_pinned, FIXADDR_TOP);
993} 1026}
@@ -1270,8 +1303,8 @@ static void xen_flush_tlb_others(const struct cpumask *cpus,
1270 } *args; 1303 } *args;
1271 struct multicall_space mcs; 1304 struct multicall_space mcs;
1272 1305
1273 BUG_ON(cpumask_empty(cpus)); 1306 if (cpumask_empty(cpus))
1274 BUG_ON(!mm); 1307 return; /* nothing to do */
1275 1308
1276 mcs = xen_mc_entry(sizeof(*args)); 1309 mcs = xen_mc_entry(sizeof(*args));
1277 args = mcs.args; 1310 args = mcs.args;
@@ -1438,6 +1471,15 @@ static __init void xen_set_pte_init(pte_t *ptep, pte_t pte)
1438} 1471}
1439#endif 1472#endif
1440 1473
1474static void pin_pagetable_pfn(unsigned cmd, unsigned long pfn)
1475{
1476 struct mmuext_op op;
1477 op.cmd = cmd;
1478 op.arg1.mfn = pfn_to_mfn(pfn);
1479 if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF))
1480 BUG();
1481}
1482
1441/* Early in boot, while setting up the initial pagetable, assume 1483/* Early in boot, while setting up the initial pagetable, assume
1442 everything is pinned. */ 1484 everything is pinned. */
1443static __init void xen_alloc_pte_init(struct mm_struct *mm, unsigned long pfn) 1485static __init void xen_alloc_pte_init(struct mm_struct *mm, unsigned long pfn)
@@ -1446,22 +1488,29 @@ static __init void xen_alloc_pte_init(struct mm_struct *mm, unsigned long pfn)
1446 BUG_ON(mem_map); /* should only be used early */ 1488 BUG_ON(mem_map); /* should only be used early */
1447#endif 1489#endif
1448 make_lowmem_page_readonly(__va(PFN_PHYS(pfn))); 1490 make_lowmem_page_readonly(__va(PFN_PHYS(pfn)));
1491 pin_pagetable_pfn(MMUEXT_PIN_L1_TABLE, pfn);
1492}
1493
1494/* Used for pmd and pud */
1495static __init void xen_alloc_pmd_init(struct mm_struct *mm, unsigned long pfn)
1496{
1497#ifdef CONFIG_FLATMEM
1498 BUG_ON(mem_map); /* should only be used early */
1499#endif
1500 make_lowmem_page_readonly(__va(PFN_PHYS(pfn)));
1449} 1501}
1450 1502
1451/* Early release_pte assumes that all pts are pinned, since there's 1503/* Early release_pte assumes that all pts are pinned, since there's
1452 only init_mm and anything attached to that is pinned. */ 1504 only init_mm and anything attached to that is pinned. */
1453static void xen_release_pte_init(unsigned long pfn) 1505static __init void xen_release_pte_init(unsigned long pfn)
1454{ 1506{
1507 pin_pagetable_pfn(MMUEXT_UNPIN_TABLE, pfn);
1455 make_lowmem_page_readwrite(__va(PFN_PHYS(pfn))); 1508 make_lowmem_page_readwrite(__va(PFN_PHYS(pfn)));
1456} 1509}
1457 1510
1458static void pin_pagetable_pfn(unsigned cmd, unsigned long pfn) 1511static __init void xen_release_pmd_init(unsigned long pfn)
1459{ 1512{
1460 struct mmuext_op op; 1513 make_lowmem_page_readwrite(__va(PFN_PHYS(pfn)));
1461 op.cmd = cmd;
1462 op.arg1.mfn = pfn_to_mfn(pfn);
1463 if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF))
1464 BUG();
1465} 1514}
1466 1515
1467/* This needs to make sure the new pte page is pinned iff its being 1516/* This needs to make sure the new pte page is pinned iff its being
@@ -1746,11 +1795,16 @@ __init pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd,
1746 1795
1747 pin_pagetable_pfn(MMUEXT_PIN_L3_TABLE, PFN_DOWN(__pa(swapper_pg_dir))); 1796 pin_pagetable_pfn(MMUEXT_PIN_L3_TABLE, PFN_DOWN(__pa(swapper_pg_dir)));
1748 1797
1798 reserve_early(__pa(xen_start_info->pt_base),
1799 __pa(xen_start_info->pt_base +
1800 xen_start_info->nr_pt_frames * PAGE_SIZE),
1801 "XEN PAGETABLES");
1802
1749 return swapper_pg_dir; 1803 return swapper_pg_dir;
1750} 1804}
1751#endif /* CONFIG_X86_64 */ 1805#endif /* CONFIG_X86_64 */
1752 1806
1753static void xen_set_fixmap(unsigned idx, unsigned long phys, pgprot_t prot) 1807static void xen_set_fixmap(unsigned idx, phys_addr_t phys, pgprot_t prot)
1754{ 1808{
1755 pte_t pte; 1809 pte_t pte;
1756 1810
@@ -1773,6 +1827,9 @@ static void xen_set_fixmap(unsigned idx, unsigned long phys, pgprot_t prot)
1773#ifdef CONFIG_X86_LOCAL_APIC 1827#ifdef CONFIG_X86_LOCAL_APIC
1774 case FIX_APIC_BASE: /* maps dummy local APIC */ 1828 case FIX_APIC_BASE: /* maps dummy local APIC */
1775#endif 1829#endif
1830 case FIX_TEXT_POKE0:
1831 case FIX_TEXT_POKE1:
1832 /* All local page mappings */
1776 pte = pfn_pte(phys, prot); 1833 pte = pfn_pte(phys, prot);
1777 break; 1834 break;
1778 1835
@@ -1819,7 +1876,6 @@ __init void xen_post_allocator_init(void)
1819 xen_mark_init_mm_pinned(); 1876 xen_mark_init_mm_pinned();
1820} 1877}
1821 1878
1822
1823const struct pv_mmu_ops xen_mmu_ops __initdata = { 1879const struct pv_mmu_ops xen_mmu_ops __initdata = {
1824 .pagetable_setup_start = xen_pagetable_setup_start, 1880 .pagetable_setup_start = xen_pagetable_setup_start,
1825 .pagetable_setup_done = xen_pagetable_setup_done, 1881 .pagetable_setup_done = xen_pagetable_setup_done,
@@ -1843,9 +1899,9 @@ const struct pv_mmu_ops xen_mmu_ops __initdata = {
1843 1899
1844 .alloc_pte = xen_alloc_pte_init, 1900 .alloc_pte = xen_alloc_pte_init,
1845 .release_pte = xen_release_pte_init, 1901 .release_pte = xen_release_pte_init,
1846 .alloc_pmd = xen_alloc_pte_init, 1902 .alloc_pmd = xen_alloc_pmd_init,
1847 .alloc_pmd_clone = paravirt_nop, 1903 .alloc_pmd_clone = paravirt_nop,
1848 .release_pmd = xen_release_pte_init, 1904 .release_pmd = xen_release_pmd_init,
1849 1905
1850#ifdef CONFIG_HIGHPTE 1906#ifdef CONFIG_HIGHPTE
1851 .kmap_atomic_pte = xen_kmap_atomic_pte, 1907 .kmap_atomic_pte = xen_kmap_atomic_pte,
@@ -1883,8 +1939,8 @@ const struct pv_mmu_ops xen_mmu_ops __initdata = {
1883 .make_pud = PV_CALLEE_SAVE(xen_make_pud), 1939 .make_pud = PV_CALLEE_SAVE(xen_make_pud),
1884 .set_pgd = xen_set_pgd_hyper, 1940 .set_pgd = xen_set_pgd_hyper,
1885 1941
1886 .alloc_pud = xen_alloc_pte_init, 1942 .alloc_pud = xen_alloc_pmd_init,
1887 .release_pud = xen_release_pte_init, 1943 .release_pud = xen_release_pmd_init,
1888#endif /* PAGETABLE_LEVELS == 4 */ 1944#endif /* PAGETABLE_LEVELS == 4 */
1889 1945
1890 .activate_mm = xen_activate_mm, 1946 .activate_mm = xen_activate_mm,