svn commit: r253135 - in projects/bhyve_npt_pmap/sys/amd64: include vmm

Neel Natu neel at FreeBSD.org
Wed Jul 10 07:12:56 UTC 2013


Author: neel
Date: Wed Jul 10 07:12:55 2013
New Revision: 253135
URL: http://svnweb.freebsd.org/changeset/base/253135

Log:
  Replace vm_gpa2hpa() with a pair of functions vm_gpa_hold()/vm_gpa_release().
  
  We guarantee that the vm_page backing the 'gpa' is not reclaimed by
  the page daemon until the caller indicates that they are done using it
  by calling 'vm_gpa_release()'.

Modified:
  projects/bhyve_npt_pmap/sys/amd64/include/vmm.h
  projects/bhyve_npt_pmap/sys/amd64/vmm/vmm.c
  projects/bhyve_npt_pmap/sys/amd64/vmm/vmm_dev.c
  projects/bhyve_npt_pmap/sys/amd64/vmm/vmm_instruction_emul.c

Modified: projects/bhyve_npt_pmap/sys/amd64/include/vmm.h
==============================================================================
--- projects/bhyve_npt_pmap/sys/amd64/include/vmm.h	Wed Jul 10 06:46:46 2013	(r253134)
+++ projects/bhyve_npt_pmap/sys/amd64/include/vmm.h	Wed Jul 10 07:12:55 2013	(r253135)
@@ -93,6 +93,9 @@ const char *vm_name(struct vm *vm);
 int vm_malloc(struct vm *vm, vm_paddr_t gpa, size_t len);
 int vm_map_mmio(struct vm *vm, vm_paddr_t gpa, size_t len, vm_paddr_t hpa);
 int vm_unmap_mmio(struct vm *vm, vm_paddr_t gpa, size_t len);
+void *vm_gpa_hold(struct vm *, vm_paddr_t gpa, size_t len, int prot,
+		  void **cookie);
+void vm_gpa_release(void *cookie);
 vm_paddr_t vm_gpa2hpa(struct vm *vm, vm_paddr_t gpa, size_t size);
 int vm_gpabase2memseg(struct vm *vm, vm_paddr_t gpabase,
 	      struct vm_memory_segment *seg);

Modified: projects/bhyve_npt_pmap/sys/amd64/vmm/vmm.c
==============================================================================
--- projects/bhyve_npt_pmap/sys/amd64/vmm/vmm.c	Wed Jul 10 06:46:46 2013	(r253134)
+++ projects/bhyve_npt_pmap/sys/amd64/vmm/vmm.c	Wed Jul 10 07:12:55 2013	(r253135)
@@ -439,16 +439,48 @@ vm_malloc(struct vm *vm, vm_paddr_t gpa,
 	return (0);
 }
 
-vm_paddr_t
-vm_gpa2hpa(struct vm *vm, vm_paddr_t gpa, size_t len)
+void *
+vm_gpa_hold(struct vm *vm, vm_paddr_t gpa, size_t len, int reqprot,
+	    void **cookie)
 {
-	vm_paddr_t nextpage;
+	int rv, pageoff;
+	vm_page_t m;
+	struct proc *p;
+
+	pageoff = gpa & PAGE_MASK;
+	if (len > PAGE_SIZE - pageoff)
+		panic("vm_gpa_hold: invalid gpa/len: 0x%016lx/%lu", gpa, len);
+
+	p = curthread->td_proc;
+
+	PROC_LOCK(p);
+	p->p_lock++;
+	PROC_UNLOCK(p);
 
-	nextpage = rounddown(gpa + PAGE_SIZE, PAGE_SIZE);
-	if (len > nextpage - gpa)
-		panic("vm_gpa2hpa: invalid gpa/len: 0x%016lx/%lu", gpa, len);
+	rv = vm_fault_hold(&vm->vmspace->vm_map, trunc_page(gpa), reqprot,
+			   VM_FAULT_NORMAL, &m);
+
+	PROC_LOCK(p);
+	p->p_lock--;
+	PROC_UNLOCK(p);
+
+	if (rv == KERN_SUCCESS) {
+		*cookie = m;
+		return ((void *)(PHYS_TO_DMAP(VM_PAGE_TO_PHYS(m)) + pageoff));
+	} else {
+		*cookie = NULL;
+		return (NULL);
+	}
+}
+
+void
+vm_gpa_release(void *cookie)
+{
+	vm_page_t m = cookie;
 
-	return ((vm_paddr_t)-1);	/* XXX fixme */
+	vm_page_lock(m);
+	vm_page_unhold(m);
+	vm_page_unlock(m);
 }
 
 int

