[haiku-commits] haiku: hrev56185 - src/libs/compat/freebsd_network

  • From: waddlesplash <waddlesplash@xxxxxxxxx>
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Mon, 13 Jun 2022 19:06:35 +0000 (UTC)

hrev56185 adds 2 changesets to branch 'master'
old head: ed666fb497cde2076771bc7d0251c4306c576364
new head: 7de24641a4b997a57682d4add14469ef64aa8471
overview: 
https://git.haiku-os.org/haiku/log/?qt=range&q=7de24641a4b9+%5Eed666fb497cd

----------------------------------------------------------------------------

73603a51636c: freebsd_network: Clean up bus_dma code.
  
   * Turn lastaddrp into a reference instead of a pointer.
   * Use PAGESIZE instead of B_PAGE_SIZE for consistency.
   * Rename "nsegs" variables to "seg" as it is an offset and not a count.
  
  No functional change intended.

7de24641a4b9: freebsd_network: Adjust address validation in bus_dma code.
  
  We need not (in fact, must not) revalidate addresses if we are just
  going to coalesce with the previous segment; otherwise, we will incorrectly
  reject buffers that are more than page-aligned.
  
  Should fix #17798 and the new KDL in #14260.

                              [ Augustin Cavalier <waddlesplash@xxxxxxxxx> ]

----------------------------------------------------------------------------

1 file changed, 29 insertions(+), 33 deletions(-)
src/libs/compat/freebsd_network/bus_dma.cpp | 62 ++++++++++++-------------

############################################################################

Commit:      73603a51636c780768ba57911971bcf35f257e75
URL:         https://git.haiku-os.org/haiku/commit/?id=73603a51636c
Author:      Augustin Cavalier <waddlesplash@xxxxxxxxx>
Date:        Mon Jun 13 18:54:40 2022 UTC

freebsd_network: Clean up bus_dma code.

 * Turn lastaddrp into a reference instead of a pointer.
 * Use PAGESIZE instead of B_PAGE_SIZE for consistency.
 * Rename "nsegs" variables to "seg" as it is an offset and not a count.

No functional change intended.

----------------------------------------------------------------------------

diff --git a/src/libs/compat/freebsd_network/bus_dma.cpp 
b/src/libs/compat/freebsd_network/bus_dma.cpp
index 9ddbe05c7d..ecaedae2ff 100644
--- a/src/libs/compat/freebsd_network/bus_dma.cpp
+++ b/src/libs/compat/freebsd_network/bus_dma.cpp
@@ -332,11 +332,10 @@ _validate_address(bus_dma_tag_t dmat, bus_addr_t paddr)
 
 static int
 _bus_load_buffer(bus_dma_tag_t dmat, void* buf, bus_size_t buflen,
-       int flags, bus_addr_t* lastaddrp, bus_dma_segment_t* segs,
+       int flags, bus_addr_t& last_phys_addr, bus_dma_segment_t* segs,
        int& seg, bool first)
 {
        vm_offset_t virtual_addr = (vm_offset_t)buf;
-       bus_addr_t last_phys_addr = *lastaddrp;
        const bus_addr_t boundary_mask = ~(dmat->boundary - 1);
 
        while (buflen > 0) {
@@ -344,7 +343,7 @@ _bus_load_buffer(bus_dma_tag_t dmat, void* buf, bus_size_t 
buflen,
                if (!_validate_address(dmat, phys_addr))
                        return ERANGE;
 
-               bus_size_t segment_size = B_PAGE_SIZE - (phys_addr & PAGE_MASK);
+               bus_size_t segment_size = PAGESIZE - (phys_addr & PAGE_MASK);
                if (segment_size > buflen)
                        segment_size = buflen;
                if (segment_size > dmat->maxsegsz)
@@ -383,7 +382,6 @@ _bus_load_buffer(bus_dma_tag_t dmat, void* buf, bus_size_t 
buflen,
                buflen -= segment_size;
        }
 
-       *lastaddrp = last_phys_addr;
        return (buflen != 0 ? EFBIG : 0);
 }
 
@@ -394,13 +392,13 @@ bus_dmamap_load(bus_dma_tag_t dmat, bus_dmamap_t map, 
void *buf,
        void *callback_arg, int flags)
 {
        bus_addr_t lastaddr = 0;
-       int error, nsegs = 0;
+       int error, seg = 0;
 
        if (buflen > dmat->maxsize)
                return EINVAL;
 
        error = _bus_load_buffer(dmat, buf, buflen, flags,
-               &lastaddr, map->segments, nsegs, true);
+               lastaddr, map->segments, seg, true);
 
        if (error != 0) {
                // Try again using a bounce buffer.
@@ -412,15 +410,15 @@ bus_dmamap_load(bus_dma_tag_t dmat, bus_dmamap_t map, 
void *buf,
                map->buffer = buf;
                map->buffer_length = buflen;
 
-               nsegs = lastaddr = 0;
+               seg = lastaddr = 0;
                error = _bus_load_buffer(dmat, map->bounce_buffer, buflen, 
flags,
-                       &lastaddr, map->segments, nsegs, true);
+                       lastaddr, map->segments, seg, true);
        }
 
        if (error)
                (*callback)(callback_arg, map->segments, 0, error);
        else
-               (*callback)(callback_arg, map->segments, nsegs + 1, 0);
+               (*callback)(callback_arg, map->segments, seg + 1, 0);
 
        // ENOMEM is returned; all other errors are only sent to the callback.
        if (error == ENOMEM)
@@ -438,7 +436,7 @@ bus_dmamap_load_mbuf_sg(bus_dma_tag_t dmat, bus_dmamap_t 
map, struct mbuf* mb,
        if (mb->m_pkthdr.len > dmat->maxsize)
                return EINVAL;
 
-       int nsegs = 0, error = 0;
+       int seg = 0, error = 0;
        bool first = true;
        bus_addr_t lastaddr = 0;
        flags |= BUS_DMA_NOWAIT;
@@ -448,7 +446,7 @@ bus_dmamap_load_mbuf_sg(bus_dma_tag_t dmat, bus_dmamap_t 
map, struct mbuf* mb,
                        continue;
 
                error = _bus_load_buffer(dmat, m->m_data, m->m_len,
-                       flags, &lastaddr, segs, nsegs, first);
+                       flags, lastaddr, segs, seg, first);
                first = false;
        }
 
@@ -461,12 +459,12 @@ bus_dmamap_load_mbuf_sg(bus_dma_tag_t dmat, bus_dmamap_t 
map, struct mbuf* mb,
                map->buffer_type = bus_dmamap::BUFFER_TYPE_MBUF;
                map->mbuf = mb;
 
-               nsegs = lastaddr = 0;
+               seg = lastaddr = 0;
                error = _bus_load_buffer(dmat, map->bounce_buffer, 
mb->m_pkthdr.len, flags,
-                       &lastaddr, segs, nsegs, true);
+                       lastaddr, segs, seg, true);
        }
 
-       *_nsegs = nsegs + 1;
+       *_nsegs = seg + 1;
        return error;
 }
 

