vmx: Introduce VMXNET3 Network Driver from FreeBSD 14.1

Tested with VMWare Workstation Pro 17.6.0 with Haiku x86_64 hrev58201.
To test, had to manually open the .vmx file associated with the VM and added the line:
ethernet0.virtualDev = "vmxnet3"

Change-Id: Ic76dcc61583707345bee46624814a38f66eb4f9f
Reviewed-on: https://review.haiku-os.org/c/haiku/+/8438
Reviewed-by: waddlesplash <waddlesplash@gmail.com>
This commit is contained in:
CodeforEvolution 2024-10-03 14:07:06 -05:00 committed by waddlesplash
parent 0059775c1d
commit 48d27198d0
7 changed files with 3143 additions and 0 deletions

View File

@ -332,6 +332,7 @@ SYSTEM_ADD_ONS_DRIVERS_NET = [ FFilterByBuildFeatures
sis900
syskonnect
via_rhine
vmx
vt612x
}@ # x86,x86_64,riscv64

View File

@ -33,6 +33,7 @@ HaikuSubInclude sis19x ;
HaikuSubInclude sis900 ;
HaikuSubInclude syskonnect ;
HaikuSubInclude via_rhine ;
HaikuSubInclude vmx ;
HaikuSubInclude vt612x ;
# OpenBSD drivers

View File

