These patches are submitted for your amusement. My AMD64 system runs to the extent that it compiled the kernel and ran fsck. DMA is allowed to pages over 0xFFFFFFFF. I/O to raw disk devices uses much less system time.
There are five pieces: fix bounded allocation in uvm_pmemrange enable existing flag BUS_DMA_32BIT for broken hardware and software force all USB allocations to low 4G using _32BIT flag for the obtuse EHCI spec - control blocks can't span 4G add flag to enable asking for dma accessible anon memory used if page is faulted in to be wired (presumably for DMA?) makes physio() likely not to use copyin/copyout There may be definition disfunctions with OHCI similar to those with EHCI. There's a suspicious malloc(). I'll look at them later. Happy new year! Geoff Steckel Diffs and dmesg: Index: arch/amd64/amd64/bus_dma.c =================================================================== RCS file: /cvs/src/sys/arch/amd64/amd64/bus_dma.c,v retrieving revision 1.38 diff -u -r1.38 bus_dma.c --- arch/amd64/amd64/bus_dma.c 3 Jul 2011 18:31:02 -0000 1.38 +++ arch/amd64/amd64/bus_dma.c 1 Jan 2012 04:18:24 -0000 @@ -418,6 +418,10 @@ bus_size_t boundary, bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags) { + paddr_t limit = (paddr_t) -1LL ; /* huge for 64 bit */ + + if (flags & BUS_DMA_32BIT) /* broken controller or code */ + limit = (paddr_t) 0xffffffffLL ; /* * XXX in the presence of decent (working) iommus and bouncebuffers @@ -426,7 +430,7 @@ * memory under the 4gig boundary. */ return (_bus_dmamem_alloc_range(t, size, alignment, boundary, - segs, nsegs, rsegs, flags, (paddr_t)0, (paddr_t)0xffffffff)); + segs, nsegs, rsegs, flags, (paddr_t)0, limit)); } /* Index: arch/amd64/amd64/machdep.c =================================================================== RCS file: /cvs/src/sys/arch/amd64/amd64/machdep.c,v retrieving revision 1.149 diff -u -r1.149 machdep.c --- arch/amd64/amd64/machdep.c 10 Jul 2011 18:11:49 -0000 1.149 +++ arch/amd64/amd64/machdep.c 1 Jan 2012 04:18:24 -0000 @@ -203,7 +203,7 @@ /* UVM constraint ranges. */ struct uvm_constraint_range isa_constraint = { 0x0, 0x00ffffffUL }; -struct uvm_constraint_range dma_constraint = { 0x0, 0xffffffffUL }; +struct uvm_constraint_range dma_constraint = { 0x0, 0x1ffffffffUL }; struct uvm_constraint_range *uvm_md_constraints[] = { &isa_constraint, &dma_constraint, Index: dev/usb/usb_mem.c =================================================================== RCS file: /cvs/src/sys/dev/usb/usb_mem.c,v retrieving revision 1.23 diff -u -r1.23 usb_mem.c --- dev/usb/usb_mem.c 5 Apr 2011 19:54:35 -0000 1.23 +++ dev/usb/usb_mem.c 1 Jan 2012 04:18:25 -0000 @@ -137,7 +137,7 @@ p->align = align; error = bus_dmamem_alloc(tag, p->size, align, 0, p->segs, nitems(p->segs), - &p->nsegs, BUS_DMA_NOWAIT); + &p->nsegs, BUS_DMA_NOWAIT | BUS_DMA_32BIT); if (error) goto free0; Index: uvm/uvm_anon.c =================================================================== RCS file: /cvs/src/sys/uvm/uvm_anon.c,v retrieving revision 1.35 diff -u -r1.35 uvm_anon.c --- uvm/uvm_anon.c 3 Jul 2011 18:34:14 -0000 1.35 +++ uvm/uvm_anon.c 1 Jan 2012 04:18:25 -0000 @@ -296,7 +296,7 @@ int rv; /* locked: anon */ - rv = uvmfault_anonget(NULL, NULL, anon); + rv = uvmfault_anonget(NULL, NULL, anon, 0); /* * if rv == VM_PAGER_OK, anon is still locked, else anon * is unlocked Index: uvm/uvm_extern.h =================================================================== RCS file: /cvs/src/sys/uvm/uvm_extern.h,v retrieving revision 1.103 diff -u -r1.103 uvm_extern.h --- uvm/uvm_extern.h 8 Jul 2011 00:10:59 -0000 1.103 +++ uvm/uvm_extern.h 1 Jan 2012 04:18:25 -0000 @@ -213,6 +213,7 @@ */ #define UVM_PGA_USERESERVE 0x0001 /* ok to use reserve pages */ #define UVM_PGA_ZERO 0x0002 /* returned page must be zeroed */ +#define UVM_PGA_DMA 0x0004 /* try to put page in DMA space */ /* * flags for uvm_pglistalloc() Index: uvm/uvm_fault.c =================================================================== RCS file: /cvs/src/sys/uvm/uvm_fault.c,v retrieving revision 1.62 diff -u -r1.62 uvm_fault.c --- uvm/uvm_fault.c 3 Jul 2011 18:34:14 -0000 1.62 +++ uvm/uvm_fault.c 1 Jan 2012 04:18:25 -0000 @@ -291,7 +291,7 @@ int uvmfault_anonget(struct uvm_faultinfo *ufi, struct vm_amap *amap, - struct vm_anon *anon) + struct vm_anon *anon, int need_dma) { boolean_t we_own; /* we own anon's page? */ boolean_t locked; /* did we relock? */ @@ -365,7 +365,8 @@ /* * no page, we must try and bring it in. */ - pg = uvm_pagealloc(NULL, 0, anon, 0); + pg = uvm_pagealloc(NULL, 0, anon, + need_dma ? UVM_PGA_DMA : 0); if (pg == NULL) { /* out of RAM. */ @@ -992,7 +993,7 @@ * lock that object for us if it does not fail. */ - result = uvmfault_anonget(&ufi, amap, anon); + result = uvmfault_anonget(&ufi, amap, anon, wired); switch (result) { case VM_PAGER_OK: break; @@ -1057,7 +1058,8 @@ if (anon->an_ref == 1) { /* get new un-owned replacement page */ - pg = uvm_pagealloc(NULL, 0, NULL, 0); + pg = uvm_pagealloc(NULL, 0, NULL, + wired ? UVM_PGA_DMA : 0); if (pg == NULL) { uvmfault_unlockall(&ufi, amap, uobj, anon); @@ -1121,7 +1123,8 @@ oanon = anon; /* oanon = old, locked anon */ anon = uvm_analloc(); if (anon) { - pg = uvm_pagealloc(NULL, 0, anon, 0); + pg = uvm_pagealloc(NULL, 0, anon, + wired ? UVM_PGA_DMA : 0); } /* check for out of RAM */ @@ -1399,7 +1402,8 @@ /* write fault: must break the loan here */ /* alloc new un-owned page */ - pg = uvm_pagealloc(NULL, 0, NULL, 0); + pg = uvm_pagealloc(NULL, 0, NULL, + wired ? UVM_PGA_DMA : 0); if (pg == NULL) { /* @@ -1485,9 +1489,11 @@ * uobjpage == PGO_DONTCARE, we want * a zero'd, dirty page, so have * uvm_pagealloc() do that for us. + * If this is a fault from mlock, put in DMA memory. */ pg = uvm_pagealloc(NULL, 0, anon, - (uobjpage == PGO_DONTCARE) ? UVM_PGA_ZERO : 0); + ((uobjpage == PGO_DONTCARE) ? UVM_PGA_ZERO : 0) | + (wired ? UVM_PGA_DMA : 0)); } /* Index: uvm/uvm_fault.h =================================================================== RCS file: /cvs/src/sys/uvm/uvm_fault.h,v retrieving revision 1.13 diff -u -r1.13 uvm_fault.h --- uvm/uvm_fault.h 25 Mar 2009 20:00:18 -0000 1.13 +++ uvm/uvm_fault.h 1 Jan 2012 04:18:25 -0000 @@ -78,7 +78,7 @@ void uvmfault_unlockall(struct uvm_faultinfo *, struct vm_amap *, struct uvm_object *, struct vm_anon *); int uvmfault_anonget(struct uvm_faultinfo *, struct vm_amap *, - struct vm_anon *); + struct vm_anon *, int); int uvm_fault_wire(vm_map_t, vaddr_t, vaddr_t, vm_prot_t); void uvm_fault_unwire(vm_map_t, vaddr_t, vaddr_t); Index: uvm/uvm_page.c =================================================================== RCS file: /cvs/src/sys/uvm/uvm_page.c,v retrieving revision 1.114 diff -u -r1.114 uvm_page.c --- uvm/uvm_page.c 8 Jul 2011 00:10:59 -0000 1.114 +++ uvm/uvm_page.c 1 Jan 2012 04:18:25 -0000 @@ -955,8 +955,19 @@ if (flags & UVM_PGA_ZERO) pmr_flags |= UVM_PLA_ZERO; TAILQ_INIT(&pgl); - if (uvm_pmr_getpages(1, 0, 0, 1, 0, 1, pmr_flags, &pgl) != 0) - goto fail; + /* + * If a DMA page is requested, attempt to get it. + * Don't fail if not available but try for any page. + */ + if (flags & UVM_PGA_DMA) { + if (uvm_pmr_getpages(1, atop(dma_constraint.ucr_low), + atop(dma_constraint.ucr_high + 1), 1, 0, 1, pmr_flags, + &pgl) != 0) + if (uvm_pmr_getpages(1, 0, 0, 1, 0, 1, pmr_flags, &pgl) != 0) + goto fail; + } else + if (uvm_pmr_getpages(1, 0, 0, 1, 0, 1, pmr_flags, &pgl) != 0) + goto fail; pg = TAILQ_FIRST(&pgl); KASSERT(pg != NULL && TAILQ_NEXT(pg, pageq) == NULL); Index: uvm/uvm_pmemrange.c =================================================================== RCS file: /cvs/src/sys/uvm/uvm_pmemrange.c,v retrieving revision 1.33 diff -u -r1.33 uvm_pmemrange.c --- uvm/uvm_pmemrange.c 3 Dec 2011 20:07:06 -0000 1.33 +++ uvm/uvm_pmemrange.c 1 Jan 2012 04:18:25 -0000 @@ -912,6 +912,8 @@ fend = atop(VM_PAGE_TO_PHYS(found)) + found->fpgsz; if (fstart >= fend) continue; + if (end && fstart >= end) + continue; if (boundary != 0) { fend = MIN(fend, PMR_ALIGN(fstart + 1, boundary)); Dmesg: OpenBSD 5.0-current (debuni) #13: Sat Dec 31 22:55:29 EST 2011 g...@lib.oat.com:/dorm/usr/src/sys/arch/amd64/compile/debuni real mem = 3754819584 (3580MB) avail mem = 3640602624 (3471MB) mainbus0 at root bios0 at mainbus0: SMBIOS rev. 2.4 @ 0xf0100 (55 entries) bios0: vendor Award Software International, Inc. version "F2" date 04/30/2009 bios0: Gigabyte Technology Co., Ltd. GA-MA790GP-UD4H acpi0 at bios0: rev 0 acpi0: sleep states S0 S3 S4 S5 acpi0: tables DSDT FACP SSDT HPET MCFG TAMG APIC acpi0: wakeup devices USB0(S3) USB1(S3) USB2(S3) USB3(S3) USB4(S3) USB5(S3) USB6(S3) SBAZ(S4) P2P_(S5) PCE2(S4) PCE3(S4) PCE4(S4) PCE5(S4) PCE6(S4) PCE7(S4) PCE9(S4) PCEA(S4) PCEB(S4) PCEC(S4) PS2M(S5) PS2K(S5) PCI0(S5) acpitimer0 at acpi0: 3579545 Hz, 32 bits acpihpet0 at acpi0: 14318180 Hz acpimcfg0 at acpi0 addr 0xe0000000, bus 0-255 acpimadt0 at acpi0 addr 0xfee00000: PC-AT compat cpu0 at mainbus0: apid 0 (boot processor) cpu0: AMD Athlon(tm) 64 X2 Dual Core Processor 5600+, 2913.79 MHz cpu0: FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,MMX,FXSR,SSE,SSE2,HTT,SSE3,CX16,NXE,MMXX,FFXSR,LONG,3DNOW2,3DNOW,LAHF,CMPLEG,SVM,EAPICSP,AMCR8,3DNOWP cpu0: 64KB 64b/line 2-way I-cache, 64KB 64b/line 2-way D-cache, 512KB 64b/line 16-way L2 cache cpu0: ITLB 32 4KB entries fully associative, 8 4MB entries fully associative cpu0: DTLB 32 4KB entries fully associative, 8 4MB entries fully associative cpu0: apic clock running at 200MHz cpu at mainbus0: not configured ioapic0 at mainbus0: apid 2 pa 0xfec00000, version 21, 24 pins ioapic0: misconfigured as apic 0, remapped to apid 2 acpiprt0 at acpi0: bus 0 (PCI0) acpiprt1 at acpi0: bus 3 (P2P_) acpiprt2 at acpi0: bus -1 (PCE2) acpiprt3 at acpi0: bus -1 (PCE3) acpiprt4 at acpi0: bus -1 (PCE4) acpiprt5 at acpi0: bus -1 (PCE5) acpiprt6 at acpi0: bus -1 (PCE6) acpiprt7 at acpi0: bus -1 (PCE7) acpiprt8 at acpi0: bus -1 (PCE9) acpiprt9 at acpi0: bus 2 (PCEA) acpiprt10 at acpi0: bus -1 (PCEB) acpiprt11 at acpi0: bus -1 (PCEC) acpiprt12 at acpi0: bus 1 (AGP_) acpicpu0 at acpi0: PSS acpibtn0 at acpi0: PWRB cpu0: PowerNow! K8 2913 MHz: speeds: 2900 2800 2600 2400 2200 2000 1800 1000 MHz pci0 at mainbus0 bus 0 mem address conflict 0xe0000000/0x20000000 pchb0 at pci0 dev 0 function 0 "AMD RS780 Host" rev 0x00 ppb0 at pci0 dev 1 function 0 "AMD RS780 PCIE" rev 0x00 pci1 at ppb0 bus 1 vga1 at pci1 dev 5 function 0 "ATI Radeon HD 3300" rev 0x00 wsdisplay0 at vga1 mux 1: console (80x25, vt100 emulation) wsdisplay0: screen 1-5 added (80x25, vt100 emulation) radeondrm0 at vga1: apic 2 int 18 drm0 at radeondrm0 azalia0 at pci1 dev 5 function 1 "ATI RS780 HD Audio" rev 0x00: msi azalia0: no supported codecs ppb1 at pci0 dev 10 function 0 "AMD RS780 PCIE" rev 0x00: msi pci2 at ppb1 bus 2 re0 at pci2 dev 0 function 0 "Realtek 8168" rev 0x02: RTL8168C/8111C (0x3c00), apic 2 int 18, address 00:24:1d:19:01:0d rgephy0 at re0 phy 7: RTL8169S/8110S PHY, rev. 2 ahci0 at pci0 dev 17 function 0 "ATI SBx00 SATA" rev 0x00: apic 2 int 22, AHCI 1.1 scsibus0 at ahci0: 32 targets cd0 at scsibus0 targ 0 lun 0: <TSSTcorp, CDDVDW SH-S203B, SB03> ATAPI 5/cdrom removable sd0 at scsibus0 targ 2 lun 0: <ATA, STT_FTM16GL25V, 2030> SCSI3 0/direct fixed t10.ATA_STT_FTM16GL25V_I649324-MJBY-910A017 sd0: 15271MB, 512 bytes/sector, 31275119 sectors, thin sd1 at scsibus0 targ 3 lun 0: <ATA, WDC WD10EACS-00Z, 01.0> SCSI3 0/direct fixed naa.50014ee20162c2fe sd1: 953869MB, 512 bytes/sector, 1953525168 sectors sd2 at scsibus0 targ 4 lun 0: <ATA, Hitachi HDT72101, ST6O> SCSI3 0/direct fixed naa.5000cca349d9d845 sd2: 953869MB, 512 bytes/sector, 1953525168 sectors sd3 at scsibus0 targ 5 lun 0: <ATA, Hitachi HDT72101, ST6O> SCSI3 0/direct fixed naa.5000cca35ec7d00b sd3: 953868MB, 512 bytes/sector, 1953523055 sectors ohci0 at pci0 dev 18 function 0 "ATI SB700 USB" rev 0x00: apic 2 int 16, version 1.0, legacy support ohci1 at pci0 dev 18 function 1 "ATI SB700 USB" rev 0x00: apic 2 int 16, version 1.0, legacy support ohci1: SMM does not respond, will reset ehci0 at pci0 dev 18 function 2 "ATI SB700 USB2" rev 0x00: apic 2 int 17 usb0 at ehci0: USB revision 2.0 uhub0 at usb0 "ATI EHCI root hub" rev 2.00/1.00 addr 1 ohci2 at pci0 dev 19 function 0 "ATI SB700 USB" rev 0x00: apic 2 int 18, version 1.0, legacy support ohci3 at pci0 dev 19 function 1 "ATI SB700 USB" rev 0x00: apic 2 int 18, version 1.0, legacy support ehci1 at pci0 dev 19 function 2 "ATI SB700 USB2" rev 0x00: apic 2 int 19 usb1 at ehci1: USB revision 2.0 uhub1 at usb1 "ATI EHCI root hub" rev 2.00/1.00 addr 1 piixpm0 at pci0 dev 20 function 0 "ATI SBx00 SMBus" rev 0x3a: SMI iic0 at piixpm0 spdmem0 at iic0 addr 0x50: 2GB DDR2 SDRAM non-parity PC2-6400CL5 spdmem1 at iic0 addr 0x51: 2GB DDR2 SDRAM non-parity PC2-6400CL5 pciide0 at pci0 dev 20 function 1 "ATI SB700 IDE" rev 0x00: DMA, channel 0 configured to compatibility, channel 1 configured to compatibility azalia1 at pci0 dev 20 function 2 "ATI SBx00 HD Audio" rev 0x00: apic 2 int 16 azalia1: codecs: Realtek ALC885 audio0 at azalia1 pcib0 at pci0 dev 20 function 3 "ATI SB700 ISA" rev 0x00 ppb2 at pci0 dev 20 function 4 "ATI SB600 PCI" rev 0x00 pci3 at ppb2 bus 3 ohci4 at pci0 dev 20 function 5 "ATI SB700 USB" rev 0x00: apic 2 int 18, version 1.0, legacy support pchb1 at pci0 dev 24 function 0 "AMD AMD64 0Fh HyperTransport" rev 0x00 pchb2 at pci0 dev 24 function 1 "AMD AMD64 0Fh Address Map" rev 0x00 pchb3 at pci0 dev 24 function 2 "AMD AMD64 0Fh DRAM Cfg" rev 0x00 kate0 at pci0 dev 24 function 3 "AMD AMD64 0Fh Misc Cfg" rev 0x00: core rev BH-G2 usb2 at ohci0: USB revision 1.0 uhub2 at usb2 "ATI OHCI root hub" rev 1.00/1.00 addr 1 usb3 at ohci1: USB revision 1.0 uhub3 at usb3 "ATI OHCI root hub" rev 1.00/1.00 addr 1 usb4 at ohci2: USB revision 1.0 uhub4 at usb4 "ATI OHCI root hub" rev 1.00/1.00 addr 1 usb5 at ohci3: USB revision 1.0 uhub5 at usb5 "ATI OHCI root hub" rev 1.00/1.00 addr 1 isa0 at pcib0 isadma0 at isa0 com0 at isa0 port 0x3f8/8 irq 4: ns16550a, 16 byte fifo pckbc0 at isa0 port 0x60/5 pckbd0 at pckbc0 (kbd slot) pckbc0: using irq 1 for kbd slot wskbd0 at pckbd0: console keyboard, using wsdisplay0 pms0 at pckbc0 (aux slot) pckbc0: using irq 12 for aux slot wsmouse0 at pms0 mux 0 pcppi0 at isa0 port 0x61 spkr0 at pcppi0 it0 at isa0 port 0x2e/2: IT8718F rev 5, EC port 0x228 usb6 at ohci4: USB revision 1.0 uhub6 at usb6 "ATI OHCI root hub" rev 1.00/1.00 addr 1 mtrr: Pentium Pro MTRR support umass0 at uhub0 port 3 configuration 1 interface 0 "JMicron JM20336 SATA, USB Combo" rev 2.00/1.00 addr 2 umass0: using SCSI over Bulk-Only scsibus1 at umass0: 2 targets, initiator 0 sd4 at scsibus1 targ 1 lun 0: <ST350064, 1AS, > SCSI2 0/direct fixed serial.152d2336308888888888 sd4: 476940MB, 512 bytes/sector, 976773168 sectors vscsi0 at root scsibus2 at vscsi0: 256 targets softraid0 at root scsibus3 at softraid0: 256 targets root on sd0a (f5a51d458cf981a9.a) swap on sd0b dump on sd0b