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

Reply via email to