From 6909b616efbc9b627a0c9ea87d25a10d508cc879 Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Wed, 25 Sep 2024 23:14:08 +0200 Subject: hw/microblaze: Restrict MemoryRegionOps are implemented as 32-bit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All these MemoryRegionOps read() and write() handlers are implemented expecting 32-bit accesses. Clarify that setting .impl.min/max_access_size fields. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Anton Johansson Message-Id: <20241105130431.22564-8-philmd@linaro.org> --- hw/net/xilinx_ethlite.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'hw/net/xilinx_ethlite.c') diff --git a/hw/net/xilinx_ethlite.c b/hw/net/xilinx_ethlite.c index 4c0c7fcae3..88ab331acc 100644 --- a/hw/net/xilinx_ethlite.c +++ b/hw/net/xilinx_ethlite.c @@ -166,6 +166,10 @@ static const MemoryRegionOps eth_ops = { .read = eth_read, .write = eth_write, .endianness = DEVICE_NATIVE_ENDIAN, + .impl = { + .min_access_size = 4, + .max_access_size = 4, + }, .valid = { .min_access_size = 4, .max_access_size = 4 -- cgit 1.4.1 From fa3ca9aa1ceb9b762f4c7a51245226f247e35560 Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Sat, 9 Nov 2024 19:35:36 +0100 Subject: hw/net/xilinx_ethlite: Map MDIO registers (as unimplemented) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rather than handling the MDIO registers as RAM, map them as unimplemented I/O within the device MR. The memory flat view becomes: (qemu) info mtree -f FlatView #0 Root memory region: system 0000000081000000-00000000810007e3 (prio 0, i/o): xlnx.xps-ethernetlite 00000000810007e4-00000000810007f3 (prio 0, i/o): ethlite.mdio 00000000810007f4-0000000081001fff (prio 0, i/o): xlnx.xps-ethernetlite @00000000000007f4 Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Edgar E. Iglesias Message-Id: <20241112181044.92193-7-philmd@linaro.org> --- hw/net/xilinx_ethlite.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'hw/net/xilinx_ethlite.c') diff --git a/hw/net/xilinx_ethlite.c b/hw/net/xilinx_ethlite.c index 88ab331acc..442467abeb 100644 --- a/hw/net/xilinx_ethlite.c +++ b/hw/net/xilinx_ethlite.c @@ -28,15 +28,18 @@ #include "qemu/osdep.h" #include "qemu/module.h" #include "qom/object.h" +#include "qapi/error.h" #include "exec/tswap.h" #include "hw/sysbus.h" #include "hw/irq.h" #include "hw/qdev-properties.h" +#include "hw/misc/unimp.h" #include "net/net.h" #include "trace.h" #define R_TX_BUF0 0 #define BUFSZ_MAX 0x07e4 +#define A_MDIO_BASE 0x07e4 #define R_TX_LEN0 (0x07f4 / 4) #define R_TX_GIE0 (0x07f8 / 4) #define R_TX_CTRL0 (0x07fc / 4) @@ -72,6 +75,7 @@ struct XlnxXpsEthLite uint32_t c_rx_pingpong; unsigned int port_index; /* dual port RAM index */ + UnimplementedDeviceState mdio; uint32_t regs[R_MAX]; }; @@ -232,6 +236,14 @@ static void xilinx_ethlite_realize(DeviceState *dev, Error **errp) { XlnxXpsEthLite *s = XILINX_ETHLITE(dev); + object_initialize_child(OBJECT(dev), "ethlite.mdio", &s->mdio, + TYPE_UNIMPLEMENTED_DEVICE); + qdev_prop_set_string(DEVICE(&s->mdio), "name", "ethlite.mdio"); + qdev_prop_set_uint64(DEVICE(&s->mdio), "size", 4 * 4); + sysbus_realize(SYS_BUS_DEVICE(&s->mdio), &error_fatal); + memory_region_add_subregion(&s->mmio, A_MDIO_BASE, + sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->mdio), 0)); + qemu_macaddr_default_if_unset(&s->conf.macaddr); s->nic = qemu_new_nic(&net_xilinx_ethlite_info, &s->conf, object_get_typename(OBJECT(dev)), dev->id, -- cgit 1.4.1 From 8d956610f5e79bcc53a9f296ebecd53ee7c449ca Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Mon, 11 Nov 2024 18:49:56 +0100 Subject: hw/net/xilinx_ethlite: Introduce txbuf_ptr() helper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For a particular physical address within the EthLite MMIO range, addr_to_port_index() returns which port is accessed. txbuf_ptr() points to the beginning of a (RAM) TX buffer within the device state. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Edgar E. Iglesias Message-Id: <20241112181044.92193-10-philmd@linaro.org> --- hw/net/xilinx_ethlite.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'hw/net/xilinx_ethlite.c') diff --git a/hw/net/xilinx_ethlite.c b/hw/net/xilinx_ethlite.c index 442467abeb..8df621904a 100644 --- a/hw/net/xilinx_ethlite.c +++ b/hw/net/xilinx_ethlite.c @@ -27,6 +27,7 @@ #include "qemu/osdep.h" #include "qemu/module.h" +#include "qemu/bitops.h" #include "qom/object.h" #include "qapi/error.h" #include "exec/tswap.h" @@ -87,6 +88,18 @@ static inline void eth_pulse_irq(XlnxXpsEthLite *s) } } +static unsigned addr_to_port_index(hwaddr addr) +{ + return extract64(addr, 11, 1); +} + +static void *txbuf_ptr(XlnxXpsEthLite *s, unsigned port_index) +{ + unsigned int rxbase = port_index * (0x800 / 4); + + return &s->regs[rxbase + R_TX_BUF0]; +} + static uint64_t eth_read(void *opaque, hwaddr addr, unsigned int size) { @@ -119,6 +132,7 @@ eth_write(void *opaque, hwaddr addr, uint64_t val64, unsigned int size) { XlnxXpsEthLite *s = opaque; + unsigned int port_index = addr_to_port_index(addr); unsigned int base = 0; uint32_t value = val64; @@ -132,12 +146,12 @@ eth_write(void *opaque, hwaddr addr, if ((value & (CTRL_P | CTRL_S)) == CTRL_S) { qemu_send_packet(qemu_get_queue(s->nic), - (void *) &s->regs[base], + txbuf_ptr(s, port_index), s->regs[base + R_TX_LEN0]); if (s->regs[base + R_TX_CTRL0] & CTRL_I) eth_pulse_irq(s); } else if ((value & (CTRL_P | CTRL_S)) == (CTRL_P | CTRL_S)) { - memcpy(&s->conf.macaddr.a[0], &s->regs[base], 6); + memcpy(&s->conf.macaddr.a[0], txbuf_ptr(s, port_index), 6); if (s->regs[base + R_TX_CTRL0] & CTRL_I) eth_pulse_irq(s); } -- cgit 1.4.1 From 785fd1a9afd5cb894f3e53753d732c7fbbb3d74a Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Mon, 11 Nov 2024 18:51:57 +0100 Subject: hw/net/xilinx_ethlite: Introduce rxbuf_ptr() helper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit rxbuf_ptr() points to the beginning of a (RAM) RX buffer within the device state. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Edgar E. Iglesias Message-Id: <20241112181044.92193-11-philmd@linaro.org> --- hw/net/xilinx_ethlite.c | 39 +++++++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 10 deletions(-) (limited to 'hw/net/xilinx_ethlite.c') diff --git a/hw/net/xilinx_ethlite.c b/hw/net/xilinx_ethlite.c index 8df621904a..67adecc088 100644 --- a/hw/net/xilinx_ethlite.c +++ b/hw/net/xilinx_ethlite.c @@ -60,6 +60,12 @@ #define CTRL_P 0x2 #define CTRL_S 0x1 +typedef struct XlnxXpsEthLitePort { + struct { + uint32_t rx_ctrl; + } reg; +} XlnxXpsEthLitePort; + #define TYPE_XILINX_ETHLITE "xlnx.xps-ethernetlite" OBJECT_DECLARE_SIMPLE_TYPE(XlnxXpsEthLite, XILINX_ETHLITE) @@ -77,6 +83,7 @@ struct XlnxXpsEthLite unsigned int port_index; /* dual port RAM index */ UnimplementedDeviceState mdio; + XlnxXpsEthLitePort port[2]; uint32_t regs[R_MAX]; }; @@ -100,10 +107,18 @@ static void *txbuf_ptr(XlnxXpsEthLite *s, unsigned port_index) return &s->regs[rxbase + R_TX_BUF0]; } +static void *rxbuf_ptr(XlnxXpsEthLite *s, unsigned port_index) +{ + unsigned int rxbase = port_index * (0x800 / 4); + + return &s->regs[rxbase + R_RX_BUF0]; +} + static uint64_t eth_read(void *opaque, hwaddr addr, unsigned int size) { XlnxXpsEthLite *s = opaque; + unsigned port_index = addr_to_port_index(addr); uint32_t r = 0; addr >>= 2; @@ -115,9 +130,12 @@ eth_read(void *opaque, hwaddr addr, unsigned int size) case R_TX_LEN1: case R_TX_CTRL1: case R_TX_CTRL0: + r = s->regs[addr]; + break; + case R_RX_CTRL1: case R_RX_CTRL0: - r = s->regs[addr]; + r = s->port[port_index].reg.rx_ctrl; break; default: @@ -167,7 +185,9 @@ eth_write(void *opaque, hwaddr addr, if (!(value & CTRL_S)) { qemu_flush_queued_packets(qemu_get_queue(s->nic)); } - /* fall through */ + s->port[port_index].reg.rx_ctrl = value; + break; + case R_TX_LEN0: case R_TX_LEN1: case R_TX_GIE0: @@ -197,22 +217,21 @@ static const MemoryRegionOps eth_ops = { static bool eth_can_rx(NetClientState *nc) { XlnxXpsEthLite *s = qemu_get_nic_opaque(nc); - unsigned int rxbase = s->port_index * (0x800 / 4); - return !(s->regs[rxbase + R_RX_CTRL0] & CTRL_S); + return !(s->port[s->port_index].reg.rx_ctrl & CTRL_S); } static ssize_t eth_rx(NetClientState *nc, const uint8_t *buf, size_t size) { XlnxXpsEthLite *s = qemu_get_nic_opaque(nc); - unsigned int rxbase = s->port_index * (0x800 / 4); + unsigned int port_index = s->port_index; /* DA filter. */ if (!(buf[0] & 0x80) && memcmp(&s->conf.macaddr.a[0], buf, 6)) return size; - if (s->regs[rxbase + R_RX_CTRL0] & CTRL_S) { - trace_ethlite_pkt_lost(s->regs[R_RX_CTRL0]); + if (s->port[port_index].reg.rx_ctrl & CTRL_S) { + trace_ethlite_pkt_lost(s->port[port_index].reg.rx_ctrl); return -1; } @@ -220,10 +239,10 @@ static ssize_t eth_rx(NetClientState *nc, const uint8_t *buf, size_t size) trace_ethlite_pkt_size_too_big(size); return -1; } - memcpy(&s->regs[rxbase + R_RX_BUF0], buf, size); + memcpy(rxbuf_ptr(s, port_index), buf, size); - s->regs[rxbase + R_RX_CTRL0] |= CTRL_S; - if (s->regs[R_RX_CTRL0] & CTRL_I) { + s->port[port_index].reg.rx_ctrl |= CTRL_S; + if (s->port[port_index].reg.rx_ctrl & CTRL_I) { eth_pulse_irq(s); } -- cgit 1.4.1 From 64fdbae7e1bc6408204a3cf3b8e6a2e7d8e36fe2 Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Sat, 9 Nov 2024 19:45:58 +0100 Subject: hw/net/xilinx_ethlite: Access TX_GIE register for each port MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rather than accessing the registers within the mixed RAM/MMIO region as indexed register, declare a per-port TX_GIE. This will help to map the RAM as RAM (keeping MMIO as MMIO) in few commits. Previous s->regs[R_TX_GIE0] and s->regs[R_TX_GIE1] are now unused. Not a concern, this array will soon disappear. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Edgar E. Iglesias Message-Id: <20241112181044.92193-13-philmd@linaro.org> --- hw/net/xilinx_ethlite.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'hw/net/xilinx_ethlite.c') diff --git a/hw/net/xilinx_ethlite.c b/hw/net/xilinx_ethlite.c index 67adecc088..3252c9d508 100644 --- a/hw/net/xilinx_ethlite.c +++ b/hw/net/xilinx_ethlite.c @@ -62,6 +62,8 @@ typedef struct XlnxXpsEthLitePort { struct { + uint32_t tx_gie; + uint32_t rx_ctrl; } reg; } XlnxXpsEthLitePort; @@ -90,7 +92,7 @@ struct XlnxXpsEthLite static inline void eth_pulse_irq(XlnxXpsEthLite *s) { /* Only the first gie reg is active. */ - if (s->regs[R_TX_GIE0] & GIE_GIE) { + if (s->port[0].reg.tx_gie & GIE_GIE) { qemu_irq_pulse(s->irq); } } @@ -126,6 +128,9 @@ eth_read(void *opaque, hwaddr addr, unsigned int size) switch (addr) { case R_TX_GIE0: + r = s->port[port_index].reg.tx_gie; + break; + case R_TX_LEN0: case R_TX_LEN1: case R_TX_CTRL1: @@ -190,10 +195,13 @@ eth_write(void *opaque, hwaddr addr, case R_TX_LEN0: case R_TX_LEN1: - case R_TX_GIE0: s->regs[addr] = value; break; + case R_TX_GIE0: + s->port[port_index].reg.tx_gie = value; + break; + default: s->regs[addr] = tswap32(value); break; -- cgit 1.4.1 From c629791859d5d1777d8471f260f418e76078e97e Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Sat, 9 Nov 2024 19:48:36 +0100 Subject: hw/net/xilinx_ethlite: Access TX_LEN register for each port MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rather than accessing the registers within the mixed RAM/MMIO region as indexed register, declare a per-port TX_LEN. This will help to map the RAM as RAM (keeping MMIO as MMIO) in few commits. Previous s->regs[R_TX_LEN0] and s->regs[R_TX_LEN1] are now unused. Not a concern, this array will soon disappear. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Edgar E. Iglesias Message-Id: <20241112181044.92193-14-philmd@linaro.org> --- hw/net/xilinx_ethlite.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'hw/net/xilinx_ethlite.c') diff --git a/hw/net/xilinx_ethlite.c b/hw/net/xilinx_ethlite.c index 3252c9d508..ce9555bd1e 100644 --- a/hw/net/xilinx_ethlite.c +++ b/hw/net/xilinx_ethlite.c @@ -62,6 +62,7 @@ typedef struct XlnxXpsEthLitePort { struct { + uint32_t tx_len; uint32_t tx_gie; uint32_t rx_ctrl; @@ -133,6 +134,9 @@ eth_read(void *opaque, hwaddr addr, unsigned int size) case R_TX_LEN0: case R_TX_LEN1: + r = s->port[port_index].reg.tx_len; + break; + case R_TX_CTRL1: case R_TX_CTRL0: r = s->regs[addr]; @@ -170,7 +174,7 @@ eth_write(void *opaque, hwaddr addr, if ((value & (CTRL_P | CTRL_S)) == CTRL_S) { qemu_send_packet(qemu_get_queue(s->nic), txbuf_ptr(s, port_index), - s->regs[base + R_TX_LEN0]); + s->port[port_index].reg.tx_len); if (s->regs[base + R_TX_CTRL0] & CTRL_I) eth_pulse_irq(s); } else if ((value & (CTRL_P | CTRL_S)) == (CTRL_P | CTRL_S)) { @@ -195,7 +199,7 @@ eth_write(void *opaque, hwaddr addr, case R_TX_LEN0: case R_TX_LEN1: - s->regs[addr] = value; + s->port[port_index].reg.tx_len = value; break; case R_TX_GIE0: -- cgit 1.4.1 From a37506699109d2dbf86ec5c02734eee35d065d94 Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Sat, 9 Nov 2024 19:51:55 +0100 Subject: hw/net/xilinx_ethlite: Access TX_CTRL register for each port MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rather than accessing the registers within the mixed RAM/MMIO region as indexed register, declare a per-port TX_CTRL. This will help to map the RAM as RAM (keeping MMIO as MMIO) in few commits. Previous s->regs[R_TX_CTRL0] and s->regs[R_TX_CTRL1] are now unused. Not a concern, this array will soon disappear. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Edgar E. Iglesias Message-Id: <20241112181044.92193-15-philmd@linaro.org> --- hw/net/xilinx_ethlite.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'hw/net/xilinx_ethlite.c') diff --git a/hw/net/xilinx_ethlite.c b/hw/net/xilinx_ethlite.c index ce9555bd1e..f8b01fe9a6 100644 --- a/hw/net/xilinx_ethlite.c +++ b/hw/net/xilinx_ethlite.c @@ -64,6 +64,7 @@ typedef struct XlnxXpsEthLitePort { struct { uint32_t tx_len; uint32_t tx_gie; + uint32_t tx_ctrl; uint32_t rx_ctrl; } reg; @@ -139,7 +140,7 @@ eth_read(void *opaque, hwaddr addr, unsigned int size) case R_TX_CTRL1: case R_TX_CTRL0: - r = s->regs[addr]; + r = s->port[port_index].reg.tx_ctrl; break; case R_RX_CTRL1: @@ -160,7 +161,6 @@ eth_write(void *opaque, hwaddr addr, { XlnxXpsEthLite *s = opaque; unsigned int port_index = addr_to_port_index(addr); - unsigned int base = 0; uint32_t value = val64; addr >>= 2; @@ -168,24 +168,23 @@ eth_write(void *opaque, hwaddr addr, { case R_TX_CTRL0: case R_TX_CTRL1: - if (addr == R_TX_CTRL1) - base = 0x800 / 4; - if ((value & (CTRL_P | CTRL_S)) == CTRL_S) { qemu_send_packet(qemu_get_queue(s->nic), txbuf_ptr(s, port_index), s->port[port_index].reg.tx_len); - if (s->regs[base + R_TX_CTRL0] & CTRL_I) + if (s->port[port_index].reg.tx_ctrl & CTRL_I) { eth_pulse_irq(s); + } } else if ((value & (CTRL_P | CTRL_S)) == (CTRL_P | CTRL_S)) { memcpy(&s->conf.macaddr.a[0], txbuf_ptr(s, port_index), 6); - if (s->regs[base + R_TX_CTRL0] & CTRL_I) + if (s->port[port_index].reg.tx_ctrl & CTRL_I) { eth_pulse_irq(s); + } } /* We are fast and get ready pretty much immediately so we actually never flip the S nor P bits to one. */ - s->regs[addr] = value & ~(CTRL_P | CTRL_S); + s->port[port_index].reg.tx_ctrl = value & ~(CTRL_P | CTRL_S); break; /* Keep these native. */ -- cgit 1.4.1 From 72294962065e5d237dda3cd298016b47fef0c3c0 Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Sat, 9 Nov 2024 20:03:00 +0100 Subject: hw/net/xilinx_ethlite: Map RX_CTRL as MMIO MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Declare RX registers as MMIO region, split it out of the current mixed RAM/MMIO region. The memory flat view becomes: (qemu) info mtree -f FlatView #0 Root memory region: system 0000000081000000-00000000810007e3 (prio 0, i/o): xlnx.xps-ethernetlite 00000000810007e4-00000000810007f3 (prio 0, i/o): ethlite.mdio 00000000810007f4-00000000810017fb (prio 0, i/o): xlnx.xps-ethernetlite @00000000000007f4 00000000810017fc-00000000810017ff (prio 0, i/o): ethlite.rx[0]io 0000000081001800-0000000081001ffb (prio 0, i/o): xlnx.xps-ethernetlite @0000000000001800 0000000081001ffc-0000000081001fff (prio 0, i/o): ethlite.rx[1]io Reviewed-by: Edgar E. Iglesias Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20241112181044.92193-16-philmd@linaro.org> --- hw/net/xilinx_ethlite.c | 82 ++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 67 insertions(+), 15 deletions(-) (limited to 'hw/net/xilinx_ethlite.c') diff --git a/hw/net/xilinx_ethlite.c b/hw/net/xilinx_ethlite.c index f8b01fe9a6..9ac81ca1e0 100644 --- a/hw/net/xilinx_ethlite.c +++ b/hw/net/xilinx_ethlite.c @@ -49,11 +49,16 @@ #define R_TX_CTRL1 (0x0ffc / 4) #define R_RX_BUF0 (0x1000 / 4) -#define R_RX_CTRL0 (0x17fc / 4) +#define A_RX_BASE0 0x17fc #define R_RX_BUF1 (0x1800 / 4) -#define R_RX_CTRL1 (0x1ffc / 4) +#define A_RX_BASE1 0x1ffc #define R_MAX (0x2000 / 4) +enum { + RX_CTRL = 0, + RX_MAX +}; + #define GIE_GIE 0x80000000 #define CTRL_I 0x8 @@ -61,6 +66,8 @@ #define CTRL_S 0x1 typedef struct XlnxXpsEthLitePort { + MemoryRegion rxio; + struct { uint32_t tx_len; uint32_t tx_gie; @@ -118,6 +125,55 @@ static void *rxbuf_ptr(XlnxXpsEthLite *s, unsigned port_index) return &s->regs[rxbase + R_RX_BUF0]; } +static uint64_t port_rx_read(void *opaque, hwaddr addr, unsigned int size) +{ + XlnxXpsEthLite *s = opaque; + unsigned port_index = addr_to_port_index(addr); + uint32_t r = 0; + + switch (addr >> 2) { + case RX_CTRL: + r = s->port[port_index].reg.rx_ctrl; + break; + default: + g_assert_not_reached(); + } + + return r; +} + +static void port_rx_write(void *opaque, hwaddr addr, uint64_t value, + unsigned int size) +{ + XlnxXpsEthLite *s = opaque; + unsigned port_index = addr_to_port_index(addr); + + switch (addr >> 2) { + case RX_CTRL: + if (!(value & CTRL_S)) { + qemu_flush_queued_packets(qemu_get_queue(s->nic)); + } + s->port[port_index].reg.rx_ctrl = value; + break; + default: + g_assert_not_reached(); + } +} + +static const MemoryRegionOps eth_portrx_ops = { + .read = port_rx_read, + .write = port_rx_write, + .endianness = DEVICE_NATIVE_ENDIAN, + .impl = { + .min_access_size = 4, + .max_access_size = 4, + }, + .valid = { + .min_access_size = 4, + .max_access_size = 4, + }, +}; + static uint64_t eth_read(void *opaque, hwaddr addr, unsigned int size) { @@ -143,11 +199,6 @@ eth_read(void *opaque, hwaddr addr, unsigned int size) r = s->port[port_index].reg.tx_ctrl; break; - case R_RX_CTRL1: - case R_RX_CTRL0: - r = s->port[port_index].reg.rx_ctrl; - break; - default: r = tswap32(s->regs[addr]); break; @@ -188,14 +239,6 @@ eth_write(void *opaque, hwaddr addr, break; /* Keep these native. */ - case R_RX_CTRL0: - case R_RX_CTRL1: - if (!(value & CTRL_S)) { - qemu_flush_queued_packets(qemu_get_queue(s->nic)); - } - s->port[port_index].reg.rx_ctrl = value; - break; - case R_TX_LEN0: case R_TX_LEN1: s->port[port_index].reg.tx_len = value; @@ -288,6 +331,15 @@ static void xilinx_ethlite_realize(DeviceState *dev, Error **errp) memory_region_add_subregion(&s->mmio, A_MDIO_BASE, sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->mdio), 0)); + for (unsigned i = 0; i < 2; i++) { + memory_region_init_io(&s->port[i].rxio, OBJECT(dev), + ð_portrx_ops, s, + i ? "ethlite.rx[1]io" : "ethlite.rx[0]io", + 4 * RX_MAX); + memory_region_add_subregion(&s->mmio, i ? A_RX_BASE1 : A_RX_BASE0, + &s->port[i].rxio); + } + qemu_macaddr_default_if_unset(&s->conf.macaddr); s->nic = qemu_new_nic(&net_xilinx_ethlite_info, &s->conf, object_get_typename(OBJECT(dev)), dev->id, -- cgit 1.4.1 From 46dd6af2592d7a7d876ed8617b1e70d43c676ebb Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Sun, 10 Nov 2024 16:51:24 +0100 Subject: hw/net/xilinx_ethlite: Map TX_LEN as MMIO MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Declare TX registers as MMIO region, split it out of the current mixed RAM/MMIO region. The memory flat view becomes: (qemu) info mtree -f FlatView #0 Root memory region: system 0000000081000000-00000000810007e3 (prio 0, i/o): xlnx.xps-ethernetlite 00000000810007e4-00000000810007f3 (prio 0, i/o): ethlite.mdio 00000000810007f4-00000000810007f7 (prio 0, i/o): ethlite.tx[0]io 00000000810007f8-0000000081000ff3 (prio 0, i/o): xlnx.xps-ethernetlite @00000000000007f8 0000000081000ff4-0000000081000ff7 (prio 0, i/o): ethlite.tx[1]io 0000000081000ff8-00000000810017fb (prio 0, i/o): xlnx.xps-ethernetlite @0000000000000ff8 00000000810017fc-00000000810017ff (prio 0, i/o): ethlite.rx[0]io 0000000081001800-0000000081001ffb (prio 0, i/o): xlnx.xps-ethernetlite @0000000000001800 0000000081001ffc-0000000081001fff (prio 0, i/o): ethlite.rx[1]io Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Edgar E. Iglesias Message-Id: <20241112181044.92193-17-philmd@linaro.org> --- hw/net/xilinx_ethlite.c | 73 +++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 61 insertions(+), 12 deletions(-) (limited to 'hw/net/xilinx_ethlite.c') diff --git a/hw/net/xilinx_ethlite.c b/hw/net/xilinx_ethlite.c index 9ac81ca1e0..5dac44fa68 100644 --- a/hw/net/xilinx_ethlite.c +++ b/hw/net/xilinx_ethlite.c @@ -41,11 +41,11 @@ #define R_TX_BUF0 0 #define BUFSZ_MAX 0x07e4 #define A_MDIO_BASE 0x07e4 -#define R_TX_LEN0 (0x07f4 / 4) +#define A_TX_BASE0 0x07f4 #define R_TX_GIE0 (0x07f8 / 4) #define R_TX_CTRL0 (0x07fc / 4) #define R_TX_BUF1 (0x0800 / 4) -#define R_TX_LEN1 (0x0ff4 / 4) +#define A_TX_BASE1 0x0ff4 #define R_TX_CTRL1 (0x0ffc / 4) #define R_RX_BUF0 (0x1000 / 4) @@ -54,6 +54,11 @@ #define A_RX_BASE1 0x1ffc #define R_MAX (0x2000 / 4) +enum { + TX_LEN = 0, + TX_MAX +}; + enum { RX_CTRL = 0, RX_MAX @@ -66,6 +71,7 @@ enum { #define CTRL_S 0x1 typedef struct XlnxXpsEthLitePort { + MemoryRegion txio; MemoryRegion rxio; struct { @@ -125,6 +131,52 @@ static void *rxbuf_ptr(XlnxXpsEthLite *s, unsigned port_index) return &s->regs[rxbase + R_RX_BUF0]; } +static uint64_t port_tx_read(void *opaque, hwaddr addr, unsigned int size) +{ + XlnxXpsEthLite *s = opaque; + unsigned port_index = addr_to_port_index(addr); + uint32_t r = 0; + + switch (addr >> 2) { + case TX_LEN: + r = s->port[port_index].reg.tx_len; + break; + default: + g_assert_not_reached(); + } + + return r; +} + +static void port_tx_write(void *opaque, hwaddr addr, uint64_t value, + unsigned int size) +{ + XlnxXpsEthLite *s = opaque; + unsigned port_index = addr_to_port_index(addr); + + switch (addr >> 2) { + case TX_LEN: + s->port[port_index].reg.tx_len = value; + break; + default: + g_assert_not_reached(); + } +} + +static const MemoryRegionOps eth_porttx_ops = { + .read = port_tx_read, + .write = port_tx_write, + .endianness = DEVICE_NATIVE_ENDIAN, + .impl = { + .min_access_size = 4, + .max_access_size = 4, + }, + .valid = { + .min_access_size = 4, + .max_access_size = 4, + }, +}; + static uint64_t port_rx_read(void *opaque, hwaddr addr, unsigned int size) { XlnxXpsEthLite *s = opaque; @@ -189,11 +241,6 @@ eth_read(void *opaque, hwaddr addr, unsigned int size) r = s->port[port_index].reg.tx_gie; break; - case R_TX_LEN0: - case R_TX_LEN1: - r = s->port[port_index].reg.tx_len; - break; - case R_TX_CTRL1: case R_TX_CTRL0: r = s->port[port_index].reg.tx_ctrl; @@ -239,11 +286,6 @@ eth_write(void *opaque, hwaddr addr, break; /* Keep these native. */ - case R_TX_LEN0: - case R_TX_LEN1: - s->port[port_index].reg.tx_len = value; - break; - case R_TX_GIE0: s->port[port_index].reg.tx_gie = value; break; @@ -332,6 +374,13 @@ static void xilinx_ethlite_realize(DeviceState *dev, Error **errp) sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->mdio), 0)); for (unsigned i = 0; i < 2; i++) { + memory_region_init_io(&s->port[i].txio, OBJECT(dev), + ð_porttx_ops, s, + i ? "ethlite.tx[1]io" : "ethlite.tx[0]io", + 4 * TX_MAX); + memory_region_add_subregion(&s->mmio, i ? A_TX_BASE1 : A_TX_BASE0, + &s->port[i].txio); + memory_region_init_io(&s->port[i].rxio, OBJECT(dev), ð_portrx_ops, s, i ? "ethlite.rx[1]io" : "ethlite.rx[0]io", -- cgit 1.4.1 From 01198add29ddecc1283f1ab5cb4b34885e7daaa3 Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Mon, 11 Nov 2024 17:15:56 +0100 Subject: hw/net/xilinx_ethlite: Map TX_GIE as MMIO MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add TX_GIE to the TX registers MMIO region. Before TX_GIE1 was accessed as RAM, with no effect. Now it is accessed as MMIO, also without any effect. The memory flat view becomes: (qemu) info mtree -f FlatView #0 Root memory region: system 0000000081000000-00000000810007e3 (prio 0, i/o): xlnx.xps-ethernetlite 00000000810007e4-00000000810007f3 (prio 0, i/o): ethlite.mdio 00000000810007f4-00000000810007fb (prio 0, i/o): ethlite.tx[0]io 00000000810007fc-0000000081000ff3 (prio 0, i/o): xlnx.xps-ethernetlite @00000000000007fc 0000000081000ff4-0000000081000ffb (prio 0, i/o): ethlite.tx[1]io 0000000081000ffc-00000000810017fb (prio 0, i/o): xlnx.xps-ethernetlite @0000000000000ffc 00000000810017fc-00000000810017ff (prio 0, i/o): ethlite.rx[0]io 0000000081001800-0000000081001ffb (prio 0, i/o): xlnx.xps-ethernetlite @0000000000001800 0000000081001ffc-0000000081001fff (prio 0, i/o): ethlite.rx[1]io Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Edgar E. Iglesias Message-Id: <20241112181044.92193-18-philmd@linaro.org> --- hw/net/xilinx_ethlite.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) (limited to 'hw/net/xilinx_ethlite.c') diff --git a/hw/net/xilinx_ethlite.c b/hw/net/xilinx_ethlite.c index 5dac44fa68..898c09b398 100644 --- a/hw/net/xilinx_ethlite.c +++ b/hw/net/xilinx_ethlite.c @@ -42,7 +42,6 @@ #define BUFSZ_MAX 0x07e4 #define A_MDIO_BASE 0x07e4 #define A_TX_BASE0 0x07f4 -#define R_TX_GIE0 (0x07f8 / 4) #define R_TX_CTRL0 (0x07fc / 4) #define R_TX_BUF1 (0x0800 / 4) #define A_TX_BASE1 0x0ff4 @@ -56,6 +55,7 @@ enum { TX_LEN = 0, + TX_GIE = 1, TX_MAX }; @@ -141,6 +141,9 @@ static uint64_t port_tx_read(void *opaque, hwaddr addr, unsigned int size) case TX_LEN: r = s->port[port_index].reg.tx_len; break; + case TX_GIE: + r = s->port[port_index].reg.tx_gie; + break; default: g_assert_not_reached(); } @@ -158,6 +161,9 @@ static void port_tx_write(void *opaque, hwaddr addr, uint64_t value, case TX_LEN: s->port[port_index].reg.tx_len = value; break; + case TX_GIE: + s->port[port_index].reg.tx_gie = value; + break; default: g_assert_not_reached(); } @@ -237,10 +243,6 @@ eth_read(void *opaque, hwaddr addr, unsigned int size) switch (addr) { - case R_TX_GIE0: - r = s->port[port_index].reg.tx_gie; - break; - case R_TX_CTRL1: case R_TX_CTRL0: r = s->port[port_index].reg.tx_ctrl; @@ -285,11 +287,6 @@ eth_write(void *opaque, hwaddr addr, s->port[port_index].reg.tx_ctrl = value & ~(CTRL_P | CTRL_S); break; - /* Keep these native. */ - case R_TX_GIE0: - s->port[port_index].reg.tx_gie = value; - break; - default: s->regs[addr] = tswap32(value); break; -- cgit 1.4.1 From a34606dbb3c7094b6e9fde5e1463a306b6921255 Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Mon, 11 Nov 2024 17:19:39 +0100 Subject: hw/net/xilinx_ethlite: Map TX_CTRL as MMIO MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add TX_CTRL to the TX registers MMIO region. The memory flat view becomes: (qemu) info mtree -f FlatView #0 Root memory region: system 0000000081000000-00000000810007e3 (prio 0, i/o): xlnx.xps-ethernetlite 00000000810007e4-00000000810007f3 (prio 0, i/o): ethlite.mdio 00000000810007f4-00000000810007ff (prio 0, i/o): ethlite.tx[0]io 0000000081000800-0000000081000ff3 (prio 0, i/o): xlnx.xps-ethernetlite @0000000000000800 0000000081000ff4-0000000081000fff (prio 0, i/o): ethlite.tx[1]io 0000000081001000-00000000810017fb (prio 0, i/o): xlnx.xps-ethernetlite @0000000000001000 00000000810017fc-00000000810017ff (prio 0, i/o): ethlite.rx[0]io 0000000081001800-0000000081001ffb (prio 0, i/o): xlnx.xps-ethernetlite @0000000000001800 0000000081001ffc-0000000081001fff (prio 0, i/o): ethlite.rx[1]io Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Edgar E. Iglesias Message-Id: <20241112181044.92193-19-philmd@linaro.org> --- hw/net/xilinx_ethlite.c | 54 ++++++++++++++++++++++--------------------------- 1 file changed, 24 insertions(+), 30 deletions(-) (limited to 'hw/net/xilinx_ethlite.c') diff --git a/hw/net/xilinx_ethlite.c b/hw/net/xilinx_ethlite.c index 898c09b398..5ab8ae43b2 100644 --- a/hw/net/xilinx_ethlite.c +++ b/hw/net/xilinx_ethlite.c @@ -42,10 +42,8 @@ #define BUFSZ_MAX 0x07e4 #define A_MDIO_BASE 0x07e4 #define A_TX_BASE0 0x07f4 -#define R_TX_CTRL0 (0x07fc / 4) #define R_TX_BUF1 (0x0800 / 4) #define A_TX_BASE1 0x0ff4 -#define R_TX_CTRL1 (0x0ffc / 4) #define R_RX_BUF0 (0x1000 / 4) #define A_RX_BASE0 0x17fc @@ -56,6 +54,7 @@ enum { TX_LEN = 0, TX_GIE = 1, + TX_CTRL = 2, TX_MAX }; @@ -144,6 +143,9 @@ static uint64_t port_tx_read(void *opaque, hwaddr addr, unsigned int size) case TX_GIE: r = s->port[port_index].reg.tx_gie; break; + case TX_CTRL: + r = s->port[port_index].reg.tx_ctrl; + break; default: g_assert_not_reached(); } @@ -164,6 +166,26 @@ static void port_tx_write(void *opaque, hwaddr addr, uint64_t value, case TX_GIE: s->port[port_index].reg.tx_gie = value; break; + case TX_CTRL: + if ((value & (CTRL_P | CTRL_S)) == CTRL_S) { + qemu_send_packet(qemu_get_queue(s->nic), + txbuf_ptr(s, port_index), + s->port[port_index].reg.tx_len); + if (s->port[port_index].reg.tx_ctrl & CTRL_I) { + eth_pulse_irq(s); + } + } else if ((value & (CTRL_P | CTRL_S)) == (CTRL_P | CTRL_S)) { + memcpy(&s->conf.macaddr.a[0], txbuf_ptr(s, port_index), 6); + if (s->port[port_index].reg.tx_ctrl & CTRL_I) { + eth_pulse_irq(s); + } + } + /* + * We are fast and get ready pretty much immediately + * so we actually never flip the S nor P bits to one. + */ + s->port[port_index].reg.tx_ctrl = value & ~(CTRL_P | CTRL_S); + break; default: g_assert_not_reached(); } @@ -236,18 +258,12 @@ static uint64_t eth_read(void *opaque, hwaddr addr, unsigned int size) { XlnxXpsEthLite *s = opaque; - unsigned port_index = addr_to_port_index(addr); uint32_t r = 0; addr >>= 2; switch (addr) { - case R_TX_CTRL1: - case R_TX_CTRL0: - r = s->port[port_index].reg.tx_ctrl; - break; - default: r = tswap32(s->regs[addr]); break; @@ -260,33 +276,11 @@ eth_write(void *opaque, hwaddr addr, uint64_t val64, unsigned int size) { XlnxXpsEthLite *s = opaque; - unsigned int port_index = addr_to_port_index(addr); uint32_t value = val64; addr >>= 2; switch (addr) { - case R_TX_CTRL0: - case R_TX_CTRL1: - if ((value & (CTRL_P | CTRL_S)) == CTRL_S) { - qemu_send_packet(qemu_get_queue(s->nic), - txbuf_ptr(s, port_index), - s->port[port_index].reg.tx_len); - if (s->port[port_index].reg.tx_ctrl & CTRL_I) { - eth_pulse_irq(s); - } - } else if ((value & (CTRL_P | CTRL_S)) == (CTRL_P | CTRL_S)) { - memcpy(&s->conf.macaddr.a[0], txbuf_ptr(s, port_index), 6); - if (s->port[port_index].reg.tx_ctrl & CTRL_I) { - eth_pulse_irq(s); - } - } - - /* We are fast and get ready pretty much immediately so - we actually never flip the S nor P bits to one. */ - s->port[port_index].reg.tx_ctrl = value & ~(CTRL_P | CTRL_S); - break; - default: s->regs[addr] = tswap32(value); break; -- cgit 1.4.1 From 0bd0ba87a0fa22b5d3dda206f1920547df6eb918 Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Mon, 11 Nov 2024 17:44:53 +0100 Subject: hw/net/xilinx_ethlite: Map the RAM buffer as RAM memory region MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rather than using I/O registers for RAM buffer, having to swap endianness back and forth (because the core memory layer automatically swaps endiannes for us), declare the buffers as RAM regions. The "xlnx.xps-ethernetlite" MR doesn't have any more I/O regions. Remove the now unused s->regs[] array. The memory flat view becomes: FlatView #0 Root memory region: system 0000000081000000-00000000810007e3 (prio 0, ram): ethlite.tx[0]buf 00000000810007e4-00000000810007f3 (prio 0, i/o): ethlite.mdio 00000000810007f4-00000000810007ff (prio 0, i/o): ethlite.tx[0]io 0000000081000800-0000000081000fe3 (prio 0, ram): ethlite.tx[1]buf 0000000081000ff4-0000000081000fff (prio 0, i/o): ethlite.tx[1]io 0000000081001000-00000000810017e3 (prio 0, ram): ethlite.rx[0]buf 00000000810017fc-00000000810017ff (prio 0, i/o): ethlite.rx[0]io 0000000081001800-0000000081001fe3 (prio 0, ram): ethlite.rx[1]buf 0000000081001ffc-0000000081001fff (prio 0, i/o): ethlite.rx[1]io Reported-by: Paolo Bonzini Reviewed-by: Edgar E. Iglesias Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20241114210010.34502-18-philmd@linaro.org> --- hw/net/xilinx_ethlite.c | 81 +++++++++++-------------------------------------- 1 file changed, 17 insertions(+), 64 deletions(-) (limited to 'hw/net/xilinx_ethlite.c') diff --git a/hw/net/xilinx_ethlite.c b/hw/net/xilinx_ethlite.c index 5ab8ae43b2..758226a65d 100644 --- a/hw/net/xilinx_ethlite.c +++ b/hw/net/xilinx_ethlite.c @@ -2,6 +2,7 @@ * QEMU model of the Xilinx Ethernet Lite MAC. * * Copyright (c) 2009 Edgar E. Iglesias. + * Copyright (c) 2024 Linaro, Ltd * * DS580: https://docs.amd.com/v/u/en-US/xps_ethernetlite * LogiCORE IP XPS Ethernet Lite Media Access Controller @@ -30,7 +31,6 @@ #include "qemu/bitops.h" #include "qom/object.h" #include "qapi/error.h" -#include "exec/tswap.h" #include "hw/sysbus.h" #include "hw/irq.h" #include "hw/qdev-properties.h" @@ -38,18 +38,12 @@ #include "net/net.h" #include "trace.h" -#define R_TX_BUF0 0 #define BUFSZ_MAX 0x07e4 #define A_MDIO_BASE 0x07e4 #define A_TX_BASE0 0x07f4 -#define R_TX_BUF1 (0x0800 / 4) #define A_TX_BASE1 0x0ff4 - -#define R_RX_BUF0 (0x1000 / 4) #define A_RX_BASE0 0x17fc -#define R_RX_BUF1 (0x1800 / 4) #define A_RX_BASE1 0x1ffc -#define R_MAX (0x2000 / 4) enum { TX_LEN = 0, @@ -72,6 +66,8 @@ enum { typedef struct XlnxXpsEthLitePort { MemoryRegion txio; MemoryRegion rxio; + MemoryRegion txbuf; + MemoryRegion rxbuf; struct { uint32_t tx_len; @@ -100,7 +96,6 @@ struct XlnxXpsEthLite UnimplementedDeviceState mdio; XlnxXpsEthLitePort port[2]; - uint32_t regs[R_MAX]; }; static inline void eth_pulse_irq(XlnxXpsEthLite *s) @@ -118,16 +113,12 @@ static unsigned addr_to_port_index(hwaddr addr) static void *txbuf_ptr(XlnxXpsEthLite *s, unsigned port_index) { - unsigned int rxbase = port_index * (0x800 / 4); - - return &s->regs[rxbase + R_TX_BUF0]; + return memory_region_get_ram_ptr(&s->port[port_index].txbuf); } static void *rxbuf_ptr(XlnxXpsEthLite *s, unsigned port_index) { - unsigned int rxbase = port_index * (0x800 / 4); - - return &s->regs[rxbase + R_RX_BUF0]; + return memory_region_get_ram_ptr(&s->port[port_index].rxbuf); } static uint64_t port_tx_read(void *opaque, hwaddr addr, unsigned int size) @@ -254,53 +245,6 @@ static const MemoryRegionOps eth_portrx_ops = { }, }; -static uint64_t -eth_read(void *opaque, hwaddr addr, unsigned int size) -{ - XlnxXpsEthLite *s = opaque; - uint32_t r = 0; - - addr >>= 2; - - switch (addr) - { - default: - r = tswap32(s->regs[addr]); - break; - } - return r; -} - -static void -eth_write(void *opaque, hwaddr addr, - uint64_t val64, unsigned int size) -{ - XlnxXpsEthLite *s = opaque; - uint32_t value = val64; - - addr >>= 2; - switch (addr) - { - default: - s->regs[addr] = tswap32(value); - break; - } -} - -static const MemoryRegionOps eth_ops = { - .read = eth_read, - .write = eth_write, - .endianness = DEVICE_NATIVE_ENDIAN, - .impl = { - .min_access_size = 4, - .max_access_size = 4, - }, - .valid = { - .min_access_size = 4, - .max_access_size = 4 - } -}; - static bool eth_can_rx(NetClientState *nc) { XlnxXpsEthLite *s = qemu_get_nic_opaque(nc); @@ -356,6 +300,9 @@ static void xilinx_ethlite_realize(DeviceState *dev, Error **errp) { XlnxXpsEthLite *s = XILINX_ETHLITE(dev); + memory_region_init(&s->mmio, OBJECT(dev), + "xlnx.xps-ethernetlite", 0x2000); + object_initialize_child(OBJECT(dev), "ethlite.mdio", &s->mdio, TYPE_UNIMPLEMENTED_DEVICE); qdev_prop_set_string(DEVICE(&s->mdio), "name", "ethlite.mdio"); @@ -365,6 +312,10 @@ static void xilinx_ethlite_realize(DeviceState *dev, Error **errp) sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->mdio), 0)); for (unsigned i = 0; i < 2; i++) { + memory_region_init_ram(&s->port[i].txbuf, OBJECT(dev), + i ? "ethlite.tx[1]buf" : "ethlite.tx[0]buf", + BUFSZ_MAX, &error_abort); + memory_region_add_subregion(&s->mmio, 0x0800 * i, &s->port[i].txbuf); memory_region_init_io(&s->port[i].txio, OBJECT(dev), ð_porttx_ops, s, i ? "ethlite.tx[1]io" : "ethlite.tx[0]io", @@ -372,6 +323,11 @@ static void xilinx_ethlite_realize(DeviceState *dev, Error **errp) memory_region_add_subregion(&s->mmio, i ? A_TX_BASE1 : A_TX_BASE0, &s->port[i].txio); + memory_region_init_ram(&s->port[i].rxbuf, OBJECT(dev), + i ? "ethlite.rx[1]buf" : "ethlite.rx[0]buf", + BUFSZ_MAX, &error_abort); + memory_region_add_subregion(&s->mmio, 0x1000 + 0x0800 * i, + &s->port[i].rxbuf); memory_region_init_io(&s->port[i].rxio, OBJECT(dev), ð_portrx_ops, s, i ? "ethlite.rx[1]io" : "ethlite.rx[0]io", @@ -392,9 +348,6 @@ static void xilinx_ethlite_init(Object *obj) XlnxXpsEthLite *s = XILINX_ETHLITE(obj); sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq); - - memory_region_init_io(&s->mmio, obj, ð_ops, s, - "xlnx.xps-ethernetlite", R_MAX * 4); sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio); } -- cgit 1.4.1 From ce336679b72cfb5cbbf1539d209764242fc5458a Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Mon, 11 Nov 2024 17:44:53 +0100 Subject: hw/net/xilinx_ethlite: Rename 'mmio' MR as 'container' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Having all its address range mapped by subregions, s->mmio MemoryRegion effectively became a container. Rename it as 'container' for clarity. Reviewed-by: Edgar E. Iglesias Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20241112181044.92193-21-philmd@linaro.org> --- hw/net/xilinx_ethlite.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'hw/net/xilinx_ethlite.c') diff --git a/hw/net/xilinx_ethlite.c b/hw/net/xilinx_ethlite.c index 758226a65d..a7f6d1b368 100644 --- a/hw/net/xilinx_ethlite.c +++ b/hw/net/xilinx_ethlite.c @@ -85,7 +85,7 @@ struct XlnxXpsEthLite { SysBusDevice parent_obj; - MemoryRegion mmio; + MemoryRegion container; qemu_irq irq; NICState *nic; NICConf conf; @@ -300,7 +300,7 @@ static void xilinx_ethlite_realize(DeviceState *dev, Error **errp) { XlnxXpsEthLite *s = XILINX_ETHLITE(dev); - memory_region_init(&s->mmio, OBJECT(dev), + memory_region_init(&s->container, OBJECT(dev), "xlnx.xps-ethernetlite", 0x2000); object_initialize_child(OBJECT(dev), "ethlite.mdio", &s->mdio, @@ -308,31 +308,31 @@ static void xilinx_ethlite_realize(DeviceState *dev, Error **errp) qdev_prop_set_string(DEVICE(&s->mdio), "name", "ethlite.mdio"); qdev_prop_set_uint64(DEVICE(&s->mdio), "size", 4 * 4); sysbus_realize(SYS_BUS_DEVICE(&s->mdio), &error_fatal); - memory_region_add_subregion(&s->mmio, A_MDIO_BASE, + memory_region_add_subregion(&s->container, A_MDIO_BASE, sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->mdio), 0)); for (unsigned i = 0; i < 2; i++) { memory_region_init_ram(&s->port[i].txbuf, OBJECT(dev), i ? "ethlite.tx[1]buf" : "ethlite.tx[0]buf", BUFSZ_MAX, &error_abort); - memory_region_add_subregion(&s->mmio, 0x0800 * i, &s->port[i].txbuf); + memory_region_add_subregion(&s->container, 0x0800 * i, &s->port[i].txbuf); memory_region_init_io(&s->port[i].txio, OBJECT(dev), ð_porttx_ops, s, i ? "ethlite.tx[1]io" : "ethlite.tx[0]io", 4 * TX_MAX); - memory_region_add_subregion(&s->mmio, i ? A_TX_BASE1 : A_TX_BASE0, + memory_region_add_subregion(&s->container, i ? A_TX_BASE1 : A_TX_BASE0, &s->port[i].txio); memory_region_init_ram(&s->port[i].rxbuf, OBJECT(dev), i ? "ethlite.rx[1]buf" : "ethlite.rx[0]buf", BUFSZ_MAX, &error_abort); - memory_region_add_subregion(&s->mmio, 0x1000 + 0x0800 * i, + memory_region_add_subregion(&s->container, 0x1000 + 0x0800 * i, &s->port[i].rxbuf); memory_region_init_io(&s->port[i].rxio, OBJECT(dev), ð_portrx_ops, s, i ? "ethlite.rx[1]io" : "ethlite.rx[0]io", 4 * RX_MAX); - memory_region_add_subregion(&s->mmio, i ? A_RX_BASE1 : A_RX_BASE0, + memory_region_add_subregion(&s->container, i ? A_RX_BASE1 : A_RX_BASE0, &s->port[i].rxio); } @@ -348,7 +348,7 @@ static void xilinx_ethlite_init(Object *obj) XlnxXpsEthLite *s = XILINX_ETHLITE(obj); sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq); - sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio); + sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->container); } static const Property xilinx_ethlite_properties[] = { -- cgit 1.4.1 From 74f1caa8c33f608168c4224bb23d9a6453224a56 Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Thu, 14 Nov 2024 18:46:36 +0100 Subject: hw/net/xilinx_ethlite: Map RESERVED I/O as unimplemented MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In order to track access to reserved I/O space, use yet another UnimplementedDevice covering the whole device memory range. Mapped with lower priority (-1). The memory flat view becomes: (qemu) info mtree -f FlatView #0 Root memory region: system 0000000081000000-00000000810007e3 (prio 0, ram): ethlite.tx[0]buf 00000000810007e4-00000000810007f3 (prio 0, i/o): ethlite.mdio 00000000810007f4-00000000810007ff (prio 0, i/o): ethlite.tx[0]io 0000000081000800-0000000081000fe3 (prio 0, ram): ethlite.tx[1]buf 0000000081000fe4-0000000081000ff3 (prio -1, i/o): ethlite.reserved @0000000000000fe4 0000000081000ff4-0000000081000fff (prio 0, i/o): ethlite.tx[1]io 0000000081001000-00000000810017e3 (prio 0, ram): ethlite.rx[0]buf 00000000810017e4-00000000810017fb (prio -1, i/o): ethlite.reserved @00000000000017e4 00000000810017fc-00000000810017ff (prio 0, i/o): ethlite.rx[0]io 0000000081001800-0000000081001fe3 (prio 0, ram): ethlite.rx[1]buf 0000000081001fe4-0000000081001ffb (prio -1, i/o): ethlite.reserved @0000000000001fe4 0000000081001ffc-0000000081001fff (prio 0, i/o): ethlite.rx[1]io Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Alex Bennée Message-Id: <20241114210010.34502-20-philmd@linaro.org> --- hw/net/xilinx_ethlite.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'hw/net/xilinx_ethlite.c') diff --git a/hw/net/xilinx_ethlite.c b/hw/net/xilinx_ethlite.c index a7f6d1b368..14bf2b2e17 100644 --- a/hw/net/xilinx_ethlite.c +++ b/hw/net/xilinx_ethlite.c @@ -94,6 +94,7 @@ struct XlnxXpsEthLite uint32_t c_rx_pingpong; unsigned int port_index; /* dual port RAM index */ + UnimplementedDeviceState rsvd; UnimplementedDeviceState mdio; XlnxXpsEthLitePort port[2]; }; @@ -303,6 +304,16 @@ static void xilinx_ethlite_realize(DeviceState *dev, Error **errp) memory_region_init(&s->container, OBJECT(dev), "xlnx.xps-ethernetlite", 0x2000); + object_initialize_child(OBJECT(dev), "ethlite.reserved", &s->rsvd, + TYPE_UNIMPLEMENTED_DEVICE); + qdev_prop_set_string(DEVICE(&s->rsvd), "name", "ethlite.reserved"); + qdev_prop_set_uint64(DEVICE(&s->rsvd), "size", + memory_region_size(&s->container)); + sysbus_realize(SYS_BUS_DEVICE(&s->rsvd), &error_fatal); + memory_region_add_subregion_overlap(&s->container, 0, + sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->rsvd), 0), + -1); + object_initialize_child(OBJECT(dev), "ethlite.mdio", &s->mdio, TYPE_UNIMPLEMENTED_DEVICE); qdev_prop_set_string(DEVICE(&s->mdio), "name", "ethlite.mdio"); -- cgit 1.4.1