1a82ab411SLuigi Rizzo /* 2a82ab411SLuigi Rizzo * Copyright (C) 2013-2016 Luigi Rizzo 3a82ab411SLuigi Rizzo * Copyright (C) 2013-2016 Giuseppe Lettieri 4a82ab411SLuigi Rizzo * Copyright (C) 2013-2016 Vincenzo Maffione 5a82ab411SLuigi Rizzo * Copyright (C) 2015 Stefano Garzarella 6a82ab411SLuigi Rizzo * All rights reserved. 7a82ab411SLuigi Rizzo * 8a82ab411SLuigi Rizzo * Redistribution and use in source and binary forms, with or without 9a82ab411SLuigi Rizzo * modification, are permitted provided that the following conditions 10a82ab411SLuigi Rizzo * are met: 11a82ab411SLuigi Rizzo * 1. Redistributions of source code must retain the above copyright 12a82ab411SLuigi Rizzo * notice, this list of conditions and the following disclaimer. 13a82ab411SLuigi Rizzo * 2. Redistributions in binary form must reproduce the above copyright 14a82ab411SLuigi Rizzo * notice, this list of conditions and the following disclaimer in the 15a82ab411SLuigi Rizzo * documentation and/or other materials provided with the distribution. 16a82ab411SLuigi Rizzo * 17a82ab411SLuigi Rizzo * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18a82ab411SLuigi Rizzo * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19a82ab411SLuigi Rizzo * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20a82ab411SLuigi Rizzo * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21a82ab411SLuigi Rizzo * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22a82ab411SLuigi Rizzo * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23a82ab411SLuigi Rizzo * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24a82ab411SLuigi Rizzo * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25a82ab411SLuigi Rizzo * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26a82ab411SLuigi Rizzo * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27a82ab411SLuigi Rizzo * SUCH DAMAGE. 28a82ab411SLuigi Rizzo * 29a82ab411SLuigi Rizzo * $FreeBSD$ 30a82ab411SLuigi Rizzo */ 31a82ab411SLuigi Rizzo 32a82ab411SLuigi Rizzo #ifndef NETMAP_VIRT_H 33a82ab411SLuigi Rizzo #define NETMAP_VIRT_H 34a82ab411SLuigi Rizzo 35a82ab411SLuigi Rizzo #define NETMAP_VIRT_CSB_SIZE 4096 36a82ab411SLuigi Rizzo 37a82ab411SLuigi Rizzo /* ptnetmap features */ 38a82ab411SLuigi Rizzo #define PTNETMAP_F_BASE 1 39a82ab411SLuigi Rizzo #define PTNETMAP_F_FULL 2 /* not used */ 40a82ab411SLuigi Rizzo #define PTNETMAP_F_VNET_HDR 4 41a82ab411SLuigi Rizzo 42a82ab411SLuigi Rizzo /* 43a82ab411SLuigi Rizzo * ptnetmap_memdev: device used to expose memory into the guest VM 44a82ab411SLuigi Rizzo * 45a82ab411SLuigi Rizzo * These macros are used in the hypervisor frontend (QEMU, bhyve) and in the 46a82ab411SLuigi Rizzo * guest device driver. 47a82ab411SLuigi Rizzo */ 48a82ab411SLuigi Rizzo 49a82ab411SLuigi Rizzo /* PCI identifiers and PCI BARs for the ptnetmap memdev 50a82ab411SLuigi Rizzo * and ptnetmap network interface. */ 51a82ab411SLuigi Rizzo #define PTNETMAP_MEMDEV_NAME "ptnetmap-memdev" 52a82ab411SLuigi Rizzo #define PTNETMAP_PCI_VENDOR_ID 0x3333 /* TODO change vendor_id */ 53a82ab411SLuigi Rizzo #define PTNETMAP_PCI_DEVICE_ID 0x0001 /* memory device */ 54a82ab411SLuigi Rizzo #define PTNETMAP_PCI_NETIF_ID 0x0002 /* ptnet network interface */ 55a82ab411SLuigi Rizzo #define PTNETMAP_IO_PCI_BAR 0 56a82ab411SLuigi Rizzo #define PTNETMAP_MEM_PCI_BAR 1 57a82ab411SLuigi Rizzo #define PTNETMAP_MSIX_PCI_BAR 2 58a82ab411SLuigi Rizzo 59a82ab411SLuigi Rizzo /* Registers for the ptnetmap memdev */ 60a82ab411SLuigi Rizzo /* 32 bit r/o */ 61*a2a74091SLuigi Rizzo #define PTNETMAP_IO_PCI_MEMSIZE 0 /* size of the netmap memory shared 62a82ab411SLuigi Rizzo * between guest and host */ 63a82ab411SLuigi Rizzo /* 16 bit r/o */ 64*a2a74091SLuigi Rizzo #define PTNETMAP_IO_PCI_HOSTID 4 /* memory allocator ID in netmap host */ 65*a2a74091SLuigi Rizzo #define PTNETMAP_IO_SIZE 6 66a82ab411SLuigi Rizzo 67a82ab411SLuigi Rizzo /* 68a82ab411SLuigi Rizzo * ptnetmap configuration 69a82ab411SLuigi Rizzo * 70a82ab411SLuigi Rizzo * The hypervisor (QEMU or bhyve) sends this struct to the host netmap 71a82ab411SLuigi Rizzo * module through an ioctl() command when it wants to start the ptnetmap 72a82ab411SLuigi Rizzo * kthreads. 73a82ab411SLuigi Rizzo */ 74a82ab411SLuigi Rizzo struct ptnetmap_cfg { 75a82ab411SLuigi Rizzo #define PTNETMAP_CFG_FEAT_CSB 0x0001 76a82ab411SLuigi Rizzo #define PTNETMAP_CFG_FEAT_EVENTFD 0x0002 77a82ab411SLuigi Rizzo #define PTNETMAP_CFG_FEAT_IOCTL 0x0004 78a82ab411SLuigi Rizzo uint32_t features; 79a82ab411SLuigi Rizzo void *ptrings; /* ptrings inside CSB */ 80a82ab411SLuigi Rizzo uint32_t num_rings; /* number of entries */ 81a82ab411SLuigi Rizzo struct ptnet_ring_cfg entries[0]; /* per-ptring configuration */ 82a82ab411SLuigi Rizzo }; 83a82ab411SLuigi Rizzo 84a82ab411SLuigi Rizzo /* 85a82ab411SLuigi Rizzo * Functions used to write ptnetmap_cfg from/to the nmreq. 86a82ab411SLuigi Rizzo * The user-space application writes the pointer of ptnetmap_cfg 87a82ab411SLuigi Rizzo * (user-space buffer) starting from nr_arg1 field, so that the kernel 88a82ab411SLuigi Rizzo * can read it with copyin (copy_from_user). 89a82ab411SLuigi Rizzo */ 90a82ab411SLuigi Rizzo static inline void 91a82ab411SLuigi Rizzo ptnetmap_write_cfg(struct nmreq *nmr, struct ptnetmap_cfg *cfg) 92a82ab411SLuigi Rizzo { 93a82ab411SLuigi Rizzo uintptr_t *nmr_ptncfg = (uintptr_t *)&nmr->nr_arg1; 94a82ab411SLuigi Rizzo *nmr_ptncfg = (uintptr_t)cfg; 95a82ab411SLuigi Rizzo } 96a82ab411SLuigi Rizzo 97a82ab411SLuigi Rizzo /* ptnetmap control commands */ 98a82ab411SLuigi Rizzo #define PTNETMAP_PTCTL_CONFIG 1 99a82ab411SLuigi Rizzo #define PTNETMAP_PTCTL_FINALIZE 2 100a82ab411SLuigi Rizzo #define PTNETMAP_PTCTL_IFNEW 3 101a82ab411SLuigi Rizzo #define PTNETMAP_PTCTL_IFDELETE 4 102a82ab411SLuigi Rizzo #define PTNETMAP_PTCTL_RINGSCREATE 5 103a82ab411SLuigi Rizzo #define PTNETMAP_PTCTL_RINGSDELETE 6 104a82ab411SLuigi Rizzo #define PTNETMAP_PTCTL_DEREF 7 105a82ab411SLuigi Rizzo #define PTNETMAP_PTCTL_TXSYNC 8 106a82ab411SLuigi Rizzo #define PTNETMAP_PTCTL_RXSYNC 9 107a82ab411SLuigi Rizzo #define PTNETMAP_PTCTL_REGIF 10 108a82ab411SLuigi Rizzo #define PTNETMAP_PTCTL_UNREGIF 11 109a82ab411SLuigi Rizzo #define PTNETMAP_PTCTL_HOSTMEMID 12 110a82ab411SLuigi Rizzo 111a82ab411SLuigi Rizzo 112a82ab411SLuigi Rizzo /* I/O registers for the ptnet device. */ 113a82ab411SLuigi Rizzo #define PTNET_IO_PTFEAT 0 114a82ab411SLuigi Rizzo #define PTNET_IO_PTCTL 4 115a82ab411SLuigi Rizzo #define PTNET_IO_PTSTS 8 116*a2a74091SLuigi Rizzo #define PTNET_IO_MAC_LO 12 117*a2a74091SLuigi Rizzo #define PTNET_IO_MAC_HI 16 118*a2a74091SLuigi Rizzo #define PTNET_IO_CSBBAH 20 119*a2a74091SLuigi Rizzo #define PTNET_IO_CSBBAL 24 120*a2a74091SLuigi Rizzo #define PTNET_IO_NIFP_OFS 28 121*a2a74091SLuigi Rizzo #define PTNET_IO_NUM_TX_RINGS 32 122*a2a74091SLuigi Rizzo #define PTNET_IO_NUM_RX_RINGS 36 123*a2a74091SLuigi Rizzo #define PTNET_IO_NUM_TX_SLOTS 40 124*a2a74091SLuigi Rizzo #define PTNET_IO_NUM_RX_SLOTS 44 125*a2a74091SLuigi Rizzo #define PTNET_IO_VNET_HDR_LEN 48 126*a2a74091SLuigi Rizzo #define PTNET_IO_END 52 127a82ab411SLuigi Rizzo #define PTNET_IO_KICK_BASE 128 128a82ab411SLuigi Rizzo #define PTNET_IO_MASK 0xff 129a82ab411SLuigi Rizzo 130a82ab411SLuigi Rizzo /* If defined, CSB is allocated by the guest, not by the host. */ 131a82ab411SLuigi Rizzo #define PTNET_CSB_ALLOC 132a82ab411SLuigi Rizzo 133a82ab411SLuigi Rizzo /* ptnetmap ring fields shared between guest and host */ 134a82ab411SLuigi Rizzo struct ptnet_ring { 135a82ab411SLuigi Rizzo /* XXX revise the layout to minimize cache bounces. */ 136a82ab411SLuigi Rizzo uint32_t head; /* GW+ HR+ the head of the guest netmap_ring */ 137a82ab411SLuigi Rizzo uint32_t cur; /* GW+ HR+ the cur of the guest netmap_ring */ 138a82ab411SLuigi Rizzo uint32_t guest_need_kick; /* GW+ HR+ host-->guest notification enable */ 139*a2a74091SLuigi Rizzo uint32_t sync_flags; /* GW+ HR+ the flags of the guest [tx|rx]sync() */ 140a82ab411SLuigi Rizzo uint32_t hwcur; /* GR+ HW+ the hwcur of the host netmap_kring */ 141a82ab411SLuigi Rizzo uint32_t hwtail; /* GR+ HW+ the hwtail of the host netmap_kring */ 142a82ab411SLuigi Rizzo uint32_t host_need_kick; /* GR+ HW+ guest-->host notification enable */ 143*a2a74091SLuigi Rizzo char pad[4]; 144a82ab411SLuigi Rizzo }; 145a82ab411SLuigi Rizzo 146a82ab411SLuigi Rizzo /* CSB for the ptnet device. */ 147a82ab411SLuigi Rizzo struct ptnet_csb { 148a82ab411SLuigi Rizzo struct ptnet_ring rings[NETMAP_VIRT_CSB_SIZE/sizeof(struct ptnet_ring)]; 149a82ab411SLuigi Rizzo }; 150a82ab411SLuigi Rizzo 151a82ab411SLuigi Rizzo #if defined (WITH_PTNETMAP_HOST) || defined (WITH_PTNETMAP_GUEST) 152a82ab411SLuigi Rizzo 153a82ab411SLuigi Rizzo /* return l_elem - r_elem with wraparound */ 154a82ab411SLuigi Rizzo static inline uint32_t 155a82ab411SLuigi Rizzo ptn_sub(uint32_t l_elem, uint32_t r_elem, uint32_t num_slots) 156a82ab411SLuigi Rizzo { 157a82ab411SLuigi Rizzo int64_t res; 158a82ab411SLuigi Rizzo 159a82ab411SLuigi Rizzo res = (int64_t)(l_elem) - r_elem; 160a82ab411SLuigi Rizzo 161a82ab411SLuigi Rizzo return (res < 0) ? res + num_slots : res; 162a82ab411SLuigi Rizzo } 163a82ab411SLuigi Rizzo #endif /* WITH_PTNETMAP_HOST || WITH_PTNETMAP_GUEST */ 164a82ab411SLuigi Rizzo 165*a2a74091SLuigi Rizzo #ifdef WITH_PTNETMAP_GUEST 166*a2a74091SLuigi Rizzo 167*a2a74091SLuigi Rizzo /* ptnetmap_memdev routines used to talk with ptnetmap_memdev device driver */ 168*a2a74091SLuigi Rizzo struct ptnetmap_memdev; 169*a2a74091SLuigi Rizzo int nm_os_pt_memdev_iomap(struct ptnetmap_memdev *, vm_paddr_t *, void **); 170*a2a74091SLuigi Rizzo void nm_os_pt_memdev_iounmap(struct ptnetmap_memdev *); 171*a2a74091SLuigi Rizzo 172*a2a74091SLuigi Rizzo /* Guest driver: Write kring pointers (cur, head) to the CSB. 173*a2a74091SLuigi Rizzo * This routine is coupled with ptnetmap_host_read_kring_csb(). */ 174*a2a74091SLuigi Rizzo static inline void 175*a2a74091SLuigi Rizzo ptnetmap_guest_write_kring_csb(struct ptnet_ring *ptr, uint32_t cur, 176*a2a74091SLuigi Rizzo uint32_t head) 177*a2a74091SLuigi Rizzo { 178*a2a74091SLuigi Rizzo /* 179*a2a74091SLuigi Rizzo * We need to write cur and head to the CSB but we cannot do it atomically. 180*a2a74091SLuigi Rizzo * There is no way we can prevent the host from reading the updated value 181*a2a74091SLuigi Rizzo * of one of the two and the old value of the other. However, if we make 182*a2a74091SLuigi Rizzo * sure that the host never reads a value of head more recent than the 183*a2a74091SLuigi Rizzo * value of cur we are safe. We can allow the host to read a value of cur 184*a2a74091SLuigi Rizzo * more recent than the value of head, since in the netmap ring cur can be 185*a2a74091SLuigi Rizzo * ahead of head and cur cannot wrap around head because it must be behind 186*a2a74091SLuigi Rizzo * tail. Inverting the order of writes below could instead result into the 187*a2a74091SLuigi Rizzo * host to think head went ahead of cur, which would cause the sync 188*a2a74091SLuigi Rizzo * prologue to fail. 189*a2a74091SLuigi Rizzo * 190*a2a74091SLuigi Rizzo * The following memory barrier scheme is used to make this happen: 191*a2a74091SLuigi Rizzo * 192*a2a74091SLuigi Rizzo * Guest Host 193*a2a74091SLuigi Rizzo * 194*a2a74091SLuigi Rizzo * STORE(cur) LOAD(head) 195*a2a74091SLuigi Rizzo * mb() <-----------> mb() 196*a2a74091SLuigi Rizzo * STORE(head) LOAD(cur) 197*a2a74091SLuigi Rizzo */ 198*a2a74091SLuigi Rizzo ptr->cur = cur; 199*a2a74091SLuigi Rizzo mb(); 200*a2a74091SLuigi Rizzo ptr->head = head; 201*a2a74091SLuigi Rizzo } 202*a2a74091SLuigi Rizzo 203*a2a74091SLuigi Rizzo /* Guest driver: Read kring pointers (hwcur, hwtail) from the CSB. 204*a2a74091SLuigi Rizzo * This routine is coupled with ptnetmap_host_write_kring_csb(). */ 205*a2a74091SLuigi Rizzo static inline void 206*a2a74091SLuigi Rizzo ptnetmap_guest_read_kring_csb(struct ptnet_ring *ptr, struct netmap_kring *kring) 207*a2a74091SLuigi Rizzo { 208*a2a74091SLuigi Rizzo /* 209*a2a74091SLuigi Rizzo * We place a memory barrier to make sure that the update of hwtail never 210*a2a74091SLuigi Rizzo * overtakes the update of hwcur. 211*a2a74091SLuigi Rizzo * (see explanation in ptnetmap_host_write_kring_csb). 212*a2a74091SLuigi Rizzo */ 213*a2a74091SLuigi Rizzo kring->nr_hwtail = ptr->hwtail; 214*a2a74091SLuigi Rizzo mb(); 215*a2a74091SLuigi Rizzo kring->nr_hwcur = ptr->hwcur; 216*a2a74091SLuigi Rizzo } 217*a2a74091SLuigi Rizzo 218*a2a74091SLuigi Rizzo #endif /* WITH_PTNETMAP_GUEST */ 219*a2a74091SLuigi Rizzo 220a82ab411SLuigi Rizzo #ifdef WITH_PTNETMAP_HOST 221a82ab411SLuigi Rizzo /* 222a82ab411SLuigi Rizzo * ptnetmap kernel thread routines 223a82ab411SLuigi Rizzo * */ 224a82ab411SLuigi Rizzo 225a82ab411SLuigi Rizzo /* Functions to read and write CSB fields in the host */ 226a82ab411SLuigi Rizzo #if defined (linux) 227a82ab411SLuigi Rizzo #define CSB_READ(csb, field, r) (get_user(r, &csb->field)) 228a82ab411SLuigi Rizzo #define CSB_WRITE(csb, field, v) (put_user(v, &csb->field)) 229a82ab411SLuigi Rizzo #else /* ! linux */ 230a82ab411SLuigi Rizzo #define CSB_READ(csb, field, r) (r = fuword32(&csb->field)) 231a82ab411SLuigi Rizzo #define CSB_WRITE(csb, field, v) (suword32(&csb->field, v)) 232a82ab411SLuigi Rizzo #endif /* ! linux */ 233a82ab411SLuigi Rizzo 234*a2a74091SLuigi Rizzo /* Host netmap: Write kring pointers (hwcur, hwtail) to the CSB. 235*a2a74091SLuigi Rizzo * This routine is coupled with ptnetmap_guest_read_kring_csb(). */ 236a82ab411SLuigi Rizzo static inline void 237a82ab411SLuigi Rizzo ptnetmap_host_write_kring_csb(struct ptnet_ring __user *ptr, uint32_t hwcur, 238a82ab411SLuigi Rizzo uint32_t hwtail) 239a82ab411SLuigi Rizzo { 240*a2a74091SLuigi Rizzo /* 241*a2a74091SLuigi Rizzo * The same scheme used in ptnetmap_guest_write_kring_csb() applies here. 242*a2a74091SLuigi Rizzo * We allow the guest to read a value of hwcur more recent than the value 243*a2a74091SLuigi Rizzo * of hwtail, since this would anyway result in a consistent view of the 244*a2a74091SLuigi Rizzo * ring state (and hwcur can never wraparound hwtail, since hwcur must be 245*a2a74091SLuigi Rizzo * behind head). 246*a2a74091SLuigi Rizzo * 247*a2a74091SLuigi Rizzo * The following memory barrier scheme is used to make this happen: 248*a2a74091SLuigi Rizzo * 249*a2a74091SLuigi Rizzo * Guest Host 250*a2a74091SLuigi Rizzo * 251*a2a74091SLuigi Rizzo * STORE(hwcur) LOAD(hwtail) 252*a2a74091SLuigi Rizzo * mb() <-------------> mb() 253*a2a74091SLuigi Rizzo * STORE(hwtail) LOAD(hwcur) 254*a2a74091SLuigi Rizzo */ 255a82ab411SLuigi Rizzo CSB_WRITE(ptr, hwcur, hwcur); 256*a2a74091SLuigi Rizzo mb(); 257*a2a74091SLuigi Rizzo CSB_WRITE(ptr, hwtail, hwtail); 258*a2a74091SLuigi Rizzo } 259a82ab411SLuigi Rizzo 260*a2a74091SLuigi Rizzo /* Host netmap: Read kring pointers (head, cur, sync_flags) from the CSB. 261*a2a74091SLuigi Rizzo * This routine is coupled with ptnetmap_guest_write_kring_csb(). */ 262*a2a74091SLuigi Rizzo static inline void 263*a2a74091SLuigi Rizzo ptnetmap_host_read_kring_csb(struct ptnet_ring __user *ptr, 264*a2a74091SLuigi Rizzo struct netmap_ring *shadow_ring, 265*a2a74091SLuigi Rizzo uint32_t num_slots) 266*a2a74091SLuigi Rizzo { 267*a2a74091SLuigi Rizzo /* 268*a2a74091SLuigi Rizzo * We place a memory barrier to make sure that the update of head never 269*a2a74091SLuigi Rizzo * overtakes the update of cur. 270*a2a74091SLuigi Rizzo * (see explanation in ptnetmap_guest_write_kring_csb). 271*a2a74091SLuigi Rizzo */ 272*a2a74091SLuigi Rizzo CSB_READ(ptr, head, shadow_ring->head); 273*a2a74091SLuigi Rizzo mb(); 274*a2a74091SLuigi Rizzo CSB_READ(ptr, cur, shadow_ring->cur); 275*a2a74091SLuigi Rizzo CSB_READ(ptr, sync_flags, shadow_ring->flags); 276a82ab411SLuigi Rizzo } 277a82ab411SLuigi Rizzo 278a82ab411SLuigi Rizzo #endif /* WITH_PTNETMAP_HOST */ 279a82ab411SLuigi Rizzo 280a82ab411SLuigi Rizzo #endif /* NETMAP_VIRT_H */ 281