On Mon, 11 Jul 2016, Reyk Floeter wrote:
> The intentional 4GB limit is for forwarding: what if you forward mbufs 
> from a 64bit-capable interface to another one that doesn't support 64bit 
> DMA? And even if you would only enable it if all interfaces are 
> 64bit-capable, what if you plug in a 32bit USB/hotplug interface? We did 
> not want to support bounce buffers in OpenBSD.

Yes, I have understood that. My mail was more about non-mbuf DMA: Does it 
make sense to allow 64bit DMA in other cases while keeping the 4GB 
limitation for mbufs?

Cheers,
Stefan

> 
> Reyk
> 
> > On 11.07.2016, at 15:37, Stefan Fritsch <s...@sfritsch.de> wrote:
> > 
> > Hi,
> > 
> > following the discussion about mbufs, I have some questions about 64bit 
> > DMA in general.
> > 
> > Openbsd on amd64 assumes that DMA is only possible to the lower 4GB. But 
> > there are many devices (PCIe, virtio, ...) that can do DMA to the whole 
> > memory. Is it feasible to have known good devices opt-in into 64bit DMA?
> > 
> > I have done a patch that allows virtio to do 64bit DMA. This works insofar 
> > as the queues used by the device will now be allocated above 4GB. But this 
> > is only a small amount of memory. More interesting would be bufs and 
> > mbufs.
> > 
> > 
> > For bufs, Bob added some code for copying bufs above/below 4GB. But this 
> > code only has a single flag B_DMA to denote if DMA is possible into a buf 
> > or not. Would it make sense to replace that by a mechanism that is device 
> > specific, so that we can use devices efficiently that allow 64bit DMA? 
> > Maybe a flag in the device vnode?
> > 
> > 
> > Does it make sense to commit something like the diff below (not tested 
> > much), even if it saves at most a few MB below 4GB right now?
> > 
> > Cheers,
> > Stefan
> > 
> > 
> > diff --git sys/arch/amd64/amd64/bus_dma.c sys/arch/amd64/amd64/bus_dma.c
> > index 8eaa2e7..1aba7c0 100644
> > --- sys/arch/amd64/amd64/bus_dma.c
> > +++ sys/arch/amd64/amd64/bus_dma.c
> > @@ -293,6 +293,7 @@ _bus_dmamap_load_raw(bus_dma_tag_t t, bus_dmamap_t map, 
> > bus_dma_segment_t *segs,
> > {
> >     bus_addr_t paddr, baddr, bmask, lastaddr = 0;
> >     bus_size_t plen, sgsize, mapsize;
> > +   struct uvm_constraint_range *constraint = t->_cookie;
> >     int first = 1;
> >     int i, seg = 0;
> > 
> > @@ -320,7 +321,7 @@ _bus_dmamap_load_raw(bus_dma_tag_t t, bus_dmamap_t map, 
> > bus_dma_segment_t *segs,
> >                     if (plen < sgsize)
> >                             sgsize = plen;
> > 
> > -                   if (paddr > dma_constraint.ucr_high)
> > +                   if (paddr > constraint->ucr_high)
> >                             panic("Non dma-reachable buffer at paddr 
> > %#lx(raw)",
> >                                 paddr);
> > 
> > @@ -405,15 +406,11 @@ _bus_dmamem_alloc(bus_dma_tag_t t, bus_size_t size, 
> > bus_size_t alignment,
> >     bus_size_t boundary, bus_dma_segment_t *segs, int nsegs, int *rsegs,
> >     int flags)
> > {
> > +   struct uvm_constraint_range *constraint = t->_cookie;
> > 
> > -   /*
> > -    * XXX in the presence of decent (working) iommus and bouncebuffers
> > -    * we can then fallback this allocation to a range of { 0, -1 }.
> > -    * However for now  we err on the side of caution and allocate dma
> > -    * memory under the 4gig boundary.
> > -    */
> >     return (_bus_dmamem_alloc_range(t, size, alignment, boundary,
> > -       segs, nsegs, rsegs, flags, (bus_addr_t)0, (bus_addr_t)0xffffffff));
> > +       segs, nsegs, rsegs, flags, (bus_addr_t)constraint->ucr_low,
> > +       (bus_addr_t)constraint->ucr_high));
> > }
> > 
> > /*
> > @@ -567,6 +564,7 @@ _bus_dmamap_load_buffer(bus_dma_tag_t t, bus_dmamap_t 
> > map, void *buf,
> >     bus_size_t sgsize;
> >     bus_addr_t curaddr, lastaddr, baddr, bmask;
> >     vaddr_t vaddr = (vaddr_t)buf;
> > +   struct uvm_constraint_range *constraint = t->_cookie;
> >     int seg;
> >     pmap_t pmap;
> > 
> > @@ -584,7 +582,7 @@ _bus_dmamap_load_buffer(bus_dma_tag_t t, bus_dmamap_t 
> > map, void *buf,
> >              */
> >             pmap_extract(pmap, vaddr, (paddr_t *)&curaddr);
> > 
> > -           if (curaddr > dma_constraint.ucr_high)
> > +           if (curaddr > constraint->ucr_high)
> >                     panic("Non dma-reachable buffer at curaddr %#lx(raw)",
> >                         curaddr);
> > 
> > diff --git sys/arch/amd64/amd64/machdep.c sys/arch/amd64/amd64/machdep.c
> > index de9f481..7640532 100644
> > --- sys/arch/amd64/amd64/machdep.c
> > +++ sys/arch/amd64/amd64/machdep.c
> > @@ -201,6 +201,12 @@ struct vm_map *phys_map = NULL;
> > 
> > /* UVM constraint ranges. */
> > struct uvm_constraint_range  isa_constraint = { 0x0, 0x00ffffffUL };
> > +   /*
> > +    * XXX in the presence of decent (working) iommus and bouncebuffers
> > +    * we can then fallback this allocation to a range of { 0, -1 }.
> > +    * However for now  we err on the side of caution and allocate dma
> > +    * memory under the 4gig boundary.
> > +    */
> > struct uvm_constraint_range  dma_constraint = { 0x0, 0xffffffffUL };
> > struct uvm_constraint_range *uvm_md_constraints[] = {
> >     &isa_constraint,
> > diff --git sys/arch/amd64/include/pci_machdep.h 
> > sys/arch/amd64/include/pci_machdep.h
> > index 27b833b..bf54f31 100644
> > --- sys/arch/amd64/include/pci_machdep.h
> > +++ sys/arch/amd64/include/pci_machdep.h
> > @@ -41,6 +41,7 @@
> >  */
> > 
> > extern struct bus_dma_tag pci_bus_dma_tag;
> > +extern struct bus_dma_tag virtio_pci_bus_dma_tag;
> > 
> > /*
> >  * Types provided to machine-independent PCI code
> > diff --git sys/arch/amd64/isa/isa_machdep.c sys/arch/amd64/isa/isa_machdep.c
> > index 74dc907..ec35edead 100644
> > --- sys/arch/amd64/isa/isa_machdep.c
> > +++ sys/arch/amd64/isa/isa_machdep.c
> > @@ -140,7 +140,7 @@ void    _isa_dma_free_bouncebuf(bus_dma_tag_t, 
> > bus_dmamap_t);
> >  * buffers, if necessary.
> >  */
> > struct bus_dma_tag isa_bus_dma_tag = {
> > -   NULL,                   /* _cookie */
> > +   &isa_constraint,
> >     _isa_bus_dmamap_create,
> >     _isa_bus_dmamap_destroy,
> >     _isa_bus_dmamap_load,
> > diff --git sys/arch/amd64/pci/pci_machdep.c sys/arch/amd64/pci/pci_machdep.c
> > index 19983b0..5dca63a 100644
> > --- sys/arch/amd64/pci/pci_machdep.c
> > +++ sys/arch/amd64/pci/pci_machdep.c
> > @@ -130,7 +130,7 @@ do {                                                    
> >                 \
> >  * of these functions.
> >  */
> > struct bus_dma_tag pci_bus_dma_tag = {
> > -   NULL,                   /* _may_bounce */
> > +   &dma_constraint,
> >     _bus_dmamap_create,
> >     _bus_dmamap_destroy,
> >     _bus_dmamap_load,
> > @@ -147,6 +147,25 @@ struct bus_dma_tag pci_bus_dma_tag = {
> >     _bus_dmamem_mmap,
> > };
> > 
> > +struct bus_dma_tag virtio_pci_bus_dma_tag = {
> > +   &no_constraint,
> > +   _bus_dmamap_create,
> > +   _bus_dmamap_destroy,
> > +   _bus_dmamap_load,
> > +   _bus_dmamap_load_mbuf,
> > +   _bus_dmamap_load_uio,
> > +   _bus_dmamap_load_raw,
> > +   _bus_dmamap_unload,
> > +   _bus_dmamap_sync,
> > +   _bus_dmamem_alloc,
> > +   _bus_dmamem_alloc_range,
> > +   _bus_dmamem_free,
> > +   _bus_dmamem_map,
> > +   _bus_dmamem_unmap,
> > +   _bus_dmamem_mmap,
> > +};
> > +
> > +
> > void
> > pci_attach_hook(struct device *parent, struct device *self,
> >     struct pcibus_attach_args *pba)
> > diff --git sys/arch/i386/pci/pci_machdep.h sys/arch/i386/pci/pci_machdep.h
> > index 2831470..6e6484b 100644
> > --- sys/arch/i386/pci/pci_machdep.h
> > +++ sys/arch/i386/pci/pci_machdep.h
> > @@ -56,6 +56,7 @@ union i386_pci_tag_u {
> > };
> > 
> > extern struct bus_dma_tag pci_bus_dma_tag;
> > +#define            virtio_pci_bus_dma_tag  pci_bus_dma_tag
> > 
> > /*
> >  * Types provided to machine-independent PCI code
> > diff --git sys/dev/pci/virtio_pci.c sys/dev/pci/virtio_pci.c
> > index 489a449..6c08579 100644
> > --- sys/dev/pci/virtio_pci.c
> > +++ sys/dev/pci/virtio_pci.c
> > @@ -183,7 +183,7 @@ virtio_pci_attach(struct device *parent, struct device 
> > *self, void *aux)
> > 
> >     vsc->sc_ops = &virtio_pci_ops;
> >     sc->sc_pc = pc;
> > -   vsc->sc_dmat = pa->pa_dmat;
> > +   vsc->sc_dmat = &virtio_pci_bus_dma_tag;
> >     sc->sc_config_offset = VIRTIO_CONFIG_DEVICE_CONFIG_NOMSI;
> > 
> >     if (pci_mapreg_map(pa, PCI_MAPREG_START, PCI_MAPREG_TYPE_IO, 0,
> > 
> 
> 

Reply via email to