Date: Wed, 10 Jul 2013 07:12:55 +0000 (UTC) From: Neel Natu <neel@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r253135 - in projects/bhyve_npt_pmap/sys/amd64: include vmm Message-ID: <201307100712.r6A7CtsB031581@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201307100712.r6A7CtsB031581>