1 /* 2 * QEMU Intel 82576 SR/IOV Ethernet Controller Emulation 3 * 4 * Datasheet: 5 * https://www.intel.com/content/dam/www/public/us/en/documents/datasheets/82576eg-gbe-datasheet.pdf 6 * 7 * Copyright (c) 2020-2023 Red Hat, Inc. 8 * Copyright (c) 2015 Ravello Systems LTD (http://ravellosystems.com) 9 * Developed by Daynix Computing LTD (http://www.daynix.com) 10 * 11 * Authors: 12 * Akihiko Odaki <akihiko.odaki@daynix.com> 13 * Gal Hammmer <gal.hammer@sap.com> 14 * Marcel Apfelbaum <marcel.apfelbaum@gmail.com> 15 * Dmitry Fleytman <dmitry@daynix.com> 16 * Leonid Bloch <leonid@daynix.com> 17 * Yan Vugenfirer <yan@daynix.com> 18 * 19 * Based on work done by: 20 * Nir Peleg, Tutis Systems Ltd. for Qumranet Inc. 21 * Copyright (c) 2008 Qumranet 22 * Based on work done by: 23 * Copyright (c) 2007 Dan Aloni 24 * Copyright (c) 2004 Antony T Curtis 25 * 26 * This library is free software; you can redistribute it and/or 27 * modify it under the terms of the GNU Lesser General Public 28 * License as published by the Free Software Foundation; either 29 * version 2.1 of the License, or (at your option) any later version. 30 * 31 * This library is distributed in the hope that it will be useful, 32 * but WITHOUT ANY WARRANTY; without even the implied warranty of 33 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 34 * Lesser General Public License for more details. 35 * 36 * You should have received a copy of the GNU Lesser General Public 37 * License along with this library; if not, see <http://www.gnu.org/licenses/>. 38 */ 39 40 #include "qemu/osdep.h" 41 #include "hw/hw.h" 42 #include "hw/net/mii.h" 43 #include "hw/pci/pci_device.h" 44 #include "hw/pci/pcie.h" 45 #include "hw/pci/msix.h" 46 #include "net/eth.h" 47 #include "net/net.h" 48 #include "igb_common.h" 49 #include "igb_core.h" 50 #include "trace.h" 51 #include "qapi/error.h" 52 53 OBJECT_DECLARE_SIMPLE_TYPE(IgbVfState, IGBVF) 54 55 struct IgbVfState { 56 PCIDevice parent_obj; 57 58 MemoryRegion mmio; 59 MemoryRegion msix; 60 }; 61 62 static hwaddr vf_to_pf_addr(hwaddr addr, uint16_t vfn, bool write) 63 { 64 switch (addr) { 65 case E1000_CTRL: 66 case E1000_CTRL_DUP: 67 return E1000_PVTCTRL(vfn); 68 case E1000_EICS: 69 return E1000_PVTEICS(vfn); 70 case E1000_EIMS: 71 return E1000_PVTEIMS(vfn); 72 case E1000_EIMC: 73 return E1000_PVTEIMC(vfn); 74 case E1000_EIAC: 75 return E1000_PVTEIAC(vfn); 76 case E1000_EIAM: 77 return E1000_PVTEIAM(vfn); 78 case E1000_EICR: 79 return E1000_PVTEICR(vfn); 80 case E1000_EITR(0): 81 case E1000_EITR(1): 82 case E1000_EITR(2): 83 return E1000_EITR(22) + (addr - E1000_EITR(0)) - vfn * 0xC; 84 case E1000_IVAR0: 85 return E1000_VTIVAR + vfn * 4; 86 case E1000_IVAR_MISC: 87 return E1000_VTIVAR_MISC + vfn * 4; 88 case 0x0F04: /* PBACL */ 89 return E1000_PBACLR; 90 case 0x0F0C: /* PSRTYPE */ 91 return E1000_PSRTYPE(vfn); 92 case E1000_V2PMAILBOX(0): 93 return E1000_V2PMAILBOX(vfn); 94 case E1000_VMBMEM(0) ... E1000_VMBMEM(0) + 0x3F: 95 return addr + vfn * 0x40; 96 case E1000_RDBAL_A(0): 97 return E1000_RDBAL(vfn); 98 case E1000_RDBAL_A(1): 99 return E1000_RDBAL(vfn + IGB_MAX_VF_FUNCTIONS); 100 case E1000_RDBAH_A(0): 101 return E1000_RDBAH(vfn); 102 case E1000_RDBAH_A(1): 103 return E1000_RDBAH(vfn + IGB_MAX_VF_FUNCTIONS); 104 case E1000_RDLEN_A(0): 105 return E1000_RDLEN(vfn); 106 case E1000_RDLEN_A(1): 107 return E1000_RDLEN(vfn + IGB_MAX_VF_FUNCTIONS); 108 case E1000_SRRCTL_A(0): 109 return E1000_SRRCTL(vfn); 110 case E1000_SRRCTL_A(1): 111 return E1000_SRRCTL(vfn + IGB_MAX_VF_FUNCTIONS); 112 case E1000_RDH_A(0): 113 return E1000_RDH(vfn); 114 case E1000_RDH_A(1): 115 return E1000_RDH(vfn + IGB_MAX_VF_FUNCTIONS); 116 case E1000_RXCTL_A(0): 117 return E1000_RXCTL(vfn); 118 case E1000_RXCTL_A(1): 119 return E1000_RXCTL(vfn + IGB_MAX_VF_FUNCTIONS); 120 case E1000_RDT_A(0): 121 return E1000_RDT(vfn); 122 case E1000_RDT_A(1): 123 return E1000_RDT(vfn + IGB_MAX_VF_FUNCTIONS); 124 case E1000_RXDCTL_A(0): 125 return E1000_RXDCTL(vfn); 126 case E1000_RXDCTL_A(1): 127 return E1000_RXDCTL(vfn + IGB_MAX_VF_FUNCTIONS); 128 case E1000_RQDPC_A(0): 129 return E1000_RQDPC(vfn); 130 case E1000_RQDPC_A(1): 131 return E1000_RQDPC(vfn + IGB_MAX_VF_FUNCTIONS); 132 case E1000_TDBAL_A(0): 133 return E1000_TDBAL(vfn); 134 case E1000_TDBAL_A(1): 135 return E1000_TDBAL(vfn + IGB_MAX_VF_FUNCTIONS); 136 case E1000_TDBAH_A(0): 137 return E1000_TDBAH(vfn); 138 case E1000_TDBAH_A(1): 139 return E1000_TDBAH(vfn + IGB_MAX_VF_FUNCTIONS); 140 case E1000_TDLEN_A(0): 141 return E1000_TDLEN(vfn); 142 case E1000_TDLEN_A(1): 143 return E1000_TDLEN(vfn + IGB_MAX_VF_FUNCTIONS); 144 case E1000_TDH_A(0): 145 return E1000_TDH(vfn); 146 case E1000_TDH_A(1): 147 return E1000_TDH(vfn + IGB_MAX_VF_FUNCTIONS); 148 case E1000_TXCTL_A(0): 149 return E1000_TXCTL(vfn); 150 case E1000_TXCTL_A(1): 151 return E1000_TXCTL(vfn + IGB_MAX_VF_FUNCTIONS); 152 case E1000_TDT_A(0): 153 return E1000_TDT(vfn); 154 case E1000_TDT_A(1): 155 return E1000_TDT(vfn + IGB_MAX_VF_FUNCTIONS); 156 case E1000_TXDCTL_A(0): 157 return E1000_TXDCTL(vfn); 158 case E1000_TXDCTL_A(1): 159 return E1000_TXDCTL(vfn + IGB_MAX_VF_FUNCTIONS); 160 case E1000_TDWBAL_A(0): 161 return E1000_TDWBAL(vfn); 162 case E1000_TDWBAL_A(1): 163 return E1000_TDWBAL(vfn + IGB_MAX_VF_FUNCTIONS); 164 case E1000_TDWBAH_A(0): 165 return E1000_TDWBAH(vfn); 166 case E1000_TDWBAH_A(1): 167 return E1000_TDWBAH(vfn + IGB_MAX_VF_FUNCTIONS); 168 case E1000_VFGPRC: 169 return E1000_PVFGPRC(vfn); 170 case E1000_VFGPTC: 171 return E1000_PVFGPTC(vfn); 172 case E1000_VFGORC: 173 return E1000_PVFGORC(vfn); 174 case E1000_VFGOTC: 175 return E1000_PVFGOTC(vfn); 176 case E1000_VFMPRC: 177 return E1000_PVFMPRC(vfn); 178 case E1000_VFGPRLBC: 179 return E1000_PVFGPRLBC(vfn); 180 case E1000_VFGPTLBC: 181 return E1000_PVFGPTLBC(vfn); 182 case E1000_VFGORLBC: 183 return E1000_PVFGORLBC(vfn); 184 case E1000_VFGOTLBC: 185 return E1000_PVFGOTLBC(vfn); 186 case E1000_STATUS: 187 case E1000_FRTIMER: 188 if (write) { 189 return HWADDR_MAX; 190 } 191 /* fallthrough */ 192 case 0x34E8: /* PBTWAC */ 193 case 0x24E8: /* PBRWAC */ 194 return addr; 195 } 196 197 trace_igbvf_wrn_io_addr_unknown(addr); 198 199 return HWADDR_MAX; 200 } 201 202 static void igbvf_write_config(PCIDevice *dev, uint32_t addr, uint32_t val, 203 int len) 204 { 205 trace_igbvf_write_config(addr, val, len); 206 pci_default_write_config(dev, addr, val, len); 207 if (object_property_get_bool(OBJECT(pcie_sriov_get_pf(dev)), 208 "x-pcie-flr-init", &error_abort)) { 209 pcie_cap_flr_write_config(dev, addr, val, len); 210 } 211 } 212 213 static uint64_t igbvf_mmio_read(void *opaque, hwaddr addr, unsigned size) 214 { 215 PCIDevice *vf = PCI_DEVICE(opaque); 216 PCIDevice *pf = pcie_sriov_get_pf(vf); 217 218 addr = vf_to_pf_addr(addr, pcie_sriov_vf_number(vf), false); 219 return addr == HWADDR_MAX ? 0 : igb_mmio_read(pf, addr, size); 220 } 221 222 static void igbvf_mmio_write(void *opaque, hwaddr addr, uint64_t val, 223 unsigned size) 224 { 225 PCIDevice *vf = PCI_DEVICE(opaque); 226 PCIDevice *pf = pcie_sriov_get_pf(vf); 227 228 addr = vf_to_pf_addr(addr, pcie_sriov_vf_number(vf), true); 229 if (addr != HWADDR_MAX) { 230 igb_mmio_write(pf, addr, val, size); 231 } 232 } 233 234 static const MemoryRegionOps mmio_ops = { 235 .read = igbvf_mmio_read, 236 .write = igbvf_mmio_write, 237 .endianness = DEVICE_LITTLE_ENDIAN, 238 .impl = { 239 .min_access_size = 4, 240 .max_access_size = 4, 241 }, 242 }; 243 244 static void igbvf_pci_realize(PCIDevice *dev, Error **errp) 245 { 246 IgbVfState *s = IGBVF(dev); 247 int ret; 248 int i; 249 250 dev->config_write = igbvf_write_config; 251 252 memory_region_init_io(&s->mmio, OBJECT(dev), &mmio_ops, s, "igbvf-mmio", 253 IGBVF_MMIO_SIZE); 254 pcie_sriov_vf_register_bar(dev, IGBVF_MMIO_BAR_IDX, &s->mmio); 255 256 memory_region_init(&s->msix, OBJECT(dev), "igbvf-msix", IGBVF_MSIX_SIZE); 257 pcie_sriov_vf_register_bar(dev, IGBVF_MSIX_BAR_IDX, &s->msix); 258 259 ret = msix_init(dev, IGBVF_MSIX_VEC_NUM, &s->msix, IGBVF_MSIX_BAR_IDX, 0, 260 &s->msix, IGBVF_MSIX_BAR_IDX, 0x2000, 0x70, errp); 261 if (ret) { 262 return; 263 } 264 265 for (i = 0; i < IGBVF_MSIX_VEC_NUM; i++) { 266 msix_vector_use(dev, i); 267 } 268 269 if (pcie_endpoint_cap_init(dev, 0xa0) < 0) { 270 hw_error("Failed to initialize PCIe capability"); 271 } 272 273 if (object_property_get_bool(OBJECT(pcie_sriov_get_pf(dev)), 274 "x-pcie-flr-init", &error_abort)) { 275 pcie_cap_flr_init(dev); 276 } 277 278 if (pcie_aer_init(dev, 1, 0x100, 0x40, errp) < 0) { 279 hw_error("Failed to initialize AER capability"); 280 } 281 282 pcie_ari_init(dev, 0x150); 283 } 284 285 static void igbvf_qdev_reset_hold(Object *obj, ResetType type) 286 { 287 PCIDevice *vf = PCI_DEVICE(obj); 288 289 igb_vf_reset(pcie_sriov_get_pf(vf), pcie_sriov_vf_number(vf)); 290 } 291 292 static void igbvf_pci_uninit(PCIDevice *dev) 293 { 294 IgbVfState *s = IGBVF(dev); 295 296 pcie_aer_exit(dev); 297 pcie_cap_exit(dev); 298 msix_unuse_all_vectors(dev); 299 msix_uninit(dev, &s->msix, &s->msix); 300 } 301 302 static void igbvf_class_init(ObjectClass *class, void *data) 303 { 304 DeviceClass *dc = DEVICE_CLASS(class); 305 PCIDeviceClass *c = PCI_DEVICE_CLASS(class); 306 ResettableClass *rc = RESETTABLE_CLASS(class); 307 308 c->realize = igbvf_pci_realize; 309 c->exit = igbvf_pci_uninit; 310 c->vendor_id = PCI_VENDOR_ID_INTEL; 311 c->device_id = E1000_DEV_ID_82576_VF; 312 c->revision = 1; 313 c->class_id = PCI_CLASS_NETWORK_ETHERNET; 314 315 rc->phases.hold = igbvf_qdev_reset_hold; 316 317 dc->desc = "Intel 82576 Virtual Function"; 318 dc->user_creatable = false; 319 320 set_bit(DEVICE_CATEGORY_NETWORK, dc->categories); 321 } 322 323 static const TypeInfo igbvf_info = { 324 .name = TYPE_IGBVF, 325 .parent = TYPE_PCI_DEVICE, 326 .instance_size = sizeof(IgbVfState), 327 .class_init = igbvf_class_init, 328 .interfaces = (InterfaceInfo[]) { 329 { INTERFACE_PCIE_DEVICE }, 330 { } 331 }, 332 }; 333 334 static void igb_register_types(void) 335 { 336 type_register_static(&igbvf_info); 337 } 338 339 type_init(igb_register_types) 340