############################################################################

Revision:    hrev56185
Commit:      7de24641a4b997a57682d4add14469ef64aa8471
URL:         https://git.haiku-os.org/haiku/commit/?id=7de24641a4b9
Author:      Augustin Cavalier <waddlesplash@xxxxxxxxx>
Date:        Mon Jun 13 19:05:25 2022 UTC

Ticket:      https://dev.haiku-os.org/ticket/14260
Ticket:      https://dev.haiku-os.org/ticket/17798

freebsd_network: Adjust address validation in bus_dma code.

We need not (in fact, must not) revalidate addresses if we are just
going to coalesce with the previous segment; otherwise, we will incorrectly
reject buffers that are more than page-aligned.

Should fix #17798 and the new KDL in #14260.

----------------------------------------------------------------------------

diff --git a/src/libs/compat/freebsd_network/bus_dma.cpp 
b/src/libs/compat/freebsd_network/bus_dma.cpp
index ecaedae2ff..d11faddcf2 100644
--- a/src/libs/compat/freebsd_network/bus_dma.cpp
+++ b/src/libs/compat/freebsd_network/bus_dma.cpp
@@ -340,8 +340,6 @@ _bus_load_buffer(bus_dma_tag_t dmat, void* buf, bus_size_t 
buflen,
 
        while (buflen > 0) {
                const bus_addr_t phys_addr = pmap_kextract(virtual_addr);
-               if (!_validate_address(dmat, phys_addr))
-                       return ERANGE;
 
                bus_size_t segment_size = PAGESIZE - (phys_addr & PAGE_MASK);
                if (segment_size > buflen)
@@ -356,25 +354,25 @@ _bus_load_buffer(bus_dma_tag_t dmat, void* buf, 
bus_size_t buflen,
                                segment_size = (boundary_addr - phys_addr);
                }
 
-               // Insert chunk into a segment.
-               if (first) {
+               // If possible, coalesce into the previous segment.
+               if (!first && phys_addr == last_phys_addr
+                               && (segs[seg].ds_len + segment_size) <= 
dmat->maxsegsz
+                               && (dmat->boundary == 0
+                                       || (segs[seg].ds_addr & boundary_mask)
+                                               == (phys_addr & 
boundary_mask))) {
+                       // No need to validate the address here.
+                       segs[seg].ds_len += segment_size;
+               } else {
+                       if (first)
+                               first = false;
+                       else if (++seg >= dmat->maxsegments)
+                               break;
+
+                       if (!_validate_address(dmat, phys_addr))
+                               return ERANGE;
+
                        segs[seg].ds_addr = phys_addr;
                        segs[seg].ds_len = segment_size;
-                       first = false;
-               } else {
-                       // If possible, coalesce into the previous segment.
-                       if (phys_addr == last_phys_addr
-                               && (segs[seg].ds_len + segment_size) <= 
dmat->maxsegsz
-                                       && (dmat->boundary == 0
-                                               || (segs[seg].ds_addr & 
boundary_mask)
-                                                       == (phys_addr & 
boundary_mask))) {
-                               segs[seg].ds_len += segment_size;
-                       } else {
-                               if (++seg >= dmat->maxsegments)
-                                       break;
-                               segs[seg].ds_addr = phys_addr;
-                               segs[seg].ds_len = segment_size;
-                       }
                }
 
                last_phys_addr = phys_addr + segment_size;


Other related posts:

  • » [haiku-commits] haiku: hrev56185 - src/libs/compat/freebsd_network - waddlesplash