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 "qemu/units.h" 423a977deeSAkihiko Odaki #include "net/eth.h" 433a977deeSAkihiko Odaki #include "net/net.h" 443a977deeSAkihiko Odaki #include "net/tap.h" 453a977deeSAkihiko Odaki #include "qemu/module.h" 463a977deeSAkihiko Odaki #include "qemu/range.h" 473a977deeSAkihiko Odaki #include "sysemu/sysemu.h" 483a977deeSAkihiko Odaki #include "hw/hw.h" 493a977deeSAkihiko Odaki #include "hw/net/mii.h" 503a977deeSAkihiko Odaki #include "hw/pci/pci.h" 513a977deeSAkihiko Odaki #include "hw/pci/pcie.h" 523a977deeSAkihiko Odaki #include "hw/pci/pcie_sriov.h" 533a977deeSAkihiko Odaki #include "hw/pci/msi.h" 543a977deeSAkihiko Odaki #include "hw/pci/msix.h" 553a977deeSAkihiko Odaki #include "hw/qdev-properties.h" 563a977deeSAkihiko Odaki #include "migration/vmstate.h" 573a977deeSAkihiko Odaki 583a977deeSAkihiko Odaki #include "igb_common.h" 593a977deeSAkihiko Odaki #include "igb_core.h" 603a977deeSAkihiko Odaki 613a977deeSAkihiko Odaki #include "trace.h" 623a977deeSAkihiko Odaki #include "qapi/error.h" 633a977deeSAkihiko Odaki #include "qom/object.h" 643a977deeSAkihiko Odaki 653a977deeSAkihiko Odaki #define TYPE_IGB "igb" 663a977deeSAkihiko Odaki OBJECT_DECLARE_SIMPLE_TYPE(IGBState, IGB) 673a977deeSAkihiko Odaki 683a977deeSAkihiko Odaki struct IGBState { 693a977deeSAkihiko Odaki PCIDevice parent_obj; 703a977deeSAkihiko Odaki NICState *nic; 713a977deeSAkihiko Odaki NICConf conf; 723a977deeSAkihiko Odaki 733a977deeSAkihiko Odaki MemoryRegion mmio; 743a977deeSAkihiko Odaki MemoryRegion flash; 753a977deeSAkihiko Odaki MemoryRegion io; 763a977deeSAkihiko Odaki MemoryRegion msix; 773a977deeSAkihiko Odaki 783a977deeSAkihiko Odaki uint32_t ioaddr; 793a977deeSAkihiko Odaki 803a977deeSAkihiko Odaki IGBCore core; 81d90014fcSCédric Le Goater bool has_flr; 823a977deeSAkihiko Odaki }; 833a977deeSAkihiko Odaki 843a977deeSAkihiko Odaki #define IGB_CAP_SRIOV_OFFSET (0x160) 853a977deeSAkihiko Odaki #define IGB_VF_OFFSET (0x80) 863a977deeSAkihiko Odaki #define IGB_VF_STRIDE (2) 873a977deeSAkihiko Odaki 883a977deeSAkihiko Odaki #define E1000E_MMIO_IDX 0 893a977deeSAkihiko Odaki #define E1000E_FLASH_IDX 1 903a977deeSAkihiko Odaki #define E1000E_IO_IDX 2 913a977deeSAkihiko Odaki #define E1000E_MSIX_IDX 3 923a977deeSAkihiko Odaki 933a977deeSAkihiko Odaki #define E1000E_MMIO_SIZE (128 * KiB) 943a977deeSAkihiko Odaki #define E1000E_FLASH_SIZE (128 * KiB) 953a977deeSAkihiko Odaki #define E1000E_IO_SIZE (32) 963a977deeSAkihiko Odaki #define E1000E_MSIX_SIZE (16 * KiB) 973a977deeSAkihiko Odaki 983a977deeSAkihiko Odaki static void igb_write_config(PCIDevice *dev, uint32_t addr, 993a977deeSAkihiko Odaki uint32_t val, int len) 1003a977deeSAkihiko Odaki { 1013a977deeSAkihiko Odaki IGBState *s = IGB(dev); 1023a977deeSAkihiko Odaki 1033a977deeSAkihiko Odaki trace_igb_write_config(addr, val, len); 1043a977deeSAkihiko Odaki pci_default_write_config(dev, addr, val, len); 105d90014fcSCédric Le Goater if (s->has_flr) { 106d90014fcSCédric Le Goater pcie_cap_flr_write_config(dev, addr, val, len); 107d90014fcSCédric Le Goater } 1083a977deeSAkihiko Odaki 1093a977deeSAkihiko Odaki if (range_covers_byte(addr, len, PCI_COMMAND) && 1103a977deeSAkihiko Odaki (dev->config[PCI_COMMAND] & PCI_COMMAND_MASTER)) { 1113a977deeSAkihiko Odaki igb_start_recv(&s->core); 1123a977deeSAkihiko Odaki } 1133a977deeSAkihiko Odaki } 1143a977deeSAkihiko Odaki 1153a977deeSAkihiko Odaki uint64_t 1163a977deeSAkihiko Odaki igb_mmio_read(void *opaque, hwaddr addr, unsigned size) 1173a977deeSAkihiko Odaki { 1183a977deeSAkihiko Odaki IGBState *s = opaque; 1193a977deeSAkihiko Odaki return igb_core_read(&s->core, addr, size); 1203a977deeSAkihiko Odaki } 1213a977deeSAkihiko Odaki 1223a977deeSAkihiko Odaki void 1233a977deeSAkihiko Odaki igb_mmio_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) 1243a977deeSAkihiko Odaki { 1253a977deeSAkihiko Odaki IGBState *s = opaque; 1263a977deeSAkihiko Odaki igb_core_write(&s->core, addr, val, size); 1273a977deeSAkihiko Odaki } 1283a977deeSAkihiko Odaki 129fe73674aSCédric Le Goater void igb_vf_reset(void *opaque, uint16_t vfn) 130fe73674aSCédric Le Goater { 131fe73674aSCédric Le Goater IGBState *s = opaque; 132fe73674aSCédric Le Goater igb_core_vf_reset(&s->core, vfn); 133fe73674aSCédric Le Goater } 134fe73674aSCédric Le Goater 1353a977deeSAkihiko Odaki static bool 1363a977deeSAkihiko Odaki igb_io_get_reg_index(IGBState *s, uint32_t *idx) 1373a977deeSAkihiko Odaki { 1383a977deeSAkihiko Odaki if (s->ioaddr < 0x1FFFF) { 1393a977deeSAkihiko Odaki *idx = s->ioaddr; 1403a977deeSAkihiko Odaki return true; 1413a977deeSAkihiko Odaki } 1423a977deeSAkihiko Odaki 1433a977deeSAkihiko Odaki if (s->ioaddr < 0x7FFFF) { 1443a977deeSAkihiko Odaki trace_e1000e_wrn_io_addr_undefined(s->ioaddr); 1453a977deeSAkihiko Odaki return false; 1463a977deeSAkihiko Odaki } 1473a977deeSAkihiko Odaki 1483a977deeSAkihiko Odaki if (s->ioaddr < 0xFFFFF) { 1493a977deeSAkihiko Odaki trace_e1000e_wrn_io_addr_flash(s->ioaddr); 1503a977deeSAkihiko Odaki return false; 1513a977deeSAkihiko Odaki } 1523a977deeSAkihiko Odaki 1533a977deeSAkihiko Odaki trace_e1000e_wrn_io_addr_unknown(s->ioaddr); 1543a977deeSAkihiko Odaki return false; 1553a977deeSAkihiko Odaki } 1563a977deeSAkihiko Odaki 1573a977deeSAkihiko Odaki static uint64_t 1583a977deeSAkihiko Odaki igb_io_read(void *opaque, hwaddr addr, unsigned size) 1593a977deeSAkihiko Odaki { 1603a977deeSAkihiko Odaki IGBState *s = opaque; 1613a977deeSAkihiko Odaki uint32_t idx = 0; 1623a977deeSAkihiko Odaki uint64_t val; 1633a977deeSAkihiko Odaki 1643a977deeSAkihiko Odaki switch (addr) { 1653a977deeSAkihiko Odaki case E1000_IOADDR: 1663a977deeSAkihiko Odaki trace_e1000e_io_read_addr(s->ioaddr); 1673a977deeSAkihiko Odaki return s->ioaddr; 1683a977deeSAkihiko Odaki case E1000_IODATA: 1693a977deeSAkihiko Odaki if (igb_io_get_reg_index(s, &idx)) { 1703a977deeSAkihiko Odaki val = igb_core_read(&s->core, idx, sizeof(val)); 1713a977deeSAkihiko Odaki trace_e1000e_io_read_data(idx, val); 1723a977deeSAkihiko Odaki return val; 1733a977deeSAkihiko Odaki } 1743a977deeSAkihiko Odaki return 0; 1753a977deeSAkihiko Odaki default: 1763a977deeSAkihiko Odaki trace_e1000e_wrn_io_read_unknown(addr); 1773a977deeSAkihiko Odaki return 0; 1783a977deeSAkihiko Odaki } 1793a977deeSAkihiko Odaki } 1803a977deeSAkihiko Odaki 1813a977deeSAkihiko Odaki static void 1823a977deeSAkihiko Odaki igb_io_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) 1833a977deeSAkihiko Odaki { 1843a977deeSAkihiko Odaki IGBState *s = opaque; 1853a977deeSAkihiko Odaki uint32_t idx = 0; 1863a977deeSAkihiko Odaki 1873a977deeSAkihiko Odaki switch (addr) { 1883a977deeSAkihiko Odaki case E1000_IOADDR: 1893a977deeSAkihiko Odaki trace_e1000e_io_write_addr(val); 1903a977deeSAkihiko Odaki s->ioaddr = (uint32_t) val; 1913a977deeSAkihiko Odaki return; 1923a977deeSAkihiko Odaki case E1000_IODATA: 1933a977deeSAkihiko Odaki if (igb_io_get_reg_index(s, &idx)) { 1943a977deeSAkihiko Odaki trace_e1000e_io_write_data(idx, val); 1953a977deeSAkihiko Odaki igb_core_write(&s->core, idx, val, sizeof(val)); 1963a977deeSAkihiko Odaki } 1973a977deeSAkihiko Odaki return; 1983a977deeSAkihiko Odaki default: 1993a977deeSAkihiko Odaki trace_e1000e_wrn_io_write_unknown(addr); 2003a977deeSAkihiko Odaki return; 2013a977deeSAkihiko Odaki } 2023a977deeSAkihiko Odaki } 2033a977deeSAkihiko Odaki 2043a977deeSAkihiko Odaki static const MemoryRegionOps mmio_ops = { 2053a977deeSAkihiko Odaki .read = igb_mmio_read, 2063a977deeSAkihiko Odaki .write = igb_mmio_write, 2073a977deeSAkihiko Odaki .endianness = DEVICE_LITTLE_ENDIAN, 2083a977deeSAkihiko Odaki .impl = { 2093a977deeSAkihiko Odaki .min_access_size = 4, 2103a977deeSAkihiko Odaki .max_access_size = 4, 2113a977deeSAkihiko Odaki }, 2123a977deeSAkihiko Odaki }; 2133a977deeSAkihiko Odaki 2143a977deeSAkihiko Odaki static const MemoryRegionOps io_ops = { 2153a977deeSAkihiko Odaki .read = igb_io_read, 2163a977deeSAkihiko Odaki .write = igb_io_write, 2173a977deeSAkihiko Odaki .endianness = DEVICE_LITTLE_ENDIAN, 2183a977deeSAkihiko Odaki .impl = { 2193a977deeSAkihiko Odaki .min_access_size = 4, 2203a977deeSAkihiko Odaki .max_access_size = 4, 2213a977deeSAkihiko Odaki }, 2223a977deeSAkihiko Odaki }; 2233a977deeSAkihiko Odaki 2243a977deeSAkihiko Odaki static bool 2253a977deeSAkihiko Odaki igb_nc_can_receive(NetClientState *nc) 2263a977deeSAkihiko Odaki { 2273a977deeSAkihiko Odaki IGBState *s = qemu_get_nic_opaque(nc); 2283a977deeSAkihiko Odaki return igb_can_receive(&s->core); 2293a977deeSAkihiko Odaki } 2303a977deeSAkihiko Odaki 2313a977deeSAkihiko Odaki static ssize_t 2323a977deeSAkihiko Odaki igb_nc_receive_iov(NetClientState *nc, const struct iovec *iov, int iovcnt) 2333a977deeSAkihiko Odaki { 2343a977deeSAkihiko Odaki IGBState *s = qemu_get_nic_opaque(nc); 2353a977deeSAkihiko Odaki return igb_receive_iov(&s->core, iov, iovcnt); 2363a977deeSAkihiko Odaki } 2373a977deeSAkihiko Odaki 2383a977deeSAkihiko Odaki static ssize_t 2393a977deeSAkihiko Odaki igb_nc_receive(NetClientState *nc, const uint8_t *buf, size_t size) 2403a977deeSAkihiko Odaki { 2413a977deeSAkihiko Odaki IGBState *s = qemu_get_nic_opaque(nc); 2423a977deeSAkihiko Odaki return igb_receive(&s->core, buf, size); 2433a977deeSAkihiko Odaki } 2443a977deeSAkihiko Odaki 2453a977deeSAkihiko Odaki static void 2463a977deeSAkihiko Odaki igb_set_link_status(NetClientState *nc) 2473a977deeSAkihiko Odaki { 2483a977deeSAkihiko Odaki IGBState *s = qemu_get_nic_opaque(nc); 2493a977deeSAkihiko Odaki igb_core_set_link_status(&s->core); 2503a977deeSAkihiko Odaki } 2513a977deeSAkihiko Odaki 2523a977deeSAkihiko Odaki static NetClientInfo net_igb_info = { 2533a977deeSAkihiko Odaki .type = NET_CLIENT_DRIVER_NIC, 2543a977deeSAkihiko Odaki .size = sizeof(NICState), 2553a977deeSAkihiko Odaki .can_receive = igb_nc_can_receive, 2563a977deeSAkihiko Odaki .receive = igb_nc_receive, 2573a977deeSAkihiko Odaki .receive_iov = igb_nc_receive_iov, 2583a977deeSAkihiko Odaki .link_status_changed = igb_set_link_status, 2593a977deeSAkihiko Odaki }; 2603a977deeSAkihiko Odaki 2613a977deeSAkihiko Odaki /* 2623a977deeSAkihiko Odaki * EEPROM (NVM) contents documented in section 6.1, table 6-1: 2633a977deeSAkihiko Odaki * and in 6.10 Software accessed words. 2643a977deeSAkihiko Odaki */ 2653a977deeSAkihiko Odaki static const uint16_t igb_eeprom_template[] = { 2663a977deeSAkihiko Odaki /* Address |Compat.|OEM sp.| ImRev | OEM sp. */ 2673a977deeSAkihiko Odaki 0x0000, 0x0000, 0x0000, 0x0d34, 0xffff, 0x2010, 0xffff, 0xffff, 2683a977deeSAkihiko Odaki /* PBA |ICtrl1 | SSID | SVID | DevID |-------|ICtrl2 */ 2693a977deeSAkihiko Odaki 0x1040, 0xffff, 0x002b, 0x0000, 0x8086, 0x10c9, 0x0000, 0x70c3, 2703a977deeSAkihiko Odaki /* SwPin0| DevID | EESZ |-------|ICtrl3 |PCI-tc | MSIX | APtr */ 2713a977deeSAkihiko Odaki 0x0004, 0x10c9, 0x5c00, 0x0000, 0x2880, 0x0014, 0x4a40, 0x0060, 2723a977deeSAkihiko Odaki /* PCIe Init. Conf 1,2,3 |PCICtrl| LD1,3 |DDevID |DevRev | LD0,2 */ 2733a977deeSAkihiko Odaki 0x6cfb, 0xc7b0, 0x0abe, 0x0403, 0x0783, 0x10a6, 0x0001, 0x0602, 2743a977deeSAkihiko Odaki /* SwPin1| FunC |LAN-PWR|ManHwC |ICtrl3 | IOVct |VDevID |-------*/ 2753a977deeSAkihiko Odaki 0x0004, 0x0020, 0x0000, 0x004a, 0x2080, 0x00f5, 0x10ca, 0x0000, 2763a977deeSAkihiko Odaki /*---------------| LD1,3 | LD0,2 | ROEnd | ROSta | Wdog | VPD */ 2773a977deeSAkihiko Odaki 0x0000, 0x0000, 0x4784, 0x4602, 0x0000, 0x0000, 0x1000, 0xffff, 2783a977deeSAkihiko Odaki /* PCSet0| Ccfg0 |PXEver |IBAcap |PCSet1 | Ccfg1 |iSCVer | ?? */ 2793a977deeSAkihiko Odaki 0x0100, 0x4000, 0x131f, 0x4013, 0x0100, 0x4000, 0xffff, 0xffff, 2803a977deeSAkihiko Odaki /* PCSet2| Ccfg2 |PCSet3 | Ccfg3 | ?? |AltMacP| ?? |CHKSUM */ 2813a977deeSAkihiko Odaki 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x00e0, 0xffff, 0x0000, 2823a977deeSAkihiko Odaki /* NC-SIC */ 2833a977deeSAkihiko Odaki 0x0003, 2843a977deeSAkihiko Odaki }; 2853a977deeSAkihiko Odaki 2863a977deeSAkihiko Odaki static void igb_core_realize(IGBState *s) 2873a977deeSAkihiko Odaki { 2883a977deeSAkihiko Odaki s->core.owner = &s->parent_obj; 2893a977deeSAkihiko Odaki s->core.owner_nic = s->nic; 2903a977deeSAkihiko Odaki } 2913a977deeSAkihiko Odaki 2923a977deeSAkihiko Odaki static void 2933a977deeSAkihiko Odaki igb_init_msix(IGBState *s) 2943a977deeSAkihiko Odaki { 2953a977deeSAkihiko Odaki int i, res; 2963a977deeSAkihiko Odaki 2973a977deeSAkihiko Odaki res = msix_init(PCI_DEVICE(s), IGB_MSIX_VEC_NUM, 2983a977deeSAkihiko Odaki &s->msix, 2993a977deeSAkihiko Odaki E1000E_MSIX_IDX, 0, 3003a977deeSAkihiko Odaki &s->msix, 3013a977deeSAkihiko Odaki E1000E_MSIX_IDX, 0x2000, 3023a977deeSAkihiko Odaki 0x70, NULL); 3033a977deeSAkihiko Odaki 3043a977deeSAkihiko Odaki if (res < 0) { 3053a977deeSAkihiko Odaki trace_e1000e_msix_init_fail(res); 3063a977deeSAkihiko Odaki } else { 3073a977deeSAkihiko Odaki for (i = 0; i < IGB_MSIX_VEC_NUM; i++) { 3083a977deeSAkihiko Odaki msix_vector_use(PCI_DEVICE(s), i); 3093a977deeSAkihiko Odaki } 3103a977deeSAkihiko Odaki } 3113a977deeSAkihiko Odaki } 3123a977deeSAkihiko Odaki 3133a977deeSAkihiko Odaki static void 3143a977deeSAkihiko Odaki igb_cleanup_msix(IGBState *s) 3153a977deeSAkihiko Odaki { 3163a977deeSAkihiko Odaki msix_unuse_all_vectors(PCI_DEVICE(s)); 3173a977deeSAkihiko Odaki msix_uninit(PCI_DEVICE(s), &s->msix, &s->msix); 3183a977deeSAkihiko Odaki } 3193a977deeSAkihiko Odaki 3203a977deeSAkihiko Odaki static void 3213a977deeSAkihiko Odaki igb_init_net_peer(IGBState *s, PCIDevice *pci_dev, uint8_t *macaddr) 3223a977deeSAkihiko Odaki { 3233a977deeSAkihiko Odaki DeviceState *dev = DEVICE(pci_dev); 3243a977deeSAkihiko Odaki NetClientState *nc; 3253a977deeSAkihiko Odaki int i; 3263a977deeSAkihiko Odaki 3273a977deeSAkihiko Odaki s->nic = qemu_new_nic(&net_igb_info, &s->conf, 3287d0fefdfSAkihiko Odaki object_get_typename(OBJECT(s)), dev->id, &dev->mem_reentrancy_guard, s); 3293a977deeSAkihiko Odaki 3303a977deeSAkihiko Odaki s->core.max_queue_num = s->conf.peers.queues ? s->conf.peers.queues - 1 : 0; 3313a977deeSAkihiko Odaki 3323a977deeSAkihiko Odaki trace_e1000e_mac_set_permanent(MAC_ARG(macaddr)); 3333a977deeSAkihiko Odaki memcpy(s->core.permanent_mac, macaddr, sizeof(s->core.permanent_mac)); 3343a977deeSAkihiko Odaki 3353a977deeSAkihiko Odaki qemu_format_nic_info_str(qemu_get_queue(s->nic), macaddr); 3363a977deeSAkihiko Odaki 3373a977deeSAkihiko Odaki /* Setup virtio headers */ 3383a977deeSAkihiko Odaki for (i = 0; i < s->conf.peers.queues; i++) { 3393a977deeSAkihiko Odaki nc = qemu_get_subqueue(s->nic, i); 3403a977deeSAkihiko Odaki if (!nc->peer || !qemu_has_vnet_hdr(nc->peer)) { 3413a977deeSAkihiko Odaki trace_e1000e_cfg_support_virtio(false); 3423a977deeSAkihiko Odaki return; 3433a977deeSAkihiko Odaki } 3443a977deeSAkihiko Odaki } 3453a977deeSAkihiko Odaki 3463a977deeSAkihiko Odaki trace_e1000e_cfg_support_virtio(true); 3473a977deeSAkihiko Odaki s->core.has_vnet = true; 3483a977deeSAkihiko Odaki 3493a977deeSAkihiko Odaki for (i = 0; i < s->conf.peers.queues; i++) { 3503a977deeSAkihiko Odaki nc = qemu_get_subqueue(s->nic, i); 3513a977deeSAkihiko Odaki qemu_set_vnet_hdr_len(nc->peer, sizeof(struct virtio_net_hdr)); 3523a977deeSAkihiko Odaki qemu_using_vnet_hdr(nc->peer, true); 3533a977deeSAkihiko Odaki } 3543a977deeSAkihiko Odaki } 3553a977deeSAkihiko Odaki 3563a977deeSAkihiko Odaki static int 3573a977deeSAkihiko Odaki igb_add_pm_capability(PCIDevice *pdev, uint8_t offset, uint16_t pmc) 3583a977deeSAkihiko Odaki { 3593a977deeSAkihiko Odaki Error *local_err = NULL; 3603a977deeSAkihiko Odaki int ret = pci_add_capability(pdev, PCI_CAP_ID_PM, offset, 3613a977deeSAkihiko Odaki PCI_PM_SIZEOF, &local_err); 3623a977deeSAkihiko Odaki 3633a977deeSAkihiko Odaki if (local_err) { 3643a977deeSAkihiko Odaki error_report_err(local_err); 3653a977deeSAkihiko Odaki return ret; 3663a977deeSAkihiko Odaki } 3673a977deeSAkihiko Odaki 3683a977deeSAkihiko Odaki pci_set_word(pdev->config + offset + PCI_PM_PMC, 3693a977deeSAkihiko Odaki PCI_PM_CAP_VER_1_1 | 3703a977deeSAkihiko Odaki pmc); 3713a977deeSAkihiko Odaki 3723a977deeSAkihiko Odaki pci_set_word(pdev->wmask + offset + PCI_PM_CTRL, 3733a977deeSAkihiko Odaki PCI_PM_CTRL_STATE_MASK | 3743a977deeSAkihiko Odaki PCI_PM_CTRL_PME_ENABLE | 3753a977deeSAkihiko Odaki PCI_PM_CTRL_DATA_SEL_MASK); 3763a977deeSAkihiko Odaki 3773a977deeSAkihiko Odaki pci_set_word(pdev->w1cmask + offset + PCI_PM_CTRL, 3783a977deeSAkihiko Odaki PCI_PM_CTRL_PME_STATUS); 3793a977deeSAkihiko Odaki 3803a977deeSAkihiko Odaki return ret; 3813a977deeSAkihiko Odaki } 3823a977deeSAkihiko Odaki 3833a977deeSAkihiko Odaki static void igb_pci_realize(PCIDevice *pci_dev, Error **errp) 3843a977deeSAkihiko Odaki { 3853a977deeSAkihiko Odaki IGBState *s = IGB(pci_dev); 3863a977deeSAkihiko Odaki uint8_t *macaddr; 3873a977deeSAkihiko Odaki int ret; 3883a977deeSAkihiko Odaki 3893a977deeSAkihiko Odaki trace_e1000e_cb_pci_realize(); 3903a977deeSAkihiko Odaki 3913a977deeSAkihiko Odaki pci_dev->config_write = igb_write_config; 3923a977deeSAkihiko Odaki 3933a977deeSAkihiko Odaki pci_dev->config[PCI_CACHE_LINE_SIZE] = 0x10; 3943a977deeSAkihiko Odaki pci_dev->config[PCI_INTERRUPT_PIN] = 1; 3953a977deeSAkihiko Odaki 3963a977deeSAkihiko Odaki /* Define IO/MMIO regions */ 3973a977deeSAkihiko Odaki memory_region_init_io(&s->mmio, OBJECT(s), &mmio_ops, s, 3983a977deeSAkihiko Odaki "igb-mmio", E1000E_MMIO_SIZE); 3993a977deeSAkihiko Odaki pci_register_bar(pci_dev, E1000E_MMIO_IDX, 4003a977deeSAkihiko Odaki PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mmio); 4013a977deeSAkihiko Odaki 4023a977deeSAkihiko Odaki /* 4033a977deeSAkihiko Odaki * We provide a dummy implementation for the flash BAR 4043a977deeSAkihiko Odaki * for drivers that may theoretically probe for its presence. 4053a977deeSAkihiko Odaki */ 4063a977deeSAkihiko Odaki memory_region_init(&s->flash, OBJECT(s), 4073a977deeSAkihiko Odaki "igb-flash", E1000E_FLASH_SIZE); 4083a977deeSAkihiko Odaki pci_register_bar(pci_dev, E1000E_FLASH_IDX, 4093a977deeSAkihiko Odaki PCI_BASE_ADDRESS_SPACE_MEMORY, &s->flash); 4103a977deeSAkihiko Odaki 4113a977deeSAkihiko Odaki memory_region_init_io(&s->io, OBJECT(s), &io_ops, s, 4123a977deeSAkihiko Odaki "igb-io", E1000E_IO_SIZE); 4133a977deeSAkihiko Odaki pci_register_bar(pci_dev, E1000E_IO_IDX, 4143a977deeSAkihiko Odaki PCI_BASE_ADDRESS_SPACE_IO, &s->io); 4153a977deeSAkihiko Odaki 4163a977deeSAkihiko Odaki memory_region_init(&s->msix, OBJECT(s), "igb-msix", 4173a977deeSAkihiko Odaki E1000E_MSIX_SIZE); 4183a977deeSAkihiko Odaki pci_register_bar(pci_dev, E1000E_MSIX_IDX, 4193a977deeSAkihiko Odaki PCI_BASE_ADDRESS_MEM_TYPE_64, &s->msix); 4203a977deeSAkihiko Odaki 4213a977deeSAkihiko Odaki /* Create networking backend */ 4223a977deeSAkihiko Odaki qemu_macaddr_default_if_unset(&s->conf.macaddr); 4233a977deeSAkihiko Odaki macaddr = s->conf.macaddr.a; 4243a977deeSAkihiko Odaki 4253a977deeSAkihiko Odaki /* Add PCI capabilities in reverse order */ 4263a977deeSAkihiko Odaki assert(pcie_endpoint_cap_init(pci_dev, 0xa0) > 0); 4273a977deeSAkihiko Odaki 4283a977deeSAkihiko Odaki igb_init_msix(s); 4293a977deeSAkihiko Odaki 4303a977deeSAkihiko Odaki ret = msi_init(pci_dev, 0x50, 1, true, true, NULL); 4313a977deeSAkihiko Odaki if (ret) { 4323a977deeSAkihiko Odaki trace_e1000e_msi_init_fail(ret); 4333a977deeSAkihiko Odaki } 4343a977deeSAkihiko Odaki 4353a977deeSAkihiko Odaki if (igb_add_pm_capability(pci_dev, 0x40, PCI_PM_CAP_DSI) < 0) { 4363a977deeSAkihiko Odaki hw_error("Failed to initialize PM capability"); 4373a977deeSAkihiko Odaki } 4383a977deeSAkihiko Odaki 4393a977deeSAkihiko Odaki /* PCIe extended capabilities (in order) */ 440d90014fcSCédric Le Goater if (s->has_flr) { 441d90014fcSCédric Le Goater pcie_cap_flr_init(pci_dev); 442d90014fcSCédric Le Goater } 443d90014fcSCédric Le Goater 4443a977deeSAkihiko Odaki if (pcie_aer_init(pci_dev, 1, 0x100, 0x40, errp) < 0) { 4453a977deeSAkihiko Odaki hw_error("Failed to initialize AER capability"); 4463a977deeSAkihiko Odaki } 4473a977deeSAkihiko Odaki 448445416e3SAkihiko Odaki pcie_ari_init(pci_dev, 0x150); 4493a977deeSAkihiko Odaki 450ff2b24c8SAkihiko Odaki pcie_sriov_pf_init(pci_dev, IGB_CAP_SRIOV_OFFSET, TYPE_IGBVF, 4513a977deeSAkihiko Odaki IGB_82576_VF_DEV_ID, IGB_MAX_VF_FUNCTIONS, IGB_MAX_VF_FUNCTIONS, 4523a977deeSAkihiko Odaki IGB_VF_OFFSET, IGB_VF_STRIDE); 4533a977deeSAkihiko Odaki 454ff2b24c8SAkihiko Odaki pcie_sriov_pf_init_vf_bar(pci_dev, IGBVF_MMIO_BAR_IDX, 4553a977deeSAkihiko Odaki PCI_BASE_ADDRESS_MEM_TYPE_64 | PCI_BASE_ADDRESS_MEM_PREFETCH, 456ff2b24c8SAkihiko Odaki IGBVF_MMIO_SIZE); 457ff2b24c8SAkihiko Odaki pcie_sriov_pf_init_vf_bar(pci_dev, IGBVF_MSIX_BAR_IDX, 4583a977deeSAkihiko Odaki PCI_BASE_ADDRESS_MEM_TYPE_64 | PCI_BASE_ADDRESS_MEM_PREFETCH, 459ff2b24c8SAkihiko Odaki IGBVF_MSIX_SIZE); 4603a977deeSAkihiko Odaki 4613a977deeSAkihiko Odaki igb_init_net_peer(s, pci_dev, macaddr); 4623a977deeSAkihiko Odaki 4633a977deeSAkihiko Odaki /* Initialize core */ 4643a977deeSAkihiko Odaki igb_core_realize(s); 4653a977deeSAkihiko Odaki 4663a977deeSAkihiko Odaki igb_core_pci_realize(&s->core, 4673a977deeSAkihiko Odaki igb_eeprom_template, 4683a977deeSAkihiko Odaki sizeof(igb_eeprom_template), 4693a977deeSAkihiko Odaki macaddr); 4703a977deeSAkihiko Odaki } 4713a977deeSAkihiko Odaki 4723a977deeSAkihiko Odaki static void igb_pci_uninit(PCIDevice *pci_dev) 4733a977deeSAkihiko Odaki { 4743a977deeSAkihiko Odaki IGBState *s = IGB(pci_dev); 4753a977deeSAkihiko Odaki 4763a977deeSAkihiko Odaki trace_e1000e_cb_pci_uninit(); 4773a977deeSAkihiko Odaki 4783a977deeSAkihiko Odaki igb_core_pci_uninit(&s->core); 4793a977deeSAkihiko Odaki 4803a977deeSAkihiko Odaki pcie_sriov_pf_exit(pci_dev); 4813a977deeSAkihiko Odaki pcie_cap_exit(pci_dev); 4823a977deeSAkihiko Odaki 4833a977deeSAkihiko Odaki qemu_del_nic(s->nic); 4843a977deeSAkihiko Odaki 4853a977deeSAkihiko Odaki igb_cleanup_msix(s); 4863a977deeSAkihiko Odaki msi_uninit(pci_dev); 4873a977deeSAkihiko Odaki } 4883a977deeSAkihiko Odaki 4893a977deeSAkihiko Odaki static void igb_qdev_reset_hold(Object *obj) 4903a977deeSAkihiko Odaki { 4913a977deeSAkihiko Odaki PCIDevice *d = PCI_DEVICE(obj); 4923a977deeSAkihiko Odaki IGBState *s = IGB(obj); 4933a977deeSAkihiko Odaki 4943a977deeSAkihiko Odaki trace_e1000e_cb_qdev_reset_hold(); 4953a977deeSAkihiko Odaki 4963a977deeSAkihiko Odaki pcie_sriov_pf_disable_vfs(d); 4973a977deeSAkihiko Odaki igb_core_reset(&s->core); 4983a977deeSAkihiko Odaki } 4993a977deeSAkihiko Odaki 5003a977deeSAkihiko Odaki static int igb_pre_save(void *opaque) 5013a977deeSAkihiko Odaki { 5023a977deeSAkihiko Odaki IGBState *s = opaque; 5033a977deeSAkihiko Odaki 5043a977deeSAkihiko Odaki trace_e1000e_cb_pre_save(); 5053a977deeSAkihiko Odaki 5063a977deeSAkihiko Odaki igb_core_pre_save(&s->core); 5073a977deeSAkihiko Odaki 5083a977deeSAkihiko Odaki return 0; 5093a977deeSAkihiko Odaki } 5103a977deeSAkihiko Odaki 5113a977deeSAkihiko Odaki static int igb_post_load(void *opaque, int version_id) 5123a977deeSAkihiko Odaki { 5133a977deeSAkihiko Odaki IGBState *s = opaque; 5143a977deeSAkihiko Odaki 5153a977deeSAkihiko Odaki trace_e1000e_cb_post_load(); 5163a977deeSAkihiko Odaki return igb_core_post_load(&s->core); 5173a977deeSAkihiko Odaki } 5183a977deeSAkihiko Odaki 519212f7b1dSAkihiko Odaki static const VMStateDescription igb_vmstate_tx_ctx = { 520212f7b1dSAkihiko Odaki .name = "igb-tx-ctx", 5213a977deeSAkihiko Odaki .version_id = 1, 5223a977deeSAkihiko Odaki .minimum_version_id = 1, 523*1de81b42SRichard Henderson .fields = (const VMStateField[]) { 524212f7b1dSAkihiko Odaki VMSTATE_UINT32(vlan_macip_lens, struct e1000_adv_tx_context_desc), 525212f7b1dSAkihiko Odaki VMSTATE_UINT32(seqnum_seed, struct e1000_adv_tx_context_desc), 526212f7b1dSAkihiko Odaki VMSTATE_UINT32(type_tucmd_mlhl, struct e1000_adv_tx_context_desc), 527212f7b1dSAkihiko Odaki VMSTATE_UINT32(mss_l4len_idx, struct e1000_adv_tx_context_desc), 528212f7b1dSAkihiko Odaki VMSTATE_END_OF_LIST() 529212f7b1dSAkihiko Odaki } 530212f7b1dSAkihiko Odaki }; 531212f7b1dSAkihiko Odaki 532212f7b1dSAkihiko Odaki static const VMStateDescription igb_vmstate_tx = { 533212f7b1dSAkihiko Odaki .name = "igb-tx", 534212f7b1dSAkihiko Odaki .version_id = 2, 535212f7b1dSAkihiko Odaki .minimum_version_id = 2, 536*1de81b42SRichard Henderson .fields = (const VMStateField[]) { 537212f7b1dSAkihiko Odaki VMSTATE_STRUCT_ARRAY(ctx, struct igb_tx, 2, 0, igb_vmstate_tx_ctx, 538212f7b1dSAkihiko Odaki struct e1000_adv_tx_context_desc), 539212f7b1dSAkihiko Odaki VMSTATE_UINT32(first_cmd_type_len, struct igb_tx), 540212f7b1dSAkihiko Odaki VMSTATE_UINT32(first_olinfo_status, struct igb_tx), 5413a977deeSAkihiko Odaki VMSTATE_BOOL(first, struct igb_tx), 5423a977deeSAkihiko Odaki VMSTATE_BOOL(skip_cp, struct igb_tx), 5433a977deeSAkihiko Odaki VMSTATE_END_OF_LIST() 5443a977deeSAkihiko Odaki } 5453a977deeSAkihiko Odaki }; 5463a977deeSAkihiko Odaki 5473a977deeSAkihiko Odaki static const VMStateDescription igb_vmstate_intr_timer = { 5483a977deeSAkihiko Odaki .name = "igb-intr-timer", 5493a977deeSAkihiko Odaki .version_id = 1, 5503a977deeSAkihiko Odaki .minimum_version_id = 1, 551*1de81b42SRichard Henderson .fields = (const VMStateField[]) { 5523a977deeSAkihiko Odaki VMSTATE_TIMER_PTR(timer, IGBIntrDelayTimer), 5533a977deeSAkihiko Odaki VMSTATE_BOOL(running, IGBIntrDelayTimer), 5543a977deeSAkihiko Odaki VMSTATE_END_OF_LIST() 5553a977deeSAkihiko Odaki } 5563a977deeSAkihiko Odaki }; 5573a977deeSAkihiko Odaki 5583a977deeSAkihiko Odaki #define VMSTATE_IGB_INTR_DELAY_TIMER(_f, _s) \ 5593a977deeSAkihiko Odaki VMSTATE_STRUCT(_f, _s, 0, \ 5603a977deeSAkihiko Odaki igb_vmstate_intr_timer, IGBIntrDelayTimer) 5613a977deeSAkihiko Odaki 5623a977deeSAkihiko Odaki #define VMSTATE_IGB_INTR_DELAY_TIMER_ARRAY(_f, _s, _num) \ 5633a977deeSAkihiko Odaki VMSTATE_STRUCT_ARRAY(_f, _s, _num, 0, \ 5643a977deeSAkihiko Odaki igb_vmstate_intr_timer, IGBIntrDelayTimer) 5653a977deeSAkihiko Odaki 5663a977deeSAkihiko Odaki static const VMStateDescription igb_vmstate = { 5673a977deeSAkihiko Odaki .name = "igb", 5683a977deeSAkihiko Odaki .version_id = 1, 5693a977deeSAkihiko Odaki .minimum_version_id = 1, 5703a977deeSAkihiko Odaki .pre_save = igb_pre_save, 5713a977deeSAkihiko Odaki .post_load = igb_post_load, 572*1de81b42SRichard Henderson .fields = (const VMStateField[]) { 5733a977deeSAkihiko Odaki VMSTATE_PCI_DEVICE(parent_obj, IGBState), 5743a977deeSAkihiko Odaki VMSTATE_MSIX(parent_obj, IGBState), 5753a977deeSAkihiko Odaki 5763a977deeSAkihiko Odaki VMSTATE_UINT32(ioaddr, IGBState), 5773a977deeSAkihiko Odaki VMSTATE_UINT8(core.rx_desc_len, IGBState), 5783a977deeSAkihiko Odaki VMSTATE_UINT16_ARRAY(core.eeprom, IGBState, IGB_EEPROM_SIZE), 5793a977deeSAkihiko Odaki VMSTATE_UINT16_ARRAY(core.phy, IGBState, MAX_PHY_REG_ADDRESS + 1), 5803a977deeSAkihiko Odaki VMSTATE_UINT32_ARRAY(core.mac, IGBState, E1000E_MAC_SIZE), 5813a977deeSAkihiko Odaki VMSTATE_UINT8_ARRAY(core.permanent_mac, IGBState, ETH_ALEN), 5823a977deeSAkihiko Odaki 5833a977deeSAkihiko Odaki VMSTATE_IGB_INTR_DELAY_TIMER_ARRAY(core.eitr, IGBState, 5843a977deeSAkihiko Odaki IGB_INTR_NUM), 5853a977deeSAkihiko Odaki 5863a977deeSAkihiko Odaki VMSTATE_UINT32_ARRAY(core.eitr_guest_value, IGBState, IGB_INTR_NUM), 5873a977deeSAkihiko Odaki 5883a977deeSAkihiko Odaki VMSTATE_STRUCT_ARRAY(core.tx, IGBState, IGB_NUM_QUEUES, 0, 5893a977deeSAkihiko Odaki igb_vmstate_tx, struct igb_tx), 5903a977deeSAkihiko Odaki 5913a977deeSAkihiko Odaki VMSTATE_INT64(core.timadj, IGBState), 5923a977deeSAkihiko Odaki 5933a977deeSAkihiko Odaki VMSTATE_END_OF_LIST() 5943a977deeSAkihiko Odaki } 5953a977deeSAkihiko Odaki }; 5963a977deeSAkihiko Odaki 5973a977deeSAkihiko Odaki static Property igb_properties[] = { 5983a977deeSAkihiko Odaki DEFINE_NIC_PROPERTIES(IGBState, conf), 599d90014fcSCédric Le Goater DEFINE_PROP_BOOL("x-pcie-flr-init", IGBState, has_flr, true), 6003a977deeSAkihiko Odaki DEFINE_PROP_END_OF_LIST(), 6013a977deeSAkihiko Odaki }; 6023a977deeSAkihiko Odaki 6033a977deeSAkihiko Odaki static void igb_class_init(ObjectClass *class, void *data) 6043a977deeSAkihiko Odaki { 6053a977deeSAkihiko Odaki DeviceClass *dc = DEVICE_CLASS(class); 6063a977deeSAkihiko Odaki ResettableClass *rc = RESETTABLE_CLASS(class); 6073a977deeSAkihiko Odaki PCIDeviceClass *c = PCI_DEVICE_CLASS(class); 6083a977deeSAkihiko Odaki 6093a977deeSAkihiko Odaki c->realize = igb_pci_realize; 6103a977deeSAkihiko Odaki c->exit = igb_pci_uninit; 6113a977deeSAkihiko Odaki c->vendor_id = PCI_VENDOR_ID_INTEL; 6123a977deeSAkihiko Odaki c->device_id = E1000_DEV_ID_82576; 6133a977deeSAkihiko Odaki c->revision = 1; 6143a977deeSAkihiko Odaki c->class_id = PCI_CLASS_NETWORK_ETHERNET; 6153a977deeSAkihiko Odaki 6163a977deeSAkihiko Odaki rc->phases.hold = igb_qdev_reset_hold; 6173a977deeSAkihiko Odaki 6183a977deeSAkihiko Odaki dc->desc = "Intel 82576 Gigabit Ethernet Controller"; 6193a977deeSAkihiko Odaki dc->vmsd = &igb_vmstate; 6203a977deeSAkihiko Odaki 6213a977deeSAkihiko Odaki device_class_set_props(dc, igb_properties); 6223a977deeSAkihiko Odaki set_bit(DEVICE_CATEGORY_NETWORK, dc->categories); 6233a977deeSAkihiko Odaki } 6243a977deeSAkihiko Odaki 6253a977deeSAkihiko Odaki static void igb_instance_init(Object *obj) 6263a977deeSAkihiko Odaki { 6273a977deeSAkihiko Odaki IGBState *s = IGB(obj); 6283a977deeSAkihiko Odaki device_add_bootindex_property(obj, &s->conf.bootindex, 6293a977deeSAkihiko Odaki "bootindex", "/ethernet-phy@0", 6303a977deeSAkihiko Odaki DEVICE(obj)); 6313a977deeSAkihiko Odaki } 6323a977deeSAkihiko Odaki 6333a977deeSAkihiko Odaki static const TypeInfo igb_info = { 6343a977deeSAkihiko Odaki .name = TYPE_IGB, 6353a977deeSAkihiko Odaki .parent = TYPE_PCI_DEVICE, 6363a977deeSAkihiko Odaki .instance_size = sizeof(IGBState), 6373a977deeSAkihiko Odaki .class_init = igb_class_init, 6383a977deeSAkihiko Odaki .instance_init = igb_instance_init, 6393a977deeSAkihiko Odaki .interfaces = (InterfaceInfo[]) { 6403a977deeSAkihiko Odaki { INTERFACE_PCIE_DEVICE }, 6413a977deeSAkihiko Odaki { } 6423a977deeSAkihiko Odaki }, 6433a977deeSAkihiko Odaki }; 6443a977deeSAkihiko Odaki 6453a977deeSAkihiko Odaki static void igb_register_types(void) 6463a977deeSAkihiko Odaki { 6473a977deeSAkihiko Odaki type_register_static(&igb_info); 6483a977deeSAkihiko Odaki } 6493a977deeSAkihiko Odaki 6503a977deeSAkihiko Odaki type_init(igb_register_types) 651