Port-xen archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
pmap cleanup approach.
Hi,
I'm trying to cleanup as many XEN-isms from x86 pmap as possible.
Could somebody have a look at this patch please, and let me know what
they think ? I haven't tested on dom0 yet.
I want to ideally remove all #ifdef XEN(PV) out of pmap.c
Finally, as an experiment for later (once PVHVM is stable) I want to
experiment with removing the idea of 'p2m/m2p' tables in their entirety
and use the power of our uvm_hotplug(9) infrastructure to directly
manage 'machine frames', however fragmented they are.
At the very least this would be an interesting test case for how well we
manage fragmented RAM.
Anyway, thoughts / testing on this patch below would be very welcome
please.
--
~cherry
Index: arch/amd64/include/pmap.h
===================================================================
RCS file: /cvsroot/src/sys/arch/amd64/include/pmap.h,v
retrieving revision 1.59
diff -u -p -r1.59 pmap.h
--- arch/amd64/include/pmap.h 11 Feb 2019 14:59:32 -0000 1.59
+++ arch/amd64/include/pmap.h 16 Feb 2019 08:38:59 -0000
@@ -195,9 +195,44 @@ extern bool svs_enabled;
#else
extern kmutex_t pte_lock;
+#define XPTE_MASK L1_FRAME
+/* Selects the index of a PTE in PTE_BASE */
+#define XPTE_SHIFT (L1_SHIFT - ilog2(sizeof(pt_entry_t)))
+
+/* PTE access inline fuctions */
+
+/*
+ * Get the machine address of the pointed pte
+ * We use hardware MMU to get value so works only for levels 1-3
+ */
+
+static __inline paddr_t
+xpmap_ptetomach(pt_entry_t *pte)
+{
+ pt_entry_t *up_pte;
+ vaddr_t va = (vaddr_t) pte;
+
+ va = ((va & XPTE_MASK) >> XPTE_SHIFT) | (vaddr_t) PTE_BASE;
+ up_pte = (pt_entry_t *) va;
+
+ return (paddr_t) (((*up_pte) & PG_FRAME) + (((vaddr_t) pte) & (~PG_FRAME & ~VA_SIGN_MASK)));
+}
+
+/* Xen helpers to change bits of a pte */
+#define XPMAP_UPDATE_DIRECT 1 /* Update direct map entry flags too */
+
+paddr_t vtomach(vaddr_t);
+#define vtomfn(va) (vtomach(va) >> PAGE_SHIFT)
+
static __inline pt_entry_t
pmap_pa2pte(paddr_t pa)
{
+ extern paddr_t pmap_pa_start; /* PA of first physical page for this domain */
+ extern paddr_t pmap_pa_end; /* PA of last physical page for this domain */
+
+ if (__predict_false(pa < pmap_pa_start || pmap_pa_end <= pa))
+ return (pa & PG_FRAME);
+
return (pt_entry_t)xpmap_ptom_masked(pa);
}
Index: arch/i386/include/pmap.h
===================================================================
RCS file: /cvsroot/src/sys/arch/i386/include/pmap.h,v
retrieving revision 1.122
diff -u -p -r1.122 pmap.h
--- arch/i386/include/pmap.h 11 Feb 2019 14:59:32 -0000 1.122
+++ arch/i386/include/pmap.h 16 Feb 2019 08:38:59 -0000
@@ -314,9 +314,44 @@
#else /* XENPV */
extern kmutex_t pte_lock;
+#define XPTE_MASK L1_FRAME
+/* Selects the index of a PTE in PTE_BASE */
+#define XPTE_SHIFT (L1_SHIFT - ilog2(sizeof(pt_entry_t)))
+
+/* PTE access inline fuctions */
+
+/*
+ * Get the machine address of the pointed pte
+ * We use hardware MMU to get value so works only for levels 1-3
+ */
+
+static __inline paddr_t
+xpmap_ptetomach(pt_entry_t *pte)
+{
+ pt_entry_t *up_pte;
+ vaddr_t va = (vaddr_t) pte;
+
+ va = ((va & XPTE_MASK) >> XPTE_SHIFT) | (vaddr_t) PTE_BASE;
+ up_pte = (pt_entry_t *) va;
+
+ return (paddr_t) (((*up_pte) & PG_FRAME) + (((vaddr_t) pte) & (~PG_FRAME & ~VA_SIGN_MASK)));
+}
+
+/* Xen helpers to change bits of a pte */
+#define XPMAP_UPDATE_DIRECT 1 /* Update direct map entry flags too */
+
+paddr_t vtomach(vaddr_t);
+#define vtomfn(va) (vtomach(va) >> PAGE_SHIFT)
+
static __inline pt_entry_t
pmap_pa2pte(paddr_t pa)
{
+ extern paddr_t pmap_pa_start; /* PA of first physical page for this domain */
+ extern paddr_t pmap_pa_end; /* PA of last physical page for this domain */
+
+ if (__predict_false(pa < pmap_pa_start || pmap_pa_end <= pa))
+ return (pa & PG_FRAME);
+
return (pt_entry_t)xpmap_ptom_masked(pa);
}
Index: arch/x86/include/pmap.h
===================================================================
RCS file: /cvsroot/src/sys/arch/x86/include/pmap.h,v
retrieving revision 1.97
diff -u -p -r1.97 pmap.h
--- arch/x86/include/pmap.h 13 Feb 2019 08:38:25 -0000 1.97
+++ arch/x86/include/pmap.h 16 Feb 2019 08:39:00 -0000
@@ -324,6 +324,7 @@ extern long nkptp[PTP_LEVELS];
#define pmap_phys_address(ppn) (x86_ptob(ppn) & ~X86_MMAP_FLAG_MASK)
#define pmap_mmap_flags(ppn) x86_mmap_flags(ppn)
#define pmap_valid_entry(E) ((E) & PG_V) /* is PDE or PTE valid? */
+#define pmap_entry_flags(E) ((E) & ~PG_FRAME)
#if defined(__x86_64__) || defined(PAE)
#define X86_MMAP_FLAG_SHIFT (64 - PGSHIFT)
@@ -337,7 +338,6 @@ extern long nkptp[PTP_LEVELS];
/*
* prototypes
*/
-
void pmap_activate(struct lwp *);
void pmap_bootstrap(vaddr_t);
bool pmap_clear_attrs(struct vm_page *, unsigned);
@@ -530,43 +530,11 @@ vaddr_t pmap_map(vaddr_t, paddr_t, paddr
void pmap_cpu_init_late(struct cpu_info *);
bool sse2_idlezero_page(void *);
-#ifdef XENPV
-#include <sys/bitops.h>
-
-#define XPTE_MASK L1_FRAME
-/* Selects the index of a PTE in (A)PTE_BASE */
-#define XPTE_SHIFT (L1_SHIFT - ilog2(sizeof(pt_entry_t)))
-
-/* PTE access inline fuctions */
-
-/*
- * Get the machine address of the pointed pte
- * We use hardware MMU to get value so works only for levels 1-3
- */
-
-static __inline paddr_t
-xpmap_ptetomach(pt_entry_t *pte)
-{
- pt_entry_t *up_pte;
- vaddr_t va = (vaddr_t) pte;
-
- va = ((va & XPTE_MASK) >> XPTE_SHIFT) | (vaddr_t) PTE_BASE;
- up_pte = (pt_entry_t *) va;
-
- return (paddr_t) (((*up_pte) & PG_FRAME) + (((vaddr_t) pte) & (~PG_FRAME & ~VA_SIGN_MASK)));
-}
-
-/* Xen helpers to change bits of a pte */
-#define XPMAP_UPDATE_DIRECT 1 /* Update direct map entry flags too */
-
-paddr_t vtomach(vaddr_t);
-#define vtomfn(va) (vtomach(va) >> PAGE_SHIFT)
-#endif /* XENPV */
/* pmap functions with machine addresses */
void pmap_kenter_ma(vaddr_t, paddr_t, vm_prot_t, u_int);
-int pmap_enter_ma(struct pmap *, vaddr_t, paddr_t, paddr_t,
- vm_prot_t, u_int, int);
+int pmap_enter_pa(struct pmap *, vaddr_t, paddr_t,
+ vm_prot_t, u_int);
bool pmap_extract_ma(pmap_t, vaddr_t, paddr_t *);
void pmap_free_ptps(struct vm_page *);
Index: arch/x86/x86/pmap.c
===================================================================
RCS file: /cvsroot/src/sys/arch/x86/x86/pmap.c,v
retrieving revision 1.323
diff -u -p -r1.323 pmap.c
--- arch/x86/x86/pmap.c 14 Feb 2019 08:18:25 -0000 1.323
+++ arch/x86/x86/pmap.c 16 Feb 2019 08:39:00 -0000
@@ -4140,7 +4140,7 @@ pmap_enter_default(pmap_t pmap, vaddr_t
return (*pmap->pm_enter)(pmap, va, pa, prot, flags);
}
- return pmap_enter_ma(pmap, va, pa, pa, prot, flags, 0);
+ return pmap_enter_pa(pmap, va, pa, prot, flags);
}
/*
@@ -4150,8 +4150,8 @@ pmap_enter_default(pmap_t pmap, vaddr_t
* => we set pmap => pv_head locking
*/
int
-pmap_enter_ma(struct pmap *pmap, vaddr_t va, paddr_t ma, paddr_t pa,
- vm_prot_t prot, u_int flags, int domid)
+pmap_enter_pa(struct pmap *pmap, vaddr_t va, paddr_t pa,
+ vm_prot_t prot, u_int flags)
{
pt_entry_t *ptes, opte, npte;
pt_entry_t *ptep;
@@ -4175,11 +4175,8 @@ pmap_enter_ma(struct pmap *pmap, vaddr_t
pmap_valid_entry(pmap->pm_pdir[pl_i(va, PTP_LEVELS)]),
"%s: missing kernel PTP for va=%#" PRIxVADDR, __func__, va);
-#ifdef XENPV
- KASSERT(domid == DOMID_SELF || pa == 0);
-#endif
-
- npte = ma | protection_codes[prot] | PG_V;
+ npte = pmap_pa2pte(pa);
+ npte |= protection_codes[prot] | PG_V;
npte |= pmap_pat_flags(flags);
if (wired)
npte |= PG_W;
@@ -4196,12 +4193,7 @@ pmap_enter_ma(struct pmap *pmap, vaddr_t
}
}
-#ifdef XENPV
- if (domid != DOMID_SELF)
- new_pg = NULL;
- else
-#endif
- new_pg = PHYS_TO_VM_PAGE(pa);
+ new_pg = PHYS_TO_VM_PAGE(pa);
if (new_pg != NULL) {
/* This is a managed page */
npte |= PG_PVLIST;
@@ -4278,27 +4270,7 @@ pmap_enter_ma(struct pmap *pmap, vaddr_t
if (((opte ^ npte) & (PG_FRAME | PG_V)) == 0) {
npte |= opte & (PG_U | PG_M);
}
-#if defined(XENPV)
- if (domid != DOMID_SELF) {
- /* pmap_pte_cas with error handling */
- int s = splvm();
- if (opte != *ptep) {
- splx(s);
- continue;
- }
- error = xpq_update_foreign(
- vtomach((vaddr_t)ptep), npte, domid);
- splx(s);
- if (error) {
- if (ptp != NULL && ptp->wire_count <= 1) {
- pmap_free_ptp(pmap, ptp, va, ptes, pdes);
- }
- pmap_unmap_ptes(pmap, pmap2);
- goto out;
- }
- break;
- }
-#endif /* defined(XENPV) */
+
} while (pmap_pte_cas(ptep, opte, npte) != opte);
/*
Index: arch/xen/include/xenfunc.h
===================================================================
RCS file: /cvsroot/src/sys/arch/xen/include/xenfunc.h,v
retrieving revision 1.17
diff -u -p -r1.17 xenfunc.h
--- arch/xen/include/xenfunc.h 12 Feb 2019 08:04:53 -0000 1.17
+++ arch/xen/include/xenfunc.h 16 Feb 2019 08:39:00 -0000
@@ -33,8 +33,6 @@
#include <xen/xen.h>
#include <xen/hypervisor.h>
#include <xen/evtchn.h>
-#include <xen/xenpmap.h>
-#include <machine/pte.h>
void xen_disable_intr(void);
void xen_enable_intr(void);
Index: arch/xen/include/xenpmap.h
===================================================================
RCS file: /cvsroot/src/sys/arch/xen/include/xenpmap.h,v
retrieving revision 1.41
diff -u -p -r1.41 xenpmap.h
--- arch/xen/include/xenpmap.h 13 Feb 2019 06:52:43 -0000 1.41
+++ arch/xen/include/xenpmap.h 16 Feb 2019 08:39:00 -0000
@@ -34,6 +34,7 @@
#include "opt_xen.h"
#endif
+#include <sys/bitops.h>
#include <sys/types.h>
#include <sys/kcpuset.h>
@@ -171,4 +172,9 @@ MULTI_update_va_mapping_otherdomain(
void xen_set_user_pgd(paddr_t);
#endif
+int xen_pmap_enter_ma(struct pmap *, vaddr_t, paddr_t,
+ vm_prot_t, u_int, int);
+
+/* pmap hooks */
+
#endif /* _XEN_XENPMAP_H_ */
Index: arch/xen/x86/xen_pmap.c
===================================================================
RCS file: /cvsroot/src/sys/arch/xen/x86/xen_pmap.c,v
retrieving revision 1.28
diff -u -p -r1.28 xen_pmap.c
--- arch/xen/x86/xen_pmap.c 2 Feb 2019 12:32:55 -0000 1.28
+++ arch/xen/x86/xen_pmap.c 16 Feb 2019 08:39:00 -0000
@@ -140,21 +140,69 @@ __KERNEL_RCSID(0, "$NetBSD: xen_pmap.c,v
extern pd_entry_t * const normal_pdes[];
-extern paddr_t pmap_pa_start; /* PA of first physical page for this domain */
-extern paddr_t pmap_pa_end; /* PA of last physical page for this domain */
-
int
-pmap_enter(struct pmap *pmap, vaddr_t va, paddr_t pa, vm_prot_t prot, u_int flags)
+xen_pmap_enter_ma(struct pmap *pmap, vaddr_t va, paddr_t ma, vm_prot_t prot,
+ u_int flags, int domid)
{
- paddr_t ma;
+ int error = 0;
+ pt_entry_t *ptes, *ptep, opte, npte;
+ pd_entry_t * const *pdes;
+ struct pmap *pmap2;
+
+ KASSERT(domid != DOMID_SELF);
+ error = pmap_enter(pmap, va, xpmap_mtop_masked(ma), prot, flags);
- if (__predict_false(pa < pmap_pa_start || pmap_pa_end <= pa)) {
- ma = pa; /* XXX hack */
- } else {
- ma = xpmap_ptom(pa);
+ if (error != 0) {
+ pmap_remove(pmap, va, va + PAGE_SIZE);
+ return error;
}
- return pmap_enter_ma(pmap, va, ma, pa, prot, flags, DOMID_SELF);
+ kpreempt_disable();
+ pmap_map_ptes(pmap, &pmap2, &ptes, &pdes); /* locks pmap */
+ ptep = &ptes[pl1_i(va)];
+ npte = ma & PG_FRAME; /* Flags will come from opte */
+
+ do {
+ opte = *ptep;
+
+ /*
+ * Pull in opte flags - these were assembled
+ * during pmap_enter_pa()
+ */
+
+ npte |= pmap_entry_flags(opte);
+
+ if (flags & PMAP_WIRED)
+ npte |= PG_W;
+ /* pmap_pte_cas with error handling */
+ int s = splvm();
+ if (opte != *ptep) {
+ splx(s);
+ continue;
+ }
+
+ error = xpq_update_foreign(vtomach((vaddr_t)ptep),
+ npte, domid);
+ splx(s);
+
+ if (error) {
+ pmap_unmap_ptes(pmap, pmap2);
+ pmap_remove(pmap, va, va + PAGE_SIZE);
+ return error;
+ }
+ break;
+ } while (opte != *ptep);
+
+ pmap_unmap_ptes(pmap, pmap2);
+ kpreempt_enable();
+
+ return error;
+}
+
+int
+pmap_enter(struct pmap *pmap, vaddr_t va, paddr_t pa, vm_prot_t prot, u_int flags)
+{
+ return pmap_enter_pa(pmap, va, pa, prot, flags);
}
/*
Index: arch/xen/xen/privcmd.c
===================================================================
RCS file: /cvsroot/src/sys/arch/xen/xen/privcmd.c,v
retrieving revision 1.51
diff -u -p -r1.51 privcmd.c
--- arch/xen/xen/privcmd.c 22 Jun 2017 22:36:50 -0000 1.51
+++ arch/xen/xen/privcmd.c 16 Feb 2019 08:39:00 -0000
@@ -413,7 +413,7 @@ privcmd_ioctl(void *v)
return error;
}
ma = ((paddr_t)mfn) << PGSHIFT;
- if (pmap_enter_ma(pmap_kernel(), trymap, ma, 0,
+ if (xen_pmap_enter_ma(pmap_kernel(), trymap, ma,
prot, PMAP_CANFAIL, pmb->dom)) {
mfn |= 0xF0000000;
copyout(&mfn, &pmb->arr[i], sizeof(mfn));
@@ -497,8 +497,8 @@ privpgop_fault(struct uvm_faultinfo *ufi
error = EFAULT;
break;
}
- error = pmap_enter_ma(ufi->orig_map->pmap, vaddr,
- pobj->maddr[maddr_i], 0, ufi->entry->protection,
+ error = xen_pmap_enter_ma(ufi->orig_map->pmap, vaddr,
+ pobj->maddr[maddr_i], ufi->entry->protection,
PMAP_CANFAIL | ufi->entry->protection,
pobj->domid);
if (error == ENOMEM) {
Home |
Main Index |
Thread Index |
Old Index