Define dvma_map{in,out}() to map a buffer into DVMA space. These are
safe for use at interrupt time. Implement vmapbuf() and vunmapbuf() in terms of these new functions.
This commit is contained in:
parent
68e9c36909
commit
34c8ad8c30
@ -1,4 +1,4 @@
|
|||||||
/* $NetBSD: vm_machdep.c,v 1.13 1995/05/19 06:58:30 pk Exp $ */
|
/* $NetBSD: vm_machdep.c,v 1.14 1995/06/26 22:46:04 pk Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1992, 1993
|
* Copyright (c) 1992, 1993
|
||||||
@ -87,44 +87,98 @@ pagemove(from, to, size)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Map a range [va, va+len] in the given map to a kernel address
|
||||||
|
* in DVMA space.
|
||||||
|
*/
|
||||||
|
vm_offset_t
|
||||||
|
dvma_mapin(map, va, len, canwait)
|
||||||
|
struct vm_map *map;
|
||||||
|
vm_offset_t va;
|
||||||
|
int len, canwait;
|
||||||
|
{
|
||||||
|
vm_offset_t kva, tva;
|
||||||
|
register int npf, s;
|
||||||
|
register vm_offset_t pa;
|
||||||
|
long pn;
|
||||||
|
|
||||||
|
npf = btoc(round_page(len));
|
||||||
|
|
||||||
|
s = splimp();
|
||||||
|
for (;;) {
|
||||||
|
pn = rmalloc(dvmamap, npf);
|
||||||
|
if (pn != 0)
|
||||||
|
break;
|
||||||
|
if (canwait) {
|
||||||
|
(void)tsleep(dvmamap, PRIBIO+1, "physio", 0);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
splx(s);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
splx(s);
|
||||||
|
|
||||||
|
kva = tva = rctov(pn);
|
||||||
|
|
||||||
|
while (npf--) {
|
||||||
|
pa = pmap_extract(vm_map_pmap(map), va);
|
||||||
|
if (pa == 0)
|
||||||
|
panic("dvma_mapin: null page frame");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ### pmap_enter distributes this mapping to all contexts...
|
||||||
|
* maybe we should avoid this extra work
|
||||||
|
*/
|
||||||
|
pmap_enter(pmap_kernel(), tva,
|
||||||
|
trunc_page(pa) | PMAP_NC,
|
||||||
|
VM_PROT_READ|VM_PROT_WRITE, 1);
|
||||||
|
tva += PAGE_SIZE;
|
||||||
|
va += PAGE_SIZE;
|
||||||
|
}
|
||||||
|
return kva;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Remove double map of `va' in DVMA space at `kva'.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
dvma_mapout(kva, va, len)
|
||||||
|
vm_offset_t kva, va;
|
||||||
|
int len;
|
||||||
|
{
|
||||||
|
register int s;
|
||||||
|
|
||||||
|
pmap_remove(pmap_kernel(), kva, kva + len);
|
||||||
|
|
||||||
|
s = splimp();
|
||||||
|
rmfree(dvmamap, btoc(len), vtorc(kva));
|
||||||
|
wakeup(dvmamap);
|
||||||
|
splx(s);
|
||||||
|
|
||||||
|
if (vactype != VAC_NONE)
|
||||||
|
cache_flush((caddr_t)va, len);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Map an IO request into kernel virtual address space.
|
* Map an IO request into kernel virtual address space.
|
||||||
*
|
|
||||||
* ### pmap_enter distributes this mapping to all contexts ... maybe
|
|
||||||
* we should avoid this extra work
|
|
||||||
*
|
|
||||||
* THIS IS NOT IDEAL -- WE NEED ONLY VIRTUAL SPACE BUT kmem_alloc_wait
|
|
||||||
* DOES WORK DESIGNED TO SUPPLY PHYSICAL SPACE ON DEMAND LATER
|
|
||||||
*/
|
*/
|
||||||
vmapbuf(bp)
|
vmapbuf(bp)
|
||||||
register struct buf *bp;
|
register struct buf *bp;
|
||||||
{
|
{
|
||||||
register int npf;
|
register int len;
|
||||||
register caddr_t addr;
|
register caddr_t addr;
|
||||||
struct proc *p;
|
struct proc *p;
|
||||||
int off;
|
int off;
|
||||||
vm_offset_t kva;
|
vm_offset_t kva;
|
||||||
register vm_offset_t pa;
|
|
||||||
|
|
||||||
if ((bp->b_flags & B_PHYS) == 0)
|
if ((bp->b_flags & B_PHYS) == 0)
|
||||||
panic("vmapbuf");
|
panic("vmapbuf");
|
||||||
addr = bp->b_saveaddr = bp->b_un.b_addr;
|
addr = bp->b_saveaddr = bp->b_un.b_addr;
|
||||||
off = (int)addr & PGOFSET;
|
off = (int)addr & PGOFSET;
|
||||||
p = bp->b_proc;
|
p = bp->b_proc;
|
||||||
npf = btoc(round_page(bp->b_bcount + off));
|
len = round_page(bp->b_bcount + off);
|
||||||
kva = kmem_alloc_wait(phys_map, ctob(npf));
|
kva = dvma_mapin(&p->p_vmspace->vm_map, addr-off, len, 1);
|
||||||
bp->b_un.b_addr = (caddr_t) (kva + off);
|
bp->b_un.b_addr = (caddr_t) (kva + off);
|
||||||
while (npf--) {
|
|
||||||
pa = pmap_extract(vm_map_pmap(&p->p_vmspace->vm_map),
|
|
||||||
(vm_offset_t)addr);
|
|
||||||
if (pa == 0)
|
|
||||||
panic("vmapbuf: null page frame");
|
|
||||||
pmap_enter(vm_map_pmap(phys_map), kva,
|
|
||||||
trunc_page(pa) | PMAP_NC,
|
|
||||||
VM_PROT_READ|VM_PROT_WRITE, 1);
|
|
||||||
addr += PAGE_SIZE;
|
|
||||||
kva += PAGE_SIZE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -138,14 +192,13 @@ vunmapbuf(bp)
|
|||||||
|
|
||||||
if ((bp->b_flags & B_PHYS) == 0)
|
if ((bp->b_flags & B_PHYS) == 0)
|
||||||
panic("vunmapbuf");
|
panic("vunmapbuf");
|
||||||
off = (int)kva & PGOFSET;
|
|
||||||
kva -= off;
|
|
||||||
npf = btoc(round_page(bp->b_bcount + off));
|
|
||||||
kmem_free_wakeup(phys_map, kva, ctob(npf));
|
|
||||||
bp->b_un.b_addr = bp->b_saveaddr;
|
bp->b_un.b_addr = bp->b_saveaddr;
|
||||||
bp->b_saveaddr = NULL;
|
bp->b_saveaddr = NULL;
|
||||||
if (vactype != VAC_NONE)
|
|
||||||
cache_flush(bp->b_un.b_addr, bp->b_bcount - bp->b_resid);
|
off = (int)kva & PGOFSET;
|
||||||
|
kva -= off;
|
||||||
|
dvma_mapout(kva, bp->b_un.b_addr, round_page(bp->b_bcount + off));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -166,6 +219,18 @@ dvma_malloc(size)
|
|||||||
return (va);
|
return (va);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Free dvma addresses allocated with dvma_malloc()
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
dvma_free(ptr, size)
|
||||||
|
caddr_t ptr;
|
||||||
|
size_t size;
|
||||||
|
{
|
||||||
|
kmem_free(phys_map, (vm_offset_t)ptr, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The offset of the topmost frame in the kernel stack.
|
* The offset of the topmost frame in the kernel stack.
|
||||||
*/
|
*/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user