diff --git a/hw/core/machine.c b/hw/core/machine.c index 775add0795..943974d411 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -41,6 +41,8 @@ GlobalProperty hw_compat_6_0[] = { { "gpex-pcihost", "allow-unmapped-accesses", "false" }, { "i8042", "extended-state", "false"}, { "nvme-ns", "eui64-default", "off"}, + { "e1000", "init-vet", "off" }, + { "e1000e", "init-vet", "off" }, }; const size_t hw_compat_6_0_len = G_N_ELEMENTS(hw_compat_6_0); diff --git a/hw/net/can/can_sja1000.c b/hw/net/can/can_sja1000.c index 42d2f99dfb..34eea684ce 100644 --- a/hw/net/can/can_sja1000.c +++ b/hw/net/can/can_sja1000.c @@ -275,6 +275,10 @@ static void buff2frame_pel(const uint8_t *buff, qemu_can_frame *frame) } frame->can_dlc = buff[0] & 0x0f; + if (frame->can_dlc > 8) { + frame->can_dlc = 8; + } + if (buff[0] & 0x80) { /* Extended */ frame->can_id |= QEMU_CAN_EFF_FLAG; frame->can_id |= buff[1] << 21; /* ID.28~ID.21 */ @@ -311,6 +315,10 @@ static void buff2frame_bas(const uint8_t *buff, qemu_can_frame *frame) } frame->can_dlc = buff[1] & 0x0f; + if (frame->can_dlc > 8) { + frame->can_dlc = 8; + } + for (i = 0; i < frame->can_dlc; i++) { frame->data[i] = buff[2 + i]; } diff --git a/hw/net/e1000.c b/hw/net/e1000.c index 4f75b44cfc..a30546c5d5 100644 --- a/hw/net/e1000.c +++ b/hw/net/e1000.c @@ -29,6 +29,7 @@ #include "hw/pci/pci.h" #include "hw/qdev-properties.h" #include "migration/vmstate.h" +#include "net/eth.h" #include "net/net.h" #include "net/checksum.h" #include "sysemu/sysemu.h" @@ -130,10 +131,13 @@ struct E1000State_st { #define E1000_FLAG_MIT_BIT 1 #define E1000_FLAG_MAC_BIT 2 #define E1000_FLAG_TSO_BIT 3 +#define E1000_FLAG_VET_BIT 4 #define E1000_FLAG_AUTONEG (1 << E1000_FLAG_AUTONEG_BIT) #define E1000_FLAG_MIT (1 << E1000_FLAG_MIT_BIT) #define E1000_FLAG_MAC (1 << E1000_FLAG_MAC_BIT) #define E1000_FLAG_TSO (1 << E1000_FLAG_TSO_BIT) +#define E1000_FLAG_VET (1 << E1000_FLAG_VET_BIT) + uint32_t compat_flags; bool received_tx_tso; bool use_tso_for_migration; @@ -361,6 +365,13 @@ e1000_autoneg_timer(void *opaque) } } +static bool e1000_vet_init_need(void *opaque) +{ + E1000State *s = opaque; + + return chkflag(VET); +} + static void e1000_reset(void *opaque) { E1000State *d = opaque; @@ -386,6 +397,10 @@ static void e1000_reset(void *opaque) } e1000x_reset_mac_addr(d->nic, d->mac_reg, macaddr); + + if (e1000_vet_init_need(d)) { + d->mac_reg[VET] = ETH_P_VLAN; + } } static void @@ -1737,6 +1752,8 @@ static Property e1000_properties[] = { compat_flags, E1000_FLAG_MAC_BIT, true), DEFINE_PROP_BIT("migrate_tso_props", E1000State, compat_flags, E1000_FLAG_TSO_BIT, true), + DEFINE_PROP_BIT("init-vet", E1000State, + compat_flags, E1000_FLAG_VET_BIT, true), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/net/e1000e.c b/hw/net/e1000e.c index a8a77eca95..ac96f7665a 100644 --- a/hw/net/e1000e.c +++ b/hw/net/e1000e.c @@ -35,6 +35,7 @@ #include "qemu/osdep.h" #include "qemu/units.h" +#include "net/eth.h" #include "net/net.h" #include "net/tap.h" #include "qemu/module.h" @@ -79,7 +80,7 @@ struct E1000EState { bool disable_vnet; E1000ECore core; - + bool init_vet; }; #define E1000E_MMIO_IDX 0 @@ -527,6 +528,10 @@ static void e1000e_qdev_reset(DeviceState *dev) trace_e1000e_cb_qdev_reset(); e1000e_core_reset(&s->core); + + if (s->init_vet) { + s->core.mac[VET] = ETH_P_VLAN; + } } static int e1000e_pre_save(void *opaque) @@ -666,6 +671,7 @@ static Property e1000e_properties[] = { e1000e_prop_subsys_ven, uint16_t), DEFINE_PROP_SIGNED("subsys", E1000EState, subsys, 0, e1000e_prop_subsys, uint16_t), + DEFINE_PROP_BOOL("init-vet", E1000EState, init_vet, true), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c index b75f2ab8fc..8ae6fb7e14 100644 --- a/hw/net/e1000e_core.c +++ b/hw/net/e1000e_core.c @@ -731,7 +731,7 @@ e1000e_process_tx_desc(E1000ECore *core, if (e1000x_vlan_enabled(core->mac) && e1000x_is_vlan_txd(txd_lower)) { net_tx_pkt_setup_vlan_header_ex(tx->tx_pkt, - le16_to_cpu(dp->upper.fields.special), core->vet); + le16_to_cpu(dp->upper.fields.special), core->mac[VET]); } if (e1000e_tx_pkt_send(core, tx, queue_index)) { e1000e_on_tx_done_update_stats(core, tx->tx_pkt); @@ -1012,7 +1012,7 @@ e1000e_receive_filter(E1000ECore *core, const uint8_t *buf, int size) { uint32_t rctl = core->mac[RCTL]; - if (e1000x_is_vlan_packet(buf, core->vet) && + if (e1000x_is_vlan_packet(buf, core->mac[VET]) && e1000x_vlan_rx_filter_enabled(core->mac)) { uint16_t vid = lduw_be_p(buf + 14); uint32_t vfta = ldl_le_p((uint32_t *)(core->mac + VFTA) + @@ -1285,7 +1285,6 @@ e1000e_write_lgcy_rx_descr(E1000ECore *core, uint8_t *desc, &d->special); d->errors = (uint8_t) (le32_to_cpu(status_flags) >> 24); d->status = (uint8_t) le32_to_cpu(status_flags); - d->special = 0; } static inline void @@ -1686,7 +1685,7 @@ e1000e_receive_iov(E1000ECore *core, const struct iovec *iov, int iovcnt) } net_rx_pkt_attach_iovec_ex(core->rx_pkt, iov, iovcnt, iov_ofs, - e1000x_vlan_enabled(core->mac), core->vet); + e1000x_vlan_enabled(core->mac), core->mac[VET]); e1000e_rss_parse_packet(core, core->rx_pkt, &rss_info); e1000e_rx_ring_init(core, &rxr, rss_info.queue); @@ -2397,8 +2396,7 @@ static void e1000e_set_vet(E1000ECore *core, int index, uint32_t val) { core->mac[VET] = val & 0xffff; - core->vet = le16_to_cpu(core->mac[VET]); - trace_e1000e_vlan_vet(core->vet); + trace_e1000e_vlan_vet(core->mac[VET]); } static void diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c index f6bd8c53b1..41f796a247 100644 --- a/hw/net/vmxnet3.c +++ b/hw/net/vmxnet3.c @@ -1381,7 +1381,7 @@ static void vmxnet3_validate_interrupts(VMXNET3State *s) } } -static void vmxnet3_validate_queues(VMXNET3State *s) +static bool vmxnet3_validate_queues(VMXNET3State *s) { /* * txq_num and rxq_num are total number of queues @@ -1390,12 +1390,18 @@ static void vmxnet3_validate_queues(VMXNET3State *s) */ if (s->txq_num > VMXNET3_DEVICE_MAX_TX_QUEUES) { - hw_error("Bad TX queues number: %d\n", s->txq_num); + qemu_log_mask(LOG_GUEST_ERROR, "vmxnet3: Bad TX queues number: %d\n", + s->txq_num); + return false; } if (s->rxq_num > VMXNET3_DEVICE_MAX_RX_QUEUES) { - hw_error("Bad RX queues number: %d\n", s->rxq_num); + qemu_log_mask(LOG_GUEST_ERROR, "vmxnet3: Bad RX queues number: %d\n", + s->rxq_num); + return false; } + + return true; } static void vmxnet3_activate_device(VMXNET3State *s) @@ -1419,6 +1425,16 @@ static void vmxnet3_activate_device(VMXNET3State *s) return; } + s->txq_num = + VMXNET3_READ_DRV_SHARED8(d, s->drv_shmem, devRead.misc.numTxQueues); + s->rxq_num = + VMXNET3_READ_DRV_SHARED8(d, s->drv_shmem, devRead.misc.numRxQueues); + + VMW_CFPRN("Number of TX/RX queues %u/%u", s->txq_num, s->rxq_num); + if (!vmxnet3_validate_queues(s)) { + return; + } + vmxnet3_adjust_by_guest_type(s); vmxnet3_update_features(s); vmxnet3_update_pm_state(s); @@ -1445,14 +1461,6 @@ static void vmxnet3_activate_device(VMXNET3State *s) VMXNET3_READ_DRV_SHARED8(d, s->drv_shmem, devRead.intrConf.autoMask); VMW_CFPRN("Automatic interrupt masking is %d", (int)s->auto_int_masking); - s->txq_num = - VMXNET3_READ_DRV_SHARED8(d, s->drv_shmem, devRead.misc.numTxQueues); - s->rxq_num = - VMXNET3_READ_DRV_SHARED8(d, s->drv_shmem, devRead.misc.numRxQueues); - - VMW_CFPRN("Number of TX/RX queues %u/%u", s->txq_num, s->rxq_num); - vmxnet3_validate_queues(s); - qdescr_table_pa = VMXNET3_READ_DRV_SHARED64(d, s->drv_shmem, devRead.misc.queueDescPA); VMW_CFPRN("TX queues descriptors table is at 0x%" PRIx64, qdescr_table_pa); @@ -2404,7 +2412,9 @@ static int vmxnet3_post_load(void *opaque, int version_id) } } - vmxnet3_validate_queues(s); + if (!vmxnet3_validate_queues(s)) { + return -1; + } vmxnet3_validate_interrupts(s); return 0;