[haiku-commits] haiku: hrev56149 - in src/libs/compat/freebsd_network: . compat/vm compat/sys

  • From: waddlesplash <waddlesplash@xxxxxxxxx>
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Fri, 3 Jun 2022 01:13:31 +0000 (UTC)

hrev56149 adds 1 changeset to branch 'master'
old head: 6ba3c443a20def06bb8dda5807d184f4a83066ad
new head: d66ceb73f8a0193209ac8b709454e8bca400fd32
overview: 
https://git.haiku-os.org/haiku/log/?qt=range&q=d66ceb73f8a0+%5E6ba3c443a20d

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

d66ceb73f8a0: freebsd_network: Implement bouncing and address validation in 
bus_dma.
  
  This has been missing since the rewrite in 
26b95c15f255904694ce8224b6f21f0b931a9cff.
  
  Until now it seems to not have been a problem since buffer sizes
  were generally small enough and did not cross page boundaries due
  to alignment guarantees. However, now that we have enabled jumbo
  frames by default, some drivers do hit DMA limits without bouncing,
  as these frames cross pages.
  
  So, now we implement a basic bouncing system. Unlike FreeBSD which
  maintains a global "bounce pages" cache that it pulls from,
  we use per-dmamap bounce buffers, lazily allocated only if needed.
  I tested this by forcing all non-"prohibited" dmamaps to bounce all
  transactions, and the rtl81xx driver still worked that way (though
  not all drivers may as they have expectations about contiguously
  allocated memory never getting bounced.)
  
  This should fix #17763. Hopefully it will also fix #17766 as well.

                              [ Augustin Cavalier <waddlesplash@xxxxxxxxx> ]

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

Revision:    hrev56149
Commit:      d66ceb73f8a0193209ac8b709454e8bca400fd32
URL:         https://git.haiku-os.org/haiku/commit/?id=d66ceb73f8a0
Author:      Augustin Cavalier <waddlesplash@xxxxxxxxx>
Date:        Fri Jun  3 01:08:26 2022 UTC

Ticket:      https://dev.haiku-os.org/ticket/17763
Ticket:      https://dev.haiku-os.org/ticket/17766

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

4 files changed, 334 insertions(+), 106 deletions(-)
src/libs/compat/freebsd_network/bus_dma.cpp      | 338 ++++++++++++++-----
.../compat/freebsd_network/compat/sys/bus_dma.h  |  30 +-
.../compat/freebsd_network/compat/vm/vm_extern.h |  69 ++++
src/libs/compat/freebsd_network/malloc.cpp       |   3 +

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

diff --git a/src/libs/compat/freebsd_network/bus_dma.cpp 
b/src/libs/compat/freebsd_network/bus_dma.cpp
index 2359cf1523..426179733d 100644
--- a/src/libs/compat/freebsd_network/bus_dma.cpp
+++ b/src/libs/compat/freebsd_network/bus_dma.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright 2019, Haiku, Inc. All rights reserved.
+ * Copyright 2019-2022, Haiku, Inc. All rights reserved.
  * Distributed under the terms of the MIT License.
  *
  * Authors:
@@ -14,25 +14,59 @@ extern "C" {
 #include <sys/mbuf.h>
 
 #include <machine/bus.h>
+#include <vm/vm_extern.h>
 }
 
