summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorkmacy <kmacy@FreeBSD.org>2008-09-29 22:13:29 +0000
committerkmacy <kmacy@FreeBSD.org>2008-09-29 22:13:29 +0000
commitcc2238d3339259960bfe8a6173749d9b0f95c9d9 (patch)
treedff10c28a75372762a0d64fd69327dc92ebb8084 /sys
parentde9e8917480edc80682a8b4355dfd83e315ea796 (diff)
downloadFreeBSD-src-cc2238d3339259960bfe8a6173749d9b0f95c9d9.zip
FreeBSD-src-cc2238d3339259960bfe8a6173749d9b0f95c9d9.tar.gz
vm_fault_hold_user_pages will not return if an address in the range passed in is mapped RO
but an RW mapping exists for the underlying page. This change fixes the bug by using the page / NULL returned from pmap_extract_and_hold to determine whether or not vm_fault needs to be called. The bug was pointed out by alc. MFC after: 3 days
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/cxgb/ulp/tom/cxgb_vm.c22
1 files changed, 8 insertions, 14 deletions
diff --git a/sys/dev/cxgb/ulp/tom/cxgb_vm.c b/sys/dev/cxgb/ulp/tom/cxgb_vm.c
index 9c6898a..0b83d4e 100644
--- a/sys/dev/cxgb/ulp/tom/cxgb_vm.c
+++ b/sys/dev/cxgb/ulp/tom/cxgb_vm.c
@@ -65,9 +65,7 @@ __FBSDID("$FreeBSD$");
int
vm_fault_hold_user_pages(vm_offset_t addr, vm_page_t *mp, int count, int flags)
{
-
vm_offset_t end, va;
- vm_paddr_t pa;
int faults, rv;
struct thread *td;
@@ -96,7 +94,6 @@ vm_fault_hold_user_pages(vm_offset_t addr, vm_page_t *mp, int count, int flags)
prot = VM_PROT_READ;
prot |= (flags & VM_HOLD_WRITEABLE) ? VM_PROT_WRITE : 0;
- bzero(pages, sizeof(vm_page_t *) * count);
retry:
/*
@@ -115,13 +112,12 @@ retry:
* we were only acquiring the pmap lock 1 time as opposed to potentially
* many dozens of times
*/
- m = pmap_extract_and_hold(pmap, va, prot);
+ *pages = m = pmap_extract_and_hold(pmap, va, prot);
if (m == NULL) {
faults++;
continue;
}
- *pages = m;
if (flags & VM_HOLD_WRITEABLE)
vm_page_dirty(m);
}
@@ -137,16 +133,14 @@ retry:
* trigger a fault where neccessary
*
*/
- for (va = addr; va < end; va += PAGE_SIZE) {
- m = NULL;
- pa = pmap_extract(pmap, va);
+ for (pages = mp, va = addr; va < end; va += PAGE_SIZE, pages++) {
+ m = *pages;
rv = 0;
- if (pa)
- m = PHYS_TO_VM_PAGE(pa);
- if (flags & VM_HOLD_WRITEABLE) {
- if (m == NULL || (m->flags & PG_WRITEABLE) == 0)
- rv = vm_fault(map, va, VM_PROT_WRITE, VM_FAULT_DIRTY);
- } else if (m == NULL)
+ if (m)
+ continue;
+ if (flags & VM_HOLD_WRITEABLE)
+ rv = vm_fault(map, va, VM_PROT_WRITE, VM_FAULT_DIRTY);
+ else
rv = vm_fault(map, va, VM_PROT_READ, VM_FAULT_NORMAL);
if (rv) {
printf("vm_fault bad return rv=%d va=0x%zx\n", rv, va);
OpenPOWER on IntegriCloud