This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit fa935ecae1c2ac344bfe6938294d16b0c62585aa
Author: Ulaş Sertan Kemeç <[email protected]>
AuthorDate: Wed Aug 5 10:32:55 2026 +0300

    drivers/vhost: Add vhost-net, a device-role virtio network driver.
    
    Implements the device end of virtio-net, so a peer running the stock
    virtio-net driver sees this side as a network card, and registers a netdev
    lowerhalf.
    
    Ring layout follows the peer's numbering: vq[0] is its RX queue, which we 
fill
    to transmit, and vq[1] its TX queue, which we harvest.  No features are
    negotiated, so every frame carries the zeroed legacy virtio_net_hdr.
    
    Peer buffers are reached by raw 64-bit address through an arch-provided
    translation window -- the AM67 RAT, identity mapping elsewhere -- splitting
    copies that straddle it.
    
    Also gives DRIVERS_VHOST a prompt; it was promptless and so unselectable
    without a driver forcing it.
    
    Verified on t3-gem-o1 against an unmodified Linux virtio_net: eth0 
registers,
    ifup brings it to RUNNING, and the peer pings it 5/5 at 0.27 ms and 60/60 
with
    0% loss.
    
    Assisted-by: Claude Code:claude-fable-5
    Signed-off-by: Ulaş Sertan Kemeç <[email protected]>
---
 arch/arm/Kconfig             |   1 +
 arch/arm/src/am67/am67_rat.c |  17 ++
 drivers/vhost/CMakeLists.txt |   4 +
 drivers/vhost/Kconfig        |  32 ++-
 drivers/vhost/Make.defs      |   4 +
 drivers/vhost/vhost-net.c    | 495 +++++++++++++++++++++++++++++++++++++++++++
 drivers/vhost/vhost-net.h    |  28 +++
 include/nuttx/vhost/vhost.h  |  11 +
 8 files changed, 591 insertions(+), 1 deletion(-)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 9b53f6c2e1c..0b9bcdfd7bd 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -88,6 +88,7 @@ config ARCH_CHIP_AM67
        select ARCH_CORTEXR5
        select ARCH_HAVE_LOWVECTORS
        select ARCH_HAVE_TICKLESS
+       select ARCH_HAVE_VHOST_IOMAP
        select SCHED_HPWORK if RPTUN
        ---help---
                TI AM67 family
diff --git a/arch/arm/src/am67/am67_rat.c b/arch/arm/src/am67/am67_rat.c
index 867abc7ba62..35f0d69cbbb 100644
--- a/arch/arm/src/am67/am67_rat.c
+++ b/arch/arm/src/am67/am67_rat.c
@@ -53,6 +53,7 @@
 
 #include "arm_internal.h"
 #include "am67_rat.h"