+#include <vm/vm_page.h>
+
 
 // #pragma mark - structures
 
 
 struct bus_dma_tag {
        bus_dma_tag_t   parent;
+       int32                   ref_count;
+       int32                   map_count;
+
+       int                             flags;
+#define BUS_DMA_COULD_BOUNCE   BUS_DMA_BUS1
+
        phys_size_t             alignment;
        phys_addr_t             boundary;
        phys_addr_t             lowaddr;
        phys_addr_t             highaddr;
+
        bus_dma_filter_t* filter;
        void*                   filterarg;
+
        phys_size_t             maxsize;
        uint32                  maxsegments;
-       bus_dma_segment_t* segments;
        phys_size_t             maxsegsz;
-       int32                   ref_count;
+};
+
+struct bus_dmamap {
+       bus_dma_tag_t           dmat;
+
+       bus_dma_segment_t*      segments;
+       int                                     nsegs;
+
+       void*           bounce_buffer;
+       bus_size_t      bounce_buffer_size;
+
+       enum {
+               BUFFER_NONE = 0,
+               BUFFER_PROHIBITED,
+
+               BUFFER_TYPE_SIMPLE,
+               BUFFER_TYPE_MBUF,
+       } buffer_type;
+       union {
+               struct {
+                       void*                           buffer;
+                       bus_size_t                      buffer_length;
+               };
+               struct mbuf*            mbuf;
+       };
 };
 
 
@@ -82,7 +116,11 @@ bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t 
alignment, bus_size_t bounda
        newtag->maxsize = maxsize;
        newtag->maxsegments = nsegments;
        newtag->maxsegsz = maxsegsz;
+       newtag->flags = flags;
        newtag->ref_count = 1;
+       newtag->map_count = 0;
+
+       // lockfunc is only needed if callbacks will be invoked asynchronously.
 
        if (newtag->parent != NULL) {
                atomic_add(&parent->ref_count, 1);
@@ -102,8 +140,10 @@ bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t 
alignment, bus_size_t bounda
                }
        }
 
-       if (newtag->filter != NULL)
-               panic("bus_dma_tag_create: error: filters not implemented!");
+       if (newtag->lowaddr < vm_page_max_address())
+               newtag->flags |= BUS_DMA_COULD_BOUNCE;
+       if (newtag->alignment > 1)
+               newtag->flags |= BUS_DMA_COULD_BOUNCE;
 
        *dmat = newtag;
        return 0;
