diff options
author | jkim <jkim@FreeBSD.org> | 2010-08-09 17:54:26 +0000 |
---|---|---|
committer | jkim <jkim@FreeBSD.org> | 2010-08-09 17:54:26 +0000 |
commit | c9e34bbc399cb5bc6d59b9dba93b0ab0a2267f72 (patch) | |
tree | 8ac94b4eb88021ef75be6bdf44cdeceb4a9c84e6 | |
parent | c11b0f0ec97c203033bc6d735388b3d0cc658fd3 (diff) | |
download | FreeBSD-src-c9e34bbc399cb5bc6d59b9dba93b0ab0a2267f72.zip FreeBSD-src-c9e34bbc399cb5bc6d59b9dba93b0ab0a2267f72.tar.gz |
Reduce diffs between VM86 and X86EMU wrappers for x86bios_alloc() and
x86bios_free(). Add strict sanity checks for VM86 wrapper and add strict
page table locking for X86EMU wrapper.
-rw-r--r-- | sys/compat/x86bios/x86bios.c | 52 |
1 files changed, 29 insertions, 23 deletions
diff --git a/sys/compat/x86bios/x86bios.c b/sys/compat/x86bios/x86bios.c index 47c2b97..14f714e 100644 --- a/sys/compat/x86bios/x86bios.c +++ b/sys/compat/x86bios/x86bios.c @@ -112,44 +112,49 @@ x86bios_vmf2emu(struct vm86frame *vmf, struct x86emu_regs *regs) void * x86bios_alloc(uint32_t *offset, size_t size, int flags) { - vm_offset_t addr; + void *vaddr; int i; - addr = (vm_offset_t)contigmalloc(size, M_DEVBUF, flags, 0, - X86BIOS_MEM_SIZE, PAGE_SIZE, 0); - if (addr != 0) { - *offset = vtophys(addr); + if (offset == NULL || size == 0) + return (NULL); + vaddr = contigmalloc(size, M_DEVBUF, flags, 0, X86BIOS_MEM_SIZE, + PAGE_SIZE, 0); + if (vaddr != NULL) { + *offset = vtophys(vaddr); mtx_lock(&x86bios_lock); for (i = 0; i < atop(round_page(size)); i++) vm86_addpage(&x86bios_vmc, atop(*offset) + i, - addr + ptoa(i)); + (vm_offset_t)vaddr + ptoa(i)); mtx_unlock(&x86bios_lock); } - return ((void *)addr); + return (vaddr); } void x86bios_free(void *addr, size_t size) { - int i, last; + vm_paddr_t paddr; + int i, nfree; + if (addr == NULL || size == 0) + return; + paddr = vtophys(addr); + if (paddr >= X86BIOS_MEM_SIZE || (paddr & PAGE_MASK) != 0) + return; + nfree = atop(round_page(size)); mtx_lock(&x86bios_lock); - for (i = 0, last = -1; i < x86bios_vmc.npages; i++) - if (x86bios_vmc.pmap[i].kva >= (vm_offset_t)addr && - x86bios_vmc.pmap[i].kva < (vm_offset_t)addr + size) { - bzero(&x86bios_vmc.pmap[i], - sizeof(x86bios_vmc.pmap[i])); - last = i; - } - if (last < 0) { + for (i = 0; i < x86bios_vmc.npages; i++) + if (x86bios_vmc.pmap[i].kva == (vm_offset_t)addr) + break; + if (i >= x86bios_vmc.npages) { mtx_unlock(&x86bios_lock); return; } - if (last == x86bios_vmc.npages - 1) { - x86bios_vmc.npages -= atop(round_page(size)); - for (i = x86bios_vmc.npages - 1; - i >= 0 && x86bios_vmc.pmap[i].kva == 0; i--) + bzero(x86bios_vmc.pmap + i, sizeof(*x86bios_vmc.pmap) * nfree); + if (i + nfree == x86bios_vmc.npages) { + x86bios_vmc.npages -= nfree; + while (--i >= 0 && x86bios_vmc.pmap[i].kva == 0) x86bios_vmc.npages--; } mtx_unlock(&x86bios_lock); @@ -552,12 +557,13 @@ x86bios_alloc(uint32_t *offset, size_t size, int flags) if (offset == NULL || size == 0) return (NULL); - vaddr = contigmalloc(size, M_DEVBUF, flags, X86BIOS_RAM_BASE, x86bios_rom_phys, X86BIOS_PAGE_SIZE, 0); if (vaddr != NULL) { *offset = vtophys(vaddr); + mtx_lock_spin(&x86bios_lock); x86bios_set_pages((vm_offset_t)vaddr, *offset, size); + mtx_unlock_spin(&x86bios_lock); } return (vaddr); @@ -570,14 +576,14 @@ x86bios_free(void *addr, size_t size) if (addr == NULL || size == 0) return; - paddr = vtophys(addr); if (paddr < X86BIOS_RAM_BASE || paddr >= x86bios_rom_phys || paddr % X86BIOS_PAGE_SIZE != 0) return; - + mtx_lock_spin(&x86bios_lock); bzero(x86bios_map + paddr / X86BIOS_PAGE_SIZE, sizeof(*x86bios_map) * howmany(size, X86BIOS_PAGE_SIZE)); + mtx_unlock_spin(&x86bios_lock); contigfree(addr, size, M_DEVBUF); } |