+#include <nuttx/vhost/vhost.h>
 
 /****************************************************************************
  * Pre-processor Definitions
@@ -112,3 +113,19 @@ FAR void *am67_rat_map(uint64_t pa, FAR size_t *avail)
 
   return (FAR void *)(AM67_RAT_WIN_BASE + offset);
 }
+
+/****************************************************************************
+ * Name: up_vhost_iomap
+ *
+ * Description:
+ *   Arch hook used by the vhost drivers to reach peer buffers by 64-bit
+ *   physical address (see ARCH_HAVE_VHOST_IOMAP).
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_DRIVERS_VHOST
+FAR void *up_vhost_iomap(uint64_t pa, FAR size_t *avail)
+{
+  return am67_rat_map(pa, avail);
+}
+#endif
diff --git a/drivers/vhost/CMakeLists.txt b/drivers/vhost/CMakeLists.txt
index 4669b175218..d630c4d0fc2 100644
--- a/drivers/vhost/CMakeLists.txt
+++ b/drivers/vhost/CMakeLists.txt
@@ -29,6 +29,10 @@ if(CONFIG_DRIVERS_VHOST_RNG)
   list(APPEND SRCS vhost-rng.c)
 endif()
 
+if(CONFIG_DRIVERS_VHOST_NET)
+  list(APPEND SRCS vhost-net.c)
+endif()
+
 if(CONFIG_DRIVERS_VHOST_RPMSG)
   list(APPEND SRCS vhost-rpmsg.c)
 endif()
diff --git a/drivers/vhost/Kconfig b/drivers/vhost/Kconfig
index 3622cc0e20b..d3581b7fbe6 100644
--- a/drivers/vhost/Kconfig
+++ b/drivers/vhost/Kconfig
@@ -3,17 +3,47 @@
 # see the file kconfig-language.txt in the NuttX tools repository.
 #
 
-config DRIVERS_VHOST
+config ARCH_HAVE_VHOST_IOMAP
        bool
+       default n
+
+config DRIVERS_VHOST
+       bool "Virtual Host (device-role virtio) support"
        select OPENAMP
        select SCHED_WORKQUEUE
        default n
+       ---help---
+               Framework for implementing the DEVICE side of virtio links
+               (the peer's driver uses us as the device, e.g. a remoteproc
+               master like Linux).  rptun registers device-role vdevs from the
+               resource table through this bus; without it such vdevs are
+               rejected with -ENODEV.
 
 config DRIVERS_VHOST_RNG
        bool "Virtual Host Rng Device Support"
        default n
        select DRIVERS_VHOST
 
+config DRIVERS_VHOST_NET
+       bool "Virtual Host Network Device Support"
+       default n
+       depends on NETDEVICES
+       select DRIVERS_VHOST
+       ---help---
+               Device-role virtio-net: expose this side as a network card to a
+               peer processor running a standard virtio-net driver (e.g. Linux
+               via remoteproc), providing a NuttX ethN interface.
+
+config DRIVERS_VHOST_NET_MACADDR
+       hex "vhost-net MAC address"
+       default 0x025433000001
+       depends on DRIVERS_VHOST_NET
+       ---help---
+               No virtio-net features are negotiated on this link, so there is
+               no MAC config space to read; this fixed, software-assigned,
+               locally administered address is presented to the network stack
+               instead.
+
 config DRIVERS_VHOST_RPMSG
        bool "Virtual Host Rpmsg Device Support"
        default n
diff --git a/drivers/vhost/Make.defs b/drivers/vhost/Make.defs
index d48ca2b45c8..87063aefb3a 100644
--- a/drivers/vhost/Make.defs
+++ b/drivers/vhost/Make.defs
@@ -30,6 +30,10 @@ ifeq ($(CONFIG_DRIVERS_VHOST_RNG),y)
   CSRCS += vhost-rng.c
 endif
 
+ifeq ($(CONFIG_DRIVERS_VHOST_NET),y)
+CSRCS += vhost-net.c
+endif
+
 ifeq ($(CONFIG_DRIVERS_VHOST_RPMSG),y)
   CSRCS += vhost-rpmsg.c
 endif
diff --git a/drivers/vhost/vhost-net.c b/drivers/vhost/vhost-net.c
new file mode 100644
index 00000000000..712e45e270d
--- /dev/null
+++ b/drivers/vhost/vhost-net.c
@@ -0,0 +1,495 @@
+/****************************************************************************
+ * drivers/vhost/vhost-net.c
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/* Device-role virtio network driver ("vhost-net"): implements the DEVICE
+ * end of a virtio-net link, so a peer processor running a stock virtio-net
+ * DRIVER (e.g. Linux via remoteproc/rproc-virtio) sees this side as a
+ * network card.  Registers a NuttX netdev lowerhalf (ethN).
+ *
+ * Ring layout is fixed by the peer driver's point of view:
+ *   vq[0] = peer driver RX queue: the peer posts empty buffers; the
+ *           device side fills them to transmit toward the peer.
+ *   vq[1] = peer driver TX queue: the peer posts filled buffers; the
+ *           device side harvests them as its receive path.
+ *
+ * No virtio-net features are negotiated (the resource table advertises
+ * none), so every packet is prefixed by the legacy 10-byte
+ * struct virtio_net_hdr with all fields zero (gso_type NONE).
+ */
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <debug.h>
+#include <string.h>
+#include <sys/param.h>
+
+#include <nuttx/kmalloc.h>
+#include <nuttx/net/netdev_lowerhalf.h>
+#include <nuttx/vhost/vhost.h>
+
+#include "vhost-net.h"
+
+/* Peer buffers are referenced by 64-bit guest physical addresses that may
+ * exceed the CPU's direct reach; arches that provide a translation window
+ * implement up_vhost_iomap() (ARCH_HAVE_VHOST_IOMAP), others use the
+ * identity mapping.
+ */
+
+#ifdef CONFIG_ARCH_HAVE_VHOST_IOMAP
+#  define vhost_net_map(pa, avl) up_vhost_iomap((pa), (avl))
+#else
+static inline FAR void *vhost_net_map(uint64_t pa, FAR size_t *avail)
+{
+  if (avail != NULL)
+    {
+      *avail = SIZE_MAX;
+    }
+
+  return (FAR void *)(uintptr_t)pa;
+}
+#endif
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Queue indices (peer driver's numbering, see file header) */
+
+#define VHOST_NET_PEER_RXQ   0    /* device-side transmit lane */
+#define VHOST_NET_PEER_TXQ   1    /* device-side receive lane */
+#define VHOST_NET_NUM        2
+
+/* Legacy struct virtio_net_hdr (no VIRTIO_NET_F_MRG_RXBUF): flags(1) +
+ * gso_type(1) + hdr_len(2) + gso_size(2) + csum_start(2) + csum_offset(2)
+ */
+
+#define VHOST_NET_HDRSIZE    10
+
+/* netpkt quota per direction and the longest peer descriptor chain we
+ * accept on receive (Linux commonly splits header and payload).
+ */
+
+#define VHOST_NET_NPKTS      8
+#define VHOST_NET_MAXCHAIN   8
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct vhost_net_priv_s
+{
+  struct netdev_lowerhalf_s lower;      /* Must be first for casts */
+  FAR struct vhost_device  *hdev;
+  FAR struct virtqueue     *txq;        /* peer RX ring (filled here) */
+  FAR struct virtqueue     *rxq;        /* peer TX ring (drained here) */
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static int vhost_net_ifup(FAR struct netdev_lowerhalf_s *dev);
+static int vhost_net_ifdown(FAR struct netdev_lowerhalf_s *dev);
+static int vhost_net_transmit(FAR struct netdev_lowerhalf_s *dev,
+                              FAR netpkt_t *pkt);
+static FAR netpkt_t *vhost_net_receive(FAR struct netdev_lowerhalf_s *dev);
+static int vhost_net_probe(FAR struct vhost_device *hdev);
+static void vhost_net_remove(FAR struct vhost_device *hdev);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct netdev_ops_s g_vhost_net_ops =
+{
+  vhost_net_ifup,
+  vhost_net_ifdown,
+  vhost_net_transmit,
+  vhost_net_receive,
+#ifdef CONFIG_NET_MCASTGROUP
+  NULL,
+  NULL,
+#endif
+#ifdef CONFIG_NETDEV_IOCTL
+  NULL,
+#endif
+  NULL
+};
+
+static struct vhost_driver g_vhost_net_driver =
+{
+  LIST_INITIAL_VALUE(g_vhost_net_driver.node),  /* node */
+  VIRTIO_ID_NETWORK,                            /* device id */
+  vhost_net_probe,                              /* probe */
+  vhost_net_remove,                             /* remove */
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: vhost_net_rxready / vhost_net_txdone
+ *
+ * Description:
+ *   Virtqueue kick callbacks (transport notification context, thread
+ *   level).  Notify the upper half that ring work is pending; the rings
+ *   are processed in transmit()/receive().
+ *
+ ****************************************************************************/
+
+static void vhost_net_rxready(FAR struct virtqueue *vq)
+{
+  FAR struct vhost_net_priv_s *priv = vq->vq_dev->priv;
+
+  netdev_lower_rxready(&priv->lower);
+}
+
+static void vhost_net_txdone(FAR struct virtqueue *vq)
+{
+  FAR struct vhost_net_priv_s *priv = vq->vq_dev->priv;
+
+  netdev_lower_txdone(&priv->lower);
+}
+
+/****************************************************************************
+ * Name: vhost_net_ifup / vhost_net_ifdown
+ ****************************************************************************/
+
+static int vhost_net_ifup(FAR struct netdev_lowerhalf_s *dev)
+{
+  netdev_lower_carrier_on(dev);
+  return OK;
+}
+
+static int vhost_net_ifdown(FAR struct netdev_lowerhalf_s *dev)
+{
+  netdev_lower_carrier_off(dev);
+  return OK;
+}
+
+/****************************************************************************
+ * Name: vhost_net_transmit
+ *
+ * Description:
+ *   Fill one peer-posted RX buffer with the frame and complete it.
+ *   Completion is synchronous: the netpkt is consumed and freed before
+ *   returning.
+ *
+ ****************************************************************************/
+
+static int vhost_net_transmit(FAR struct netdev_lowerhalf_s *dev,
+                              FAR netpkt_t *pkt)
+{
+  FAR struct vhost_net_priv_s *priv = (FAR struct vhost_net_priv_s *)dev;
+  struct vhost_buf_s vb[1];
+  unsigned int len;
+  unsigned int pos;
+  size_t cnt;
+  int head;
+
+  head = vhost_get_vq_buffers_pa(priv->txq, vb, nitems(vb), &cnt);
+  if (head < 0)
+    {
+      /* Peer has not posted buffers (yet).  Re-enable its notifications;
+       * enable_cb reports buffers that arrived in the race window (their
+       * kick was suppressed), so grab them now if so.
+       */
+
+      if (!virtqueue_enable_cb(priv->txq))
+        {
+          return -ENOBUFS;
+        }
+
+      head = vhost_get_vq_buffers_pa(priv->txq, vb, nitems(vb), &cnt);
+      if (head < 0)
+        {
+          return -ENOBUFS;
+        }
+    }
+
+  len = netpkt_getdatalen(dev, pkt);
+  if (len + VHOST_NET_HDRSIZE > vb[0].len)
+    {
+      /* Frame cannot fit the peer's buffer: complete it empty (drop) */
+
+      vhosterr("frame %u exceeds peer buffer %" PRIu32 ", dropped\n",
+               len, vb[0].len);
+      len = 0;
+    }
+  else
+    {
+      /* Serialize the zero header + frame into the peer buffer through
+       * the translation window, honoring window-boundary splits.
+       */
+
+      for (pos = 0; pos < len + VHOST_NET_HDRSIZE; )
+        {
+          size_t avail;
+          FAR uint8_t *dst = vhost_net_map(vb[0].addr + pos, &avail);
+          unsigned int chunk = MIN(len + VHOST_NET_HDRSIZE - pos, avail);
+          unsigned int hdrlen = 0;
+          int ret = OK;
+
+          if (pos < VHOST_NET_HDRSIZE)
+            {
+              hdrlen = MIN(VHOST_NET_HDRSIZE - pos, chunk);
+              memset(dst, 0, hdrlen);
+            }
+
+          if (chunk > hdrlen)
+            {
+              ret = netpkt_copyout(dev, dst + hdrlen, pkt, chunk - hdrlen,
+                                   pos + hdrlen - VHOST_NET_HDRSIZE);
+            }
+
+          if (ret < 0)
+            {
+              vhosterr("netpkt_copyout failed, ret=%d, dropped\n", ret);
+              len = 0;
+              break;
+            }
+
+          pos += chunk;
+        }
+    }
+
+  virtqueue_add_consumed_buffer(priv->txq, head,
+                                len ? len + VHOST_NET_HDRSIZE : 0);
+  virtqueue_kick(priv->txq);
+
+  netpkt_free(dev, pkt, NETPKT_TX);
+  netdev_lower_txdone(dev);
+  return OK;
+}
+
+/****************************************************************************
+ * Name: vhost_net_receive
+ *
+ * Description:
+ *   Harvest one frame (possibly a descriptor chain) from the peer TX
+ *   ring, copy it into a fresh netpkt (stripping the virtio-net header)
+ *   and return the buffers to the peer.
+ *
+ ****************************************************************************/
+
+static FAR netpkt_t *vhost_net_receive(FAR struct netdev_lowerhalf_s *dev)
+{
+  FAR struct vhost_net_priv_s *priv = (FAR struct vhost_net_priv_s *)dev;
+  struct vhost_buf_s vb[VHOST_NET_MAXCHAIN];
+  FAR netpkt_t *pkt = NULL;
+  unsigned int total = 0;
+  unsigned int skip = VHOST_NET_HDRSIZE;
+  int offset = 0;
+  size_t cnt;
+  size_t i;
+  int head;
+
+  head = vhost_get_vq_buffers_pa(priv->rxq, vb, nitems(vb), &cnt);
+  if (head < 0)
+    {
+      /* See vhost_net_transmit() for the enable_cb recheck rationale */
+
+      if (!virtqueue_enable_cb(priv->rxq))
+        {
+          return NULL;
+        }
+
+      head = vhost_get_vq_buffers_pa(priv->rxq, vb, nitems(vb), &cnt);
+      if (head < 0)
+        {
+          return NULL;
+        }
+    }
+
+  for (i = 0; i < cnt; i++)
+    {
+      total += vb[i].len;
+    }
+
+  if (total > skip)
+    {
+      pkt = netpkt_alloc(dev, NETPKT_RX);
+    }
+
+  if (pkt != NULL &&
+      netpkt_setdatalen(dev, pkt, total - skip) < total - skip)
+    {
+      vhosterr("rx dropped: cannot size netpkt to %u\n", total - skip);
+      netpkt_free(dev, pkt, NETPKT_RX);
+      pkt = NULL;
+    }
+
+  if (pkt != NULL)
+    {
+      for (i = 0; i < cnt; i++)
+        {
+          uint64_t pa = vb[i].addr;
+          uint32_t blen = vb[i].len;
+
+          if (skip > 0)
+            {
+              uint32_t skiplen = MIN(skip, blen);
+
+              pa   += skiplen;
+              blen -= skiplen;
+              skip -= skiplen;
+            }
+
+          /* Copy through the translation window, honoring
+           * window-boundary splits.
+           */
+
+          while (blen > 0)
+            {
+              size_t avail;
+              FAR const uint8_t *src = vhost_net_map(pa, &avail);
+              uint32_t chunk = MIN(blen, avail);
+
+              if (netpkt_copyin(dev, pkt, src, chunk, offset) < 0)
+                {
+                  vhosterr("netpkt_copyin failed, rx dropped\n");
+                  netpkt_free(dev, pkt, NETPKT_RX);
+                  pkt = NULL;
+                  goto out;
+                }
+
+              offset += chunk;
+              pa     += chunk;
+              blen   -= chunk;
+            }
+        }
+    }
+  else
+    {
+      vhosterr("rx dropped: total=%u (no netpkt)\n", total);
+    }
+
+out:
+
+  /* Hand the buffers back to the peer either way */
+
+  virtqueue_add_consumed_buffer(priv->rxq, head, total);
+  virtqueue_kick(priv->rxq);
+
+  return pkt;
+}
+
+/****************************************************************************
+ * Name: vhost_net_probe
+ ****************************************************************************/
+
+static int vhost_net_probe(FAR struct vhost_device *hdev)
+{
+  FAR struct vhost_net_priv_s *priv;
+  FAR const char *vqnames[VHOST_NET_NUM];
+  vq_callback callbacks[VHOST_NET_NUM];
+  FAR uint8_t *mac;
+  int ret;
+
+  priv = kmm_zalloc(sizeof(*priv));
+  if (priv == NULL)
+    {
+      return -ENOMEM;
+    }
+
+  priv->hdev = hdev;
+  hdev->priv = priv;
+
+  vqnames[VHOST_NET_PEER_RXQ]   = "vhost_net_peer_rx";
+  vqnames[VHOST_NET_PEER_TXQ]   = "vhost_net_peer_tx";
+  callbacks[VHOST_NET_PEER_RXQ] = vhost_net_txdone;
+  callbacks[VHOST_NET_PEER_TXQ] = vhost_net_rxready;
+  ret = vhost_create_virtqueues(hdev, 0, VHOST_NET_NUM, vqnames,
+                                callbacks, NULL);
+  if (ret < 0)
+    {
+      vhosterr("vhost_create_virtqueues failed, ret=%d\n", ret);
+      goto err_with_priv;
+    }
+
+  priv->txq = hdev->vrings_info[VHOST_NET_PEER_RXQ].vq;
+  priv->rxq = hdev->vrings_info[VHOST_NET_PEER_TXQ].vq;
+
+  priv->lower.quota[NETPKT_RX] = VHOST_NET_NPKTS;
+  priv->lower.quota[NETPKT_TX] = VHOST_NET_NPKTS;
+  priv->lower.ops = &g_vhost_net_ops;
+
+  /* Software-assigned MAC (no MAC config space without negotiated
+   * features); see CONFIG_DRIVERS_VHOST_NET_MACADDR.
+   */
+
+  mac = priv->lower.netdev.d_mac.ether.ether_addr_octet;
+  mac[0] = (CONFIG_DRIVERS_VHOST_NET_MACADDR >> (8 * 5)) & 0xff;
+  mac[1] = (CONFIG_DRIVERS_VHOST_NET_MACADDR >> (8 * 4)) & 0xff;
+  mac[2] = (CONFIG_DRIVERS_VHOST_NET_MACADDR >> (8 * 3)) & 0xff;
+  mac[3] = (CONFIG_DRIVERS_VHOST_NET_MACADDR >> (8 * 2)) & 0xff;
+  mac[4] = (CONFIG_DRIVERS_VHOST_NET_MACADDR >> (8 * 1)) & 0xff;
+  mac[5] = (CONFIG_DRIVERS_VHOST_NET_MACADDR >> (8 * 0)) & 0xff;
+
+  ret = netdev_lower_register(&priv->lower, NET_LL_ETHERNET);
+  if (ret < 0)
+    {
+      vhosterr("netdev_lower_register failed, ret=%d\n", ret);
+      goto err_with_vqs;
+    }
+
+  return OK;
+
+err_with_vqs:
+  vhost_delete_virtqueues(hdev);
+err_with_priv:
+  kmm_free(priv);
+  hdev->priv = NULL;
+  return ret;
+}
+
+/****************************************************************************
+ * Name: vhost_net_remove
+ ****************************************************************************/
+
+static void vhost_net_remove(FAR struct vhost_device *hdev)
+{
+  FAR struct vhost_net_priv_s *priv = hdev->priv;
+
+  netdev_lower_unregister(&priv->lower);
+  vhost_delete_virtqueues(hdev);
+  kmm_free(priv);
+  hdev->priv = NULL;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: vhost_register_net_driver
+ ****************************************************************************/
+
+int vhost_register_net_driver(void)
+{
+  return vhost_register_driver(&g_vhost_net_driver);
+}
diff --git a/drivers/vhost/vhost-net.h b/drivers/vhost/vhost-net.h
new file mode 100644
index 00000000000..17133e6c1c6
--- /dev/null
+++ b/drivers/vhost/vhost-net.h
@@ -0,0 +1,28 @@
+/****************************************************************************
+ * drivers/vhost/vhost-net.h
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __DRIVERS_VHOST_VHOST_NET_H
+#define __DRIVERS_VHOST_VHOST_NET_H
+
+int vhost_register_net_driver(void);
+
+#endif /* __DRIVERS_VHOST_VHOST_NET_H */
diff --git a/include/nuttx/vhost/vhost.h b/include/nuttx/vhost/vhost.h
index 60f32db1cc8..e46cd1015e8 100644
--- a/include/nuttx/vhost/vhost.h
+++ b/include/nuttx/vhost/vhost.h
@@ -109,6 +109,17 @@ int vhost_get_vq_buffers_pa(FAR struct virtqueue *vq,
                             FAR struct vhost_buf_s *vb, size_t vbsize,
                             FAR size_t *vbcnt);
 
+#ifdef CONFIG_ARCH_HAVE_VHOST_IOMAP
+/* Arch-provided: map a peer 64-bit physical address into CPU-reachable
+ * memory.  Returns the mapped VA; *avail (if non-NULL) receives the number
+ * of contiguous bytes reachable from it.  The mapping may be invalidated
+ * by the next call (e.g. a sliding hardware window), so callers must
+ * serialize use.
+ */
+
+FAR void *up_vhost_iomap(uint64_t pa, FAR size_t *avail);
+#endif
+
 /****************************************************************************
  * Name: vhost_register_drivers
  ****************************************************************************/

Reply via email to