| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,102 @@ | ||
| /* | ||
| * QEMU e1000(e) emulation - shared definitions | ||
| * | ||
| * Copyright (c) 2008 Qumranet | ||
| * | ||
| * Based on work done by: | ||
| * Nir Peleg, Tutis Systems Ltd. for Qumranet Inc. | ||
| * Copyright (c) 2007 Dan Aloni | ||
| * Copyright (c) 2004 Antony T Curtis | ||
| * | ||
| * This library is free software; you can redistribute it and/or | ||
| * modify it under the terms of the GNU Lesser General Public | ||
| * License as published by the Free Software Foundation; either | ||
| * version 2.1 of the License, or (at your option) any later version. | ||
| * | ||
| * This library is distributed in the hope that it will be useful, | ||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| * Lesser General Public License for more details. | ||
| * | ||
| * You should have received a copy of the GNU Lesser General Public | ||
| * License along with this library; if not, see <http://www.gnu.org/licenses/>. | ||
| */ | ||
|
|
||
| #ifndef HW_NET_E1000_COMMON_H | ||
| #define HW_NET_E1000_COMMON_H | ||
|
|
||
| #include "e1000_regs.h" | ||
|
|
||
| #define defreg(x) x = (E1000_##x >> 2) | ||
| enum { | ||
| defreg(CTRL), defreg(EECD), defreg(EERD), defreg(GPRC), | ||
| defreg(GPTC), defreg(ICR), defreg(ICS), defreg(IMC), | ||
| defreg(IMS), defreg(LEDCTL), defreg(MANC), defreg(MDIC), | ||
| defreg(MPC), defreg(PBA), defreg(RCTL), defreg(RDBAH0), | ||
| defreg(RDBAL0), defreg(RDH0), defreg(RDLEN0), defreg(RDT0), | ||
| defreg(STATUS), defreg(SWSM), defreg(TCTL), defreg(TDBAH), | ||
| defreg(TDBAL), defreg(TDH), defreg(TDLEN), defreg(TDT), | ||
| defreg(TDLEN1), defreg(TDBAL1), defreg(TDBAH1), defreg(TDH1), | ||
| defreg(TDT1), defreg(TORH), defreg(TORL), defreg(TOTH), | ||
| defreg(TOTL), defreg(TPR), defreg(TPT), defreg(TXDCTL), | ||
| defreg(WUFC), defreg(RA), defreg(MTA), defreg(CRCERRS), | ||
| defreg(VFTA), defreg(VET), defreg(RDTR), defreg(RADV), | ||
| defreg(TADV), defreg(ITR), defreg(SCC), defreg(ECOL), | ||
| defreg(MCC), defreg(LATECOL), defreg(COLC), defreg(DC), | ||
| defreg(TNCRS), defreg(SEQEC), defreg(CEXTERR), defreg(RLEC), | ||
| defreg(XONRXC), defreg(XONTXC), defreg(XOFFRXC), defreg(XOFFTXC), | ||
| defreg(FCRUC), defreg(AIT), defreg(TDFH), defreg(TDFT), | ||
| defreg(TDFHS), defreg(TDFTS), defreg(TDFPC), defreg(WUC), | ||
| defreg(WUS), defreg(POEMB), defreg(PBS), defreg(RDFH), | ||
| defreg(RDFT), defreg(RDFHS), defreg(RDFTS), defreg(RDFPC), | ||
| defreg(PBM), defreg(IPAV), defreg(IP4AT), defreg(IP6AT), | ||
| defreg(WUPM), defreg(FFLT), defreg(FFMT), defreg(FFVT), | ||
| defreg(TARC0), defreg(TARC1), defreg(IAM), defreg(EXTCNF_CTRL), | ||
| defreg(GCR), defreg(TIMINCA), defreg(EIAC), defreg(CTRL_EXT), | ||
| defreg(IVAR), defreg(MFUTP01), defreg(MFUTP23), defreg(MANC2H), | ||
| defreg(MFVAL), defreg(MDEF), defreg(FACTPS), defreg(FTFT), | ||
| defreg(RUC), defreg(ROC), defreg(RFC), defreg(RJC), | ||
| defreg(PRC64), defreg(PRC127), defreg(PRC255), defreg(PRC511), | ||
| defreg(PRC1023), defreg(PRC1522), defreg(PTC64), defreg(PTC127), | ||
| defreg(PTC255), defreg(PTC511), defreg(PTC1023), defreg(PTC1522), | ||
| defreg(GORCL), defreg(GORCH), defreg(GOTCL), defreg(GOTCH), | ||
| defreg(RNBC), defreg(BPRC), defreg(MPRC), defreg(RFCTL), | ||
| defreg(PSRCTL), defreg(MPTC), defreg(BPTC), defreg(TSCTFC), | ||
| defreg(IAC), defreg(MGTPRC), defreg(MGTPDC), defreg(MGTPTC), | ||
| defreg(TSCTC), defreg(RXCSUM), defreg(FUNCTAG), defreg(GSCL_1), | ||
| defreg(GSCL_2), defreg(GSCL_3), defreg(GSCL_4), defreg(GSCN_0), | ||
| defreg(GSCN_1), defreg(GSCN_2), defreg(GSCN_3), defreg(GCR2), | ||
| defreg(RAID), defreg(RSRPD), defreg(TIDV), defreg(EITR), | ||
| defreg(MRQC), defreg(RETA), defreg(RSSRK), defreg(RDBAH1), | ||
| defreg(RDBAL1), defreg(RDLEN1), defreg(RDH1), defreg(RDT1), | ||
| defreg(PBACLR), defreg(FCAL), defreg(FCAH), defreg(FCT), | ||
| defreg(FCRTH), defreg(FCRTL), defreg(FCTTV), defreg(FCRTV), | ||
| defreg(FLA), defreg(EEWR), defreg(FLOP), defreg(FLOL), | ||
| defreg(FLSWCTL), defreg(FLSWCNT), defreg(RXDCTL), defreg(RXDCTL1), | ||
| defreg(MAVTV0), defreg(MAVTV1), defreg(MAVTV2), defreg(MAVTV3), | ||
| defreg(TXSTMPL), defreg(TXSTMPH), defreg(SYSTIML), defreg(SYSTIMH), | ||
| defreg(RXCFGL), defreg(RXUDP), defreg(TIMADJL), defreg(TIMADJH), | ||
| defreg(RXSTMPH), defreg(RXSTMPL), defreg(RXSATRL), defreg(RXSATRH), | ||
| defreg(FLASHT), defreg(TIPG), defreg(RDH), defreg(RDT), | ||
| defreg(RDLEN), defreg(RDBAH), defreg(RDBAL), | ||
| defreg(TXDCTL1), | ||
| defreg(FLSWDATA), | ||
| defreg(CTRL_DUP), | ||
| defreg(EXTCNF_SIZE), | ||
| defreg(EEMNGCTL), | ||
| defreg(EEMNGDATA), | ||
| defreg(FLMNGCTL), | ||
| defreg(FLMNGDATA), | ||
| defreg(FLMNGCNT), | ||
| defreg(TSYNCRXCTL), | ||
| defreg(TSYNCTXCTL), | ||
|
|
||
| /* Aliases */ | ||
| defreg(RDH0_A), defreg(RDT0_A), defreg(RDTR_A), defreg(RDFH_A), | ||
| defreg(RDFT_A), defreg(TDH_A), defreg(TDT_A), defreg(TIDV_A), | ||
| defreg(TDFH_A), defreg(TDFT_A), defreg(RA_A), defreg(RDBAL0_A), | ||
| defreg(TDBAL_A), defreg(TDLEN_A), defreg(VFTA_A), defreg(RDLEN0_A), | ||
| defreg(FCRTL_A), defreg(FCRTH_A) | ||
| }; | ||
|
|
||
| #endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,146 @@ | ||
| /* | ||
| * QEMU igb emulation - shared definitions | ||
| * | ||
| * Copyright (c) 2020-2023 Red Hat, Inc. | ||
| * Copyright (c) 2008 Qumranet | ||
| * | ||
| * Based on work done by: | ||
| * Nir Peleg, Tutis Systems Ltd. for Qumranet Inc. | ||
| * Copyright (c) 2007 Dan Aloni | ||
| * Copyright (c) 2004 Antony T Curtis | ||
| * | ||
| * This library is free software; you can redistribute it and/or | ||
| * modify it under the terms of the GNU Lesser General Public | ||
| * License as published by the Free Software Foundation; either | ||
| * version 2.1 of the License, or (at your option) any later version. | ||
| * | ||
| * This library is distributed in the hope that it will be useful, | ||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| * Lesser General Public License for more details. | ||
| * | ||
| * You should have received a copy of the GNU Lesser General Public | ||
| * License along with this library; if not, see <http://www.gnu.org/licenses/>. | ||
| */ | ||
|
|
||
| #ifndef HW_NET_IGB_COMMON_H | ||
| #define HW_NET_IGB_COMMON_H | ||
|
|
||
| #include "igb_regs.h" | ||
|
|
||
| #define defreg(x) x = (E1000_##x >> 2) | ||
| #define defreg_indexed(x, i) x##i = (E1000_##x(i) >> 2) | ||
| #define defreg_indexeda(x, i) x##i##_A = (E1000_##x##_A(i) >> 2) | ||
|
|
||
| #define defregd(x) defreg_indexed(x, 0), defreg_indexed(x, 1), \ | ||
| defreg_indexed(x, 2), defreg_indexed(x, 3), \ | ||
| defreg_indexed(x, 4), defreg_indexed(x, 5), \ | ||
| defreg_indexed(x, 6), defreg_indexed(x, 7), \ | ||
| defreg_indexed(x, 8), defreg_indexed(x, 9), \ | ||
| defreg_indexed(x, 10), defreg_indexed(x, 11), \ | ||
| defreg_indexed(x, 12), defreg_indexed(x, 13), \ | ||
| defreg_indexed(x, 14), defreg_indexed(x, 15), \ | ||
| defreg_indexeda(x, 0), defreg_indexeda(x, 1), \ | ||
| defreg_indexeda(x, 2), defreg_indexeda(x, 3) | ||
|
|
||
| #define defregv(x) defreg_indexed(x, 0), defreg_indexed(x, 1), \ | ||
| defreg_indexed(x, 2), defreg_indexed(x, 3), \ | ||
| defreg_indexed(x, 4), defreg_indexed(x, 5), \ | ||
| defreg_indexed(x, 6), defreg_indexed(x, 7) | ||
|
|
||
| enum { | ||
| defreg(CTRL), defreg(EECD), defreg(EERD), defreg(GPRC), | ||
| defreg(GPTC), defreg(ICR), defreg(ICS), defreg(IMC), | ||
| defreg(IMS), defreg(LEDCTL), defreg(MANC), defreg(MDIC), | ||
| defreg(MPC), defreg(RCTL), | ||
| defreg(STATUS), defreg(SWSM), defreg(TCTL), | ||
| defreg(TORH), defreg(TORL), defreg(TOTH), | ||
| defreg(TOTL), defreg(TPR), defreg(TPT), | ||
| defreg(WUFC), defreg(RA), defreg(MTA), defreg(CRCERRS), | ||
| defreg(VFTA), defreg(VET), | ||
| defreg(SCC), defreg(ECOL), | ||
| defreg(MCC), defreg(LATECOL), defreg(COLC), defreg(DC), | ||
| defreg(TNCRS), defreg(RLEC), | ||
| defreg(XONRXC), defreg(XONTXC), defreg(XOFFRXC), defreg(XOFFTXC), | ||
| defreg(FCRUC), defreg(TDFH), defreg(TDFT), | ||
| defreg(TDFHS), defreg(TDFTS), defreg(TDFPC), defreg(WUC), | ||
| defreg(WUS), defreg(RDFH), | ||
| defreg(RDFT), defreg(RDFHS), defreg(RDFTS), defreg(RDFPC), | ||
| defreg(IPAV), defreg(IP4AT), defreg(IP6AT), | ||
| defreg(WUPM), defreg(FFMT), | ||
| defreg(IAM), | ||
| defreg(GCR), defreg(TIMINCA), defreg(EIAC), defreg(CTRL_EXT), | ||
| defreg(IVAR0), defreg(MANC2H), | ||
| defreg(MFVAL), defreg(MDEF), defreg(FACTPS), defreg(FTFT), | ||
| defreg(RUC), defreg(ROC), defreg(RFC), defreg(RJC), | ||
| defreg(PRC64), defreg(PRC127), defreg(PRC255), defreg(PRC511), | ||
| defreg(PRC1023), defreg(PRC1522), defreg(PTC64), defreg(PTC127), | ||
| defreg(PTC255), defreg(PTC511), defreg(PTC1023), defreg(PTC1522), | ||
| defreg(GORCL), defreg(GORCH), defreg(GOTCL), defreg(GOTCH), | ||
| defreg(RNBC), defreg(BPRC), defreg(MPRC), defreg(RFCTL), | ||
| defreg(MPTC), defreg(BPTC), | ||
| defreg(IAC), defreg(MGTPRC), defreg(MGTPDC), defreg(MGTPTC), | ||
| defreg(TSCTC), defreg(RXCSUM), defreg(FUNCTAG), defreg(GSCL_1), | ||
| defreg(GSCL_2), defreg(GSCL_3), defreg(GSCL_4), defreg(GSCN_0), | ||
| defreg(GSCN_1), defreg(GSCN_2), defreg(GSCN_3), | ||
| defreg_indexed(EITR, 0), | ||
| defreg(MRQC), defreg(RETA), defreg(RSSRK), | ||
| defreg(PBACLR), defreg(FCAL), defreg(FCAH), defreg(FCT), | ||
| defreg(FCRTH), defreg(FCRTL), defreg(FCTTV), defreg(FCRTV), | ||
| defreg(FLA), defreg(FLOP), | ||
| defreg(MAVTV0), defreg(MAVTV1), defreg(MAVTV2), defreg(MAVTV3), | ||
| defreg(TXSTMPL), defreg(TXSTMPH), defreg(SYSTIML), defreg(SYSTIMH), | ||
| defreg(TIMADJL), defreg(TIMADJH), | ||
| defreg(RXSTMPH), defreg(RXSTMPL), defreg(RXSATRL), defreg(RXSATRH), | ||
| defreg(TIPG), | ||
| defreg(CTRL_DUP), | ||
| defreg(EEMNGCTL), | ||
| defreg(EEMNGDATA), | ||
| defreg(FLMNGCTL), | ||
| defreg(FLMNGDATA), | ||
| defreg(FLMNGCNT), | ||
| defreg(TSYNCRXCTL), | ||
| defreg(TSYNCTXCTL), | ||
| defreg(RLPML), | ||
| defreg(UTA), | ||
|
|
||
| /* Aliases */ | ||
| defreg(RDFH_A), defreg(RDFT_A), defreg(TDFH_A), defreg(TDFT_A), | ||
| defreg(RA_A), defreg(VFTA_A), defreg(FCRTL_A), | ||
|
|
||
| /* Additional regs used by IGB */ | ||
| defreg(FWSM), defreg(SW_FW_SYNC), | ||
|
|
||
| defreg(EICS), defreg(EIMS), defreg(EIMC), defreg(EIAM), | ||
| defreg(EICR), defreg(IVAR_MISC), defreg(GPIE), | ||
|
|
||
| defreg(RXPBS), defregd(RDBAL), defregd(RDBAH), defregd(RDLEN), | ||
| defregd(SRRCTL), defregd(RDH), defregd(RDT), | ||
| defregd(RXDCTL), defregd(RXCTL), defregd(RQDPC), defreg(RA2), | ||
|
|
||
| defreg(TXPBS), defreg(TCTL_EXT), defreg(DTXCTL), defreg(HTCBDPC), | ||
| defregd(TDBAL), defregd(TDBAH), defregd(TDLEN), defregd(TDH), | ||
| defregd(TDT), defregd(TXDCTL), defregd(TXCTL), | ||
| defregd(TDWBAL), defregd(TDWBAH), | ||
|
|
||
| defreg(VT_CTL), | ||
|
|
||
| defregv(P2VMAILBOX), defregv(V2PMAILBOX), defreg(MBVFICR), defreg(MBVFIMR), | ||
| defreg(VFLRE), defreg(VFRE), defreg(VFTE), defreg(WVBR), | ||
| defreg(QDE), defreg(DTXSWC), defreg_indexed(VLVF, 0), | ||
| defregv(VMOLR), defreg(RPLOLR), defregv(VMBMEM), defregv(VMVIR), | ||
|
|
||
| defregv(PVTCTRL), defregv(PVTEICS), defregv(PVTEIMS), defregv(PVTEIMC), | ||
| defregv(PVTEIAC), defregv(PVTEIAM), defregv(PVTEICR), defregv(PVFGPRC), | ||
| defregv(PVFGPTC), defregv(PVFGORC), defregv(PVFGOTC), defregv(PVFMPRC), | ||
| defregv(PVFGPRLBC), defregv(PVFGPTLBC), defregv(PVFGORLBC), defregv(PVFGOTLBC), | ||
|
|
||
| defreg(MTA_A), | ||
|
|
||
| defreg(VTIVAR), defreg(VTIVAR_MISC), | ||
| }; | ||
|
|
||
| uint64_t igb_mmio_read(void *opaque, hwaddr addr, unsigned size); | ||
| void igb_mmio_write(void *opaque, hwaddr addr, uint64_t val, unsigned size); | ||
|
|
||
| #endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,146 @@ | ||
| /* | ||
| * Core code for QEMU igb emulation | ||
| * | ||
| * Datasheet: | ||
| * https://www.intel.com/content/dam/www/public/us/en/documents/datasheets/82576eg-gbe-datasheet.pdf | ||
| * | ||
| * Copyright (c) 2020-2023 Red Hat, Inc. | ||
| * Copyright (c) 2015 Ravello Systems LTD (http://ravellosystems.com) | ||
| * Developed by Daynix Computing LTD (http://www.daynix.com) | ||
| * | ||
| * Authors: | ||
| * Akihiko Odaki <akihiko.odaki@daynix.com> | ||
| * Gal Hammmer <gal.hammer@sap.com> | ||
| * Marcel Apfelbaum <marcel.apfelbaum@gmail.com> | ||
| * Dmitry Fleytman <dmitry@daynix.com> | ||
| * Leonid Bloch <leonid@daynix.com> | ||
| * Yan Vugenfirer <yan@daynix.com> | ||
| * | ||
| * Based on work done by: | ||
| * Nir Peleg, Tutis Systems Ltd. for Qumranet Inc. | ||
| * Copyright (c) 2008 Qumranet | ||
| * Based on work done by: | ||
| * Copyright (c) 2007 Dan Aloni | ||
| * Copyright (c) 2004 Antony T Curtis | ||
| * | ||
| * This library is free software; you can redistribute it and/or | ||
| * modify it under the terms of the GNU Lesser General Public | ||
| * License as published by the Free Software Foundation; either | ||
| * version 2.1 of the License, or (at your option) any later version. | ||
| * | ||
| * This library is distributed in the hope that it will be useful, | ||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| * Lesser General Public License for more details. | ||
| * | ||
| * You should have received a copy of the GNU Lesser General Public | ||
| * License along with this library; if not, see <http://www.gnu.org/licenses/>. | ||
| */ | ||
|
|
||
| #ifndef HW_NET_IGB_CORE_H | ||
| #define HW_NET_IGB_CORE_H | ||
|
|
||
| #define E1000E_MAC_SIZE (0x8000) | ||
| #define IGB_EEPROM_SIZE (1024) | ||
|
|
||
| #define IGB_INTR_NUM (25) | ||
| #define IGB_MSIX_VEC_NUM (10) | ||
| #define IGBVF_MSIX_VEC_NUM (3) | ||
| #define IGB_NUM_QUEUES (16) | ||
|
|
||
| typedef struct IGBCore IGBCore; | ||
|
|
||
| enum { PHY_R = BIT(0), | ||
| PHY_W = BIT(1), | ||
| PHY_RW = PHY_R | PHY_W }; | ||
|
|
||
| typedef struct IGBIntrDelayTimer_st { | ||
| QEMUTimer *timer; | ||
| bool running; | ||
| uint32_t delay_reg; | ||
| uint32_t delay_resolution_ns; | ||
| IGBCore *core; | ||
| } IGBIntrDelayTimer; | ||
|
|
||
| struct IGBCore { | ||
| uint32_t mac[E1000E_MAC_SIZE]; | ||
| uint16_t phy[MAX_PHY_REG_ADDRESS + 1]; | ||
| uint16_t eeprom[IGB_EEPROM_SIZE]; | ||
|
|
||
| uint8_t rx_desc_len; | ||
|
|
||
| QEMUTimer *autoneg_timer; | ||
|
|
||
| struct igb_tx { | ||
| uint16_t vlan; /* VLAN Tag */ | ||
| uint16_t mss; /* Maximum Segment Size */ | ||
| bool tse; /* TCP/UDP Segmentation Enable */ | ||
| bool ixsm; /* Insert IP Checksum */ | ||
| bool txsm; /* Insert TCP/UDP Checksum */ | ||
|
|
||
| bool first; | ||
| bool skip_cp; | ||
|
|
||
| struct NetTxPkt *tx_pkt; | ||
| } tx[IGB_NUM_QUEUES]; | ||
|
|
||
| struct NetRxPkt *rx_pkt; | ||
|
|
||
| bool has_vnet; | ||
| int max_queue_num; | ||
|
|
||
| IGBIntrDelayTimer eitr[IGB_INTR_NUM]; | ||
|
|
||
| VMChangeStateEntry *vmstate; | ||
|
|
||
| uint32_t eitr_guest_value[IGB_INTR_NUM]; | ||
|
|
||
| uint8_t permanent_mac[ETH_ALEN]; | ||
|
|
||
| NICState *owner_nic; | ||
| PCIDevice *owner; | ||
| void (*owner_start_recv)(PCIDevice *d); | ||
|
|
||
| int64_t timadj; | ||
| }; | ||
|
|
||
| void | ||
| igb_core_write(IGBCore *core, hwaddr addr, uint64_t val, unsigned size); | ||
|
|
||
| uint64_t | ||
| igb_core_read(IGBCore *core, hwaddr addr, unsigned size); | ||
|
|
||
| void | ||
| igb_core_pci_realize(IGBCore *regs, | ||
| const uint16_t *eeprom_templ, | ||
| uint32_t eeprom_size, | ||
| const uint8_t *macaddr); | ||
|
|
||
| void | ||
| igb_core_reset(IGBCore *core); | ||
|
|
||
| void | ||
| igb_core_pre_save(IGBCore *core); | ||
|
|
||
| int | ||
| igb_core_post_load(IGBCore *core); | ||
|
|
||
| void | ||
| igb_core_set_link_status(IGBCore *core); | ||
|
|
||
| void | ||
| igb_core_pci_uninit(IGBCore *core); | ||
|
|
||
| bool | ||
| igb_can_receive(IGBCore *core); | ||
|
|
||
| ssize_t | ||
| igb_receive(IGBCore *core, const uint8_t *buf, size_t size); | ||
|
|
||
| ssize_t | ||
| igb_receive_iov(IGBCore *core, const struct iovec *iov, int iovcnt); | ||
|
|
||
| void | ||
| igb_start_recv(IGBCore *core); | ||
|
|
||
| #endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,327 @@ | ||
| /* | ||
| * QEMU Intel 82576 SR/IOV Ethernet Controller Emulation | ||
| * | ||
| * Datasheet: | ||
| * https://www.intel.com/content/dam/www/public/us/en/documents/datasheets/82576eg-gbe-datasheet.pdf | ||
| * | ||
| * Copyright (c) 2020-2023 Red Hat, Inc. | ||
| * Copyright (c) 2015 Ravello Systems LTD (http://ravellosystems.com) | ||
| * Developed by Daynix Computing LTD (http://www.daynix.com) | ||
| * | ||
| * Authors: | ||
| * Akihiko Odaki <akihiko.odaki@daynix.com> | ||
| * Gal Hammmer <gal.hammer@sap.com> | ||
| * Marcel Apfelbaum <marcel.apfelbaum@gmail.com> | ||
| * Dmitry Fleytman <dmitry@daynix.com> | ||
| * Leonid Bloch <leonid@daynix.com> | ||
| * Yan Vugenfirer <yan@daynix.com> | ||
| * | ||
| * Based on work done by: | ||
| * Nir Peleg, Tutis Systems Ltd. for Qumranet Inc. | ||
| * Copyright (c) 2008 Qumranet | ||
| * Based on work done by: | ||
| * Copyright (c) 2007 Dan Aloni | ||
| * Copyright (c) 2004 Antony T Curtis | ||
| * | ||
| * This library is free software; you can redistribute it and/or | ||
| * modify it under the terms of the GNU Lesser General Public | ||
| * License as published by the Free Software Foundation; either | ||
| * version 2.1 of the License, or (at your option) any later version. | ||
| * | ||
| * This library is distributed in the hope that it will be useful, | ||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| * Lesser General Public License for more details. | ||
| * | ||
| * You should have received a copy of the GNU Lesser General Public | ||
| * License along with this library; if not, see <http://www.gnu.org/licenses/>. | ||
| */ | ||
|
|
||
| #include "qemu/osdep.h" | ||
| #include "hw/hw.h" | ||
| #include "hw/net/mii.h" | ||
| #include "hw/pci/pci_device.h" | ||
| #include "hw/pci/pcie.h" | ||
| #include "hw/pci/msix.h" | ||
| #include "net/eth.h" | ||
| #include "net/net.h" | ||
| #include "igb_common.h" | ||
| #include "igb_core.h" | ||
| #include "trace.h" | ||
| #include "qapi/error.h" | ||
|
|
||
| #define TYPE_IGBVF "igbvf" | ||
| OBJECT_DECLARE_SIMPLE_TYPE(IgbVfState, IGBVF) | ||
|
|
||
| #define IGBVF_MMIO_BAR_IDX (0) | ||
| #define IGBVF_MSIX_BAR_IDX (3) | ||
|
|
||
| #define IGBVF_MMIO_SIZE (16 * 1024) | ||
| #define IGBVF_MSIX_SIZE (16 * 1024) | ||
|
|
||
| struct IgbVfState { | ||
| PCIDevice parent_obj; | ||
|
|
||
| MemoryRegion mmio; | ||
| MemoryRegion msix; | ||
| }; | ||
|
|
||
| static hwaddr vf_to_pf_addr(hwaddr addr, uint16_t vfn, bool write) | ||
| { | ||
| switch (addr) { | ||
| case E1000_CTRL: | ||
| case E1000_CTRL_DUP: | ||
| return E1000_PVTCTRL(vfn); | ||
| case E1000_EICS: | ||
| return E1000_PVTEICS(vfn); | ||
| case E1000_EIMS: | ||
| return E1000_PVTEIMS(vfn); | ||
| case E1000_EIMC: | ||
| return E1000_PVTEIMC(vfn); | ||
| case E1000_EIAC: | ||
| return E1000_PVTEIAC(vfn); | ||
| case E1000_EIAM: | ||
| return E1000_PVTEIAM(vfn); | ||
| case E1000_EICR: | ||
| return E1000_PVTEICR(vfn); | ||
| case E1000_EITR(0): | ||
| case E1000_EITR(1): | ||
| case E1000_EITR(2): | ||
| return E1000_EITR(22) + (addr - E1000_EITR(0)) - vfn * 0xC; | ||
| case E1000_IVAR0: | ||
| return E1000_VTIVAR + vfn * 4; | ||
| case E1000_IVAR_MISC: | ||
| return E1000_VTIVAR_MISC + vfn * 4; | ||
| case 0x0F04: /* PBACL */ | ||
| return E1000_PBACLR; | ||
| case 0x0F0C: /* PSRTYPE */ | ||
| return E1000_PSRTYPE(vfn); | ||
| case E1000_V2PMAILBOX(0): | ||
| return E1000_V2PMAILBOX(vfn); | ||
| case E1000_VMBMEM(0) ... E1000_VMBMEM(0) + 0x3F: | ||
| return addr + vfn * 0x40; | ||
| case E1000_RDBAL_A(0): | ||
| return E1000_RDBAL(vfn); | ||
| case E1000_RDBAL_A(1): | ||
| return E1000_RDBAL(vfn + IGB_MAX_VF_FUNCTIONS); | ||
| case E1000_RDBAH_A(0): | ||
| return E1000_RDBAH(vfn); | ||
| case E1000_RDBAH_A(1): | ||
| return E1000_RDBAH(vfn + IGB_MAX_VF_FUNCTIONS); | ||
| case E1000_RDLEN_A(0): | ||
| return E1000_RDLEN(vfn); | ||
| case E1000_RDLEN_A(1): | ||
| return E1000_RDLEN(vfn + IGB_MAX_VF_FUNCTIONS); | ||
| case E1000_SRRCTL_A(0): | ||
| return E1000_SRRCTL(vfn); | ||
| case E1000_SRRCTL_A(1): | ||
| return E1000_SRRCTL(vfn + IGB_MAX_VF_FUNCTIONS); | ||
| case E1000_RDH_A(0): | ||
| return E1000_RDH(vfn); | ||
| case E1000_RDH_A(1): | ||
| return E1000_RDH(vfn + IGB_MAX_VF_FUNCTIONS); | ||
| case E1000_RXCTL_A(0): | ||
| return E1000_RXCTL(vfn); | ||
| case E1000_RXCTL_A(1): | ||
| return E1000_RXCTL(vfn + IGB_MAX_VF_FUNCTIONS); | ||
| case E1000_RDT_A(0): | ||
| return E1000_RDT(vfn); | ||
| case E1000_RDT_A(1): | ||
| return E1000_RDT(vfn + IGB_MAX_VF_FUNCTIONS); | ||
| case E1000_RXDCTL_A(0): | ||
| return E1000_RXDCTL(vfn); | ||
| case E1000_RXDCTL_A(1): | ||
| return E1000_RXDCTL(vfn + IGB_MAX_VF_FUNCTIONS); | ||
| case E1000_RQDPC_A(0): | ||
| return E1000_RQDPC(vfn); | ||
| case E1000_RQDPC_A(1): | ||
| return E1000_RQDPC(vfn + IGB_MAX_VF_FUNCTIONS); | ||
| case E1000_TDBAL_A(0): | ||
| return E1000_TDBAL(vfn); | ||
| case E1000_TDBAL_A(1): | ||
| return E1000_TDBAL(vfn + IGB_MAX_VF_FUNCTIONS); | ||
| case E1000_TDBAH_A(0): | ||
| return E1000_TDBAH(vfn); | ||
| case E1000_TDBAH_A(1): | ||
| return E1000_TDBAH(vfn + IGB_MAX_VF_FUNCTIONS); | ||
| case E1000_TDLEN_A(0): | ||
| return E1000_TDLEN(vfn); | ||
| case E1000_TDLEN_A(1): | ||
| return E1000_TDLEN(vfn + IGB_MAX_VF_FUNCTIONS); | ||
| case E1000_TDH_A(0): | ||
| return E1000_TDH(vfn); | ||
| case E1000_TDH_A(1): | ||
| return E1000_TDH(vfn + IGB_MAX_VF_FUNCTIONS); | ||
| case E1000_TXCTL_A(0): | ||
| return E1000_TXCTL(vfn); | ||
| case E1000_TXCTL_A(1): | ||
| return E1000_TXCTL(vfn + IGB_MAX_VF_FUNCTIONS); | ||
| case E1000_TDT_A(0): | ||
| return E1000_TDT(vfn); | ||
| case E1000_TDT_A(1): | ||
| return E1000_TDT(vfn + IGB_MAX_VF_FUNCTIONS); | ||
| case E1000_TXDCTL_A(0): | ||
| return E1000_TXDCTL(vfn); | ||
| case E1000_TXDCTL_A(1): | ||
| return E1000_TXDCTL(vfn + IGB_MAX_VF_FUNCTIONS); | ||
| case E1000_TDWBAL_A(0): | ||
| return E1000_TDWBAL(vfn); | ||
| case E1000_TDWBAL_A(1): | ||
| return E1000_TDWBAL(vfn + IGB_MAX_VF_FUNCTIONS); | ||
| case E1000_TDWBAH_A(0): | ||
| return E1000_TDWBAH(vfn); | ||
| case E1000_TDWBAH_A(1): | ||
| return E1000_TDWBAH(vfn + IGB_MAX_VF_FUNCTIONS); | ||
| case E1000_VFGPRC: | ||
| return E1000_PVFGPRC(vfn); | ||
| case E1000_VFGPTC: | ||
| return E1000_PVFGPTC(vfn); | ||
| case E1000_VFGORC: | ||
| return E1000_PVFGORC(vfn); | ||
| case E1000_VFGOTC: | ||
| return E1000_PVFGOTC(vfn); | ||
| case E1000_VFMPRC: | ||
| return E1000_PVFMPRC(vfn); | ||
| case E1000_VFGPRLBC: | ||
| return E1000_PVFGPRLBC(vfn); | ||
| case E1000_VFGPTLBC: | ||
| return E1000_PVFGPTLBC(vfn); | ||
| case E1000_VFGORLBC: | ||
| return E1000_PVFGORLBC(vfn); | ||
| case E1000_VFGOTLBC: | ||
| return E1000_PVFGOTLBC(vfn); | ||
| case E1000_STATUS: | ||
| case E1000_FRTIMER: | ||
| if (write) { | ||
| return HWADDR_MAX; | ||
| } | ||
| /* fallthrough */ | ||
| case 0x34E8: /* PBTWAC */ | ||
| case 0x24E8: /* PBRWAC */ | ||
| return addr; | ||
| } | ||
|
|
||
| trace_igbvf_wrn_io_addr_unknown(addr); | ||
|
|
||
| return HWADDR_MAX; | ||
| } | ||
|
|
||
| static void igbvf_write_config(PCIDevice *dev, uint32_t addr, uint32_t val, | ||
| int len) | ||
| { | ||
| trace_igbvf_write_config(addr, val, len); | ||
| pci_default_write_config(dev, addr, val, len); | ||
| } | ||
|
|
||
| static uint64_t igbvf_mmio_read(void *opaque, hwaddr addr, unsigned size) | ||
| { | ||
| PCIDevice *vf = PCI_DEVICE(opaque); | ||
| PCIDevice *pf = pcie_sriov_get_pf(vf); | ||
|
|
||
| addr = vf_to_pf_addr(addr, pcie_sriov_vf_number(vf), false); | ||
| return addr == HWADDR_MAX ? 0 : igb_mmio_read(pf, addr, size); | ||
| } | ||
|
|
||
| static void igbvf_mmio_write(void *opaque, hwaddr addr, uint64_t val, | ||
| unsigned size) | ||
| { | ||
| PCIDevice *vf = PCI_DEVICE(opaque); | ||
| PCIDevice *pf = pcie_sriov_get_pf(vf); | ||
|
|
||
| addr = vf_to_pf_addr(addr, pcie_sriov_vf_number(vf), true); | ||
| if (addr != HWADDR_MAX) { | ||
| igb_mmio_write(pf, addr, val, size); | ||
| } | ||
| } | ||
|
|
||
| static const MemoryRegionOps mmio_ops = { | ||
| .read = igbvf_mmio_read, | ||
| .write = igbvf_mmio_write, | ||
| .endianness = DEVICE_LITTLE_ENDIAN, | ||
| .impl = { | ||
| .min_access_size = 4, | ||
| .max_access_size = 4, | ||
| }, | ||
| }; | ||
|
|
||
| static void igbvf_pci_realize(PCIDevice *dev, Error **errp) | ||
| { | ||
| IgbVfState *s = IGBVF(dev); | ||
| int ret; | ||
| int i; | ||
|
|
||
| dev->config_write = igbvf_write_config; | ||
|
|
||
| memory_region_init_io(&s->mmio, OBJECT(dev), &mmio_ops, s, "igbvf-mmio", | ||
| IGBVF_MMIO_SIZE); | ||
| pcie_sriov_vf_register_bar(dev, IGBVF_MMIO_BAR_IDX, &s->mmio); | ||
|
|
||
| memory_region_init(&s->msix, OBJECT(dev), "igbvf-msix", IGBVF_MSIX_SIZE); | ||
| pcie_sriov_vf_register_bar(dev, IGBVF_MSIX_BAR_IDX, &s->msix); | ||
|
|
||
| ret = msix_init(dev, IGBVF_MSIX_VEC_NUM, &s->msix, IGBVF_MSIX_BAR_IDX, 0, | ||
| &s->msix, IGBVF_MSIX_BAR_IDX, 0x2000, 0x70, errp); | ||
| if (ret) { | ||
| return; | ||
| } | ||
|
|
||
| for (i = 0; i < IGBVF_MSIX_VEC_NUM; i++) { | ||
| msix_vector_use(dev, i); | ||
| } | ||
|
|
||
| if (pcie_endpoint_cap_init(dev, 0xa0) < 0) { | ||
| hw_error("Failed to initialize PCIe capability"); | ||
| } | ||
|
|
||
| if (pcie_aer_init(dev, 1, 0x100, 0x40, errp) < 0) { | ||
| hw_error("Failed to initialize AER capability"); | ||
| } | ||
|
|
||
| pcie_ari_init(dev, 0x150, 1); | ||
| } | ||
|
|
||
| static void igbvf_pci_uninit(PCIDevice *dev) | ||
| { | ||
| IgbVfState *s = IGBVF(dev); | ||
|
|
||
| pcie_aer_exit(dev); | ||
| pcie_cap_exit(dev); | ||
| msix_unuse_all_vectors(dev); | ||
| msix_uninit(dev, &s->msix, &s->msix); | ||
| } | ||
|
|
||
| static void igbvf_class_init(ObjectClass *class, void *data) | ||
| { | ||
| DeviceClass *dc = DEVICE_CLASS(class); | ||
| PCIDeviceClass *c = PCI_DEVICE_CLASS(class); | ||
|
|
||
| c->realize = igbvf_pci_realize; | ||
| c->exit = igbvf_pci_uninit; | ||
| c->vendor_id = PCI_VENDOR_ID_INTEL; | ||
| c->device_id = E1000_DEV_ID_82576_VF; | ||
| c->revision = 1; | ||
| c->class_id = PCI_CLASS_NETWORK_ETHERNET; | ||
|
|
||
| dc->desc = "Intel 82576 Virtual Function"; | ||
| dc->user_creatable = false; | ||
|
|
||
| set_bit(DEVICE_CATEGORY_NETWORK, dc->categories); | ||
| } | ||
|
|
||
| static const TypeInfo igbvf_info = { | ||
| .name = TYPE_IGBVF, | ||
| .parent = TYPE_PCI_DEVICE, | ||
| .instance_size = sizeof(IgbVfState), | ||
| .class_init = igbvf_class_init, | ||
| .interfaces = (InterfaceInfo[]) { | ||
| { INTERFACE_PCIE_DEVICE }, | ||
| { } | ||
| }, | ||
| }; | ||
|
|
||
| static void igb_register_types(void) | ||
| { | ||
| type_register_static(&igbvf_info); | ||
| } | ||
|
|
||
| type_init(igb_register_types) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| # SPDX-License-Identifier: GPL-2.0-or-later | ||
| # ethtool tests for igb registers, interrupts, etc | ||
|
|
||
| from avocado_qemu import LinuxTest | ||
|
|
||
| class IGB(LinuxTest): | ||
| """ | ||
| :avocado: tags=accel:kvm | ||
| :avocado: tags=arch:x86_64 | ||
| :avocado: tags=distro:fedora | ||
| :avocado: tags=distro_version:31 | ||
| :avocado: tags=machine:q35 | ||
| """ | ||
|
|
||
| timeout = 180 | ||
|
|
||
| def test(self): | ||
| self.require_accelerator('kvm') | ||
| kernel_url = self.distro.pxeboot_url + 'vmlinuz' | ||
| kernel_hash = '5b6f6876e1b5bda314f93893271da0d5777b1f3c' | ||
| kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) | ||
| initrd_url = self.distro.pxeboot_url + 'initrd.img' | ||
| initrd_hash = 'dd0340a1b39bd28f88532babd4581c67649ec5b1' | ||
| initrd_path = self.fetch_asset(initrd_url, asset_hash=initrd_hash) | ||
|
|
||
| # Ideally we want to test MSI as well, but it is blocked by a bug | ||
| # fixed with: | ||
| # https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=28e96556baca7056d11d9fb3cdd0aba4483e00d8 | ||
| kernel_params = self.distro.default_kernel_params + ' pci=nomsi' | ||
|
|
||
| self.vm.add_args('-kernel', kernel_path, | ||
| '-initrd', initrd_path, | ||
| '-append', kernel_params, | ||
| '-accel', 'kvm', | ||
| '-device', 'igb') | ||
| self.launch_and_wait() | ||
| self.ssh_command('dnf -y install ethtool') | ||
| self.ssh_command('ethtool -t eth1 offline') |