@ -0,0 +1,18 @@
SubDir HAIKU_TOP src add-ons kernel drivers network ether vmx ;
UseHeaders [ FDirName $(HAIKU_TOP) src libs compat freebsd_iflib compat ] : true ;
UseHeaders [ FDirName $(HAIKU_TOP) src libs compat freebsd_network compat ] : true ;
UsePrivateHeaders net system ;
UsePrivateKernelHeaders ;
UseHeaders [ FDirName $(SUBDIR) ] : true ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) dev vmxnet3 ] ;
SubDirCcFlags [ FDefines _KERNEL=1 FBSD_DRIVER=1 _XOPEN_SOURCE ] ;
KernelAddon vmx :
glue.c
if_vmx.c
: freebsd_iflib.a libfreebsd_network.a
;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,341 @@
/*-
* Copyright (c) 2013 Tsubai Masanari
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $OpenBSD: src/sys/dev/pci/if_vmxreg.h,v 1.2 2013/06/12 01:07:33 uebayasi Exp $
*/
#ifndef _IF_VMXREG_H
#define _IF_VMXREG_H
struct UPT1_TxStats {
uint64_t TSO_packets;
uint64_t TSO_bytes;
uint64_t ucast_packets;
uint64_t ucast_bytes;
uint64_t mcast_packets;
uint64_t mcast_bytes;
uint64_t bcast_packets;
uint64_t bcast_bytes;
uint64_t error;
uint64_t discard;
} __packed;
struct UPT1_RxStats {
uint64_t LRO_packets;
uint64_t LRO_bytes;
uint64_t ucast_packets;
uint64_t ucast_bytes;
uint64_t mcast_packets;
uint64_t mcast_bytes;
uint64_t bcast_packets;
uint64_t bcast_bytes;
uint64_t nobuffer;
uint64_t error;
} __packed;
/* Interrupt moderation levels */
#define UPT1_IMOD_NONE 0 /* No moderation */
#define UPT1_IMOD_HIGHEST 7 /* Least interrupts */
#define UPT1_IMOD_ADAPTIVE 8 /* Adaptive interrupt moderation */
/* Hardware features */
#define UPT1_F_CSUM 0x0001 /* Rx checksum verification */
#define UPT1_F_RSS 0x0002 /* Receive side scaling */
#define UPT1_F_VLAN 0x0004 /* VLAN tag stripping */
#define UPT1_F_LRO 0x0008 /* Large receive offloading */
#define VMXNET3_BAR0_IMASK(irq) (0x000 + (irq) * 8) /* Interrupt mask */
#define VMXNET3_BAR0_TXH(q) (0x600 + (q) * 8) /* Tx head */
#define VMXNET3_BAR0_RXH1(q) (0x800 + (q) * 8) /* Ring1 Rx head */
#define VMXNET3_BAR0_RXH2(q) (0xA00 + (q) * 8) /* Ring2 Rx head */
#define VMXNET3_BAR1_VRRS 0x000 /* VMXNET3 revision report selection */
#define VMXNET3_BAR1_UVRS 0x008 /* UPT version report selection */
#define VMXNET3_BAR1_DSL 0x010 /* Driver shared address low */
#define VMXNET3_BAR1_DSH 0x018 /* Driver shared address high */
#define VMXNET3_BAR1_CMD 0x020 /* Command */
#define VMXNET3_BAR1_MACL 0x028 /* MAC address low */
#define VMXNET3_BAR1_MACH 0x030 /* MAC address high */
#define VMXNET3_BAR1_INTR 0x038 /* Interrupt status */
#define VMXNET3_BAR1_EVENT 0x040 /* Event status */
#define VMXNET3_CMD_ENABLE 0xCAFE0000 /* Enable VMXNET3 */
#define VMXNET3_CMD_DISABLE 0xCAFE0001 /* Disable VMXNET3 */
#define VMXNET3_CMD_RESET 0xCAFE0002 /* Reset device */
#define VMXNET3_CMD_SET_RXMODE 0xCAFE0003 /* Set interface flags */
#define VMXNET3_CMD_SET_FILTER 0xCAFE0004 /* Set address filter */
#define VMXNET3_CMD_VLAN_FILTER 0xCAFE0005 /* Set VLAN filter */
#define VMXNET3_CMD_GET_STATUS 0xF00D0000 /* Get queue errors */
#define VMXNET3_CMD_GET_STATS 0xF00D0001 /* Get queue statistics */
#define VMXNET3_CMD_GET_LINK 0xF00D0002 /* Get link status */
#define VMXNET3_CMD_GET_MACL 0xF00D0003 /* Get MAC address low */
#define VMXNET3_CMD_GET_MACH 0xF00D0004 /* Get MAC address high */
#define VMXNET3_CMD_GET_INTRCFG 0xF00D0008 /* Get interrupt config */
#define VMXNET3_DMADESC_ALIGN 128
#define VMXNET3_INIT_GEN 1
struct vmxnet3_txdesc {
uint64_t addr;
uint32_t len:14;
uint32_t gen:1; /* Generation */
uint32_t pad1:1;
uint32_t dtype:1; /* Descriptor type */
uint32_t pad2:1;
uint32_t offload_pos:14; /* Offloading position */
uint32_t hlen:10; /* Header len */
uint32_t offload_mode:2; /* Offloading mode */
uint32_t eop:1; /* End of packet */
uint32_t compreq:1; /* Completion request */
uint32_t pad3:1;
uint32_t vtag_mode:1; /* VLAN tag insertion mode */
uint32_t vtag:16; /* VLAN tag */
} __packed;
/* Offloading modes */
#define VMXNET3_OM_NONE 0
#define VMXNET3_OM_CSUM 2
#define VMXNET3_OM_TSO 3
struct vmxnet3_txcompdesc {
uint32_t eop_idx:12; /* EOP index in Tx ring */
uint32_t pad1:20;
uint32_t pad2:32;
uint32_t pad3:32;
uint32_t rsvd:24;
uint32_t type:7;
uint32_t gen:1;
} __packed;
struct vmxnet3_rxdesc {
uint64_t addr;
uint32_t len:14;
uint32_t btype:1; /* Buffer type */
uint32_t dtype:1; /* Descriptor type */
uint32_t rsvd:15;
uint32_t gen:1;
uint32_t pad1:32;
} __packed;
/* Buffer types */
#define VMXNET3_BTYPE_HEAD 0 /* Head only */
#define VMXNET3_BTYPE_BODY 1 /* Body only */
struct vmxnet3_rxcompdesc {
uint32_t rxd_idx:12; /* Rx descriptor index */
uint32_t pad1:2;
uint32_t eop:1; /* End of packet */
uint32_t sop:1; /* Start of packet */
uint32_t qid:10;
uint32_t rss_type:4;
uint32_t no_csum:1; /* No checksum calculated */
uint32_t pad2:1;
uint32_t rss_hash:32; /* RSS hash value */
uint32_t len:14;
uint32_t error:1;
uint32_t vlan:1; /* 802.1Q VLAN frame */
uint32_t vtag:16; /* VLAN tag */
uint32_t csum:16;
uint32_t csum_ok:1; /* TCP/UDP checksum ok */
uint32_t udp:1;
uint32_t tcp:1;
uint32_t ipcsum_ok:1; /* IP checksum OK */
uint32_t ipv6:1;
uint32_t ipv4:1;
uint32_t fragment:1; /* IP fragment */
uint32_t fcs:1; /* Frame CRC correct */
uint32_t type:7;
uint32_t gen:1;
} __packed;
#define VMXNET3_RCD_RSS_TYPE_NONE 0
#define VMXNET3_RCD_RSS_TYPE_IPV4 1
#define VMXNET3_RCD_RSS_TYPE_TCPIPV4 2
#define VMXNET3_RCD_RSS_TYPE_IPV6 3
#define VMXNET3_RCD_RSS_TYPE_TCPIPV6 4
#define VMXNET3_REV1_MAGIC 0XBABEFEE1
#define VMXNET3_GOS_UNKNOWN 0x00
#define VMXNET3_GOS_LINUX 0x04
#define VMXNET3_GOS_WINDOWS 0x08
#define VMXNET3_GOS_SOLARIS 0x0C
#define VMXNET3_GOS_FREEBSD 0x10
#define VMXNET3_GOS_PXE 0x14
#define VMXNET3_GOS_32BIT 0x01
#define VMXNET3_GOS_64BIT 0x02
#define VMXNET3_MAX_TX_QUEUES 8
#define VMXNET3_MAX_RX_QUEUES 16
#define VMXNET3_MAX_INTRS \
(VMXNET3_MAX_TX_QUEUES + VMXNET3_MAX_RX_QUEUES + 1)
#define VMXNET3_ICTRL_DISABLE_ALL 0x01
#define VMXNET3_RXMODE_UCAST 0x01
#define VMXNET3_RXMODE_MCAST 0x02
#define VMXNET3_RXMODE_BCAST 0x04
#define VMXNET3_RXMODE_ALLMULTI 0x08
#define VMXNET3_RXMODE_PROMISC 0x10
#define VMXNET3_EVENT_RQERROR 0x01
#define VMXNET3_EVENT_TQERROR 0x02
#define VMXNET3_EVENT_LINK 0x04
#define VMXNET3_EVENT_DIC 0x08
#define VMXNET3_EVENT_DEBUG 0x10
#define VMXNET3_MIN_MTU 60
#define VMXNET3_MAX_MTU 9000
/* Interrupt mask mode. */
#define VMXNET3_IMM_AUTO 0x00
#define VMXNET3_IMM_ACTIVE 0x01
#define VMXNET3_IMM_LAZY 0x02
/* Interrupt type. */
#define VMXNET3_IT_AUTO 0x00
#define VMXNET3_IT_LEGACY 0x01
#define VMXNET3_IT_MSI 0x02
#define VMXNET3_IT_MSIX 0x03
struct vmxnet3_driver_shared {
uint32_t magic;
uint32_t pad1;
/* Misc. control */
uint32_t version; /* Driver version */
uint32_t guest; /* Guest OS */
uint32_t vmxnet3_revision; /* Supported VMXNET3 revision */
uint32_t upt_version; /* Supported UPT version */
uint64_t upt_features;
uint64_t driver_data;
uint64_t queue_shared;
uint32_t driver_data_len;
uint32_t queue_shared_len;
uint32_t mtu;
uint16_t nrxsg_max;
uint8_t ntxqueue;
uint8_t nrxqueue;
uint32_t reserved1[4];
/* Interrupt control */
uint8_t automask;
uint8_t nintr;
uint8_t evintr;
uint8_t modlevel[VMXNET3_MAX_INTRS];
uint32_t ictrl;
uint32_t reserved2[2];
/* Receive filter parameters */
uint32_t rxmode;
uint16_t mcast_tablelen;
uint16_t pad2;
uint64_t mcast_table;
uint32_t vlan_filter[4096 / 32];
struct {
uint32_t version;
uint32_t len;
uint64_t paddr;
} rss, pm, plugin;
uint32_t event;
uint32_t reserved3[5];
} __packed;
struct vmxnet3_txq_shared {
/* Control */
uint32_t npending;
uint32_t intr_threshold;
uint64_t reserved1;
/* Config */
uint64_t cmd_ring;
uint64_t data_ring;
uint64_t comp_ring;
uint64_t driver_data;
uint64_t reserved2;
uint32_t cmd_ring_len;
uint32_t data_ring_len;
uint32_t comp_ring_len;
uint32_t driver_data_len;
uint8_t intr_idx;
uint8_t pad1[7];
/* Queue status */
uint8_t stopped;
uint8_t pad2[3];
uint32_t error;
struct UPT1_TxStats stats;
uint8_t pad3[88];
} __packed;
struct vmxnet3_rxq_shared {
uint8_t update_rxhead;
uint8_t pad1[7];
uint64_t reserved1;
uint64_t cmd_ring[2];
uint64_t comp_ring;
uint64_t driver_data;
uint64_t reserved2;
uint32_t cmd_ring_len[2];
uint32_t comp_ring_len;
uint32_t driver_data_len;
uint8_t intr_idx;
uint8_t pad2[7];
uint8_t stopped;
uint8_t pad3[3];
uint32_t error;
struct UPT1_RxStats stats;
uint8_t pad4[88];
} __packed;
#define UPT1_RSS_HASH_TYPE_NONE 0x00
#define UPT1_RSS_HASH_TYPE_IPV4 0x01
#define UPT1_RSS_HASH_TYPE_TCP_IPV4 0x02
#define UPT1_RSS_HASH_TYPE_IPV6 0x04
#define UPT1_RSS_HASH_TYPE_TCP_IPV6 0x08
#define UPT1_RSS_HASH_FUNC_NONE 0x00
#define UPT1_RSS_HASH_FUNC_TOEPLITZ 0x01
#define UPT1_RSS_MAX_KEY_SIZE 40
#define UPT1_RSS_MAX_IND_TABLE_SIZE 128
struct vmxnet3_rss_shared {
uint16_t hash_type;
uint16_t hash_func;
uint16_t hash_key_size;
uint16_t ind_table_size;
uint8_t hash_key[UPT1_RSS_MAX_KEY_SIZE];
uint8_t ind_table[UPT1_RSS_MAX_IND_TABLE_SIZE];
} __packed;
#endif /* _IF_VMXREG_H */