Modified: projects/bhyve_npt_pmap/sys/amd64/vmm/vmm_dev.c
==============================================================================
--- projects/bhyve_npt_pmap/sys/amd64/vmm/vmm_dev.c	Wed Jul 10 06:46:46 2013	(r253134)
+++ projects/bhyve_npt_pmap/sys/amd64/vmm/vmm_dev.c	Wed Jul 10 07:12:55 2013	(r253135)
@@ -95,8 +95,9 @@ vmmdev_lookup2(struct cdev *cdev)
 static int
 vmmdev_rw(struct cdev *cdev, struct uio *uio, int flags)
 {
-	int error, off, c;
-	vm_paddr_t hpa, gpa;
+	int error, off, c, prot;
+	vm_paddr_t gpa;
+	void *hpa, *cookie;
 	struct vmmdev_softc *sc;
 
 	static char zerobuf[PAGE_SIZE];
@@ -107,6 +108,7 @@ vmmdev_rw(struct cdev *cdev, struct uio 
 	if (sc == NULL)
 		error = ENXIO;
 
+	prot = (uio->uio_rw == UIO_WRITE ? VM_PROT_WRITE : VM_PROT_READ);
 	while (uio->uio_resid > 0 && error == 0) {
 		gpa = uio->uio_offset;
 		off = gpa & PAGE_MASK;
@@ -120,14 +122,16 @@ vmmdev_rw(struct cdev *cdev, struct uio 
 		 * Since this device does not support lseek(2), dd(1) will
 		 * read(2) blocks of data to simulate the lseek(2).
 		 */
-		hpa = vm_gpa2hpa(sc->vm, gpa, c);
-		if (hpa == (vm_paddr_t)-1) {
+		hpa = vm_gpa_hold(sc->vm, gpa, c, prot, &cookie);
+		if (hpa == NULL) {
 			if (uio->uio_rw == UIO_READ)
 				error = uiomove(zerobuf, c, uio);
 			else
 				error = EFAULT;
-		} else
-			error = uiomove((void *)PHYS_TO_DMAP(hpa), c, uio);
+		} else {
+			error = uiomove(hpa, c, uio);
+			vm_gpa_release(cookie);
+		}
 	}
 
 	mtx_unlock(&vmmdev_mtx);

Modified: projects/bhyve_npt_pmap/sys/amd64/vmm/vmm_instruction_emul.c
==============================================================================
--- projects/bhyve_npt_pmap/sys/amd64/vmm/vmm_instruction_emul.c	Wed Jul 10 06:46:46 2013	(r253134)
+++ projects/bhyve_npt_pmap/sys/amd64/vmm/vmm_instruction_emul.c	Wed Jul 10 07:12:55 2013	(r253135)
@@ -413,9 +413,9 @@ static int
 gla2gpa(struct vm *vm, uint64_t gla, uint64_t ptpphys,
 	uint64_t *gpa, uint64_t *gpaend)
 {
-	vm_paddr_t hpa;
 	int nlevels, ptpshift, ptpindex;
 	uint64_t *ptpbase, pte, pgsize;
+	void *cookie;
 
 	/*
 	 * XXX assumes 64-bit guest with 4 page walk levels
@@ -425,18 +425,19 @@ gla2gpa(struct vm *vm, uint64_t gla, uin
 		/* Zero out the lower 12 bits and the upper 12 bits */
 		ptpphys >>= 12; ptpphys <<= 24; ptpphys >>= 12;
 
-		hpa = vm_gpa2hpa(vm, ptpphys, PAGE_SIZE);
-		if (hpa == -1)
+		ptpbase = vm_gpa_hold(vm, ptpphys, PAGE_SIZE, VM_PROT_READ,
+				      &cookie);
+		if (ptpbase == NULL)
 			goto error;
 
-		ptpbase = (uint64_t *)PHYS_TO_DMAP(hpa);
-
 		ptpshift = PAGE_SHIFT + nlevels * 9;
 		ptpindex = (gla >> ptpshift) & 0x1FF;
 		pgsize = 1UL << ptpshift;
 
 		pte = ptpbase[ptpindex];
 
+		vm_gpa_release(cookie);
+
 		if ((pte & PG_V) == 0)
 			goto error;
 
@@ -464,13 +465,15 @@ int
 vmm_fetch_instruction(struct vm *vm, int cpuid, uint64_t rip, int inst_length,
 		      uint64_t cr3, struct vie *vie)
 {
-	int n, err;
-	uint64_t hpa, gpa, gpaend, off;
+	int n, err, prot;
+	uint64_t gpa, gpaend, off;
+	void *hpa, *cookie;
 
 	/*
 	 * XXX cache previously fetched instructions using 'rip' as the tag
 	 */
 
+	prot = VM_PROT_READ | VM_PROT_EXECUTE;
 	if (inst_length > VIE_INST_SIZE)
 		panic("vmm_fetch_instruction: invalid length %d", inst_length);
 
@@ -483,11 +486,12 @@ vmm_fetch_instruction(struct vm *vm, int
 		off = gpa & PAGE_MASK;
 		n = min(inst_length - vie->num_valid, PAGE_SIZE - off);
 
-		hpa = vm_gpa2hpa(vm, gpa, n);
-		if (hpa == -1)
+		if ((hpa = vm_gpa_hold(vm, gpa, n, prot, &cookie)) == NULL)
 			break;
 
-		bcopy((void *)PHYS_TO_DMAP(hpa), &vie->inst[vie->num_valid], n);
+		bcopy(hpa, &vie->inst[vie->num_valid], n);
+
+		vm_gpa_release(cookie);
 
 		rip += n;
 		vie->num_valid += n;


More information about the svn-src-projects mailing list