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