Re: [PATCH v8 4/6] hw/ppc/pegasos2: Fix PCI interrupt routing

2023-03-06 Thread Mark Cave-Ayland

On 06/03/2023 22:14, BALATON Zoltan wrote:

Can you explain a bit more about how the PCI interrupt lines are connected to both 
the MV64361 and VT8231? The reason for asking is that I see a similar pattern in 
the bonito board, but there I can't see how those lines would be used because they 
can also raise a CPU interrupt, yet it is a different one compared to the 8259.


Given that we know from Bernhard's tests that the fuloong2e board works with 
pci_bus_irqs() included in via_isa_realize() which overwrites the bonito 
equivalent, I'm wondering if the mv_pirq array is actually needed at all and


Also I'd be cautious of tests on fuloong2e unless it was done with binary known to 
work on real machine as we have found before that those binaries for the real machine 
expect IDE to use IRQ 14/15 like pegasos2 guests but the e.g. the default config in 
Linux would also work with native IRQs as documented in the datasheet but that's 
apparently not how it really works on real hardware (proven by binaries written for 
and tested on real hardware did not work with the model which followed the datasheet) 
so we had to change that later to match hardware. You may remember this, it was found 
around the time when we tested via-ide with different guests and some worked some 
didn't with the native mode IRQs. This suggests that datasheets and tests with code 
not verified to work on real hardware is unreliable (so are PCI standards that the 
VIA chip apparently does not follow). So I'd only trust guests that were running on 
the real machine.


This may have been true when these discussions occurred a couple of years ago, but 
things are different now. I'm now confident that there is no such thing as a "half 
native" mode, and in fact the confusing behaviour being exhibited was because the 
code was trying to work around the fact that the VIA device was missing PCI IRQ routing.


Can you provide details of the kernel, initrd and rootfs that you use to test the 
fuloong2e board?



ATB,

Mark.



Re: [PATCH v8 3/6] hw/isa/vt82c686: Implement PCI IRQ routing

2023-03-06 Thread Bernhard Beschow



Am 6. März 2023 12:33:31 UTC schrieb BALATON Zoltan :
>The real VIA south bridges implement a PCI IRQ router which is configured
>by the BIOS or the OS. In order to respect these configurations, QEMU
>needs to implement it as well. The real chip may allow routing IRQs from
>internal functions independently of PCI interrupts but since guests
>usually configute it to a single shared interrupt we don't model that
>here for simplicity.
>
>Note: The implementation was taken from piix4_set_irq() in hw/isa/piix4.
>
>Suggested-by: Bernhard Beschow 
>Signed-off-by: BALATON Zoltan 
>Tested-by: Rene Engel 
>---
> hw/isa/vt82c686.c | 42 ++
> 1 file changed, 42 insertions(+)
>
>diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c
>index 8900d87f59..3383ab7e2d 100644
>--- a/hw/isa/vt82c686.c
>+++ b/hw/isa/vt82c686.c
>@@ -600,6 +600,46 @@ void via_isa_set_irq(PCIDevice *d, int n, int level)
> qemu_set_irq(s->isa_irqs_in[n], level);
> }
> 
>+static int via_isa_get_pci_irq(const ViaISAState *s, int irq_num)
>+{
>+switch (irq_num) {
>+case 0:
>+return s->dev.config[0x55] >> 4;
>+case 1:
>+return s->dev.config[0x56] & 0xf;
>+case 2:
>+return s->dev.config[0x56] >> 4;
>+case 3:
>+return s->dev.config[0x57] >> 4;
>+}
>+return 0;
>+}
>+
>+static void via_isa_set_pci_irq(void *opaque, int irq_num, int level)
>+{
>+ViaISAState *s = opaque;
>+PCIBus *bus = pci_get_bus(>dev);
>+int i, pic_level, pic_irq = via_isa_get_pci_irq(s, irq_num);
>+
>+/* IRQ 0: disabled, IRQ 2,8,13: reserved */
>+if (!pic_irq) {
>+return;
>+}
>+if (unlikely(pic_irq == 2 || pic_irq == 8 || pic_irq == 13)) {
>+qemu_log_mask(LOG_GUEST_ERROR, "Invalid ISA IRQ routing");

I wonder whether we should return here or not. But well, that's probably why 
it's reserved. Let's see how it goes and revist in case we learn more...

Reviewed-by: Bernhard Beschow 

>+}
>+
>+/* The pic level is the logical OR of all the PCI irqs mapped to it. */
>+pic_level = 0;
>+for (i = 0; i < PCI_NUM_PINS; i++) {
>+if (pic_irq == via_isa_get_pci_irq(s, i)) {
>+pic_level |= pci_bus_get_irq_level(bus, i);
>+}
>+}
>+/* Now we change the pic irq level according to the via irq mappings. */
>+qemu_set_irq(s->isa_irqs_in[pic_irq], pic_level);
>+}
>+
> static void via_isa_realize(PCIDevice *d, Error **errp)
> {
> ViaISAState *s = VIA_ISA(d);
>@@ -620,6 +660,8 @@ static void via_isa_realize(PCIDevice *d, Error **errp)
> i8254_pit_init(isa_bus, 0x40, 0, NULL);
> i8257_dma_init(isa_bus, 0);
> 
>+qdev_init_gpio_in_named(dev, via_isa_set_pci_irq, "pirq", PCI_NUM_PINS);
>+
> /* RTC */
> qdev_prop_set_int32(DEVICE(>rtc), "base_year", 2000);
> if (!qdev_realize(DEVICE(>rtc), BUS(isa_bus), errp)) {



Re: [PATCH v8 4/6] hw/ppc/pegasos2: Fix PCI interrupt routing

2023-03-06 Thread Mark Cave-Ayland

On 06/03/2023 22:00, BALATON Zoltan wrote:


On Mon, 6 Mar 2023, Mark Cave-Ayland wrote:

On 06/03/2023 12:33, BALATON Zoltan wrote:

According to the PegasosII schematics the PCI interrupt lines are
connected to both the gpp pins of the Mv64361 north bridge and the
PINT pins of the VT8231 south bridge so guests can get interrupts from
either of these. So far we only had the MV64361 connections which
worked for on board devices but for additional PCI devices (such as
network or sound card added with -device) guest OSes expect interrupt
from the ISA IRQ 9 where the firmware routes these PCI interrupts in
VT8231 ISA bridge. After the previous patches we can now model this
and also remove the board specific connection from mv64361. Also
configure routing of these lines when using Virtual Open Firmware to
match board firmware for guests that expect this.

This fixes PCI interrupts on pegasos2 under Linux, MorphOS and AmigaOS.

Signed-off-by: BALATON Zoltan 
Reviewed-by: Daniel Henrique Barboza 
Tested-by: Rene Engel 
---
  hw/pci-host/mv64361.c |  4 
  hw/ppc/pegasos2.c | 26 +-
  2 files changed, 25 insertions(+), 5 deletions(-)

diff --git a/hw/pci-host/mv64361.c b/hw/pci-host/mv64361.c
index 298564f1f5..19e8031a3f 100644
--- a/hw/pci-host/mv64361.c
+++ b/hw/pci-host/mv64361.c
@@ -873,10 +873,6 @@ static void mv64361_realize(DeviceState *dev, Error **errp)
  }
  sysbus_init_irq(SYS_BUS_DEVICE(dev), >cpu_irq);
  qdev_init_gpio_in_named(dev, mv64361_gpp_irq, "gpp", 32);
-    /* FIXME: PCI IRQ connections may be board specific */
-    for (i = 0; i < PCI_NUM_PINS; i++) {
-    s->pci[1].irq[i] = qdev_get_gpio_in_named(dev, "gpp", 12 + i);
-    }
  }
    static void mv64361_reset(DeviceState *dev)
diff --git a/hw/ppc/pegasos2.c b/hw/ppc/pegasos2.c
index b0ada9c963..ded5dc2dc9 100644
--- a/hw/ppc/pegasos2.c
+++ b/hw/ppc/pegasos2.c
@@ -73,6 +73,8 @@ struct Pegasos2MachineState {
  MachineState parent_obj;
  PowerPCCPU *cpu;
  DeviceState *mv;
+    qemu_irq mv_pirq[PCI_NUM_PINS];
+    qemu_irq via_pirq[PCI_NUM_PINS];
  Vof *vof;
  void *fdt_blob;
  uint64_t kernel_addr;
@@ -95,6 +97,15 @@ static void pegasos2_cpu_reset(void *opaque)
  }
  }
  +static void pegasos2_pci_irq(void *opaque, int n, int level)
+{
+    Pegasos2MachineState *pm = opaque;
+
+    /* PCI interrupt lines are connected to both MV64361 and VT8231 */
+    qemu_set_irq(pm->mv_pirq[n], level);
+    qemu_set_irq(pm->via_pirq[n], level);
+}
+


Can you explain a bit more about how the PCI interrupt lines are connected to both 
the MV64361 and VT8231? The reason for asking is that I see a similar


I think I already did that in previous replies but I try again. In pagasosII 
schematics at https://www.powerdeveloper.org/platforms/pegasos/schematics


Sheet 2 Marvell System Controller shows PINTA-D are connected to MV64361 MPP12-15 
pins that are also called GPP in the docs (I think these are referred to as either 
Multi Purpose or General Purpose Pins).


Sheet 18 VIA VT8231 Southbridge shows INTR_A-D connected to VT8231 PINTA-D pins, 
which are connected to INTA-D on sheet 13 PCI Top Level. Sheet 1 Top Level Pegasos 
shows that Sheet 13 INTA-D are connected to Sheet 2 PINTA-D.


pattern in the bonito board, but there I can't see how those lines would be used 
because they can also raise a CPU interrupt, yet it is a different one compared to 
the 8259.


Both the MV64361 and VT8231 have interrupt mask registers which allow the guest to 
choose where it wants an interrupt from. I guess different guests could use one or 
the other, unlikely they would use both but they could even do that if they wanted. I 
guess in bonito it's also maskable so the guest could set up irqs by programing the 
apprpriate north and south bridge registers. A guest which has ISA drivers (probably 
most) may likely want to route them to ISA IRQs in the VIA chip. Maybe this strange 
behaviour has to do with Windows compatibility and standards back then which never 
really took off like CHRP for PP


Given that we know from Bernhard's tests that the fuloong2e board works with 
pci_bus_irqs() included in via_isa_realize() which overwrites the bonito 
equivalent, I'm wondering if the mv_pirq array is actually needed at all and 
whether it may just be a debugging aid? Certainly it makes things simpler to just 
route everything to the VIA device.


In any case calling pci_bus_irqs in the VIA device would be wrong and connections 


Why? In general the PCI bus should be managed completely internally and not exposed 
to the board. This should certainly be the case for the VIA chipsets which can be 
used across multiple QEMU machines.


should be made here by the board as that correctly models the hardware separating 
components and allows different boards to use the chip model in the future. I 
remember that I've implemenred connections to MV64361 for something but I don't 
remember which guest so as this already 

Re: [PATCH] Fix slli_uw decoding

2023-03-06 Thread Ivan Klokov
Hello guys. I would be really appreciate if you look this patch.It would be nice to merge it to new release 8.0 27.02.2023, 12:02, "Ivan Klokov" :The decoding of the slli_uw currently contains decodingerror: shamt part of opcode has six bits, not five.Fixes 3de1fb71("target/riscv: update disas.c for xnor/orn/andn and slli.uw")Signed-off-by: Ivan Klokov --- disas/riscv.c | 8  1 file changed, 4 insertions(+), 4 deletions(-)diff --git a/disas/riscv.c b/disas/riscv.cindex ddda687c13..03cfefb0d3 100644--- a/disas/riscv.c+++ b/disas/riscv.c@@ -1647,7 +1647,7 @@ const rv_opcode_data opcode_data[] = { { "clzw", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 }, { "clzw", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 }, { "cpopw", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },- { "slli.uw", rv_codec_i_sh5, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 },+ { "slli.uw", rv_codec_i_sh6, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 }, { "add.uw", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, { "rolw", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, { "rorw", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },@@ -2617,10 +2617,10 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa isa) switch (((inst >> 12) & 0b111)) { case 0: op = rv_op_addiw; break; case 1:- switch (((inst >> 25) & 0b111)) {+ switch (((inst >> 26) & 0b11)) { case 0: op = rv_op_slliw; break;- case 4: op = rv_op_slli_uw; break;- case 48:+ case 2: op = rv_op_slli_uw; break;+ case 24: switch ((inst >> 20) & 0b1) { case 0b0: op = rv_op_clzw; break; case 0b1: op = rv_op_ctzw; break;--2.34.1   -- Kind regards,Ivan Klokov 

[PULL 40/51] tests/qtest/libqos/e1000e: Export macreg functions

2023-03-06 Thread Jason Wang
From: Akihiko Odaki 

They will be useful for igb testing.

Signed-off-by: Akihiko Odaki 
Reviewed-by: Thomas Huth 
Signed-off-by: Jason Wang 
---
 tests/qtest/libqos/e1000e.c | 12 
 tests/qtest/libqos/e1000e.h | 12 
 2 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/tests/qtest/libqos/e1000e.c b/tests/qtest/libqos/e1000e.c
index 28fb305..925654c 100644
--- a/tests/qtest/libqos/e1000e.c
+++ b/tests/qtest/libqos/e1000e.c
@@ -36,18 +36,6 @@
 
 #define E1000E_RING_LEN (0x1000)
 
-static void e1000e_macreg_write(QE1000E *d, uint32_t reg, uint32_t val)
-{
-QE1000E_PCI *d_pci = container_of(d, QE1000E_PCI, e1000e);
-qpci_io_writel(_pci->pci_dev, d_pci->mac_regs, reg, val);
-}
-
-static uint32_t e1000e_macreg_read(QE1000E *d, uint32_t reg)
-{
-QE1000E_PCI *d_pci = container_of(d, QE1000E_PCI, e1000e);
-return qpci_io_readl(_pci->pci_dev, d_pci->mac_regs, reg);
-}
-
 void e1000e_tx_ring_push(QE1000E *d, void *descr)
 {
 QE1000E_PCI *d_pci = container_of(d, QE1000E_PCI, e1000e);
diff --git a/tests/qtest/libqos/e1000e.h b/tests/qtest/libqos/e1000e.h
index 5e2b201..30643c8 100644
--- a/tests/qtest/libqos/e1000e.h
+++ b/tests/qtest/libqos/e1000e.h
@@ -42,6 +42,18 @@ struct QE1000E_PCI {
 QE1000E e1000e;
 };
 
+static inline void e1000e_macreg_write(QE1000E *d, uint32_t reg, uint32_t val)
+{
+QE1000E_PCI *d_pci = container_of(d, QE1000E_PCI, e1000e);
+qpci_io_writel(_pci->pci_dev, d_pci->mac_regs, reg, val);
+}
+
+static inline uint32_t e1000e_macreg_read(QE1000E *d, uint32_t reg)
+{
+QE1000E_PCI *d_pci = container_of(d, QE1000E_PCI, e1000e);
+return qpci_io_readl(_pci->pci_dev, d_pci->mac_regs, reg);
+}
+
 void e1000e_wait_isr(QE1000E *d, uint16_t msg_id);
 void e1000e_tx_ring_push(QE1000E *d, void *descr);
 void e1000e_rx_ring_push(QE1000E *d, void *descr);
-- 
2.7.4




[PULL 49/51] hw/net/eepro100: Remove instance EEPRO100State::has_extended_tcb_support

2023-03-06 Thread Jason Wang
From: Philippe Mathieu-Daudé 

'has_extended_tcb_support' is accessed read-only and is present
in the class definition. No need to duplicate it in the instance
state. Directly access the class field.

Signed-off-by: Philippe Mathieu-Daudé 
Signed-off-by: Jason Wang 
---
 hw/net/eepro100.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/hw/net/eepro100.c b/hw/net/eepro100.c
index ab20558..d775790 100644
--- a/hw/net/eepro100.c
+++ b/hw/net/eepro100.c
@@ -292,7 +292,6 @@ struct EEPRO100State {
 
 /* Quasi static device properties (no need to save them). */
 uint16_t stats_size;
-bool has_extended_tcb_support;
 };
 
 /* Word indices in EEPROM. */
@@ -511,7 +510,6 @@ static void e100_pci_reset(DeviceState *dev)
 pci_set_byte(pci_conf + PCI_MAX_LAT, 0x18);
 
 s->stats_size = info->stats_size;
-s->has_extended_tcb_support = info->has_extended_tcb_support;
 
 switch (device) {
 case i82550:
@@ -746,6 +744,8 @@ static void read_cb(EEPRO100State *s)
 
 static void tx_command(EEPRO100State *s)
 {
+EEPRO100Class *ek = EEPRO100_GET_CLASS(s);
+const E100PCIDeviceInfo *info = ek->info;
 const MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED;
 uint32_t tbd_array = s->tx.tbd_array_addr;
 uint16_t tcb_bytes = s->tx.tcb_bytes & 0x3fff;
@@ -782,7 +782,7 @@ static void tx_command(EEPRO100State *s)
 uint16_t tx_buffer_size;
 uint16_t tx_buffer_el;
 
-if (s->has_extended_tcb_support && !(s->configuration[6] & BIT(4))) {
+if (info->has_extended_tcb_support && !(s->configuration[6] & BIT(4))) 
{
 /* Extended Flexible TCB. */
 for (; tbd_count < 2; tbd_count++) {
 ldl_le_pci_dma(>dev, tbd_address, _buffer_address, 
attrs);
-- 
2.7.4




[PULL 39/51] tests/qtest/e1000e-test: Fabricate ethernet header

2023-03-06 Thread Jason Wang
From: Akihiko Odaki 

e1000e understands ethernet header so fabricate something convincing.

Signed-off-by: Akihiko Odaki 
Reviewed-by: Thomas Huth 
Signed-off-by: Jason Wang 
---
 tests/qtest/e1000e-test.c   | 25 +++--
 tests/qtest/libqos/e1000e.h |  2 ++
 2 files changed, 17 insertions(+), 10 deletions(-)

diff --git a/tests/qtest/e1000e-test.c b/tests/qtest/e1000e-test.c
index b63a4d3..de9738f 100644
--- a/tests/qtest/e1000e-test.c
+++ b/tests/qtest/e1000e-test.c
@@ -27,6 +27,7 @@
 #include "qemu/osdep.h"
 #include "libqtest-single.h"
 #include "libqos/pci-pc.h"
+#include "net/eth.h"
 #include "qemu/sockets.h"
 #include "qemu/iov.h"
 #include "qemu/module.h"
@@ -35,9 +36,13 @@
 #include "libqos/e1000e.h"
 #include "hw/net/e1000_regs.h"
 
+static const struct eth_header packet = {
+.h_dest = E1000E_ADDRESS,
+.h_source = E1000E_ADDRESS,
+};
+
 static void e1000e_send_verify(QE1000E *d, int *test_sockets, QGuestAllocator 
*alloc)
 {
-static const char test[] = "TEST";
 struct e1000_tx_desc descr;
 char buffer[64];
 int ret;
@@ -45,7 +50,7 @@ static void e1000e_send_verify(QE1000E *d, int *test_sockets, 
QGuestAllocator *a
 
 /* Prepare test data buffer */
 uint64_t data = guest_alloc(alloc, sizeof(buffer));
-memwrite(data, test, sizeof(test));
+memwrite(data, , sizeof(packet));
 
 /* Prepare TX descriptor */
 memset(, 0, sizeof(descr));
@@ -71,7 +76,7 @@ static void e1000e_send_verify(QE1000E *d, int *test_sockets, 
QGuestAllocator *a
 g_assert_cmpint(ret, == , sizeof(recv_len));
 ret = recv(test_sockets[0], buffer, sizeof(buffer), 0);
 g_assert_cmpint(ret, ==, sizeof(buffer));
-g_assert_cmpstr(buffer, == , test);
+g_assert_false(memcmp(buffer, , sizeof(packet)));
 
 /* Free test data buffer */
 guest_free(alloc, data);
@@ -81,15 +86,15 @@ static void e1000e_receive_verify(QE1000E *d, int 
*test_sockets, QGuestAllocator
 {
 union e1000_rx_desc_extended descr;
 
-char test[] = "TEST";
-int len = htonl(sizeof(test));
+struct eth_header test_iov = packet;
+int len = htonl(sizeof(packet));
 struct iovec iov[] = {
 {
 .iov_base = ,
 .iov_len = sizeof(len),
 },{
-.iov_base = test,
-.iov_len = sizeof(test),
+.iov_base = _iov,
+.iov_len = sizeof(packet),
 },
 };
 
@@ -97,8 +102,8 @@ static void e1000e_receive_verify(QE1000E *d, int 
*test_sockets, QGuestAllocator
 int ret;
 
 /* Send a dummy packet to device's socket*/
-ret = iov_send(test_sockets[0], iov, 2, 0, sizeof(len) + sizeof(test));
-g_assert_cmpint(ret, == , sizeof(test) + sizeof(len));
+ret = iov_send(test_sockets[0], iov, 2, 0, sizeof(len) + sizeof(packet));
+g_assert_cmpint(ret, == , sizeof(packet) + sizeof(len));
 
 /* Prepare test data buffer */
 uint64_t data = guest_alloc(alloc, sizeof(buffer));
@@ -119,7 +124,7 @@ static void e1000e_receive_verify(QE1000E *d, int 
*test_sockets, QGuestAllocator
 
 /* Check data sent to the backend */
 memread(data, buffer, sizeof(buffer));
-g_assert_cmpstr(buffer, == , test);
+g_assert_false(memcmp(buffer, , sizeof(packet)));
 
 /* Free test data buffer */
 guest_free(alloc, data);
diff --git a/tests/qtest/libqos/e1000e.h b/tests/qtest/libqos/e1000e.h
index 091ce13..5e2b201 100644
--- a/tests/qtest/libqos/e1000e.h
+++ b/tests/qtest/libqos/e1000e.h
@@ -25,6 +25,8 @@
 #define E1000E_RX0_MSG_ID   (0)
 #define E1000E_TX0_MSG_ID   (1)
 
+#define E1000E_ADDRESS { 0x52, 0x54, 0x00, 0x12, 0x34, 0x56 }
+
 typedef struct QE1000E QE1000E;
 typedef struct QE1000E_PCI QE1000E_PCI;
 
-- 
2.7.4




[PULL 50/51] hw/net/eepro100: Remove instance's EEPRO100State::device

2023-03-06 Thread Jason Wang
From: Philippe Mathieu-Daudé 

'device' is accessed read-only and is present in the class
definition. No need to duplicate it in the instance state.
Directly access the class field.

Signed-off-by: Philippe Mathieu-Daudé 
Signed-off-by: Jason Wang 
---
 hw/net/eepro100.c | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/hw/net/eepro100.c b/hw/net/eepro100.c
index d775790..bce3776 100644
--- a/hw/net/eepro100.c
+++ b/hw/net/eepro100.c
@@ -263,7 +263,6 @@ struct EEPRO100State {
 /* region must not be saved by nic_save. */
 uint16_t mdimem[32];
 eeprom_t *eeprom;
-uint32_t device;/* device variant */
 /* (cu_base + cu_offset) address the next command block in the command 
block list. */
 uint32_t cu_base;   /* CU base address */
 uint32_t cu_offset; /* CU address offset */
@@ -591,6 +590,9 @@ static void e100_pci_reset(DeviceState *dev)
 
 static void nic_selective_reset(EEPRO100State * s)
 {
+EEPRO100Class *ek = EEPRO100_GET_CLASS(s);
+const E100PCIDeviceInfo *info = ek->info;
+
 size_t i;
 uint16_t *eeprom_contents = eeprom93xx_data(s->eeprom);
 #if 0
@@ -598,8 +600,9 @@ static void nic_selective_reset(EEPRO100State * s)
 #endif
 memcpy(eeprom_contents, s->conf.macaddr.a, 6);
 eeprom_contents[EEPROM_ID] = EEPROM_ID_VALID;
-if (s->device == i82557B || s->device == i82557C)
+if (info->device == i82557B || info->device == i82557C) {
 eeprom_contents[5] = 0x0100;
+}
 eeprom_contents[EEPROM_PHY_ID] = 1;
 uint16_t sum = 0;
 for (i = 0; i < EEPROM_SIZE - 1; i++) {
@@ -1794,7 +1797,7 @@ static const VMStateDescription vmstate_eepro100 = {
 VMSTATE_UNUSED(19*4),
 VMSTATE_UINT16_ARRAY(mdimem, EEPRO100State, 32),
 /* The eeprom should be saved and restored by its own routines. */
-VMSTATE_UINT32(device, EEPRO100State),
+VMSTATE_UNUSED(sizeof(uint32_t)), /* was device variant */
 /* TODO check device. */
 VMSTATE_UINT32(cu_base, EEPRO100State),
 VMSTATE_UINT32(cu_offset, EEPRO100State),
@@ -1848,12 +1851,9 @@ static NetClientInfo net_eepro100_info = {
 static void e100_nic_realize(PCIDevice *pci_dev, Error **errp)
 {
 EEPRO100State *s = DO_UPCAST(EEPRO100State, dev, pci_dev);
-EEPRO100Class *ek = EEPRO100_GET_CLASS(s);
 
 TRACE(OTHER, logout("\n"));
 
-s->device = ek->info->device;
-
 /* Add 64 * 2 EEPROM. i82557 and i82558 support a 64 word EEPROM,
  * i82559 and later support 64 or 256 word EEPROM. */
 s->eeprom = eeprom93xx_new(_dev->qdev, EEPROM_SIZE);
-- 
2.7.4




[PULL 46/51] hw/net/eepro100: Introduce TYPE_EEPRO100 QOM abstract parent

2023-03-06 Thread Jason Wang
From: Philippe Mathieu-Daudé 

Have all the EEPRO100-based devices share a common (abstract)
QOM parent.

Signed-off-by: Philippe Mathieu-Daudé 
Signed-off-by: Jason Wang 
---
 hw/net/eepro100.c | 60 ++-
 1 file changed, 42 insertions(+), 18 deletions(-)

diff --git a/hw/net/eepro100.c b/hw/net/eepro100.c
index dce7503..4b5d455 100644
--- a/hw/net/eepro100.c
+++ b/hw/net/eepro100.c
@@ -235,8 +235,20 @@ typedef enum {
 ru_ready = 4
 } ru_state_t;
 
-typedef struct {
+#define TYPE_EEPRO100 "eepro100"
+OBJECT_DECLARE_TYPE(EEPRO100State, EEPRO100Class, EEPRO100)
+
+struct EEPRO100Class {
+/*< private >*/
+PCIDeviceClass parent_class;
+/*< public >*/
+};
+
+struct EEPRO100State {
+/*< private >*/
 PCIDevice dev;
+/*< public >*/
+
 /* Hash register (multicast mask array, multiple individual addresses). */
 uint8_t mult[8];
 MemoryRegion mmio_bar;
@@ -279,7 +291,7 @@ typedef struct {
 /* Quasi static device properties (no need to save them). */
 uint16_t stats_size;
 bool has_extended_tcb_support;
-} EEPRO100State;
+};
 
 /* Word indices in EEPROM. */
 typedef enum {
@@ -2055,43 +2067,55 @@ static Property e100_properties[] = {
 DEFINE_PROP_END_OF_LIST(),
 };
 
-static void eepro100_class_init(ObjectClass *klass, void *data)
+static void eepro100_base_class_init(ObjectClass *klass, void *data)
 {
 DeviceClass *dc = DEVICE_CLASS(klass);
 PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
 E100PCIDeviceInfo *info;
 
-info = eepro100_get_class_by_name(object_class_get_name(klass));
 
 set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
 device_class_set_props(dc, e100_properties);
-dc->desc = info->desc;
 k->vendor_id = PCI_VENDOR_ID_INTEL;
 k->class_id = PCI_CLASS_NETWORK_ETHERNET;
 k->romfile = "pxe-eepro100.rom";
 k->realize = e100_nic_realize;
 k->exit = pci_nic_uninit;
+
+info = eepro100_get_class_by_name(object_class_get_name(klass));
+if (!info) {
+/* base class */
+return;
+}
+dc->desc = info->desc;
 k->device_id = info->device_id;
 k->revision = info->revision;
 k->subsystem_vendor_id = info->subsystem_vendor_id;
 k->subsystem_id = info->subsystem_id;
 }
 
+static const TypeInfo eepro100_base_info = {
+.name  = TYPE_EEPRO100,
+.parent= TYPE_PCI_DEVICE,
+.abstract  = true,
+.class_init= eepro100_base_class_init,
+.class_size= sizeof(EEPRO100Class),
+.instance_size = sizeof(EEPRO100State),
+.instance_init = eepro100_instance_init,
+.interfaces = (InterfaceInfo[]) {
+{ INTERFACE_CONVENTIONAL_PCI_DEVICE },
+{ },
+},
+};
+
 static void eepro100_register_types(void)
 {
-size_t i;
-for (i = 0; i < ARRAY_SIZE(e100_devices); i++) {
-TypeInfo type_info = {};
-E100PCIDeviceInfo *info = _devices[i];
-
-type_info.name = info->name;
-type_info.parent = TYPE_PCI_DEVICE;
-type_info.class_init = eepro100_class_init;
-type_info.instance_size = sizeof(EEPRO100State);
-type_info.instance_init = eepro100_instance_init;
-type_info.interfaces = (InterfaceInfo[]) {
-{ INTERFACE_CONVENTIONAL_PCI_DEVICE },
-{ },
+type_register_static(_base_info);
+
+for (size_t i = 0; i < ARRAY_SIZE(e100_devices); i++) {
+TypeInfo type_info = {
+.name   = e100_devices[i].name,
+.parent = TYPE_EEPRO100,
 };
 
 type_register(_info);
-- 
2.7.4




[PULL 47/51] hw/net/eepro100: Convert reset handler to DeviceReset

2023-03-06 Thread Jason Wang
From: Philippe Mathieu-Daudé 

Signed-off-by: Philippe Mathieu-Daudé 
Signed-off-by: Jason Wang 
---
 hw/net/eepro100.c | 11 +++
 1 file changed, 3 insertions(+), 8 deletions(-)

diff --git a/hw/net/eepro100.c b/hw/net/eepro100.c
index 4b5d455..722fb55 100644
--- a/hw/net/eepro100.c
+++ b/hw/net/eepro100.c
@@ -486,8 +486,9 @@ static void eepro100_fcp_interrupt(EEPRO100State * s)
 }
 #endif
 
-static void e100_pci_reset(EEPRO100State *s, Error **errp)
+static void e100_pci_reset(DeviceState *dev)
 {
+EEPRO100State *s = EEPRO100(dev);
 E100PCIDeviceInfo *info = eepro100_get_class(s);
 uint32_t device = s->device;
 uint8_t *pci_conf = s->dev.config;
@@ -1847,18 +1848,11 @@ static void e100_nic_realize(PCIDevice *pci_dev, Error 
**errp)
 {
 EEPRO100State *s = DO_UPCAST(EEPRO100State, dev, pci_dev);
 E100PCIDeviceInfo *info = eepro100_get_class(s);
-Error *local_err = NULL;
 
 TRACE(OTHER, logout("\n"));
 
 s->device = info->device;
 
-e100_pci_reset(s, _err);
-if (local_err) {
-error_propagate(errp, local_err);
-return;
-}
-
 /* Add 64 * 2 EEPROM. i82557 and i82558 support a 64 word EEPROM,
  * i82559 and later support 64 or 256 word EEPROM. */
 s->eeprom = eeprom93xx_new(_dev->qdev, EEPROM_SIZE);
@@ -2076,6 +2070,7 @@ static void eepro100_base_class_init(ObjectClass *klass, 
void *data)
 
 set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
 device_class_set_props(dc, e100_properties);
+dc->reset = e100_pci_reset;
 k->vendor_id = PCI_VENDOR_ID_INTEL;
 k->class_id = PCI_CLASS_NETWORK_ETHERNET;
 k->romfile = "pxe-eepro100.rom";
-- 
2.7.4




[PULL 45/51] hw/net/eepro100: Abort if pci_add_capability() ever fail

2023-03-06 Thread Jason Wang
From: Philippe Mathieu-Daudé 

If pci_add_capability() ever fail, the EEPRO100 device is broken,
which is a bug. No need to report that to the user, abort instead.

Signed-off-by: Philippe Mathieu-Daudé 
Signed-off-by: Jason Wang 
---
 hw/net/eepro100.c | 9 ++---
 1 file changed, 2 insertions(+), 7 deletions(-)

diff --git a/hw/net/eepro100.c b/hw/net/eepro100.c
index dc07984..dce7503 100644
--- a/hw/net/eepro100.c
+++ b/hw/net/eepro100.c
@@ -549,13 +549,8 @@ static void e100_pci_reset(EEPRO100State *s, Error **errp)
 if (info->power_management) {
 /* Power Management Capabilities */
 int cfg_offset = 0xdc;
-int r = pci_add_capability(>dev, PCI_CAP_ID_PM,
-   cfg_offset, PCI_PM_SIZEOF,
-   errp);
-if (r < 0) {
-return;
-}
-
+pci_add_capability(>dev, PCI_CAP_ID_PM, cfg_offset, PCI_PM_SIZEOF,
+   _abort);
 pci_set_word(pci_conf + cfg_offset + PCI_PM_PMC, 0x7e21);
 #if 0 /* TODO: replace dummy code for power management emulation. */
 /* TODO: Power Management Control / Status. */
-- 
2.7.4




[PULL 16/51] e1000e: Introduce e1000_rx_desc_union

2023-03-06 Thread Jason Wang
From: Akihiko Odaki 

Before this change, e1000e_write_packet_to_guest() allocated the
receive descriptor buffer as an array of uint8_t. This does not ensure
the buffer is sufficiently aligned.

Introduce e1000_rx_desc_union type, a union type of all receive
descriptor types to correct this.

Signed-off-by: Akihiko Odaki 
Signed-off-by: Jason Wang 
---
 hw/net/e1000_regs.h  |   1 -
 hw/net/e1000e_core.c | 115 +--
 2 files changed, 57 insertions(+), 59 deletions(-)

diff --git a/hw/net/e1000_regs.h b/hw/net/e1000_regs.h
index 6a36573..4545fe2 100644
--- a/hw/net/e1000_regs.h
+++ b/hw/net/e1000_regs.h
@@ -1061,7 +1061,6 @@ union e1000_rx_desc_packet_split {
 #define E1000_RING_DESC_LEN_SHIFT (4)
 
 #define E1000_MIN_RX_DESC_LEN   E1000_RING_DESC_LEN
-#define E1000_MAX_RX_DESC_LEN   (sizeof(union e1000_rx_desc_packet_split))
 
 /* Receive Descriptor bit definitions */
 #define E1000_RXD_STAT_DD   0x01/* Descriptor Done */
diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c
index b867066..d8c17ba 100644
--- a/hw/net/e1000e_core.c
+++ b/hw/net/e1000e_core.c
@@ -55,6 +55,12 @@
 
 #define E1000E_MAX_TX_FRAGS (64)
 
+union e1000_rx_desc_union {
+struct e1000_rx_desc legacy;
+union e1000_rx_desc_extended extended;
+union e1000_rx_desc_packet_split packet_split;
+};
+
 static inline void
 e1000e_set_interrupt_cause(E1000ECore *core, uint32_t val);
 
@@ -1053,29 +1059,28 @@ e1000e_receive_filter(E1000ECore *core, const uint8_t 
*buf, int size)
 }
 
 static inline void
-e1000e_read_lgcy_rx_descr(E1000ECore *core, uint8_t *desc, hwaddr *buff_addr)
+e1000e_read_lgcy_rx_descr(E1000ECore *core, struct e1000_rx_desc *desc,
+  hwaddr *buff_addr)
 {
-struct e1000_rx_desc *d = (struct e1000_rx_desc *) desc;
-*buff_addr = le64_to_cpu(d->buffer_addr);
+*buff_addr = le64_to_cpu(desc->buffer_addr);
 }
 
 static inline void
-e1000e_read_ext_rx_descr(E1000ECore *core, uint8_t *desc, hwaddr *buff_addr)
+e1000e_read_ext_rx_descr(E1000ECore *core, union e1000_rx_desc_extended *desc,
+ hwaddr *buff_addr)
 {
-union e1000_rx_desc_extended *d = (union e1000_rx_desc_extended *) desc;
-*buff_addr = le64_to_cpu(d->read.buffer_addr);
+*buff_addr = le64_to_cpu(desc->read.buffer_addr);
 }
 
 static inline void
-e1000e_read_ps_rx_descr(E1000ECore *core, uint8_t *desc,
+e1000e_read_ps_rx_descr(E1000ECore *core,
+union e1000_rx_desc_packet_split *desc,
 hwaddr (*buff_addr)[MAX_PS_BUFFERS])
 {
 int i;
-union e1000_rx_desc_packet_split *d =
-(union e1000_rx_desc_packet_split *) desc;
 
 for (i = 0; i < MAX_PS_BUFFERS; i++) {
-(*buff_addr)[i] = le64_to_cpu(d->read.buffer_addr[i]);
+(*buff_addr)[i] = le64_to_cpu(desc->read.buffer_addr[i]);
 }
 
 trace_e1000e_rx_desc_ps_read((*buff_addr)[0], (*buff_addr)[1],
@@ -1083,17 +1088,17 @@ e1000e_read_ps_rx_descr(E1000ECore *core, uint8_t *desc,
 }
 
 static inline void
-e1000e_read_rx_descr(E1000ECore *core, uint8_t *desc,
+e1000e_read_rx_descr(E1000ECore *core, union e1000_rx_desc_union *desc,
  hwaddr (*buff_addr)[MAX_PS_BUFFERS])
 {
 if (e1000e_rx_use_legacy_descriptor(core)) {
-e1000e_read_lgcy_rx_descr(core, desc, &(*buff_addr)[0]);
+e1000e_read_lgcy_rx_descr(core, >legacy, &(*buff_addr)[0]);
 (*buff_addr)[1] = (*buff_addr)[2] = (*buff_addr)[3] = 0;
 } else {
 if (core->mac[RCTL] & E1000_RCTL_DTYP_PS) {
-e1000e_read_ps_rx_descr(core, desc, buff_addr);
+e1000e_read_ps_rx_descr(core, >packet_split, buff_addr);
 } else {
-e1000e_read_ext_rx_descr(core, desc, &(*buff_addr)[0]);
+e1000e_read_ext_rx_descr(core, >extended, &(*buff_addr)[0]);
 (*buff_addr)[1] = (*buff_addr)[2] = (*buff_addr)[3] = 0;
 }
 }
@@ -1264,7 +1269,7 @@ func_exit:
 }
 
 static inline void
-e1000e_write_lgcy_rx_descr(E1000ECore *core, uint8_t *desc,
+e1000e_write_lgcy_rx_descr(E1000ECore *core, struct e1000_rx_desc *desc,
struct NetRxPkt *pkt,
const E1000E_RSSInfo *rss_info,
uint16_t length)
@@ -1272,71 +1277,66 @@ e1000e_write_lgcy_rx_descr(E1000ECore *core, uint8_t 
*desc,
 uint32_t status_flags, rss, mrq;
 uint16_t ip_id;
 
-struct e1000_rx_desc *d = (struct e1000_rx_desc *) desc;
-
 assert(!rss_info->enabled);
 
-d->length = cpu_to_le16(length);
-d->csum = 0;
+desc->length = cpu_to_le16(length);
+desc->csum = 0;
 
 e1000e_build_rx_metadata(core, pkt, pkt != NULL,
  rss_info,
  , ,
  _flags, _id,
- >special);
-d->errors = (uint8_t) (le32_to_cpu(status_flags) >> 24);
-d->status = (uint8_t) le32_to_cpu(status_flags);
+   

[PULL 30/51] e1000e: Combine rx traces

2023-03-06 Thread Jason Wang
From: Akihiko Odaki 

Whether a packet will be written back to the guest depends on the
remaining space of the queue. Therefore, e1000e_rx_written_to_guest and
e1000e_rx_not_written_to_guest should log the index of the queue instead
of generated interrupts. This also removes the need of
e1000e_rx_rss_dispatched_to_queue, which logs the queue index.

Signed-off-by: Akihiko Odaki 
Signed-off-by: Jason Wang 
---
 hw/net/e1000e_core.c | 6 ++
 hw/net/trace-events  | 5 ++---
 2 files changed, 4 insertions(+), 7 deletions(-)

diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c
index 76c7814..4fec6df 100644
--- a/hw/net/e1000e_core.c
+++ b/hw/net/e1000e_core.c
@@ -1759,8 +1759,6 @@ e1000e_receive_internal(E1000ECore *core, const struct 
iovec *iov, int iovcnt,
 e1000e_rss_parse_packet(core, core->rx_pkt, _info);
 e1000e_rx_ring_init(core, , rss_info.queue);
 
-trace_e1000e_rx_rss_dispatched_to_queue(rxr.i->idx);
-
 total_size = net_rx_pkt_get_total_len(core->rx_pkt) +
 e1000x_fcs_len(core->mac);
 
@@ -1786,12 +1784,12 @@ e1000e_receive_internal(E1000ECore *core, const struct 
iovec *iov, int iovcnt,
 rdmts_hit = e1000e_rx_descr_threshold_hit(core, rxr.i);
 n |= e1000e_rx_wb_interrupt_cause(core, rxr.i->idx, rdmts_hit);
 
-trace_e1000e_rx_written_to_guest(n);
+trace_e1000e_rx_written_to_guest(rxr.i->idx);
 } else {
 n |= E1000_ICS_RXO;
 retval = 0;
 
-trace_e1000e_rx_not_written_to_guest(n);
+trace_e1000e_rx_not_written_to_guest(rxr.i->idx);
 }
 
 if (!e1000e_intrmgr_delay_rx_causes(core, )) {
diff --git a/hw/net/trace-events b/hw/net/trace-events
index f7257a0..d24ba94 100644
--- a/hw/net/trace-events
+++ b/hw/net/trace-events
@@ -165,8 +165,8 @@ e1000e_rx_descr(int ridx, uint64_t base, uint8_t len) "Next 
RX descriptor: ring
 e1000e_rx_set_rctl(uint32_t rctl) "RCTL = 0x%x"
 e1000e_rx_receive_iov(int iovcnt) "Received vector of %d fragments"
 e1000e_rx_flt_dropped(void) "Received packet dropped by RX filter"
-e1000e_rx_written_to_guest(uint32_t causes) "Received packet written to guest 
(ICR causes %u)"
-e1000e_rx_not_written_to_guest(uint32_t causes) "Received packet NOT written 
to guest (ICR causes %u)"
+e1000e_rx_written_to_guest(int queue_idx) "Received packet written to guest 
(queue %d)"
+e1000e_rx_not_written_to_guest(int queue_idx) "Received packet NOT written to 
guest (queue %d)"
 e1000e_rx_interrupt_set(uint32_t causes) "Receive interrupt set (ICR causes 
%u)"
 e1000e_rx_interrupt_delayed(uint32_t causes) "Receive interrupt delayed (ICR 
causes %u)"
 e1000e_rx_set_cso(int cso_state) "RX CSO state set to %d"
@@ -180,7 +180,6 @@ e1000e_rx_rss_type(uint32_t type) "RSS type is %u"
 e1000e_rx_rss_ip4(bool isfragment, bool istcp, uint32_t mrqc, bool 
tcpipv4_enabled, bool ipv4_enabled) "RSS IPv4: fragment %d, tcp %d, mrqc 0x%X, 
tcpipv4 enabled %d, ipv4 enabled %d"
 e1000e_rx_rss_ip6_rfctl(uint32_t rfctl) "RSS IPv6: rfctl 0x%X"
 e1000e_rx_rss_ip6(bool ex_dis, bool new_ex_dis, bool istcp, bool 
has_ext_headers, bool ex_dst_valid, bool ex_src_valid, uint32_t mrqc, bool 
tcpipv6_enabled, bool ipv6ex_enabled, bool ipv6_enabled) "RSS IPv6: ex_dis: %d, 
new_ex_dis: %d, tcp %d, has_ext_headers %d, ex_dst_valid %d, ex_src_valid %d, 
mrqc 0x%X, tcpipv6 enabled %d, ipv6ex enabled %d, ipv6 enabled %d"
-e1000e_rx_rss_dispatched_to_queue(int queue_idx) "Packet being dispatched to 
queue %d"
 
 e1000e_rx_metadata_protocols(bool isip4, bool isip6, bool isudp, bool istcp) 
"protocols: ip4: %d, ip6: %d, udp: %d, tcp: %d"
 e1000e_rx_metadata_vlan(uint16_t vlan_tag) "VLAN tag is 0x%X"
-- 
2.7.4




[PULL 32/51] e1000e: Count CRC in Tx statistics

2023-03-06 Thread Jason Wang
From: Akihiko Odaki 

The datasheet 8.19.29 "Good Packets Transmitted Count - GPTC (0x04080;
RC)" says:
> This register counts the number of good (no errors) packets
> transmitted. A good transmit packet is considered one that is 64 or
> more bytes in length (from  through ,
> inclusively) in length.

It also says similar for the other Tx statistics registers. Add the
number of bytes for CRC to those registers.

Signed-off-by: Akihiko Odaki 
Signed-off-by: Jason Wang 
---
 hw/net/e1000e_core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c
index 4fec6df..326b9a1 100644
--- a/hw/net/e1000e_core.c
+++ b/hw/net/e1000e_core.c
@@ -691,7 +691,7 @@ e1000e_on_tx_done_update_stats(E1000ECore *core, struct 
NetTxPkt *tx_pkt)
 static const int PTCregs[6] = { PTC64, PTC127, PTC255, PTC511,
 PTC1023, PTC1522 };
 
-size_t tot_len = net_tx_pkt_get_total_len(tx_pkt);
+size_t tot_len = net_tx_pkt_get_total_len(tx_pkt) + 4;
 
 e1000x_increase_size_stats(core->mac, PTCregs, tot_len);
 e1000x_inc_reg_if_not_full(core->mac, TPT);
-- 
2.7.4




[PULL 33/51] net/eth: Report if headers are actually present

2023-03-06 Thread Jason Wang
From: Akihiko Odaki 

The values returned by eth_get_protocols() are used to perform RSS,
checksumming and segmentation. Even when a packet signals the use of the
protocols which these operations can be applied to, the headers for them
may not be present because of too short packet or fragmentation, for
example. In such a case, the operations cannot be applied safely.

Report the presence of headers instead of whether the use of the
protocols are indicated with eth_get_protocols(). This also makes
corresponding changes to the callers of eth_get_protocols() to match
with its new signature and to remove redundant checks for fragmentation.

Fixes: 75020a7021 ("Common definitions for VMWARE devices")
Signed-off-by: Akihiko Odaki 
Signed-off-by: Jason Wang 
---
 hw/net/e1000e_core.c | 65 ++---
 hw/net/net_rx_pkt.c  | 86 -
 hw/net/net_rx_pkt.h  | 12 +++
 hw/net/trace-events  |  6 ++--
 hw/net/virtio-net.c  | 32 --
 hw/net/vmxnet3.c | 20 ++--
 include/net/eth.h|  4 +--
 net/eth.c| 91 
 8 files changed, 150 insertions(+), 166 deletions(-)

diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c
index 326b9a1..a297463 100644
--- a/hw/net/e1000e_core.c
+++ b/hw/net/e1000e_core.c
@@ -497,27 +497,25 @@ typedef struct E1000E_RSSInfo_st {
 static uint32_t
 e1000e_rss_get_hash_type(E1000ECore *core, struct NetRxPkt *pkt)
 {
-bool isip4, isip6, isudp, istcp;
+bool hasip4, hasip6, hasudp, hastcp;
 
 assert(e1000e_rss_enabled(core));
 
-net_rx_pkt_get_protocols(pkt, , , , );
+net_rx_pkt_get_protocols(pkt, , , , );
 
-if (isip4) {
-bool fragment = net_rx_pkt_get_ip4_info(pkt)->fragment;
-
-trace_e1000e_rx_rss_ip4(fragment, istcp, core->mac[MRQC],
+if (hasip4) {
+trace_e1000e_rx_rss_ip4(hastcp, core->mac[MRQC],
 E1000_MRQC_EN_TCPIPV4(core->mac[MRQC]),
 E1000_MRQC_EN_IPV4(core->mac[MRQC]));
 
-if (!fragment && istcp && E1000_MRQC_EN_TCPIPV4(core->mac[MRQC])) {
+if (hastcp && E1000_MRQC_EN_TCPIPV4(core->mac[MRQC])) {
 return E1000_MRQ_RSS_TYPE_IPV4TCP;
 }
 
 if (E1000_MRQC_EN_IPV4(core->mac[MRQC])) {
 return E1000_MRQ_RSS_TYPE_IPV4;
 }
-} else if (isip6) {
+} else if (hasip6) {
 eth_ip6_hdr_info *ip6info = net_rx_pkt_get_ip6_info(pkt);
 
 bool ex_dis = core->mac[RFCTL] & E1000_RFCTL_IPV6_EX_DIS;
@@ -531,7 +529,7 @@ e1000e_rss_get_hash_type(E1000ECore *core, struct NetRxPkt 
*pkt)
  * backends like these.
  */
 trace_e1000e_rx_rss_ip6_rfctl(core->mac[RFCTL]);
-trace_e1000e_rx_rss_ip6(ex_dis, new_ex_dis, istcp,
+trace_e1000e_rx_rss_ip6(ex_dis, new_ex_dis, hastcp,
 ip6info->has_ext_hdrs,
 ip6info->rss_ex_dst_valid,
 ip6info->rss_ex_src_valid,
@@ -544,8 +542,7 @@ e1000e_rss_get_hash_type(E1000ECore *core, struct NetRxPkt 
*pkt)
 (!new_ex_dis || !(ip6info->rss_ex_dst_valid ||
   ip6info->rss_ex_src_valid))) {
 
-if (istcp && !ip6info->fragment &&
-E1000_MRQC_EN_TCPIPV6(core->mac[MRQC])) {
+if (hastcp && E1000_MRQC_EN_TCPIPV6(core->mac[MRQC])) {
 return E1000_MRQ_RSS_TYPE_IPV6TCP;
 }
 
@@ -1127,7 +1124,7 @@ static void
 e1000e_verify_csum_in_sw(E1000ECore *core,
  struct NetRxPkt *pkt,
  uint32_t *status_flags,
- bool istcp, bool isudp)
+ bool hastcp, bool hasudp)
 {
 bool csum_valid;
 uint32_t csum_error;
@@ -1155,10 +1152,10 @@ e1000e_verify_csum_in_sw(E1000ECore *core,
 
 csum_error = csum_valid ? 0 : E1000_RXDEXT_STATERR_TCPE;
 
-if (istcp) {
+if (hastcp) {
 *status_flags |= E1000_RXD_STAT_TCPCS |
  csum_error;
-} else if (isudp) {
+} else if (hasudp) {
 *status_flags |= E1000_RXD_STAT_TCPCS |
  E1000_RXD_STAT_UDPCS |
  csum_error;
@@ -1190,7 +1187,7 @@ e1000e_build_rx_metadata(E1000ECore *core,
  uint16_t *vlan_tag)
 {
 struct virtio_net_hdr *vhdr;
-bool isip4, isip6, istcp, isudp;
+bool hasip4, hasip6, hastcp, hasudp;
 uint32_t pkt_type;
 
 *status_flags = E1000_RXD_STAT_DD;
@@ -1202,8 +1199,8 @@ e1000e_build_rx_metadata(E1000ECore *core,
 
 *status_flags |= E1000_RXD_STAT_EOP;
 
-net_rx_pkt_get_protocols(pkt, , , , );
-trace_e1000e_rx_metadata_protocols(isip4, isip6, isudp, istcp);
+net_rx_pkt_get_protocols(pkt, , , , );
+trace_e1000e_rx_metadata_protocols(hasip4, hasip6, hasudp, hastcp);
 
 /* VLAN state */
 if 

[PULL 36/51] pcie: Introduce pcie_sriov_num_vfs

2023-03-06 Thread Jason Wang
From: Akihiko Odaki 

igb can use this function to change its behavior depending on the
number of virtual functions currently enabled.

Signed-off-by: Gal Hammer 
Signed-off-by: Marcel Apfelbaum 
Signed-off-by: Akihiko Odaki 
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Jason Wang 
---
 hw/pci/pcie_sriov.c | 5 +
 include/hw/pci/pcie_sriov.h | 3 +++
 2 files changed, 8 insertions(+)

diff --git a/hw/pci/pcie_sriov.c b/hw/pci/pcie_sriov.c
index f0bd72e..aa5a757 100644
--- a/hw/pci/pcie_sriov.c
+++ b/hw/pci/pcie_sriov.c
@@ -300,3 +300,8 @@ PCIDevice *pcie_sriov_get_vf_at_index(PCIDevice *dev, int n)
 }
 return NULL;
 }
+
+uint16_t pcie_sriov_num_vfs(PCIDevice *dev)
+{
+return dev->exp.sriov_pf.num_vfs;
+}
diff --git a/include/hw/pci/pcie_sriov.h b/include/hw/pci/pcie_sriov.h
index 96cc743..095fb0c 100644
--- a/include/hw/pci/pcie_sriov.h
+++ b/include/hw/pci/pcie_sriov.h
@@ -76,4 +76,7 @@ PCIDevice *pcie_sriov_get_pf(PCIDevice *dev);
  */
 PCIDevice *pcie_sriov_get_vf_at_index(PCIDevice *dev, int n);
 
+/* Returns the current number of virtual functions. */
+uint16_t pcie_sriov_num_vfs(PCIDevice *dev);
+
 #endif /* QEMU_PCIE_SRIOV_H */
-- 
2.7.4




[PULL 12/51] e1000e: Remove pending interrupt flags

2023-03-06 Thread Jason Wang
From: Akihiko Odaki 

They are duplicate of running throttling timer flags and incomplete as
the flags are not cleared when the interrupts are fired or the device is
reset.

Signed-off-by: Akihiko Odaki 
Signed-off-by: Jason Wang 
---
 hw/net/e1000e.c  |  5 ++---
 hw/net/e1000e_core.c | 19 +++
 hw/net/e1000e_core.h |  2 --
 hw/net/trace-events  |  2 --
 4 files changed, 5 insertions(+), 23 deletions(-)

diff --git a/hw/net/e1000e.c b/hw/net/e1000e.c
index d591d01..0bc222d 100644
--- a/hw/net/e1000e.c
+++ b/hw/net/e1000e.c
@@ -631,12 +631,11 @@ static const VMStateDescription e1000e_vmstate = {
 VMSTATE_E1000E_INTR_DELAY_TIMER(core.tidv, E1000EState),
 
 VMSTATE_E1000E_INTR_DELAY_TIMER(core.itr, E1000EState),
-VMSTATE_BOOL(core.itr_intr_pending, E1000EState),
+VMSTATE_UNUSED(1),
 
 VMSTATE_E1000E_INTR_DELAY_TIMER_ARRAY(core.eitr, E1000EState,
   E1000E_MSIX_VEC_NUM),
-VMSTATE_BOOL_ARRAY(core.eitr_intr_pending, E1000EState,
-   E1000E_MSIX_VEC_NUM),
+VMSTATE_UNUSED(E1000E_MSIX_VEC_NUM),
 
 VMSTATE_UINT32(core.itr_guest_value, E1000EState),
 VMSTATE_UINT32_ARRAY(core.eitr_guest_value, E1000EState,
diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c
index 87f964c..37aec6a 100644
--- a/hw/net/e1000e_core.c
+++ b/hw/net/e1000e_core.c
@@ -154,11 +154,6 @@ e1000e_intrmgr_on_throttling_timer(void *opaque)
 
 timer->running = false;
 
-if (!timer->core->itr_intr_pending) {
-trace_e1000e_irq_throttling_no_pending_interrupts();
-return;
-}
-
 if (msi_enabled(timer->core->owner)) {
 trace_e1000e_irq_msi_notify_postponed();
 /* Clear msi_causes_pending to fire MSI eventually */
@@ -180,11 +175,6 @@ e1000e_intrmgr_on_msix_throttling_timer(void *opaque)
 
 timer->running = false;
 
-if (!timer->core->eitr_intr_pending[idx]) {
-trace_e1000e_irq_throttling_no_pending_vec(idx);
-return;
-}
-
 trace_e1000e_irq_msix_notify_postponed_vec(idx);
 msix_notify(timer->core->owner, idx);
 }
@@ -2015,13 +2005,11 @@ e1000e_clear_ims_bits(E1000ECore *core, uint32_t bits)
 }
 
 static inline bool
-e1000e_postpone_interrupt(bool *interrupt_pending,
-   E1000IntrDelayTimer *timer)
+e1000e_postpone_interrupt(E1000IntrDelayTimer *timer)
 {
 if (timer->running) {
 trace_e1000e_irq_postponed_by_xitr(timer->delay_reg << 2);
 
-*interrupt_pending = true;
 return true;
 }
 
@@ -2035,14 +2023,13 @@ e1000e_postpone_interrupt(bool *interrupt_pending,
 static inline bool
 e1000e_itr_should_postpone(E1000ECore *core)
 {
-return e1000e_postpone_interrupt(>itr_intr_pending, >itr);
+return e1000e_postpone_interrupt(>itr);
 }
 
 static inline bool
 e1000e_eitr_should_postpone(E1000ECore *core, int idx)
 {
-return e1000e_postpone_interrupt(>eitr_intr_pending[idx],
- >eitr[idx]);
+return e1000e_postpone_interrupt(>eitr[idx]);
 }
 
 static void
diff --git a/hw/net/e1000e_core.h b/hw/net/e1000e_core.h
index b8f38c4..d0a14b4 100644
--- a/hw/net/e1000e_core.h
+++ b/hw/net/e1000e_core.h
@@ -95,10 +95,8 @@ struct E1000Core {
 E1000IntrDelayTimer tidv;
 
 E1000IntrDelayTimer itr;
-bool itr_intr_pending;
 
 E1000IntrDelayTimer eitr[E1000E_MSIX_VEC_NUM];
-bool eitr_intr_pending[E1000E_MSIX_VEC_NUM];
 
 VMChangeStateEntry *vmstate;
 
diff --git a/hw/net/trace-events b/hw/net/trace-events
index 4c0ec3f..8fa4299 100644
--- a/hw/net/trace-events
+++ b/hw/net/trace-events
@@ -201,10 +201,8 @@ e1000e_rx_metadata_ipv6_filtering_disabled(void) "IPv6 RX 
filtering disabled by
 e1000e_vlan_vet(uint16_t vet) "Setting VLAN ethernet type 0x%X"
 
 e1000e_irq_msi_notify(uint32_t cause) "MSI notify 0x%x"
-e1000e_irq_throttling_no_pending_interrupts(void) "No pending interrupts to 
notify"
 e1000e_irq_msi_notify_postponed(void) "Sending MSI postponed by ITR"
 e1000e_irq_legacy_notify_postponed(void) "Raising legacy IRQ postponed by ITR"
-e1000e_irq_throttling_no_pending_vec(int idx) "No pending interrupts for 
vector %d"
 e1000e_irq_msix_notify_postponed_vec(int idx) "Sending MSI-X postponed by 
EITR[%d]"
 e1000e_irq_legacy_notify(bool level) "IRQ line state: %d"
 e1000e_irq_msix_notify_vec(uint32_t vector) "MSI-X notify vector 0x%x"
-- 
2.7.4




[PULL 24/51] e1000e: Perform software segmentation for loopback

2023-03-06 Thread Jason Wang
From: Akihiko Odaki 

e1000e didn't perform software segmentation for loopback if virtio-net
header is enabled, which is wrong.

To fix the problem, introduce net_tx_pkt_send_custom(), which allows the
caller to specify whether offloading should be assumed or not.

net_tx_pkt_send_custom() also allows the caller to provide a custom
sending function. Packets with virtio-net headers and ones without
virtio-net headers will be provided at the same time so the function
can choose the preferred version. In case of e1000e loopback, it prefers
to have virtio-net headers as they allows to skip the checksum
verification if VIRTIO_NET_HDR_F_DATA_VALID is set.

Signed-off-by: Akihiko Odaki 
Signed-off-by: Jason Wang 
---
 hw/net/e1000e_core.c | 27 +--
 hw/net/net_rx_pkt.c  |  7 +
 hw/net/net_rx_pkt.h  |  8 ++
 hw/net/net_tx_pkt.c  | 76 +---
 hw/net/net_tx_pkt.h  | 21 ---
 5 files changed, 88 insertions(+), 51 deletions(-)

diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c
index 95245c4..ff93547 100644
--- a/hw/net/e1000e_core.c
+++ b/hw/net/e1000e_core.c
@@ -61,6 +61,10 @@ union e1000_rx_desc_union {
 union e1000_rx_desc_packet_split packet_split;
 };
 
+static ssize_t
+e1000e_receive_internal(E1000ECore *core, const struct iovec *iov, int iovcnt,
+bool has_vnet);
+
 static inline void
 e1000e_set_interrupt_cause(E1000ECore *core, uint32_t val);
 
@@ -655,6 +659,15 @@ e1000e_setup_tx_offloads(E1000ECore *core, struct 
e1000e_tx *tx)
 return true;
 }
 
+static void e1000e_tx_pkt_callback(void *core,
+   const struct iovec *iov,
+   int iovcnt,
+   const struct iovec *virt_iov,
+   int virt_iovcnt)
+{
+e1000e_receive_internal(core, virt_iov, virt_iovcnt, true);
+}
+
 static bool
 e1000e_tx_pkt_send(E1000ECore *core, struct e1000e_tx *tx, int queue_index)
 {
@@ -669,7 +682,8 @@ e1000e_tx_pkt_send(E1000ECore *core, struct e1000e_tx *tx, 
int queue_index)
 
 if ((core->phy[0][MII_BMCR] & MII_BMCR_LOOPBACK) ||
 ((core->mac[RCTL] & E1000_RCTL_LBM_MAC) == E1000_RCTL_LBM_MAC)) {
-return net_tx_pkt_send_loopback(tx->tx_pkt, queue);
+return net_tx_pkt_send_custom(tx->tx_pkt, false,
+  e1000e_tx_pkt_callback, core);
 } else {
 return net_tx_pkt_send(tx->tx_pkt, queue);
 }
@@ -1675,6 +1689,13 @@ e1000e_rx_fix_l4_csum(E1000ECore *core, struct NetRxPkt 
*pkt)
 ssize_t
 e1000e_receive_iov(E1000ECore *core, const struct iovec *iov, int iovcnt)
 {
+return e1000e_receive_internal(core, iov, iovcnt, core->has_vnet);
+}
+
+static ssize_t
+e1000e_receive_internal(E1000ECore *core, const struct iovec *iov, int iovcnt,
+bool has_vnet)
+{
 static const int maximum_ethernet_hdr_len = (ETH_HLEN + 4);
 
 uint32_t n = 0;
@@ -1696,9 +1717,11 @@ e1000e_receive_iov(E1000ECore *core, const struct iovec 
*iov, int iovcnt)
 }
 
 /* Pull virtio header in */
-if (core->has_vnet) {
+if (has_vnet) {
 net_rx_pkt_set_vhdr_iovec(core->rx_pkt, iov, iovcnt);
 iov_ofs = sizeof(struct virtio_net_hdr);
+} else {
+net_rx_pkt_unset_vhdr(core->rx_pkt);
 }
 
 filter_buf = iov->iov_base + iov_ofs;
diff --git a/hw/net/net_rx_pkt.c b/hw/net/net_rx_pkt.c
index b309c2f..a53e756 100644
--- a/hw/net/net_rx_pkt.c
+++ b/hw/net/net_rx_pkt.c
@@ -463,6 +463,13 @@ void net_rx_pkt_set_vhdr_iovec(struct NetRxPkt *pkt,
 iov_to_buf(iov, iovcnt, 0, >virt_hdr, sizeof pkt->virt_hdr);
 }
 
+void net_rx_pkt_unset_vhdr(struct NetRxPkt *pkt)
+{
+assert(pkt);
+
+memset(>virt_hdr, 0, sizeof(pkt->virt_hdr));
+}
+
 bool net_rx_pkt_is_vlan_stripped(struct NetRxPkt *pkt)
 {
 assert(pkt);
diff --git a/hw/net/net_rx_pkt.h b/hw/net/net_rx_pkt.h
index 7277907..8b69ddb 100644
--- a/hw/net/net_rx_pkt.h
+++ b/hw/net/net_rx_pkt.h
@@ -313,6 +313,14 @@ void net_rx_pkt_set_vhdr_iovec(struct NetRxPkt *pkt,
 const struct iovec *iov, int iovcnt);
 
 /**
+ * unset vhdr data from packet context
+ *
+ * @pkt:packet
+ *
+ */
+void net_rx_pkt_unset_vhdr(struct NetRxPkt *pkt);
+
+/**
  * save packet type in packet context
  *
  * @pkt:packet
diff --git a/hw/net/net_tx_pkt.c b/hw/net/net_tx_pkt.c
index cf46c84..6afd3f6 100644
--- a/hw/net/net_tx_pkt.c
+++ b/hw/net/net_tx_pkt.c
@@ -53,8 +53,6 @@ struct NetTxPkt {
 uint16_t hdr_len;
 eth_pkt_types_e packet_type;
 uint8_t l4proto;
-
-bool is_loopback;
 };
 
 void net_tx_pkt_init(struct NetTxPkt **pkt, PCIDevice *pci_dev,
@@ -508,12 +506,6 @@ static void net_tx_pkt_do_sw_csum(struct NetTxPkt *pkt)
 iov_from_buf(iov, iov_len, csum_offset, , sizeof csum);
 }
 
-enum {
-NET_TX_PKT_FRAGMENT_L2_HDR_POS = 0,
-NET_TX_PKT_FRAGMENT_L3_HDR_POS,
-NET_TX_PKT_FRAGMENT_HEADER_NUM
-};
-
 #define 

[PULL 26/51] hw/net/net_tx_pkt: Check the payload length

2023-03-06 Thread Jason Wang
From: Akihiko Odaki 

Check the payload length if checksumming to ensure the payload contains
the space for the resulting value.

This bug was found by Alexander Bulekov with the fuzzer:
https://patchew.org/QEMU/20230129053316.1071513-1-alx...@bu.edu/

The fixed test case is:
fuzz/crash_6aeaa33e7211ecd603726c53e834df4c6d1e08bc

Fixes: e263cd49c7 ("Packet abstraction for VMWARE network devices")
Signed-off-by: Akihiko Odaki 
Signed-off-by: Jason Wang 
---
 hw/net/net_tx_pkt.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/hw/net/net_tx_pkt.c b/hw/net/net_tx_pkt.c
index 4a35e84..986a3ad 100644
--- a/hw/net/net_tx_pkt.c
+++ b/hw/net/net_tx_pkt.c
@@ -342,11 +342,17 @@ bool net_tx_pkt_build_vheader(struct NetTxPkt *pkt, bool 
tso_enable,
 if (csum_enable) {
 switch (pkt->l4proto) {
 case IP_PROTO_TCP:
+if (pkt->payload_len < sizeof(struct tcp_hdr)) {
+return false;
+}
 pkt->virt_hdr.flags = VIRTIO_NET_HDR_F_NEEDS_CSUM;
 pkt->virt_hdr.csum_start = pkt->hdr_len;
 pkt->virt_hdr.csum_offset = offsetof(struct tcp_hdr, th_sum);
 break;
 case IP_PROTO_UDP:
+if (pkt->payload_len < sizeof(struct udp_hdr)) {
+return false;
+}
 pkt->virt_hdr.flags = VIRTIO_NET_HDR_F_NEEDS_CSUM;
 pkt->virt_hdr.csum_start = pkt->hdr_len;
 pkt->virt_hdr.csum_offset = offsetof(struct udp_hdr, uh_sum);
-- 
2.7.4




[PULL 43/51] docs/system/devices/igb: Add igb documentation

2023-03-06 Thread Jason Wang
From: Akihiko Odaki 

Signed-off-by: Akihiko Odaki 
Reviewed-by: Cédric Le Goater 
Signed-off-by: Jason Wang 
---
 MAINTAINERS  |  1 +
 docs/system/device-emulation.rst |  1 +
 docs/system/devices/igb.rst  | 71 
 3 files changed, 73 insertions(+)
 create mode 100644 docs/system/devices/igb.rst

diff --git a/MAINTAINERS b/MAINTAINERS
index 77f3dd3..e10eaa7 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2235,6 +2235,7 @@ F: tests/qtest/libqos/e1000e.*
 igb
 M: Akihiko Odaki 
 S: Maintained
+F: docs/system/devices/igb.rst
 F: hw/net/igb*
 F: tests/avocado/igb.py
 F: tests/qtest/igb-test.c
diff --git a/docs/system/device-emulation.rst b/docs/system/device-emulation.rst
index 0506006..c1b1934 100644
--- a/docs/system/device-emulation.rst
+++ b/docs/system/device-emulation.rst
@@ -93,3 +93,4 @@ Emulated Devices
devices/virtio-pmem.rst
devices/vhost-user-rng.rst
devices/canokey.rst
+   devices/igb.rst
diff --git a/docs/system/devices/igb.rst b/docs/system/devices/igb.rst
new file mode 100644
index 000..70edadd
--- /dev/null
+++ b/docs/system/devices/igb.rst
@@ -0,0 +1,71 @@
+.. SPDX-License-Identifier: GPL-2.0-or-later
+.. _igb:
+
+igb
+---
+
+igb is a family of Intel's gigabit ethernet controllers. In QEMU, 82576
+emulation is implemented in particular. Its datasheet is available at [1]_.
+
+This implementation is expected to be useful to test SR-IOV networking without
+requiring physical hardware.
+
+Limitations
+===
+
+This igb implementation was tested with Linux Test Project [2]_ and Windows HLK
+[3]_ during the initial development. The command used when testing with LTP is:
+
+.. code-block:: shell
+
+  network.sh -6mta
+
+Be aware that this implementation lacks many functionalities available with the
+actual hardware, and you may experience various failures if you try to use it
+with a different operating system other than Linux and Windows or if you try
+functionalities not covered by the tests.
+
+Using igb
+=
+
+Using igb should be nothing different from using another network device. See
+:ref:`pcsys_005fnetwork` in general.
+
+However, you may also need to perform additional steps to activate SR-IOV
+feature on your guest. For Linux, refer to [4]_.
+
+Developing igb
+==
+
+igb is the successor of e1000e, and e1000e is the successor of e1000 in turn.
+As these devices are very similar, if you make a change for igb and the same
+change can be applied to e1000e and e1000, please do so.
+
+Please do not forget to run tests before submitting a change. As tests included
+in QEMU is very minimal, run some application which is likely to be affected by
+the change to confirm it works in an integrated system.
+
+Testing igb
+===
+
+A qtest of the basic functionality is available. Run the below at the build
+directory:
+
+.. code-block:: shell
+
+  meson test qtest-x86_64/qos-test
+
+ethtool can test register accesses, interrupts, etc. It is automated as an
+Avocado test and can be ran with the following command:
+
+.. code:: shell
+
+  make check-avocado AVOCADO_TESTS=tests/avocado/igb.py
+
+References
+==
+
+.. [1] 
https://www.intel.com/content/dam/www/public/us/en/documents/datasheets/82576eb-gigabit-ethernet-controller-datasheet.pdf
+.. [2] https://github.com/linux-test-project/ltp
+.. [3] https://learn.microsoft.com/en-us/windows-hardware/test/hlk/
+.. [4] https://docs.kernel.org/PCI/pci-iov-howto.html
-- 
2.7.4




[PULL 31/51] e1000: Count CRC in Tx statistics

2023-03-06 Thread Jason Wang
From: Akihiko Odaki 

The Software Developer's Manual 13.7.4.5 "Packets Transmitted (64 Bytes)
Count" says:
> This register counts the number of packets transmitted that are
> exactly 64 bytes (from  through ,
> inclusively) in length.

It also says similar for the other Tx statistics registers. Add the
number of bytes for CRC to those registers.

Signed-off-by: Akihiko Odaki 
Signed-off-by: Jason Wang 
---
 hw/net/e1000.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/net/e1000.c b/hw/net/e1000.c
index c81d914..c830798 100644
--- a/hw/net/e1000.c
+++ b/hw/net/e1000.c
@@ -571,7 +571,7 @@ e1000_send_packet(E1000State *s, const uint8_t *buf, int 
size)
 qemu_send_packet(nc, buf, size);
 }
 inc_tx_bcast_or_mcast_count(s, buf);
-e1000x_increase_size_stats(s->mac_reg, PTCregs, size);
+e1000x_increase_size_stats(s->mac_reg, PTCregs, size + 4);
 }
 
 static void
@@ -635,7 +635,7 @@ xmit_seg(E1000State *s)
 }
 
 e1000x_inc_reg_if_not_full(s->mac_reg, TPT);
-e1000x_grow_8reg_if_not_full(s->mac_reg, TOTL, s->tx.size);
+e1000x_grow_8reg_if_not_full(s->mac_reg, TOTL, s->tx.size + 4);
 s->mac_reg[GPTC] = s->mac_reg[TPT];
 s->mac_reg[GOTCL] = s->mac_reg[TOTL];
 s->mac_reg[GOTCH] = s->mac_reg[TOTH];
-- 
2.7.4




[PULL 51/51] hw/net/eepro100: Replace DO_UPCAST(EEPRO100State) by EEPRO100()

2023-03-06 Thread Jason Wang
From: Philippe Mathieu-Daudé 

Use the EEPRO100() QOM type-checking macro to avoid DO_UPCAST().

Signed-off-by: Philippe Mathieu-Daudé 
Signed-off-by: Jason Wang 
---
 hw/net/eepro100.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/hw/net/eepro100.c b/hw/net/eepro100.c
index bce3776..6db15f1 100644
--- a/hw/net/eepro100.c
+++ b/hw/net/eepro100.c
@@ -1834,7 +1834,7 @@ static const VMStateDescription vmstate_eepro100 = {
 
 static void pci_nic_uninit(PCIDevice *pci_dev)
 {
-EEPRO100State *s = DO_UPCAST(EEPRO100State, dev, pci_dev);
+EEPRO100State *s = EEPRO100(pci_dev);
 
 vmstate_unregister(VMSTATE_IF(_dev->qdev), s->vmstate, s);
 g_free(s->vmstate);
@@ -1850,7 +1850,7 @@ static NetClientInfo net_eepro100_info = {
 
 static void e100_nic_realize(PCIDevice *pci_dev, Error **errp)
 {
-EEPRO100State *s = DO_UPCAST(EEPRO100State, dev, pci_dev);
+EEPRO100State *s = EEPRO100(pci_dev);
 
 TRACE(OTHER, logout("\n"));
 
@@ -1891,7 +1891,7 @@ static void e100_nic_realize(PCIDevice *pci_dev, Error 
**errp)
 
 static void eepro100_instance_init(Object *obj)
 {
-EEPRO100State *s = DO_UPCAST(EEPRO100State, dev, PCI_DEVICE(obj));
+EEPRO100State *s = EEPRO100(obj);
 device_add_bootindex_property(obj, >conf.bootindex,
   "bootindex", "/ethernet-phy@0",
   DEVICE(s));
-- 
2.7.4




[PULL 41/51] igb: Introduce qtest for igb device

2023-03-06 Thread Jason Wang
From: Akihiko Odaki 

This change is derived from qtest for e1000e device.

Signed-off-by: Akihiko Odaki 
Acked-by: Thomas Huth 
Signed-off-by: Jason Wang 
---
 MAINTAINERS |   2 +
 tests/qtest/fuzz/generic_fuzz_configs.h |   5 +
 tests/qtest/igb-test.c  | 243 
 tests/qtest/libqos/igb.c| 185 
 tests/qtest/libqos/meson.build  |   1 +
 tests/qtest/meson.build |   1 +
 6 files changed, 437 insertions(+)
 create mode 100644 tests/qtest/igb-test.c
 create mode 100644 tests/qtest/libqos/igb.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 4e3e904..e5d5d9f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2236,6 +2236,8 @@ igb
 M: Akihiko Odaki 
 S: Maintained
 F: hw/net/igb*
+F: tests/qtest/igb-test.c
+F: tests/qtest/libqos/igb.c
 
 eepro100
 M: Stefan Weil 
diff --git a/tests/qtest/fuzz/generic_fuzz_configs.h 
b/tests/qtest/fuzz/generic_fuzz_configs.h
index a825b78..50689da 100644
--- a/tests/qtest/fuzz/generic_fuzz_configs.h
+++ b/tests/qtest/fuzz/generic_fuzz_configs.h
@@ -91,6 +91,11 @@ const generic_fuzz_config predefined_configs[] = {
 "-device e1000e,netdev=net0 -netdev user,id=net0",
 .objects = "e1000e",
 },{
+.name = "igb",
+.args = "-M q35 -nodefaults "
+"-device igb,netdev=net0 -netdev user,id=net0",
+.objects = "igb",
+},{
 .name = "cirrus-vga",
 .args = "-machine q35 -nodefaults -device cirrus-vga",
 .objects = "cirrus*",
diff --git a/tests/qtest/igb-test.c b/tests/qtest/igb-test.c
new file mode 100644
index 000..b36ddec
--- /dev/null
+++ b/tests/qtest/igb-test.c
@@ -0,0 +1,243 @@
+/*
+ * QTest testcase for igb NIC
+ *
+ * Copyright (c) 2022-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 
+ * Dmitry Fleytman 
+ * Leonid Bloch 
+ * Yan Vugenfirer 
+ *
+ * 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 .
+ */
+
+
+#include "qemu/osdep.h"
+#include "libqtest-single.h"
+#include "libqos/pci-pc.h"
+#include "net/eth.h"
+#include "qemu/sockets.h"
+#include "qemu/iov.h"
+#include "qemu/module.h"
+#include "qemu/bitops.h"
+#include "libqos/libqos-malloc.h"
+#include "libqos/e1000e.h"
+#include "hw/net/igb_regs.h"
+
+static const struct eth_header packet = {
+.h_dest = E1000E_ADDRESS,
+.h_source = E1000E_ADDRESS,
+};
+
+static void igb_send_verify(QE1000E *d, int *test_sockets, QGuestAllocator 
*alloc)
+{
+union e1000_adv_tx_desc descr;
+char buffer[64];
+int ret;
+uint32_t recv_len;
+
+/* Prepare test data buffer */
+uint64_t data = guest_alloc(alloc, sizeof(buffer));
+memwrite(data, , sizeof(packet));
+
+/* Prepare TX descriptor */
+memset(, 0, sizeof(descr));
+descr.read.buffer_addr = cpu_to_le64(data);
+descr.read.cmd_type_len = cpu_to_le32(E1000_TXD_CMD_RS   |
+  E1000_TXD_CMD_EOP  |
+  E1000_TXD_DTYP_D   |
+  sizeof(buffer));
+
+/* Put descriptor to the ring */
+e1000e_tx_ring_push(d, );
+
+/* Wait for TX WB interrupt */
+e1000e_wait_isr(d, E1000E_TX0_MSG_ID);
+
+/* Check DD bit */
+g_assert_cmphex(le32_to_cpu(descr.wb.status) & E1000_TXD_STAT_DD, ==,
+E1000_TXD_STAT_DD);
+
+/* Check data sent to the backend */
+ret = recv(test_sockets[0], _len, sizeof(recv_len), 0);
+g_assert_cmpint(ret, == , sizeof(recv_len));
+ret = recv(test_sockets[0], buffer, sizeof(buffer), 0);
+g_assert_cmpint(ret, ==, sizeof(buffer));
+g_assert_false(memcmp(buffer, , sizeof(packet)));
+
+/* Free test data buffer */
+guest_free(alloc, data);
+}
+
+static void igb_receive_verify(QE1000E *d, int *test_sockets, QGuestAllocator 
*alloc)
+{
+union e1000_adv_rx_desc descr;
+
+struct eth_header test_iov = packet;
+int len = htonl(sizeof(packet));
+struct iovec iov[] = {
+{
+.iov_base = ,
+.iov_len = sizeof(len),
+},{
+.iov_base = _iov,
+.iov_len = sizeof(packet),
+},
+};
+
+char buffer[64];
+int ret;
+
+/* Send a dummy 

[PULL 23/51] hw/net/net_rx_pkt: Remove net_rx_pkt_has_virt_hdr

2023-03-06 Thread Jason Wang
From: Akihiko Odaki 

When virtio-net header is not set, net_rx_pkt_get_vhdr() returns
zero-filled virtio_net_hdr, which is actually valid. In fact, tap device
uses zero-filled virtio_net_hdr when virtio-net header is not provided
by the peer. Therefore, we can just remove net_rx_pkt_has_virt_hdr() and
always assume NetTxPkt has a valid virtio-net header.

Signed-off-by: Akihiko Odaki 
Signed-off-by: Jason Wang 
---
 hw/net/e1000e_core.c | 16 
 hw/net/net_rx_pkt.c  | 11 +--
 hw/net/net_rx_pkt.h  | 12 +---
 hw/net/trace-events  |  1 -
 hw/net/virtio-net.c  |  2 +-
 hw/net/vmxnet3.c | 12 ++--
 6 files changed, 9 insertions(+), 45 deletions(-)

diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c
index 954a007..95245c4 100644
--- a/hw/net/e1000e_core.c
+++ b/hw/net/e1000e_core.c
@@ -1240,12 +1240,6 @@ e1000e_build_rx_metadata(E1000ECore *core,
 goto func_exit;
 }
 
-if (!net_rx_pkt_has_virt_hdr(pkt)) {
-trace_e1000e_rx_metadata_no_virthdr();
-e1000e_verify_csum_in_sw(core, pkt, status_flags, istcp, isudp);
-goto func_exit;
-}
-
 vhdr = net_rx_pkt_get_vhdr(pkt);
 
 if (!(vhdr->flags & VIRTIO_NET_HDR_F_DATA_VALID) &&
@@ -1671,12 +1665,10 @@ e1000e_write_packet_to_guest(E1000ECore *core, struct 
NetRxPkt *pkt,
 static inline void
 e1000e_rx_fix_l4_csum(E1000ECore *core, struct NetRxPkt *pkt)
 {
-if (net_rx_pkt_has_virt_hdr(pkt)) {
-struct virtio_net_hdr *vhdr = net_rx_pkt_get_vhdr(pkt);
+struct virtio_net_hdr *vhdr = net_rx_pkt_get_vhdr(pkt);
 
-if (vhdr->flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) {
-net_rx_pkt_fix_l4_csum(pkt);
-}
+if (vhdr->flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) {
+net_rx_pkt_fix_l4_csum(pkt);
 }
 }
 
@@ -3379,7 +3371,7 @@ e1000e_core_pci_realize(E1000ECore *core,
 net_tx_pkt_init(>tx[i].tx_pkt, core->owner, E1000E_MAX_TX_FRAGS);
 }
 
-net_rx_pkt_init(>rx_pkt, core->has_vnet);
+net_rx_pkt_init(>rx_pkt);
 
 e1000x_core_prepare_eeprom(core->eeprom,
eeprom_templ,
diff --git a/hw/net/net_rx_pkt.c b/hw/net/net_rx_pkt.c
index 1e1c504..b309c2f 100644
--- a/hw/net/net_rx_pkt.c
+++ b/hw/net/net_rx_pkt.c
@@ -30,7 +30,6 @@ struct NetRxPkt {
 uint32_t tot_len;
 uint16_t tci;
 size_t ehdr_buf_len;
-bool has_virt_hdr;
 eth_pkt_types_e packet_type;
 
 /* Analysis results */
@@ -48,10 +47,9 @@ struct NetRxPkt {
 eth_l4_hdr_info  l4hdr_info;
 };
 
-void net_rx_pkt_init(struct NetRxPkt **pkt, bool has_virt_hdr)
+void net_rx_pkt_init(struct NetRxPkt **pkt)
 {
 struct NetRxPkt *p = g_malloc0(sizeof *p);
-p->has_virt_hdr = has_virt_hdr;
 p->vec = NULL;
 p->vec_len_total = 0;
 *pkt = p;
@@ -472,13 +470,6 @@ bool net_rx_pkt_is_vlan_stripped(struct NetRxPkt *pkt)
 return pkt->ehdr_buf_len ? true : false;
 }
 
-bool net_rx_pkt_has_virt_hdr(struct NetRxPkt *pkt)
-{
-assert(pkt);
-
-return pkt->has_virt_hdr;
-}
-
 uint16_t net_rx_pkt_get_vlan_tag(struct NetRxPkt *pkt)
 {
 assert(pkt);
diff --git a/hw/net/net_rx_pkt.h b/hw/net/net_rx_pkt.h
index 048e346..7277907 100644
--- a/hw/net/net_rx_pkt.h
+++ b/hw/net/net_rx_pkt.h
@@ -37,10 +37,9 @@ void net_rx_pkt_uninit(struct NetRxPkt *pkt);
  * Init function for rx packet functionality
  *
  * @pkt:packet pointer
- * @has_virt_hdr:   device uses virtio header
  *
  */
-void net_rx_pkt_init(struct NetRxPkt **pkt, bool has_virt_hdr);
+void net_rx_pkt_init(struct NetRxPkt **pkt);
 
 /**
  * returns total length of data attached to rx context
@@ -215,15 +214,6 @@ uint16_t net_rx_pkt_get_vlan_tag(struct NetRxPkt *pkt);
 bool net_rx_pkt_is_vlan_stripped(struct NetRxPkt *pkt);
 
 /**
- * notifies caller if the packet has virtio header
- *
- * @pkt:packet
- * @ret:true if packet has virtio header, false otherwize
- *
- */
-bool net_rx_pkt_has_virt_hdr(struct NetRxPkt *pkt);
-
-/**
 * attach scatter-gather data to rx packet
 *
 * @pkt:packet
diff --git a/hw/net/trace-events b/hw/net/trace-events
index c98ad12..f7257a0 100644
--- a/hw/net/trace-events
+++ b/hw/net/trace-events
@@ -188,7 +188,6 @@ e1000e_rx_metadata_rss(uint32_t rss, uint32_t mrq) "RSS 
data: rss: 0x%X, mrq: 0x
 e1000e_rx_metadata_ip_id(uint16_t ip_id) "the IPv4 ID is 0x%X"
 e1000e_rx_metadata_ack(void) "the packet is TCP ACK"
 e1000e_rx_metadata_pkt_type(uint32_t pkt_type) "the packet type is %u"
-e1000e_rx_metadata_no_virthdr(void) "the packet has no virt-header"
 e1000e_rx_metadata_virthdr_no_csum_info(void) "virt-header does not contain 
checksum info"
 e1000e_rx_metadata_l3_cso_disabled(void) "IP4 CSO is disabled"
 e1000e_rx_metadata_l4_cso_disabled(void) "TCP/UDP CSO is disabled"
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 09d5c7a..dda7da2 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -3718,7 +3718,7 @@ static void virtio_net_device_realize(DeviceState *dev, 
Error 

[PULL 27/51] e1000e: Do not assert when MSI-X is disabled later

2023-03-06 Thread Jason Wang
From: Akihiko Odaki 

Assertions will fail if MSI-X gets disabled while a timer for MSI-X
interrupts is running so remove them to avoid abortions. Fortunately,
nothing bad happens even if the assertions won't trigger as
msix_notify(), called by timer handlers, does nothing when MSI-X is
disabled.

This bug was found by Alexander Bulekov when fuzzing igb, a new
device implementation derived from e1000e:
https://patchew.org/QEMU/20230129053316.1071513-1-alx...@bu.edu/

The fixed test case is:
fuzz/crash_aea040166819193cf9fedb810c6d100221da721a

Fixes: 6f3fbe4ed0 ("net: Introduce e1000e device emulation")
Signed-off-by: Akihiko Odaki 
Signed-off-by: Jason Wang 
---
 hw/net/e1000e_core.c | 4 
 1 file changed, 4 deletions(-)

diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c
index ff93547..76c7814 100644
--- a/hw/net/e1000e_core.c
+++ b/hw/net/e1000e_core.c
@@ -162,8 +162,6 @@ e1000e_intrmgr_on_throttling_timer(void *opaque)
 {
 E1000IntrDelayTimer *timer = opaque;
 
-assert(!msix_enabled(timer->core->owner));
-
 timer->running = false;
 
 if (msi_enabled(timer->core->owner)) {
@@ -183,8 +181,6 @@ e1000e_intrmgr_on_msix_throttling_timer(void *opaque)
 E1000IntrDelayTimer *timer = opaque;
 int idx = timer - >core->eitr[0];
 
-assert(msix_enabled(timer->core->owner));
-
 timer->running = false;
 
 trace_e1000e_irq_msix_notify_postponed_vec(idx);
-- 
2.7.4




[PULL 44/51] ebpf: fix compatibility with libbpf 1.0+

2023-03-06 Thread Jason Wang
From: Shreesh Adiga <16567adigashre...@gmail.com>

The current implementation fails to load on a system with
libbpf 1.0 and reports that legacy map definitions in 'maps'
section are not supported by libbpf v1.0+. This commit updates
the Makefile to add BTF (-g flag) and appropriately updates
the maps in rss.bpf.c and update the skeleton file in repo.

Signed-off-by: Shreesh Adiga <16567adigashre...@gmail.com>
Signed-off-by: Jason Wang 
---
 ebpf/rss.bpf.skeleton.h  | 1171 ++
 tools/ebpf/Makefile.ebpf |8 +-
 tools/ebpf/rss.bpf.c |   43 +-
 3 files changed, 891 insertions(+), 331 deletions(-)

diff --git a/ebpf/rss.bpf.skeleton.h b/ebpf/rss.bpf.skeleton.h
index 126683e..18eb2ad 100644
--- a/ebpf/rss.bpf.skeleton.h
+++ b/ebpf/rss.bpf.skeleton.h
@@ -1,9 +1,10 @@
 /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
 
-/* THIS FILE IS AUTOGENERATED! */
+/* THIS FILE IS AUTOGENERATED BY BPFTOOL! */
 #ifndef __RSS_BPF_SKEL_H__
 #define __RSS_BPF_SKEL_H__
 
+#include 
 #include 
 #include 
 
@@ -12,8 +13,8 @@ struct rss_bpf {
struct bpf_object *obj;
struct {
struct bpf_map *tap_rss_map_configurations;
-   struct bpf_map *tap_rss_map_indirection_table;
struct bpf_map *tap_rss_map_toeplitz_key;
+   struct bpf_map *tap_rss_map_indirection_table;
} maps;
struct {
struct bpf_program *tun_rss_steering_prog;
@@ -21,6 +22,16 @@ struct rss_bpf {
struct {
struct bpf_link *tun_rss_steering_prog;
} links;
+
+#ifdef __cplusplus
+   static inline struct rss_bpf *open(const struct bpf_object_open_opts 
*opts = nullptr);
+   static inline struct rss_bpf *open_and_load();
+   static inline int load(struct rss_bpf *skel);
+   static inline int attach(struct rss_bpf *skel);
+   static inline void detach(struct rss_bpf *skel);
+   static inline void destroy(struct rss_bpf *skel);
+   static inline const void *elf_bytes(size_t *sz);
+#endif /* __cplusplus */
 };
 
 static void
@@ -40,18 +51,26 @@ static inline struct rss_bpf *
 rss_bpf__open_opts(const struct bpf_object_open_opts *opts)
 {
struct rss_bpf *obj;
+   int err;
 
obj = (struct rss_bpf *)calloc(1, sizeof(*obj));
-   if (!obj)
+   if (!obj) {
+   errno = ENOMEM;
return NULL;
-   if (rss_bpf__create_skeleton(obj))
-   goto err;
-   if (bpf_object__open_skeleton(obj->skeleton, opts))
-   goto err;
+   }
+
+   err = rss_bpf__create_skeleton(obj);
+   if (err)
+   goto err_out;
+
+   err = bpf_object__open_skeleton(obj->skeleton, opts);
+   if (err)
+   goto err_out;
 
return obj;
-err:
+err_out:
rss_bpf__destroy(obj);
+   errno = -err;
return NULL;
 }
 
@@ -71,12 +90,15 @@ static inline struct rss_bpf *
 rss_bpf__open_and_load(void)
 {
struct rss_bpf *obj;
+   int err;
 
obj = rss_bpf__open();
if (!obj)
return NULL;
-   if (rss_bpf__load(obj)) {
+   err = rss_bpf__load(obj);
+   if (err) {
rss_bpf__destroy(obj);
+   errno = -err;
return NULL;
}
return obj;
@@ -91,18 +113,22 @@ rss_bpf__attach(struct rss_bpf *obj)
 static inline void
 rss_bpf__detach(struct rss_bpf *obj)
 {
-   return bpf_object__detach_skeleton(obj->skeleton);
+   bpf_object__detach_skeleton(obj->skeleton);
 }
 
+static inline const void *rss_bpf__elf_bytes(size_t *sz);
+
 static inline int
 rss_bpf__create_skeleton(struct rss_bpf *obj)
 {
struct bpf_object_skeleton *s;
+   int err;
 
s = (struct bpf_object_skeleton *)calloc(1, sizeof(*s));
-   if (!s)
-   return -1;
-   obj->skeleton = s;
+   if (!s) {
+   err = -ENOMEM;
+   goto err;
+   }
 
s->sz = sizeof(*s);
s->name = "rss_bpf";
@@ -112,320 +138,855 @@ rss_bpf__create_skeleton(struct rss_bpf *obj)
s->map_cnt = 3;
s->map_skel_sz = sizeof(*s->maps);
s->maps = (struct bpf_map_skeleton *)calloc(s->map_cnt, s->map_skel_sz);
-   if (!s->maps)
+   if (!s->maps) {
+   err = -ENOMEM;
goto err;
+   }
 
s->maps[0].name = "tap_rss_map_configurations";
s->maps[0].map = >maps.tap_rss_map_configurations;
 
-   s->maps[1].name = "tap_rss_map_indirection_table";
-   s->maps[1].map = >maps.tap_rss_map_indirection_table;
+   s->maps[1].name = "tap_rss_map_toeplitz_key";
+   s->maps[1].map = >maps.tap_rss_map_toeplitz_key;
 
-   s->maps[2].name = "tap_rss_map_toeplitz_key";
-   s->maps[2].map = >maps.tap_rss_map_toeplitz_key;
+   s->maps[2].name = "tap_rss_map_indirection_table";
+   s->maps[2].map = >maps.tap_rss_map_indirection_table;
 
/* programs */
s->prog_cnt = 

[PULL 22/51] hw/net/net_tx_pkt: Automatically determine if virtio-net header is used

2023-03-06 Thread Jason Wang
From: Akihiko Odaki 

The new function qemu_get_using_vnet_hdr() allows to automatically
determine if virtio-net header is used.

Signed-off-by: Akihiko Odaki 
Signed-off-by: Jason Wang 
---
 hw/net/e1000e_core.c |  3 +--
 hw/net/net_tx_pkt.c  | 19 ++-
 hw/net/net_tx_pkt.h  |  3 +--
 hw/net/vmxnet3.c |  6 ++
 4 files changed, 14 insertions(+), 17 deletions(-)

diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c
index 38d374f..954a007 100644
--- a/hw/net/e1000e_core.c
+++ b/hw/net/e1000e_core.c
@@ -3376,8 +3376,7 @@ e1000e_core_pci_realize(E1000ECore *core,
 qemu_add_vm_change_state_handler(e1000e_vm_state_change, core);
 
 for (i = 0; i < E1000E_NUM_QUEUES; i++) {
-net_tx_pkt_init(>tx[i].tx_pkt, core->owner,
-E1000E_MAX_TX_FRAGS, core->has_vnet);
+net_tx_pkt_init(>tx[i].tx_pkt, core->owner, E1000E_MAX_TX_FRAGS);
 }
 
 net_rx_pkt_init(>rx_pkt, core->has_vnet);
diff --git a/hw/net/net_tx_pkt.c b/hw/net/net_tx_pkt.c
index 8a23899..cf46c84 100644
--- a/hw/net/net_tx_pkt.c
+++ b/hw/net/net_tx_pkt.c
@@ -35,7 +35,6 @@ struct NetTxPkt {
 PCIDevice *pci_dev;
 
 struct virtio_net_hdr virt_hdr;
-bool has_virt_hdr;
 
 struct iovec *raw;
 uint32_t raw_frags;
@@ -59,7 +58,7 @@ struct NetTxPkt {
 };
 
 void net_tx_pkt_init(struct NetTxPkt **pkt, PCIDevice *pci_dev,
-uint32_t max_frags, bool has_virt_hdr)
+uint32_t max_frags)
 {
 struct NetTxPkt *p = g_malloc0(sizeof *p);
 
@@ -71,10 +70,8 @@ void net_tx_pkt_init(struct NetTxPkt **pkt, PCIDevice 
*pci_dev,
 
 p->max_payload_frags = max_frags;
 p->max_raw_frags = max_frags;
-p->has_virt_hdr = has_virt_hdr;
 p->vec[NET_TX_PKT_VHDR_FRAG].iov_base = >virt_hdr;
-p->vec[NET_TX_PKT_VHDR_FRAG].iov_len =
-p->has_virt_hdr ? sizeof p->virt_hdr : 0;
+p->vec[NET_TX_PKT_VHDR_FRAG].iov_len = sizeof p->virt_hdr;
 p->vec[NET_TX_PKT_L2HDR_FRAG].iov_base = >l2_hdr;
 p->vec[NET_TX_PKT_L3HDR_FRAG].iov_base = >l3_hdr;
 
@@ -617,9 +614,11 @@ static bool net_tx_pkt_do_sw_fragmentation(struct NetTxPkt 
*pkt,
 
 bool net_tx_pkt_send(struct NetTxPkt *pkt, NetClientState *nc)
 {
+bool using_vnet_hdr = qemu_get_using_vnet_hdr(nc->peer);
+
 assert(pkt);
 
-if (!pkt->has_virt_hdr &&
+if (!using_vnet_hdr &&
 pkt->virt_hdr.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) {
 net_tx_pkt_do_sw_csum(pkt);
 }
@@ -636,11 +635,13 @@ bool net_tx_pkt_send(struct NetTxPkt *pkt, NetClientState 
*nc)
 }
 }
 
-if (pkt->has_virt_hdr ||
+if (using_vnet_hdr ||
 pkt->virt_hdr.gso_type == VIRTIO_NET_HDR_GSO_NONE) {
+int index = using_vnet_hdr ?
+NET_TX_PKT_VHDR_FRAG : NET_TX_PKT_L2HDR_FRAG;
 net_tx_pkt_fix_ip6_payload_len(pkt);
-net_tx_pkt_sendv(pkt, nc, pkt->vec,
-pkt->payload_frags + NET_TX_PKT_PL_START_FRAG);
+net_tx_pkt_sendv(pkt, nc, pkt->vec + index,
+pkt->payload_frags + NET_TX_PKT_PL_START_FRAG - index);
 return true;
 }
 
diff --git a/hw/net/net_tx_pkt.h b/hw/net/net_tx_pkt.h
index 2e38a5f..8d3faa4 100644
--- a/hw/net/net_tx_pkt.h
+++ b/hw/net/net_tx_pkt.h
@@ -32,10 +32,9 @@ struct NetTxPkt;
  * @pkt:packet pointer
  * @pci_dev:PCI device processing this packet
  * @max_frags:  max tx ip fragments
- * @has_virt_hdr:   device uses virtio header.
  */
 void net_tx_pkt_init(struct NetTxPkt **pkt, PCIDevice *pci_dev,
-uint32_t max_frags, bool has_virt_hdr);
+uint32_t max_frags);
 
 /**
  * Clean all tx packet resources.
diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c
index d7d492a..eab8fa4 100644
--- a/hw/net/vmxnet3.c
+++ b/hw/net/vmxnet3.c
@@ -1521,8 +1521,7 @@ static void vmxnet3_activate_device(VMXNET3State *s)
 
 /* Preallocate TX packet wrapper */
 VMW_CFPRN("Max TX fragments is %u", s->max_tx_frags);
-net_tx_pkt_init(>tx_pkt, PCI_DEVICE(s),
-s->max_tx_frags, s->peer_has_vhdr);
+net_tx_pkt_init(>tx_pkt, PCI_DEVICE(s), s->max_tx_frags);
 net_rx_pkt_init(>rx_pkt, s->peer_has_vhdr);
 
 /* Read rings memory locations for RX queues */
@@ -2402,8 +2401,7 @@ static int vmxnet3_post_load(void *opaque, int version_id)
 {
 VMXNET3State *s = opaque;
 
-net_tx_pkt_init(>tx_pkt, PCI_DEVICE(s),
-s->max_tx_frags, s->peer_has_vhdr);
+net_tx_pkt_init(>tx_pkt, PCI_DEVICE(s), s->max_tx_frags);
 net_rx_pkt_init(>rx_pkt, s->peer_has_vhdr);
 
 if (s->msix_used) {
-- 
2.7.4




[PULL 01/51] e1000e: Fix the code style

2023-03-06 Thread Jason Wang
From: Akihiko Odaki 

igb implementation first starts off by copying e1000e code. Correct the
code style before that.

Signed-off-by: Akihiko Odaki 
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Jason Wang 
---
 hw/net/e1000.c |  41 ++--
 hw/net/e1000e.c|  72 +-
 hw/net/e1000e_core.c   | 103 +++--
 hw/net/e1000e_core.h   |  66 +++
 hw/net/e1000x_common.h |  44 ++---
 5 files changed, 168 insertions(+), 158 deletions(-)

diff --git a/hw/net/e1000.c b/hw/net/e1000.c
index 7efb8a4..8ee30aa 100644
--- a/hw/net/e1000.c
+++ b/hw/net/e1000.c
@@ -808,10 +808,11 @@ receive_filter(E1000State *s, const uint8_t *buf, int 
size)
 if (e1000x_is_vlan_packet(buf, le16_to_cpu(s->mac_reg[VET])) &&
 e1000x_vlan_rx_filter_enabled(s->mac_reg)) {
 uint16_t vid = lduw_be_p(buf + 14);
-uint32_t vfta = ldl_le_p((uint32_t*)(s->mac_reg + VFTA) +
+uint32_t vfta = ldl_le_p((uint32_t *)(s->mac_reg + VFTA) +
  ((vid >> 5) & 0x7f));
-if ((vfta & (1 << (vid & 0x1f))) == 0)
+if ((vfta & (1 << (vid & 0x1f))) == 0) {
 return 0;
+}
 }
 
 if (!isbcast && !ismcast && (rctl & E1000_RCTL_UPE)) { /* promiscuous 
ucast */
@@ -1220,16 +1221,16 @@ static const readops macreg_readops[] = {
 [TDFPC]   = mac_low13_read,
 [AIT] = mac_low16_read,
 
-[CRCERRS ... MPC]   = _readreg,
-[IP6AT ... IP6AT+3] = _readreg,[IP4AT ... IP4AT+6] = _readreg,
-[FFLT ... FFLT+6]   = _low11_read,
-[RA ... RA+31]  = _readreg,
-[WUPM ... WUPM+31]  = _readreg,
-[MTA ... MTA+127]   = _readreg,
-[VFTA ... VFTA+127] = _readreg,
-[FFMT ... FFMT+254] = _low4_read,
-[FFVT ... FFVT+254] = _readreg,
-[PBM ... PBM+16383] = _readreg,
+[CRCERRS ... MPC] = _readreg,
+[IP6AT ... IP6AT + 3] = _readreg,[IP4AT ... IP4AT + 6] = 
_readreg,
+[FFLT ... FFLT + 6]   = _low11_read,
+[RA ... RA + 31]  = _readreg,
+[WUPM ... WUPM + 31]  = _readreg,
+[MTA ... MTA + 127]   = _readreg,
+[VFTA ... VFTA + 127] = _readreg,
+[FFMT ... FFMT + 254] = _low4_read,
+[FFVT ... FFVT + 254] = _readreg,
+[PBM ... PBM + 16383] = _readreg,
 };
 enum { NREADOPS = ARRAY_SIZE(macreg_readops) };
 
@@ -1252,14 +1253,14 @@ static const writeops macreg_writeops[] = {
 [RDTR]   = set_16bit,  [RADV]   = set_16bit,  [TADV] = set_16bit,
 [ITR]= set_16bit,
 
-[IP6AT ... IP6AT+3] = _writereg, [IP4AT ... IP4AT+6] = _writereg,
-[FFLT ... FFLT+6]   = _writereg,
-[RA ... RA+31]  = _writereg,
-[WUPM ... WUPM+31]  = _writereg,
-[MTA ... MTA+127]   = _writereg,
-[VFTA ... VFTA+127] = _writereg,
-[FFMT ... FFMT+254] = _writereg, [FFVT ... FFVT+254] = _writereg,
-[PBM ... PBM+16383] = _writereg,
+[IP6AT ... IP6AT + 3] = _writereg, [IP4AT ... IP4AT + 6] = 
_writereg,
+[FFLT ... FFLT + 6]   = _writereg,
+[RA ... RA + 31]  = _writereg,
+[WUPM ... WUPM + 31]  = _writereg,
+[MTA ... MTA + 127]   = _writereg,
+[VFTA ... VFTA + 127] = _writereg,
+[FFMT ... FFMT + 254] = _writereg, [FFVT ... FFVT + 254] = 
_writereg,
+[PBM ... PBM + 16383] = _writereg,
 };
 
 enum { NWRITEOPS = ARRAY_SIZE(macreg_writeops) };
diff --git a/hw/net/e1000e.c b/hw/net/e1000e.c
index 7523e9f..8635ca1 100644
--- a/hw/net/e1000e.c
+++ b/hw/net/e1000e.c
@@ -1,37 +1,37 @@
 /*
-* QEMU INTEL 82574 GbE NIC emulation
-*
-* Software developer's manuals:
-* 
http://www.intel.com/content/dam/doc/datasheet/82574l-gbe-controller-datasheet.pdf
-*
-* Copyright (c) 2015 Ravello Systems LTD (http://ravellosystems.com)
-* Developed by Daynix Computing LTD (http://www.daynix.com)
-*
-* Authors:
-* Dmitry Fleytman 
-* Leonid Bloch 
-* Yan Vugenfirer 
-*
-* 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 .
-*/
+ * QEMU INTEL 82574 GbE NIC emulation
+ *
+ * Software developer's manuals:
+ * 
http://www.intel.com/content/dam/doc/datasheet/82574l-gbe-controller-datasheet.pdf
+ *
+ * Copyright (c) 2015 Ravello Systems LTD 

[PULL 29/51] MAINTAINERS: Add e1000e test files

2023-03-06 Thread Jason Wang
From: Akihiko Odaki 

Signed-off-by: Akihiko Odaki 
Acked-by: Thomas Huth 
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Jason Wang 
---
 MAINTAINERS | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index d263e52..35682ca 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2229,6 +2229,8 @@ R: Akihiko Odaki 
 S: Maintained
 F: hw/net/e1000e*
 F: tests/qtest/fuzz-e1000e-test.c
+F: tests/qtest/e1000e-test.c
+F: tests/qtest/libqos/e1000e.*
 
 eepro100
 M: Stefan Weil 
-- 
2.7.4




[PULL 35/51] net/eth: Introduce EthL4HdrProto

2023-03-06 Thread Jason Wang
From: Akihiko Odaki 

igb, a new network device emulation, will need SCTP checksum offloading.
Currently eth_get_protocols() has a bool parameter for each protocol
currently it supports, but there will be a bit too many parameters if
we add yet another protocol.

Introduce an enum type, EthL4HdrProto to represent all L4 protocols
eth_get_protocols() support with one parameter.

Signed-off-by: Akihiko Odaki 
Signed-off-by: Jason Wang 
---
 hw/net/e1000e_core.c | 60 ++---
 hw/net/net_rx_pkt.c  | 48 ++--
 hw/net/net_rx_pkt.h  |  5 ++--
 hw/net/trace-events  |  8 +++---
 hw/net/virtio-net.c  | 69 ++--
 hw/net/vmxnet3.c | 22 +++--
 include/net/eth.h|  8 +-
 net/eth.c| 26 +++-
 8 files changed, 147 insertions(+), 99 deletions(-)

diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c
index e8d466b..c6111c2 100644
--- a/hw/net/e1000e_core.c
+++ b/hw/net/e1000e_core.c
@@ -497,18 +497,20 @@ typedef struct E1000E_RSSInfo_st {
 static uint32_t
 e1000e_rss_get_hash_type(E1000ECore *core, struct NetRxPkt *pkt)
 {
-bool hasip4, hasip6, hasudp, hastcp;
+bool hasip4, hasip6;
+EthL4HdrProto l4hdr_proto;
 
 assert(e1000e_rss_enabled(core));
 
-net_rx_pkt_get_protocols(pkt, , , , );
+net_rx_pkt_get_protocols(pkt, , , _proto);
 
 if (hasip4) {
-trace_e1000e_rx_rss_ip4(hastcp, core->mac[MRQC],
+trace_e1000e_rx_rss_ip4(l4hdr_proto, core->mac[MRQC],
 E1000_MRQC_EN_TCPIPV4(core->mac[MRQC]),
 E1000_MRQC_EN_IPV4(core->mac[MRQC]));
 
-if (hastcp && E1000_MRQC_EN_TCPIPV4(core->mac[MRQC])) {
+if (l4hdr_proto == ETH_L4_HDR_PROTO_TCP &&
+E1000_MRQC_EN_TCPIPV4(core->mac[MRQC])) {
 return E1000_MRQ_RSS_TYPE_IPV4TCP;
 }
 
@@ -529,7 +531,7 @@ e1000e_rss_get_hash_type(E1000ECore *core, struct NetRxPkt 
*pkt)
  * backends like these.
  */
 trace_e1000e_rx_rss_ip6_rfctl(core->mac[RFCTL]);
-trace_e1000e_rx_rss_ip6(ex_dis, new_ex_dis, hastcp,
+trace_e1000e_rx_rss_ip6(ex_dis, new_ex_dis, l4hdr_proto,
 ip6info->has_ext_hdrs,
 ip6info->rss_ex_dst_valid,
 ip6info->rss_ex_src_valid,
@@ -542,7 +544,8 @@ e1000e_rss_get_hash_type(E1000ECore *core, struct NetRxPkt 
*pkt)
 (!new_ex_dis || !(ip6info->rss_ex_dst_valid ||
   ip6info->rss_ex_src_valid))) {
 
-if (hastcp && E1000_MRQC_EN_TCPIPV6(core->mac[MRQC])) {
+if (l4hdr_proto == ETH_L4_HDR_PROTO_TCP &&
+E1000_MRQC_EN_TCPIPV6(core->mac[MRQC])) {
 return E1000_MRQ_RSS_TYPE_IPV6TCP;
 }
 
@@ -1124,7 +1127,7 @@ static void
 e1000e_verify_csum_in_sw(E1000ECore *core,
  struct NetRxPkt *pkt,
  uint32_t *status_flags,
- bool hastcp, bool hasudp)
+ EthL4HdrProto l4hdr_proto)
 {
 bool csum_valid;
 uint32_t csum_error;
@@ -1151,14 +1154,10 @@ e1000e_verify_csum_in_sw(E1000ECore *core,
 }
 
 csum_error = csum_valid ? 0 : E1000_RXDEXT_STATERR_TCPE;
+*status_flags |= E1000_RXD_STAT_TCPCS | csum_error;
 
-if (hastcp) {
-*status_flags |= E1000_RXD_STAT_TCPCS |
- csum_error;
-} else if (hasudp) {
-*status_flags |= E1000_RXD_STAT_TCPCS |
- E1000_RXD_STAT_UDPCS |
- csum_error;
+if (l4hdr_proto == ETH_L4_HDR_PROTO_UDP) {
+*status_flags |= E1000_RXD_STAT_UDPCS;
 }
 }
 
@@ -1187,7 +1186,8 @@ e1000e_build_rx_metadata(E1000ECore *core,
  uint16_t *vlan_tag)
 {
 struct virtio_net_hdr *vhdr;
-bool hasip4, hasip6, hastcp, hasudp;
+bool hasip4, hasip6;
+EthL4HdrProto l4hdr_proto;
 uint32_t pkt_type;
 
 *status_flags = E1000_RXD_STAT_DD;
@@ -1199,8 +1199,8 @@ e1000e_build_rx_metadata(E1000ECore *core,
 
 *status_flags |= E1000_RXD_STAT_EOP;
 
-net_rx_pkt_get_protocols(pkt, , , , );
-trace_e1000e_rx_metadata_protocols(hasip4, hasip6, hasudp, hastcp);
+net_rx_pkt_get_protocols(pkt, , , _proto);
+trace_e1000e_rx_metadata_protocols(hasip4, hasip6, l4hdr_proto);
 
 /* VLAN state */
 if (net_rx_pkt_is_vlan_stripped(pkt)) {
@@ -1222,7 +1222,7 @@ e1000e_build_rx_metadata(E1000ECore *core,
 trace_e1000e_rx_metadata_ip_id(*ip_id);
 }
 
-if (hastcp && e1000e_is_tcp_ack(core, pkt)) {
+if (l4hdr_proto == ETH_L4_HDR_PROTO_TCP && e1000e_is_tcp_ack(core, pkt)) {
 *status_flags |= E1000_RXD_STAT_ACK;
 trace_e1000e_rx_metadata_ack();
 }
@@ -1230,7 +1230,8 @@ e1000e_build_rx_metadata(E1000ECore *core,
 if (hasip6 && (core->mac[RFCTL] & 

[PULL 34/51] e1000e: Implement system clock

2023-03-06 Thread Jason Wang
From: Akihiko Odaki 

The system clock is necessary to implement PTP features. While we are
not implementing PTP features for e1000e yet, we do have a plan to
implement them for igb, a new network device derived from e1000e,
so add system clock to the common base first.

Signed-off-by: Akihiko Odaki 
Signed-off-by: Jason Wang 
---
 hw/core/machine.c  |  1 +
 hw/net/e1000_regs.h| 27 +++
 hw/net/e1000e.c| 11 +++
 hw/net/e1000e_core.c   | 39 ++-
 hw/net/e1000e_core.h   |  2 ++
 hw/net/e1000x_common.c | 25 +
 hw/net/e1000x_common.h |  3 +++
 7 files changed, 103 insertions(+), 5 deletions(-)

diff --git a/hw/core/machine.c b/hw/core/machine.c
index 1cf6822..45e3d24 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -40,6 +40,7 @@
 #include "hw/virtio/virtio-pci.h"
 
 GlobalProperty hw_compat_7_2[] = {
+{ "e1000e", "migrate-timadj", "off" },
 { "virtio-mem", "x-early-migration", "false" },
 };
 const size_t hw_compat_7_2_len = G_N_ELEMENTS(hw_compat_7_2);
diff --git a/hw/net/e1000_regs.h b/hw/net/e1000_regs.h
index 4545fe2..77144cb 100644
--- a/hw/net/e1000_regs.h
+++ b/hw/net/e1000_regs.h
@@ -908,6 +908,33 @@
 #define E1000_EEPROM_CFG_DONE 0x0004   /* MNG config cycle done */
 #define E1000_EEPROM_CFG_DONE_PORT_1  0x0008   /* ...for second port */
 
+/* HH Time Sync */
+#define E1000_TSYNCTXCTL_MAX_ALLOWED_DLY_MASK 0xF000 /* max delay */
+#define E1000_TSYNCTXCTL_SYNC_COMP0x4000 /* sync complete */
+#define E1000_TSYNCTXCTL_START_SYNC   0x8000 /* initiate sync */
+
+#define E1000_TSYNCTXCTL_VALID0x0001 /* Tx timestamp valid 
*/
+#define E1000_TSYNCTXCTL_ENABLED  0x0010 /* enable Tx 
timestamping */
+
+#define E1000_TSYNCRXCTL_VALID0x0001 /* Rx timestamp valid 
*/
+#define E1000_TSYNCRXCTL_TYPE_MASK0x000E /* Rx type mask */
+#define E1000_TSYNCRXCTL_TYPE_L2_V2   0x00
+#define E1000_TSYNCRXCTL_TYPE_L4_V1   0x02
+#define E1000_TSYNCRXCTL_TYPE_L2_L4_V20x04
+#define E1000_TSYNCRXCTL_TYPE_ALL 0x08
+#define E1000_TSYNCRXCTL_TYPE_EVENT_V20x0A
+#define E1000_TSYNCRXCTL_ENABLED  0x0010 /* enable Rx 
timestamping */
+#define E1000_TSYNCRXCTL_SYSCFI   0x0020 /* Sys clock 
frequency */
+
+#define E1000_RXMTRL_PTP_V1_SYNC_MESSAGE  0x
+#define E1000_RXMTRL_PTP_V1_DELAY_REQ_MESSAGE 0x0001
+
+#define E1000_RXMTRL_PTP_V2_SYNC_MESSAGE  0x
+#define E1000_RXMTRL_PTP_V2_DELAY_REQ_MESSAGE 0x0100
+
+#define E1000_TIMINCA_INCPERIOD_SHIFT 24
+#define E1000_TIMINCA_INCVALUE_MASK   0x00FF
+
 /* PCI Express Control */
 /* 3GIO Control Register - GCR (0x05B00; RW) */
 #define E1000_L0S_ADJUST  (1 << 9)
diff --git a/hw/net/e1000e.c b/hw/net/e1000e.c
index ec27431..78c07a8 100644
--- a/hw/net/e1000e.c
+++ b/hw/net/e1000e.c
@@ -82,6 +82,7 @@ struct E1000EState {
 
 E1000ECore core;
 bool init_vet;
+bool timadj;
 };
 
 #define E1000E_MMIO_IDX 0
@@ -554,6 +555,12 @@ static int e1000e_post_load(void *opaque, int version_id)
 return e1000e_core_post_load(>core);
 }
 
+static bool e1000e_migrate_timadj(void *opaque, int version_id)
+{
+E1000EState *s = opaque;
+return s->timadj;
+}
+
 static const VMStateDescription e1000e_vmstate_tx = {
 .name = "e1000e-tx",
 .version_id = 1,
@@ -645,6 +652,9 @@ static const VMStateDescription e1000e_vmstate = {
 
 VMSTATE_STRUCT_ARRAY(core.tx, E1000EState, E1000E_NUM_QUEUES, 0,
  e1000e_vmstate_tx, struct e1000e_tx),
+
+VMSTATE_INT64_TEST(core.timadj, E1000EState, e1000e_migrate_timadj),
+
 VMSTATE_END_OF_LIST()
 }
 };
@@ -663,6 +673,7 @@ static Property e1000e_properties[] = {
 DEFINE_PROP_SIGNED("subsys", E1000EState, subsys, 0,
 e1000e_prop_subsys, uint16_t),
 DEFINE_PROP_BOOL("init-vet", E1000EState, init_vet, true),
+DEFINE_PROP_BOOL("migrate-timadj", E1000EState, timadj, true),
 DEFINE_PROP_END_OF_LIST(),
 };
 
diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c
index a297463..e8d466b 100644
--- a/hw/net/e1000e_core.c
+++ b/hw/net/e1000e_core.c
@@ -2902,6 +2902,35 @@ e1000e_set_gcr(E1000ECore *core, int index, uint32_t val)
 core->mac[GCR] = (val & ~E1000_GCR_RO_BITS) | ro_bits;
 }
 
+static uint32_t e1000e_get_systiml(E1000ECore *core, int index)
+{
+e1000x_timestamp(core->mac, core->timadj, SYSTIML, SYSTIMH);
+return core->mac[SYSTIML];
+}
+
+static uint32_t e1000e_get_rxsatrh(E1000ECore *core, int index)
+{
+core->mac[TSYNCRXCTL] &= ~E1000_TSYNCRXCTL_VALID;
+return core->mac[RXSATRH];
+}
+
+static uint32_t e1000e_get_txstmph(E1000ECore *core, int index)
+{
+core->mac[TSYNCTXCTL] &= ~E1000_TSYNCTXCTL_VALID;
+return core->mac[TXSTMPH];
+}
+
+static void 

[PULL 14/51] e1000: Configure ResettableClass

2023-03-06 Thread Jason Wang
From: Akihiko Odaki 

This is part of recent efforts of refactoring e1000 and e1000e.

DeviceClass's reset member is deprecated so migrate to ResettableClass.
There is no behavioral difference.

Signed-off-by: Akihiko Odaki 
Reviewed-by: Peter Maydell 
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Jason Wang 
---
 hw/net/e1000.c | 13 -
 1 file changed, 4 insertions(+), 9 deletions(-)

diff --git a/hw/net/e1000.c b/hw/net/e1000.c
index 3353a37..c81d914 100644
--- a/hw/net/e1000.c
+++ b/hw/net/e1000.c
@@ -377,9 +377,9 @@ static bool e1000_vet_init_need(void *opaque)
 return chkflag(VET);
 }
 
-static void e1000_reset(void *opaque)
+static void e1000_reset_hold(Object *obj)
 {
-E1000State *d = opaque;
+E1000State *d = E1000(obj);
 E1000BaseClass *edc = E1000_GET_CLASS(d);
 uint8_t *macaddr = d->conf.macaddr.a;
 
@@ -1731,12 +1731,6 @@ static void pci_e1000_realize(PCIDevice *pci_dev, Error 
**errp)
 e1000_flush_queue_timer, d);
 }
 
-static void qdev_e1000_reset(DeviceState *dev)
-{
-E1000State *d = E1000(dev);
-e1000_reset(d);
-}
-
 static Property e1000_properties[] = {
 DEFINE_NIC_PROPERTIES(E1000State, conf),
 DEFINE_PROP_BIT("autonegotiation", E1000State,
@@ -1762,6 +1756,7 @@ typedef struct E1000Info {
 static void e1000_class_init(ObjectClass *klass, void *data)
 {
 DeviceClass *dc = DEVICE_CLASS(klass);
+ResettableClass *rc = RESETTABLE_CLASS(klass);
 PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
 E1000BaseClass *e = E1000_CLASS(klass);
 const E1000Info *info = data;
@@ -1774,9 +1769,9 @@ static void e1000_class_init(ObjectClass *klass, void 
*data)
 k->revision = info->revision;
 e->phy_id2 = info->phy_id2;
 k->class_id = PCI_CLASS_NETWORK_ETHERNET;
+rc->phases.hold = e1000_reset_hold;
 set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
 dc->desc = "Intel Gigabit Ethernet";
-dc->reset = qdev_e1000_reset;
 dc->vmsd = _e1000;
 device_class_set_props(dc, e1000_properties);
 }
-- 
2.7.4




[PULL 42/51] tests/avocado: Add igb test

2023-03-06 Thread Jason Wang
From: Akihiko Odaki 

This automates ethtool tests for igb registers, interrupts, etc.

Signed-off-by: Akihiko Odaki 
Reviewed-by: Cédric Le Goater 
Signed-off-by: Jason Wang 
---
 MAINTAINERS|  1 +
 scripts/ci/org.centos/stream/8/x86_64/test-avocado |  1 +
 tests/avocado/igb.py   | 38 ++
 3 files changed, 40 insertions(+)
 create mode 100644 tests/avocado/igb.py

diff --git a/MAINTAINERS b/MAINTAINERS
index e5d5d9f..77f3dd3 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2236,6 +2236,7 @@ igb
 M: Akihiko Odaki 
 S: Maintained
 F: hw/net/igb*
+F: tests/avocado/igb.py
 F: tests/qtest/igb-test.c
 F: tests/qtest/libqos/igb.c
 
diff --git a/scripts/ci/org.centos/stream/8/x86_64/test-avocado 
b/scripts/ci/org.centos/stream/8/x86_64/test-avocado
index f403e4e..d2c0e5f 100755
--- a/scripts/ci/org.centos/stream/8/x86_64/test-avocado
+++ b/scripts/ci/org.centos/stream/8/x86_64/test-avocado
@@ -30,6 +30,7 @@ make get-vm-images
 tests/avocado/cpu_queries.py:QueryCPUModelExpansion.test \
 tests/avocado/empty_cpu_model.py:EmptyCPUModel.test \
 tests/avocado/hotplug_cpu.py:HotPlugCPU.test \
+tests/avocado/igb.py:IGB.test \
 tests/avocado/info_usernet.py:InfoUsernet.test_hostfwd \
 tests/avocado/intel_iommu.py:IntelIOMMU.test_intel_iommu \
 tests/avocado/intel_iommu.py:IntelIOMMU.test_intel_iommu_pt \
diff --git a/tests/avocado/igb.py b/tests/avocado/igb.py
new file mode 100644
index 000..abf5dfa
--- /dev/null
+++ b/tests/avocado/igb.py
@@ -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')
-- 
2.7.4




[PULL 07/51] e1000e: Mask registers when writing

2023-03-06 Thread Jason Wang
From: Akihiko Odaki 

When a register has effective bits fewer than their width, the old code
inconsistently masked when writing or reading. Make the code consistent
by always masking when writing, and remove some code duplication.

Signed-off-by: Akihiko Odaki 
Signed-off-by: Jason Wang 
---
 hw/net/e1000e_core.c | 76 ++--
 1 file changed, 32 insertions(+), 44 deletions(-)

diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c
index 1cafc38..e6fc85e 100644
--- a/hw/net/e1000e_core.c
+++ b/hw/net/e1000e_core.c
@@ -2447,7 +2447,11 @@ e1000e_set_fcrtl(E1000ECore *core, int index, uint32_t 
val)
 core->mac[index] = val & (BIT(num) - 1); \
 }
 
+E1000E_LOW_BITS_SET_FUNC(4)
+E1000E_LOW_BITS_SET_FUNC(6)
+E1000E_LOW_BITS_SET_FUNC(11)
 E1000E_LOW_BITS_SET_FUNC(12)
+E1000E_LOW_BITS_SET_FUNC(13)
 E1000E_LOW_BITS_SET_FUNC(16)
 
 static void
@@ -2619,22 +2623,6 @@ e1000e_mac_ims_read(E1000ECore *core, int index)
 return core->mac[IMS];
 }
 
-#define E1000E_LOW_BITS_READ_FUNC(num)  \
-static uint32_t \
-e1000e_mac_low##num##_read(E1000ECore *core, int index) \
-{   \
-return core->mac[index] & (BIT(num) - 1);   \
-}   \
-
-#define E1000E_LOW_BITS_READ(num)   \
-e1000e_mac_low##num##_read
-
-E1000E_LOW_BITS_READ_FUNC(4);
-E1000E_LOW_BITS_READ_FUNC(6);
-E1000E_LOW_BITS_READ_FUNC(11);
-E1000E_LOW_BITS_READ_FUNC(13);
-E1000E_LOW_BITS_READ_FUNC(16);
-
 static uint32_t
 e1000e_mac_swsm_read(E1000ECore *core, int index)
 {
@@ -2928,7 +2916,19 @@ static const readops e1000e_macreg_readops[] = {
 e1000e_getreg(LATECOL),
 e1000e_getreg(SEQEC),
 e1000e_getreg(XONTXC),
+e1000e_getreg(AIT),
+e1000e_getreg(TDFH),
+e1000e_getreg(TDFT),
+e1000e_getreg(TDFHS),
+e1000e_getreg(TDFTS),
+e1000e_getreg(TDFPC),
 e1000e_getreg(WUS),
+e1000e_getreg(PBS),
+e1000e_getreg(RDFH),
+e1000e_getreg(RDFT),
+e1000e_getreg(RDFHS),
+e1000e_getreg(RDFTS),
+e1000e_getreg(RDFPC),
 e1000e_getreg(GORCL),
 e1000e_getreg(MGTPRC),
 e1000e_getreg(EERD),
@@ -3064,16 +3064,9 @@ static const readops e1000e_macreg_readops[] = {
 [MPTC]= e1000e_mac_read_clr4,
 [IAC] = e1000e_mac_read_clr4,
 [ICR] = e1000e_mac_icr_read,
-[RDFH]= E1000E_LOW_BITS_READ(13),
-[RDFHS]   = E1000E_LOW_BITS_READ(13),
-[RDFPC]   = E1000E_LOW_BITS_READ(13),
-[TDFH]= E1000E_LOW_BITS_READ(13),
-[TDFHS]   = E1000E_LOW_BITS_READ(13),
 [STATUS]  = e1000e_get_status,
 [TARC0]   = e1000e_get_tarc,
-[PBS] = E1000E_LOW_BITS_READ(6),
 [ICS] = e1000e_mac_ics_read,
-[AIT] = E1000E_LOW_BITS_READ(16),
 [TORH]= e1000e_mac_read_clr8,
 [GORCH]   = e1000e_mac_read_clr8,
 [PRC127]  = e1000e_mac_read_clr4,
@@ -3089,11 +3082,6 @@ static const readops e1000e_macreg_readops[] = {
 [BPTC]= e1000e_mac_read_clr4,
 [TSCTC]   = e1000e_mac_read_clr4,
 [ITR] = e1000e_mac_itr_read,
-[RDFT]= E1000E_LOW_BITS_READ(13),
-[RDFTS]   = E1000E_LOW_BITS_READ(13),
-[TDFPC]   = E1000E_LOW_BITS_READ(13),
-[TDFT]= E1000E_LOW_BITS_READ(13),
-[TDFTS]   = E1000E_LOW_BITS_READ(13),
 [CTRL]= e1000e_get_ctrl,
 [TARC1]   = e1000e_get_tarc,
 [SWSM]= e1000e_mac_swsm_read,
@@ -3106,10 +3094,10 @@ static const readops e1000e_macreg_readops[] = {
 [WUPM ... WUPM + 31]   = e1000e_mac_readreg,
 [MTA ... MTA + 127]= e1000e_mac_readreg,
 [VFTA ... VFTA + 127]  = e1000e_mac_readreg,
-[FFMT ... FFMT + 254]  = E1000E_LOW_BITS_READ(4),
+[FFMT ... FFMT + 254]  = e1000e_mac_readreg,
 [FFVT ... FFVT + 254]  = e1000e_mac_readreg,
 [MDEF ... MDEF + 7]= e1000e_mac_readreg,
-[FFLT ... FFLT + 10]   = E1000E_LOW_BITS_READ(11),
+[FFLT ... FFLT + 10]   = e1000e_mac_readreg,
 [FTFT ... FTFT + 254]  = e1000e_mac_readreg,
 [PBM ... PBM + 10239]  = e1000e_mac_readreg,
 [RETA ... RETA + 31]   = e1000e_mac_readreg,
@@ -3132,19 +3120,8 @@ static const writeops e1000e_macreg_writeops[] = {
 e1000e_putreg(LEDCTL),
 e1000e_putreg(FCAL),
 e1000e_putreg(FCRUC),
-e1000e_putreg(AIT),
-e1000e_putreg(TDFH),
-e1000e_putreg(TDFT),
-e1000e_putreg(TDFHS),
-e1000e_putreg(TDFTS),
-e1000e_putreg(TDFPC),
 e1000e_putreg(WUC),
 e1000e_putreg(WUS),
-e1000e_putreg(RDFH),
-e1000e_putreg(RDFT),
-e1000e_putreg(RDFHS),
-e1000e_putreg(RDFTS),
-e1000e_putreg(RDFPC),
 e1000e_putreg(IPAV),
 e1000e_putreg(TDBAH1),
 e1000e_putreg(TIMINCA),
@@ -3155,7 +3132,6 @@ static const writeops e1000e_macreg_writeops[] = {
 e1000e_putreg(TARC1),
 e1000e_putreg(FLSWDATA),
 e1000e_putreg(POEMB),
-e1000e_putreg(PBS),
 

[PULL 20/51] e1000x: Alter the signature of e1000x_is_vlan_packet

2023-03-06 Thread Jason Wang
From: Akihiko Odaki 

e1000x_is_vlan_packet() had a pointer to uint8_t as a parameter, but
it does not have to be uint8_t. Change the type to void *.

Signed-off-by: Akihiko Odaki 
Signed-off-by: Jason Wang 
---
 hw/net/e1000x_common.c | 2 +-
 hw/net/e1000x_common.h | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/net/e1000x_common.c b/hw/net/e1000x_common.c
index b3bbf31..e6387dd 100644
--- a/hw/net/e1000x_common.c
+++ b/hw/net/e1000x_common.c
@@ -47,7 +47,7 @@ bool e1000x_rx_ready(PCIDevice *d, uint32_t *mac)
 return true;
 }
 
-bool e1000x_is_vlan_packet(const uint8_t *buf, uint16_t vet)
+bool e1000x_is_vlan_packet(const void *buf, uint16_t vet)
 {
 uint16_t eth_proto = lduw_be_p(_GET_ETH_HDR(buf)->h_proto);
 bool res = (eth_proto == vet);
diff --git a/hw/net/e1000x_common.h b/hw/net/e1000x_common.h
index b991d81..86a31b6 100644
--- a/hw/net/e1000x_common.h
+++ b/hw/net/e1000x_common.h
@@ -178,7 +178,7 @@ uint32_t e1000x_rxbufsize(uint32_t rctl);
 
 bool e1000x_rx_ready(PCIDevice *d, uint32_t *mac);
 
-bool e1000x_is_vlan_packet(const uint8_t *buf, uint16_t vet);
+bool e1000x_is_vlan_packet(const void *buf, uint16_t vet);
 
 bool e1000x_rx_group_filter(uint32_t *mac, const uint8_t *buf);
 
-- 
2.7.4




[PULL 06/51] e1000e: Introduce E1000E_LOW_BITS_SET_FUNC

2023-03-06 Thread Jason Wang
From: Akihiko Odaki 

e1000e_set_16bit and e1000e_set_12bit look so similar so define a
generic macro.

Signed-off-by: Akihiko Odaki 
Signed-off-by: Jason Wang 
---
 hw/net/e1000e_core.c | 18 --
 1 file changed, 8 insertions(+), 10 deletions(-)

diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c
index 181c1e0..1cafc38 100644
--- a/hw/net/e1000e_core.c
+++ b/hw/net/e1000e_core.c
@@ -2440,17 +2440,15 @@ e1000e_set_fcrtl(E1000ECore *core, int index, uint32_t 
val)
 core->mac[FCRTL] = val & 0x8000FFF8;
 }
 
-static inline void
-e1000e_set_16bit(E1000ECore *core, int index, uint32_t val)
-{
-core->mac[index] = val & 0x;
-}
+#define E1000E_LOW_BITS_SET_FUNC(num)\
+static void  \
+e1000e_set_##num##bit(E1000ECore *core, int index, uint32_t val) \
+{\
+core->mac[index] = val & (BIT(num) - 1); \
+}
 
-static void
-e1000e_set_12bit(E1000ECore *core, int index, uint32_t val)
-{
-core->mac[index] = val & 0xfff;
-}
+E1000E_LOW_BITS_SET_FUNC(12)
+E1000E_LOW_BITS_SET_FUNC(16)
 
 static void
 e1000e_set_vet(E1000ECore *core, int index, uint32_t val)
-- 
2.7.4




[PULL 10/51] e1000: Use memcpy to intialize registers

2023-03-06 Thread Jason Wang
From: Akihiko Odaki 

Use memcpy instead of memmove to initialize registers. The initial
register templates and register table instances will never overlap.

Signed-off-by: Akihiko Odaki 
Signed-off-by: Jason Wang 
---
 hw/net/e1000.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/net/e1000.c b/hw/net/e1000.c
index d9d048f..3353a37 100644
--- a/hw/net/e1000.c
+++ b/hw/net/e1000.c
@@ -390,10 +390,10 @@ static void e1000_reset(void *opaque)
 d->mit_irq_level = 0;
 d->mit_ide = 0;
 memset(d->phy_reg, 0, sizeof d->phy_reg);
-memmove(d->phy_reg, phy_reg_init, sizeof phy_reg_init);
+memcpy(d->phy_reg, phy_reg_init, sizeof phy_reg_init);
 d->phy_reg[MII_PHYID2] = edc->phy_id2;
 memset(d->mac_reg, 0, sizeof d->mac_reg);
-memmove(d->mac_reg, mac_reg_init, sizeof mac_reg_init);
+memcpy(d->mac_reg, mac_reg_init, sizeof mac_reg_init);
 d->rxbuf_min_shift = 1;
 memset(>tx, 0, sizeof d->tx);
 
-- 
2.7.4




[PULL 17/51] e1000e: Set MII_ANER_NWAY

2023-03-06 Thread Jason Wang
From: Akihiko Odaki 

This keeps Windows driver 12.18.9.23 from generating an event with ID
30. The description of the event is as follows:
> Intel(R) 82574L Gigabit Network Connection
>  PROBLEM: The network adapter is configured for auto-negotiation but
> the link partner is not.  This may result in a duplex mismatch.
>  ACTION: Configure the link partner for auto-negotiation.

Signed-off-by: Akihiko Odaki 
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Jason Wang 
---
 hw/net/e1000e_core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c
index d8c17ba..7367084 100644
--- a/hw/net/e1000e_core.c
+++ b/hw/net/e1000e_core.c
@@ -3426,7 +3426,7 @@ 
e1000e_phy_reg_init[E1000E_PHY_PAGES][E1000E_PHY_PAGE_SIZE] = {
 [MII_ANLPAR]= MII_ANLPAR_10 | MII_ANLPAR_10FD |
   MII_ANLPAR_TX | MII_ANLPAR_TXFD |
   MII_ANLPAR_T4 | MII_ANLPAR_PAUSE,
-[MII_ANER]  = MII_ANER_NP,
+[MII_ANER]  = MII_ANER_NP | MII_ANER_NWAY,
 [MII_ANNP]  = 1 | MII_ANNP_MP,
 [MII_CTRL1000]  = MII_CTRL1000_HALF | MII_CTRL1000_FULL |
   MII_CTRL1000_PORT | MII_CTRL1000_MASTER,
-- 
2.7.4




[PULL 48/51] hw/net/eepro100: Pass E100PCIDeviceInfo as class init data

2023-03-06 Thread Jason Wang
From: Philippe Mathieu-Daudé 

QOM already provides the TypeInfo::class_data to set
class-specific data. Use it instead of reinventing the
wheel with eepro100_get_class_by_name(). This finishes
the QDev conversion started 12 years ago in commit
40021f0888 ("pci: convert to QEMU Object Model").

Signed-off-by: Philippe Mathieu-Daudé 
Signed-off-by: Jason Wang 
---
 hw/net/eepro100.c | 63 ++-
 1 file changed, 20 insertions(+), 43 deletions(-)

diff --git a/hw/net/eepro100.c b/hw/net/eepro100.c
index 722fb55..ab20558 100644
--- a/hw/net/eepro100.c
+++ b/hw/net/eepro100.c
@@ -242,6 +242,8 @@ struct EEPRO100Class {
 /*< private >*/
 PCIDeviceClass parent_class;
 /*< public >*/
+
+const E100PCIDeviceInfo *info;
 };
 
 struct EEPRO100State {
@@ -338,8 +340,6 @@ static const uint16_t eepro100_mdi_mask[] = {
 0x, 0x, 0x, 0x, 0x, 0x, 0x, 0x,
 };
 
-static E100PCIDeviceInfo *eepro100_get_class(EEPRO100State *s);
-
 /* Read a 16 bit control/status (CSR) register. */
 static uint16_t e100_read_reg2(EEPRO100State *s, E100RegisterOffset addr)
 {
@@ -489,8 +489,9 @@ static void eepro100_fcp_interrupt(EEPRO100State * s)
 static void e100_pci_reset(DeviceState *dev)
 {
 EEPRO100State *s = EEPRO100(dev);
-E100PCIDeviceInfo *info = eepro100_get_class(s);
-uint32_t device = s->device;
+EEPRO100Class *ek = EEPRO100_GET_CLASS(s);
+const E100PCIDeviceInfo *info = ek->info;
+uint32_t device = info->device;
 uint8_t *pci_conf = s->dev.config;
 
 TRACE(OTHER, logout("%p\n", s));
@@ -1847,11 +1848,11 @@ static NetClientInfo net_eepro100_info = {
 static void e100_nic_realize(PCIDevice *pci_dev, Error **errp)
 {
 EEPRO100State *s = DO_UPCAST(EEPRO100State, dev, pci_dev);
-E100PCIDeviceInfo *info = eepro100_get_class(s);
+EEPRO100Class *ek = EEPRO100_GET_CLASS(s);
 
 TRACE(OTHER, logout("\n"));
 
-s->device = info->device;
+s->device = ek->info->device;
 
 /* Add 64 * 2 EEPROM. i82557 and i82558 support a 64 word EEPROM,
  * i82559 and later support 64 or 256 word EEPROM. */
@@ -2028,32 +2029,19 @@ static E100PCIDeviceInfo e100_devices[] = {
 }
 };
 
-static E100PCIDeviceInfo *eepro100_get_class_by_name(const char *typename)
+static void eepro100_class_init(ObjectClass *klass, void *data)
 {
-E100PCIDeviceInfo *info = NULL;
-int i;
-
-/* This is admittedly awkward but also temporary.  QOM allows for
- * parameterized typing and for subclassing both of which would suitable
- * handle what's going on here.  But class_data is already being used as
- * a stop-gap hack to allow incremental qdev conversion so we cannot use it
- * right now.  Once we merge the final QOM series, we can come back here 
and
- * do this in a much more elegant fashion.
- */
-for (i = 0; i < ARRAY_SIZE(e100_devices); i++) {
-if (strcmp(e100_devices[i].name, typename) == 0) {
-info = _devices[i];
-break;
-}
-}
-assert(info != NULL);
-
-return info;
-}
+DeviceClass *dc = DEVICE_CLASS(klass);
+PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+EEPRO100Class *ek = EEPRO100_CLASS(klass);
+const E100PCIDeviceInfo *info = data;
 
-static E100PCIDeviceInfo *eepro100_get_class(EEPRO100State *s)
-{
-return eepro100_get_class_by_name(object_get_typename(OBJECT(s)));
+dc->desc = info->desc;
+k->device_id = info->device_id;
+k->revision = info->revision;
+k->subsystem_vendor_id = info->subsystem_vendor_id;
+k->subsystem_id = info->subsystem_id;
+ek->info = info;
 }
 
 static Property e100_properties[] = {
@@ -2065,8 +2053,6 @@ static void eepro100_base_class_init(ObjectClass *klass, 
void *data)
 {
 DeviceClass *dc = DEVICE_CLASS(klass);
 PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
-E100PCIDeviceInfo *info;
-
 
 set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
 device_class_set_props(dc, e100_properties);
@@ -2076,17 +2062,6 @@ static void eepro100_base_class_init(ObjectClass *klass, 
void *data)
 k->romfile = "pxe-eepro100.rom";
 k->realize = e100_nic_realize;
 k->exit = pci_nic_uninit;
-
-info = eepro100_get_class_by_name(object_class_get_name(klass));
-if (!info) {
-/* base class */
-return;
-}
-dc->desc = info->desc;
-k->device_id = info->device_id;
-k->revision = info->revision;
-k->subsystem_vendor_id = info->subsystem_vendor_id;
-k->subsystem_id = info->subsystem_id;
 }
 
 static const TypeInfo eepro100_base_info = {
@@ -2111,6 +2086,8 @@ static void eepro100_register_types(void)
 TypeInfo type_info = {
 .name   = e100_devices[i].name,
 .parent = TYPE_EEPRO100,
+.class_init= eepro100_class_init,
+.class_data = (void *)_devices[i],
 };
 
 type_register(_info);
-- 
2.7.4




[PULL 08/51] e1000: Use more constant definitions

2023-03-06 Thread Jason Wang
From: Akihiko Odaki 

The definitions for E1000_VFTA_ENTRY_SHIFT, E1000_VFTA_ENTRY_MASK, and
E1000_VFTA_ENTRY_BIT_SHIFT_MASK were copied from:
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/drivers/net/ethernet/intel/e1000/e1000_hw.h?h=v6.0.9#n306

The definitions for E1000_NUM_UNICAST, E1000_MC_TBL_SIZE, and
E1000_VLAN_FILTER_TBL_SIZE were copied from:
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/drivers/net/ethernet/intel/e1000/e1000_hw.h?h=v6.0.9#n707

Signed-off-by: Akihiko Odaki 
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Jason Wang 
---
 hw/net/e1000.c | 50 --
 hw/net/e1000_regs.h|  9 +
 hw/net/e1000x_common.c |  5 +++--
 hw/net/e1000x_common.h |  2 +-
 4 files changed, 41 insertions(+), 25 deletions(-)

diff --git a/hw/net/e1000.c b/hw/net/e1000.c
index 0925a99..d9d048f 100644
--- a/hw/net/e1000.c
+++ b/hw/net/e1000.c
@@ -43,8 +43,6 @@
 #include "trace.h"
 #include "qom/object.h"
 
-static const uint8_t bcast[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
-
 /* #define E1000_DEBUG */
 
 #ifdef E1000_DEBUG
@@ -67,9 +65,8 @@ static int debugflags = DBGBIT(TXERR) | DBGBIT(GENERAL);
 
 #define IOPORT_SIZE   0x40
 #define PNPMMIO_SIZE  0x2
-#define MIN_BUF_SIZE  60 /* Min. octets in an ethernet frame sans FCS */
 
-#define MAXIMUM_ETHERNET_HDR_LEN (14+4)
+#define MAXIMUM_ETHERNET_HDR_LEN (ETH_HLEN + 4)
 
 /*
  * HW models:
@@ -239,10 +236,16 @@ static const uint16_t phy_reg_init[] = {
 
 [MII_PHYID1] = 0x141,
 /* [MII_PHYID2] configured per DevId, from e1000_reset() */
-[MII_ANAR] = 0xde1,
-[MII_ANLPAR] = 0x1e0,
-[MII_CTRL1000] = 0x0e00,
-[MII_STAT1000] = 0x3c00,
+[MII_ANAR] = MII_ANAR_CSMACD | MII_ANAR_10 |
+ MII_ANAR_10FD | MII_ANAR_TX |
+ MII_ANAR_TXFD | MII_ANAR_PAUSE |
+ MII_ANAR_PAUSE_ASYM,
+[MII_ANLPAR] = MII_ANLPAR_10 | MII_ANLPAR_10FD |
+   MII_ANLPAR_TX | MII_ANLPAR_TXFD,
+[MII_CTRL1000] = MII_CTRL1000_FULL | MII_CTRL1000_PORT |
+ MII_CTRL1000_MASTER,
+[MII_STAT1000] = MII_STAT1000_HALF | MII_STAT1000_FULL |
+ MII_STAT1000_ROK | MII_STAT1000_LOK,
 [M88E1000_PHY_SPEC_CTRL] = 0x360,
 [M88E1000_PHY_SPEC_STATUS] = 0xac00,
 [M88E1000_EXT_PHY_SPEC_CTRL] = 0x0d60,
@@ -548,9 +551,9 @@ putsum(uint8_t *data, uint32_t n, uint32_t sloc, uint32_t 
css, uint32_t cse)
 static inline void
 inc_tx_bcast_or_mcast_count(E1000State *s, const unsigned char *arr)
 {
-if (!memcmp(arr, bcast, sizeof bcast)) {
+if (is_broadcast_ether_addr(arr)) {
 e1000x_inc_reg_if_not_full(s->mac_reg, BPTC);
-} else if (arr[0] & 1) {
+} else if (is_multicast_ether_addr(arr)) {
 e1000x_inc_reg_if_not_full(s->mac_reg, MPTC);
 }
 }
@@ -804,14 +807,16 @@ static int
 receive_filter(E1000State *s, const uint8_t *buf, int size)
 {
 uint32_t rctl = s->mac_reg[RCTL];
-int isbcast = !memcmp(buf, bcast, sizeof bcast), ismcast = (buf[0] & 1);
+int isbcast = is_broadcast_ether_addr(buf);
+int ismcast = is_multicast_ether_addr(buf);
 
 if (e1000x_is_vlan_packet(buf, le16_to_cpu(s->mac_reg[VET])) &&
 e1000x_vlan_rx_filter_enabled(s->mac_reg)) {
-uint16_t vid = lduw_be_p(buf + 14);
-uint32_t vfta = ldl_le_p((uint32_t *)(s->mac_reg + VFTA) +
- ((vid >> 5) & 0x7f));
-if ((vfta & (1 << (vid & 0x1f))) == 0) {
+uint16_t vid = lduw_be_p(_GET_VLAN_HDR(buf)->h_tci);
+uint32_t vfta =
+ldl_le_p((uint32_t *)(s->mac_reg + VFTA) +
+ ((vid >> E1000_VFTA_ENTRY_SHIFT) & 
E1000_VFTA_ENTRY_MASK));
+if ((vfta & (1 << (vid & E1000_VFTA_ENTRY_BIT_SHIFT_MASK))) == 0) {
 return 0;
 }
 }
@@ -909,7 +914,7 @@ e1000_receive_iov(NetClientState *nc, const struct iovec 
*iov, int iovcnt)
 uint32_t rdh_start;
 uint16_t vlan_special = 0;
 uint8_t vlan_status = 0;
-uint8_t min_buf[MIN_BUF_SIZE];
+uint8_t min_buf[ETH_ZLEN];
 struct iovec min_iov;
 uint8_t *filter_buf = iov->iov_base;
 size_t size = iov_size(iov, iovcnt);
@@ -1204,8 +1209,8 @@ static const readops macreg_readops[] = {
 [FFLT ... FFLT + 6]   = _readreg,
 [RA ... RA + 31]  = _readreg,
 [WUPM ... WUPM + 31]  = _readreg,
-[MTA ... MTA + 127]   = _readreg,
-[VFTA ... VFTA + 127] = _readreg,
+[MTA ... MTA + E1000_MC_TBL_SIZE - 1]   = _readreg,
+[VFTA ... VFTA + E1000_VLAN_FILTER_TBL_SIZE - 1] = _readreg,
 [FFMT ... FFMT + 254] = _readreg,
 [FFVT ... FFVT + 254] = _readreg,
 [PBM ... PBM + 16383] = _readreg,
@@ -1236,8 +1241,8 @@ static const writeops macreg_writeops[] = {
 [FFLT ... FFLT + 6]   = _11bit,
 [RA ... RA + 31]  = _writereg,
 [WUPM ... WUPM + 31]  = _writereg,
-[MTA ... MTA + 127]   = _writereg,
-[VFTA ... VFTA + 127] = _writereg,

[PULL 02/51] hw/net: Add more MII definitions

2023-03-06 Thread Jason Wang
From: Akihiko Odaki 

The definitions will be used by igb.

Signed-off-by: Akihiko Odaki 
Signed-off-by: Jason Wang 
---
 include/hw/net/mii.h | 13 -
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/include/hw/net/mii.h b/include/hw/net/mii.h
index 4ae4dcc..c6a767a 100644
--- a/include/hw/net/mii.h
+++ b/include/hw/net/mii.h
@@ -81,20 +81,31 @@
 #define MII_ANLPAR_ACK  (1 << 14)
 #define MII_ANLPAR_PAUSEASY (1 << 11) /* can pause asymmetrically */
 #define MII_ANLPAR_PAUSE(1 << 10) /* can pause */
+#define MII_ANLPAR_T4   (1 << 9)
 #define MII_ANLPAR_TXFD (1 << 8)
 #define MII_ANLPAR_TX   (1 << 7)
 #define MII_ANLPAR_10FD (1 << 6)
 #define MII_ANLPAR_10   (1 << 5)
 #define MII_ANLPAR_CSMACD   (1 << 0)
 
-#define MII_ANER_NWAY   (1 << 0) /* Can do N-way auto-nego */
+#define MII_ANER_NP (1 << 2)  /* Next Page Able */
+#define MII_ANER_NWAY   (1 << 0)  /* Can do N-way auto-nego */
 
+#define MII_ANNP_MP (1 << 13) /* Message Page */
+
+#define MII_CTRL1000_MASTER (1 << 11) /* MASTER-SLAVE Manual Configuration 
Value */
+#define MII_CTRL1000_PORT   (1 << 10) /* T2_Repeater/DTE bit */
 #define MII_CTRL1000_FULL   (1 << 9)  /* 1000BASE-T full duplex */
 #define MII_CTRL1000_HALF   (1 << 8)  /* 1000BASE-T half duplex */
 
+#define MII_STAT1000_LOK(1 << 13) /* Local Receiver Status */
+#define MII_STAT1000_ROK(1 << 12) /* Remote Receiver Status */
 #define MII_STAT1000_FULL   (1 << 11) /* 1000BASE-T full duplex */
 #define MII_STAT1000_HALF   (1 << 10) /* 1000BASE-T half duplex */
 
+#define MII_EXTSTAT_1000T_FD (1 << 13) /* 1000BASE-T Full Duplex */
+#define MII_EXTSTAT_1000T_HD (1 << 12) /* 1000BASE-T Half Duplex */
+
 /* List of vendor identifiers */
 /* RealTek 8201 */
 #define RTL8201CP_PHYID10x
-- 
2.7.4




[PULL 09/51] e1000e: Use more constant definitions

2023-03-06 Thread Jason Wang
From: Akihiko Odaki 

The definitions of SW Semaphore Register were copied from:
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/drivers/net/ethernet/intel/e1000e/defines.h?h=v6.0.9#n374

Signed-off-by: Akihiko Odaki 
Signed-off-by: Jason Wang 
---
 hw/net/e1000_regs.h  |  7 +++
 hw/net/e1000e_core.c | 49 +++--
 2 files changed, 34 insertions(+), 22 deletions(-)

diff --git a/hw/net/e1000_regs.h b/hw/net/e1000_regs.h
index 3f6b5d0..6a36573 100644
--- a/hw/net/e1000_regs.h
+++ b/hw/net/e1000_regs.h
@@ -525,6 +525,13 @@
 #define M88E1000_PHY_VCO_REG_BIT8  0x100 /* Bits 8 & 11 are adjusted for */
 #define M88E1000_PHY_VCO_REG_BIT11 0x800/* improved BER performance */
 
+/* SW Semaphore Register */
+#define E1000_SWSM_SMBI 0x0001 /* Driver Semaphore bit */
+#define E1000_SWSM_SWESMBI  0x0002 /* FW Semaphore bit */
+#define E1000_SWSM_DRV_LOAD 0x0008 /* Driver Loaded Bit */
+
+#define E1000_SWSM2_LOCK0x0002 /* Secondary driver semaphore bit */
+
 /* Interrupt Cause Read */
 #define E1000_ICR_TXDW  0x0001 /* Transmit desc written back */
 #define E1000_ICR_TXQE  0x0002 /* Transmit Queue empty */
diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c
index e6fc85e..6a4da72 100644
--- a/hw/net/e1000e_core.c
+++ b/hw/net/e1000e_core.c
@@ -1022,10 +1022,11 @@ e1000e_receive_filter(E1000ECore *core, const uint8_t 
*buf, int size)
 
 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) +
- ((vid >> 5) & 0x7f));
-if ((vfta & (1 << (vid & 0x1f))) == 0) {
+uint16_t vid = lduw_be_p(_GET_VLAN_HDR(buf)->h_tci);
+uint32_t vfta =
+ldl_le_p((uint32_t *)(core->mac + VFTA) +
+ ((vid >> E1000_VFTA_ENTRY_SHIFT) & 
E1000_VFTA_ENTRY_MASK));
+if ((vfta & (1 << (vid & E1000_VFTA_ENTRY_BIT_SHIFT_MASK))) == 0) {
 trace_e1000e_rx_flt_vlan_mismatch(vid);
 return false;
 } else {
@@ -1679,16 +1680,13 @@ e1000e_rx_fix_l4_csum(E1000ECore *core, struct NetRxPkt 
*pkt)
 }
 }
 
-/* Min. octets in an ethernet frame sans FCS */
-#define MIN_BUF_SIZE 60
-
 ssize_t
 e1000e_receive_iov(E1000ECore *core, const struct iovec *iov, int iovcnt)
 {
-static const int maximum_ethernet_hdr_len = (14 + 4);
+static const int maximum_ethernet_hdr_len = (ETH_HLEN + 4);
 
 uint32_t n = 0;
-uint8_t min_buf[MIN_BUF_SIZE];
+uint8_t min_buf[ETH_ZLEN];
 struct iovec min_iov;
 uint8_t *filter_buf;
 size_t size, orig_size;
@@ -2627,7 +2625,7 @@ static uint32_t
 e1000e_mac_swsm_read(E1000ECore *core, int index)
 {
 uint32_t val = core->mac[SWSM];
-core->mac[SWSM] = val | 1;
+core->mac[SWSM] = val | E1000_SWSM_SMBI;
 return val;
 }
 
@@ -3092,8 +3090,8 @@ static const readops e1000e_macreg_readops[] = {
 [IP4AT ... IP4AT + 6]  = e1000e_mac_readreg,
 [RA ... RA + 31]   = e1000e_mac_readreg,
 [WUPM ... WUPM + 31]   = e1000e_mac_readreg,
-[MTA ... MTA + 127]= e1000e_mac_readreg,
-[VFTA ... VFTA + 127]  = e1000e_mac_readreg,
+[MTA ... MTA + E1000_MC_TBL_SIZE - 1] = e1000e_mac_readreg,
+[VFTA ... VFTA + E1000_VLAN_FILTER_TBL_SIZE - 1]  = e1000e_mac_readreg,
 [FFMT ... FFMT + 254]  = e1000e_mac_readreg,
 [FFVT ... FFVT + 254]  = e1000e_mac_readreg,
 [MDEF ... MDEF + 7]= e1000e_mac_readreg,
@@ -3245,8 +3243,8 @@ static const writeops e1000e_macreg_writeops[] = {
 [IP4AT ... IP4AT + 6]= e1000e_mac_writereg,
 [RA + 2 ... RA + 31] = e1000e_mac_writereg,
 [WUPM ... WUPM + 31] = e1000e_mac_writereg,
-[MTA ... MTA + 127]  = e1000e_mac_writereg,
-[VFTA ... VFTA + 127]= e1000e_mac_writereg,
+[MTA ... MTA + E1000_MC_TBL_SIZE - 1] = e1000e_mac_writereg,
+[VFTA ... VFTA + E1000_VLAN_FILTER_TBL_SIZE - 1]= e1000e_mac_writereg,
 [FFMT ... FFMT + 254]= e1000e_set_4bit,
 [FFVT ... FFVT + 254]= e1000e_mac_writereg,
 [PBM ... PBM + 10239]= e1000e_mac_writereg,
@@ -3276,7 +3274,7 @@ static const uint16_t mac_reg_access[E1000E_MAC_SIZE] = {
 [TDH_A]   = 0x0cf8, [TDT_A]   = 0x0cf8, [TIDV_A] = 0x0cf8,
 [TDFH_A]  = 0xed00, [TDFT_A]  = 0xed00,
 [RA_A ... RA_A + 31]  = 0x14f0,
-[VFTA_A ... VFTA_A + 127] = 0x1400,
+[VFTA_A ... VFTA_A + E1000_VLAN_FILTER_TBL_SIZE - 1] = 0x1400,
 [RDBAL0_A ... RDLEN0_A] = 0x09bc,
 [TDBAL_A ... TDLEN_A]   = 0x0cf8,
 /* Access options */
@@ -3433,13 +3431,20 @@ 
e1000e_phy_reg_init[E1000E_PHY_PAGES][E1000E_PHY_PAGE_SIZE] = {
 
 [MII_PHYID1]= 0x141,
 [MII_PHYID2]= E1000_PHY_ID2_82574x,
-[MII_ANAR]  = 0xde1,
-[MII_ANLPAR]= 0x7e0,
-[MII_ANER]  

[PULL 37/51] e1000: Split header files

2023-03-06 Thread Jason Wang
From: Akihiko Odaki 

Some definitions in the header files are invalid for igb so extract
them to new header files to keep igb from referring to them.

Signed-off-by: Gal Hammer 
Signed-off-by: Marcel Apfelbaum 
Signed-off-by: Akihiko Odaki 
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Jason Wang 
---
 hw/net/e1000.c |   1 +
 hw/net/e1000_common.h  | 102 ++
 hw/net/e1000_regs.h| 954 +---
 hw/net/e1000e.c|   3 +-
 hw/net/e1000e_core.c   |   1 +
 hw/net/e1000x_common.c |   1 +
 hw/net/e1000x_common.h |  74 
 hw/net/e1000x_regs.h   | 967 +
 8 files changed, 1076 insertions(+), 1027 deletions(-)
 create mode 100644 hw/net/e1000_common.h
 create mode 100644 hw/net/e1000x_regs.h

diff --git a/hw/net/e1000.c b/hw/net/e1000.c
index c830798..23d6606 100644
--- a/hw/net/e1000.c
+++ b/hw/net/e1000.c
@@ -39,6 +39,7 @@
 #include "qemu/module.h"
 #include "qemu/range.h"
 
+#include "e1000_common.h"
 #include "e1000x_common.h"
 #include "trace.h"
 #include "qom/object.h"
diff --git a/hw/net/e1000_common.h b/hw/net/e1000_common.h
new file mode 100644
index 000..48feda7
--- /dev/null
+++ b/hw/net/e1000_common.h
@@ -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 .
+ */
+
+#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),

[PULL 18/51] e1000e: Remove extra pointer indirection

2023-03-06 Thread Jason Wang
From: Akihiko Odaki 

e1000e_write_packet_to_guest() passes the reference of variable ba as a
pointer to an array, and that pointer indirection is just unnecessary;
all functions which uses the passed reference performs no pointer
operation on the pointer and they simply dereference the passed
pointer. Remove the extra pointer indirection.

Signed-off-by: Akihiko Odaki 
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Jason Wang 
---
 hw/net/e1000e_core.c | 38 +++---
 1 file changed, 19 insertions(+), 19 deletions(-)

diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c
index 7367084..d143f2a 100644
--- a/hw/net/e1000e_core.c
+++ b/hw/net/e1000e_core.c
@@ -1075,31 +1075,31 @@ e1000e_read_ext_rx_descr(E1000ECore *core, union 
e1000_rx_desc_extended *desc,
 static inline void
 e1000e_read_ps_rx_descr(E1000ECore *core,
 union e1000_rx_desc_packet_split *desc,
-hwaddr (*buff_addr)[MAX_PS_BUFFERS])
+hwaddr buff_addr[MAX_PS_BUFFERS])
 {
 int i;
 
 for (i = 0; i < MAX_PS_BUFFERS; i++) {
-(*buff_addr)[i] = le64_to_cpu(desc->read.buffer_addr[i]);
+buff_addr[i] = le64_to_cpu(desc->read.buffer_addr[i]);
 }
 
-trace_e1000e_rx_desc_ps_read((*buff_addr)[0], (*buff_addr)[1],
- (*buff_addr)[2], (*buff_addr)[3]);
+trace_e1000e_rx_desc_ps_read(buff_addr[0], buff_addr[1],
+ buff_addr[2], buff_addr[3]);
 }
 
 static inline void
 e1000e_read_rx_descr(E1000ECore *core, union e1000_rx_desc_union *desc,
- hwaddr (*buff_addr)[MAX_PS_BUFFERS])
+ hwaddr buff_addr[MAX_PS_BUFFERS])
 {
 if (e1000e_rx_use_legacy_descriptor(core)) {
-e1000e_read_lgcy_rx_descr(core, >legacy, &(*buff_addr)[0]);
-(*buff_addr)[1] = (*buff_addr)[2] = (*buff_addr)[3] = 0;
+e1000e_read_lgcy_rx_descr(core, >legacy, _addr[0]);
+buff_addr[1] = buff_addr[2] = buff_addr[3] = 0;
 } else {
 if (core->mac[RCTL] & E1000_RCTL_DTYP_PS) {
 e1000e_read_ps_rx_descr(core, >packet_split, buff_addr);
 } else {
-e1000e_read_ext_rx_descr(core, >extended, &(*buff_addr)[0]);
-(*buff_addr)[1] = (*buff_addr)[2] = (*buff_addr)[3] = 0;
+e1000e_read_ext_rx_descr(core, >extended, _addr[0]);
+buff_addr[1] = buff_addr[2] = buff_addr[3] = 0;
 }
 }
 }
@@ -1420,14 +1420,14 @@ typedef struct e1000e_ba_state_st {
 
 static inline void
 e1000e_write_hdr_to_rx_buffers(E1000ECore *core,
-   hwaddr (*ba)[MAX_PS_BUFFERS],
+   hwaddr ba[MAX_PS_BUFFERS],
e1000e_ba_state *bastate,
const char *data,
dma_addr_t data_len)
 {
 assert(data_len <= core->rxbuf_sizes[0] - bastate->written[0]);
 
-pci_dma_write(core->owner, (*ba)[0] + bastate->written[0], data, data_len);
+pci_dma_write(core->owner, ba[0] + bastate->written[0], data, data_len);
 bastate->written[0] += data_len;
 
 bastate->cur_idx = 1;
@@ -1435,7 +1435,7 @@ e1000e_write_hdr_to_rx_buffers(E1000ECore *core,
 
 static void
 e1000e_write_to_rx_buffers(E1000ECore *core,
-   hwaddr (*ba)[MAX_PS_BUFFERS],
+   hwaddr ba[MAX_PS_BUFFERS],
e1000e_ba_state *bastate,
const char *data,
dma_addr_t data_len)
@@ -1447,13 +1447,13 @@ e1000e_write_to_rx_buffers(E1000ECore *core,
 uint32_t bytes_to_write = MIN(data_len, cur_buf_bytes_left);
 
 trace_e1000e_rx_desc_buff_write(bastate->cur_idx,
-(*ba)[bastate->cur_idx],
+ba[bastate->cur_idx],
 bastate->written[bastate->cur_idx],
 data,
 bytes_to_write);
 
 pci_dma_write(core->owner,
-(*ba)[bastate->cur_idx] + bastate->written[bastate->cur_idx],
+ba[bastate->cur_idx] + bastate->written[bastate->cur_idx],
 data, bytes_to_write);
 
 bastate->written[bastate->cur_idx] += bytes_to_write;
@@ -1577,7 +1577,7 @@ e1000e_write_packet_to_guest(E1000ECore *core, struct 
NetRxPkt *pkt,
 
 trace_e1000e_rx_descr(rxi->idx, base, core->rx_desc_len);
 
-e1000e_read_rx_descr(core, , );
+e1000e_read_rx_descr(core, , ba);
 
 if (ba[0]) {
 if (desc_offset < size) {
@@ -1596,7 +1596,7 @@ e1000e_write_packet_to_guest(E1000ECore *core, struct 
NetRxPkt *pkt,
 iov_copy = MIN(ps_hdr_len - ps_hdr_copied,
iov->iov_len - iov_ofs);
 
-e1000e_write_hdr_to_rx_buffers(core, 

[PULL 15/51] e1000e: Configure ResettableClass

2023-03-06 Thread Jason Wang
From: Akihiko Odaki 

This is part of recent efforts of refactoring e1000 and e1000e.

DeviceClass's reset member is deprecated so migrate to ResettableClass.
There is no behavioral difference.

Signed-off-by: Akihiko Odaki 
Reviewed-by: Peter Maydell 
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Jason Wang 
---
 hw/net/e1000e.c | 10 ++
 hw/net/trace-events |  2 +-
 2 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/hw/net/e1000e.c b/hw/net/e1000e.c
index 0bc222d..ec27431 100644
--- a/hw/net/e1000e.c
+++ b/hw/net/e1000e.c
@@ -513,11 +513,11 @@ static void e1000e_pci_uninit(PCIDevice *pci_dev)
 msi_uninit(pci_dev);
 }
 
-static void e1000e_qdev_reset(DeviceState *dev)
+static void e1000e_qdev_reset_hold(Object *obj)
 {
-E1000EState *s = E1000E(dev);
+E1000EState *s = E1000E(obj);
 
-trace_e1000e_cb_qdev_reset();
+trace_e1000e_cb_qdev_reset_hold();
 
 e1000e_core_reset(>core);
 
@@ -669,6 +669,7 @@ static Property e1000e_properties[] = {
 static void e1000e_class_init(ObjectClass *class, void *data)
 {
 DeviceClass *dc = DEVICE_CLASS(class);
+ResettableClass *rc = RESETTABLE_CLASS(class);
 PCIDeviceClass *c = PCI_DEVICE_CLASS(class);
 
 c->realize = e1000e_pci_realize;
@@ -679,8 +680,9 @@ static void e1000e_class_init(ObjectClass *class, void 
*data)
 c->romfile = "efi-e1000e.rom";
 c->class_id = PCI_CLASS_NETWORK_ETHERNET;
 
+rc->phases.hold = e1000e_qdev_reset_hold;
+
 dc->desc = "Intel 82574L GbE Controller";
-dc->reset = e1000e_qdev_reset;
 dc->vmsd = _vmstate;
 
 e1000e_prop_disable_vnet = qdev_prop_uint8;
diff --git a/hw/net/trace-events b/hw/net/trace-events
index 8fa4299..c98ad12 100644
--- a/hw/net/trace-events
+++ b/hw/net/trace-events
@@ -251,7 +251,7 @@ e1000e_vm_state_stopped(void) "VM state is stopped"
 # e1000e.c
 e1000e_cb_pci_realize(void) "E1000E PCI realize entry"
 e1000e_cb_pci_uninit(void) "E1000E PCI unit entry"
-e1000e_cb_qdev_reset(void) "E1000E qdev reset entry"
+e1000e_cb_qdev_reset_hold(void) "E1000E qdev reset hold"
 e1000e_cb_pre_save(void) "E1000E pre save entry"
 e1000e_cb_post_load(void) "E1000E post load entry"
 
-- 
2.7.4




[PULL 28/51] MAINTAINERS: Add Akihiko Odaki as a e1000e reviewer

2023-03-06 Thread Jason Wang
From: Akihiko Odaki 

I want to know to be notified when there is a new change for e1000e
as e1000e is similar to igb and such a change may also be applicable for
igb.

Signed-off-by: Akihiko Odaki 
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Jason Wang 
---
 MAINTAINERS | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index da29661..d263e52 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2219,11 +2219,13 @@ F: docs/specs/rocker.txt
 
 e1000x
 M: Dmitry Fleytman 
+R: Akihiko Odaki 
 S: Maintained
 F: hw/net/e1000x*
 
 e1000e
 M: Dmitry Fleytman 
+R: Akihiko Odaki 
 S: Maintained
 F: hw/net/e1000e*
 F: tests/qtest/fuzz-e1000e-test.c
-- 
2.7.4




[PULL 03/51] fsl_etsec: Use hw/net/mii.h

2023-03-06 Thread Jason Wang
From: Akihiko Odaki 

hw/net/mii.h provides common definitions for MII.

Signed-off-by: Akihiko Odaki 
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Jason Wang 
---
 hw/net/fsl_etsec/etsec.c | 11 ++-
 hw/net/fsl_etsec/etsec.h | 17 -
 hw/net/fsl_etsec/miim.c  |  5 +++--
 include/hw/net/mii.h |  1 +
 4 files changed, 10 insertions(+), 24 deletions(-)

diff --git a/hw/net/fsl_etsec/etsec.c b/hw/net/fsl_etsec/etsec.c
index c753bfb..798ea33 100644
--- a/hw/net/fsl_etsec/etsec.c
+++ b/hw/net/fsl_etsec/etsec.c
@@ -29,6 +29,7 @@
 #include "qemu/osdep.h"
 #include "hw/sysbus.h"
 #include "hw/irq.h"
+#include "hw/net/mii.h"
 #include "hw/ptimer.h"
 #include "hw/qdev-properties.h"
 #include "etsec.h"
@@ -339,11 +340,11 @@ static void etsec_reset(DeviceState *d)
 etsec->rx_buffer_len = 0;
 
 etsec->phy_status =
-MII_SR_EXTENDED_CAPS| MII_SR_LINK_STATUS   | MII_SR_AUTONEG_CAPS  |
-MII_SR_AUTONEG_COMPLETE | MII_SR_PREAMBLE_SUPPRESS |
-MII_SR_EXTENDED_STATUS  | MII_SR_100T2_HD_CAPS | MII_SR_100T2_FD_CAPS |
-MII_SR_10T_HD_CAPS  | MII_SR_10T_FD_CAPS   | MII_SR_100X_HD_CAPS  |
-MII_SR_100X_FD_CAPS | MII_SR_100T4_CAPS;
+MII_BMSR_EXTCAP   | MII_BMSR_LINK_ST  | MII_BMSR_AUTONEG  |
+MII_BMSR_AN_COMP  | MII_BMSR_MFPS | MII_BMSR_EXTSTAT  |
+MII_BMSR_100T2_HD | MII_BMSR_100T2_FD |
+MII_BMSR_10T_HD   | MII_BMSR_10T_FD   |
+MII_BMSR_100TX_HD | MII_BMSR_100TX_FD | MII_BMSR_100T4;
 
 etsec_update_irq(etsec);
 }
diff --git a/hw/net/fsl_etsec/etsec.h b/hw/net/fsl_etsec/etsec.h
index 3c625c9..3860864 100644
--- a/hw/net/fsl_etsec/etsec.h
+++ b/hw/net/fsl_etsec/etsec.h
@@ -76,23 +76,6 @@ typedef struct eTSEC_rxtx_bd {
 #define FCB_TX_CTU (1 << 1)
 #define FCB_TX_NPH (1 << 0)
 
-/* PHY Status Register */
-#define MII_SR_EXTENDED_CAPS 0x0001/* Extended register capabilities */
-#define MII_SR_JABBER_DETECT 0x0002/* Jabber Detected */
-#define MII_SR_LINK_STATUS   0x0004/* Link Status 1 = link */
-#define MII_SR_AUTONEG_CAPS  0x0008/* Auto Neg Capable */
-#define MII_SR_REMOTE_FAULT  0x0010/* Remote Fault Detect */
-#define MII_SR_AUTONEG_COMPLETE  0x0020/* Auto Neg Complete */
-#define MII_SR_PREAMBLE_SUPPRESS 0x0040/* Preamble may be suppressed */
-#define MII_SR_EXTENDED_STATUS   0x0100/* Ext. status info in Reg 0x0F */
-#define MII_SR_100T2_HD_CAPS 0x0200/* 100T2 Half Duplex Capable */
-#define MII_SR_100T2_FD_CAPS 0x0400/* 100T2 Full Duplex Capable */
-#define MII_SR_10T_HD_CAPS   0x0800/* 10T   Half Duplex Capable */
-#define MII_SR_10T_FD_CAPS   0x1000/* 10T   Full Duplex Capable */
-#define MII_SR_100X_HD_CAPS  0x2000/* 100X  Half Duplex Capable */
-#define MII_SR_100X_FD_CAPS  0x4000/* 100X  Full Duplex Capable */
-#define MII_SR_100T4_CAPS0x8000/* 100T4 Capable */
-
 /* eTSEC */
 
 /* Number of register in the device */
diff --git a/hw/net/fsl_etsec/miim.c b/hw/net/fsl_etsec/miim.c
index 6bba01c..b48d2cb 100644
--- a/hw/net/fsl_etsec/miim.c
+++ b/hw/net/fsl_etsec/miim.c
@@ -23,6 +23,7 @@
  */
 
 #include "qemu/osdep.h"
+#include "hw/net/mii.h"
 #include "etsec.h"
 #include "registers.h"
 
@@ -140,8 +141,8 @@ void etsec_miim_link_status(eTSEC *etsec, NetClientState 
*nc)
 {
 /* Set link status */
 if (nc->link_down) {
-etsec->phy_status &= ~MII_SR_LINK_STATUS;
+etsec->phy_status &= ~MII_BMSR_LINK_ST;
 } else {
-etsec->phy_status |= MII_SR_LINK_STATUS;
+etsec->phy_status |= MII_BMSR_LINK_ST;
 }
 }
diff --git a/include/hw/net/mii.h b/include/hw/net/mii.h
index c6a767a..ed1bb52 100644
--- a/include/hw/net/mii.h
+++ b/include/hw/net/mii.h
@@ -55,6 +55,7 @@
 #define MII_BMCR_CTST   (1 << 7)  /* Collision test */
 #define MII_BMCR_SPEED1000  (1 << 6)  /* MSB of Speed (1000) */
 
+#define MII_BMSR_100T4  (1 << 15) /* Can do 100mbps T4 */
 #define MII_BMSR_100TX_FD   (1 << 14) /* Can do 100mbps, full-duplex */
 #define MII_BMSR_100TX_HD   (1 << 13) /* Can do 100mbps, half-duplex */
 #define MII_BMSR_10T_FD (1 << 12) /* Can do 10mbps, full-duplex */
-- 
2.7.4




[PULL 25/51] hw/net/net_tx_pkt: Implement TCP segmentation

2023-03-06 Thread Jason Wang
From: Akihiko Odaki 

There was no proper implementation of TCP segmentation before this
change, and net_tx_pkt relied solely on IPv4 fragmentation. Not only
this is not aligned with the specification, but it also resulted in
corrupted IPv6 packets.

This is particularly problematic for the igb, a new proposed device
implementation; igb provides loopback feature for VMDq and the feature
relies on software segmentation.

Implement proper TCP segmentation in net_tx_pkt to fix such a scenario.

Signed-off-by: Akihiko Odaki 
Signed-off-by: Jason Wang 
---
 hw/net/net_tx_pkt.c | 248 +++-
 include/net/eth.h   |   5 --
 net/eth.c   |  27 --
 3 files changed, 206 insertions(+), 74 deletions(-)

diff --git a/hw/net/net_tx_pkt.c b/hw/net/net_tx_pkt.c
index 6afd3f6..4a35e84 100644
--- a/hw/net/net_tx_pkt.c
+++ b/hw/net/net_tx_pkt.c
@@ -326,7 +326,8 @@ bool net_tx_pkt_build_vheader(struct NetTxPkt *pkt, bool 
tso_enable,
 case VIRTIO_NET_HDR_GSO_TCPV6:
 bytes_read = iov_to_buf(>vec[NET_TX_PKT_PL_START_FRAG],
 pkt->payload_frags, 0, , sizeof(l4hdr));
-if (bytes_read < sizeof(l4hdr)) {
+if (bytes_read < sizeof(l4hdr) ||
+l4hdr.th_off * sizeof(uint32_t) < sizeof(l4hdr)) {
 return false;
 }
 
@@ -466,15 +467,14 @@ void net_tx_pkt_reset(struct NetTxPkt *pkt)
 pkt->l4proto = 0;
 }
 
-static void net_tx_pkt_do_sw_csum(struct NetTxPkt *pkt)
+static void net_tx_pkt_do_sw_csum(struct NetTxPkt *pkt,
+  struct iovec *iov, uint32_t iov_len,
+  uint16_t csl)
 {
-struct iovec *iov = >vec[NET_TX_PKT_L2HDR_FRAG];
 uint32_t csum_cntr;
 uint16_t csum = 0;
 uint32_t cso;
 /* num of iovec without vhdr */
-uint32_t iov_len = pkt->payload_frags + NET_TX_PKT_PL_START_FRAG - 1;
-uint16_t csl;
 size_t csum_offset = pkt->virt_hdr.csum_start + pkt->virt_hdr.csum_offset;
 uint16_t l3_proto = eth_get_l3_proto(iov, 1, iov->iov_len);
 
@@ -482,8 +482,6 @@ static void net_tx_pkt_do_sw_csum(struct NetTxPkt *pkt)
 iov_from_buf(iov, iov_len, csum_offset, , sizeof csum);
 
 /* Calculate L4 TCP/UDP checksum */
-csl = pkt->payload_len;
-
 csum_cntr = 0;
 cso = 0;
 /* add pseudo header to csum */
@@ -509,14 +507,13 @@ static void net_tx_pkt_do_sw_csum(struct NetTxPkt *pkt)
 #define NET_MAX_FRAG_SG_LIST (64)
 
 static size_t net_tx_pkt_fetch_fragment(struct NetTxPkt *pkt,
-int *src_idx, size_t *src_offset, struct iovec *dst, int *dst_idx)
+int *src_idx, size_t *src_offset, size_t src_len,
+struct iovec *dst, int *dst_idx)
 {
 size_t fetched = 0;
 struct iovec *src = pkt->vec;
 
-*dst_idx = NET_TX_PKT_PL_START_FRAG;
-
-while (fetched < IP_FRAG_ALIGN_SIZE(pkt->virt_hdr.gso_size)) {
+while (fetched < src_len) {
 
 /* no more place in fragment iov */
 if (*dst_idx == NET_MAX_FRAG_SG_LIST) {
@@ -531,7 +528,7 @@ static size_t net_tx_pkt_fetch_fragment(struct NetTxPkt 
*pkt,
 
 dst[*dst_idx].iov_base = src[*src_idx].iov_base + *src_offset;
 dst[*dst_idx].iov_len = MIN(src[*src_idx].iov_len - *src_offset,
-IP_FRAG_ALIGN_SIZE(pkt->virt_hdr.gso_size) - fetched);
+src_len - fetched);
 
 *src_offset += dst[*dst_idx].iov_len;
 fetched += dst[*dst_idx].iov_len;
@@ -560,58 +557,223 @@ static void net_tx_pkt_sendv(
 }
 }
 
+static bool net_tx_pkt_tcp_fragment_init(struct NetTxPkt *pkt,
+ struct iovec *fragment,
+ int *pl_idx,
+ size_t *l4hdr_len,
+ int *src_idx,
+ size_t *src_offset,
+ size_t *src_len)
+{
+struct iovec *l4 = fragment + NET_TX_PKT_PL_START_FRAG;
+size_t bytes_read = 0;
+struct tcp_hdr *th;
+
+if (!pkt->payload_frags) {
+return false;
+}
+
+l4->iov_len = pkt->virt_hdr.hdr_len - pkt->hdr_len;
+l4->iov_base = g_malloc(l4->iov_len);
+
+*src_idx = NET_TX_PKT_PL_START_FRAG;
+while (pkt->vec[*src_idx].iov_len < l4->iov_len - bytes_read) {
+memcpy((char *)l4->iov_base + bytes_read, pkt->vec[*src_idx].iov_base,
+   pkt->vec[*src_idx].iov_len);
+
+bytes_read += pkt->vec[*src_idx].iov_len;
+
+(*src_idx)++;
+if (*src_idx >= pkt->payload_frags + NET_TX_PKT_PL_START_FRAG) {
+g_free(l4->iov_base);
+return false;
+}
+}
+
+*src_offset = l4->iov_len - bytes_read;
+memcpy((char *)l4->iov_base + bytes_read, pkt->vec[*src_idx].iov_base,
+   *src_offset);
+
+th = l4->iov_base;
+th->th_flags &= ~(TH_FIN | TH_PUSH);
+
+*pl_idx = NET_TX_PKT_PL_START_FRAG + 1;
+*l4hdr_len = l4->iov_len;
+*src_len = 

[PULL 11/51] e1000e: Use memcpy to intialize registers

2023-03-06 Thread Jason Wang
From: Akihiko Odaki 

Use memcpy instead of memmove to initialize registers. The initial
register templates and register table instances will never overlap.

Signed-off-by: Akihiko Odaki 
Signed-off-by: Jason Wang 
---
 hw/net/e1000e_core.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c
index 6a4da72..87f964c 100644
--- a/hw/net/e1000e_core.c
+++ b/hw/net/e1000e_core.c
@@ -3511,9 +3511,9 @@ e1000e_core_reset(E1000ECore *core)
 e1000e_intrmgr_reset(core);
 
 memset(core->phy, 0, sizeof core->phy);
-memmove(core->phy, e1000e_phy_reg_init, sizeof e1000e_phy_reg_init);
+memcpy(core->phy, e1000e_phy_reg_init, sizeof e1000e_phy_reg_init);
 memset(core->mac, 0, sizeof core->mac);
-memmove(core->mac, e1000e_mac_reg_init, sizeof e1000e_mac_reg_init);
+memcpy(core->mac, e1000e_mac_reg_init, sizeof e1000e_mac_reg_init);
 
 core->rxbuf_min_shift = 1 + E1000_RING_DESC_LEN_SHIFT;
 
-- 
2.7.4




[PULL 21/51] net: Strip virtio-net header when dumping

2023-03-06 Thread Jason Wang
From: Akihiko Odaki 

filter-dump specifiees Ethernet as PCAP LinkType, which does not expect
virtio-net header. Having virtio-net header in such PCAP file breaks
PCAP unconsumable. Unfortunately currently there is no LinkType for
virtio-net so for now strip virtio-net header to convert the output to
Ethernet.

Signed-off-by: Akihiko Odaki 
Signed-off-by: Jason Wang 
---
 include/net/net.h |  6 ++
 net/dump.c| 11 +++
 net/net.c | 18 ++
 net/tap.c | 16 
 4 files changed, 47 insertions(+), 4 deletions(-)

diff --git a/include/net/net.h b/include/net/net.h
index 1d88621..1448d00 100644
--- a/include/net/net.h
+++ b/include/net/net.h
@@ -56,8 +56,10 @@ typedef RxFilterInfo *(QueryRxFilter)(NetClientState *);
 typedef bool (HasUfo)(NetClientState *);
 typedef bool (HasVnetHdr)(NetClientState *);
 typedef bool (HasVnetHdrLen)(NetClientState *, int);
+typedef bool (GetUsingVnetHdr)(NetClientState *);
 typedef void (UsingVnetHdr)(NetClientState *, bool);
 typedef void (SetOffload)(NetClientState *, int, int, int, int, int);
+typedef int (GetVnetHdrLen)(NetClientState *);
 typedef void (SetVnetHdrLen)(NetClientState *, int);
 typedef int (SetVnetLE)(NetClientState *, bool);
 typedef int (SetVnetBE)(NetClientState *, bool);
@@ -84,8 +86,10 @@ typedef struct NetClientInfo {
 HasUfo *has_ufo;
 HasVnetHdr *has_vnet_hdr;
 HasVnetHdrLen *has_vnet_hdr_len;
+GetUsingVnetHdr *get_using_vnet_hdr;
 UsingVnetHdr *using_vnet_hdr;
 SetOffload *set_offload;
+GetVnetHdrLen *get_vnet_hdr_len;
 SetVnetHdrLen *set_vnet_hdr_len;
 SetVnetLE *set_vnet_le;
 SetVnetBE *set_vnet_be;
@@ -185,9 +189,11 @@ void qemu_format_nic_info_str(NetClientState *nc, uint8_t 
macaddr[6]);
 bool qemu_has_ufo(NetClientState *nc);
 bool qemu_has_vnet_hdr(NetClientState *nc);
 bool qemu_has_vnet_hdr_len(NetClientState *nc, int len);
+bool qemu_get_using_vnet_hdr(NetClientState *nc);
 void qemu_using_vnet_hdr(NetClientState *nc, bool enable);
 void qemu_set_offload(NetClientState *nc, int csum, int tso4, int tso6,
   int ecn, int ufo);
+int qemu_get_vnet_hdr_len(NetClientState *nc);
 void qemu_set_vnet_hdr_len(NetClientState *nc, int len);
 int qemu_set_vnet_le(NetClientState *nc, bool is_le);
 int qemu_set_vnet_be(NetClientState *nc, bool is_be);
diff --git a/net/dump.c b/net/dump.c
index 6a63b15..7d05f16 100644
--- a/net/dump.c
+++ b/net/dump.c
@@ -61,12 +61,13 @@ struct pcap_sf_pkthdr {
 uint32_t len;
 };
 
-static ssize_t dump_receive_iov(DumpState *s, const struct iovec *iov, int cnt)
+static ssize_t dump_receive_iov(DumpState *s, const struct iovec *iov, int cnt,
+int offset)
 {
 struct pcap_sf_pkthdr hdr;
 int64_t ts;
 int caplen;
-size_t size = iov_size(iov, cnt);
+size_t size = iov_size(iov, cnt) - offset;
 struct iovec dumpiov[cnt + 1];
 
 /* Early return in case of previous error. */
@@ -84,7 +85,7 @@ static ssize_t dump_receive_iov(DumpState *s, const struct 
iovec *iov, int cnt)
 
 dumpiov[0].iov_base = 
 dumpiov[0].iov_len = sizeof(hdr);
-cnt = iov_copy([1], cnt, iov, cnt, 0, caplen);
+cnt = iov_copy([1], cnt, iov, cnt, offset, caplen);
 
 if (writev(s->fd, dumpiov, cnt + 1) != sizeof(hdr) + caplen) {
 error_report("network dump write error - stopping dump");
@@ -153,8 +154,10 @@ static ssize_t filter_dump_receive_iov(NetFilterState *nf, 
NetClientState *sndr,
int iovcnt, NetPacketSent *sent_cb)
 {
 NetFilterDumpState *nfds = FILTER_DUMP(nf);
+int offset = qemu_get_using_vnet_hdr(nf->netdev) ?
+ qemu_get_vnet_hdr_len(nf->netdev) : 0;
 
-dump_receive_iov(>ds, iov, iovcnt);
+dump_receive_iov(>ds, iov, iovcnt, offset);
 return 0;
 }
 
diff --git a/net/net.c b/net/net.c
index ebc7ce0..6492ad5 100644
--- a/net/net.c
+++ b/net/net.c
@@ -513,6 +513,15 @@ bool qemu_has_vnet_hdr_len(NetClientState *nc, int len)
 return nc->info->has_vnet_hdr_len(nc, len);
 }
 
+bool qemu_get_using_vnet_hdr(NetClientState *nc)
+{
+if (!nc || !nc->info->get_using_vnet_hdr) {
+return false;
+}
+
+return nc->info->get_using_vnet_hdr(nc);
+}
+
 void qemu_using_vnet_hdr(NetClientState *nc, bool enable)
 {
 if (!nc || !nc->info->using_vnet_hdr) {
@@ -532,6 +541,15 @@ void qemu_set_offload(NetClientState *nc, int csum, int 
tso4, int tso6,
 nc->info->set_offload(nc, csum, tso4, tso6, ecn, ufo);
 }
 
+int qemu_get_vnet_hdr_len(NetClientState *nc)
+{
+if (!nc || !nc->info->get_vnet_hdr_len) {
+return 0;
+}
+
+return nc->info->get_vnet_hdr_len(nc);
+}
+
 void qemu_set_vnet_hdr_len(NetClientState *nc, int len)
 {
 if (!nc || !nc->info->set_vnet_hdr_len) {
diff --git a/net/tap.c b/net/tap.c
index 7d7bc1d..1bf085d 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -255,6 +255,13 @@ static bool tap_has_vnet_hdr_len(NetClientState *nc, int 
len)

[PULL 13/51] e1000e: Improve software reset

2023-03-06 Thread Jason Wang
From: Akihiko Odaki 

This change makes e1000e reset more things when software reset was
triggered. Some registers are exempted from software reset in the
datasheet and this change also implements the behavior accordingly.

Signed-off-by: Akihiko Odaki 
Signed-off-by: Jason Wang 
---
 hw/net/e1000e_core.c | 24 +++-
 1 file changed, 19 insertions(+), 5 deletions(-)

diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c
index 37aec6a..b867066 100644
--- a/hw/net/e1000e_core.c
+++ b/hw/net/e1000e_core.c
@@ -58,6 +58,8 @@
 static inline void
 e1000e_set_interrupt_cause(E1000ECore *core, uint32_t val);
 
+static void e1000e_reset(E1000ECore *core, bool sw);
+
 static inline void
 e1000e_process_ts_option(E1000ECore *core, struct e1000_tx_desc *dp)
 {
@@ -1882,7 +1884,7 @@ e1000e_set_ctrl(E1000ECore *core, int index, uint32_t val)
 
 if (val & E1000_CTRL_RST) {
 trace_e1000e_core_ctrl_sw_reset();
-e1000x_reset_mac_addr(core->owner_nic, core->mac, core->permanent_mac);
+e1000e_reset(core, true);
 }
 
 if (val & E1000_CTRL_PHY_RST) {
@@ -3488,8 +3490,7 @@ static const uint32_t e1000e_mac_reg_init[] = {
 [EITR...EITR + E1000E_MSIX_VEC_NUM - 1] = E1000E_MIN_XITR,
 };
 
-void
-e1000e_core_reset(E1000ECore *core)
+static void e1000e_reset(E1000ECore *core, bool sw)
 {
 int i;
 
@@ -3499,8 +3500,15 @@ e1000e_core_reset(E1000ECore *core)
 
 memset(core->phy, 0, sizeof core->phy);
 memcpy(core->phy, e1000e_phy_reg_init, sizeof e1000e_phy_reg_init);
-memset(core->mac, 0, sizeof core->mac);
-memcpy(core->mac, e1000e_mac_reg_init, sizeof e1000e_mac_reg_init);
+
+for (i = 0; i < E1000E_MAC_SIZE; i++) {
+if (sw && (i == PBA || i == PBS || i == FLA)) {
+continue;
+}
+
+core->mac[i] = i < ARRAY_SIZE(e1000e_mac_reg_init) ?
+   e1000e_mac_reg_init[i] : 0;
+}
 
 core->rxbuf_min_shift = 1 + E1000_RING_DESC_LEN_SHIFT;
 
@@ -3517,6 +3525,12 @@ e1000e_core_reset(E1000ECore *core)
 }
 }
 
+void
+e1000e_core_reset(E1000ECore *core)
+{
+e1000e_reset(core, false);
+}
+
 void e1000e_core_pre_save(E1000ECore *core)
 {
 int i;
-- 
2.7.4




[PULL 05/51] e1000: Mask registers when writing

2023-03-06 Thread Jason Wang
From: Akihiko Odaki 

When a register has effective bits fewer than their width, the old code
inconsistently masked when writing or reading. Make the code consistent
by always masking when writing, and remove some code duplication.

Signed-off-by: Akihiko Odaki 
Signed-off-by: Jason Wang 
---
 hw/net/e1000.c | 84 ++
 1 file changed, 31 insertions(+), 53 deletions(-)

diff --git a/hw/net/e1000.c b/hw/net/e1000.c
index 9619a2e..0925a99 100644
--- a/hw/net/e1000.c
+++ b/hw/net/e1000.c
@@ -1063,30 +1063,6 @@ mac_readreg(E1000State *s, int index)
 }
 
 static uint32_t
-mac_low4_read(E1000State *s, int index)
-{
-return s->mac_reg[index] & 0xf;
-}
-
-static uint32_t
-mac_low11_read(E1000State *s, int index)
-{
-return s->mac_reg[index] & 0x7ff;
-}
-
-static uint32_t
-mac_low13_read(E1000State *s, int index)
-{
-return s->mac_reg[index] & 0x1fff;
-}
-
-static uint32_t
-mac_low16_read(E1000State *s, int index)
-{
-return s->mac_reg[index] & 0x;
-}
-
-static uint32_t
 mac_icr_read(E1000State *s, int index)
 {
 uint32_t ret = s->mac_reg[ICR];
@@ -1138,11 +1114,17 @@ set_rdt(E1000State *s, int index, uint32_t val)
 }
 }
 
-static void
-set_16bit(E1000State *s, int index, uint32_t val)
-{
-s->mac_reg[index] = val & 0x;
-}
+#define LOW_BITS_SET_FUNC(num) \
+static void\
+set_##num##bit(E1000State *s, int index, uint32_t val) \
+{  \
+s->mac_reg[index] = val & (BIT(num) - 1);  \
+}
+
+LOW_BITS_SET_FUNC(4)
+LOW_BITS_SET_FUNC(11)
+LOW_BITS_SET_FUNC(13)
+LOW_BITS_SET_FUNC(16)
 
 static void
 set_dlen(E1000State *s, int index, uint32_t val)
@@ -1196,7 +1178,9 @@ static const readops macreg_readops[] = {
 getreg(XONRXC),   getreg(XONTXC),   getreg(XOFFRXC),  getreg(XOFFTXC),
 getreg(RFC),  getreg(RJC),  getreg(RNBC), getreg(TSCTFC),
 getreg(MGTPRC),   getreg(MGTPDC),   getreg(MGTPTC),   getreg(GORCL),
-getreg(GOTCL),
+getreg(GOTCL),getreg(RDFH), getreg(RDFT), getreg(RDFHS),
+getreg(RDFTS),getreg(RDFPC),getreg(TDFH), getreg(TDFT),
+getreg(TDFHS),getreg(TDFTS),getreg(TDFPC),getreg(AIT),
 
 [TOTH]= mac_read_clr8,  [TORH]= mac_read_clr8,
 [GOTCH]   = mac_read_clr8,  [GORCH]   = mac_read_clr8,
@@ -1214,22 +1198,15 @@ static const readops macreg_readops[] = {
 [MPTC]= mac_read_clr4,
 [ICR] = mac_icr_read,   [EECD]= get_eecd,
 [EERD]= flash_eerd_read,
-[RDFH]= mac_low13_read, [RDFT]= mac_low13_read,
-[RDFHS]   = mac_low13_read, [RDFTS]   = mac_low13_read,
-[RDFPC]   = mac_low13_read,
-[TDFH]= mac_low11_read, [TDFT]= mac_low11_read,
-[TDFHS]   = mac_low13_read, [TDFTS]   = mac_low13_read,
-[TDFPC]   = mac_low13_read,
-[AIT] = mac_low16_read,
 
 [CRCERRS ... MPC] = _readreg,
 [IP6AT ... IP6AT + 3] = _readreg,[IP4AT ... IP4AT + 6] = 
_readreg,
-[FFLT ... FFLT + 6]   = _low11_read,
+[FFLT ... FFLT + 6]   = _readreg,
 [RA ... RA + 31]  = _readreg,
 [WUPM ... WUPM + 31]  = _readreg,
 [MTA ... MTA + 127]   = _readreg,
 [VFTA ... VFTA + 127] = _readreg,
-[FFMT ... FFMT + 254] = _low4_read,
+[FFMT ... FFMT + 254] = _readreg,
 [FFVT ... FFVT + 254] = _readreg,
 [PBM ... PBM + 16383] = _readreg,
 };
@@ -1241,26 +1218,27 @@ static const writeops macreg_writeops[] = {
 putreg(PBA),  putreg(EERD), putreg(SWSM), putreg(WUFC),
 putreg(TDBAL),putreg(TDBAH),putreg(TXDCTL),   putreg(RDBAH),
 putreg(RDBAL),putreg(LEDCTL),   putreg(VET),  putreg(FCRUC),
-putreg(TDFH), putreg(TDFT), putreg(TDFHS),putreg(TDFTS),
-putreg(TDFPC),putreg(RDFH), putreg(RDFT), putreg(RDFHS),
-putreg(RDFTS),putreg(RDFPC),putreg(IPAV), putreg(WUC),
-putreg(WUS),  putreg(AIT),
-
-[TDLEN]  = set_dlen,   [RDLEN]  = set_dlen,   [TCTL] = set_tctl,
-[TDT]= set_tctl,   [MDIC]   = set_mdic,   [ICS]  = set_ics,
-[TDH]= set_16bit,  [RDH]= set_16bit,  [RDT]  = set_rdt,
-[IMC]= set_imc,[IMS]= set_ims,[ICR]  = set_icr,
-[EECD]   = set_eecd,   [RCTL]   = set_rx_control, [CTRL] = set_ctrl,
-[RDTR]   = set_16bit,  [RADV]   = set_16bit,  [TADV] = set_16bit,
-[ITR]= set_16bit,
+putreg(IPAV), putreg(WUC),
+putreg(WUS),
+
+[TDLEN]  = set_dlen,   [RDLEN]  = set_dlen,   [TCTL]  = set_tctl,
+[TDT]= set_tctl,   [MDIC]   = set_mdic,   [ICS]   = set_ics,
+[TDH]= set_16bit,  [RDH]= set_16bit,  [RDT]   = set_rdt,
+[IMC]= set_imc,[IMS]= set_ims,[ICR]   = set_icr,
+[EECD]   = set_eecd,   [RCTL]   = set_rx_control, [CTRL]  = set_ctrl,
+[RDTR]   = set_16bit,  

[PULL 19/51] net: Check L4 header size

2023-03-06 Thread Jason Wang
From: Akihiko Odaki 

net_tx_pkt_build_vheader() inspects TCP header but had no check for
the header size, resulting in an undefined behavior. Check the header
size and drop the packet if the header is too small.

Signed-off-by: Akihiko Odaki 
Signed-off-by: Jason Wang 
---
 hw/net/e1000e_core.c | 19 ++-
 hw/net/net_tx_pkt.c  | 13 ++---
 hw/net/net_tx_pkt.h  |  3 ++-
 hw/net/vmxnet3.c | 14 +++---
 4 files changed, 33 insertions(+), 16 deletions(-)

diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c
index d143f2a..38d374f 100644
--- a/hw/net/e1000e_core.c
+++ b/hw/net/e1000e_core.c
@@ -629,23 +629,30 @@ e1000e_rss_parse_packet(E1000ECore *core,
 info->queue = E1000_RSS_QUEUE(>mac[RETA], info->hash);
 }
 
-static void
+static bool
 e1000e_setup_tx_offloads(E1000ECore *core, struct e1000e_tx *tx)
 {
 if (tx->props.tse && tx->cptse) {
-net_tx_pkt_build_vheader(tx->tx_pkt, true, true, tx->props.mss);
+if (!net_tx_pkt_build_vheader(tx->tx_pkt, true, true, tx->props.mss)) {
+return false;
+}
+
 net_tx_pkt_update_ip_checksums(tx->tx_pkt);
 e1000x_inc_reg_if_not_full(core->mac, TSCTC);
-return;
+return true;
 }
 
 if (tx->sum_needed & E1000_TXD_POPTS_TXSM) {
-net_tx_pkt_build_vheader(tx->tx_pkt, false, true, 0);
+if (!net_tx_pkt_build_vheader(tx->tx_pkt, false, true, 0)) {
+return false;
+}
 }
 
 if (tx->sum_needed & E1000_TXD_POPTS_IXSM) {
 net_tx_pkt_update_ip_hdr_checksum(tx->tx_pkt);
 }
+
+return true;
 }
 
 static bool
@@ -654,7 +661,9 @@ e1000e_tx_pkt_send(E1000ECore *core, struct e1000e_tx *tx, 
int queue_index)
 int target_queue = MIN(core->max_queue_num, queue_index);
 NetClientState *queue = qemu_get_subqueue(core->owner_nic, target_queue);
 
-e1000e_setup_tx_offloads(core, tx);
+if (!e1000e_setup_tx_offloads(core, tx)) {
+return false;
+}
 
 net_tx_pkt_dump(tx->tx_pkt);
 
diff --git a/hw/net/net_tx_pkt.c b/hw/net/net_tx_pkt.c
index 2533ea2..8a23899 100644
--- a/hw/net/net_tx_pkt.c
+++ b/hw/net/net_tx_pkt.c
@@ -304,10 +304,11 @@ func_exit:
 return rc;
 }
 
-void net_tx_pkt_build_vheader(struct NetTxPkt *pkt, bool tso_enable,
+bool net_tx_pkt_build_vheader(struct NetTxPkt *pkt, bool tso_enable,
 bool csum_enable, uint32_t gso_size)
 {
 struct tcp_hdr l4hdr;
+size_t bytes_read;
 assert(pkt);
 
 /* csum has to be enabled if tso is. */
@@ -328,8 +329,12 @@ void net_tx_pkt_build_vheader(struct NetTxPkt *pkt, bool 
tso_enable,
 
 case VIRTIO_NET_HDR_GSO_TCPV4:
 case VIRTIO_NET_HDR_GSO_TCPV6:
-iov_to_buf(>vec[NET_TX_PKT_PL_START_FRAG], pkt->payload_frags,
-   0, , sizeof(l4hdr));
+bytes_read = iov_to_buf(>vec[NET_TX_PKT_PL_START_FRAG],
+pkt->payload_frags, 0, , sizeof(l4hdr));
+if (bytes_read < sizeof(l4hdr)) {
+return false;
+}
+
 pkt->virt_hdr.hdr_len = pkt->hdr_len + l4hdr.th_off * sizeof(uint32_t);
 pkt->virt_hdr.gso_size = gso_size;
 break;
@@ -354,6 +359,8 @@ void net_tx_pkt_build_vheader(struct NetTxPkt *pkt, bool 
tso_enable,
 break;
 }
 }
+
+return true;
 }
 
 void net_tx_pkt_setup_vlan_header_ex(struct NetTxPkt *pkt,
diff --git a/hw/net/net_tx_pkt.h b/hw/net/net_tx_pkt.h
index 4ec8bbe..2e38a5f 100644
--- a/hw/net/net_tx_pkt.h
+++ b/hw/net/net_tx_pkt.h
@@ -59,9 +59,10 @@ struct virtio_net_hdr *net_tx_pkt_get_vhdr(struct NetTxPkt 
*pkt);
  * @tso_enable: TSO enabled
  * @csum_enable:CSO enabled
  * @gso_size:   MSS size for TSO
+ * @ret:operation result
  *
  */
-void net_tx_pkt_build_vheader(struct NetTxPkt *pkt, bool tso_enable,
+bool net_tx_pkt_build_vheader(struct NetTxPkt *pkt, bool tso_enable,
 bool csum_enable, uint32_t gso_size);
 
 /**
diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c
index 56559cd..d7d492a 100644
--- a/hw/net/vmxnet3.c
+++ b/hw/net/vmxnet3.c
@@ -440,19 +440,19 @@ vmxnet3_setup_tx_offloads(VMXNET3State *s)
 {
 switch (s->offload_mode) {
 case VMXNET3_OM_NONE:
-net_tx_pkt_build_vheader(s->tx_pkt, false, false, 0);
-break;
+return net_tx_pkt_build_vheader(s->tx_pkt, false, false, 0);
 
 case VMXNET3_OM_CSUM:
-net_tx_pkt_build_vheader(s->tx_pkt, false, true, 0);
 VMW_PKPRN("L4 CSO requested\n");
-break;
+return net_tx_pkt_build_vheader(s->tx_pkt, false, true, 0);
 
 case VMXNET3_OM_TSO:
-net_tx_pkt_build_vheader(s->tx_pkt, true, true,
-s->cso_or_gso_size);
-net_tx_pkt_update_ip_checksums(s->tx_pkt);
 VMW_PKPRN("GSO offload requested.");
+if (!net_tx_pkt_build_vheader(s->tx_pkt, true, true,
+s->cso_or_gso_size)) {
+return false;
+}
+net_tx_pkt_update_ip_checksums(s->tx_pkt);
 break;
 
 default:
-- 
2.7.4

[PULL 04/51] e1000: Use hw/net/mii.h

2023-03-06 Thread Jason Wang
From: Akihiko Odaki 

hw/net/mii.h provides common definitions for MII.

Signed-off-by: Akihiko Odaki 
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Jason Wang 
---
 hw/net/e1000.c | 86 +--
 hw/net/e1000_regs.h| 46 ---
 hw/net/e1000e.c|  1 +
 hw/net/e1000e_core.c   | 99 +-
 hw/net/e1000x_common.c |  5 ++-
 hw/net/e1000x_common.h |  8 ++--
 6 files changed, 101 insertions(+), 144 deletions(-)

diff --git a/hw/net/e1000.c b/hw/net/e1000.c
index 8ee30aa..9619a2e 100644
--- a/hw/net/e1000.c
+++ b/hw/net/e1000.c
@@ -26,6 +26,7 @@
 
 
 #include "qemu/osdep.h"
+#include "hw/net/mii.h"
 #include "hw/pci/pci_device.h"
 #include "hw/qdev-properties.h"
 #include "migration/vmstate.h"
@@ -181,67 +182,67 @@ e1000_autoneg_done(E1000State *s)
 static bool
 have_autoneg(E1000State *s)
 {
-return chkflag(AUTONEG) && (s->phy_reg[PHY_CTRL] & MII_CR_AUTO_NEG_EN);
+return chkflag(AUTONEG) && (s->phy_reg[MII_BMCR] & MII_BMCR_AUTOEN);
 }
 
 static void
 set_phy_ctrl(E1000State *s, int index, uint16_t val)
 {
-/* bits 0-5 reserved; MII_CR_[RESTART_AUTO_NEG,RESET] are self clearing */
-s->phy_reg[PHY_CTRL] = val & ~(0x3f |
-   MII_CR_RESET |
-   MII_CR_RESTART_AUTO_NEG);
+/* bits 0-5 reserved; MII_BMCR_[ANRESTART,RESET] are self clearing */
+s->phy_reg[MII_BMCR] = val & ~(0x3f |
+   MII_BMCR_RESET |
+   MII_BMCR_ANRESTART);
 
 /*
  * QEMU 1.3 does not support link auto-negotiation emulation, so if we
  * migrate during auto negotiation, after migration the link will be
  * down.
  */
-if (have_autoneg(s) && (val & MII_CR_RESTART_AUTO_NEG)) {
+if (have_autoneg(s) && (val & MII_BMCR_ANRESTART)) {
 e1000x_restart_autoneg(s->mac_reg, s->phy_reg, s->autoneg_timer);
 }
 }
 
 static void (*phyreg_writeops[])(E1000State *, int, uint16_t) = {
-[PHY_CTRL] = set_phy_ctrl,
+[MII_BMCR] = set_phy_ctrl,
 };
 
 enum { NPHYWRITEOPS = ARRAY_SIZE(phyreg_writeops) };
 
 enum { PHY_R = 1, PHY_W = 2, PHY_RW = PHY_R | PHY_W };
 static const char phy_regcap[0x20] = {
-[PHY_STATUS]  = PHY_R, [M88E1000_EXT_PHY_SPEC_CTRL] = PHY_RW,
-[PHY_ID1] = PHY_R, [M88E1000_PHY_SPEC_CTRL] = PHY_RW,
-[PHY_CTRL]= PHY_RW,[PHY_1000T_CTRL] = PHY_RW,
-[PHY_LP_ABILITY]  = PHY_R, [PHY_1000T_STATUS]   = PHY_R,
-[PHY_AUTONEG_ADV] = PHY_RW,[M88E1000_RX_ERR_CNTR]   = PHY_R,
-[PHY_ID2] = PHY_R, [M88E1000_PHY_SPEC_STATUS]   = PHY_R,
-[PHY_AUTONEG_EXP] = PHY_R,
+[MII_BMSR]   = PHY_R, [M88E1000_EXT_PHY_SPEC_CTRL] = PHY_RW,
+[MII_PHYID1] = PHY_R, [M88E1000_PHY_SPEC_CTRL] = PHY_RW,
+[MII_BMCR]   = PHY_RW,[MII_CTRL1000]   = PHY_RW,
+[MII_ANLPAR] = PHY_R, [MII_STAT1000]   = PHY_R,
+[MII_ANAR]   = PHY_RW,[M88E1000_RX_ERR_CNTR]   = PHY_R,
+[MII_PHYID2] = PHY_R, [M88E1000_PHY_SPEC_STATUS]   = PHY_R,
+[MII_ANER]   = PHY_R,
 };
 
-/* PHY_ID2 documented in 8254x_GBe_SDM.pdf, pp. 250 */
+/* MII_PHYID2 documented in 8254x_GBe_SDM.pdf, pp. 250 */
 static const uint16_t phy_reg_init[] = {
-[PHY_CTRL]   = MII_CR_SPEED_SELECT_MSB |
-   MII_CR_FULL_DUPLEX |
-   MII_CR_AUTO_NEG_EN,
-
-[PHY_STATUS] = MII_SR_EXTENDED_CAPS |
-   MII_SR_LINK_STATUS |   /* link initially up */
-   MII_SR_AUTONEG_CAPS |
-   /* MII_SR_AUTONEG_COMPLETE: initially NOT completed */
-   MII_SR_PREAMBLE_SUPPRESS |
-   MII_SR_EXTENDED_STATUS |
-   MII_SR_10T_HD_CAPS |
-   MII_SR_10T_FD_CAPS |
-   MII_SR_100X_HD_CAPS |
-   MII_SR_100X_FD_CAPS,
-
-[PHY_ID1] = 0x141,
-/* [PHY_ID2] configured per DevId, from e1000_reset() */
-[PHY_AUTONEG_ADV] = 0xde1,
-[PHY_LP_ABILITY] = 0x1e0,
-[PHY_1000T_CTRL] = 0x0e00,
-[PHY_1000T_STATUS] = 0x3c00,
+[MII_BMCR] = MII_BMCR_SPEED1000 |
+ MII_BMCR_FD |
+ MII_BMCR_AUTOEN,
+
+[MII_BMSR] = MII_BMSR_EXTCAP |
+ MII_BMSR_LINK_ST |   /* link initially up */
+ MII_BMSR_AUTONEG |
+ /* MII_BMSR_AN_COMP: initially NOT completed */
+ MII_BMSR_MFPS |
+ MII_BMSR_EXTSTAT |
+ MII_BMSR_10T_HD |
+ MII_BMSR_10T_FD |
+ MII_BMSR_100TX_HD |
+ MII_BMSR_100TX_FD,
+
+[MII_PHYID1] = 0x141,
+/* [MII_PHYID2] configured per DevId, from e1000_reset() */
+[MII_ANAR] = 0xde1,
+[MII_ANLPAR] = 0x1e0,
+[MII_CTRL1000] = 0x0e00,
+[MII_STAT1000] = 0x3c00,
 [M88E1000_PHY_SPEC_CTRL] = 0x360,
 

[PULL 00/51] Net patches

2023-03-06 Thread Jason Wang
The following changes since commit 817fd33836e73812df2f1907612b57750fcb9491:

  Merge tag 'audio-pull-request' of https://gitlab.com/marcandre.lureau/qemu 
into staging (2023-03-06 14:06:06 +)

are available in the git repository at:

  https://github.com/jasowang/qemu.git tags/net-pull-request

for you to fetch changes up to c19b566a3898510ec2b3e881b3fb78614b240414:

  hw/net/eepro100: Replace DO_UPCAST(EEPRO100State) by EEPRO100() (2023-03-07 
14:55:39 +0800)




Akihiko Odaki (43):
  e1000e: Fix the code style
  hw/net: Add more MII definitions
  fsl_etsec: Use hw/net/mii.h
  e1000: Use hw/net/mii.h
  e1000: Mask registers when writing
  e1000e: Introduce E1000E_LOW_BITS_SET_FUNC
  e1000e: Mask registers when writing
  e1000: Use more constant definitions
  e1000e: Use more constant definitions
  e1000: Use memcpy to intialize registers
  e1000e: Use memcpy to intialize registers
  e1000e: Remove pending interrupt flags
  e1000e: Improve software reset
  e1000: Configure ResettableClass
  e1000e: Configure ResettableClass
  e1000e: Introduce e1000_rx_desc_union
  e1000e: Set MII_ANER_NWAY
  e1000e: Remove extra pointer indirection
  net: Check L4 header size
  e1000x: Alter the signature of e1000x_is_vlan_packet
  net: Strip virtio-net header when dumping
  hw/net/net_tx_pkt: Automatically determine if virtio-net header is used
  hw/net/net_rx_pkt: Remove net_rx_pkt_has_virt_hdr
  e1000e: Perform software segmentation for loopback
  hw/net/net_tx_pkt: Implement TCP segmentation
  hw/net/net_tx_pkt: Check the payload length
  e1000e: Do not assert when MSI-X is disabled later
  MAINTAINERS: Add Akihiko Odaki as a e1000e reviewer
  MAINTAINERS: Add e1000e test files
  e1000e: Combine rx traces
  e1000: Count CRC in Tx statistics
  e1000e: Count CRC in Tx statistics
  net/eth: Report if headers are actually present
  e1000e: Implement system clock
  net/eth: Introduce EthL4HdrProto
  pcie: Introduce pcie_sriov_num_vfs
  e1000: Split header files
  Intrdocue igb device emulation
  tests/qtest/e1000e-test: Fabricate ethernet header
  tests/qtest/libqos/e1000e: Export macreg functions
  igb: Introduce qtest for igb device
  tests/avocado: Add igb test
  docs/system/devices/igb: Add igb documentation

Philippe Mathieu-Daudé (7):
  hw/net/eepro100: Abort if pci_add_capability() ever fail
  hw/net/eepro100: Introduce TYPE_EEPRO100 QOM abstract parent
  hw/net/eepro100: Convert reset handler to DeviceReset
  hw/net/eepro100: Pass E100PCIDeviceInfo as class init data
  hw/net/eepro100: Remove instance EEPRO100State::has_extended_tcb_support
  hw/net/eepro100: Remove instance's EEPRO100State::device
  hw/net/eepro100: Replace DO_UPCAST(EEPRO100State) by EEPRO100()

Shreesh Adiga (1):
  ebpf: fix compatibility with libbpf 1.0+

 MAINTAINERS|   13 +
 docs/system/device-emulation.rst   |1 +
 docs/system/devices/igb.rst|   71 +
 ebpf/rss.bpf.skeleton.h| 1171 --
 hw/core/machine.c  |1 +
 hw/net/Kconfig |5 +
 hw/net/e1000.c |  259 +-
 hw/net/e1000_common.h  |  102 +
 hw/net/e1000_regs.h|  958 +
 hw/net/e1000e.c|  102 +-
 hw/net/e1000e_core.c   |  719 ++--
 hw/net/e1000e_core.h   |   70 +-
 hw/net/e1000x_common.c |   38 +-
 hw/net/e1000x_common.h |  133 +-
 hw/net/e1000x_regs.h   |  967 +
 hw/net/eepro100.c  |  149 +-
 hw/net/fsl_etsec/etsec.c   |   11 +-
 hw/net/fsl_etsec/etsec.h   |   17 -
 hw/net/fsl_etsec/miim.c|5 +-
 hw/net/igb.c   |  615 +++
 hw/net/igb_common.h|  146 +
 hw/net/igb_core.c  | 4077 
 hw/net/igb_core.h  |  146 +
 hw/net/igb_regs.h  |  648 
 hw/net/igbvf.c |  327 ++
 hw/net/meson.build |2 +
 hw/net/net_rx_pkt.c|  102 +-
 hw/net/net_rx_pkt.h|   31 +-
 hw/net/net_tx_pkt.c|  332 +-
 hw/net/net_tx_pkt.h|   27 +-
 

Re: [PATCH v4 12/15] vdpa: block migration if device has unsupported features

2023-03-06 Thread Jason Wang
On Mon, Mar 6, 2023 at 7:33 PM Eugenio Perez Martin  wrote:
>
> On Mon, Mar 6, 2023 at 4:42 AM Jason Wang  wrote:
> >
> > On Fri, Mar 3, 2023 at 4:58 PM Eugenio Perez Martin  
> > wrote:
> > >
> > > On Fri, Mar 3, 2023 at 4:48 AM Jason Wang  wrote:
> > > >
> > > >
> > > > 在 2023/3/2 03:32, Eugenio Perez Martin 写道:
> > > > > On Mon, Feb 27, 2023 at 9:20 AM Jason Wang  
> > > > > wrote:
> > > > >> On Mon, Feb 27, 2023 at 4:15 PM Jason Wang  
> > > > >> wrote:
> > > > >>>
> > > > >>> 在 2023/2/24 23:54, Eugenio Pérez 写道:
> > > >  A vdpa net device must initialize with SVQ in order to be 
> > > >  migratable at
> > > >  this moment, and initialization code verifies some conditions.  If 
> > > >  the
> > > >  device is not initialized with the x-svq parameter, it will not 
> > > >  expose
> > > >  _F_LOG so the vhost subsystem will block VM migration from its
> > > >  initialization.
> > > > 
> > > >  Next patches change this, so we need to verify migration conditions
> > > >  differently.
> > > > 
> > > >  QEMU only supports a subset of net features in SVQ, and it cannot
> > > >  migrate state that cannot track or restore in the destination.  
> > > >  Add a
> > > >  migration blocker if the device offer an unsupported feature.
> > > > 
> > > >  Signed-off-by: Eugenio Pérez 
> > > >  ---
> > > >  v3: add mirgation blocker properly so vhost_dev can handle it.
> > > >  ---
> > > > net/vhost-vdpa.c | 12 
> > > > 1 file changed, 8 insertions(+), 4 deletions(-)
> > > > 
> > > >  diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c
> > > >  index 4f983df000..094dc1c2d0 100644
> > > >  --- a/net/vhost-vdpa.c
> > > >  +++ b/net/vhost-vdpa.c
> > > >  @@ -795,7 +795,8 @@ static NetClientState 
> > > >  *net_vhost_vdpa_init(NetClientState *peer,
> > > >    int nvqs,
> > > >    bool is_datapath,
> > > >    bool svq,
> > > >  -   struct 
> > > >  vhost_vdpa_iova_range iova_range)
> > > >  +   struct 
> > > >  vhost_vdpa_iova_range iova_range,
> > > >  +   uint64_t features)
> > > > {
> > > > NetClientState *nc = NULL;
> > > > VhostVDPAState *s;
> > > >  @@ -818,7 +819,10 @@ static NetClientState 
> > > >  *net_vhost_vdpa_init(NetClientState *peer,
> > > > s->vhost_vdpa.shadow_vqs_enabled = svq;
> > > > s->vhost_vdpa.iova_range = iova_range;
> > > > s->vhost_vdpa.shadow_data = svq;
> > > >  -if (!is_datapath) {
> > > >  +if (queue_pair_index == 0) {
> > > >  +vhost_vdpa_net_valid_svq_features(features,
> > > >  +  
> > > >  >vhost_vdpa.migration_blocker);
> > > > >>>
> > > > >>> Since we do validation at initialization, is this necessary to valid
> > > > >>> once again in other places?
> > > > >> Ok, after reading patch 13, I think the question is:
> > > > >>
> > > > >> The validation seems to be independent to net, can we valid it once
> > > > >> during vhost_vdpa_init()?
> > > > >>
> > > > > vhost_vdpa_net_valid_svq_features also checks for net features. In
> > > > > particular, all the non transport features must be in
> > > > > vdpa_svq_device_features.
> > > > >
> > > > > This is how we protect that the device / guest will never negotiate
> > > > > things like VLAN filtering support, as SVQ still does not know how to
> > > > > restore at the destination.
> > > > >
> > > > > In the VLAN filtering case CVQ is needed to restore VLAN, so it is
> > > > > covered by patch 11/15. But other future features may need support for
> > > > > restoring it in the destination.
> > > >
> > > >
> > > > I wonder how hard to have a general validation code let net specific
> > > > code to advertise a blacklist to avoid code duplication.
> > > >
> > >
> > > A blacklist does not work here, because I don't know if SVQ needs
> > > changes for future feature bits that are still not in / proposed to
> > > the standard.
> >
> > Could you give me an example for this?
> >
>
> Maybe I'm not understanding your blacklist proposal. I'm going to
> explain my thoughts on it with a few examples.
>
> SVQ was merged in qemu before VIRTIO_F_RING_RESET, and there are some
> proposals like VIRTIO_NET_F_NOTF_COAL or VIRTIO_F_PARTIAL_ORDER in the
> virtio-comment list.
>
> If we had gone with the blacklist approach back then, the blacklist
> would contain all the features of Virtio standard but the one we do
> support in SVQ, isn't it? Then, VIRTIO_F_RING_RESET would get merged,
> and SVQ would claim it supports it, but it is not true.

To solve this, the general SVQ code can have a whitelist for transport features?

>
> The 

Re: [PATCH 1/1] hw/core/cpu: always print cpu index with cpu state

2023-03-06 Thread Dongli Zhang
Ping?

The patch already got the Reviewed-by from Philippe Mathieu-Daudé and Alistair
Francis.

The current log does not provide much information when (1) multiple CPUs are
involved in the bug, and (2) when the "info registers -a" is not used to collect
the context from all CPUs for comparison.

We may wait for very long timer until the bug filer can reproduce the error 
again.

To print the cpu index helps a lot.

Thank you very much!

Dongli Zhang

On 2/6/23 15:42, Dongli Zhang wrote:
> The cpu_dump_state() does not print the cpu index. When the
> cpu_dump_state() is invoked due to the KVM failure, we are not able to tell
> from which CPU the state is. The below is an example.
> 
> KVM internal error. Suberror: 764064
> RAX=0002 RBX=8a9e57c38400 RCX= 
> RDX=8a9cc00ba8a0
> RSI=0003 RDI=8a9e57c38400 RBP=b6120c5b3c50 
> RSP=b6120c5b3c40
> R8 = R9 =8a9cc00ba8a0 R10=8e467350 
> R11=0007
> R12=000a R13=8f987e25 R14=8f988a01 
> R15=
> RIP=8e51bb04 RFL=00010046 [---Z-P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
> ES =   00c0
> CS =0010   00a09b00 DPL=0 CS64 [-RA]
> SS =   00c0
> DS =   00c0
> FS =   00c0
> GS = 8ac27fcc  00c0
> LDT=   00c0
> TR =0040 fe096000 206f 8b00 DPL=0 TSS64-busy
> GDT= fe094000 007f
> IDT= fe00 0fff
> CR0=80050033 CR2= CR3=0010ca40a001 CR4=003606e0
> DR0= DR1= DR2= 
> DR3=
> DR6=fffe0ff0 DR7=0400
> EFER=0d01
> Code=0f 1f ... ...
> 
> Print the cpu->cpu_index in cpu_dump_state() and remove it from the caller.
> 
> Cc: Joe Jin 
> Signed-off-by: Dongli Zhang 
> ---
>  hw/core/cpu-common.c  | 1 +
>  monitor/hmp-cmds-target.c | 2 --
>  softmmu/cpus.c| 1 -
>  3 files changed, 1 insertion(+), 3 deletions(-)
> 
> diff --git a/hw/core/cpu-common.c b/hw/core/cpu-common.c
> index 5ccc3837b6..d2503f2d09 100644
> --- a/hw/core/cpu-common.c
> +++ b/hw/core/cpu-common.c
> @@ -105,6 +105,7 @@ void cpu_dump_state(CPUState *cpu, FILE *f, int flags)
>  
>  if (cc->dump_state) {
>  cpu_synchronize_state(cpu);
> +qemu_fprintf(f, "\nCPU#%d\n", cpu->cpu_index);
>  cc->dump_state(cpu, f, flags);
>  }
>  }
> diff --git a/monitor/hmp-cmds-target.c b/monitor/hmp-cmds-target.c
> index 0d3e84d960..f7dd354d2a 100644
> --- a/monitor/hmp-cmds-target.c
> +++ b/monitor/hmp-cmds-target.c
> @@ -99,7 +99,6 @@ void hmp_info_registers(Monitor *mon, const QDict *qdict)
>  
>  if (all_cpus) {
>  CPU_FOREACH(cs) {
> -monitor_printf(mon, "\nCPU#%d\n", cs->cpu_index);
>  cpu_dump_state(cs, NULL, CPU_DUMP_FPU);
>  }
>  } else {
> @@ -114,7 +113,6 @@ void hmp_info_registers(Monitor *mon, const QDict *qdict)
>  return;
>  }
>  
> -monitor_printf(mon, "\nCPU#%d\n", cs->cpu_index);
>  cpu_dump_state(cs, NULL, CPU_DUMP_FPU);
>  }
>  }
> diff --git a/softmmu/cpus.c b/softmmu/cpus.c
> index 9cbc8172b5..f69bbe6abc 100644
> --- a/softmmu/cpus.c
> +++ b/softmmu/cpus.c
> @@ -122,7 +122,6 @@ void hw_error(const char *fmt, ...)
>  vfprintf(stderr, fmt, ap);
>  fprintf(stderr, "\n");
>  CPU_FOREACH(cpu) {
> -fprintf(stderr, "CPU #%d:\n", cpu->cpu_index);
>  cpu_dump_state(cpu, stderr, CPU_DUMP_FPU);
>  }
>  va_end(ap);



Re: [PATCH] hw/acpi: Set memory regions to native endian as a work around

2023-03-06 Thread Paolo Bonzini
Il mar 7 mar 2023, 01:06 BALATON Zoltan  ha scritto:

> I'm not sure I follow what you mean so I'd need a patch to see then I can
> test it with the clients I run on pegasos2.


Do you have a spec, or pointer to the morphos kernel sources, to figure out
how the hardware works?

Paolo


> Regards,
> BALATON Zoltan


Re: [PATCH V2] docs: vhost-user: Add Xen specific memory mapping support

2023-03-06 Thread Viresh Kumar
On 06-03-23, 10:34, Stefan Hajnoczi wrote:
> On Mon, Mar 06, 2023 at 04:40:24PM +0530, Viresh Kumar wrote:
> > +Xen mmap description
> > +
> > +
> > ++---+---+
> > +| flags | domid |
> > ++---+---+
> > +
> > +:flags: 64-bit bit field
> > +
> > +- Bit 0 is set for Xen foreign memory memory mapping.
> > +- Bit 1 is set for Xen grant memory memory mapping.
> > +- Bit 2 is set if the back-end can directly map additional memory (like
> > +  descriptor buffers or indirect descriptors, which aren't part of already
> > +  shared memory regions) without the need of front-end sending an 
> > additional
> > +  memory region first.
> 
> I don't understand what Bit 2 does. Can you rephrase this? It's unclear
> to me how additional memory can be mapped without a memory region
> (especially the fd) is sent?

I (somehow) assumed we will be able to use the same file descriptor
that was shared for the virtqueues memory regions and yes I can see
now why it wouldn't work or create problems.

And I need suggestion now on how to make this work.

With Xen grants, the front end receives grant address from the from
guest kernel, they aren't physical addresses, kind of IOMMU stuff.

The back-end gets access for memory regions of the virtqueues alone
initially.  When the back-end gets a request, it reads the descriptor
and finds the buffer address, which isn't part of already shared
regions. The same happens for descriptor addresses in case indirect
descriptor feature is negotiated.

At this point I was thinking maybe the back-end can simply call the
mmap/ioctl to map the memory, using the file descriptor used for the
virtqueues.

How else can we make this work ? We also need to unmap/remove the
memory region, as soon as the buffer is processed as the grant address
won't be relevant for any subsequent request.

Should I use VHOST_USER_IOTLB_MSG for this ? I did look at it and I
wasn't convinced if it was an exact fit. For example it says that a
memory address reported with miss/access fail should be part of an
already sent memory region, which isn't the case here.

> This message modifies the behavior of subsequent
> VHOST_USER_SET_MEM_TABLE and VHOST_USER_ADD_MEM_REG messages. The memory
> region structs can be extended and then VHOST_USER_SET_XEN_MMAP isn't
> needed.
> 
> In other words:
> 
>   When VHOST_USER_PROTOCOL_F_XEN_MMAP is negotiated, each "Memory
>   regions description" and "Single memory region description" has the
>   following additional fields appended:
> 
>   ++---+
>   | xen_mmap_flags | domid |
>   ++---+

This looks fine.

-- 
viresh



Re: [PATCH v6 01/14] Hexagon (target/hexagon) Add overrides for jumpr31 instructions

2023-03-06 Thread Richard Henderson

On 3/6/23 18:58, Taylor Simpson wrote:

Add overrides for
 SL2_jumpr31Unconditional
 SL2_jumpr31_t  Predicated true (old value)
 SL2_jumpr31_f  Predicated false (old value)
 SL2_jumpr31_tnew   Predicated true (new value)
 SL2_jumpr31_fnew   Predicated false (new value)

Signed-off-by: Taylor Simpson
Reviewed-by: Anton Johansson
---
  target/hexagon/gen_tcg.h | 15 ++-
  target/hexagon/genptr.c  |  9 -
  2 files changed, 22 insertions(+), 2 deletions(-)


Reviewed-by: Richard Henderson 

r~



[PULL 17/17] Hexagon (target/hexagon) Improve code gen for predicated HVX instructions

2023-03-06 Thread Taylor Simpson
The following improvements are made for predicated HVX instructions
During gen_commit_hvx, unconditionally move the "new" value into
the dest
Don't set slot_cancelled
Remove runtime bookkeeping of which registers were updated
Reduce the cases where gen_log_vreg_write[_pair] is called
It's only needed for special operands VxxV and VyV
Remove gen_log_qreg_write

Signed-off-by: Taylor Simpson 
Reviewed-by: Anton Johansson 
Message-Id: <20230307025828.1612809-15-tsimp...@quicinc.com>
---
 target/hexagon/cpu.h|  5 +--
 target/hexagon/gen_tcg_hvx.h| 17 +
 target/hexagon/translate.h  | 15 +++-
 target/hexagon/genptr.c | 48 +++-
 target/hexagon/translate.c  | 58 +++--
 target/hexagon/README   | 21 +++
 target/hexagon/gen_analyze_funcs.py |  3 +-
 target/hexagon/gen_tcg_funcs.py | 35 -
 8 files changed, 34 insertions(+), 168 deletions(-)

diff --git a/target/hexagon/cpu.h b/target/hexagon/cpu.h
index 34c0ae0a67..81b663ecfb 100644
--- a/target/hexagon/cpu.h
+++ b/target/hexagon/cpu.h
@@ -1,5 +1,5 @@
 /*
- *  Copyright(c) 2019-2022 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
+ *  Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -111,11 +111,8 @@ typedef struct CPUArchState {
 MMVector future_VRegs[VECTOR_TEMPS_MAX] QEMU_ALIGNED(16);
 MMVector tmp_VRegs[VECTOR_TEMPS_MAX] QEMU_ALIGNED(16);
 
-VRegMask VRegs_updated;
-
 MMQReg QRegs[NUM_QREGS] QEMU_ALIGNED(16);
 MMQReg future_QRegs[NUM_QREGS] QEMU_ALIGNED(16);
-QRegMask QRegs_updated;
 
 /* Temporaries used within instructions */
 MMVectorPair VuuV QEMU_ALIGNED(16);
diff --git a/target/hexagon/gen_tcg_hvx.h b/target/hexagon/gen_tcg_hvx.h
index 94f272e286..d4aefe8e3f 100644
--- a/target/hexagon/gen_tcg_hvx.h
+++ b/target/hexagon/gen_tcg_hvx.h
@@ -1,5 +1,5 @@
 /*
- *  Copyright(c) 2019-2022 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
+ *  Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -133,16 +133,11 @@ static inline void assert_vhist_tmp(DisasContext *ctx)
 do { \
 TCGv lsb = tcg_temp_new(); \
 TCGLabel *false_label = gen_new_label(); \
-TCGLabel *end_label = gen_new_label(); \
 tcg_gen_andi_tl(lsb, PsV, 1); \
 tcg_gen_brcondi_tl(TCG_COND_NE, lsb, PRED, false_label); \
 tcg_gen_gvec_mov(MO_64, VdV_off, VuV_off, \
  sizeof(MMVector), sizeof(MMVector)); \
-tcg_gen_br(end_label); \
 gen_set_label(false_label); \
-tcg_gen_ori_tl(hex_slot_cancelled, hex_slot_cancelled, \
-   1 << insn->slot); \
-gen_set_label(end_label); \
 } while (0)
 
 
@@ -547,17 +542,12 @@ static inline void assert_vhist_tmp(DisasContext *ctx)
 do { \
 TCGv LSB = tcg_temp_new(); \
 TCGLabel *false_label = gen_new_label(); \
-TCGLabel *end_label = gen_new_label(); \
 GET_EA; \
 PRED; \
 tcg_gen_brcondi_tl(TCG_COND_EQ, LSB, 0, false_label); \
 gen_vreg_load(ctx, DSTOFF, EA, true); \
 INC; \
-tcg_gen_br(end_label); \
 gen_set_label(false_label); \
-tcg_gen_ori_tl(hex_slot_cancelled, hex_slot_cancelled, \
-   1 << insn->slot); \
-gen_set_label(end_label); \
 } while (0)
 
 #define fGEN_TCG_PRED_VEC_LOAD_pred_pi \
@@ -717,17 +707,12 @@ static inline void assert_vhist_tmp(DisasContext *ctx)
 do { \
 TCGv LSB = tcg_temp_new(); \
 TCGLabel *false_label = gen_new_label(); \
-TCGLabel *end_label = gen_new_label(); \
 GET_EA; \
 PRED; \
 tcg_gen_brcondi_tl(TCG_COND_EQ, LSB, 0, false_label); \
 gen_vreg_store(ctx, EA, SRCOFF, insn->slot, ALIGN); \
 INC; \
-tcg_gen_br(end_label); \
 gen_set_label(false_label); \
-tcg_gen_ori_tl(hex_slot_cancelled, hex_slot_cancelled, \
-   1 << insn->slot); \
-gen_set_label(end_label); \
 } while (0)
 
 #define fGEN_TCG_PRED_VEC_STORE_pred_pi(ALIGN) \
diff --git a/target/hexagon/translate.h b/target/hexagon/translate.h
index 6e59a90c41..db832b0f88 100644
--- a/target/hexagon/translate.h
+++ b/target/hexagon/translate.h
@@ -49,7 +49,6 @@ typedef struct DisasContext {
 int tmp_vregs_idx;
 int tmp_vregs_num[VECTOR_TEMPS_MAX];
 int vreg_log[NUM_VREGS];
-bool vreg_is_predicated[NUM_VREGS];
 int vreg_log_idx;
 DECLARE_BITMAP(vregs_updated_tmp, NUM_VREGS);
 DECLARE_BITMAP(vregs_updated, 

[PULL 06/17] Hexagon (target/hexagon) Add overrides for endloop1/endloop01

2023-03-06 Thread Taylor Simpson
Signed-off-by: Taylor Simpson 
Reviewed-by: Anton Johansson 
Message-Id: <20230307025828.1612809-4-tsimp...@quicinc.com>
---
 target/hexagon/gen_tcg.h |  4 +++
 target/hexagon/genptr.c  | 78 
 2 files changed, 82 insertions(+)

diff --git a/target/hexagon/gen_tcg.h b/target/hexagon/gen_tcg.h
index fb23d56d4a..5b7263a82c 100644
--- a/target/hexagon/gen_tcg.h
+++ b/target/hexagon/gen_tcg.h
@@ -603,6 +603,10 @@
 
 #define fGEN_TCG_J2_endloop0(SHORTCODE) \
 gen_endloop0(ctx)
+#define fGEN_TCG_J2_endloop1(SHORTCODE) \
+gen_endloop1(ctx)
+#define fGEN_TCG_J2_endloop01(SHORTCODE) \
+gen_endloop01(ctx)
 
 /*
  * Compound compare and jump instructions
diff --git a/target/hexagon/genptr.c b/target/hexagon/genptr.c
index 592438f61e..f7017fd483 100644
--- a/target/hexagon/genptr.c
+++ b/target/hexagon/genptr.c
@@ -770,6 +770,84 @@ static void gen_endloop0(DisasContext *ctx)
 }
 }
 
+static void gen_endloop1(DisasContext *ctx)
+{
+/*
+ *if (hex_gpr[HEX_REG_LC1] > 1) {
+ *PC = hex_gpr[HEX_REG_SA1];
+ *hex_new_value[HEX_REG_LC1] = hex_gpr[HEX_REG_LC1] - 1;
+ *}
+ */
+TCGLabel *label = gen_new_label();
+tcg_gen_brcondi_tl(TCG_COND_LEU, hex_gpr[HEX_REG_LC1], 1, label);
+{
+gen_jumpr(ctx, hex_gpr[HEX_REG_SA1]);
+tcg_gen_subi_tl(hex_new_value[HEX_REG_LC1], hex_gpr[HEX_REG_LC1], 1);
+}
+gen_set_label(label);
+}
+
+static void gen_endloop01(DisasContext *ctx)
+{
+TCGv lpcfg = tcg_temp_new();
+TCGLabel *label1 = gen_new_label();
+TCGLabel *label2 = gen_new_label();
+TCGLabel *label3 = gen_new_label();
+TCGLabel *done = gen_new_label();
+
+GET_USR_FIELD(USR_LPCFG, lpcfg);
+
+/*
+ *if (lpcfg == 1) {
+ *hex_new_pred_value[3] = 0xff;
+ *hex_pred_written |= 1 << 3;
+ *}
+ */
+tcg_gen_brcondi_tl(TCG_COND_NE, lpcfg, 1, label1);
+{
+tcg_gen_movi_tl(hex_new_pred_value[3], 0xff);
+tcg_gen_ori_tl(hex_pred_written, hex_pred_written, 1 << 3);
+}
+gen_set_label(label1);
+
+/*
+ *if (lpcfg) {
+ *SET_USR_FIELD(USR_LPCFG, lpcfg - 1);
+ *}
+ */
+tcg_gen_brcondi_tl(TCG_COND_EQ, lpcfg, 0, label2);
+{
+tcg_gen_subi_tl(lpcfg, lpcfg, 1);
+SET_USR_FIELD(USR_LPCFG, lpcfg);
+}
+gen_set_label(label2);
+
+/*
+ *if (hex_gpr[HEX_REG_LC0] > 1) {
+ *PC = hex_gpr[HEX_REG_SA0];
+ *hex_new_value[HEX_REG_LC0] = hex_gpr[HEX_REG_LC0] - 1;
+ *} else {
+ *if (hex_gpr[HEX_REG_LC1] > 1) {
+ *hex_next_pc = hex_gpr[HEX_REG_SA1];
+ *hex_new_value[HEX_REG_LC1] = hex_gpr[HEX_REG_LC1] - 1;
+ *}
+ *}
+ */
+tcg_gen_brcondi_tl(TCG_COND_LEU, hex_gpr[HEX_REG_LC0], 1, label3);
+{
+gen_jumpr(ctx, hex_gpr[HEX_REG_SA0]);
+tcg_gen_subi_tl(hex_new_value[HEX_REG_LC0], hex_gpr[HEX_REG_LC0], 1);
+tcg_gen_br(done);
+}
+gen_set_label(label3);
+tcg_gen_brcondi_tl(TCG_COND_LEU, hex_gpr[HEX_REG_LC1], 1, done);
+{
+gen_jumpr(ctx, hex_gpr[HEX_REG_SA1]);
+tcg_gen_subi_tl(hex_new_value[HEX_REG_LC1], hex_gpr[HEX_REG_LC1], 1);
+}
+gen_set_label(done);
+}
+
 static void gen_cmp_jumpnv(DisasContext *ctx,
TCGCond cond, TCGv val, TCGv src, int pc_off)
 {
-- 
2.25.1



[PULL 13/17] Hexagon (tests/tcg/hexagon) Enable HVX tests

2023-03-06 Thread Taylor Simpson
Made possible by new toolchain container

Signed-off-by: Taylor Simpson 
Reviewed-by: Anton Johansson 
Message-Id: <20230307025828.1612809-11-tsimp...@quicinc.com>
---
 tests/tcg/hexagon/Makefile.target | 13 -
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/tests/tcg/hexagon/Makefile.target 
b/tests/tcg/hexagon/Makefile.target
index 18e6a5969e..0d82dfa76e 100644
--- a/tests/tcg/hexagon/Makefile.target
+++ b/tests/tcg/hexagon/Makefile.target
@@ -1,5 +1,5 @@
 ##
-##  Copyright(c) 2019-2022 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
+##  Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
 ##
 ##  This program is free software; you can redistribute it and/or modify
 ##  it under the terms of the GNU General Public License as published by
@@ -45,6 +45,10 @@ HEX_TESTS += fpstuff
 HEX_TESTS += overflow
 HEX_TESTS += signal_context
 HEX_TESTS += reg_mut
+HEX_TESTS += vector_add_int
+HEX_TESTS += scatter_gather
+HEX_TESTS += hvx_misc
+HEX_TESTS += hvx_histogram
 
 HEX_TESTS += test_abs
 HEX_TESTS += test_bitcnt
@@ -78,3 +82,10 @@ TESTS += $(HEX_TESTS)
 usr: usr.c
$(CC) $(CFLAGS) -mv67t -O2 -Wno-inline-asm -Wno-expansion-to-defined $< 
-o $@ $(LDFLAGS)
 
+scatter_gather: CFLAGS += -mhvx
+vector_add_int: CFLAGS += -mhvx -fvectorize
+hvx_misc: CFLAGS += -mhvx
+hvx_histogram: CFLAGS += -mhvx -Wno-gnu-folding-constant
+
+hvx_histogram: hvx_histogram.c hvx_histogram_row.S
+   $(CC) $(CFLAGS) $(CROSS_CC_GUEST_CFLAGS) $^ -o $@ $(LDFLAGS)
-- 
2.25.1



[PULL 11/17] Hexagon (tests/tcg/hexagon) Update preg_alias.c

2023-03-06 Thread Taylor Simpson
Add control registers (c4, c5) to clobbers list
Made possible by new toolchain container

Signed-off-by: Taylor Simpson 
Reviewed-by: Anton Johansson 
Message-Id: <20230307025828.1612809-9-tsimp...@quicinc.com>
---
 tests/tcg/hexagon/preg_alias.c | 10 +-
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/tests/tcg/hexagon/preg_alias.c b/tests/tcg/hexagon/preg_alias.c
index b44a8112b4..8798fbcaf3 100644
--- a/tests/tcg/hexagon/preg_alias.c
+++ b/tests/tcg/hexagon/preg_alias.c
@@ -1,5 +1,5 @@
 /*
- *  Copyright(c) 2019-2022 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
+ *  Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -65,7 +65,7 @@ static inline void creg_alias(int cval, PRegs *pregs)
   : "=r"(pregs->pregs.p0), "=r"(pregs->pregs.p1),
 "=r"(pregs->pregs.p2), "=r"(pregs->pregs.p3)
   : "r"(cval)
-  : "p0", "p1", "p2", "p3");
+  : "c4", "p0", "p1", "p2", "p3");
 }
 
 int err;
@@ -92,7 +92,7 @@ static inline void creg_alias_pair(unsigned int cval, PRegs 
*pregs)
: "=r"(pregs->pregs.p0), "=r"(pregs->pregs.p1),
  "=r"(pregs->pregs.p2), "=r"(pregs->pregs.p3), "=r"(c5)
: "r"(cval_pair)
-   : "p0", "p1", "p2", "p3");
+   : "c4", "c5", "p0", "p1", "p2", "p3");
 
   check(c5, 0xdeadbeef);
 }
@@ -117,7 +117,7 @@ static void test_packet(void)
  "}\n\t"
  : "+r"(result)
  : "r"(0x), "r"(0xff00), "r"(0x837ed653)
- : "p0", "p1", "p2", "p3");
+ : "c4", "p0", "p1", "p2", "p3");
 check(result, old_val);
 
 /* Test a predicated store */
@@ -129,7 +129,7 @@ static void test_packet(void)
  "}\n\t"
  :
  : "r"(0), "r"(0x), "r"()
- : "p0", "p1", "p2", "p3", "memory");
+ : "c4", "p0", "p1", "p2", "p3", "memory");
 check(result, 0x0);
 }
 
-- 
2.25.1



[PULL 03/17] target/hexagon/idef-parser: Remove unused code paths

2023-03-06 Thread Taylor Simpson
From: Anton Johansson 

Removes code paths used by COF instructions, which are no longer
processed by idef-parser.

Tested-by: Taylor Simpson 
Reviewed-by: Taylor Simpson 
Signed-off-by: Taylor Simpson 
Signed-off-by: Anton Johansson 
Message-Id: <20230131223133.8592-1-a...@rev.ng>
---
 target/hexagon/idef-parser/idef-parser.h|  1 -
 target/hexagon/idef-parser/parser-helpers.c |  3 --
 target/hexagon/idef-parser/idef-parser.lex  | 27 +
 target/hexagon/idef-parser/idef-parser.y| 44 +
 target/hexagon/idef-parser/macros.inc   |  9 -
 5 files changed, 4 insertions(+), 80 deletions(-)

diff --git a/target/hexagon/idef-parser/idef-parser.h 
b/target/hexagon/idef-parser/idef-parser.h
index 17d2ebfaf6..d23e71f13b 100644
--- a/target/hexagon/idef-parser/idef-parser.h
+++ b/target/hexagon/idef-parser/idef-parser.h
@@ -82,7 +82,6 @@ enum ImmUnionTag {
 VALUE,
 QEMU_TMP,
 IMM_PC,
-IMM_NPC,
 IMM_CONSTEXT,
 };
 
diff --git a/target/hexagon/idef-parser/parser-helpers.c 
b/target/hexagon/idef-parser/parser-helpers.c
index 7b494c2f9e..cc2cd000db 100644
--- a/target/hexagon/idef-parser/parser-helpers.c
+++ b/target/hexagon/idef-parser/parser-helpers.c
@@ -185,9 +185,6 @@ void imm_print(Context *c, YYLTYPE *locp, HexImm *imm)
 case IMM_PC:
 EMIT(c, "ctx->base.pc_next");
 break;
-case IMM_NPC:
-EMIT(c, "ctx->npc");
-break;
 case IMM_CONSTEXT:
 EMIT(c, "insn->extension_valid");
 break;
diff --git a/target/hexagon/idef-parser/idef-parser.lex 
b/target/hexagon/idef-parser/idef-parser.lex
index ff87a02c3a..2658d9fb2e 100644
--- a/target/hexagon/idef-parser/idef-parser.lex
+++ b/target/hexagon/idef-parser/idef-parser.lex
@@ -140,8 +140,6 @@ STRING_LIT   \"(\\.|[^"\\])*\"
yylval->rvalue.is_dotnew = true;
yylval->rvalue.signedness = SIGNED;
return PRED; }
-"IV1DEAD()"  |
-"fPAUSE(uiV);"   { return ';'; }
 "+=" { return INC; }
 "-=" { return DEC; }
 "++" { return PLUSPLUS; }
@@ -159,9 +157,8 @@ STRING_LIT   \"(\\.|[^"\\])*\"
 "else"   { return ELSE; }
 "for"{ return FOR; }
 "fREAD_IREG" { return ICIRC; }
-"fPART1" { return PART1; }
 "if" { return IF; }
-"fFRAME_SCRAMBLE"{ return FSCR; }
+"fFRAME_SCRAMBLE"|
 "fFRAME_UNSCRAMBLE"  { return FSCR; }
 "fFRAMECHECK"{ return FCHK; }
 "Constant_extended"  { return CONSTEXT; }
@@ -312,11 +309,7 @@ STRING_LIT   \"(\\.|[^"\\])*\"
 "(unsigned int)" { yylval->cast.bit_width = 32;
yylval->cast.signedness = UNSIGNED;
return CAST; }
-"fREAD_PC()" |
-"PC" { return PC; }
-"fREAD_NPC()"|
-"NPC"{ return NPC; }
-"fGET_LPCFG" |
+"fREAD_PC()" { return PC; }
 "USR.LPCFG"  { return LPCFG; }
 "LOAD_CANCEL(EA)"{ return LOAD_CANCEL; }
 "STORE_CANCEL(EA)"   |
@@ -360,14 +353,6 @@ STRING_LIT   \"(\\.|[^"\\])*\"
yylval->rvalue.bit_width = 32;
yylval->rvalue.signedness = UNSIGNED;
return REG; }
-"fREAD_LC"[01]   { yylval->rvalue.type = REGISTER;
-   yylval->rvalue.reg.type = CONTROL;
-   yylval->rvalue.reg.id = HEX_REG_LC0
- + (yytext[8] - '0') * 2;
-   yylval->rvalue.reg.bit_width = 32;
-   yylval->rvalue.bit_width = 32;
-   yylval->rvalue.signedness = UNSIGNED;
-   return REG; }
 "LC"[01] { yylval->rvalue.type = REGISTER;
yylval->rvalue.reg.type = CONTROL;
yylval->rvalue.reg.id = HEX_REG_LC0
@@ -376,14 +361,6 @@ STRING_LIT   \"(\\.|[^"\\])*\"
yylval->rvalue.bit_width = 32;
yylval->rvalue.signedness = UNSIGNED;
return REG; }
-"fREAD_SA"[01]   { yylval->rvalue.type = REGISTER;
-   yylval->rvalue.reg.type = CONTROL;
-   yylval->rvalue.reg.id = HEX_REG_SA0
- + (yytext[8] - '0') * 2;
-   yylval->rvalue.reg.bit_width = 32;
-   yylval->rvalue.bit_width = 32;
-   yylval->rvalue.signedness = UNSIGNED;
-   return REG; }
 "SA"[01] { yylval->rvalue.type = REGISTER;
yylval->rvalue.reg.type = CONTROL;

[PULL 15/17] Hexagon (target/hexagon) Remove gen_log_predicated_reg_write[_pair]

2023-03-06 Thread Taylor Simpson
We assign the instruction destination register to hex_new_value[num]
instead of a TCG temp that gets copied back to hex_new_value[num].

We introduce new functions get_result_gpr[_pair] to facilitate getting
the proper destination register.

Since we preload hex_new_value for predicated instructions, we don't
need the check for slot_cancelled.  So, we call gen_log_reg_write instead.

We update the helper function generation and gen_tcg.h to maintain the
disable-hexagon-idef-parser configuration.

Here is a simple example of the differences in the TCG code generated:

IN:
0x00400094:  0xf900c102 {   if (P0) R2 = and(R0,R1) }

BEFORE
  00400094
 mov_i32 slot_cancelled,$0x0
 mov_i32 new_r2,r2
 mov_i32 loc2,$0x0
 and_i32 tmp0,p0,$0x1
 brcond_i32 tmp0,$0x0,eq,$L1
 and_i32 tmp0,r0,r1
 mov_i32 loc2,tmp0
 br $L2
 set_label $L1
 or_i32 slot_cancelled,slot_cancelled,$0x8
 set_label $L2
 and_i32 tmp0,slot_cancelled,$0x8
 movcond_i32 new_r2,tmp0,$0x0,loc2,new_r2,eq
 mov_i32 r2,new_r2

AFTER
  00400094
 mov_i32 slot_cancelled,$0x0
 mov_i32 new_r2,r2
 and_i32 tmp0,p0,$0x1
 brcond_i32 tmp0,$0x0,eq,$L1
 and_i32 tmp0,r0,r1
 mov_i32 new_r2,tmp0
 br $L2
 set_label $L1
 or_i32 slot_cancelled,slot_cancelled,$0x8
 set_label $L2
 mov_i32 r2,new_r2

We'll remove the unnecessary manipulation of slot_cancelled in a
subsequent patch.

Signed-off-by: Taylor Simpson 
Reviewed-by: Anton Johansson 
Message-Id: <20230307025828.1612809-13-tsimp...@quicinc.com>
---
 target/hexagon/gen_tcg.h|   6 +-
 target/hexagon/macros.h |  15 ---
 target/hexagon/genptr.c | 121 +---
 target/hexagon/idef-parser/parser-helpers.c |   4 +-
 target/hexagon/gen_helper_funcs.py  |  19 ++-
 target/hexagon/gen_helper_protos.py |  12 +-
 target/hexagon/gen_tcg_funcs.py |  76 +++-
 target/hexagon/hex_common.py|   9 +-
 8 files changed, 110 insertions(+), 152 deletions(-)

diff --git a/target/hexagon/gen_tcg.h b/target/hexagon/gen_tcg.h
index e72672e198..bcf0cf466a 100644
--- a/target/hexagon/gen_tcg.h
+++ b/target/hexagon/gen_tcg.h
@@ -332,8 +332,6 @@
 tcg_gen_movi_tl(EA, 0); \
 PRED;  \
 CHECK_NOSHUF_PRED(GET_EA, SIZE, LSB); \
-PRED_LOAD_CANCEL(LSB, EA); \
-tcg_gen_movi_tl(RdV, 0); \
 tcg_gen_brcondi_tl(TCG_COND_EQ, LSB, 0, label); \
 fLOAD(1, SIZE, SIGN, EA, RdV); \
 gen_set_label(label); \
@@ -391,8 +389,6 @@
 tcg_gen_movi_tl(EA, 0); \
 PRED;  \
 CHECK_NOSHUF_PRED(GET_EA, 8, LSB); \
-PRED_LOAD_CANCEL(LSB, EA); \
-tcg_gen_movi_i64(RddV, 0); \
 tcg_gen_brcondi_tl(TCG_COND_EQ, LSB, 0, label); \
 fLOAD(1, 8, u, EA, RddV); \
 gen_set_label(label); \
@@ -504,7 +500,7 @@
  */
 #define fGEN_TCG_SL2_return(SHORTCODE) \
 do { \
-TCGv_i64 RddV = tcg_temp_new_i64(); \
+TCGv_i64 RddV = get_result_gpr_pair(ctx, HEX_REG_FP); \
 gen_return(ctx, RddV, hex_gpr[HEX_REG_FP]); \
 gen_log_reg_write_pair(HEX_REG_FP, RddV); \
 } while (0)
diff --git a/target/hexagon/macros.h b/target/hexagon/macros.h
index 6974ef6c9e..1fa6057d27 100644
--- a/target/hexagon/macros.h
+++ b/target/hexagon/macros.h
@@ -210,21 +210,6 @@ static inline void gen_cancel(uint32_t slot)
 
 #define LOAD_CANCEL(EA) do { CANCEL; } while (0)
 
-#ifdef QEMU_GENERATE
-static inline void gen_pred_cancel(TCGv pred, uint32_t slot_num)
- {
-TCGv slot_mask = tcg_temp_new();
-TCGv tmp = tcg_temp_new();
-TCGv zero = tcg_constant_tl(0);
-tcg_gen_ori_tl(slot_mask, hex_slot_cancelled, 1 << slot_num);
-tcg_gen_andi_tl(tmp, pred, 1);
-tcg_gen_movcond_tl(TCG_COND_EQ, hex_slot_cancelled, tmp, zero,
-   slot_mask, hex_slot_cancelled);
-}
-#define PRED_LOAD_CANCEL(PRED, EA) \
-gen_pred_cancel(PRED, insn->is_endloop ? 4 : insn->slot)
-#endif
-
 #define STORE_CANCEL(EA) { env->slot_cancelled |= (1 << slot); }
 
 #define fMAX(A, B) (((A) > (B)) ? (A) : (B))
diff --git a/target/hexagon/genptr.c b/target/hexagon/genptr.c
index 61ab9af9e4..da5dbc83cf 100644
--- a/target/hexagon/genptr.c
+++ b/target/hexagon/genptr.c
@@ -68,26 +68,17 @@ static inline void gen_masked_reg_write(TCGv new_val, TCGv 
cur_val,
 }
 }
 
-static inline void gen_log_predicated_reg_write(int rnum, TCGv val,
-uint32_t slot)
+static TCGv get_result_gpr(DisasContext *ctx, int rnum)
 {
-TCGv zero = tcg_constant_tl(0);
-TCGv slot_mask = tcg_temp_new();
+return hex_new_value[rnum];
+}
 
-tcg_gen_andi_tl(slot_mask, hex_slot_cancelled, 1 << slot);
-tcg_gen_movcond_tl(TCG_COND_EQ, hex_new_value[rnum], slot_mask, zero,
-   val, hex_new_value[rnum]);
-if (HEX_DEBUG) {
-/*
- * Do this so HELPER(debug_commit_end) will know
- *
- * Note that slot_mask indicates the value is not written
- * 

[PULL 05/17] Hexagon (target/hexagon) Add overrides for callr

2023-03-06 Thread Taylor Simpson
Add overrides for
J2_callr
J2_callrt
J2_callrf

Signed-off-by: Taylor Simpson 
Reviewed-by: Anton Johansson 
Message-Id: <20230307025828.1612809-3-tsimp...@quicinc.com>
---
 target/hexagon/gen_tcg.h |  6 ++
 target/hexagon/macros.h  | 12 +---
 target/hexagon/genptr.c  | 18 ++
 3 files changed, 25 insertions(+), 11 deletions(-)

diff --git a/target/hexagon/gen_tcg.h b/target/hexagon/gen_tcg.h
index f898f5b389..fb23d56d4a 100644
--- a/target/hexagon/gen_tcg.h
+++ b/target/hexagon/gen_tcg.h
@@ -589,11 +589,17 @@
 
 #define fGEN_TCG_J2_call(SHORTCODE) \
 gen_call(ctx, riV)
+#define fGEN_TCG_J2_callr(SHORTCODE) \
+gen_callr(ctx, RsV)
 
 #define fGEN_TCG_J2_callt(SHORTCODE) \
 gen_cond_call(ctx, PuV, TCG_COND_EQ, riV)
 #define fGEN_TCG_J2_callf(SHORTCODE) \
 gen_cond_call(ctx, PuV, TCG_COND_NE, riV)
+#define fGEN_TCG_J2_callrt(SHORTCODE) \
+gen_cond_callr(ctx, TCG_COND_EQ, PuV, RsV)
+#define fGEN_TCG_J2_callrf(SHORTCODE) \
+gen_cond_callr(ctx, TCG_COND_NE, PuV, RsV)
 
 #define fGEN_TCG_J2_endloop0(SHORTCODE) \
 gen_endloop0(ctx)
diff --git a/target/hexagon/macros.h b/target/hexagon/macros.h
index 17facadaad..6974ef6c9e 100644
--- a/target/hexagon/macros.h
+++ b/target/hexagon/macros.h
@@ -1,5 +1,5 @@
 /*
- *  Copyright(c) 2019-2022 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
+ *  Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -415,16 +415,6 @@ static inline TCGv gen_read_ireg(TCGv result, TCGv val, 
int shift)
 #define fBRANCH(LOC, TYPE)  fWRITE_NPC(LOC)
 #define fJUMPR(REGNO, TARGET, TYPE) fBRANCH(TARGET, COF_TYPE_JUMPR)
 #define fHINTJR(TARGET) { /* Not modelled in qemu */}
-#define fCALL(A) \
-do { \
-fWRITE_LR(fREAD_NPC()); \
-fBRANCH(A, COF_TYPE_CALL); \
-} while (0)
-#define fCALLR(A) \
-do { \
-fWRITE_LR(fREAD_NPC()); \
-fBRANCH(A, COF_TYPE_CALLR); \
-} while (0)
 #define fWRITE_LOOP_REGS0(START, COUNT) \
 do { \
 WRITE_RREG(HEX_REG_LC0, COUNT);  \
diff --git a/target/hexagon/genptr.c b/target/hexagon/genptr.c
index 2bbe4e3a68..592438f61e 100644
--- a/target/hexagon/genptr.c
+++ b/target/hexagon/genptr.c
@@ -682,6 +682,13 @@ static void gen_call(DisasContext *ctx, int pc_off)
 gen_write_new_pc_pcrel(ctx, pc_off, TCG_COND_ALWAYS, NULL);
 }
 
+static void gen_callr(DisasContext *ctx, TCGv new_pc)
+{
+TCGv next_PC = tcg_constant_tl(ctx->next_PC);
+gen_log_reg_write(HEX_REG_LR, next_PC);
+gen_write_new_pc_addr(ctx, new_pc, TCG_COND_ALWAYS, NULL);
+}
+
 static void gen_cond_call(DisasContext *ctx, TCGv pred,
   TCGCond cond, int pc_off)
 {
@@ -697,6 +704,17 @@ static void gen_cond_call(DisasContext *ctx, TCGv pred,
 gen_set_label(skip);
 }
 
+static void gen_cond_callr(DisasContext *ctx,
+   TCGCond cond, TCGv pred, TCGv new_pc)
+{
+TCGv lsb = tcg_temp_new();
+TCGLabel *skip = gen_new_label();
+tcg_gen_andi_tl(lsb, pred, 1);
+tcg_gen_brcondi_tl(cond, lsb, 0, skip);
+gen_callr(ctx, new_pc);
+gen_set_label(skip);
+}
+
 static void gen_endloop0(DisasContext *ctx)
 {
 TCGv lpcfg = tcg_temp_new();
-- 
2.25.1



[PULL 02/17] target/hexagon/idef-parser: Elide mov in gen_pred_assign

2023-03-06 Thread Taylor Simpson
From: Richard Henderson 

Merge mov with andi.

Suggested-by: Taylor Simpson 
Signed-off-by: Richard Henderson 
Signed-off-by: Taylor Simpson 
Reviewed-by: Philippe Mathieu-Daudé 
Reviewed-by: Taylor Simpson 
Message-Id: <20230306225724.2105263-1-richard.hender...@linaro.org>
---
 target/hexagon/idef-parser/parser-helpers.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/target/hexagon/idef-parser/parser-helpers.c 
b/target/hexagon/idef-parser/parser-helpers.c
index e1a55412c8..7b494c2f9e 100644
--- a/target/hexagon/idef-parser/parser-helpers.c
+++ b/target/hexagon/idef-parser/parser-helpers.c
@@ -1722,9 +1722,7 @@ void gen_pred_assign(Context *c, YYLTYPE *locp, HexValue 
*left_pred,
 *left_pred = gen_tmp(c, locp, 32, UNSIGNED);
 }
 /* Extract first 8 bits, and store new predicate value */
-OUT(c, locp, "tcg_gen_mov_i32(", left_pred, ", ", , ");\n");
-OUT(c, locp, "tcg_gen_andi_i32(", left_pred, ", ", left_pred,
-", 0xff);\n");
+OUT(c, locp, "tcg_gen_andi_i32(", left_pred, ", ", , ", 0xff);\n");
 if (is_direct) {
 OUT(c, locp, "gen_log_pred_write(ctx, ", pred_id, ", ", left_pred,
 ");\n");
-- 
2.25.1



[PULL 00/17] Hexagon (target/hexagon) updates

2023-03-06 Thread Taylor Simpson
The following changes since commit f003dd8d81f7d88f4b1f8802309eaa76f6eb223a:

  Merge tag 'pull-tcg-20230305' of https://gitlab.com/rth7680/qemu into staging 
(2023-03-06 10:20:04 +)

are available in the Git repository at:

  https://github.com/quic/qemu tags/pull-hex-20230306

for you to fetch changes up to c2b33d0be998bf539953f1dad0aa0d1cc8d9d069:

  Hexagon (target/hexagon) Improve code gen for predicated HVX instructions 
(2023-03-06 20:47:12 -0800)


Hexagon (target/hexagon) updates


Anton Johansson (1):
  target/hexagon/idef-parser: Remove unused code paths

Richard Henderson (1):
  target/hexagon/idef-parser: Elide mov in gen_pred_assign

Taylor Simpson (15):
  Hexagon (target/hexagon) Restore --disable-hexagon-idef-parser build
  Hexagon (target/hexagon) Add overrides for jumpr31 instructions
  Hexagon (target/hexagon) Add overrides for callr
  Hexagon (target/hexagon) Add overrides for endloop1/endloop01
  Hexagon (target/hexagon) Add overrides for dealloc-return instructions
  Hexagon (target/hexagon) Analyze packet before generating TCG
  Hexagon (target/hexagon) Don't set pkt_has_store_s1 when not needed
  Hexagon (target/hexagon) Analyze packet for HVX
  Hexagon (tests/tcg/hexagon) Update preg_alias.c
  Hexagon (tests/tcg/hexagon) Remove __builtin from scatter_gather
  Hexagon (tests/tcg/hexagon) Enable HVX tests
  Hexagon (target/hexagon) Change subtract from zero to change sign
  Hexagon (target/hexagon) Remove gen_log_predicated_reg_write[_pair]
  Hexagon (target/hexagon) Reduce manipulation of slot_cancelled
  Hexagon (target/hexagon) Improve code gen for predicated HVX instructions

 target/hexagon/cpu.h|   5 +-
 target/hexagon/gen_tcg.h|  90 -
 target/hexagon/gen_tcg_hvx.h|  17 +-
 target/hexagon/idef-parser/idef-parser.h|   1 -
 target/hexagon/macros.h |  29 +-
 target/hexagon/op_helper.h  |   3 +-
 target/hexagon/translate.h  |  86 +++--
 target/hexagon/attribs_def.h.inc|   1 +
 target/hexagon/genptr.c | 296 ++--
 target/hexagon/idef-parser/parser-helpers.c |  19 +-
 target/hexagon/op_helper.c  |  60 ++--
 target/hexagon/translate.c  | 288 +---
 tests/tcg/hexagon/fpstuff.c |  31 +-
 tests/tcg/hexagon/preg_alias.c  |  10 +-
 tests/tcg/hexagon/scatter_gather.c  | 513 +++-
 target/hexagon/README   |  31 +-
 target/hexagon/gen_analyze_funcs.py | 252 ++
 target/hexagon/gen_helper_funcs.py  |  19 +-
 target/hexagon/gen_helper_protos.py |  12 +-
 target/hexagon/gen_tcg_funcs.py | 152 +++--
 target/hexagon/hex_common.py|  10 +-
 target/hexagon/idef-parser/idef-parser.lex  |  31 +-
 target/hexagon/idef-parser/idef-parser.y|  49 +--
 target/hexagon/idef-parser/macros.inc   |   9 -
 target/hexagon/meson.build  |  11 +-
 tests/tcg/hexagon/Makefile.target   |  13 +-
 26 files changed, 1209 insertions(+), 829 deletions(-)
 create mode 100755 target/hexagon/gen_analyze_funcs.py


[PULL 16/17] Hexagon (target/hexagon) Reduce manipulation of slot_cancelled

2023-03-06 Thread Taylor Simpson
We only need to track slot for predicated stores and predicated HVX
instructions.

Add arguments to the probe helper functions to indicate if the slot
is predicated.

Here is a simple example of the differences in the TCG code generated:

IN:
0x00400094:  0xf900c102 {   if (P0) R2 = and(R0,R1) }

BEFORE
  00400094
 mov_i32 slot_cancelled,$0x0
 mov_i32 new_r2,r2
 and_i32 tmp0,p0,$0x1
 brcond_i32 tmp0,$0x0,eq,$L1
 and_i32 tmp0,r0,r1
 mov_i32 new_r2,tmp0
 br $L2
 set_label $L1
 or_i32 slot_cancelled,slot_cancelled,$0x8
 set_label $L2
 mov_i32 r2,new_r2

AFTER
  00400094
 mov_i32 new_r2,r2
 and_i32 tmp0,p0,$0x1
 brcond_i32 tmp0,$0x0,eq,$L1
 and_i32 tmp0,r0,r1
 mov_i32 new_r2,tmp0
 br $L2
 set_label $L1
 set_label $L2
 mov_i32 r2,new_r2

Signed-off-by: Taylor Simpson 
Reviewed-by: Anton Johansson 
Message-Id: <20230307025828.1612809-14-tsimp...@quicinc.com>
---
 target/hexagon/macros.h |  2 +-
 target/hexagon/op_helper.h  |  3 +-
 target/hexagon/translate.h  | 10 +
 target/hexagon/idef-parser/parser-helpers.c |  1 -
 target/hexagon/op_helper.c  | 32 
 target/hexagon/translate.c  | 42 ++---
 target/hexagon/idef-parser/idef-parser.lex  |  4 +-
 target/hexagon/idef-parser/idef-parser.y|  7 ++--
 8 files changed, 71 insertions(+), 30 deletions(-)

diff --git a/target/hexagon/macros.h b/target/hexagon/macros.h
index 1fa6057d27..482a9c787f 100644
--- a/target/hexagon/macros.h
+++ b/target/hexagon/macros.h
@@ -205,7 +205,7 @@ static inline void gen_cancel(uint32_t slot)
 
 #define CANCEL gen_cancel(slot);
 #else
-#define CANCEL cancel_slot(env, slot)
+#define CANCEL do { } while (0)
 #endif
 
 #define LOAD_CANCEL(EA) do { CANCEL; } while (0)
diff --git a/target/hexagon/op_helper.h b/target/hexagon/op_helper.h
index 02347edee8..34b3a53975 100644
--- a/target/hexagon/op_helper.h
+++ b/target/hexagon/op_helper.h
@@ -1,5 +1,5 @@
 /*
- *  Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
+ *  Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -19,7 +19,6 @@
 #define HEXAGON_OP_HELPER_H
 
 /* Misc functions */
-void cancel_slot(CPUHexagonState *env, uint32_t slot);
 void write_new_pc(CPUHexagonState *env, bool pkt_has_multi_cof, target_ulong 
addr);
 
 uint8_t mem_load1(CPUHexagonState *env, uint32_t slot, target_ulong vaddr);
diff --git a/target/hexagon/translate.h b/target/hexagon/translate.h
index 765f2c6a22..6e59a90c41 100644
--- a/target/hexagon/translate.h
+++ b/target/hexagon/translate.h
@@ -172,4 +172,14 @@ extern TCGv hex_vstore_pending[VSTORES_MAX];
 
 bool is_gather_store_insn(DisasContext *ctx);
 void process_store(DisasContext *ctx, int slot_num);
+
+FIELD(PROBE_PKT_SCALAR_STORE_S0, MMU_IDX,   0, 2)
+FIELD(PROBE_PKT_SCALAR_STORE_S0, IS_PREDICATED, 2, 1)
+
+FIELD(PROBE_PKT_SCALAR_HVX_STORES, HAS_ST0,0, 1)
+FIELD(PROBE_PKT_SCALAR_HVX_STORES, HAS_ST1,1, 1)
+FIELD(PROBE_PKT_SCALAR_HVX_STORES, HAS_HVX_STORES, 2, 1)
+FIELD(PROBE_PKT_SCALAR_HVX_STORES, S0_IS_PRED, 3, 1)
+FIELD(PROBE_PKT_SCALAR_HVX_STORES, S1_IS_PRED, 4, 1)
+
 #endif
diff --git a/target/hexagon/idef-parser/parser-helpers.c 
b/target/hexagon/idef-parser/parser-helpers.c
index 9720ef4ad1..18cde6a1be 100644
--- a/target/hexagon/idef-parser/parser-helpers.c
+++ b/target/hexagon/idef-parser/parser-helpers.c
@@ -1727,7 +1727,6 @@ void gen_cancel(Context *c, YYLTYPE *locp)
 
 void gen_load_cancel(Context *c, YYLTYPE *locp)
 {
-gen_cancel(c, locp);
 OUT(c, locp, "if (insn->slot == 0 && pkt->pkt_has_store_s1) {\n");
 OUT(c, locp, "ctx->s1_store_processed = false;\n");
 OUT(c, locp, "process_store(ctx, 1);\n");
diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c
index 9425941c69..c9a156030e 100644
--- a/target/hexagon/op_helper.c
+++ b/target/hexagon/op_helper.c
@@ -30,6 +30,7 @@
 #include "mmvec/mmvec.h"
 #include "mmvec/macros.h"
 #include "op_helper.h"
+#include "translate.h"
 
 #define SF_BIAS127
 #define SF_MANTBITS23
@@ -415,9 +416,10 @@ int32_t HELPER(vacsh_pred)(CPUHexagonState *env,
 return PeV;
 }
 
-static void probe_store(CPUHexagonState *env, int slot, int mmu_idx)
+static void probe_store(CPUHexagonState *env, int slot, int mmu_idx,
+bool is_predicated)
 {
-if (!(env->slot_cancelled & (1 << slot))) {
+if (!is_predicated || !(env->slot_cancelled & (1 << slot))) {
 size1u_t width = env->mem_log_stores[slot].width;
 target_ulong va = env->mem_log_stores[slot].va;
 uintptr_t ra = GETPC();
@@ -437,9 +439,12 @@ void HELPER(probe_noshuf_load)(CPUHexagonState *env, 
target_ulong va,
 }
 
 /* Called during packet commit when there are two scalar stores */
-void 

[PULL 14/17] Hexagon (target/hexagon) Change subtract from zero to change sign

2023-03-06 Thread Taylor Simpson
The F2_sffms instruction [r0 -= sfmpy(r1, r2)] doesn't properly
handle -0.  Previously we would negate the input operand by subtracting
from zero.  Instead, we negate by changing the sign bit.

Test case added to tests/tcg/hexagon/fpstuff.c

Signed-off-by: Taylor Simpson 
Reviewed-by: Anton Johansson 
Message-Id: <20230307025828.1612809-12-tsimp...@quicinc.com>
---
 target/hexagon/op_helper.c  |  2 +-
 tests/tcg/hexagon/fpstuff.c | 31 ++-
 2 files changed, 31 insertions(+), 2 deletions(-)

diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c
index 38b8aee193..9425941c69 100644
--- a/target/hexagon/op_helper.c
+++ b/target/hexagon/op_helper.c
@@ -1169,7 +1169,7 @@ float32 HELPER(sffms)(CPUHexagonState *env, float32 RxV,
 {
 float32 neg_RsV;
 arch_fpop_start(env);
-neg_RsV = float32_sub(float32_zero, RsV, >fp_status);
+neg_RsV = float32_set_sign(RsV, float32_is_neg(RsV) ? 0 : 1);
 RxV = internal_fmafx(neg_RsV, RtV, RxV, 0, >fp_status);
 arch_fpop_end(env);
 return RxV;
diff --git a/tests/tcg/hexagon/fpstuff.c b/tests/tcg/hexagon/fpstuff.c
index 56bf562a40..90ce9a6ef3 100644
--- a/tests/tcg/hexagon/fpstuff.c
+++ b/tests/tcg/hexagon/fpstuff.c
@@ -1,5 +1,5 @@
 /*
- *  Copyright(c) 2020-2022 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
+ *  Copyright(c) 2020-2023 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -40,6 +40,7 @@ const int SF_HEX_NAN =0x;
 const int SF_small_neg =  0xab98fba8;
 const int SF_denorm = 0x0001;
 const int SF_random = 0x346001d6;
+const int SF_neg_zero =   0x8000;
 
 const long long DF_QNaN = 0x7ff8ULL;
 const long long DF_SNaN = 0x7ff7ULL;
@@ -536,6 +537,33 @@ static void check_sffixupd(void)
 check32(result, 0x146001d6);
 }
 
+static void check_sffms(void)
+{
+int result;
+
+/* Check that sffms properly deals with -0 */
+result = SF_neg_zero;
+asm ("%0 -= sfmpy(%1 , %2)\n\t"
+: "+r"(result)
+: "r"(SF_ZERO), "r"(SF_ZERO)
+: "r12", "r8");
+check32(result, SF_neg_zero);
+
+result = SF_ZERO;
+asm ("%0 -= sfmpy(%1 , %2)\n\t"
+: "+r"(result)
+: "r"(SF_neg_zero), "r"(SF_ZERO)
+: "r12", "r8");
+check32(result, SF_ZERO);
+
+result = SF_ZERO;
+asm ("%0 -= sfmpy(%1 , %2)\n\t"
+: "+r"(result)
+: "r"(SF_ZERO), "r"(SF_neg_zero)
+: "r12", "r8");
+check32(result, SF_ZERO);
+}
+
 static void check_float2int_convs()
 {
 int res32;
@@ -688,6 +716,7 @@ int main()
 check_invsqrta();
 check_sffixupn();
 check_sffixupd();
+check_sffms();
 check_float2int_convs();
 
 puts(err ? "FAIL" : "PASS");
-- 
2.25.1



[PULL 09/17] Hexagon (target/hexagon) Don't set pkt_has_store_s1 when not needed

2023-03-06 Thread Taylor Simpson
The pkt_has_store_s1 field in CPUHexagonState is only needed in generated
helpers for scalar load instructions.  See check_noshuf and mem_load[1248]
in op_helper.c.

We add logic in gen_analyze_funcs.py to set need_pkt_has_store_s1 in
DisasContext when it is needed at runtime.

Signed-off-by: Taylor Simpson 
Reviewed-by: Anton Johansson 
Message-Id: <20230307025828.1612809-7-tsimp...@quicinc.com>
---
 target/hexagon/translate.h  | 1 +
 target/hexagon/attribs_def.h.inc| 1 +
 target/hexagon/translate.c  | 6 +-
 target/hexagon/gen_analyze_funcs.py | 5 +
 target/hexagon/hex_common.py| 1 +
 5 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/target/hexagon/translate.h b/target/hexagon/translate.h
index d45d3a4bb0..34368b2186 100644
--- a/target/hexagon/translate.h
+++ b/target/hexagon/translate.h
@@ -61,6 +61,7 @@ typedef struct DisasContext {
 TCGCond branch_cond;
 target_ulong branch_dest;
 bool is_tight_loop;
+bool need_pkt_has_store_s1;
 } DisasContext;
 
 static inline void ctx_log_pred_write(DisasContext *ctx, int pnum)
diff --git a/target/hexagon/attribs_def.h.inc b/target/hexagon/attribs_def.h.inc
index 5d2a102c18..9874d1658f 100644
--- a/target/hexagon/attribs_def.h.inc
+++ b/target/hexagon/attribs_def.h.inc
@@ -44,6 +44,7 @@ DEF_ATTRIB(MEMSIZE_1B, "Memory width is 1 byte", "", "")
 DEF_ATTRIB(MEMSIZE_2B, "Memory width is 2 bytes", "", "")
 DEF_ATTRIB(MEMSIZE_4B, "Memory width is 4 bytes", "", "")
 DEF_ATTRIB(MEMSIZE_8B, "Memory width is 8 bytes", "", "")
+DEF_ATTRIB(SCALAR_LOAD, "Load is scalar", "", "")
 DEF_ATTRIB(SCALAR_STORE, "Store is scalar", "", "")
 DEF_ATTRIB(REGWRSIZE_1B, "Memory width is 1 byte", "", "")
 DEF_ATTRIB(REGWRSIZE_2B, "Memory width is 2 bytes", "", "")
diff --git a/target/hexagon/translate.c b/target/hexagon/translate.c
index 9e5fcee1ee..01671d5451 100644
--- a/target/hexagon/translate.c
+++ b/target/hexagon/translate.c
@@ -333,6 +333,7 @@ static void mark_implicit_pred_writes(DisasContext *ctx)
 static void analyze_packet(DisasContext *ctx)
 {
 Packet *pkt = ctx->pkt;
+ctx->need_pkt_has_store_s1 = false;
 for (int i = 0; i < pkt->num_insns; i++) {
 Insn *insn = >insn[i];
 ctx->insn = insn;
@@ -367,12 +368,15 @@ static void gen_start_packet(DisasContext *ctx)
 for (i = 0; i < STORES_MAX; i++) {
 ctx->store_width[i] = 0;
 }
-tcg_gen_movi_tl(hex_pkt_has_store_s1, pkt->pkt_has_store_s1);
 ctx->s1_store_processed = false;
 ctx->pre_commit = true;
 
 analyze_packet(ctx);
 
+if (ctx->need_pkt_has_store_s1) {
+tcg_gen_movi_tl(hex_pkt_has_store_s1, pkt->pkt_has_store_s1);
+}
+
 /*
  * pregs_written is used both in the analyze phase as well as the code
  * gen phase, so clear it again.
diff --git a/target/hexagon/gen_analyze_funcs.py 
b/target/hexagon/gen_analyze_funcs.py
index 37c166dc0d..7e1f221b3c 100755
--- a/target/hexagon/gen_analyze_funcs.py
+++ b/target/hexagon/gen_analyze_funcs.py
@@ -200,6 +200,11 @@ def gen_analyze_func(f, tag, regs, imms):
 analyze_opn(f, tag, regtype, regid, toss, numregs, i)
 i += 1
 
+has_generated_helper = (not hex_common.skip_qemu_helper(tag) and
+not hex_common.is_idef_parser_enabled(tag))
+if (has_generated_helper and
+'A_SCALAR_LOAD' in hex_common.attribdict[tag]):
+f.write("ctx->need_pkt_has_store_s1 = true;\n")
 
 f.write("}\n\n")
 
diff --git a/target/hexagon/hex_common.py b/target/hexagon/hex_common.py
index a29f61bb4f..76da362c11 100755
--- a/target/hexagon/hex_common.py
+++ b/target/hexagon/hex_common.py
@@ -89,6 +89,7 @@ def calculate_attribs():
 add_qemu_macro_attrib('fWRITE_P3', 'A_WRITES_PRED_REG')
 add_qemu_macro_attrib('fSET_OVERFLOW', 'A_IMPLICIT_WRITES_USR')
 add_qemu_macro_attrib('fSET_LPCFG', 'A_IMPLICIT_WRITES_USR')
+add_qemu_macro_attrib('fLOAD', 'A_SCALAR_LOAD')
 add_qemu_macro_attrib('fSTORE', 'A_SCALAR_STORE')
 
 # Recurse down macros, find attributes from sub-macros
-- 
2.25.1



[PULL 07/17] Hexagon (target/hexagon) Add overrides for dealloc-return instructions

2023-03-06 Thread Taylor Simpson
These instructions perform a deallocframe+return (jumpr r31)

Add overrides for
L4_return
SL2_return
L4_return_t
L4_return_f
L4_return_tnew_pt
L4_return_fnew_pt
L4_return_tnew_pnt
L4_return_fnew_pnt
SL2_return_t
SL2_return_f
SL2_return_tnew
SL2_return_fnew

This patch eliminates the last helper that uses write_new_pc, so we
remove it from op_helper.c

Signed-off-by: Taylor Simpson 
Reviewed-by: Anton Johansson 
Message-Id: <20230307025828.1612809-5-tsimp...@quicinc.com>
---
 target/hexagon/gen_tcg.h   | 53 ++
 target/hexagon/genptr.c| 77 ++
 target/hexagon/op_helper.c | 26 +
 3 files changed, 131 insertions(+), 25 deletions(-)

diff --git a/target/hexagon/gen_tcg.h b/target/hexagon/gen_tcg.h
index 5b7263a82c..e72672e198 100644
--- a/target/hexagon/gen_tcg.h
+++ b/target/hexagon/gen_tcg.h
@@ -491,6 +491,59 @@
 #define fGEN_TCG_S2_storerinew_pcr(SHORTCODE) \
 fGEN_TCG_STORE_pcr(2, fSTORE(1, 4, EA, NtN))
 
+/*
+ * dealloc_return
+ * Assembler mapped to
+ * r31:30 = dealloc_return(r30):raw
+ */
+#define fGEN_TCG_L4_return(SHORTCODE) \
+gen_return(ctx, RddV, RsV)
+
+/*
+ * sub-instruction version (no RddV, so handle it manually)
+ */
+#define fGEN_TCG_SL2_return(SHORTCODE) \
+do { \
+TCGv_i64 RddV = tcg_temp_new_i64(); \
+gen_return(ctx, RddV, hex_gpr[HEX_REG_FP]); \
+gen_log_reg_write_pair(HEX_REG_FP, RddV); \
+} while (0)
+
+/*
+ * Conditional returns follow this naming convention
+ * _t predicate true
+ * _f predicate false
+ * _tnew_pt   predicate.new true predict taken
+ * _fnew_pt   predicate.new false predict taken
+ * _tnew_pnt  predicate.new true predict not taken
+ * _fnew_pnt  predicate.new false predict not taken
+ * Predictions are not modelled in QEMU
+ *
+ * Example:
+ * if (p1) r31:30 = dealloc_return(r30):raw
+ */
+#define fGEN_TCG_L4_return_t(SHORTCODE) \
+gen_cond_return(ctx, RddV, RsV, PvV, TCG_COND_EQ);
+#define fGEN_TCG_L4_return_f(SHORTCODE) \
+gen_cond_return(ctx, RddV, RsV, PvV, TCG_COND_NE)
+#define fGEN_TCG_L4_return_tnew_pt(SHORTCODE) \
+gen_cond_return(ctx, RddV, RsV, PvN, TCG_COND_EQ)
+#define fGEN_TCG_L4_return_fnew_pt(SHORTCODE) \
+gen_cond_return(ctx, RddV, RsV, PvN, TCG_COND_NE)
+#define fGEN_TCG_L4_return_tnew_pnt(SHORTCODE) \
+gen_cond_return(ctx, RddV, RsV, PvN, TCG_COND_EQ)
+#define fGEN_TCG_L4_return_fnew_pnt(SHORTCODE) \
+gen_cond_return(ctx, RddV, RsV, PvN, TCG_COND_NE)
+
+#define fGEN_TCG_SL2_return_t(SHORTCODE) \
+gen_cond_return_subinsn(ctx, TCG_COND_EQ, hex_pred[0])
+#define fGEN_TCG_SL2_return_f(SHORTCODE) \
+gen_cond_return_subinsn(ctx, TCG_COND_NE, hex_pred[0])
+#define fGEN_TCG_SL2_return_tnew(SHORTCODE) \
+gen_cond_return_subinsn(ctx, TCG_COND_EQ, hex_new_pred_value[0])
+#define fGEN_TCG_SL2_return_fnew(SHORTCODE) \
+gen_cond_return_subinsn(ctx, TCG_COND_NE, hex_new_pred_value[0])
+
 /*
  * Mathematical operations with more than one definition require
  * special handling
diff --git a/target/hexagon/genptr.c b/target/hexagon/genptr.c
index f7017fd483..3490310812 100644
--- a/target/hexagon/genptr.c
+++ b/target/hexagon/genptr.c
@@ -715,6 +715,83 @@ static void gen_cond_callr(DisasContext *ctx,
 gen_set_label(skip);
 }
 
+/* frame ^= (int64_t)FRAMEKEY << 32 */
+static void gen_frame_unscramble(TCGv_i64 frame)
+{
+TCGv_i64 framekey = tcg_temp_new_i64();
+tcg_gen_extu_i32_i64(framekey, hex_gpr[HEX_REG_FRAMEKEY]);
+tcg_gen_shli_i64(framekey, framekey, 32);
+tcg_gen_xor_i64(frame, frame, framekey);
+}
+
+static void gen_load_frame(DisasContext *ctx, TCGv_i64 frame, TCGv EA)
+{
+Insn *insn = ctx->insn;  /* Needed for CHECK_NOSHUF */
+CHECK_NOSHUF(EA, 8);
+tcg_gen_qemu_ld64(frame, EA, ctx->mem_idx);
+}
+
+static void gen_return_base(DisasContext *ctx, TCGv_i64 dst, TCGv src,
+TCGv r29)
+{
+/*
+ * frame = *src
+ * dst = frame_unscramble(frame)
+ * SP = src + 8
+ * PC = dst.w[1]
+ */
+TCGv_i64 frame = tcg_temp_new_i64();
+TCGv r31 = tcg_temp_new();
+
+gen_load_frame(ctx, frame, src);
+gen_frame_unscramble(frame);
+tcg_gen_mov_i64(dst, frame);
+tcg_gen_addi_tl(r29, src, 8);
+tcg_gen_extrh_i64_i32(r31, dst);
+gen_jumpr(ctx, r31);
+}
+
+static void gen_return(DisasContext *ctx, TCGv_i64 dst, TCGv src)
+{
+TCGv r29 = tcg_temp_new();
+gen_return_base(ctx, dst, src, r29);
+gen_log_reg_write(HEX_REG_SP, r29);
+}
+
+/* if (pred) dst = dealloc_return(src):raw */
+static void gen_cond_return(DisasContext *ctx, TCGv_i64 dst, TCGv src,
+TCGv pred, TCGCond cond)
+{
+TCGv LSB = tcg_temp_new();
+TCGv mask = tcg_temp_new();
+TCGv r29 = tcg_temp_new();
+TCGLabel *skip = gen_new_label();
+tcg_gen_andi_tl(LSB, pred, 1);
+
+   

[PULL 08/17] Hexagon (target/hexagon) Analyze packet before generating TCG

2023-03-06 Thread Taylor Simpson
We create a new generator that creates an analyze_ function for
each instruction.  Currently, these functions record the writes to
R, P, and C registers by calling ctx_log_reg_write[_pair] or
ctx_log_pred_write.

During gen_start_packet, we invoke the analyze_ function for
each instruction in the packet, and we mark the implicit register
and predicate writes.

Doing the analysis up front has several advantages
- We remove calls to ctx_log_* from gen_tcg_funcs.py and genptr.c
- After the analysis is performed, we can initialize hex_new_value
  for each of the predicated assignments rather than during TCG
  generation for the instructions
- This is a stepping stone for future work where the analysis will
  include the set of registers that are read.  In cases where
  the packet doesn't have an overlap between the registers that are
  written and registers that are read, we can avoid the intermediate
  step of writing to hex_new_value.  Note that other checks will also
  be needed (e.g., no instructions can raise an exception).

Signed-off-by: Taylor Simpson 
Reviewed-by: Anton Johansson 
Message-Id: <20230307025828.1612809-6-tsimp...@quicinc.com>
---
 target/hexagon/translate.h  |  46 ++--
 target/hexagon/genptr.c |   5 +-
 target/hexagon/idef-parser/parser-helpers.c |   7 +-
 target/hexagon/translate.c  | 162 +++--
 target/hexagon/README   |  10 +-
 target/hexagon/gen_analyze_funcs.py | 237 
 target/hexagon/gen_tcg_funcs.py |  23 +-
 target/hexagon/meson.build  |  11 +-
 8 files changed, 383 insertions(+), 118 deletions(-)
 create mode 100755 target/hexagon/gen_analyze_funcs.py

diff --git a/target/hexagon/translate.h b/target/hexagon/translate.h
index d971f4f095..d45d3a4bb0 100644
--- a/target/hexagon/translate.h
+++ b/target/hexagon/translate.h
@@ -1,5 +1,5 @@
 /*
- *  Copyright(c) 2019-2022 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
+ *  Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -38,6 +38,7 @@ typedef struct DisasContext {
 int reg_log[REG_WRITES_MAX];
 int reg_log_idx;
 DECLARE_BITMAP(regs_written, TOTAL_PER_THREAD_REGS);
+DECLARE_BITMAP(predicated_regs, TOTAL_PER_THREAD_REGS);
 int preg_log[PRED_WRITES_MAX];
 int preg_log_idx;
 DECLARE_BITMAP(pregs_written, NUM_PREGS);
@@ -62,32 +63,39 @@ typedef struct DisasContext {
 bool is_tight_loop;
 } DisasContext;
 
-static inline void ctx_log_reg_write(DisasContext *ctx, int rnum)
+static inline void ctx_log_pred_write(DisasContext *ctx, int pnum)
 {
-if (test_bit(rnum, ctx->regs_written)) {
-HEX_DEBUG_LOG("WARNING: Multiple writes to r%d\n", rnum);
+if (!test_bit(pnum, ctx->pregs_written)) {
+ctx->preg_log[ctx->preg_log_idx] = pnum;
+ctx->preg_log_idx++;
+set_bit(pnum, ctx->pregs_written);
 }
-ctx->reg_log[ctx->reg_log_idx] = rnum;
-ctx->reg_log_idx++;
-set_bit(rnum, ctx->regs_written);
-}
-
-static inline void ctx_log_reg_write_pair(DisasContext *ctx, int rnum)
-{
-ctx_log_reg_write(ctx, rnum);
-ctx_log_reg_write(ctx, rnum + 1);
 }
 
-static inline void ctx_log_pred_write(DisasContext *ctx, int pnum)
+static inline void ctx_log_reg_write(DisasContext *ctx, int rnum,
+ bool is_predicated)
 {
-ctx->preg_log[ctx->preg_log_idx] = pnum;
-ctx->preg_log_idx++;
-set_bit(pnum, ctx->pregs_written);
+if (rnum == HEX_REG_P3_0_ALIASED) {
+for (int i = 0; i < NUM_PREGS; i++) {
+ctx_log_pred_write(ctx, i);
+}
+} else {
+if (!test_bit(rnum, ctx->regs_written)) {
+ctx->reg_log[ctx->reg_log_idx] = rnum;
+ctx->reg_log_idx++;
+set_bit(rnum, ctx->regs_written);
+}
+if (is_predicated) {
+set_bit(rnum, ctx->predicated_regs);
+}
+}
 }
 
-static inline bool is_preloaded(DisasContext *ctx, int num)
+static inline void ctx_log_reg_write_pair(DisasContext *ctx, int rnum,
+  bool is_predicated)
 {
-return test_bit(num, ctx->regs_written);
+ctx_log_reg_write(ctx, rnum, is_predicated);
+ctx_log_reg_write(ctx, rnum + 1, is_predicated);
 }
 
 static inline bool is_vreg_preloaded(DisasContext *ctx, int num)
diff --git a/target/hexagon/genptr.c b/target/hexagon/genptr.c
index 3490310812..61ab9af9e4 100644
--- a/target/hexagon/genptr.c
+++ b/target/hexagon/genptr.c
@@ -180,6 +180,7 @@ void gen_log_pred_write(DisasContext *ctx, int pnum, TCGv 
val)
hex_new_pred_value[pnum], base_val);
 }
 tcg_gen_ori_tl(hex_pred_written, hex_pred_written, 1 << pnum);
+set_bit(pnum, ctx->pregs_written);
 }
 
 static inline void 

[PULL 12/17] Hexagon (tests/tcg/hexagon) Remove __builtin from scatter_gather

2023-03-06 Thread Taylor Simpson
Replace __builtin_* with inline assembly
The __builtin's are subject to change with different compiler
releases, so might break
Mark arrays as aligned when accessed as HVX vectors
Clean up comments

Signed-off-by: Taylor Simpson 
Reviewed-by: Anton Johansson 
Message-Id: <20230307025828.1612809-10-tsimp...@quicinc.com>
---
 tests/tcg/hexagon/scatter_gather.c | 513 +++--
 1 file changed, 271 insertions(+), 242 deletions(-)

diff --git a/tests/tcg/hexagon/scatter_gather.c 
b/tests/tcg/hexagon/scatter_gather.c
index b93eb18133..bf8b5e0317 100644
--- a/tests/tcg/hexagon/scatter_gather.c
+++ b/tests/tcg/hexagon/scatter_gather.c
@@ -1,5 +1,5 @@
 /*
- *  Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
+ *  Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -40,47 +40,6 @@ typedef long HVX_VectorPair   
__attribute__((__vector_size__(256)))
 typedef long HVX_VectorPred   __attribute__((__vector_size__(128)))
   __attribute__((aligned(128)));
 
-#define VSCATTER_16(BASE, RGN, OFF, VALS) \
-__builtin_HEXAGON_V6_vscattermh_128B((int)BASE, RGN, OFF, VALS)
-#define VSCATTER_16_MASKED(MASK, BASE, RGN, OFF, VALS) \
-__builtin_HEXAGON_V6_vscattermhq_128B(MASK, (int)BASE, RGN, OFF, VALS)
-#define VSCATTER_32(BASE, RGN, OFF, VALS) \
-__builtin_HEXAGON_V6_vscattermw_128B((int)BASE, RGN, OFF, VALS)
-#define VSCATTER_32_MASKED(MASK, BASE, RGN, OFF, VALS) \
-__builtin_HEXAGON_V6_vscattermwq_128B(MASK, (int)BASE, RGN, OFF, VALS)
-#define VSCATTER_16_32(BASE, RGN, OFF, VALS) \
-__builtin_HEXAGON_V6_vscattermhw_128B((int)BASE, RGN, OFF, VALS)
-#define VSCATTER_16_32_MASKED(MASK, BASE, RGN, OFF, VALS) \
-__builtin_HEXAGON_V6_vscattermhwq_128B(MASK, (int)BASE, RGN, OFF, VALS)
-#define VSCATTER_16_ACC(BASE, RGN, OFF, VALS) \
-__builtin_HEXAGON_V6_vscattermh_add_128B((int)BASE, RGN, OFF, VALS)
-#define VSCATTER_32_ACC(BASE, RGN, OFF, VALS) \
-__builtin_HEXAGON_V6_vscattermw_add_128B((int)BASE, RGN, OFF, VALS)
-#define VSCATTER_16_32_ACC(BASE, RGN, OFF, VALS) \
-__builtin_HEXAGON_V6_vscattermhw_add_128B((int)BASE, RGN, OFF, VALS)
-
-#define VGATHER_16(DSTADDR, BASE, RGN, OFF) \
-__builtin_HEXAGON_V6_vgathermh_128B(DSTADDR, (int)BASE, RGN, OFF)
-#define VGATHER_16_MASKED(DSTADDR, MASK, BASE, RGN, OFF) \
-__builtin_HEXAGON_V6_vgathermhq_128B(DSTADDR, MASK, (int)BASE, RGN, OFF)
-#define VGATHER_32(DSTADDR, BASE, RGN, OFF) \
-__builtin_HEXAGON_V6_vgathermw_128B(DSTADDR, (int)BASE, RGN, OFF)
-#define VGATHER_32_MASKED(DSTADDR, MASK, BASE, RGN, OFF) \
-__builtin_HEXAGON_V6_vgathermwq_128B(DSTADDR, MASK, (int)BASE, RGN, OFF)
-#define VGATHER_16_32(DSTADDR, BASE, RGN, OFF) \
-__builtin_HEXAGON_V6_vgathermhw_128B(DSTADDR, (int)BASE, RGN, OFF)
-#define VGATHER_16_32_MASKED(DSTADDR, MASK, BASE, RGN, OFF) \
-__builtin_HEXAGON_V6_vgathermhwq_128B(DSTADDR, MASK, (int)BASE, RGN, OFF)
-
-#define VSHUFF_H(V) \
-__builtin_HEXAGON_V6_vshuffh_128B(V)
-#define VSPLAT_H(X) \
-__builtin_HEXAGON_V6_lvsplath_128B(X)
-#define VAND_VAL(PRED, VAL) \
-__builtin_HEXAGON_V6_vandvrt_128B(PRED, VAL)
-#define VDEAL_H(V) \
-__builtin_HEXAGON_V6_vdealh_128B(V)
-
 int err;
 
 /* define the number of rows/cols in a square matrix */
@@ -108,22 +67,22 @@ unsigned short vscatter16_32_ref[SCATTER_BUFFER_SIZE];
 unsigned short vgather16_32_ref[MATRIX_SIZE];
 
 /* declare the arrays of offsets */
-unsigned short half_offsets[MATRIX_SIZE];
-unsigned int   word_offsets[MATRIX_SIZE];
+unsigned short half_offsets[MATRIX_SIZE] __attribute__((aligned(128)));
+unsigned int   word_offsets[MATRIX_SIZE] __attribute__((aligned(128)));
 
 /* declare the arrays of values */
-unsigned short half_values[MATRIX_SIZE];
-unsigned short half_values_acc[MATRIX_SIZE];
-unsigned short half_values_masked[MATRIX_SIZE];
-unsigned int   word_values[MATRIX_SIZE];
-unsigned int   word_values_acc[MATRIX_SIZE];
-unsigned int   word_values_masked[MATRIX_SIZE];
+unsigned short half_values[MATRIX_SIZE] __attribute__((aligned(128)));
+unsigned short half_values_acc[MATRIX_SIZE] __attribute__((aligned(128)));
+unsigned short half_values_masked[MATRIX_SIZE] __attribute__((aligned(128)));
+unsigned int   word_values[MATRIX_SIZE] __attribute__((aligned(128)));
+unsigned int   word_values_acc[MATRIX_SIZE] __attribute__((aligned(128)));
+unsigned int   word_values_masked[MATRIX_SIZE] __attribute__((aligned(128)));
 
 /* declare the arrays of predicates */
-unsigned short half_predicates[MATRIX_SIZE];
-unsigned int   word_predicates[MATRIX_SIZE];
+unsigned short half_predicates[MATRIX_SIZE] __attribute__((aligned(128)));
+unsigned int   word_predicates[MATRIX_SIZE] __attribute__((aligned(128)));
 
-/* make this big enough for all the intrinsics */
+/* make this big enough for 

[PULL 04/17] Hexagon (target/hexagon) Add overrides for jumpr31 instructions

2023-03-06 Thread Taylor Simpson
Add overrides for
SL2_jumpr31Unconditional
SL2_jumpr31_t  Predicated true (old value)
SL2_jumpr31_f  Predicated false (old value)
SL2_jumpr31_tnew   Predicated true (new value)
SL2_jumpr31_fnew   Predicated false (new value)

Signed-off-by: Taylor Simpson 
Reviewed-by: Anton Johansson 
Message-Id: <20230307025828.1612809-2-tsimp...@quicinc.com>
---
 target/hexagon/gen_tcg.h | 15 ++-
 target/hexagon/genptr.c  |  9 -
 2 files changed, 22 insertions(+), 2 deletions(-)

diff --git a/target/hexagon/gen_tcg.h b/target/hexagon/gen_tcg.h
index b1955a08f0..f898f5b389 100644
--- a/target/hexagon/gen_tcg.h
+++ b/target/hexagon/gen_tcg.h
@@ -1,5 +1,5 @@
 /*
- *  Copyright(c) 2019-2022 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
+ *  Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -986,6 +986,19 @@
 #define fGEN_TCG_S2_asl_r_r_sat(SHORTCODE) \
 gen_asl_r_r_sat(RdV, RsV, RtV)
 
+#define fGEN_TCG_SL2_jumpr31(SHORTCODE) \
+gen_jumpr(ctx, hex_gpr[HEX_REG_LR])
+
+#define fGEN_TCG_SL2_jumpr31_t(SHORTCODE) \
+gen_cond_jumpr31(ctx, TCG_COND_EQ, hex_pred[0])
+#define fGEN_TCG_SL2_jumpr31_f(SHORTCODE) \
+gen_cond_jumpr31(ctx, TCG_COND_NE, hex_pred[0])
+
+#define fGEN_TCG_SL2_jumpr31_tnew(SHORTCODE) \
+gen_cond_jumpr31(ctx, TCG_COND_EQ, hex_new_pred_value[0])
+#define fGEN_TCG_SL2_jumpr31_fnew(SHORTCODE) \
+gen_cond_jumpr31(ctx, TCG_COND_NE, hex_new_pred_value[0])
+
 /* Floating point */
 #define fGEN_TCG_F2_conv_sf2df(SHORTCODE) \
 gen_helper_conv_sf2df(RddV, cpu_env, RsV)
diff --git a/target/hexagon/genptr.c b/target/hexagon/genptr.c
index 86bd093ce8..2bbe4e3a68 100644
--- a/target/hexagon/genptr.c
+++ b/target/hexagon/genptr.c
@@ -1,5 +1,5 @@
 /*
- *  Copyright(c) 2019-2022 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
+ *  Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -571,6 +571,13 @@ static void gen_cond_jumpr(DisasContext *ctx, TCGv dst_pc,
 gen_write_new_pc_addr(ctx, dst_pc, cond, pred);
 }
 
+static void gen_cond_jumpr31(DisasContext *ctx, TCGCond cond, TCGv pred)
+{
+TCGv LSB = tcg_temp_new();
+tcg_gen_andi_tl(LSB, pred, 1);
+gen_cond_jumpr(ctx, hex_gpr[HEX_REG_LR], cond, LSB);
+}
+
 static void gen_cond_jump(DisasContext *ctx, TCGCond cond, TCGv pred,
   int pc_off)
 {
-- 
2.25.1



[PULL 01/17] Hexagon (target/hexagon) Restore --disable-hexagon-idef-parser build

2023-03-06 Thread Taylor Simpson
The --disable-hexagon-idef-parser configuration was broken by this patch
2feacf60c23ba6 (target/hexagon: Drop tcg_temp_free from C code)

That config is not tested by CI

Fix is simple: Mark a few TCGv variables as unused

Signed-off-by: Taylor Simpson 
Reviewed-by: Anton Johansson 
Message-Id: <20230306172515.346813-1-tsimp...@quicinc.com>
---
 target/hexagon/gen_tcg.h | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/target/hexagon/gen_tcg.h b/target/hexagon/gen_tcg.h
index b2e7880b5c..b1955a08f0 100644
--- a/target/hexagon/gen_tcg.h
+++ b/target/hexagon/gen_tcg.h
@@ -419,16 +419,16 @@
 
 #define fGEN_TCG_STORE(SHORTCODE) \
 do { \
-TCGv HALF = tcg_temp_new(); \
-TCGv BYTE = tcg_temp_new(); \
+TCGv HALF G_GNUC_UNUSED = tcg_temp_new(); \
+TCGv BYTE G_GNUC_UNUSED = tcg_temp_new(); \
 SHORTCODE; \
 } while (0)
 
 #define fGEN_TCG_STORE_pcr(SHIFT, STORE) \
 do { \
 TCGv ireg = tcg_temp_new(); \
-TCGv HALF = tcg_temp_new(); \
-TCGv BYTE = tcg_temp_new(); \
+TCGv HALF G_GNUC_UNUSED = tcg_temp_new(); \
+TCGv BYTE G_GNUC_UNUSED = tcg_temp_new(); \
 tcg_gen_mov_tl(EA, RxV); \
 gen_read_ireg(ireg, MuV, SHIFT); \
 gen_helper_fcircadd(RxV, RxV, ireg, MuV, hex_gpr[HEX_REG_CS0 + MuN]); \
-- 
2.25.1



[PULL 10/17] Hexagon (target/hexagon) Analyze packet for HVX

2023-03-06 Thread Taylor Simpson
Extend the analyze_ functions for HVX vector and predicate writes
Remove calls to ctx_log_vreg_write[_pair] from gen_tcg_funcs.py
During gen_start_packet, reload the predicated HVX registers into
fugure_VRegs and tmp_VRegs

Signed-off-by: Taylor Simpson 
Reviewed-by: Anton Johansson 
Message-Id: <20230307025828.1612809-8-tsimp...@quicinc.com>
---
 target/hexagon/translate.h  | 14 --
 target/hexagon/translate.c  | 30 +
 target/hexagon/gen_analyze_funcs.py | 17 +---
 target/hexagon/gen_tcg_funcs.py | 18 -
 4 files changed, 52 insertions(+), 27 deletions(-)

diff --git a/target/hexagon/translate.h b/target/hexagon/translate.h
index 34368b2186..765f2c6a22 100644
--- a/target/hexagon/translate.h
+++ b/target/hexagon/translate.h
@@ -54,6 +54,8 @@ typedef struct DisasContext {
 DECLARE_BITMAP(vregs_updated_tmp, NUM_VREGS);
 DECLARE_BITMAP(vregs_updated, NUM_VREGS);
 DECLARE_BITMAP(vregs_select, NUM_VREGS);
+DECLARE_BITMAP(predicated_future_vregs, NUM_VREGS);
+DECLARE_BITMAP(predicated_tmp_vregs, NUM_VREGS);
 int qreg_log[NUM_QREGS];
 bool qreg_is_predicated[NUM_QREGS];
 int qreg_log_idx;
@@ -99,12 +101,6 @@ static inline void ctx_log_reg_write_pair(DisasContext 
*ctx, int rnum,
 ctx_log_reg_write(ctx, rnum + 1, is_predicated);
 }
 
-static inline bool is_vreg_preloaded(DisasContext *ctx, int num)
-{
-return test_bit(num, ctx->vregs_updated) ||
-   test_bit(num, ctx->vregs_updated_tmp);
-}
-
 intptr_t ctx_future_vreg_off(DisasContext *ctx, int regnum,
  int num, bool alloc_ok);
 intptr_t ctx_tmp_vreg_off(DisasContext *ctx, int regnum,
@@ -120,12 +116,18 @@ static inline void ctx_log_vreg_write(DisasContext *ctx,
 ctx->vreg_log_idx++;
 
 set_bit(rnum, ctx->vregs_updated);
+if (is_predicated) {
+set_bit(rnum, ctx->predicated_future_vregs);
+}
 }
 if (type == EXT_NEW) {
 set_bit(rnum, ctx->vregs_select);
 }
 if (type == EXT_TMP) {
 set_bit(rnum, ctx->vregs_updated_tmp);
+if (is_predicated) {
+set_bit(rnum, ctx->predicated_tmp_vregs);
+}
 }
 }
 
diff --git a/target/hexagon/translate.c b/target/hexagon/translate.c
index 01671d5451..493bc75d27 100644
--- a/target/hexagon/translate.c
+++ b/target/hexagon/translate.c
@@ -364,6 +364,8 @@ static void gen_start_packet(DisasContext *ctx)
 bitmap_zero(ctx->vregs_updated_tmp, NUM_VREGS);
 bitmap_zero(ctx->vregs_updated, NUM_VREGS);
 bitmap_zero(ctx->vregs_select, NUM_VREGS);
+bitmap_zero(ctx->predicated_future_vregs, NUM_VREGS);
+bitmap_zero(ctx->predicated_tmp_vregs, NUM_VREGS);
 ctx->qreg_log_idx = 0;
 for (i = 0; i < STORES_MAX; i++) {
 ctx->store_width[i] = 0;
@@ -415,6 +417,34 @@ static void gen_start_packet(DisasContext *ctx)
 }
 }
 
+/* Preload the predicated HVX registers into future_VRegs and tmp_VRegs */
+if (!bitmap_empty(ctx->predicated_future_vregs, NUM_VREGS)) {
+int i = find_first_bit(ctx->predicated_future_vregs, NUM_VREGS);
+while (i < NUM_VREGS) {
+const intptr_t VdV_off =
+ctx_future_vreg_off(ctx, i, 1, true);
+intptr_t src_off = offsetof(CPUHexagonState, VRegs[i]);
+tcg_gen_gvec_mov(MO_64, VdV_off,
+ src_off,
+ sizeof(MMVector),
+ sizeof(MMVector));
+i = find_next_bit(ctx->predicated_future_vregs, NUM_VREGS, i + 1);
+}
+}
+if (!bitmap_empty(ctx->predicated_tmp_vregs, NUM_VREGS)) {
+int i = find_first_bit(ctx->predicated_tmp_vregs, NUM_VREGS);
+while (i < NUM_VREGS) {
+const intptr_t VdV_off =
+ctx_tmp_vreg_off(ctx, i, 1, true);
+intptr_t src_off = offsetof(CPUHexagonState, VRegs[i]);
+tcg_gen_gvec_mov(MO_64, VdV_off,
+ src_off,
+ sizeof(MMVector),
+ sizeof(MMVector));
+i = find_next_bit(ctx->predicated_tmp_vregs, NUM_VREGS, i + 1);
+}
+}
+
 if (pkt->pkt_has_hvx) {
 tcg_gen_movi_tl(hex_VRegs_updated, 0);
 tcg_gen_movi_tl(hex_QRegs_updated, 0);
diff --git a/target/hexagon/gen_analyze_funcs.py 
b/target/hexagon/gen_analyze_funcs.py
index 7e1f221b3c..0bb4fcb476 100755
--- a/target/hexagon/gen_analyze_funcs.py
+++ b/target/hexagon/gen_analyze_funcs.py
@@ -83,9 +83,16 @@ def analyze_opn_old(f, tag, regtype, regid, regno):
 else:
 print("Bad register parse: ", regtype, regid)
 elif (regtype == "V"):
+newv = "EXT_DFL"
+if (hex_common.is_new_result(tag)):
+newv = "EXT_NEW"
+elif (hex_common.is_tmp_result(tag)):
+newv = "EXT_TMP"
 if (regid in {"dd", "xx"}):
-f.write("//const 

Re: [PATCH v2 3/3] qapi: allow unions to contain further unions

2023-03-06 Thread Het Gala

Hi,


On 23/02/23 7:10 pm, Daniel P. Berrangé wrote:

This extends the QAPI schema validation to permit unions inside unions,
provided the checks for clashing fields pass.

Signed-off-by: Daniel P. Berrangé 
---
  scripts/qapi/schema.py|  6 +-
  tests/qapi-schema/meson.build |  2 +
  tests/qapi-schema/qapi-schema-test.json   | 32 ++
  tests/qapi-schema/qapi-schema-test.out| 29 ++
  .../union-invalid-union-subfield.err  |  2 +
  .../union-invalid-union-subfield.json | 30 ++
  .../union-invalid-union-subfield.out  |  0
  .../union-invalid-union-subtype.err   |  2 +
  .../union-invalid-union-subtype.json  | 29 ++
  .../union-invalid-union-subtype.out   |  0
  tests/unit/test-qobject-input-visitor.c   | 47 +++
  tests/unit/test-qobject-output-visitor.c  | 58 +++
  12 files changed, 234 insertions(+), 3 deletions(-)
  create mode 100644 tests/qapi-schema/union-invalid-union-subfield.err
  create mode 100644 tests/qapi-schema/union-invalid-union-subfield.json
  create mode 100644 tests/qapi-schema/union-invalid-union-subfield.out
  create mode 100644 tests/qapi-schema/union-invalid-union-subtype.err
  create mode 100644 tests/qapi-schema/union-invalid-union-subtype.json
  create mode 100644 tests/qapi-schema/union-invalid-union-subtype.out

diff --git a/scripts/qapi/schema.py b/scripts/qapi/schema.py
index 6c481ab0c0..5c4457f789 100644
--- a/scripts/qapi/schema.py
+++ b/scripts/qapi/schema.py
@@ -465,9 +465,10 @@ def check(self, schema):
  # on behalf of info, which is not necessarily self.info
  def check_clash(self, info, seen):
  assert self._checked
-assert not self.variants   # not implemented
  for m in self.members:
  m.check_clash(info, seen)
+if self.variants:
+self.variants.check_clash(info, seen)
  
  def connect_doc(self, doc=None):

  super().connect_doc(doc)
@@ -652,8 +653,7 @@ def check(self, schema, seen):
  self.info,
  "branch '%s' is not a value of %s"
  % (v.name, self.tag_member.type.describe()))
-if (not isinstance(v.type, QAPISchemaObjectType)
-or v.type.variants):
+if not isinstance(v.type, QAPISchemaObjectType):
  raise QAPISemError(
  self.info,
  "%s cannot use %s"
diff --git a/tests/qapi-schema/meson.build b/tests/qapi-schema/meson.build
index d85b14f28c..1591eb322b 100644
--- a/tests/qapi-schema/meson.build
+++ b/tests/qapi-schema/meson.build
@@ -194,6 +194,8 @@ schemas = [
'union-invalid-data.json',
'union-invalid-discriminator.json',
'union-invalid-if-discriminator.json',
+  'union-invalid-union-subfield.json',
+  'union-invalid-union-subtype.json',
'union-no-base.json',
'union-optional-discriminator.json',
'union-string-discriminator.json',
diff --git a/tests/qapi-schema/qapi-schema-test.json 
b/tests/qapi-schema/qapi-schema-test.json
index ba7302f42b..40f1a3d88d 100644
--- a/tests/qapi-schema/qapi-schema-test.json
+++ b/tests/qapi-schema/qapi-schema-test.json
@@ -114,6 +114,38 @@
  { 'struct': 'UserDefC',
'data': { 'string1': 'str', 'string2': 'str' } }
  
+# this tests that unions can contain other unions in their branches

+{ 'enum': 'TestUnionEnum',
+  'data': [ 'value-a', 'value-b' ] }
+
+{ 'enum': 'TestUnionEnumA',
+  'data': [ 'value-a1', 'value-a2' ] }
+
+{ 'struct': 'TestUnionTypeA1',
+  'data': { 'integer': 'int',
+'name': 'str'} }
+
+{ 'struct': 'TestUnionTypeA2',
+  'data': { 'integer': 'int',
+'size': 'int' } }
+
+{ 'union': 'TestUnionTypeA',
+  'base': { 'type-a': 'TestUnionEnumA' },
+  'discriminator': 'type-a',
+  'data': { 'value-a1': 'TestUnionTypeA1',
+'value-a2': 'TestUnionTypeA2' } }
+
+{ 'struct': 'TestUnionTypeB',
+  'data': { 'integer': 'int',
+'onoff': 'bool' } }
+
+{ 'union': 'TestUnionInUnion',
+  'base': { 'type': 'TestUnionEnum' },
+  'discriminator': 'type',
+  'data': { 'value-a': 'TestUnionTypeA',
+'value-b': 'TestUnionTypeB' } }
+
+
  # for testing use of 'number' within alternates
  { 'alternate': 'AltEnumBool', 'data': { 'e': 'EnumOne', 'b': 'bool' } }
  { 'alternate': 'AltEnumNum', 'data': { 'e': 'EnumOne', 'n': 'number' } }
diff --git a/tests/qapi-schema/qapi-schema-test.out 
b/tests/qapi-schema/qapi-schema-test.out
index 043d75c655..9fe1038944 100644
--- a/tests/qapi-schema/qapi-schema-test.out
+++ b/tests/qapi-schema/qapi-schema-test.out
@@ -105,6 +105,35 @@ alternate UserDefAlternate
  object UserDefC
  member string1: str optional=False
  member string2: str optional=False
+enum TestUnionEnum
+member value-a
+member value-b
+enum TestUnionEnumA
+member value-a1
+member value-a2
+object 

[PATCH v3 1/1] hw/riscv: Add signature dump function for spike to run ACT tests

2023-03-06 Thread Weiwei Li
Add signature and signature-granularity properties in spike to specify the 
target
signatrue file and the line size for signature data.

Recgonize the signature section between begin_signature and end_signature 
symbols
when loading elf of ACT tests. Then dump signature data in signature section 
just
before the ACT tests exit.

Signed-off-by: Weiwei Li 
Signed-off-by: Junqiang Wang 
Reviewed-by: LIU Zhiwei 
---
 hw/char/riscv_htif.c | 39 +++-
 hw/riscv/spike.c | 13 
 include/hw/char/riscv_htif.h |  3 +++
 3 files changed, 54 insertions(+), 1 deletion(-)

diff --git a/hw/char/riscv_htif.c b/hw/char/riscv_htif.c
index 098de50e35..297c98c215 100644
--- a/hw/char/riscv_htif.c
+++ b/hw/char/riscv_htif.c
@@ -29,6 +29,8 @@
 #include "chardev/char-fe.h"
 #include "qemu/timer.h"
 #include "qemu/error-report.h"
+#include "exec/address-spaces.h"
+#include "sysemu/dma.h"
 
 #define RISCV_DEBUG_HTIF 0
 #define HTIF_DEBUG(fmt, ...)   
\
@@ -51,7 +53,10 @@
 /* PK system call number */
 #define PK_SYS_WRITE64
 
-static uint64_t fromhost_addr, tohost_addr;
+const char *sig_file;
+uint8_t line_size = 16;
+
+static uint64_t fromhost_addr, tohost_addr, sig_addr, sig_len;
 
 void htif_symbol_callback(const char *st_name, int st_info, uint64_t st_value,
   uint64_t st_size)
@@ -68,6 +73,10 @@ void htif_symbol_callback(const char *st_name, int st_info, 
uint64_t st_value,
 error_report("HTIF tohost must be 8 bytes");
 exit(1);
 }
+} else if (strcmp("begin_signature", st_name) == 0) {
+sig_addr = st_value;
+} else if (strcmp("end_signature", st_name) == 0) {
+sig_len = st_value - sig_addr;
 }
 }
 
@@ -161,6 +170,34 @@ static void htif_handle_tohost_write(HTIFState *s, 
uint64_t val_written)
 /* frontend syscall handler, shutdown and exit code support */
 if (cmd == HTIF_SYSTEM_CMD_SYSCALL) {
 if (payload & 0x1) {
+/* Dump signature data to sig_file if specified */
+if (sig_file) {
+char *sig_data = g_malloc(sig_len);
+dma_memory_read(_space_memory, sig_addr, sig_data,
+sig_len, MEMTXATTRS_UNSPECIFIED);
+FILE *signature = fopen(sig_file, "w");
+if (signature == NULL) {
+error_report("open %s: %s", sig_file,
+ strerror(errno));
+exit(1);
+}
+
+for (int i = 0; i < sig_len; i += line_size) {
+for (int j = line_size; j > 0; j--) {
+if (i + j <= sig_len) {
+fprintf(signature, "%02x",
+sig_data[i + j - 1] & 0xff);
+} else {
+fprintf(signature, "%02x", 0);
+}
+}
+fprintf(signature, "\n");
+}
+
+fclose(signature);
+g_free(sig_data);
+}
+
 /* exit code */
 int exit_code = payload >> 1;
 exit(exit_code);
diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c
index a584d5b3a2..2c5546560a 100644
--- a/hw/riscv/spike.c
+++ b/hw/riscv/spike.c
@@ -332,6 +332,11 @@ static void spike_board_init(MachineState *machine)
  htif_custom_base);
 }
 
+static void spike_set_signature(Object *obj, const char *val, Error **errp)
+{
+sig_file = g_strdup(val);
+}
+
 static void spike_machine_instance_init(Object *obj)
 {
 }
@@ -350,6 +355,14 @@ static void spike_machine_class_init(ObjectClass *oc, void 
*data)
 mc->get_default_cpu_node_id = riscv_numa_get_default_cpu_node_id;
 mc->numa_mem_supported = true;
 mc->default_ram_id = "riscv.spike.ram";
+object_class_property_add_str(oc, "signature", NULL, spike_set_signature);
+object_class_property_set_description(oc, "signature",
+  "File to write ACT test signature");
+object_class_property_add_uint8_ptr(oc, "signature-granularity",
+_size, OBJ_PROP_FLAG_WRITE);
+object_class_property_set_description(oc, "signature-granularity",
+  "Size of each line in ACT signature "
+  "file");
 }
 
 static const TypeInfo spike_machine_typeinfo = {
diff --git a/include/hw/char/riscv_htif.h b/include/hw/char/riscv_htif.h
index 5958c5b986..df493fdf6b 100644
--- a/include/hw/char/riscv_htif.h
+++ b/include/hw/char/riscv_htif.h
@@ -40,6 +40,9 @@ typedef struct HTIFState {
 uint64_t pending_read;
 } HTIFState;
 
+extern const char *sig_file;
+extern 

[PATCH v3 0/1] hw/riscv: Add ACT related support

2023-03-06 Thread Weiwei Li
ACT tests play an important role in riscv tests. This patch tries to
add related support to run ACT tests.

The port is available here:
https://github.com/plctlab/plct-qemu/tree/plct-act-upstream-v3

The ACT tests can be run on qemu-system-riscv32/64 with machine argument
"-M spike,signature=,signature-granularity=".

v3:
* move definition of signature related parameters from spike.c to riscv_htif.c

v2:
* move "extern ..." declaration from riscv_htif.c to riscv_htif.h

Weiwei Li (1):
  hw/riscv: Add signature dump function for spike to run ACT tests

 hw/char/riscv_htif.c | 39 +++-
 hw/riscv/spike.c | 13 
 include/hw/char/riscv_htif.h |  3 +++
 3 files changed, 54 insertions(+), 1 deletion(-)

-- 
2.25.1




Re: [PATCH 0/9] accel/tcg: Fix page_set_flags and related [#1528]

2023-03-06 Thread Joel Stanley
On Mon, 6 Mar 2023 at 02:14, Richard Henderson
 wrote:
>
> The primary issue is that of overflow, where "end" for the last
> page of the 32-bit address space overflows to 0.  The fix is to
> use "last" instead, which can always be represented.
>
> This requires that we adjust reserved_va as well, because of
>
> -/*
> - * There are a number of places where we assign reserved_va to a variable
> - * of type abi_ulong and expect it to fit.  Avoid the last page.
> - */
> -#   define MAX_RESERVED_VA  (0xul & TARGET_PAGE_MASK)
>
> and the related
>
> -/*
> - * reserved_va must be aligned with the host page size
> - * as it is used with mmap()
> - */
> -reserved_va = local_max_va & qemu_host_page_mask;
>
> whereby we avoided the final (host | guest) page of the address space
> because of said overflow.  With the change in representation, we can
> always use UINT32_MAX as the end of the 32-bit address space.
>
> This was observable on ppc64le (or any other 64k page host) not being
> able to load any arm32 binary, because the COMMPAGE goes at 0x,
> which violated that last host page problem above.
>
> The issue is resolved in patch 4, but the rest clean up other interfaces
> with the same issue.  I'm not touching any interfaces that use start+len
> instead of start+end.

Thanks for looking at this Richard. I gave it a spin on a ppc64le host
and it resolved the assert.

Tested-by: Joel Stanley 

Cheers,

Joel



Re: [PATCH v3] target/arm: Add Neoverse-N1 registers

2023-03-06 Thread Chen Baozi
Hi Richard,

> On Mar 7, 2023, at 10:33, Richard Henderson  
> wrote:
> 
> On 3/6/23 18:29, Richard Henderson wrote:
>> On 3/6/23 18:14, Chen Baozi wrote:
>>> Add implementation defined registers for neoverse-n1 which
>>> would be accessed by TF-A. Since there is no DSU in Qemu,
>>> CPUCFR_EL1.SCU bit is set to 1 to avoid DSU registers definition.
>>> 
>>> Signed-off-by: Chen Baozi 
>>> Tested-by: Marcin Juszkiewicz 
>>> ---
>>>   target/arm/cpu64.c |  2 ++
>>>   target/arm/cpu_tcg.c   | 66 ++
>>>   target/arm/internals.h |  2 ++
>>>   3 files changed, 70 insertions(+)
>> You really need to base on upstream master, as these files have moved.
> 
> I beg your pardon, my mistake.  Only half of the patch set which moves these 
> files was applied.  I had to do my own rebase around file movement today, but 
> these three are not yet affected.

Never mind. I was aware of that. Waiting for them to be applied and then rework.
> 
> But do be aware that there is a potential conflict out there.
> 
> My comments re the placement of the array still apply.

Ack.

Cheers,

Baozi.



[PATCH v6 13/14] Hexagon (target/hexagon) Reduce manipulation of slot_cancelled

2023-03-06 Thread Taylor Simpson
We only need to track slot for predicated stores and predicated HVX
instructions.

Add arguments to the probe helper functions to indicate if the slot
is predicated.

Here is a simple example of the differences in the TCG code generated:

IN:
0x00400094:  0xf900c102 {   if (P0) R2 = and(R0,R1) }

BEFORE
  00400094
 mov_i32 slot_cancelled,$0x0
 mov_i32 new_r2,r2
 and_i32 tmp0,p0,$0x1
 brcond_i32 tmp0,$0x0,eq,$L1
 and_i32 tmp0,r0,r1
 mov_i32 new_r2,tmp0
 br $L2
 set_label $L1
 or_i32 slot_cancelled,slot_cancelled,$0x8
 set_label $L2
 mov_i32 r2,new_r2

AFTER
  00400094
 mov_i32 new_r2,r2
 and_i32 tmp0,p0,$0x1
 brcond_i32 tmp0,$0x0,eq,$L1
 and_i32 tmp0,r0,r1
 mov_i32 new_r2,tmp0
 br $L2
 set_label $L1
 set_label $L2
 mov_i32 r2,new_r2

Signed-off-by: Taylor Simpson 
Reviewed-by: Anton Johansson 
---
 target/hexagon/macros.h |  2 +-
 target/hexagon/op_helper.h  |  3 +-
 target/hexagon/translate.h  | 10 +
 target/hexagon/idef-parser/parser-helpers.c |  1 -
 target/hexagon/op_helper.c  | 32 
 target/hexagon/translate.c  | 42 ++---
 target/hexagon/idef-parser/idef-parser.lex  |  4 +-
 target/hexagon/idef-parser/idef-parser.y|  7 ++--
 8 files changed, 71 insertions(+), 30 deletions(-)

diff --git a/target/hexagon/macros.h b/target/hexagon/macros.h
index 1fa6057d27..482a9c787f 100644
--- a/target/hexagon/macros.h
+++ b/target/hexagon/macros.h
@@ -205,7 +205,7 @@ static inline void gen_cancel(uint32_t slot)
 
 #define CANCEL gen_cancel(slot);
 #else
-#define CANCEL cancel_slot(env, slot)
+#define CANCEL do { } while (0)
 #endif
 
 #define LOAD_CANCEL(EA) do { CANCEL; } while (0)
diff --git a/target/hexagon/op_helper.h b/target/hexagon/op_helper.h
index 02347edee8..34b3a53975 100644
--- a/target/hexagon/op_helper.h
+++ b/target/hexagon/op_helper.h
@@ -1,5 +1,5 @@
 /*
- *  Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
+ *  Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -19,7 +19,6 @@
 #define HEXAGON_OP_HELPER_H
 
 /* Misc functions */
-void cancel_slot(CPUHexagonState *env, uint32_t slot);
 void write_new_pc(CPUHexagonState *env, bool pkt_has_multi_cof, target_ulong 
addr);
 
 uint8_t mem_load1(CPUHexagonState *env, uint32_t slot, target_ulong vaddr);
diff --git a/target/hexagon/translate.h b/target/hexagon/translate.h
index 765f2c6a22..6e59a90c41 100644
--- a/target/hexagon/translate.h
+++ b/target/hexagon/translate.h
@@ -172,4 +172,14 @@ extern TCGv hex_vstore_pending[VSTORES_MAX];
 
 bool is_gather_store_insn(DisasContext *ctx);
 void process_store(DisasContext *ctx, int slot_num);
+
+FIELD(PROBE_PKT_SCALAR_STORE_S0, MMU_IDX,   0, 2)
+FIELD(PROBE_PKT_SCALAR_STORE_S0, IS_PREDICATED, 2, 1)
+
+FIELD(PROBE_PKT_SCALAR_HVX_STORES, HAS_ST0,0, 1)
+FIELD(PROBE_PKT_SCALAR_HVX_STORES, HAS_ST1,1, 1)
+FIELD(PROBE_PKT_SCALAR_HVX_STORES, HAS_HVX_STORES, 2, 1)
+FIELD(PROBE_PKT_SCALAR_HVX_STORES, S0_IS_PRED, 3, 1)
+FIELD(PROBE_PKT_SCALAR_HVX_STORES, S1_IS_PRED, 4, 1)
+
 #endif
diff --git a/target/hexagon/idef-parser/parser-helpers.c 
b/target/hexagon/idef-parser/parser-helpers.c
index ba4fc377d2..ef9ca85e90 100644
--- a/target/hexagon/idef-parser/parser-helpers.c
+++ b/target/hexagon/idef-parser/parser-helpers.c
@@ -1732,7 +1732,6 @@ void gen_cancel(Context *c, YYLTYPE *locp)
 
 void gen_load_cancel(Context *c, YYLTYPE *locp)
 {
-gen_cancel(c, locp);
 OUT(c, locp, "if (insn->slot == 0 && pkt->pkt_has_store_s1) {\n");
 OUT(c, locp, "ctx->s1_store_processed = false;\n");
 OUT(c, locp, "process_store(ctx, 1);\n");
diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c
index 9425941c69..c9a156030e 100644
--- a/target/hexagon/op_helper.c
+++ b/target/hexagon/op_helper.c
@@ -30,6 +30,7 @@
 #include "mmvec/mmvec.h"
 #include "mmvec/macros.h"
 #include "op_helper.h"
+#include "translate.h"
 
 #define SF_BIAS127
 #define SF_MANTBITS23
@@ -415,9 +416,10 @@ int32_t HELPER(vacsh_pred)(CPUHexagonState *env,
 return PeV;
 }
 
-static void probe_store(CPUHexagonState *env, int slot, int mmu_idx)
+static void probe_store(CPUHexagonState *env, int slot, int mmu_idx,
+bool is_predicated)
 {
-if (!(env->slot_cancelled & (1 << slot))) {
+if (!is_predicated || !(env->slot_cancelled & (1 << slot))) {
 size1u_t width = env->mem_log_stores[slot].width;
 target_ulong va = env->mem_log_stores[slot].va;
 uintptr_t ra = GETPC();
@@ -437,9 +439,12 @@ void HELPER(probe_noshuf_load)(CPUHexagonState *env, 
target_ulong va,
 }
 
 /* Called during packet commit when there are two scalar stores */
-void HELPER(probe_pkt_scalar_store_s0)(CPUHexagonState *env, int mmu_idx)
+void 

[PATCH v6 05/14] Hexagon (target/hexagon) Analyze packet before generating TCG

2023-03-06 Thread Taylor Simpson
We create a new generator that creates an analyze_ function for
each instruction.  Currently, these functions record the writes to
R, P, and C registers by calling ctx_log_reg_write[_pair] or
ctx_log_pred_write.

During gen_start_packet, we invoke the analyze_ function for
each instruction in the packet, and we mark the implicit register
and predicate writes.

Doing the analysis up front has several advantages
- We remove calls to ctx_log_* from gen_tcg_funcs.py and genptr.c
- After the analysis is performed, we can initialize hex_new_value
  for each of the predicated assignments rather than during TCG
  generation for the instructions
- This is a stepping stone for future work where the analysis will
  include the set of registers that are read.  In cases where
  the packet doesn't have an overlap between the registers that are
  written and registers that are read, we can avoid the intermediate
  step of writing to hex_new_value.  Note that other checks will also
  be needed (e.g., no instructions can raise an exception).

Signed-off-by: Taylor Simpson 
Reviewed-by: Anton Johansson 
---
 target/hexagon/translate.h  |  46 ++--
 target/hexagon/genptr.c |   5 +-
 target/hexagon/idef-parser/parser-helpers.c |   7 +-
 target/hexagon/translate.c  | 162 +++--
 target/hexagon/README   |  10 +-
 target/hexagon/gen_analyze_funcs.py | 237 
 target/hexagon/gen_tcg_funcs.py |  23 +-
 target/hexagon/meson.build  |  11 +-
 8 files changed, 383 insertions(+), 118 deletions(-)
 create mode 100755 target/hexagon/gen_analyze_funcs.py

diff --git a/target/hexagon/translate.h b/target/hexagon/translate.h
index d971f4f095..d45d3a4bb0 100644
--- a/target/hexagon/translate.h
+++ b/target/hexagon/translate.h
@@ -1,5 +1,5 @@
 /*
- *  Copyright(c) 2019-2022 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
+ *  Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -38,6 +38,7 @@ typedef struct DisasContext {
 int reg_log[REG_WRITES_MAX];
 int reg_log_idx;
 DECLARE_BITMAP(regs_written, TOTAL_PER_THREAD_REGS);
+DECLARE_BITMAP(predicated_regs, TOTAL_PER_THREAD_REGS);
 int preg_log[PRED_WRITES_MAX];
 int preg_log_idx;
 DECLARE_BITMAP(pregs_written, NUM_PREGS);
@@ -62,32 +63,39 @@ typedef struct DisasContext {
 bool is_tight_loop;
 } DisasContext;
 
-static inline void ctx_log_reg_write(DisasContext *ctx, int rnum)
+static inline void ctx_log_pred_write(DisasContext *ctx, int pnum)
 {
-if (test_bit(rnum, ctx->regs_written)) {
-HEX_DEBUG_LOG("WARNING: Multiple writes to r%d\n", rnum);
+if (!test_bit(pnum, ctx->pregs_written)) {
+ctx->preg_log[ctx->preg_log_idx] = pnum;
+ctx->preg_log_idx++;
+set_bit(pnum, ctx->pregs_written);
 }
-ctx->reg_log[ctx->reg_log_idx] = rnum;
-ctx->reg_log_idx++;
-set_bit(rnum, ctx->regs_written);
-}
-
-static inline void ctx_log_reg_write_pair(DisasContext *ctx, int rnum)
-{
-ctx_log_reg_write(ctx, rnum);
-ctx_log_reg_write(ctx, rnum + 1);
 }
 
-static inline void ctx_log_pred_write(DisasContext *ctx, int pnum)
+static inline void ctx_log_reg_write(DisasContext *ctx, int rnum,
+ bool is_predicated)
 {
-ctx->preg_log[ctx->preg_log_idx] = pnum;
-ctx->preg_log_idx++;
-set_bit(pnum, ctx->pregs_written);
+if (rnum == HEX_REG_P3_0_ALIASED) {
+for (int i = 0; i < NUM_PREGS; i++) {
+ctx_log_pred_write(ctx, i);
+}
+} else {
+if (!test_bit(rnum, ctx->regs_written)) {
+ctx->reg_log[ctx->reg_log_idx] = rnum;
+ctx->reg_log_idx++;
+set_bit(rnum, ctx->regs_written);
+}
+if (is_predicated) {
+set_bit(rnum, ctx->predicated_regs);
+}
+}
 }
 
-static inline bool is_preloaded(DisasContext *ctx, int num)
+static inline void ctx_log_reg_write_pair(DisasContext *ctx, int rnum,
+  bool is_predicated)
 {
-return test_bit(num, ctx->regs_written);
+ctx_log_reg_write(ctx, rnum, is_predicated);
+ctx_log_reg_write(ctx, rnum + 1, is_predicated);
 }
 
 static inline bool is_vreg_preloaded(DisasContext *ctx, int num)
diff --git a/target/hexagon/genptr.c b/target/hexagon/genptr.c
index 3490310812..61ab9af9e4 100644
--- a/target/hexagon/genptr.c
+++ b/target/hexagon/genptr.c
@@ -180,6 +180,7 @@ void gen_log_pred_write(DisasContext *ctx, int pnum, TCGv 
val)
hex_new_pred_value[pnum], base_val);
 }
 tcg_gen_ori_tl(hex_pred_written, hex_pred_written, 1 << pnum);
+set_bit(pnum, ctx->pregs_written);
 }
 
 static inline void gen_read_p3_0(TCGv control_reg)
@@ -256,7 +257,6 @@ static void 

[PATCH v6 10/14] Hexagon (tests/tcg/hexagon) Enable HVX tests

2023-03-06 Thread Taylor Simpson
Made possible by new toolchain container

Signed-off-by: Taylor Simpson 
Reviewed-by: Anton Johansson 
---
 tests/tcg/hexagon/Makefile.target | 13 -
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/tests/tcg/hexagon/Makefile.target 
b/tests/tcg/hexagon/Makefile.target
index 18e6a5969e..0d82dfa76e 100644
--- a/tests/tcg/hexagon/Makefile.target
+++ b/tests/tcg/hexagon/Makefile.target
@@ -1,5 +1,5 @@
 ##
-##  Copyright(c) 2019-2022 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
+##  Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
 ##
 ##  This program is free software; you can redistribute it and/or modify
 ##  it under the terms of the GNU General Public License as published by
@@ -45,6 +45,10 @@ HEX_TESTS += fpstuff
 HEX_TESTS += overflow
 HEX_TESTS += signal_context
 HEX_TESTS += reg_mut
+HEX_TESTS += vector_add_int
+HEX_TESTS += scatter_gather
+HEX_TESTS += hvx_misc
+HEX_TESTS += hvx_histogram
 
 HEX_TESTS += test_abs
 HEX_TESTS += test_bitcnt
@@ -78,3 +82,10 @@ TESTS += $(HEX_TESTS)
 usr: usr.c
$(CC) $(CFLAGS) -mv67t -O2 -Wno-inline-asm -Wno-expansion-to-defined $< 
-o $@ $(LDFLAGS)
 
+scatter_gather: CFLAGS += -mhvx
+vector_add_int: CFLAGS += -mhvx -fvectorize
+hvx_misc: CFLAGS += -mhvx
+hvx_histogram: CFLAGS += -mhvx -Wno-gnu-folding-constant
+
+hvx_histogram: hvx_histogram.c hvx_histogram_row.S
+   $(CC) $(CFLAGS) $(CROSS_CC_GUEST_CFLAGS) $^ -o $@ $(LDFLAGS)
-- 
2.25.1



[PATCH v6 12/14] Hexagon (target/hexagon) Remove gen_log_predicated_reg_write[_pair]

2023-03-06 Thread Taylor Simpson
We assign the instruction destination register to hex_new_value[num]
instead of a TCG temp that gets copied back to hex_new_value[num].

We introduce new functions get_result_gpr[_pair] to facilitate getting
the proper destination register.

Since we preload hex_new_value for predicated instructions, we don't
need the check for slot_cancelled.  So, we call gen_log_reg_write instead.

We update the helper function generation and gen_tcg.h to maintain the
disable-hexagon-idef-parser configuration.

Here is a simple example of the differences in the TCG code generated:

IN:
0x00400094:  0xf900c102 {   if (P0) R2 = and(R0,R1) }

BEFORE
  00400094
 mov_i32 slot_cancelled,$0x0
 mov_i32 new_r2,r2
 mov_i32 loc2,$0x0
 and_i32 tmp0,p0,$0x1
 brcond_i32 tmp0,$0x0,eq,$L1
 and_i32 tmp0,r0,r1
 mov_i32 loc2,tmp0
 br $L2
 set_label $L1
 or_i32 slot_cancelled,slot_cancelled,$0x8
 set_label $L2
 and_i32 tmp0,slot_cancelled,$0x8
 movcond_i32 new_r2,tmp0,$0x0,loc2,new_r2,eq
 mov_i32 r2,new_r2

AFTER
  00400094
 mov_i32 slot_cancelled,$0x0
 mov_i32 new_r2,r2
 and_i32 tmp0,p0,$0x1
 brcond_i32 tmp0,$0x0,eq,$L1
 and_i32 tmp0,r0,r1
 mov_i32 new_r2,tmp0
 br $L2
 set_label $L1
 or_i32 slot_cancelled,slot_cancelled,$0x8
 set_label $L2
 mov_i32 r2,new_r2

We'll remove the unnecessary manipulation of slot_cancelled in a
subsequent patch.

Signed-off-by: Taylor Simpson 
Reviewed-by: Anton Johansson 
---
 target/hexagon/gen_tcg.h|   6 +-
 target/hexagon/macros.h |  15 ---
 target/hexagon/genptr.c | 121 +---
 target/hexagon/idef-parser/parser-helpers.c |   4 +-
 target/hexagon/gen_helper_funcs.py  |  19 ++-
 target/hexagon/gen_helper_protos.py |  12 +-
 target/hexagon/gen_tcg_funcs.py |  76 +++-
 target/hexagon/hex_common.py|   9 +-
 8 files changed, 110 insertions(+), 152 deletions(-)

diff --git a/target/hexagon/gen_tcg.h b/target/hexagon/gen_tcg.h
index 56bdc67089..d514aa3448 100644
--- a/target/hexagon/gen_tcg.h
+++ b/target/hexagon/gen_tcg.h
@@ -332,8 +332,6 @@
 tcg_gen_movi_tl(EA, 0); \
 PRED;  \
 CHECK_NOSHUF_PRED(GET_EA, SIZE, LSB); \
-PRED_LOAD_CANCEL(LSB, EA); \
-tcg_gen_movi_tl(RdV, 0); \
 tcg_gen_brcondi_tl(TCG_COND_EQ, LSB, 0, label); \
 fLOAD(1, SIZE, SIGN, EA, RdV); \
 gen_set_label(label); \
@@ -391,8 +389,6 @@
 tcg_gen_movi_tl(EA, 0); \
 PRED;  \
 CHECK_NOSHUF_PRED(GET_EA, 8, LSB); \
-PRED_LOAD_CANCEL(LSB, EA); \
-tcg_gen_movi_i64(RddV, 0); \
 tcg_gen_brcondi_tl(TCG_COND_EQ, LSB, 0, label); \
 fLOAD(1, 8, u, EA, RddV); \
 gen_set_label(label); \
@@ -504,7 +500,7 @@
  */
 #define fGEN_TCG_SL2_return(SHORTCODE) \
 do { \
-TCGv_i64 RddV = tcg_temp_new_i64(); \
+TCGv_i64 RddV = get_result_gpr_pair(ctx, HEX_REG_FP); \
 gen_return(ctx, RddV, hex_gpr[HEX_REG_FP]); \
 gen_log_reg_write_pair(HEX_REG_FP, RddV); \
 } while (0)
diff --git a/target/hexagon/macros.h b/target/hexagon/macros.h
index 6974ef6c9e..1fa6057d27 100644
--- a/target/hexagon/macros.h
+++ b/target/hexagon/macros.h
@@ -210,21 +210,6 @@ static inline void gen_cancel(uint32_t slot)
 
 #define LOAD_CANCEL(EA) do { CANCEL; } while (0)
 
-#ifdef QEMU_GENERATE
-static inline void gen_pred_cancel(TCGv pred, uint32_t slot_num)
- {
-TCGv slot_mask = tcg_temp_new();
-TCGv tmp = tcg_temp_new();
-TCGv zero = tcg_constant_tl(0);
-tcg_gen_ori_tl(slot_mask, hex_slot_cancelled, 1 << slot_num);
-tcg_gen_andi_tl(tmp, pred, 1);
-tcg_gen_movcond_tl(TCG_COND_EQ, hex_slot_cancelled, tmp, zero,
-   slot_mask, hex_slot_cancelled);
-}
-#define PRED_LOAD_CANCEL(PRED, EA) \
-gen_pred_cancel(PRED, insn->is_endloop ? 4 : insn->slot)
-#endif
-
 #define STORE_CANCEL(EA) { env->slot_cancelled |= (1 << slot); }
 
 #define fMAX(A, B) (((A) > (B)) ? (A) : (B))
diff --git a/target/hexagon/genptr.c b/target/hexagon/genptr.c
index 61ab9af9e4..da5dbc83cf 100644
--- a/target/hexagon/genptr.c
+++ b/target/hexagon/genptr.c
@@ -68,26 +68,17 @@ static inline void gen_masked_reg_write(TCGv new_val, TCGv 
cur_val,
 }
 }
 
-static inline void gen_log_predicated_reg_write(int rnum, TCGv val,
-uint32_t slot)
+static TCGv get_result_gpr(DisasContext *ctx, int rnum)
 {
-TCGv zero = tcg_constant_tl(0);
-TCGv slot_mask = tcg_temp_new();
+return hex_new_value[rnum];
+}
 
-tcg_gen_andi_tl(slot_mask, hex_slot_cancelled, 1 << slot);
-tcg_gen_movcond_tl(TCG_COND_EQ, hex_new_value[rnum], slot_mask, zero,
-   val, hex_new_value[rnum]);
-if (HEX_DEBUG) {
-/*
- * Do this so HELPER(debug_commit_end) will know
- *
- * Note that slot_mask indicates the value is not written
- * (i.e., slot was cancelled), so we create a true/false value before

[PATCH v6 00/14] Hexagon: COF overrides, new generator, test/bug update

2023-03-06 Thread Taylor Simpson
The idef-parser skips the change-of-flow (COF) instructions, so add
overrides

The new toolchain allows us to execute the HVX tests

New generator enables significant improvement to TCG generation for
predicated instructions by removing the need for slot_cancelled

 Changes in v2 
Add a new generator for analyze_ instructions.  Pouplate the
DisasContext ahead of generating code.

 Changes in v3 
Cleanup of analysis code:
Added test updates enabled by new toolchain container

 Changes in v4 
Additional patch for bug fix
Remove pkt_has_store_s1 from runtime state with dealloc-return patch
New patches to utilize new analyzer to improve predicated instructions

 Changes in v5 
Don't remove code that is needed for --disable-hexagon-idef-parser config
pkt_has_store_s1 runtime field and mem_load[1248] functions
Add understanding of idef-parser to analyzer
Additional patch to determine when pkt_has_store_s1 needs to be set
Update fGEN_TCG_ to preserve --disable-hexagon-idef-parser config
in Remove gen_log_predicated_reg_write[_pair] patch
Move tcg_temp_free_i64 into gen_log_vreg_write
Add get_result_qreg function

 Changes in v6 
Address feedback from Anton Johansson 
Adapt to Richard Henderson's  recent patches
- Don't call tcg_temp_local_*
- Don't call tcg_temp_free_*


Taylor Simpson (14):
  Hexagon (target/hexagon) Add overrides for jumpr31 instructions
  Hexagon (target/hexagon) Add overrides for callr
  Hexagon (target/hexagon) Add overrides for endloop1/endloop01
  Hexagon (target/hexagon) Add overrides for dealloc-return instructions
  Hexagon (target/hexagon) Analyze packet before generating TCG
  Hexagon (target/hexagon) Don't set pkt_has_store_s1 when not needed
  Hexagon (target/hexagon) Analyze packet for HVX
  Hexagon (tests/tcg/hexagon) Update preg_alias.c
  Hexagon (tests/tcg/hexagon) Remove __builtin from scatter_gather
  Hexagon (tests/tcg/hexagon) Enable HVX tests
  Hexagon (target/hexagon) Change subtract from zero to change sign
  Hexagon (target/hexagon) Remove gen_log_predicated_reg_write[_pair]
  Hexagon (target/hexagon) Reduce manipulation of slot_cancelled
  Hexagon (target/hexagon) Improve code gen for predicated HVX
instructions

 target/hexagon/cpu.h|   5 +-
 target/hexagon/gen_tcg.h|  82 +++-
 target/hexagon/gen_tcg_hvx.h|  17 +-
 target/hexagon/macros.h |  29 +-
 target/hexagon/op_helper.h  |   3 +-
 target/hexagon/translate.h  |  86 ++--
 target/hexagon/attribs_def.h.inc|   1 +
 target/hexagon/genptr.c | 296 ++-
 target/hexagon/idef-parser/parser-helpers.c |  12 +-
 target/hexagon/op_helper.c  |  60 +--
 target/hexagon/translate.c  | 288 ++-
 tests/tcg/hexagon/fpstuff.c |  31 +-
 tests/tcg/hexagon/preg_alias.c  |  10 +-
 tests/tcg/hexagon/scatter_gather.c  | 513 +++-
 target/hexagon/README   |  31 +-
 target/hexagon/gen_analyze_funcs.py | 252 ++
 target/hexagon/gen_helper_funcs.py  |  19 +-
 target/hexagon/gen_helper_protos.py |  12 +-
 target/hexagon/gen_tcg_funcs.py | 152 +++---
 target/hexagon/hex_common.py|  10 +-
 target/hexagon/idef-parser/idef-parser.lex  |   4 +-
 target/hexagon/idef-parser/idef-parser.y|   7 +-
 target/hexagon/meson.build  |  11 +-
 tests/tcg/hexagon/Makefile.target   |  13 +-
 24 files changed, 1201 insertions(+), 743 deletions(-)
 create mode 100755 target/hexagon/gen_analyze_funcs.py

-- 
2.25.1



[PATCH v6 04/14] Hexagon (target/hexagon) Add overrides for dealloc-return instructions

2023-03-06 Thread Taylor Simpson
These instructions perform a deallocframe+return (jumpr r31)

Add overrides for
L4_return
SL2_return
L4_return_t
L4_return_f
L4_return_tnew_pt
L4_return_fnew_pt
L4_return_tnew_pnt
L4_return_fnew_pnt
SL2_return_t
SL2_return_f
SL2_return_tnew
SL2_return_fnew

This patch eliminates the last helper that uses write_new_pc, so we
remove it from op_helper.c

Signed-off-by: Taylor Simpson 
Reviewed-by: Anton Johansson 
---
 target/hexagon/gen_tcg.h   | 53 ++
 target/hexagon/genptr.c| 77 ++
 target/hexagon/op_helper.c | 26 +
 3 files changed, 131 insertions(+), 25 deletions(-)

diff --git a/target/hexagon/gen_tcg.h b/target/hexagon/gen_tcg.h
index 4f84baf03b..56bdc67089 100644
--- a/target/hexagon/gen_tcg.h
+++ b/target/hexagon/gen_tcg.h
@@ -491,6 +491,59 @@
 #define fGEN_TCG_S2_storerinew_pcr(SHORTCODE) \
 fGEN_TCG_STORE_pcr(2, fSTORE(1, 4, EA, NtN))
 
+/*
+ * dealloc_return
+ * Assembler mapped to
+ * r31:30 = dealloc_return(r30):raw
+ */
+#define fGEN_TCG_L4_return(SHORTCODE) \
+gen_return(ctx, RddV, RsV)
+
+/*
+ * sub-instruction version (no RddV, so handle it manually)
+ */
+#define fGEN_TCG_SL2_return(SHORTCODE) \
+do { \
+TCGv_i64 RddV = tcg_temp_new_i64(); \
+gen_return(ctx, RddV, hex_gpr[HEX_REG_FP]); \
+gen_log_reg_write_pair(HEX_REG_FP, RddV); \
+} while (0)
+
+/*
+ * Conditional returns follow this naming convention
+ * _t predicate true
+ * _f predicate false
+ * _tnew_pt   predicate.new true predict taken
+ * _fnew_pt   predicate.new false predict taken
+ * _tnew_pnt  predicate.new true predict not taken
+ * _fnew_pnt  predicate.new false predict not taken
+ * Predictions are not modelled in QEMU
+ *
+ * Example:
+ * if (p1) r31:30 = dealloc_return(r30):raw
+ */
+#define fGEN_TCG_L4_return_t(SHORTCODE) \
+gen_cond_return(ctx, RddV, RsV, PvV, TCG_COND_EQ);
+#define fGEN_TCG_L4_return_f(SHORTCODE) \
+gen_cond_return(ctx, RddV, RsV, PvV, TCG_COND_NE)
+#define fGEN_TCG_L4_return_tnew_pt(SHORTCODE) \
+gen_cond_return(ctx, RddV, RsV, PvN, TCG_COND_EQ)
+#define fGEN_TCG_L4_return_fnew_pt(SHORTCODE) \
+gen_cond_return(ctx, RddV, RsV, PvN, TCG_COND_NE)
+#define fGEN_TCG_L4_return_tnew_pnt(SHORTCODE) \
+gen_cond_return(ctx, RddV, RsV, PvN, TCG_COND_EQ)
+#define fGEN_TCG_L4_return_fnew_pnt(SHORTCODE) \
+gen_cond_return(ctx, RddV, RsV, PvN, TCG_COND_NE)
+
+#define fGEN_TCG_SL2_return_t(SHORTCODE) \
+gen_cond_return_subinsn(ctx, TCG_COND_EQ, hex_pred[0])
+#define fGEN_TCG_SL2_return_f(SHORTCODE) \
+gen_cond_return_subinsn(ctx, TCG_COND_NE, hex_pred[0])
+#define fGEN_TCG_SL2_return_tnew(SHORTCODE) \
+gen_cond_return_subinsn(ctx, TCG_COND_EQ, hex_new_pred_value[0])
+#define fGEN_TCG_SL2_return_fnew(SHORTCODE) \
+gen_cond_return_subinsn(ctx, TCG_COND_NE, hex_new_pred_value[0])
+
 /*
  * Mathematical operations with more than one definition require
  * special handling
diff --git a/target/hexagon/genptr.c b/target/hexagon/genptr.c
index f7017fd483..3490310812 100644
--- a/target/hexagon/genptr.c
+++ b/target/hexagon/genptr.c
@@ -715,6 +715,83 @@ static void gen_cond_callr(DisasContext *ctx,
 gen_set_label(skip);
 }
 
+/* frame ^= (int64_t)FRAMEKEY << 32 */
+static void gen_frame_unscramble(TCGv_i64 frame)
+{
+TCGv_i64 framekey = tcg_temp_new_i64();
+tcg_gen_extu_i32_i64(framekey, hex_gpr[HEX_REG_FRAMEKEY]);
+tcg_gen_shli_i64(framekey, framekey, 32);
+tcg_gen_xor_i64(frame, frame, framekey);
+}
+
+static void gen_load_frame(DisasContext *ctx, TCGv_i64 frame, TCGv EA)
+{
+Insn *insn = ctx->insn;  /* Needed for CHECK_NOSHUF */
+CHECK_NOSHUF(EA, 8);
+tcg_gen_qemu_ld64(frame, EA, ctx->mem_idx);
+}
+
+static void gen_return_base(DisasContext *ctx, TCGv_i64 dst, TCGv src,
+TCGv r29)
+{
+/*
+ * frame = *src
+ * dst = frame_unscramble(frame)
+ * SP = src + 8
+ * PC = dst.w[1]
+ */
+TCGv_i64 frame = tcg_temp_new_i64();
+TCGv r31 = tcg_temp_new();
+
+gen_load_frame(ctx, frame, src);
+gen_frame_unscramble(frame);
+tcg_gen_mov_i64(dst, frame);
+tcg_gen_addi_tl(r29, src, 8);
+tcg_gen_extrh_i64_i32(r31, dst);
+gen_jumpr(ctx, r31);
+}
+
+static void gen_return(DisasContext *ctx, TCGv_i64 dst, TCGv src)
+{
+TCGv r29 = tcg_temp_new();
+gen_return_base(ctx, dst, src, r29);
+gen_log_reg_write(HEX_REG_SP, r29);
+}
+
+/* if (pred) dst = dealloc_return(src):raw */
+static void gen_cond_return(DisasContext *ctx, TCGv_i64 dst, TCGv src,
+TCGv pred, TCGCond cond)
+{
+TCGv LSB = tcg_temp_new();
+TCGv mask = tcg_temp_new();
+TCGv r29 = tcg_temp_new();
+TCGLabel *skip = gen_new_label();
+tcg_gen_andi_tl(LSB, pred, 1);
+
+/* Initialize the results in case the predicate is false 

[PATCH v6 03/14] Hexagon (target/hexagon) Add overrides for endloop1/endloop01

2023-03-06 Thread Taylor Simpson
Signed-off-by: Taylor Simpson 
Reviewed-by: Anton Johansson 
---
 target/hexagon/gen_tcg.h |  4 +++
 target/hexagon/genptr.c  | 78 
 2 files changed, 82 insertions(+)

diff --git a/target/hexagon/gen_tcg.h b/target/hexagon/gen_tcg.h
index fa0dbbec7d..4f84baf03b 100644
--- a/target/hexagon/gen_tcg.h
+++ b/target/hexagon/gen_tcg.h
@@ -603,6 +603,10 @@
 
 #define fGEN_TCG_J2_endloop0(SHORTCODE) \
 gen_endloop0(ctx)
+#define fGEN_TCG_J2_endloop1(SHORTCODE) \
+gen_endloop1(ctx)
+#define fGEN_TCG_J2_endloop01(SHORTCODE) \
+gen_endloop01(ctx)
 
 /*
  * Compound compare and jump instructions
diff --git a/target/hexagon/genptr.c b/target/hexagon/genptr.c
index 592438f61e..f7017fd483 100644
--- a/target/hexagon/genptr.c
+++ b/target/hexagon/genptr.c
@@ -770,6 +770,84 @@ static void gen_endloop0(DisasContext *ctx)
 }
 }
 
+static void gen_endloop1(DisasContext *ctx)
+{
+/*
+ *if (hex_gpr[HEX_REG_LC1] > 1) {
+ *PC = hex_gpr[HEX_REG_SA1];
+ *hex_new_value[HEX_REG_LC1] = hex_gpr[HEX_REG_LC1] - 1;
+ *}
+ */
+TCGLabel *label = gen_new_label();
+tcg_gen_brcondi_tl(TCG_COND_LEU, hex_gpr[HEX_REG_LC1], 1, label);
+{
+gen_jumpr(ctx, hex_gpr[HEX_REG_SA1]);
+tcg_gen_subi_tl(hex_new_value[HEX_REG_LC1], hex_gpr[HEX_REG_LC1], 1);
+}
+gen_set_label(label);
+}
+
+static void gen_endloop01(DisasContext *ctx)
+{
+TCGv lpcfg = tcg_temp_new();
+TCGLabel *label1 = gen_new_label();
+TCGLabel *label2 = gen_new_label();
+TCGLabel *label3 = gen_new_label();
+TCGLabel *done = gen_new_label();
+
+GET_USR_FIELD(USR_LPCFG, lpcfg);
+
+/*
+ *if (lpcfg == 1) {
+ *hex_new_pred_value[3] = 0xff;
+ *hex_pred_written |= 1 << 3;
+ *}
+ */
+tcg_gen_brcondi_tl(TCG_COND_NE, lpcfg, 1, label1);
+{
+tcg_gen_movi_tl(hex_new_pred_value[3], 0xff);
+tcg_gen_ori_tl(hex_pred_written, hex_pred_written, 1 << 3);
+}
+gen_set_label(label1);
+
+/*
+ *if (lpcfg) {
+ *SET_USR_FIELD(USR_LPCFG, lpcfg - 1);
+ *}
+ */
+tcg_gen_brcondi_tl(TCG_COND_EQ, lpcfg, 0, label2);
+{
+tcg_gen_subi_tl(lpcfg, lpcfg, 1);
+SET_USR_FIELD(USR_LPCFG, lpcfg);
+}
+gen_set_label(label2);
+
+/*
+ *if (hex_gpr[HEX_REG_LC0] > 1) {
+ *PC = hex_gpr[HEX_REG_SA0];
+ *hex_new_value[HEX_REG_LC0] = hex_gpr[HEX_REG_LC0] - 1;
+ *} else {
+ *if (hex_gpr[HEX_REG_LC1] > 1) {
+ *hex_next_pc = hex_gpr[HEX_REG_SA1];
+ *hex_new_value[HEX_REG_LC1] = hex_gpr[HEX_REG_LC1] - 1;
+ *}
+ *}
+ */
+tcg_gen_brcondi_tl(TCG_COND_LEU, hex_gpr[HEX_REG_LC0], 1, label3);
+{
+gen_jumpr(ctx, hex_gpr[HEX_REG_SA0]);
+tcg_gen_subi_tl(hex_new_value[HEX_REG_LC0], hex_gpr[HEX_REG_LC0], 1);
+tcg_gen_br(done);
+}
+gen_set_label(label3);
+tcg_gen_brcondi_tl(TCG_COND_LEU, hex_gpr[HEX_REG_LC1], 1, done);
+{
+gen_jumpr(ctx, hex_gpr[HEX_REG_SA1]);
+tcg_gen_subi_tl(hex_new_value[HEX_REG_LC1], hex_gpr[HEX_REG_LC1], 1);
+}
+gen_set_label(done);
+}
+
 static void gen_cmp_jumpnv(DisasContext *ctx,
TCGCond cond, TCGv val, TCGv src, int pc_off)
 {
-- 
2.25.1



[PATCH v6 11/14] Hexagon (target/hexagon) Change subtract from zero to change sign

2023-03-06 Thread Taylor Simpson
The F2_sffms instruction [r0 -= sfmpy(r1, r2)] doesn't properly
handle -0.  Previously we would negate the input operand by subtracting
from zero.  Instead, we negate by changing the sign bit.

Test case added to tests/tcg/hexagon/fpstuff.c

Signed-off-by: Taylor Simpson 
Reviewed-by: Anton Johansson 
---
 target/hexagon/op_helper.c  |  2 +-
 tests/tcg/hexagon/fpstuff.c | 31 ++-
 2 files changed, 31 insertions(+), 2 deletions(-)

diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c
index 38b8aee193..9425941c69 100644
--- a/target/hexagon/op_helper.c
+++ b/target/hexagon/op_helper.c
@@ -1169,7 +1169,7 @@ float32 HELPER(sffms)(CPUHexagonState *env, float32 RxV,
 {
 float32 neg_RsV;
 arch_fpop_start(env);
-neg_RsV = float32_sub(float32_zero, RsV, >fp_status);
+neg_RsV = float32_set_sign(RsV, float32_is_neg(RsV) ? 0 : 1);
 RxV = internal_fmafx(neg_RsV, RtV, RxV, 0, >fp_status);
 arch_fpop_end(env);
 return RxV;
diff --git a/tests/tcg/hexagon/fpstuff.c b/tests/tcg/hexagon/fpstuff.c
index 56bf562a40..90ce9a6ef3 100644
--- a/tests/tcg/hexagon/fpstuff.c
+++ b/tests/tcg/hexagon/fpstuff.c
@@ -1,5 +1,5 @@
 /*
- *  Copyright(c) 2020-2022 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
+ *  Copyright(c) 2020-2023 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -40,6 +40,7 @@ const int SF_HEX_NAN =0x;
 const int SF_small_neg =  0xab98fba8;
 const int SF_denorm = 0x0001;
 const int SF_random = 0x346001d6;
+const int SF_neg_zero =   0x8000;
 
 const long long DF_QNaN = 0x7ff8ULL;
 const long long DF_SNaN = 0x7ff7ULL;
@@ -536,6 +537,33 @@ static void check_sffixupd(void)
 check32(result, 0x146001d6);
 }
 
+static void check_sffms(void)
+{
+int result;
+
+/* Check that sffms properly deals with -0 */
+result = SF_neg_zero;
+asm ("%0 -= sfmpy(%1 , %2)\n\t"
+: "+r"(result)
+: "r"(SF_ZERO), "r"(SF_ZERO)
+: "r12", "r8");
+check32(result, SF_neg_zero);
+
+result = SF_ZERO;
+asm ("%0 -= sfmpy(%1 , %2)\n\t"
+: "+r"(result)
+: "r"(SF_neg_zero), "r"(SF_ZERO)
+: "r12", "r8");
+check32(result, SF_ZERO);
+
+result = SF_ZERO;
+asm ("%0 -= sfmpy(%1 , %2)\n\t"
+: "+r"(result)
+: "r"(SF_ZERO), "r"(SF_neg_zero)
+: "r12", "r8");
+check32(result, SF_ZERO);
+}
+
 static void check_float2int_convs()
 {
 int res32;
@@ -688,6 +716,7 @@ int main()
 check_invsqrta();
 check_sffixupn();
 check_sffixupd();
+check_sffms();
 check_float2int_convs();
 
 puts(err ? "FAIL" : "PASS");
-- 
2.25.1



[PATCH v6 01/14] Hexagon (target/hexagon) Add overrides for jumpr31 instructions

2023-03-06 Thread Taylor Simpson
Add overrides for
SL2_jumpr31Unconditional
SL2_jumpr31_t  Predicated true (old value)
SL2_jumpr31_f  Predicated false (old value)
SL2_jumpr31_tnew   Predicated true (new value)
SL2_jumpr31_fnew   Predicated false (new value)

Signed-off-by: Taylor Simpson 
Reviewed-by: Anton Johansson 
---
 target/hexagon/gen_tcg.h | 15 ++-
 target/hexagon/genptr.c  |  9 -
 2 files changed, 22 insertions(+), 2 deletions(-)

diff --git a/target/hexagon/gen_tcg.h b/target/hexagon/gen_tcg.h
index b2e7880b5c..5f61c95b40 100644
--- a/target/hexagon/gen_tcg.h
+++ b/target/hexagon/gen_tcg.h
@@ -1,5 +1,5 @@
 /*
- *  Copyright(c) 2019-2022 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
+ *  Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -986,6 +986,19 @@
 #define fGEN_TCG_S2_asl_r_r_sat(SHORTCODE) \
 gen_asl_r_r_sat(RdV, RsV, RtV)
 
+#define fGEN_TCG_SL2_jumpr31(SHORTCODE) \
+gen_jumpr(ctx, hex_gpr[HEX_REG_LR])
+
+#define fGEN_TCG_SL2_jumpr31_t(SHORTCODE) \
+gen_cond_jumpr31(ctx, TCG_COND_EQ, hex_pred[0])
+#define fGEN_TCG_SL2_jumpr31_f(SHORTCODE) \
+gen_cond_jumpr31(ctx, TCG_COND_NE, hex_pred[0])
+
+#define fGEN_TCG_SL2_jumpr31_tnew(SHORTCODE) \
+gen_cond_jumpr31(ctx, TCG_COND_EQ, hex_new_pred_value[0])
+#define fGEN_TCG_SL2_jumpr31_fnew(SHORTCODE) \
+gen_cond_jumpr31(ctx, TCG_COND_NE, hex_new_pred_value[0])
+
 /* Floating point */
 #define fGEN_TCG_F2_conv_sf2df(SHORTCODE) \
 gen_helper_conv_sf2df(RddV, cpu_env, RsV)
diff --git a/target/hexagon/genptr.c b/target/hexagon/genptr.c
index 86bd093ce8..2bbe4e3a68 100644
--- a/target/hexagon/genptr.c
+++ b/target/hexagon/genptr.c
@@ -1,5 +1,5 @@
 /*
- *  Copyright(c) 2019-2022 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
+ *  Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -571,6 +571,13 @@ static void gen_cond_jumpr(DisasContext *ctx, TCGv dst_pc,
 gen_write_new_pc_addr(ctx, dst_pc, cond, pred);
 }
 
+static void gen_cond_jumpr31(DisasContext *ctx, TCGCond cond, TCGv pred)
+{
+TCGv LSB = tcg_temp_new();
+tcg_gen_andi_tl(LSB, pred, 1);
+gen_cond_jumpr(ctx, hex_gpr[HEX_REG_LR], cond, LSB);
+}
+
 static void gen_cond_jump(DisasContext *ctx, TCGCond cond, TCGv pred,
   int pc_off)
 {
-- 
2.25.1



[PATCH v6 08/14] Hexagon (tests/tcg/hexagon) Update preg_alias.c

2023-03-06 Thread Taylor Simpson
Add control registers (c4, c5) to clobbers list
Made possible by new toolchain container

Signed-off-by: Taylor Simpson 
Reviewed-by: Anton Johansson 
---
 tests/tcg/hexagon/preg_alias.c | 10 +-
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/tests/tcg/hexagon/preg_alias.c b/tests/tcg/hexagon/preg_alias.c
index b44a8112b4..8798fbcaf3 100644
--- a/tests/tcg/hexagon/preg_alias.c
+++ b/tests/tcg/hexagon/preg_alias.c
@@ -1,5 +1,5 @@
 /*
- *  Copyright(c) 2019-2022 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
+ *  Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -65,7 +65,7 @@ static inline void creg_alias(int cval, PRegs *pregs)
   : "=r"(pregs->pregs.p0), "=r"(pregs->pregs.p1),
 "=r"(pregs->pregs.p2), "=r"(pregs->pregs.p3)
   : "r"(cval)
-  : "p0", "p1", "p2", "p3");
+  : "c4", "p0", "p1", "p2", "p3");
 }
 
 int err;
@@ -92,7 +92,7 @@ static inline void creg_alias_pair(unsigned int cval, PRegs 
*pregs)
: "=r"(pregs->pregs.p0), "=r"(pregs->pregs.p1),
  "=r"(pregs->pregs.p2), "=r"(pregs->pregs.p3), "=r"(c5)
: "r"(cval_pair)
-   : "p0", "p1", "p2", "p3");
+   : "c4", "c5", "p0", "p1", "p2", "p3");
 
   check(c5, 0xdeadbeef);
 }
@@ -117,7 +117,7 @@ static void test_packet(void)
  "}\n\t"
  : "+r"(result)
  : "r"(0x), "r"(0xff00), "r"(0x837ed653)
- : "p0", "p1", "p2", "p3");
+ : "c4", "p0", "p1", "p2", "p3");
 check(result, old_val);
 
 /* Test a predicated store */
@@ -129,7 +129,7 @@ static void test_packet(void)
  "}\n\t"
  :
  : "r"(0), "r"(0x), "r"()
- : "p0", "p1", "p2", "p3", "memory");
+ : "c4", "p0", "p1", "p2", "p3", "memory");
 check(result, 0x0);
 }
 
-- 
2.25.1



[PATCH v6 07/14] Hexagon (target/hexagon) Analyze packet for HVX

2023-03-06 Thread Taylor Simpson
Extend the analyze_ functions for HVX vector and predicate writes
Remove calls to ctx_log_vreg_write[_pair] from gen_tcg_funcs.py
During gen_start_packet, reload the predicated HVX registers into
fugure_VRegs and tmp_VRegs

Signed-off-by: Taylor Simpson 
Reviewed-by: Anton Johansson 
---
 target/hexagon/translate.h  | 14 --
 target/hexagon/translate.c  | 30 +
 target/hexagon/gen_analyze_funcs.py | 17 +---
 target/hexagon/gen_tcg_funcs.py | 18 -
 4 files changed, 52 insertions(+), 27 deletions(-)

diff --git a/target/hexagon/translate.h b/target/hexagon/translate.h
index 34368b2186..765f2c6a22 100644
--- a/target/hexagon/translate.h
+++ b/target/hexagon/translate.h
@@ -54,6 +54,8 @@ typedef struct DisasContext {
 DECLARE_BITMAP(vregs_updated_tmp, NUM_VREGS);
 DECLARE_BITMAP(vregs_updated, NUM_VREGS);
 DECLARE_BITMAP(vregs_select, NUM_VREGS);
+DECLARE_BITMAP(predicated_future_vregs, NUM_VREGS);
+DECLARE_BITMAP(predicated_tmp_vregs, NUM_VREGS);
 int qreg_log[NUM_QREGS];
 bool qreg_is_predicated[NUM_QREGS];
 int qreg_log_idx;
@@ -99,12 +101,6 @@ static inline void ctx_log_reg_write_pair(DisasContext 
*ctx, int rnum,
 ctx_log_reg_write(ctx, rnum + 1, is_predicated);
 }
 
-static inline bool is_vreg_preloaded(DisasContext *ctx, int num)
-{
-return test_bit(num, ctx->vregs_updated) ||
-   test_bit(num, ctx->vregs_updated_tmp);
-}
-
 intptr_t ctx_future_vreg_off(DisasContext *ctx, int regnum,
  int num, bool alloc_ok);
 intptr_t ctx_tmp_vreg_off(DisasContext *ctx, int regnum,
@@ -120,12 +116,18 @@ static inline void ctx_log_vreg_write(DisasContext *ctx,
 ctx->vreg_log_idx++;
 
 set_bit(rnum, ctx->vregs_updated);
+if (is_predicated) {
+set_bit(rnum, ctx->predicated_future_vregs);
+}
 }
 if (type == EXT_NEW) {
 set_bit(rnum, ctx->vregs_select);
 }
 if (type == EXT_TMP) {
 set_bit(rnum, ctx->vregs_updated_tmp);
+if (is_predicated) {
+set_bit(rnum, ctx->predicated_tmp_vregs);
+}
 }
 }
 
diff --git a/target/hexagon/translate.c b/target/hexagon/translate.c
index 01671d5451..493bc75d27 100644
--- a/target/hexagon/translate.c
+++ b/target/hexagon/translate.c
@@ -364,6 +364,8 @@ static void gen_start_packet(DisasContext *ctx)
 bitmap_zero(ctx->vregs_updated_tmp, NUM_VREGS);
 bitmap_zero(ctx->vregs_updated, NUM_VREGS);
 bitmap_zero(ctx->vregs_select, NUM_VREGS);
+bitmap_zero(ctx->predicated_future_vregs, NUM_VREGS);
+bitmap_zero(ctx->predicated_tmp_vregs, NUM_VREGS);
 ctx->qreg_log_idx = 0;
 for (i = 0; i < STORES_MAX; i++) {
 ctx->store_width[i] = 0;
@@ -415,6 +417,34 @@ static void gen_start_packet(DisasContext *ctx)
 }
 }
 
+/* Preload the predicated HVX registers into future_VRegs and tmp_VRegs */
+if (!bitmap_empty(ctx->predicated_future_vregs, NUM_VREGS)) {
+int i = find_first_bit(ctx->predicated_future_vregs, NUM_VREGS);
+while (i < NUM_VREGS) {
+const intptr_t VdV_off =
+ctx_future_vreg_off(ctx, i, 1, true);
+intptr_t src_off = offsetof(CPUHexagonState, VRegs[i]);
+tcg_gen_gvec_mov(MO_64, VdV_off,
+ src_off,
+ sizeof(MMVector),
+ sizeof(MMVector));
+i = find_next_bit(ctx->predicated_future_vregs, NUM_VREGS, i + 1);
+}
+}
+if (!bitmap_empty(ctx->predicated_tmp_vregs, NUM_VREGS)) {
+int i = find_first_bit(ctx->predicated_tmp_vregs, NUM_VREGS);
+while (i < NUM_VREGS) {
+const intptr_t VdV_off =
+ctx_tmp_vreg_off(ctx, i, 1, true);
+intptr_t src_off = offsetof(CPUHexagonState, VRegs[i]);
+tcg_gen_gvec_mov(MO_64, VdV_off,
+ src_off,
+ sizeof(MMVector),
+ sizeof(MMVector));
+i = find_next_bit(ctx->predicated_tmp_vregs, NUM_VREGS, i + 1);
+}
+}
+
 if (pkt->pkt_has_hvx) {
 tcg_gen_movi_tl(hex_VRegs_updated, 0);
 tcg_gen_movi_tl(hex_QRegs_updated, 0);
diff --git a/target/hexagon/gen_analyze_funcs.py 
b/target/hexagon/gen_analyze_funcs.py
index 7e1f221b3c..0bb4fcb476 100755
--- a/target/hexagon/gen_analyze_funcs.py
+++ b/target/hexagon/gen_analyze_funcs.py
@@ -83,9 +83,16 @@ def analyze_opn_old(f, tag, regtype, regid, regno):
 else:
 print("Bad register parse: ", regtype, regid)
 elif (regtype == "V"):
+newv = "EXT_DFL"
+if (hex_common.is_new_result(tag)):
+newv = "EXT_NEW"
+elif (hex_common.is_tmp_result(tag)):
+newv = "EXT_TMP"
 if (regid in {"dd", "xx"}):
-f.write("//const int %s = insn->regno[%d];\n" %\
+f.write("

[PATCH v6 14/14] Hexagon (target/hexagon) Improve code gen for predicated HVX instructions

2023-03-06 Thread Taylor Simpson
The following improvements are made for predicated HVX instructions
During gen_commit_hvx, unconditionally move the "new" value into
the dest
Don't set slot_cancelled
Remove runtime bookkeeping of which registers were updated
Reduce the cases where gen_log_vreg_write[_pair] is called
It's only needed for special operands VxxV and VyV
Remove gen_log_qreg_write

Signed-off-by: Taylor Simpson 
Reviewed-by: Anton Johansson 
---
 target/hexagon/cpu.h|  5 +--
 target/hexagon/gen_tcg_hvx.h| 17 +
 target/hexagon/translate.h  | 15 +++-
 target/hexagon/genptr.c | 48 +++-
 target/hexagon/translate.c  | 58 +++--
 target/hexagon/README   | 21 +++
 target/hexagon/gen_analyze_funcs.py |  3 +-
 target/hexagon/gen_tcg_funcs.py | 35 -
 8 files changed, 34 insertions(+), 168 deletions(-)

diff --git a/target/hexagon/cpu.h b/target/hexagon/cpu.h
index 34c0ae0a67..81b663ecfb 100644
--- a/target/hexagon/cpu.h
+++ b/target/hexagon/cpu.h
@@ -1,5 +1,5 @@
 /*
- *  Copyright(c) 2019-2022 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
+ *  Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -111,11 +111,8 @@ typedef struct CPUArchState {
 MMVector future_VRegs[VECTOR_TEMPS_MAX] QEMU_ALIGNED(16);
 MMVector tmp_VRegs[VECTOR_TEMPS_MAX] QEMU_ALIGNED(16);
 
-VRegMask VRegs_updated;
-
 MMQReg QRegs[NUM_QREGS] QEMU_ALIGNED(16);
 MMQReg future_QRegs[NUM_QREGS] QEMU_ALIGNED(16);
-QRegMask QRegs_updated;
 
 /* Temporaries used within instructions */
 MMVectorPair VuuV QEMU_ALIGNED(16);
diff --git a/target/hexagon/gen_tcg_hvx.h b/target/hexagon/gen_tcg_hvx.h
index 94f272e286..d4aefe8e3f 100644
--- a/target/hexagon/gen_tcg_hvx.h
+++ b/target/hexagon/gen_tcg_hvx.h
@@ -1,5 +1,5 @@
 /*
- *  Copyright(c) 2019-2022 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
+ *  Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -133,16 +133,11 @@ static inline void assert_vhist_tmp(DisasContext *ctx)
 do { \
 TCGv lsb = tcg_temp_new(); \
 TCGLabel *false_label = gen_new_label(); \
-TCGLabel *end_label = gen_new_label(); \
 tcg_gen_andi_tl(lsb, PsV, 1); \
 tcg_gen_brcondi_tl(TCG_COND_NE, lsb, PRED, false_label); \
 tcg_gen_gvec_mov(MO_64, VdV_off, VuV_off, \
  sizeof(MMVector), sizeof(MMVector)); \
-tcg_gen_br(end_label); \
 gen_set_label(false_label); \
-tcg_gen_ori_tl(hex_slot_cancelled, hex_slot_cancelled, \
-   1 << insn->slot); \
-gen_set_label(end_label); \
 } while (0)
 
 
@@ -547,17 +542,12 @@ static inline void assert_vhist_tmp(DisasContext *ctx)
 do { \
 TCGv LSB = tcg_temp_new(); \
 TCGLabel *false_label = gen_new_label(); \
-TCGLabel *end_label = gen_new_label(); \
 GET_EA; \
 PRED; \
 tcg_gen_brcondi_tl(TCG_COND_EQ, LSB, 0, false_label); \
 gen_vreg_load(ctx, DSTOFF, EA, true); \
 INC; \
-tcg_gen_br(end_label); \
 gen_set_label(false_label); \
-tcg_gen_ori_tl(hex_slot_cancelled, hex_slot_cancelled, \
-   1 << insn->slot); \
-gen_set_label(end_label); \
 } while (0)
 
 #define fGEN_TCG_PRED_VEC_LOAD_pred_pi \
@@ -717,17 +707,12 @@ static inline void assert_vhist_tmp(DisasContext *ctx)
 do { \
 TCGv LSB = tcg_temp_new(); \
 TCGLabel *false_label = gen_new_label(); \
-TCGLabel *end_label = gen_new_label(); \
 GET_EA; \
 PRED; \
 tcg_gen_brcondi_tl(TCG_COND_EQ, LSB, 0, false_label); \
 gen_vreg_store(ctx, EA, SRCOFF, insn->slot, ALIGN); \
 INC; \
-tcg_gen_br(end_label); \
 gen_set_label(false_label); \
-tcg_gen_ori_tl(hex_slot_cancelled, hex_slot_cancelled, \
-   1 << insn->slot); \
-gen_set_label(end_label); \
 } while (0)
 
 #define fGEN_TCG_PRED_VEC_STORE_pred_pi(ALIGN) \
diff --git a/target/hexagon/translate.h b/target/hexagon/translate.h
index 6e59a90c41..db832b0f88 100644
--- a/target/hexagon/translate.h
+++ b/target/hexagon/translate.h
@@ -49,7 +49,6 @@ typedef struct DisasContext {
 int tmp_vregs_idx;
 int tmp_vregs_num[VECTOR_TEMPS_MAX];
 int vreg_log[NUM_VREGS];
-bool vreg_is_predicated[NUM_VREGS];
 int vreg_log_idx;
 DECLARE_BITMAP(vregs_updated_tmp, NUM_VREGS);
 DECLARE_BITMAP(vregs_updated, NUM_VREGS);
@@ -57,7 +56,6 @@ typedef struct DisasContext {
 

[PATCH v6 06/14] Hexagon (target/hexagon) Don't set pkt_has_store_s1 when not needed

2023-03-06 Thread Taylor Simpson
The pkt_has_store_s1 field in CPUHexagonState is only needed in generated
helpers for scalar load instructions.  See check_noshuf and mem_load[1248]
in op_helper.c.

We add logic in gen_analyze_funcs.py to set need_pkt_has_store_s1 in
DisasContext when it is needed at runtime.

Signed-off-by: Taylor Simpson 
Reviewed-by: Anton Johansson 
---
 target/hexagon/translate.h  | 1 +
 target/hexagon/attribs_def.h.inc| 1 +
 target/hexagon/translate.c  | 6 +-
 target/hexagon/gen_analyze_funcs.py | 5 +
 target/hexagon/hex_common.py| 1 +
 5 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/target/hexagon/translate.h b/target/hexagon/translate.h
index d45d3a4bb0..34368b2186 100644
--- a/target/hexagon/translate.h
+++ b/target/hexagon/translate.h
@@ -61,6 +61,7 @@ typedef struct DisasContext {
 TCGCond branch_cond;
 target_ulong branch_dest;
 bool is_tight_loop;
+bool need_pkt_has_store_s1;
 } DisasContext;
 
 static inline void ctx_log_pred_write(DisasContext *ctx, int pnum)
diff --git a/target/hexagon/attribs_def.h.inc b/target/hexagon/attribs_def.h.inc
index 5d2a102c18..9874d1658f 100644
--- a/target/hexagon/attribs_def.h.inc
+++ b/target/hexagon/attribs_def.h.inc
@@ -44,6 +44,7 @@ DEF_ATTRIB(MEMSIZE_1B, "Memory width is 1 byte", "", "")
 DEF_ATTRIB(MEMSIZE_2B, "Memory width is 2 bytes", "", "")
 DEF_ATTRIB(MEMSIZE_4B, "Memory width is 4 bytes", "", "")
 DEF_ATTRIB(MEMSIZE_8B, "Memory width is 8 bytes", "", "")
+DEF_ATTRIB(SCALAR_LOAD, "Load is scalar", "", "")
 DEF_ATTRIB(SCALAR_STORE, "Store is scalar", "", "")
 DEF_ATTRIB(REGWRSIZE_1B, "Memory width is 1 byte", "", "")
 DEF_ATTRIB(REGWRSIZE_2B, "Memory width is 2 bytes", "", "")
diff --git a/target/hexagon/translate.c b/target/hexagon/translate.c
index 9e5fcee1ee..01671d5451 100644
--- a/target/hexagon/translate.c
+++ b/target/hexagon/translate.c
@@ -333,6 +333,7 @@ static void mark_implicit_pred_writes(DisasContext *ctx)
 static void analyze_packet(DisasContext *ctx)
 {
 Packet *pkt = ctx->pkt;
+ctx->need_pkt_has_store_s1 = false;
 for (int i = 0; i < pkt->num_insns; i++) {
 Insn *insn = >insn[i];
 ctx->insn = insn;
@@ -367,12 +368,15 @@ static void gen_start_packet(DisasContext *ctx)
 for (i = 0; i < STORES_MAX; i++) {
 ctx->store_width[i] = 0;
 }
-tcg_gen_movi_tl(hex_pkt_has_store_s1, pkt->pkt_has_store_s1);
 ctx->s1_store_processed = false;
 ctx->pre_commit = true;
 
 analyze_packet(ctx);
 
+if (ctx->need_pkt_has_store_s1) {
+tcg_gen_movi_tl(hex_pkt_has_store_s1, pkt->pkt_has_store_s1);
+}
+
 /*
  * pregs_written is used both in the analyze phase as well as the code
  * gen phase, so clear it again.
diff --git a/target/hexagon/gen_analyze_funcs.py 
b/target/hexagon/gen_analyze_funcs.py
index 37c166dc0d..7e1f221b3c 100755
--- a/target/hexagon/gen_analyze_funcs.py
+++ b/target/hexagon/gen_analyze_funcs.py
@@ -200,6 +200,11 @@ def gen_analyze_func(f, tag, regs, imms):
 analyze_opn(f, tag, regtype, regid, toss, numregs, i)
 i += 1
 
+has_generated_helper = (not hex_common.skip_qemu_helper(tag) and
+not hex_common.is_idef_parser_enabled(tag))
+if (has_generated_helper and
+'A_SCALAR_LOAD' in hex_common.attribdict[tag]):
+f.write("ctx->need_pkt_has_store_s1 = true;\n")
 
 f.write("}\n\n")
 
diff --git a/target/hexagon/hex_common.py b/target/hexagon/hex_common.py
index a29f61bb4f..76da362c11 100755
--- a/target/hexagon/hex_common.py
+++ b/target/hexagon/hex_common.py
@@ -89,6 +89,7 @@ def calculate_attribs():
 add_qemu_macro_attrib('fWRITE_P3', 'A_WRITES_PRED_REG')
 add_qemu_macro_attrib('fSET_OVERFLOW', 'A_IMPLICIT_WRITES_USR')
 add_qemu_macro_attrib('fSET_LPCFG', 'A_IMPLICIT_WRITES_USR')
+add_qemu_macro_attrib('fLOAD', 'A_SCALAR_LOAD')
 add_qemu_macro_attrib('fSTORE', 'A_SCALAR_STORE')
 
 # Recurse down macros, find attributes from sub-macros
-- 
2.25.1



[PATCH v6 09/14] Hexagon (tests/tcg/hexagon) Remove __builtin from scatter_gather

2023-03-06 Thread Taylor Simpson
Replace __builtin_* with inline assembly
The __builtin's are subject to change with different compiler
releases, so might break
Mark arrays as aligned when accessed as HVX vectors
Clean up comments

Signed-off-by: Taylor Simpson 
Reviewed-by: Anton Johansson 
---
 tests/tcg/hexagon/scatter_gather.c | 513 +++--
 1 file changed, 271 insertions(+), 242 deletions(-)

diff --git a/tests/tcg/hexagon/scatter_gather.c 
b/tests/tcg/hexagon/scatter_gather.c
index b93eb18133..bf8b5e0317 100644
--- a/tests/tcg/hexagon/scatter_gather.c
+++ b/tests/tcg/hexagon/scatter_gather.c
@@ -1,5 +1,5 @@
 /*
- *  Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
+ *  Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -40,47 +40,6 @@ typedef long HVX_VectorPair   
__attribute__((__vector_size__(256)))
 typedef long HVX_VectorPred   __attribute__((__vector_size__(128)))
   __attribute__((aligned(128)));
 
-#define VSCATTER_16(BASE, RGN, OFF, VALS) \
-__builtin_HEXAGON_V6_vscattermh_128B((int)BASE, RGN, OFF, VALS)
-#define VSCATTER_16_MASKED(MASK, BASE, RGN, OFF, VALS) \
-__builtin_HEXAGON_V6_vscattermhq_128B(MASK, (int)BASE, RGN, OFF, VALS)
-#define VSCATTER_32(BASE, RGN, OFF, VALS) \
-__builtin_HEXAGON_V6_vscattermw_128B((int)BASE, RGN, OFF, VALS)
-#define VSCATTER_32_MASKED(MASK, BASE, RGN, OFF, VALS) \
-__builtin_HEXAGON_V6_vscattermwq_128B(MASK, (int)BASE, RGN, OFF, VALS)
-#define VSCATTER_16_32(BASE, RGN, OFF, VALS) \
-__builtin_HEXAGON_V6_vscattermhw_128B((int)BASE, RGN, OFF, VALS)
-#define VSCATTER_16_32_MASKED(MASK, BASE, RGN, OFF, VALS) \
-__builtin_HEXAGON_V6_vscattermhwq_128B(MASK, (int)BASE, RGN, OFF, VALS)
-#define VSCATTER_16_ACC(BASE, RGN, OFF, VALS) \
-__builtin_HEXAGON_V6_vscattermh_add_128B((int)BASE, RGN, OFF, VALS)
-#define VSCATTER_32_ACC(BASE, RGN, OFF, VALS) \
-__builtin_HEXAGON_V6_vscattermw_add_128B((int)BASE, RGN, OFF, VALS)
-#define VSCATTER_16_32_ACC(BASE, RGN, OFF, VALS) \
-__builtin_HEXAGON_V6_vscattermhw_add_128B((int)BASE, RGN, OFF, VALS)
-
-#define VGATHER_16(DSTADDR, BASE, RGN, OFF) \
-__builtin_HEXAGON_V6_vgathermh_128B(DSTADDR, (int)BASE, RGN, OFF)
-#define VGATHER_16_MASKED(DSTADDR, MASK, BASE, RGN, OFF) \
-__builtin_HEXAGON_V6_vgathermhq_128B(DSTADDR, MASK, (int)BASE, RGN, OFF)
-#define VGATHER_32(DSTADDR, BASE, RGN, OFF) \
-__builtin_HEXAGON_V6_vgathermw_128B(DSTADDR, (int)BASE, RGN, OFF)
-#define VGATHER_32_MASKED(DSTADDR, MASK, BASE, RGN, OFF) \
-__builtin_HEXAGON_V6_vgathermwq_128B(DSTADDR, MASK, (int)BASE, RGN, OFF)
-#define VGATHER_16_32(DSTADDR, BASE, RGN, OFF) \
-__builtin_HEXAGON_V6_vgathermhw_128B(DSTADDR, (int)BASE, RGN, OFF)
-#define VGATHER_16_32_MASKED(DSTADDR, MASK, BASE, RGN, OFF) \
-__builtin_HEXAGON_V6_vgathermhwq_128B(DSTADDR, MASK, (int)BASE, RGN, OFF)
-
-#define VSHUFF_H(V) \
-__builtin_HEXAGON_V6_vshuffh_128B(V)
-#define VSPLAT_H(X) \
-__builtin_HEXAGON_V6_lvsplath_128B(X)
-#define VAND_VAL(PRED, VAL) \
-__builtin_HEXAGON_V6_vandvrt_128B(PRED, VAL)
-#define VDEAL_H(V) \
-__builtin_HEXAGON_V6_vdealh_128B(V)
-
 int err;
 
 /* define the number of rows/cols in a square matrix */
@@ -108,22 +67,22 @@ unsigned short vscatter16_32_ref[SCATTER_BUFFER_SIZE];
 unsigned short vgather16_32_ref[MATRIX_SIZE];
 
 /* declare the arrays of offsets */
-unsigned short half_offsets[MATRIX_SIZE];
-unsigned int   word_offsets[MATRIX_SIZE];
+unsigned short half_offsets[MATRIX_SIZE] __attribute__((aligned(128)));
+unsigned int   word_offsets[MATRIX_SIZE] __attribute__((aligned(128)));
 
 /* declare the arrays of values */
-unsigned short half_values[MATRIX_SIZE];
-unsigned short half_values_acc[MATRIX_SIZE];
-unsigned short half_values_masked[MATRIX_SIZE];
-unsigned int   word_values[MATRIX_SIZE];
-unsigned int   word_values_acc[MATRIX_SIZE];
-unsigned int   word_values_masked[MATRIX_SIZE];
+unsigned short half_values[MATRIX_SIZE] __attribute__((aligned(128)));
+unsigned short half_values_acc[MATRIX_SIZE] __attribute__((aligned(128)));
+unsigned short half_values_masked[MATRIX_SIZE] __attribute__((aligned(128)));
+unsigned int   word_values[MATRIX_SIZE] __attribute__((aligned(128)));
+unsigned int   word_values_acc[MATRIX_SIZE] __attribute__((aligned(128)));
+unsigned int   word_values_masked[MATRIX_SIZE] __attribute__((aligned(128)));
 
 /* declare the arrays of predicates */
-unsigned short half_predicates[MATRIX_SIZE];
-unsigned int   word_predicates[MATRIX_SIZE];
+unsigned short half_predicates[MATRIX_SIZE] __attribute__((aligned(128)));
+unsigned int   word_predicates[MATRIX_SIZE] __attribute__((aligned(128)));
 
-/* make this big enough for all the intrinsics */
+/* make this big enough for all the operations */
 const size_t region_len = 

[PATCH v6 02/14] Hexagon (target/hexagon) Add overrides for callr

2023-03-06 Thread Taylor Simpson
Add overrides for
J2_callr
J2_callrt
J2_callrf

Signed-off-by: Taylor Simpson 
Reviewed-by: Anton Johansson 
---
 target/hexagon/gen_tcg.h |  6 ++
 target/hexagon/macros.h  | 12 +---
 target/hexagon/genptr.c  | 18 ++
 3 files changed, 25 insertions(+), 11 deletions(-)

diff --git a/target/hexagon/gen_tcg.h b/target/hexagon/gen_tcg.h
index 5f61c95b40..fa0dbbec7d 100644
--- a/target/hexagon/gen_tcg.h
+++ b/target/hexagon/gen_tcg.h
@@ -589,11 +589,17 @@
 
 #define fGEN_TCG_J2_call(SHORTCODE) \
 gen_call(ctx, riV)
+#define fGEN_TCG_J2_callr(SHORTCODE) \
+gen_callr(ctx, RsV)
 
 #define fGEN_TCG_J2_callt(SHORTCODE) \
 gen_cond_call(ctx, PuV, TCG_COND_EQ, riV)
 #define fGEN_TCG_J2_callf(SHORTCODE) \
 gen_cond_call(ctx, PuV, TCG_COND_NE, riV)
+#define fGEN_TCG_J2_callrt(SHORTCODE) \
+gen_cond_callr(ctx, TCG_COND_EQ, PuV, RsV)
+#define fGEN_TCG_J2_callrf(SHORTCODE) \
+gen_cond_callr(ctx, TCG_COND_NE, PuV, RsV)
 
 #define fGEN_TCG_J2_endloop0(SHORTCODE) \
 gen_endloop0(ctx)
diff --git a/target/hexagon/macros.h b/target/hexagon/macros.h
index 17facadaad..6974ef6c9e 100644
--- a/target/hexagon/macros.h
+++ b/target/hexagon/macros.h
@@ -1,5 +1,5 @@
 /*
- *  Copyright(c) 2019-2022 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
+ *  Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -415,16 +415,6 @@ static inline TCGv gen_read_ireg(TCGv result, TCGv val, 
int shift)
 #define fBRANCH(LOC, TYPE)  fWRITE_NPC(LOC)
 #define fJUMPR(REGNO, TARGET, TYPE) fBRANCH(TARGET, COF_TYPE_JUMPR)
 #define fHINTJR(TARGET) { /* Not modelled in qemu */}
-#define fCALL(A) \
-do { \
-fWRITE_LR(fREAD_NPC()); \
-fBRANCH(A, COF_TYPE_CALL); \
-} while (0)
-#define fCALLR(A) \
-do { \
-fWRITE_LR(fREAD_NPC()); \
-fBRANCH(A, COF_TYPE_CALLR); \
-} while (0)
 #define fWRITE_LOOP_REGS0(START, COUNT) \
 do { \
 WRITE_RREG(HEX_REG_LC0, COUNT);  \
diff --git a/target/hexagon/genptr.c b/target/hexagon/genptr.c
index 2bbe4e3a68..592438f61e 100644
--- a/target/hexagon/genptr.c
+++ b/target/hexagon/genptr.c
@@ -682,6 +682,13 @@ static void gen_call(DisasContext *ctx, int pc_off)
 gen_write_new_pc_pcrel(ctx, pc_off, TCG_COND_ALWAYS, NULL);
 }
 
+static void gen_callr(DisasContext *ctx, TCGv new_pc)
+{
+TCGv next_PC = tcg_constant_tl(ctx->next_PC);
+gen_log_reg_write(HEX_REG_LR, next_PC);
+gen_write_new_pc_addr(ctx, new_pc, TCG_COND_ALWAYS, NULL);
+}
+
 static void gen_cond_call(DisasContext *ctx, TCGv pred,
   TCGCond cond, int pc_off)
 {
@@ -697,6 +704,17 @@ static void gen_cond_call(DisasContext *ctx, TCGv pred,
 gen_set_label(skip);
 }
 
+static void gen_cond_callr(DisasContext *ctx,
+   TCGCond cond, TCGv pred, TCGv new_pc)
+{
+TCGv lsb = tcg_temp_new();
+TCGLabel *skip = gen_new_label();
+tcg_gen_andi_tl(lsb, pred, 1);
+tcg_gen_brcondi_tl(cond, lsb, 0, skip);
+gen_callr(ctx, new_pc);
+gen_set_label(skip);
+}
+
 static void gen_endloop0(DisasContext *ctx)
 {
 TCGv lpcfg = tcg_temp_new();
-- 
2.25.1



Re: [PATCH v4 08/14] vfio/common: Record DMA mapped IOVA ranges

2023-03-06 Thread Alex Williamson
On Tue,  7 Mar 2023 02:02:52 +
Joao Martins  wrote:

> According to the device DMA logging uAPI, IOVA ranges to be logged by
> the device must be provided all at once upon DMA logging start.
> 
> As preparation for the following patches which will add device dirty
> page tracking, keep a record of all DMA mapped IOVA ranges so later they
> can be used for DMA logging start.
> 
> Signed-off-by: Avihai Horon 
> Signed-off-by: Joao Martins 
> ---
>  hw/vfio/common.c  | 76 +++
>  hw/vfio/trace-events  |  1 +
>  include/hw/vfio/vfio-common.h | 13 ++
>  3 files changed, 90 insertions(+)
> 
> diff --git a/hw/vfio/common.c b/hw/vfio/common.c
> index 3a6491dbc523..a9b1fc999121 100644
> --- a/hw/vfio/common.c
> +++ b/hw/vfio/common.c
> @@ -1334,11 +1334,87 @@ static int vfio_set_dirty_page_tracking(VFIOContainer 
> *container, bool start)
>  return ret;
>  }
>  
> +static void vfio_dirty_tracking_update(MemoryListener *listener,
> +   MemoryRegionSection *section)
> +{
> +VFIODirtyRanges *dirty = container_of(listener, VFIODirtyRanges, 
> listener);
> +VFIODirtyTrackingRange *range = >ranges;
> +hwaddr max32 = UINT32_MAX - 1ULL;

The -1 is wrong here, UINT32_MAX is (2^32 - 1)

> +hwaddr iova, end;
> +
> +if (!vfio_listener_valid_section(section) ||
> +!vfio_get_section_iova_range(dirty->container, section,
> + , , NULL)) {
> +return;
> +}
> +
> +/*
> + * The address space passed to the dirty tracker is reduced to two 
> ranges:
> + * one for 32-bit DMA ranges, and another one for 64-bit DMA ranges.
> + * The underlying reports of dirty will query a sub-interval of each of
> + * these ranges.
> + *
> + * The purpose of the dual range handling is to handle known cases of big
> + * holes in the address space, like the x86 AMD 1T hole. The alternative
> + * would be an IOVATree but that has a much bigger runtime overhead and
> + * unnecessary complexity.
> + */
> +if (iova < max32 && end <= max32) {

Nit, the first test is redundant, iova is necessarily less than end.

> +if (range->min32 > iova) {
> +range->min32 = iova;
> +}
> +if (range->max32 < end) {
> +range->max32 = end;
> +}
> +trace_vfio_device_dirty_tracking_update(iova, end,
> +range->min32, range->max32);
> +} else {
> +if (!range->min64 || range->min64 > iova) {

The first test should be removed, we're initializing min64 to a
non-zero value now, so if it's zero it's been set and we can't
de-prioritize that set value.

> +range->min64 = iova;
> +}
> +if (range->max64 < end) {
> +range->max64 = end;
> +}
> +trace_vfio_device_dirty_tracking_update(iova, end,
> +range->min64, range->max64);
> +}
> +
> +return;
> +}
> +
> +static const MemoryListener vfio_dirty_tracking_listener = {
> +.name = "vfio-tracking",
> +.region_add = vfio_dirty_tracking_update,
> +};
> +
> +static void vfio_dirty_tracking_init(VFIOContainer *container,
> + VFIODirtyRanges *dirty)
> +{
> +memset(dirty, 0, sizeof(*dirty));
> +dirty->ranges.min32 = UINT32_MAX;
> +dirty->ranges.min64 = UINT64_MAX;
> +dirty->listener = vfio_dirty_tracking_listener;
> +dirty->container = container;
> +

I was actually thinking the caller would just pass
VFIODirtyTrackingRange and VFIODirtyRanges would be allocated on the
stack here, perhaps both are defined private to this file, but this
works and we can refine later if we so decide.  Thanks,

Alex


> +memory_listener_register(>listener,
> + container->space->as);
> +
> +/*
> + * The memory listener is synchronous, and used to calculate the range
> + * to dirty tracking. Unregister it after we are done as we are not
> + * interested in any follow-up updates.
> + */
> +memory_listener_unregister(>listener);
> +}
> +
>  static void vfio_listener_log_global_start(MemoryListener *listener)
>  {
>  VFIOContainer *container = container_of(listener, VFIOContainer, 
> listener);
> +VFIODirtyRanges dirty;
>  int ret;
>  
> +vfio_dirty_tracking_init(container, );
> +
>  ret = vfio_set_dirty_page_tracking(container, true);
>  if (ret) {
>  vfio_set_migration_error(ret);
> diff --git a/hw/vfio/trace-events b/hw/vfio/trace-events
> index 669d9fe07cd9..d97a6de17921 100644
> --- a/hw/vfio/trace-events
> +++ b/hw/vfio/trace-events
> @@ -104,6 +104,7 @@ vfio_known_safe_misalignment(const char *name, uint64_t 
> iova, uint64_t offset_wi
>  vfio_listener_region_add_no_dma_map(const char *name, uint64_t iova, 
> uint64_t size, uint64_t page_size) "Region \"%s\" 0x%"PRIx64" 
> size=0x%"PRIx64" is not 

Re: [PATCH v4 4/5] docs/about/deprecated: Deprecate 32-bit arm hosts for system emulation

2023-03-06 Thread Richard Henderson

On 3/6/23 00:46, Thomas Huth wrote:

+continuous to be supported on 32-bit arm hosts, too)


"continues"

Acked-by: Richard Henderson 


r~



  1   2   3   4   5   6   >