Date: Sat, 11 Jan 2003 12:51:44 -0800 (PST) From: Matthew Dillon <dillon@apollo.backplane.com> To: hackers@freebsd.org Cc: "Alan L. Cox" <alc@imimic.com>, Tor.Egge@cvsup.no.freebsd.org Subject: vmapbuf/vunmapbuf consolidation -- need alpha/ia64 review. Message-ID: <200301112051.h0BKpiWr047795@apollo.backplane.com> References: <20021102171534X.tegge@cvsup.no.freebsd.org> <3DCD7F3A.DE013857@imimic.com> <200301092137.h09Lbo0E005483@apollo.backplane.com> <3E1DF369.81ADB566@imimic.com> <200301100058.h0A0wiqo000380@apollo.backplane.com> <3E1FF17B.455C2A71@imimic.com>
next in thread | previous in thread | raw e-mail | index | archive | help
This patch consolidates all the vmapbuf()/vunmapbuf() implementations into kern/vfs_bio.c, removing them from */*/vm_machdep.c. All the implmentations appeared to be the same. The alpha and Ia64 implementations appeared to be older versions of the i386 implementation. I would like people associated with the alpha and ia64 work to review the change. Basically the alpha and ia64 were using individual pmap_kenter() calls while all the other implementations use a single pmap_qenter() call (and appeared to be exactly identical to the i386 vmapbuf() and vunmapbuf()). This consolidation is a necessary precursor to a complete reorganization of how pages will be reserved for physical I/O. Right now we use useracc() and vm_map_check_protection() but at least in regards to physical I/O these are wholely inadequate as they do not reserve the underlying pages or even determine if the address space is truely valid, only that the vm_map_entry is valid (e.g. mapping a 1MB file into a 4MB space with mmap() and issuing physical I/O above 1MB will panic both -current and -stable). Thanks, -Matt Matthew Dillon <dillon@backplane.com> :> * Combine all the platform-specific vmapbuf() and friends into :> a single version in sys/vm, in -current. : :They actually look and smell a lot like other code in kern/vfs_bio.c. :In fact, their prototypes are in sys/buf.h alongside other functions :from kern/vfs_bio.c. : :Alan Index: alpha/alpha/vm_machdep.c =================================================================== RCS file: /home/ncvs/src/sys/alpha/alpha/vm_machdep.c,v retrieving revision 1.77 diff -u -r1.77 vm_machdep.c --- alpha/alpha/vm_machdep.c 10 Dec 2002 02:33:43 -0000 1.77 +++ alpha/alpha/vm_machdep.c 11 Jan 2003 20:39:48 -0000 @@ -337,6 +337,8 @@ { } +#if 0 + /* * Map an IO request into kernel virtual address space. * @@ -405,6 +407,8 @@ bp->b_data = bp->b_saveaddr; } + +#endif /* * Reset back to firmware. Index: i386/i386/vm_machdep.c =================================================================== RCS file: /home/ncvs/src/sys/i386/i386/vm_machdep.c,v retrieving revision 1.196 diff -u -r1.196 vm_machdep.c --- i386/i386/vm_machdep.c 10 Dec 2002 02:33:43 -0000 1.196 +++ i386/i386/vm_machdep.c 11 Jan 2003 20:40:23 -0000 @@ -435,6 +435,8 @@ return((int)va); } +#if 0 + /* * Map an IO request into kernel virtual address space. * @@ -508,6 +510,7 @@ bp->b_data = bp->b_saveaddr; } +#endif /* * Force reset the processor by invalidating the entire address space! Index: ia64/ia64/vm_machdep.c =================================================================== RCS file: /home/ncvs/src/sys/ia64/ia64/vm_machdep.c,v retrieving revision 1.51 diff -u -r1.51 vm_machdep.c --- ia64/ia64/vm_machdep.c 10 Dec 2002 02:33:43 -0000 1.51 +++ ia64/ia64/vm_machdep.c 11 Jan 2003 20:41:06 -0000 @@ -350,6 +350,8 @@ { } +#if 0 + /* * Map an IO request into kernel virtual address space. * @@ -418,6 +420,8 @@ bp->b_data = bp->b_saveaddr; } + +#endif /* * Force reset the processor by invalidating the entire address space! Index: powerpc/powerpc/vm_machdep.c =================================================================== RCS file: /home/ncvs/src/sys/powerpc/powerpc/vm_machdep.c,v retrieving revision 1.80 diff -u -r1.80 vm_machdep.c --- powerpc/powerpc/vm_machdep.c 8 Jan 2003 12:29:59 -0000 1.80 +++ powerpc/powerpc/vm_machdep.c 11 Jan 2003 20:41:20 -0000 @@ -230,6 +230,9 @@ panic("cpu_throw() didn't"); } + +#if 0 + /* * Map an IO request into kernel virtual address space. * @@ -303,6 +306,8 @@ bp->b_data = bp->b_saveaddr; } + +#endif /* * Reset back to firmware. Index: sparc64/sparc64/vm_machdep.c =================================================================== RCS file: /home/ncvs/src/sys/sparc64/sparc64/vm_machdep.c,v retrieving revision 1.32 diff -u -r1.32 vm_machdep.c --- sparc64/sparc64/vm_machdep.c 5 Jan 2003 05:30:40 -0000 1.32 +++ sparc64/sparc64/vm_machdep.c 11 Jan 2003 20:41:33 -0000 @@ -377,6 +377,8 @@ return(r); } +#if 0 + /* * Map an IO request into kernel virtual address space. * @@ -450,3 +452,5 @@ bp->b_data = bp->b_saveaddr; } + +#endif Index: kern/vfs_bio.c =================================================================== RCS file: /home/ncvs/src/sys/kern/vfs_bio.c,v retrieving revision 1.352 diff -u -r1.352 vfs_bio.c --- kern/vfs_bio.c 7 Jan 2003 19:55:08 -0000 1.352 +++ kern/vfs_bio.c 11 Jan 2003 20:42:03 -0000 @@ -3540,6 +3540,77 @@ bp->b_npages = newnpages; } +/* + * Map an IO request into kernel virtual address space. + * + * All requests are (re)mapped into kernel VA space. + * Notice that we use b_bufsize for the size of the buffer + * to be mapped. b_bcount might be modified by the driver. + */ +void +vmapbuf(struct buf *bp) +{ + caddr_t addr, kva; + vm_offset_t pa; + int pidx; + struct vm_page *m; + + GIANT_REQUIRED; + + if ((bp->b_flags & B_PHYS) == 0) + panic("vmapbuf"); + + for (addr = (caddr_t)trunc_page((vm_offset_t)bp->b_data), pidx = 0; + addr < bp->b_data + bp->b_bufsize; + addr += PAGE_SIZE, pidx++) { + /* + * Do the vm_fault if needed; do the copy-on-write thing + * when reading stuff off device into memory. + */ + vm_fault_quick((addr >= bp->b_data) ? addr : bp->b_data, + (bp->b_iocmd == BIO_READ)?(VM_PROT_READ|VM_PROT_WRITE):VM_PROT_READ); + pa = trunc_page(pmap_kextract((vm_offset_t) addr)); + if (pa == 0) + panic("vmapbuf: page not present"); + m = PHYS_TO_VM_PAGE(pa); + vm_page_hold(m); + bp->b_pages[pidx] = m; + } + if (pidx > btoc(MAXPHYS)) + panic("vmapbuf: mapped more than MAXPHYS"); + pmap_qenter((vm_offset_t)bp->b_saveaddr, bp->b_pages, pidx); + + kva = bp->b_saveaddr; + bp->b_npages = pidx; + bp->b_saveaddr = bp->b_data; + bp->b_data = kva + (((vm_offset_t) bp->b_data) & PAGE_MASK); +} + +/* + * Free the io map PTEs associated with this IO operation. + * We also invalidate the TLB entries and restore the original b_addr. + */ +void +vunmapbuf(struct buf *bp) +{ + int pidx; + int npages; + + GIANT_REQUIRED; + + if ((bp->b_flags & B_PHYS) == 0) + panic("vunmapbuf"); + + npages = bp->b_npages; + pmap_qremove(trunc_page((vm_offset_t)bp->b_data), + npages); + vm_page_lock_queues(); + for (pidx = 0; pidx < npages; pidx++) + vm_page_unhold(bp->b_pages[pidx]); + vm_page_unlock_queues(); + + bp->b_data = bp->b_saveaddr; +} #include "opt_ddb.h" #ifdef DDB To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-hackers" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200301112051.h0BKpiWr047795>