View File

@ -0,0 +1,198 @@
/*-
* Copyright (c) 2013 Tsubai Masanari
* Copyright (c) 2013 Bryan Venteicher <bryanv@FreeBSD.org>
* Copyright (c) 2018 Patrick Kelsey
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _IF_VMXVAR_H
#define _IF_VMXVAR_H
struct vmxnet3_softc;
/*
* The number of Rx/Tx queues this driver prefers.
*/
#define VMXNET3_DEF_RX_QUEUES 8
#define VMXNET3_DEF_TX_QUEUES 8
/*
* The number of Rx rings in each Rx queue.
*/
#define VMXNET3_RXRINGS_PERQ 2
/*
* The number of descriptors in each Rx/Tx ring.
*/
#define VMXNET3_DEF_TX_NDESC 512
#define VMXNET3_MAX_TX_NDESC 4096
#define VMXNET3_MIN_TX_NDESC 32
#define VMXNET3_MASK_TX_NDESC 0x1F
#define VMXNET3_DEF_RX_NDESC 512
#define VMXNET3_MAX_RX_NDESC 2048
#define VMXNET3_MIN_RX_NDESC 32
#define VMXNET3_MASK_RX_NDESC 0x1F
#define VMXNET3_MAX_TX_NCOMPDESC VMXNET3_MAX_TX_NDESC
#define VMXNET3_MAX_RX_NCOMPDESC \
(VMXNET3_MAX_RX_NDESC * VMXNET3_RXRINGS_PERQ)
struct vmxnet3_txring {
u_int vxtxr_next;
u_int vxtxr_ndesc;
int vxtxr_gen;
struct vmxnet3_txdesc *vxtxr_txd;
bus_addr_t vxtxr_paddr;
};
struct vmxnet3_rxring {
struct vmxnet3_rxdesc *vxrxr_rxd;
u_int vxrxr_ndesc;
int vxrxr_gen;
bus_addr_t vxrxr_paddr;
uint64_t vxrxr_desc_skips;
uint16_t vxrxr_refill_start;
};
struct vmxnet3_comp_ring {
union {
struct vmxnet3_txcompdesc *txcd;
struct vmxnet3_rxcompdesc *rxcd;
} vxcr_u;
/*
* vxcr_next is used on the transmit side to track the next index to
* begin cleaning at. It is not used on the receive side.
*/
u_int vxcr_next;
u_int vxcr_ndesc;
int vxcr_gen;
bus_addr_t vxcr_paddr;
uint64_t vxcr_zero_length;
uint64_t vcxr_zero_length_frag;
uint64_t vxcr_pkt_errors;
};
struct vmxnet3_txqueue {
struct vmxnet3_softc *vxtxq_sc;
int vxtxq_id;
int vxtxq_last_flush;
int vxtxq_intr_idx;
struct vmxnet3_txring vxtxq_cmd_ring;
struct vmxnet3_comp_ring vxtxq_comp_ring;
struct vmxnet3_txq_shared *vxtxq_ts;
struct sysctl_oid_list *vxtxq_sysctl;
char vxtxq_name[16];
} __aligned(CACHE_LINE_SIZE);
struct vmxnet3_rxqueue {
struct vmxnet3_softc *vxrxq_sc;
int vxrxq_id;
int vxrxq_intr_idx;
struct if_irq vxrxq_irq;
struct vmxnet3_rxring vxrxq_cmd_ring[VMXNET3_RXRINGS_PERQ];
struct vmxnet3_comp_ring vxrxq_comp_ring;
struct vmxnet3_rxq_shared *vxrxq_rs;
struct sysctl_oid_list *vxrxq_sysctl;
char vxrxq_name[16];
} __aligned(CACHE_LINE_SIZE);
struct vmxnet3_softc {
device_t vmx_dev;
if_ctx_t vmx_ctx;
if_shared_ctx_t vmx_sctx;
if_softc_ctx_t vmx_scctx;
if_t vmx_ifp;
struct vmxnet3_driver_shared *vmx_ds;
uint32_t vmx_flags;
#define VMXNET3_FLAG_RSS 0x0002
#define VMXNET3_FLAG_SOFT_RSS 0x0004 /* Software RSS is enabled with
compatible algorithm. */
struct vmxnet3_rxqueue *vmx_rxq;
struct vmxnet3_txqueue *vmx_txq;
struct resource *vmx_res0;
bus_space_tag_t vmx_iot0;
bus_space_handle_t vmx_ioh0;
struct resource *vmx_res1;
bus_space_tag_t vmx_iot1;
bus_space_handle_t vmx_ioh1;
int vmx_link_active;
int vmx_intr_mask_mode;
int vmx_event_intr_idx;
struct if_irq vmx_event_intr_irq;
uint8_t *vmx_mcast;
struct vmxnet3_rss_shared *vmx_rss;
struct iflib_dma_info vmx_ds_dma;
struct iflib_dma_info vmx_qs_dma;
struct iflib_dma_info vmx_mcast_dma;
struct iflib_dma_info vmx_rss_dma;
struct ifmedia *vmx_media;
uint32_t vmx_vlan_filter[4096/32];
uint8_t vmx_lladdr[ETHER_ADDR_LEN];
};
/*
* Our driver version we report to the hypervisor; we just keep
* this value constant.
*/
#define VMXNET3_DRIVER_VERSION 0x00010000
/*
* Max descriptors per Tx packet. We must limit the size of the
* any TSO packets based on the number of segments.
*/
#define VMXNET3_TX_MAXSEGS 32 /* 64K @ 2K segment size */
#define VMXNET3_TX_MAXSIZE (VMXNET3_TX_MAXSEGS * MCLBYTES)
#define VMXNET3_TSO_MAXSIZE (VMXNET3_TX_MAXSIZE - ETHER_VLAN_ENCAP_LEN)
/*
* Maximum supported Tx segment size. The length field in the
* Tx descriptor is 14 bits.
*
* XXX It's possible a descriptor length field of 0 means 2^14, but this
* isn't confirmed, so limit to 2^14 - 1 for now.
*/
#define VMXNET3_TX_MAXSEGSIZE ((1 << 14) - 1)
/*
* Maximum supported Rx segment size. The length field in the
* Rx descriptor is 14 bits.
*
* The reference drivers skip zero-length descriptors, which seems to be a
* strong indication that on the receive side, a descriptor length field of
* zero does not mean 2^14.
*/
#define VMXNET3_RX_MAXSEGSIZE ((1 << 14) - 1)
/*
* Predetermined size of the multicast MACs filter table. If the
* number of multicast addresses exceeds this size, then the
* ALL_MULTI mode is use instead.
*/
#define VMXNET3_MULTICAST_MAX 32
/*
* IP protocols that we can perform Tx checksum offloading of.
*/
#define VMXNET3_CSUM_OFFLOAD (CSUM_TCP | CSUM_UDP)
#define VMXNET3_CSUM_OFFLOAD_IPV6 (CSUM_TCP_IPV6 | CSUM_UDP_IPV6)
#define VMXNET3_CSUM_ALL_OFFLOAD \
(VMXNET3_CSUM_OFFLOAD | VMXNET3_CSUM_OFFLOAD_IPV6 | CSUM_TSO)
#endif /* _IF_VMXVAR_H */

View File

@ -0,0 +1,26 @@
/*
* Copyright 2024, Jacob Secunda <secundaja@gmail.com>
* All rights reserved. Distributed under the terms of the MIT license.
*/
#include <sys/bus.h>
extern driver_t* DRIVER_MODULE_NAME(vmx, pci);
HAIKU_FBSD_DRIVERS_GLUE(vmx);
HAIKU_DRIVER_REQUIREMENTS(0);
NO_HAIKU_FBSD_MII_DRIVER();
NO_HAIKU_CHECK_DISABLE_INTERRUPTS();
NO_HAIKU_REENABLE_INTERRUPTS();
status_t
__haiku_handle_fbsd_drivers_list(status_t (*handler)(driver_t *[], driver_t *[]))
{
driver_t *drivers[] = {
DRIVER_MODULE_NAME(vmx, pci),
NULL
};
return (*handler)(drivers, NULL);
}