13a977deeSAkihiko Odaki /* 23a977deeSAkihiko Odaki * QEMU Intel 82576 SR/IOV Ethernet Controller Emulation 33a977deeSAkihiko Odaki * 43a977deeSAkihiko Odaki * Datasheet: 53a977deeSAkihiko Odaki * https://www.intel.com/content/dam/www/public/us/en/documents/datasheets/82576eg-gbe-datasheet.pdf 63a977deeSAkihiko Odaki * 73a977deeSAkihiko Odaki * Copyright (c) 2020-2023 Red Hat, Inc. 83a977deeSAkihiko Odaki * Copyright (c) 2015 Ravello Systems LTD (http://ravellosystems.com) 93a977deeSAkihiko Odaki * Developed by Daynix Computing LTD (http://www.daynix.com) 103a977deeSAkihiko Odaki * 113a977deeSAkihiko Odaki * Authors: 123a977deeSAkihiko Odaki * Akihiko Odaki <akihiko.odaki@daynix.com> 133a977deeSAkihiko Odaki * Gal Hammmer <gal.hammer@sap.com> 143a977deeSAkihiko Odaki * Marcel Apfelbaum <marcel.apfelbaum@gmail.com> 153a977deeSAkihiko Odaki * Dmitry Fleytman <dmitry@daynix.com> 163a977deeSAkihiko Odaki * Leonid Bloch <leonid@daynix.com> 173a977deeSAkihiko Odaki * Yan Vugenfirer <yan@daynix.com> 183a977deeSAkihiko Odaki * 193a977deeSAkihiko Odaki * Based on work done by: 203a977deeSAkihiko Odaki * Nir Peleg, Tutis Systems Ltd. for Qumranet Inc. 213a977deeSAkihiko Odaki * Copyright (c) 2008 Qumranet 223a977deeSAkihiko Odaki * Based on work done by: 233a977deeSAkihiko Odaki * Copyright (c) 2007 Dan Aloni 243a977deeSAkihiko Odaki * Copyright (c) 2004 Antony T Curtis 253a977deeSAkihiko Odaki * 263a977deeSAkihiko Odaki * This library is free software; you can redistribute it and/or 273a977deeSAkihiko Odaki * modify it under the terms of the GNU Lesser General Public 283a977deeSAkihiko Odaki * License as published by the Free Software Foundation; either 293a977deeSAkihiko Odaki * version 2.1 of the License, or (at your option) any later version. 303a977deeSAkihiko Odaki * 313a977deeSAkihiko Odaki * This library is distributed in the hope that it will be useful, 323a977deeSAkihiko Odaki * but WITHOUT ANY WARRANTY; without even the implied warranty of 333a977deeSAkihiko Odaki * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 343a977deeSAkihiko Odaki * Lesser General Public License for more details. 353a977deeSAkihiko Odaki * 363a977deeSAkihiko Odaki * You should have received a copy of the GNU Lesser General Public 373a977deeSAkihiko Odaki * License along with this library; if not, see <http://www.gnu.org/licenses/>. 383a977deeSAkihiko Odaki */ 393a977deeSAkihiko Odaki 403a977deeSAkihiko Odaki #include "qemu/osdep.h" 413a977deeSAkihiko Odaki #include "hw/hw.h" 423a977deeSAkihiko Odaki #include "hw/net/mii.h" 433a977deeSAkihiko Odaki #include "hw/pci/pci_device.h" 443a977deeSAkihiko Odaki #include "hw/pci/pcie.h" 453a977deeSAkihiko Odaki #include "hw/pci/msix.h" 463a977deeSAkihiko Odaki #include "net/eth.h" 473a977deeSAkihiko Odaki #include "net/net.h" 483a977deeSAkihiko Odaki #include "igb_common.h" 493a977deeSAkihiko Odaki #include "igb_core.h" 503a977deeSAkihiko Odaki #include "trace.h" 513a977deeSAkihiko Odaki #include "qapi/error.h" 523a977deeSAkihiko Odaki 533a977deeSAkihiko Odaki OBJECT_DECLARE_SIMPLE_TYPE(IgbVfState, IGBVF) 543a977deeSAkihiko Odaki 553a977deeSAkihiko Odaki struct IgbVfState { 563a977deeSAkihiko Odaki PCIDevice parent_obj; 573a977deeSAkihiko Odaki 583a977deeSAkihiko Odaki MemoryRegion mmio; 593a977deeSAkihiko Odaki MemoryRegion msix; 603a977deeSAkihiko Odaki }; 613a977deeSAkihiko Odaki 623a977deeSAkihiko Odaki static hwaddr vf_to_pf_addr(hwaddr addr, uint16_t vfn, bool write) 633a977deeSAkihiko Odaki { 643a977deeSAkihiko Odaki switch (addr) { 653a977deeSAkihiko Odaki case E1000_CTRL: 663a977deeSAkihiko Odaki case E1000_CTRL_DUP: 673a977deeSAkihiko Odaki return E1000_PVTCTRL(vfn); 683a977deeSAkihiko Odaki case E1000_EICS: 693a977deeSAkihiko Odaki return E1000_PVTEICS(vfn); 703a977deeSAkihiko Odaki case E1000_EIMS: 713a977deeSAkihiko Odaki return E1000_PVTEIMS(vfn); 723a977deeSAkihiko Odaki case E1000_EIMC: 733a977deeSAkihiko Odaki return E1000_PVTEIMC(vfn); 743a977deeSAkihiko Odaki case E1000_EIAC: 753a977deeSAkihiko Odaki return E1000_PVTEIAC(vfn); 763a977deeSAkihiko Odaki case E1000_EIAM: 773a977deeSAkihiko Odaki return E1000_PVTEIAM(vfn); 783a977deeSAkihiko Odaki case E1000_EICR: 793a977deeSAkihiko Odaki return E1000_PVTEICR(vfn); 803a977deeSAkihiko Odaki case E1000_EITR(0): 813a977deeSAkihiko Odaki case E1000_EITR(1): 823a977deeSAkihiko Odaki case E1000_EITR(2): 833a977deeSAkihiko Odaki return E1000_EITR(22) + (addr - E1000_EITR(0)) - vfn * 0xC; 843a977deeSAkihiko Odaki case E1000_IVAR0: 853a977deeSAkihiko Odaki return E1000_VTIVAR + vfn * 4; 863a977deeSAkihiko Odaki case E1000_IVAR_MISC: 873a977deeSAkihiko Odaki return E1000_VTIVAR_MISC + vfn * 4; 883a977deeSAkihiko Odaki case 0x0F04: /* PBACL */ 893a977deeSAkihiko Odaki return E1000_PBACLR; 903a977deeSAkihiko Odaki case 0x0F0C: /* PSRTYPE */ 913a977deeSAkihiko Odaki return E1000_PSRTYPE(vfn); 923a977deeSAkihiko Odaki case E1000_V2PMAILBOX(0): 933a977deeSAkihiko Odaki return E1000_V2PMAILBOX(vfn); 943a977deeSAkihiko Odaki case E1000_VMBMEM(0) ... E1000_VMBMEM(0) + 0x3F: 953a977deeSAkihiko Odaki return addr + vfn * 0x40; 963a977deeSAkihiko Odaki case E1000_RDBAL_A(0): 973a977deeSAkihiko Odaki return E1000_RDBAL(vfn); 983a977deeSAkihiko Odaki case E1000_RDBAL_A(1): 993a977deeSAkihiko Odaki return E1000_RDBAL(vfn + IGB_MAX_VF_FUNCTIONS); 1003a977deeSAkihiko Odaki case E1000_RDBAH_A(0): 1013a977deeSAkihiko Odaki return E1000_RDBAH(vfn); 1023a977deeSAkihiko Odaki case E1000_RDBAH_A(1): 1033a977deeSAkihiko Odaki return E1000_RDBAH(vfn + IGB_MAX_VF_FUNCTIONS); 1043a977deeSAkihiko Odaki case E1000_RDLEN_A(0): 1053a977deeSAkihiko Odaki return E1000_RDLEN(vfn); 1063a977deeSAkihiko Odaki case E1000_RDLEN_A(1): 1073a977deeSAkihiko Odaki return E1000_RDLEN(vfn + IGB_MAX_VF_FUNCTIONS); 1083a977deeSAkihiko Odaki case E1000_SRRCTL_A(0): 1093a977deeSAkihiko Odaki return E1000_SRRCTL(vfn); 1103a977deeSAkihiko Odaki case E1000_SRRCTL_A(1): 1113a977deeSAkihiko Odaki return E1000_SRRCTL(vfn + IGB_MAX_VF_FUNCTIONS); 1123a977deeSAkihiko Odaki case E1000_RDH_A(0): 1133a977deeSAkihiko Odaki return E1000_RDH(vfn); 1143a977deeSAkihiko Odaki case E1000_RDH_A(1): 1153a977deeSAkihiko Odaki return E1000_RDH(vfn + IGB_MAX_VF_FUNCTIONS); 1163a977deeSAkihiko Odaki case E1000_RXCTL_A(0): 1173a977deeSAkihiko Odaki return E1000_RXCTL(vfn); 1183a977deeSAkihiko Odaki case E1000_RXCTL_A(1): 1193a977deeSAkihiko Odaki return E1000_RXCTL(vfn + IGB_MAX_VF_FUNCTIONS); 1203a977deeSAkihiko Odaki case E1000_RDT_A(0): 1213a977deeSAkihiko Odaki return E1000_RDT(vfn); 1223a977deeSAkihiko Odaki case E1000_RDT_A(1): 1233a977deeSAkihiko Odaki return E1000_RDT(vfn + IGB_MAX_VF_FUNCTIONS); 1243a977deeSAkihiko Odaki case E1000_RXDCTL_A(0): 1253a977deeSAkihiko Odaki return E1000_RXDCTL(vfn); 1263a977deeSAkihiko Odaki case E1000_RXDCTL_A(1): 1273a977deeSAkihiko Odaki return E1000_RXDCTL(vfn + IGB_MAX_VF_FUNCTIONS); 1283a977deeSAkihiko Odaki case E1000_RQDPC_A(0): 1293a977deeSAkihiko Odaki return E1000_RQDPC(vfn); 1303a977deeSAkihiko Odaki case E1000_RQDPC_A(1): 1313a977deeSAkihiko Odaki return E1000_RQDPC(vfn + IGB_MAX_VF_FUNCTIONS); 1323a977deeSAkihiko Odaki case E1000_TDBAL_A(0): 1333a977deeSAkihiko Odaki return E1000_TDBAL(vfn); 1343a977deeSAkihiko Odaki case E1000_TDBAL_A(1): 1353a977deeSAkihiko Odaki return E1000_TDBAL(vfn + IGB_MAX_VF_FUNCTIONS); 1363a977deeSAkihiko Odaki case E1000_TDBAH_A(0): 1373a977deeSAkihiko Odaki return E1000_TDBAH(vfn); 1383a977deeSAkihiko Odaki case E1000_TDBAH_A(1): 1393a977deeSAkihiko Odaki return E1000_TDBAH(vfn + IGB_MAX_VF_FUNCTIONS); 1403a977deeSAkihiko Odaki case E1000_TDLEN_A(0): 1413a977deeSAkihiko Odaki return E1000_TDLEN(vfn); 1423a977deeSAkihiko Odaki case E1000_TDLEN_A(1): 1433a977deeSAkihiko Odaki return E1000_TDLEN(vfn + IGB_MAX_VF_FUNCTIONS); 1443a977deeSAkihiko Odaki case E1000_TDH_A(0): 1453a977deeSAkihiko Odaki return E1000_TDH(vfn); 1463a977deeSAkihiko Odaki case E1000_TDH_A(1): 1473a977deeSAkihiko Odaki return E1000_TDH(vfn + IGB_MAX_VF_FUNCTIONS); 1483a977deeSAkihiko Odaki case E1000_TXCTL_A(0): 1493a977deeSAkihiko Odaki return E1000_TXCTL(vfn); 1503a977deeSAkihiko Odaki case E1000_TXCTL_A(1): 1513a977deeSAkihiko Odaki return E1000_TXCTL(vfn + IGB_MAX_VF_FUNCTIONS); 1523a977deeSAkihiko Odaki case E1000_TDT_A(0): 1533a977deeSAkihiko Odaki return E1000_TDT(vfn); 1543a977deeSAkihiko Odaki case E1000_TDT_A(1): 1553a977deeSAkihiko Odaki return E1000_TDT(vfn + IGB_MAX_VF_FUNCTIONS); 1563a977deeSAkihiko Odaki case E1000_TXDCTL_A(0): 1573a977deeSAkihiko Odaki return E1000_TXDCTL(vfn); 1583a977deeSAkihiko Odaki case E1000_TXDCTL_A(1): 1593a977deeSAkihiko Odaki return E1000_TXDCTL(vfn + IGB_MAX_VF_FUNCTIONS); 1603a977deeSAkihiko Odaki case E1000_TDWBAL_A(0): 1613a977deeSAkihiko Odaki return E1000_TDWBAL(vfn); 1623a977deeSAkihiko Odaki case E1000_TDWBAL_A(1): 1633a977deeSAkihiko Odaki return E1000_TDWBAL(vfn + IGB_MAX_VF_FUNCTIONS); 1643a977deeSAkihiko Odaki case E1000_TDWBAH_A(0): 1653a977deeSAkihiko Odaki return E1000_TDWBAH(vfn); 1663a977deeSAkihiko Odaki case E1000_TDWBAH_A(1): 1673a977deeSAkihiko Odaki return E1000_TDWBAH(vfn + IGB_MAX_VF_FUNCTIONS); 1683a977deeSAkihiko Odaki case E1000_VFGPRC: 1693a977deeSAkihiko Odaki return E1000_PVFGPRC(vfn); 1703a977deeSAkihiko Odaki case E1000_VFGPTC: 1713a977deeSAkihiko Odaki return E1000_PVFGPTC(vfn); 1723a977deeSAkihiko Odaki case E1000_VFGORC: 1733a977deeSAkihiko Odaki return E1000_PVFGORC(vfn); 1743a977deeSAkihiko Odaki case E1000_VFGOTC: 1753a977deeSAkihiko Odaki return E1000_PVFGOTC(vfn); 1763a977deeSAkihiko Odaki case E1000_VFMPRC: 1773a977deeSAkihiko Odaki return E1000_PVFMPRC(vfn); 1783a977deeSAkihiko Odaki case E1000_VFGPRLBC: 1793a977deeSAkihiko Odaki return E1000_PVFGPRLBC(vfn); 1803a977deeSAkihiko Odaki case E1000_VFGPTLBC: 1813a977deeSAkihiko Odaki return E1000_PVFGPTLBC(vfn); 1823a977deeSAkihiko Odaki case E1000_VFGORLBC: 1833a977deeSAkihiko Odaki return E1000_PVFGORLBC(vfn); 1843a977deeSAkihiko Odaki case E1000_VFGOTLBC: 1853a977deeSAkihiko Odaki return E1000_PVFGOTLBC(vfn); 1863a977deeSAkihiko Odaki case E1000_STATUS: 1873a977deeSAkihiko Odaki case E1000_FRTIMER: 1883a977deeSAkihiko Odaki if (write) { 1893a977deeSAkihiko Odaki return HWADDR_MAX; 1903a977deeSAkihiko Odaki } 1913a977deeSAkihiko Odaki /* fallthrough */ 1923a977deeSAkihiko Odaki case 0x34E8: /* PBTWAC */ 1933a977deeSAkihiko Odaki case 0x24E8: /* PBRWAC */ 1943a977deeSAkihiko Odaki return addr; 1953a977deeSAkihiko Odaki } 1963a977deeSAkihiko Odaki 1973a977deeSAkihiko Odaki trace_igbvf_wrn_io_addr_unknown(addr); 1983a977deeSAkihiko Odaki 1993a977deeSAkihiko Odaki return HWADDR_MAX; 2003a977deeSAkihiko Odaki } 2013a977deeSAkihiko Odaki 2023a977deeSAkihiko Odaki static void igbvf_write_config(PCIDevice *dev, uint32_t addr, uint32_t val, 2033a977deeSAkihiko Odaki int len) 2043a977deeSAkihiko Odaki { 2053a977deeSAkihiko Odaki trace_igbvf_write_config(addr, val, len); 2063a977deeSAkihiko Odaki pci_default_write_config(dev, addr, val, len); 2073a977deeSAkihiko Odaki } 2083a977deeSAkihiko Odaki 2093a977deeSAkihiko Odaki static uint64_t igbvf_mmio_read(void *opaque, hwaddr addr, unsigned size) 2103a977deeSAkihiko Odaki { 2113a977deeSAkihiko Odaki PCIDevice *vf = PCI_DEVICE(opaque); 2123a977deeSAkihiko Odaki PCIDevice *pf = pcie_sriov_get_pf(vf); 2133a977deeSAkihiko Odaki 2143a977deeSAkihiko Odaki addr = vf_to_pf_addr(addr, pcie_sriov_vf_number(vf), false); 2153a977deeSAkihiko Odaki return addr == HWADDR_MAX ? 0 : igb_mmio_read(pf, addr, size); 2163a977deeSAkihiko Odaki } 2173a977deeSAkihiko Odaki 2183a977deeSAkihiko Odaki static void igbvf_mmio_write(void *opaque, hwaddr addr, uint64_t val, 2193a977deeSAkihiko Odaki unsigned size) 2203a977deeSAkihiko Odaki { 2213a977deeSAkihiko Odaki PCIDevice *vf = PCI_DEVICE(opaque); 2223a977deeSAkihiko Odaki PCIDevice *pf = pcie_sriov_get_pf(vf); 2233a977deeSAkihiko Odaki 2243a977deeSAkihiko Odaki addr = vf_to_pf_addr(addr, pcie_sriov_vf_number(vf), true); 2253a977deeSAkihiko Odaki if (addr != HWADDR_MAX) { 2263a977deeSAkihiko Odaki igb_mmio_write(pf, addr, val, size); 2273a977deeSAkihiko Odaki } 2283a977deeSAkihiko Odaki } 2293a977deeSAkihiko Odaki 2303a977deeSAkihiko Odaki static const MemoryRegionOps mmio_ops = { 2313a977deeSAkihiko Odaki .read = igbvf_mmio_read, 2323a977deeSAkihiko Odaki .write = igbvf_mmio_write, 2333a977deeSAkihiko Odaki .endianness = DEVICE_LITTLE_ENDIAN, 2343a977deeSAkihiko Odaki .impl = { 2353a977deeSAkihiko Odaki .min_access_size = 4, 2363a977deeSAkihiko Odaki .max_access_size = 4, 2373a977deeSAkihiko Odaki }, 2383a977deeSAkihiko Odaki }; 2393a977deeSAkihiko Odaki 2403a977deeSAkihiko Odaki static void igbvf_pci_realize(PCIDevice *dev, Error **errp) 2413a977deeSAkihiko Odaki { 2423a977deeSAkihiko Odaki IgbVfState *s = IGBVF(dev); 2433a977deeSAkihiko Odaki int ret; 2443a977deeSAkihiko Odaki int i; 2453a977deeSAkihiko Odaki 2463a977deeSAkihiko Odaki dev->config_write = igbvf_write_config; 2473a977deeSAkihiko Odaki 2483a977deeSAkihiko Odaki memory_region_init_io(&s->mmio, OBJECT(dev), &mmio_ops, s, "igbvf-mmio", 2493a977deeSAkihiko Odaki IGBVF_MMIO_SIZE); 2503a977deeSAkihiko Odaki pcie_sriov_vf_register_bar(dev, IGBVF_MMIO_BAR_IDX, &s->mmio); 2513a977deeSAkihiko Odaki 2523a977deeSAkihiko Odaki memory_region_init(&s->msix, OBJECT(dev), "igbvf-msix", IGBVF_MSIX_SIZE); 2533a977deeSAkihiko Odaki pcie_sriov_vf_register_bar(dev, IGBVF_MSIX_BAR_IDX, &s->msix); 2543a977deeSAkihiko Odaki 2553a977deeSAkihiko Odaki ret = msix_init(dev, IGBVF_MSIX_VEC_NUM, &s->msix, IGBVF_MSIX_BAR_IDX, 0, 2563a977deeSAkihiko Odaki &s->msix, IGBVF_MSIX_BAR_IDX, 0x2000, 0x70, errp); 2573a977deeSAkihiko Odaki if (ret) { 2583a977deeSAkihiko Odaki return; 2593a977deeSAkihiko Odaki } 2603a977deeSAkihiko Odaki 2613a977deeSAkihiko Odaki for (i = 0; i < IGBVF_MSIX_VEC_NUM; i++) { 2623a977deeSAkihiko Odaki msix_vector_use(dev, i); 2633a977deeSAkihiko Odaki } 2643a977deeSAkihiko Odaki 2653a977deeSAkihiko Odaki if (pcie_endpoint_cap_init(dev, 0xa0) < 0) { 2663a977deeSAkihiko Odaki hw_error("Failed to initialize PCIe capability"); 2673a977deeSAkihiko Odaki } 2683a977deeSAkihiko Odaki 2693a977deeSAkihiko Odaki if (pcie_aer_init(dev, 1, 0x100, 0x40, errp) < 0) { 2703a977deeSAkihiko Odaki hw_error("Failed to initialize AER capability"); 2713a977deeSAkihiko Odaki } 2723a977deeSAkihiko Odaki 273*445416e3SAkihiko Odaki pcie_ari_init(dev, 0x150); 2743a977deeSAkihiko Odaki } 2753a977deeSAkihiko Odaki 2763a977deeSAkihiko Odaki static void igbvf_pci_uninit(PCIDevice *dev) 2773a977deeSAkihiko Odaki { 2783a977deeSAkihiko Odaki IgbVfState *s = IGBVF(dev); 2793a977deeSAkihiko Odaki 2803a977deeSAkihiko Odaki pcie_aer_exit(dev); 2813a977deeSAkihiko Odaki pcie_cap_exit(dev); 2823a977deeSAkihiko Odaki msix_unuse_all_vectors(dev); 2833a977deeSAkihiko Odaki msix_uninit(dev, &s->msix, &s->msix); 2843a977deeSAkihiko Odaki } 2853a977deeSAkihiko Odaki 2863a977deeSAkihiko Odaki static void igbvf_class_init(ObjectClass *class, void *data) 2873a977deeSAkihiko Odaki { 2883a977deeSAkihiko Odaki DeviceClass *dc = DEVICE_CLASS(class); 2893a977deeSAkihiko Odaki PCIDeviceClass *c = PCI_DEVICE_CLASS(class); 2903a977deeSAkihiko Odaki 2913a977deeSAkihiko Odaki c->realize = igbvf_pci_realize; 2923a977deeSAkihiko Odaki c->exit = igbvf_pci_uninit; 2933a977deeSAkihiko Odaki c->vendor_id = PCI_VENDOR_ID_INTEL; 2943a977deeSAkihiko Odaki c->device_id = E1000_DEV_ID_82576_VF; 2953a977deeSAkihiko Odaki c->revision = 1; 2963a977deeSAkihiko Odaki c->class_id = PCI_CLASS_NETWORK_ETHERNET; 2973a977deeSAkihiko Odaki 2983a977deeSAkihiko Odaki dc->desc = "Intel 82576 Virtual Function"; 2993a977deeSAkihiko Odaki dc->user_creatable = false; 3003a977deeSAkihiko Odaki 3013a977deeSAkihiko Odaki set_bit(DEVICE_CATEGORY_NETWORK, dc->categories); 3023a977deeSAkihiko Odaki } 3033a977deeSAkihiko Odaki 3043a977deeSAkihiko Odaki static const TypeInfo igbvf_info = { 3053a977deeSAkihiko Odaki .name = TYPE_IGBVF, 3063a977deeSAkihiko Odaki .parent = TYPE_PCI_DEVICE, 3073a977deeSAkihiko Odaki .instance_size = sizeof(IgbVfState), 3083a977deeSAkihiko Odaki .class_init = igbvf_class_init, 3093a977deeSAkihiko Odaki .interfaces = (InterfaceInfo[]) { 3103a977deeSAkihiko Odaki { INTERFACE_PCIE_DEVICE }, 3113a977deeSAkihiko Odaki { } 3123a977deeSAkihiko Odaki }, 3133a977deeSAkihiko Odaki }; 3143a977deeSAkihiko Odaki 3153a977deeSAkihiko Odaki static void igb_register_types(void) 3163a977deeSAkihiko Odaki { 3173a977deeSAkihiko Odaki type_register_static(&igbvf_info); 3183a977deeSAkihiko Odaki } 3193a977deeSAkihiko Odaki 3203a977deeSAkihiko Odaki type_init(igb_register_types) 321