@@ -115,6 +155,8 @@ bus_dma_tag_destroy(bus_dma_tag_t dmat)
 {
        if (dmat == NULL)
                return 0;
+       if (dmat->map_count != 0)
+               return EBUSY;
 
        while (dmat != NULL) {
                bus_dma_tag_t parent;
@@ -122,7 +164,6 @@ bus_dma_tag_destroy(bus_dma_tag_t dmat)
                parent = dmat->parent;
                atomic_add(&dmat->ref_count, -1);
                if (dmat->ref_count == 0) {
-                       kernel_free(dmat->segments, M_DEVBUF);
                        kernel_free(dmat, M_DEVBUF);
 
                        // Last reference released, so release our reference on 
our parent.
@@ -137,8 +178,52 @@ bus_dma_tag_destroy(bus_dma_tag_t dmat)
 int
 bus_dmamap_create(bus_dma_tag_t dmat, int flags, bus_dmamap_t* mapp)
 {
-       // We never bounce, so we do not need maps.
-       *mapp = NULL;
+       *mapp = (bus_dmamap_t)calloc(sizeof(**mapp), 1);
+       if (*mapp == NULL)
+               return ENOMEM;
+
+       (*mapp)->dmat = dmat;
+       (*mapp)->nsegs = 0;
+       (*mapp)->segments = (bus_dma_segment_t *)calloc(dmat->maxsegments,
+               sizeof(bus_dma_segment_t));
+       if ((*mapp)->segments == NULL) {
+               free((*mapp));
+               *mapp = NULL;
+               return ENOMEM;
+       }
+
+       atomic_add(&dmat->map_count, 1);
+       return 0;
+}
+
+
+static int
+_prepare_bounce_buffer(bus_dmamap_t map, bus_size_t reqsize, int flags)
+{
+       if (map->buffer_type == bus_dmamap::BUFFER_PROHIBITED) {
+               panic("cannot bounce, direct DMA only!");
+               return B_NOT_ALLOWED;
+       }
+       if (map->buffer_type != bus_dmamap::BUFFER_NONE) {
+               panic("bounce buffer already in use!");
+               return EBUSY;
+       }
+
+       if (map->bounce_buffer_size >= reqsize)
+               return 0;
+
+       if (map->bounce_buffer != NULL) {
+               kernel_contigfree(map->bounce_buffer, map->bounce_buffer_size, 
0);
+               map->bounce_buffer = NULL;
+       }
+
+       bus_dmamap_t extraMap;
+       int error = bus_dmamem_alloc(map->dmat, &map->bounce_buffer, flags, 
&extraMap);
+       if (error != 0)
+               return error; // TODO: retry with a smaller size?
+       map->bounce_buffer_size = map->dmat->maxsize;
+       bus_dmamap_destroy(map->dmat, extraMap);
+
        return 0;
 }
 
@@ -146,9 +231,15 @@ bus_dmamap_create(bus_dma_tag_t dmat, int flags, 
bus_dmamap_t* mapp)
 int
 bus_dmamap_destroy(bus_dma_tag_t dmat, bus_dmamap_t map)
 {
-       // We never create maps, so we never need to destroy them.
-       if (map)
-               panic("map is not NULL!");
+       if (map == NULL)
+               return 0;
+       if (map->buffer_type != bus_dmamap::BUFFER_NONE)
+               return EBUSY;
+
+       atomic_add(&map->dmat->map_count, -1);
+       kernel_contigfree(map->bounce_buffer, map->bounce_buffer_size, 
M_DEVBUF);
+       free(map->segments);
+       free(map);
        return 0;
 }
 
@@ -166,19 +257,19 @@ bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int 
flags,
        if (flags & BUS_DMA_ZERO)
                mflags |= M_ZERO;
 
-       // We never need to map/bounce.
-       *mapp = NULL;
+       bus_dmamap_create(dmat, flags, mapp);
+
+       // Drivers assume dmamem will never be bounced, so ensure that.
+       (*mapp)->buffer_type = bus_dmamap::BUFFER_PROHIBITED;
 
        // FreeBSD uses standard malloc() for the case where maxsize <= 
PAGE_SIZE,
-       // however, our malloc() has no guarantees that the allocated memory 
will
-       // not be swapped out, which obviously is a requirement here. So we must
-       // always use kernel_contigmalloc().
+       // but we want to keep DMA'd memory a bit more separate, so we always 
use
+       // contigmalloc.
 
        // The range specified by lowaddr, highaddr is an *exclusion* range,
        // not an inclusion range. So we want to at least start with the low 
end,
-       // if possible. (The most common exclusion range is 32-bit only,
-       // and ones other than that are very rare, so typically this will
-       // succeed.)
+       // if possible. (The most common exclusion range is 32-bit only, and
+       // ones other than that are very rare, so typically this will succeed.)
        if (dmat->lowaddr > B_PAGE_SIZE) {
                *vaddr = kernel_contigmalloc(dmat->maxsize, M_DEVBUF, mflags,
                        0, dmat->lowaddr,
@@ -212,25 +303,48 @@ bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int 
flags,
 void
 bus_dmamem_free(bus_dma_tag_t dmat, void* vaddr, bus_dmamap_t map)
 {
-       // We never bounce, so map should be NULL.
-       if (map != NULL)
-               panic("bus_dmamem_free: map is not NULL!");
-
        kernel_contigfree(vaddr, dmat->maxsize, M_DEVBUF);
+       bus_dmamap_destroy(dmat, map);
+}
+
+
+static bool
+_validate_address(bus_dma_tag_t dmat, bus_addr_t paddr)
+{
+       do {
+               if (dmat->filter != NULL) {
+                       if ((*dmat->filter)(dmat->filterarg, paddr) != 0)
+                               return false;
+               } else {
+                       if (paddr > dmat->lowaddr && paddr <= dmat->highaddr)
+                               return false;
+                       if (!vm_addr_align_ok(paddr, dmat->alignment))
+                               return false;
+               }
+
+               dmat = dmat->parent;
+       } while (dmat != NULL);
+
+       return true;
 }
 
 
 static int
-_bus_dmamap_load_buffer(bus_dma_tag_t dmat, bus_dmamap_t /* map */, void* buf,
-       bus_size_t buflen, int flags, bus_addr_t* lastaddrp, bus_dma_segment_t* 
segs,
+_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& 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);
 
+       if (buflen > dmat->maxsize)
+               return EINVAL;
+
        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 = B_PAGE_SIZE - (phys_addr & PAGE_MASK);
                if (segment_size > buflen)
@@ -284,21 +398,27 @@ bus_dmamap_load(bus_dma_tag_t dmat, bus_dmamap_t map, 
void *buf,
        bus_addr_t lastaddr = 0;
        int error, nsegs = 0;
 
-       if (dmat->segments == NULL) {
-               dmat->segments = (bus_dma_segment_t*)kernel_malloc(
-                       sizeof(bus_dma_segment_t) * dmat->maxsegments, M_DEVBUF,
-                       M_ZERO | M_NOWAIT);
-               if (dmat->segments == NULL)
-                       return ENOMEM;
-       }
+       error = _bus_load_buffer(dmat, buf, buflen, flags,
+               &lastaddr, map->segments, nsegs, true);
+
+       if (error == ERANGE) {
+               // Try again using a bounce buffer.
+               error = _prepare_bounce_buffer(map, buflen, flags);
+               if (error != 0)
+                       return error;
+
+               map->buffer_type = bus_dmamap::BUFFER_TYPE_SIMPLE;
+               map->buffer = buf;
 
-       error = _bus_dmamap_load_buffer(dmat, map, buf, buflen, flags,
-               &lastaddr, dmat->segments, nsegs, true);
+               nsegs = lastaddr = 0;
+               error = _bus_load_buffer(dmat, map->bounce_buffer, buflen, 
flags,
+                       &lastaddr, map->segments, nsegs, true);
+       }
 
        if (error)
-               (*callback)(callback_arg, dmat->segments, 0, error);
+               (*callback)(callback_arg, map->segments, 0, error);
        else
-               (*callback)(callback_arg, dmat->segments, nsegs + 1, 0);
+               (*callback)(callback_arg, map->segments, nsegs + 1, 0);
 
        // ENOMEM is returned; all other errors are only sent to the callback.
        if (error == ENOMEM)
@@ -308,83 +428,127 @@ bus_dmamap_load(bus_dma_tag_t dmat, bus_dmamap_t map, 
void *buf,
 
 
 int
-bus_dmamap_load_mbuf(bus_dma_tag_t dmat, bus_dmamap_t map, struct mbuf* mb,
-       bus_dmamap_callback2_t* callback, void* callback_arg, int flags)
+bus_dmamap_load_mbuf_sg(bus_dma_tag_t dmat, bus_dmamap_t map, struct mbuf* mb,
+       bus_dma_segment_t* segs, int* _nsegs, int flags)
 {
        M_ASSERTPKTHDR(mb);
 
-       if (dmat->segments == NULL) {
-               dmat->segments = (bus_dma_segment_t*)kernel_malloc(
-                       sizeof(bus_dma_segment_t) * dmat->maxsegments, M_DEVBUF,
-                       M_ZERO | M_NOWAIT);
-               if (dmat->segments == NULL)
-                       return ENOMEM;
-       }
+       if (mb->m_pkthdr.len > dmat->maxsize)
+               return EINVAL;
 
        int nsegs = 0, error = 0;
-       if (mb->m_pkthdr.len <= dmat->maxsize) {
-               bool first = true;
-               bus_addr_t lastaddr = 0;
-               for (struct mbuf* m = mb; m != NULL && error == 0; m = 
m->m_next) {
-                       if (m->m_len <= 0)
-                               continue;
-
-                       error = _bus_dmamap_load_buffer(dmat, map, m->m_data, 
m->m_len,
-                               flags, &lastaddr, dmat->segments, nsegs, first);
-                       first = false;
-               }
-       } else {
-               error = EINVAL;
+       bool first = true;
+       bus_addr_t lastaddr = 0;
+
+       for (struct mbuf* m = mb; m != NULL && error == 0; m = m->m_next) {
+               if (m->m_len <= 0)
+                       continue;
+
+               error = _bus_load_buffer(dmat, m->m_data, m->m_len,
+                       flags, &lastaddr, segs, nsegs, first);
+               first = false;
        }
 
-       if (error) {
-               (*callback)(callback_arg, dmat->segments, 0, 0, error);
-       } else {
-               (*callback)(callback_arg, dmat->segments, nsegs + 1, 
mb->m_pkthdr.len,
-                       error);
+       if (error == ERANGE) {
+               // Try again using a bounce buffer.
+               error = _prepare_bounce_buffer(map, mb->m_pkthdr.len, flags);
+               if (error != 0)
+                       return error;
+
+               map->buffer_type = bus_dmamap::BUFFER_TYPE_MBUF;
+               map->mbuf = mb;
+
+               nsegs = lastaddr = 0;
+               error = _bus_load_buffer(dmat, map->bounce_buffer, 
mb->m_pkthdr.len, flags,
+                       &lastaddr, segs, nsegs, true);
        }
+
+       *_nsegs = nsegs + 1;
        return error;
 }
 
 
 int
-bus_dmamap_load_mbuf_sg(bus_dma_tag_t dmat, bus_dmamap_t map, struct mbuf* mb,
-       bus_dma_segment_t* segs, int* nsegs, int flags)
+bus_dmamap_load_mbuf(bus_dma_tag_t dmat, bus_dmamap_t map, struct mbuf* mb,
+       bus_dmamap_callback2_t* callback, void* callback_arg, int flags)
 {
-       M_ASSERTPKTHDR(mb);
+       int nsegs, error;
+       error = bus_dmamap_load_mbuf_sg(dmat, map, mb, map->segments, &nsegs, 
flags);
 
-       *nsegs = 0;
-       int error = 0;
-       if (mb->m_pkthdr.len <= dmat->maxsize) {
-               bool first = true;
-               bus_addr_t lastaddr = 0;
-
-               for (struct mbuf* m = mb; m != NULL && error == 0; m = 
m->m_next) {
-                       if (m->m_len <= 0)
-                               continue;
-
-                       error = _bus_dmamap_load_buffer(dmat, map, m->m_data, 
m->m_len,
-                               flags, &lastaddr, segs, *nsegs, first);
-                       first = false;
-               }
+       if (error) {
+               (*callback)(callback_arg, map->segments, 0, 0, error);
        } else {
-               error = EINVAL;
+               (*callback)(callback_arg, map->segments, nsegs, 
mb->m_pkthdr.len,
+                       error);
        }
-
-       ++*nsegs;
        return error;
 }
 
 
 void
-_bus_dmamap_unload(bus_dma_tag_t dmat, bus_dmamap_t map)
+bus_dmamap_unload(bus_dma_tag_t dmat, bus_dmamap_t map)
 {
-       // We never allocate bounce pages; nothing to do.
+       if (map == NULL)
+               return;
+
+       map->buffer_type = bus_dmamap::BUFFER_NONE;
+       map->buffer = NULL;
 }
 
 
 void
-_bus_dmamap_sync(bus_dma_tag_t, bus_dmamap_t, bus_dmasync_op_t)
+bus_dmamap_sync(bus_dma_tag_t dmat, bus_dmamap_t map, bus_dmasync_op_t op)
 {
-       // We never bounce; nothing to do.
+       if (map == NULL)
+               return;
+
+       if ((op & BUS_DMASYNC_PREWRITE) != 0) {
+               // "Pre-write": after CPU writes, before device reads.
+               switch (map->buffer_type) {
+                       case bus_dmamap::BUFFER_NONE:
+                       case bus_dmamap::BUFFER_PROHIBITED:
+                               // Nothing to do.
+                               break;
+
+                       case bus_dmamap::BUFFER_TYPE_SIMPLE:
+                               memcpy(map->bounce_buffer,
+                                       map->buffer, map->buffer_length);
+                               break;
+
+                       case bus_dmamap::BUFFER_TYPE_MBUF:
+                               m_copydata(map->mbuf, 0, 
map->mbuf->m_pkthdr.len,
+                                       (caddr_t)map->bounce_buffer);
+                               break;
+
+                       default:
+                               panic("unknown buffer type");
+               }
+
+               memory_write_barrier();
+       }
+
+       if ((op & BUS_DMASYNC_POSTREAD) != 0) {
+               // "Post-read": after device writes, before CPU reads.
+               memory_read_barrier();
+
+               switch (map->buffer_type) {
+                       case bus_dmamap::BUFFER_NONE:
+                       case bus_dmamap::BUFFER_PROHIBITED:
+                               // Nothing to do.
+                               break;
+
+                       case bus_dmamap::BUFFER_TYPE_SIMPLE:
+                               memcpy(map->buffer,
+                                       map->bounce_buffer, map->buffer_length);
+                               break;
+
+                       case bus_dmamap::BUFFER_TYPE_MBUF:
+                               m_copyback(map->mbuf, 0, 
map->mbuf->m_pkthdr.len,
+                                       (caddr_t)map->bounce_buffer);
+                               break;
+
+                       default:
+                               panic("unknown buffer type");
+               }
+       }
 }
diff --git a/src/libs/compat/freebsd_network/compat/sys/bus_dma.h 
b/src/libs/compat/freebsd_network/compat/sys/bus_dma.h
index d24753ac23..90b5dfecfc 100644
--- a/src/libs/compat/freebsd_network/compat/sys/bus_dma.h
+++ b/src/libs/compat/freebsd_network/compat/sys/bus_dma.h
@@ -100,8 +100,9 @@
  * architectures
  */
 #define        BUS_DMA_NOWRITE         0x100
+#ifndef __HAIKU__
 #define        BUS_DMA_NOCACHE         0x200
-#define        BUS_DMA_ISA             0x400   /* map memory for AXP ISA dma */
+#endif
 
 /* Forwards needed by prototypes below. */
 struct mbuf;
@@ -163,11 +164,11 @@ void busdma_lock_mutex(void *arg, bus_dma_lock_op_t op);
  */
 /* XXX Should probably allow specification of alignment */
 int bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t alignment,
-                      bus_size_t boundary, bus_addr_t lowaddr,
-                      bus_addr_t highaddr, bus_dma_filter_t *filtfunc,
-                      void *filtfuncarg, bus_size_t maxsize, int nsegments,
-                      bus_size_t maxsegsz, int flags, bus_dma_lock_t *lockfunc,
-                      void *lockfuncarg, bus_dma_tag_t *dmat);
+                          bus_addr_t boundary, bus_addr_t lowaddr,
+                          bus_addr_t highaddr, bus_dma_filter_t *filtfunc,
+                          void *filtfuncarg, bus_size_t maxsize, int nsegments,
+                          bus_size_t maxsegsz, int flags, bus_dma_lock_t 
*lockfunc,
+                          void *lockfuncarg, bus_dma_tag_t *dmat);
 
 int bus_dma_tag_destroy(bus_dma_tag_t dmat);
 
@@ -240,24 +241,15 @@ int bus_dmamap_load_uio(bus_dma_tag_t dmat, bus_dmamap_t 
map,
                        int flags);
 
 /*
- * Perform a synchronization operation on the given map.
+ * Perform a synchronization operation on the given map. If the map
+ * is NULL we have a fully IO-coherent system.
  */
-void _bus_dmamap_sync(bus_dma_tag_t, bus_dmamap_t, bus_dmasync_op_t);
-#define bus_dmamap_sync(dmat, dmamap, op)                      \
-       do {                                                    \
-               if ((dmamap) != NULL)                           \
-                       _bus_dmamap_sync(dmat, dmamap, op);     \
-       } while (0)
+void bus_dmamap_sync(bus_dma_tag_t dmat, bus_dmamap_t dmamap, bus_dmasync_op_t 
op);
 
 /*
  * Release the mapping held by map.
  */
-void _bus_dmamap_unload(bus_dma_tag_t dmat, bus_dmamap_t map);
-#define bus_dmamap_unload(dmat, dmamap)                        \
-       do {                                                    \
-               if ((dmamap) != NULL)                           \
-                       _bus_dmamap_unload(dmat, dmamap);       \
-       } while (0)
+void bus_dmamap_unload(bus_dma_tag_t dmat, bus_dmamap_t dmamap);
 
 
 #endif /* _BUS_DMA_H_ */
diff --git a/src/libs/compat/freebsd_network/compat/vm/vm_extern.h 
b/src/libs/compat/freebsd_network/compat/vm/vm_extern.h
new file mode 100644
index 0000000000..4e8ce0dbcb
--- /dev/null
+++ b/src/libs/compat/freebsd_network/compat/vm/vm_extern.h
@@ -0,0 +1,69 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)vm_extern.h 8.2 (Berkeley) 1/12/94
+ * $FreeBSD$
+ */
+
+#ifndef _VM_EXTERN_H_
+#define        _VM_EXTERN_H_
+
+/*
+ * Is pa a multiple of alignment, which is a power-of-two?
+ */
+static inline bool
+vm_addr_align_ok(vm_paddr_t pa, u_long alignment)
+{
+       KASSERT(powerof2(alignment), ("%s: alignment is not a power of 2: %#lx",
+               __func__, alignment));
+       return ((pa & (alignment - 1)) == 0);
+}
+
+/*
+ * Do the first and last addresses of a range match in all bits except the ones
+ * in -boundary (a power-of-two)?  For boundary == 0, all addresses match.
+ */
+static inline bool
+vm_addr_bound_ok(vm_paddr_t pa, vm_paddr_t size, vm_paddr_t boundary)
+{
+       KASSERT(powerof2(boundary), ("%s: boundary is not a power of 2: %#jx",
+               __func__, (uintmax_t)boundary));
+       return (((pa ^ (pa + size - 1)) & -boundary) == 0);
+}
+
+static inline bool
+vm_addr_ok(vm_paddr_t pa, vm_paddr_t size, u_long alignment,
+       vm_paddr_t boundary)
+{
+       return (vm_addr_align_ok(pa, alignment) &&
+               vm_addr_bound_ok(pa, size, boundary));
+}
+
+#endif                         /* !_VM_EXTERN_H_ */
diff --git a/src/libs/compat/freebsd_network/malloc.cpp 
b/src/libs/compat/freebsd_network/malloc.cpp
index a06c42c4da..c64deeee5d 100644
--- a/src/libs/compat/freebsd_network/malloc.cpp
+++ b/src/libs/compat/freebsd_network/malloc.cpp
@@ -83,6 +83,9 @@ _kernel_contigmalloc(const char *file, int line, size_t size, 
int flags,
 void
 _kernel_contigfree(void *addr, size_t size)
 {
+       if (addr == NULL)
+               return;
+
        delete_area(area_for(addr));
 }
 


Other related posts:

  • » [haiku-commits] haiku: hrev56149 - in src/libs/compat/freebsd_network: . compat/vm compat/sys - waddlesplash