From 6b010591cb94032a6fef2cb81bed16446f31f8b6 Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Mon, 28 Jan 2013 02:31:44 +0100 Subject: Add initial code for disabling PV pagetables * xen/configfrag.ac (--disable-pv-pagetables): Add option. * i386/xen/xen_boothdr.S (XEN_ELFNOTE_FEATURES) [!MACH_PV_PAGETABLES]: Add writable_page_tables. * i386/i386/gdt.c: Turn appropriate MACH_XEN/MACH_HYP tests into MACH_PV_PAGETABLES tests. * i386/i386/i386asm.sym: Likewise * i386/i386/ldt.c: Likewise * i386/i386/locore.S: Likewise * i386/i386/proc_reg.h: Likewise * i386/i386/user_ldt.c: Likewise * i386/i386/vm_param.h: Likewise * i386/i386/xen.h: Likewise * i386/i386at/model_dep.c: Likewise * i386/intel/pmap.h: Likewise * include/mach/xen.h: Likewise * xen/console.c: Likewise * xen/store.c: Likewise * i386/intel/pmap.c: Likewise. Define pmap_map_mfn as TODO stub. --- i386/intel/pmap.c | 158 ++++++++++++++++++++++++++++-------------------------- i386/intel/pmap.h | 10 ++-- 2 files changed, 87 insertions(+), 81 deletions(-) (limited to 'i386/intel') diff --git a/i386/intel/pmap.c b/i386/intel/pmap.c index e211bf3..0be1609 100644 --- a/i386/intel/pmap.c +++ b/i386/intel/pmap.c @@ -327,7 +327,7 @@ lock_data_t pmap_system_lock; #define MAX_TBIS_SIZE 32 /* > this -> TBIA */ /* XXX */ -#ifdef MACH_HYP +#ifdef MACH_PV_PAGETABLES #if 1 #define INVALIDATE_TLB(pmap, s, e) hyp_mmuext_op_void(MMUEXT_TLB_FLUSH_LOCAL) #else @@ -339,7 +339,7 @@ lock_data_t pmap_system_lock; hyp_mmuext_op_void(MMUEXT_TLB_FLUSH_LOCAL); \ } while(0) #endif -#else /* MACH_HYP */ +#else /* MACH_PV_PAGETABLES */ #if 0 /* It is hard to know when a TLB flush becomes less expensive than a bunch of * invlpgs. But it surely is more expensive than just one invlpg. */ @@ -358,7 +358,7 @@ lock_data_t pmap_system_lock; flush_tlb(); \ } #endif -#endif /* MACH_HYP */ +#endif /* MACH_PV_PAGETABLES */ #if NCPUS > 1 @@ -528,10 +528,10 @@ vm_offset_t pmap_map_bd(virt, start, end, prot) register pt_entry_t template; register pt_entry_t *pte; int spl; -#ifdef MACH_XEN +#ifdef MACH_PV_PAGETABLES int n, i = 0; struct mmu_update update[HYP_BATCH_MMU_UPDATES]; -#endif /* MACH_XEN */ +#endif /* MACH_PV_PAGETABLES */ template = pa_to_pte(start) | INTEL_PTE_NCACHE|INTEL_PTE_WTHRU @@ -546,7 +546,7 @@ vm_offset_t pmap_map_bd(virt, start, end, prot) pte = pmap_pte(kernel_pmap, virt); if (pte == PT_ENTRY_NULL) panic("pmap_map_bd: Invalid kernel address\n"); -#ifdef MACH_XEN +#ifdef MACH_PV_PAGETABLES update[i].ptr = kv_to_ma(pte); update[i].val = pa_to_ma(template); i++; @@ -556,20 +556,20 @@ vm_offset_t pmap_map_bd(virt, start, end, prot) panic("couldn't pmap_map_bd\n"); i = 0; } -#else /* MACH_XEN */ +#else /* MACH_PV_PAGETABLES */ WRITE_PTE(pte, template) -#endif /* MACH_XEN */ +#endif /* MACH_PV_PAGETABLES */ pte_increment_pa(template); virt += PAGE_SIZE; start += PAGE_SIZE; } -#ifdef MACH_XEN +#ifdef MACH_PV_PAGETABLES if (i > HYP_BATCH_MMU_UPDATES) panic("overflowed array in pmap_map_bd"); hyp_mmu_update(kvtolin(&update), i, kvtolin(&n), DOMID_SELF); if (n != i) panic("couldn't pmap_map_bd\n"); -#endif /* MACH_XEN */ +#endif /* MACH_PV_PAGETABLES */ PMAP_READ_UNLOCK(pmap, spl); return(virt); } @@ -649,7 +649,7 @@ void pmap_bootstrap() kernel_pmap->dirbase[i] = 0; } -#ifdef MACH_XEN +#ifdef MACH_PV_PAGETABLES /* We don't actually deal with the CR3 register content at all */ hyp_vm_assist(VMASST_CMD_enable, VMASST_TYPE_pae_extended_cr3); /* @@ -698,7 +698,7 @@ void pmap_bootstrap() } } } -#endif /* MACH_XEN */ +#endif /* MACH_PV_PAGETABLES */ /* * Allocate and set up the kernel page tables. @@ -736,24 +736,24 @@ void pmap_bootstrap() WRITE_PTE(pte, 0); } else -#ifdef MACH_XEN +#ifdef MACH_PV_PAGETABLES if (va == (vm_offset_t) &hyp_shared_info) { *pte = boot_info.shared_info | INTEL_PTE_VALID | INTEL_PTE_WRITE; va += INTEL_PGBYTES; } else -#endif /* MACH_XEN */ +#endif /* MACH_PV_PAGETABLES */ { extern char _start[], etext[]; if (((va >= (vm_offset_t) _start) && (va + INTEL_PGBYTES <= (vm_offset_t)etext)) -#ifdef MACH_XEN +#ifdef MACH_PV_PAGETABLES || (va >= (vm_offset_t) boot_info.pt_base && (va + INTEL_PGBYTES <= (vm_offset_t) ptable + INTEL_PGBYTES)) -#endif /* MACH_XEN */ +#endif /* MACH_PV_PAGETABLES */ ) { WRITE_PTE(pte, pa_to_pte(_kvtophys(va)) @@ -761,7 +761,7 @@ void pmap_bootstrap() } else { -#ifdef MACH_XEN +#ifdef MACH_PV_PAGETABLES /* Keep supplementary L1 pages read-only */ int i; for (i = 0; i < NSUP_L1; i++) @@ -771,7 +771,7 @@ void pmap_bootstrap() break; } if (i == NSUP_L1) -#endif /* MACH_XEN */ +#endif /* MACH_PV_PAGETABLES */ WRITE_PTE(pte, pa_to_pte(_kvtophys(va)) | INTEL_PTE_VALID | INTEL_PTE_WRITE | global) @@ -784,11 +784,11 @@ void pmap_bootstrap() WRITE_PTE(pte, 0); va += INTEL_PGBYTES; } -#ifdef MACH_XEN +#ifdef MACH_PV_PAGETABLES pmap_set_page_readonly_init(ptable); if (!hyp_mmuext_op_mfn (MMUEXT_PIN_L1_TABLE, kv_to_mfn (ptable))) panic("couldn't pin page %p(%p)\n", ptable, (vm_offset_t) kv_to_ma (ptable)); -#endif /* MACH_XEN */ +#endif /* MACH_PV_PAGETABLES */ } } @@ -796,7 +796,7 @@ void pmap_bootstrap() soon after we return from here. */ } -#ifdef MACH_XEN +#ifdef MACH_PV_PAGETABLES /* These are only required because of Xen security policies */ /* Set back a page read write */ @@ -889,7 +889,7 @@ void pmap_clear_bootstrap_pagetable(pt_entry_t *base) { #endif /* PAE */ hyp_free_page(atop(_kvtophys(base)), base); } -#endif /* MACH_XEN */ +#endif /* MACH_PV_PAGETABLES */ void pmap_virtual_space(startp, endp) vm_offset_t *startp; @@ -1046,6 +1046,7 @@ pmap_page_table_page_alloc() } #ifdef MACH_XEN +#ifdef MACH_PV_PAGETABLES void pmap_map_mfn(void *_addr, unsigned long mfn) { vm_offset_t addr = (vm_offset_t) _addr; pt_entry_t *pte, *pdp; @@ -1067,6 +1068,11 @@ void pmap_map_mfn(void *_addr, unsigned long mfn) { if (!hyp_mmu_update_pte(kv_to_ma(pte), ma | INTEL_PTE_VALID | INTEL_PTE_WRITE)) panic("%s:%d could not set pte %p(%p) to %p(%p)\n",__FILE__,__LINE__,pte,(vm_offset_t) kv_to_ma(pte), ma, ma_to_pa(ma)); } +#else /* MACH_PV_PAGETABLES */ +void pmap_map_mfn(void *_addr, unsigned long mfn) { + panic("TODO %s:%d\n",__FILE__,__LINE__); +} +#endif /* MACH_PV_PAGETABLES */ #endif /* MACH_XEN */ /* @@ -1136,13 +1142,13 @@ pmap_t pmap_create(size) p->dirbase[lin2pdenum(LINEAR_MIN_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS)] = 0; #endif #endif -#ifdef MACH_XEN +#ifdef MACH_PV_PAGETABLES { int i; for (i = 0; i < PDPNUM; i++) pmap_set_page_readonly((void*) p->dirbase + i * INTEL_PGBYTES); } -#endif /* MACH_XEN */ +#endif /* MACH_PV_PAGETABLES */ #if PAE if (kmem_alloc_wired(kernel_map, @@ -1154,9 +1160,9 @@ pmap_t pmap_create(size) for (i = 0; i < PDPNUM; i++) WRITE_PTE(&p->pdpbase[i], pa_to_pte(kvtophys((vm_offset_t) p->dirbase + i * INTEL_PGBYTES)) | INTEL_PTE_VALID); } -#ifdef MACH_XEN +#ifdef MACH_PV_PAGETABLES pmap_set_page_readonly(p->pdpbase); -#endif /* MACH_XEN */ +#endif /* MACH_PV_PAGETABLES */ #endif /* PAE */ p->ref_count = 1; @@ -1216,29 +1222,29 @@ void pmap_destroy(p) if (m == VM_PAGE_NULL) panic("pmap_destroy: pte page not in object"); vm_page_lock_queues(); -#ifdef MACH_XEN +#ifdef MACH_PV_PAGETABLES if (!hyp_mmuext_op_mfn (MMUEXT_UNPIN_TABLE, pa_to_mfn(pa))) panic("pmap_destroy: couldn't unpin page %p(%p)\n", pa, (vm_offset_t) kv_to_ma(pa)); pmap_set_page_readwrite((void*) phystokv(pa)); -#endif /* MACH_XEN */ +#endif /* MACH_PV_PAGETABLES */ vm_page_free(m); inuse_ptepages_count--; vm_page_unlock_queues(); vm_object_unlock(pmap_object); } } -#ifdef MACH_XEN +#ifdef MACH_PV_PAGETABLES { int i; for (i = 0; i < PDPNUM; i++) pmap_set_page_readwrite((void*) p->dirbase + i * INTEL_PGBYTES); } -#endif /* MACH_XEN */ +#endif /* MACH_PV_PAGETABLES */ kmem_free(kernel_map, (vm_offset_t)p->dirbase, PDPNUM * INTEL_PGBYTES); #if PAE -#ifdef MACH_XEN +#ifdef MACH_PV_PAGETABLES pmap_set_page_readwrite(p->pdpbase); -#endif /* MACH_XEN */ +#endif /* MACH_PV_PAGETABLES */ kmem_free(kernel_map, (vm_offset_t)p->pdpbase, INTEL_PGBYTES); #endif /* PAE */ kmem_cache_free(&pmap_cache, (vm_offset_t) p); @@ -1284,10 +1290,10 @@ void pmap_remove_range(pmap, va, spte, epte) int num_removed, num_unwired; int pai; vm_offset_t pa; -#ifdef MACH_XEN +#ifdef MACH_PV_PAGETABLES int n, ii = 0; struct mmu_update update[HYP_BATCH_MMU_UPDATES]; -#endif /* MACH_XEN */ +#endif /* MACH_PV_PAGETABLES */ #if DEBUG_PTE_PAGE if (pmap != kernel_pmap) @@ -1316,7 +1322,7 @@ void pmap_remove_range(pmap, va, spte, epte) register int i = ptes_per_vm_page; register pt_entry_t *lpte = cpte; do { -#ifdef MACH_XEN +#ifdef MACH_PV_PAGETABLES update[ii].ptr = kv_to_ma(lpte); update[ii].val = 0; ii++; @@ -1326,9 +1332,9 @@ void pmap_remove_range(pmap, va, spte, epte) panic("couldn't pmap_remove_range\n"); ii = 0; } -#else /* MACH_XEN */ +#else /* MACH_PV_PAGETABLES */ *lpte = 0; -#endif /* MACH_XEN */ +#endif /* MACH_PV_PAGETABLES */ lpte++; } while (--i > 0); continue; @@ -1349,7 +1355,7 @@ void pmap_remove_range(pmap, va, spte, epte) do { pmap_phys_attributes[pai] |= *lpte & (PHYS_MODIFIED|PHYS_REFERENCED); -#ifdef MACH_XEN +#ifdef MACH_PV_PAGETABLES update[ii].ptr = kv_to_ma(lpte); update[ii].val = 0; ii++; @@ -1359,9 +1365,9 @@ void pmap_remove_range(pmap, va, spte, epte) panic("couldn't pmap_remove_range\n"); ii = 0; } -#else /* MACH_XEN */ +#else /* MACH_PV_PAGETABLES */ *lpte = 0; -#endif /* MACH_XEN */ +#endif /* MACH_PV_PAGETABLES */ lpte++; } while (--i > 0); } @@ -1407,13 +1413,13 @@ void pmap_remove_range(pmap, va, spte, epte) } } -#ifdef MACH_XEN +#ifdef MACH_PV_PAGETABLES if (ii > HYP_BATCH_MMU_UPDATES) panic("overflowed array in pmap_remove_range"); hyp_mmu_update(kvtolin(&update), ii, kvtolin(&n), DOMID_SELF); if (n != ii) panic("couldn't pmap_remove_range\n"); -#endif /* MACH_XEN */ +#endif /* MACH_PV_PAGETABLES */ /* * Update the counts @@ -1559,12 +1565,12 @@ void pmap_page_protect(phys, prot) do { pmap_phys_attributes[pai] |= *pte & (PHYS_MODIFIED|PHYS_REFERENCED); -#ifdef MACH_XEN +#ifdef MACH_PV_PAGETABLES if (!hyp_mmu_update_pte(kv_to_ma(pte++), 0)) panic("%s:%d could not clear pte %p\n",__FILE__,__LINE__,pte-1); -#else /* MACH_XEN */ +#else /* MACH_PV_PAGETABLES */ *pte++ = 0; -#endif /* MACH_XEN */ +#endif /* MACH_PV_PAGETABLES */ } while (--i > 0); } @@ -1594,12 +1600,12 @@ void pmap_page_protect(phys, prot) register int i = ptes_per_vm_page; do { -#ifdef MACH_XEN +#ifdef MACH_PV_PAGETABLES if (!hyp_mmu_update_pte(kv_to_ma(pte), *pte & ~INTEL_PTE_WRITE)) panic("%s:%d could not disable write on pte %p\n",__FILE__,__LINE__,pte); -#else /* MACH_XEN */ +#else /* MACH_PV_PAGETABLES */ *pte &= ~INTEL_PTE_WRITE; -#endif /* MACH_XEN */ +#endif /* MACH_PV_PAGETABLES */ pte++; } while (--i > 0); @@ -1688,14 +1694,14 @@ void pmap_protect(map, s, e, prot) spte = &spte[ptenum(s)]; epte = &spte[intel_btop(l-s)]; -#ifdef MACH_XEN +#ifdef MACH_PV_PAGETABLES int n, i = 0; struct mmu_update update[HYP_BATCH_MMU_UPDATES]; -#endif /* MACH_XEN */ +#endif /* MACH_PV_PAGETABLES */ while (spte < epte) { if (*spte & INTEL_PTE_VALID) { -#ifdef MACH_XEN +#ifdef MACH_PV_PAGETABLES update[i].ptr = kv_to_ma(spte); update[i].val = *spte & ~INTEL_PTE_WRITE; i++; @@ -1705,19 +1711,19 @@ void pmap_protect(map, s, e, prot) panic("couldn't pmap_protect\n"); i = 0; } -#else /* MACH_XEN */ +#else /* MACH_PV_PAGETABLES */ *spte &= ~INTEL_PTE_WRITE; -#endif /* MACH_XEN */ +#endif /* MACH_PV_PAGETABLES */ } spte++; } -#ifdef MACH_XEN +#ifdef MACH_PV_PAGETABLES if (i > HYP_BATCH_MMU_UPDATES) panic("overflowed array in pmap_protect"); hyp_mmu_update(kvtolin(&update), i, kvtolin(&n), DOMID_SELF); if (n != i) panic("couldn't pmap_protect\n"); -#endif /* MACH_XEN */ +#endif /* MACH_PV_PAGETABLES */ } s = l; pde++; @@ -1854,7 +1860,7 @@ Retry: /*XX pdp = &pmap->dirbase[pdenum(v) & ~(i-1)];*/ pdp = pmap_pde(pmap, v); do { -#ifdef MACH_XEN +#ifdef MACH_PV_PAGETABLES pmap_set_page_readonly((void *) ptp); if (!hyp_mmuext_op_mfn (MMUEXT_PIN_L1_TABLE, kv_to_mfn(ptp))) panic("couldn't pin page %p(%p)\n",ptp,(vm_offset_t) kv_to_ma(ptp)); @@ -1863,11 +1869,11 @@ Retry: | INTEL_PTE_USER | INTEL_PTE_WRITE)) panic("%s:%d could not set pde %p(%p,%p) to %p(%p,%p) %p\n",__FILE__,__LINE__, pdp, kvtophys((vm_offset_t)pdp), (vm_offset_t) pa_to_ma(kvtophys((vm_offset_t)pdp)), ptp, kvtophys(ptp), (vm_offset_t) pa_to_ma(kvtophys(ptp)), (vm_offset_t) pa_to_pte(kv_to_ma(ptp))); -#else /* MACH_XEN */ +#else /* MACH_PV_PAGETABLES */ *pdp = pa_to_pte(kvtophys(ptp)) | INTEL_PTE_VALID | INTEL_PTE_USER | INTEL_PTE_WRITE; -#endif /* MACH_XEN */ +#endif /* MACH_PV_PAGETABLES */ pdp++; ptp += INTEL_PGBYTES; } while (--i > 0); @@ -1907,12 +1913,12 @@ Retry: do { if (*pte & INTEL_PTE_MOD) template |= INTEL_PTE_MOD; -#ifdef MACH_XEN +#ifdef MACH_PV_PAGETABLES if (!hyp_mmu_update_pte(kv_to_ma(pte), pa_to_ma(template))) panic("%s:%d could not set pte %p to %p\n",__FILE__,__LINE__,pte,template); -#else /* MACH_XEN */ +#else /* MACH_PV_PAGETABLES */ WRITE_PTE(pte, template) -#endif /* MACH_XEN */ +#endif /* MACH_PV_PAGETABLES */ pte++; pte_increment_pa(template); } while (--i > 0); @@ -2017,12 +2023,12 @@ Retry: template |= INTEL_PTE_WIRED; i = ptes_per_vm_page; do { -#ifdef MACH_XEN +#ifdef MACH_PV_PAGETABLES if (!(hyp_mmu_update_pte(kv_to_ma(pte), pa_to_ma(template)))) panic("%s:%d could not set pte %p to %p\n",__FILE__,__LINE__,pte,template); -#else /* MACH_XEN */ +#else /* MACH_PV_PAGETABLES */ WRITE_PTE(pte, template) -#endif /* MACH_XEN */ +#endif /* MACH_PV_PAGETABLES */ pte++; pte_increment_pa(template); } while (--i > 0); @@ -2077,12 +2083,12 @@ void pmap_change_wiring(map, v, wired) map->stats.wired_count--; i = ptes_per_vm_page; do { -#ifdef MACH_XEN +#ifdef MACH_PV_PAGETABLES if (!(hyp_mmu_update_pte(kv_to_ma(pte), *pte & ~INTEL_PTE_WIRED))) panic("%s:%d could not wire down pte %p\n",__FILE__,__LINE__,pte); -#else /* MACH_XEN */ +#else /* MACH_PV_PAGETABLES */ *pte &= ~INTEL_PTE_WIRED; -#endif /* MACH_XEN */ +#endif /* MACH_PV_PAGETABLES */ pte++; } while (--i > 0); } @@ -2213,7 +2219,7 @@ void pmap_collect(p) register int i = ptes_per_vm_page; register pt_entry_t *pdep = pdp; do { -#ifdef MACH_XEN +#ifdef MACH_PV_PAGETABLES unsigned long pte = *pdep; void *ptable = (void*) ptetokv(pte); if (!(hyp_mmu_update_pte(pa_to_ma(kvtophys((vm_offset_t)pdep++)), 0))) @@ -2221,9 +2227,9 @@ void pmap_collect(p) if (!hyp_mmuext_op_mfn (MMUEXT_UNPIN_TABLE, kv_to_mfn(ptable))) panic("couldn't unpin page %p(%p)\n", ptable, (vm_offset_t) pa_to_ma(kvtophys((vm_offset_t)ptable))); pmap_set_page_readwrite(ptable); -#else /* MACH_XEN */ +#else /* MACH_PV_PAGETABLES */ *pdep++ = 0; -#endif /* MACH_XEN */ +#endif /* MACH_PV_PAGETABLES */ } while (--i > 0); } @@ -2440,12 +2446,12 @@ phys_attribute_clear(phys, bits) { register int i = ptes_per_vm_page; do { -#ifdef MACH_XEN +#ifdef MACH_PV_PAGETABLES if (!(hyp_mmu_update_pte(kv_to_ma(pte), *pte & ~bits))) panic("%s:%d could not clear bits %lx from pte %p\n",__FILE__,__LINE__,bits,pte); -#else /* MACH_XEN */ +#else /* MACH_PV_PAGETABLES */ *pte &= ~bits; -#endif /* MACH_XEN */ +#endif /* MACH_PV_PAGETABLES */ } while (--i > 0); } PMAP_UPDATE_TLBS(pmap, va, va + PAGE_SIZE); @@ -2806,12 +2812,12 @@ pmap_unmap_page_zero () if (!pte) return; assert (pte); -#ifdef MACH_XEN +#ifdef MACH_PV_PAGETABLES if (!hyp_mmu_update_pte(kv_to_ma(pte), 0)) printf("couldn't unmap page 0\n"); -#else /* MACH_XEN */ +#else /* MACH_PV_PAGETABLES */ *pte = 0; INVALIDATE_TLB(kernel_pmap, 0, PAGE_SIZE); -#endif /* MACH_XEN */ +#endif /* MACH_PV_PAGETABLES */ } #endif /* __i386__ */ diff --git a/i386/intel/pmap.h b/i386/intel/pmap.h index 2692aae..93293e3 100644 --- a/i386/intel/pmap.h +++ b/i386/intel/pmap.h @@ -132,12 +132,12 @@ typedef unsigned int pt_entry_t; #define INTEL_PTE_NCACHE 0x00000010 #define INTEL_PTE_REF 0x00000020 #define INTEL_PTE_MOD 0x00000040 -#ifdef MACH_XEN +#ifdef MACH_PV_PAGETABLES /* Not supported */ #define INTEL_PTE_GLOBAL 0x00000000 -#else /* MACH_XEN */ +#else /* MACH_PV_PAGETABLES */ #define INTEL_PTE_GLOBAL 0x00000100 -#endif /* MACH_XEN */ +#endif /* MACH_PV_PAGETABLES */ #define INTEL_PTE_WIRED 0x00000200 #ifdef PAE #define INTEL_PTE_PFN 0x00007ffffffff000ULL @@ -178,13 +178,13 @@ typedef struct pmap *pmap_t; #define PMAP_NULL ((pmap_t) 0) -#ifdef MACH_XEN +#ifdef MACH_PV_PAGETABLES extern void pmap_set_page_readwrite(void *addr); extern void pmap_set_page_readonly(void *addr); extern void pmap_set_page_readonly_init(void *addr); extern void pmap_map_mfn(void *addr, unsigned long mfn); extern void pmap_clear_bootstrap_pagetable(pt_entry_t *addr); -#endif /* MACH_XEN */ +#endif /* MACH_PV_PAGETABLES */ #if PAE #define set_pmap(pmap) set_cr3(kvtophys((vm_offset_t)(pmap)->pdpbase)) -- cgit v1.2.3