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;