Kext files for VirtIO

2023-12-07 Thread aziz tlili
Do u guys have some free time to develop kext files "drivers" for VirtIO
devices (like virtio-gpu-pci and virtio-blk-pci and virtio-net-pci) for
PowerPC MacOS X Tiger (10.4.11) and later (till Leopard 10.5)? Please, I
need them as soon as possible!


Re: [PATCH 1/2] target/riscv: FIX xATP_MODE validation

2023-12-07 Thread LIU Zhiwei

Hi Irina,

On 2023/12/1 19:53, Irina Ryapolova wrote:

The SATP register is an SXLEN-bit read/write WARL register. It means that CSR 
fields are only defined
for a subset of bit encodings, but allow any value to be written while 
guaranteeing to return a legal
value whenever read (See riscv-privileged-20211203, SATP CSR).

For example on rv64 we are trying to write to SATP CSR val = 0x1000 
(SATP_MODE = 1 - Reserved for standard use)
and after that we are trying to read SATP_CSR. We read from the SATP CSR value 
= 0x1000, which is not a correct
operation (return illegal value).

Signed-off-by: Irina Ryapolova 
---
  target/riscv/csr.c | 4 ++--
  1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index fde7ce1a53..6f244815b7 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -1278,8 +1278,8 @@ static RISCVException read_mstatus(CPURISCVState *env, 
int csrno,
  
  static bool validate_vm(CPURISCVState *env, target_ulong vm)

  {
-return (vm & 0xf) <=
-   satp_mode_max_from_map(riscv_cpu_cfg(env)->satp_mode.map);
+uint64_t mode_supported = riscv_cpu_cfg(env)->satp_mode.supported;


Why not use satp_mode.map? Using satp_mode.supported will violate the 
SATP settings in cpu init.


Zhiwei


+return get_field(mode_supported, (1 << vm));
  }
  
  static target_ulong legalize_mpp(CPURISCVState *env, target_ulong old_mpp,




Re: [PATCH 1/1] accel/tcg: Fix the comment for CPUTLBEntryFull

2023-12-07 Thread LIU Zhiwei



On 2023/11/28 21:04, Mark Cave-Ayland wrote:

On 01/09/2023 07:01, LIU Zhiwei wrote:


When memory region is ram, the lower TARGET_PAGE_BITS is not the
physical section number. Instead, its value is always 0.

Add comment and assert to make it clear.

Signed-off-by: LIU Zhiwei 
---
  accel/tcg/cputlb.c  | 11 +++
  include/exec/cpu-defs.h | 12 ++--
  2 files changed, 13 insertions(+), 10 deletions(-)

diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
index d68fa6867c..a1ebf75068 100644
--- a/accel/tcg/cputlb.c
+++ b/accel/tcg/cputlb.c
@@ -1192,6 +1192,7 @@ void tlb_set_page_full(CPUState *cpu, int mmu_idx,
  write_flags = read_flags;
  if (is_ram) {
  iotlb = memory_region_get_ram_addr(section->mr) + xlat;
+    assert(!(iotlb & ~TARGET_PAGE_MASK));
  /*
   * Computing is_clean is expensive; avoid all that unless
   * the page is actually writable.
@@ -1254,10 +1255,12 @@ void tlb_set_page_full(CPUState *cpu, int 
mmu_idx,

    /* refill the tlb */
  /*
- * At this point iotlb contains a physical section number in the 
lower

- * TARGET_PAGE_BITS, and either
- *  + the ram_addr_t of the page base of the target RAM (RAM)
- *  + the offset within section->mr of the page base (I/O, ROMD)
+ * When memory region is ram, iotlb contains a TARGET_PAGE_BITS
+ * aligned ram_addr_t of the page base of the target RAM.
+ * Otherwise, iotlb contains
+ *  - a physical section number in the lower TARGET_PAGE_BITS
+ *  - the offset within section->mr of the page base (I/O, ROMD) 
with the

+ *    TARGET_PAGE_BITS masked off.
   * We subtract addr_page (which is page aligned and thus won't
   * disturb the low bits) to give an offset which can be added 
to the

   * (non-page-aligned) vaddr of the eventual memory access to get
diff --git a/include/exec/cpu-defs.h b/include/exec/cpu-defs.h
index fb4c8d480f..350287852e 100644
--- a/include/exec/cpu-defs.h
+++ b/include/exec/cpu-defs.h
@@ -100,12 +100,12 @@
  typedef struct CPUTLBEntryFull {
  /*
   * @xlat_section contains:
- *  - in the lower TARGET_PAGE_BITS, a physical section number
- *  - with the lower TARGET_PAGE_BITS masked off, an offset which
- *    must be added to the virtual address to obtain:
- * + the ram_addr_t of the target RAM (if the physical section
- *   number is PHYS_SECTION_NOTDIRTY or PHYS_SECTION_ROM)
- * + the offset within the target MemoryRegion (otherwise)
+ *  - For ram, an offset which must be added to the virtual address
+ *    to obtain the ram_addr_t of the target RAM
+ *  - For other memory regions,
+ * + in the lower TARGET_PAGE_BITS, the physical section number
+ * + with the TARGET_PAGE_BITS masked off, the offset within
+ *   the target MemoryRegion
   */
  hwaddr xlat_section;


Someone sent me a test case that triggers the assert() introduced by 
this commit dff1ab6 ("accel/tcg: Fix the comment for CPUTLBEntryFull") 
for qemu-system-m68k which is still present in git master. The 
reproducer is easy:


1. Grab the machine ROM file from 
https://www.ilande.co.uk/tmp/qemu/tQuadra800.rom


2. Create an empty declaration ROM greater than 4K:

   dd if=/dev/zero of=/tmp/badrom bs=512 count=12

3. Start QEMU like this:

   qemu-system-m68k -M q800 -bios tQuadra800.rom \
   -device nubus-macfb,romfile=/tmp/badrom

The QEMU process hits the assert() with the following backtrace:

(gdb) bt
#0  0x758a9d3c in ?? () from /lib/x86_64-linux-gnu/libc.so.6
#1  0x7585af32 in raise () from /lib/x86_64-linux-gnu/libc.so.6
#2  0x75845472 in abort () from /lib/x86_64-linux-gnu/libc.so.6
#3  0x75845395 in ?? () from /lib/x86_64-linux-gnu/libc.so.6
#4  0x75853e32 in __assert_fail () from 
/lib/x86_64-linux-gnu/libc.so.6
#5  0x55942e0a in tlb_set_page_full (cpu=0x5618d4a0, 
mmu_idx=0, addr=4244631552, full=0x7fffe7d7f7c0) at 
../accel/tcg/cputlb.c:1171
#6  0x559432a0 in tlb_set_page_with_attrs (cpu=0x5618d4a0, 
addr=4244631552, paddr=4244631552, attrs=..., prot=7, mmu_idx=0, 
size=4096) at ../accel/tcg/cputlb.c:1290
#7  0x55943305 in tlb_set_page (cpu=0x5618d4a0, 
addr=4244631552, paddr=4244631552, prot=7, mmu_idx=0, size=4096) at 
../accel/tcg/cputlb.c:1297
#8  0x5588aade in m68k_cpu_tlb_fill (cs=0x5618d4a0, 
address=4244635647, size=1, qemu_access_type=MMU_DATA_LOAD, mmu_idx=0, 
probe=false, retaddr=140734805255937) at ../target/m68k/helper.c:1018
#9  0x55943367 in tlb_fill (cpu=0x5618d4a0, 
addr=4244635647, size=1, access_type=MMU_DATA_LOAD, mmu_idx=0, 
retaddr=140734805255937) at ../accel/tcg/cputlb.c:1315
#10 0x55945d78 in mmu_lookup1 (cpu=0x5618d4a0, 
data=0x7fffe7d7fa00, mmu_idx=0, access_type=MMU_DATA_LOAD, 
ra=140734805255937) at ../accel/tcg/cputlb.c:1713
#11 0x55946081 in mmu_lookup (cpu=0x5618d4a0, 

[PATCH] fix qemu build with xen-4.18.0

2023-12-07 Thread Michael Young
Builds of qemu-8.2.0rc2 with xen-4.18.0 are currently failing
with errors like
../hw/arm/xen_arm.c:74:5: error: ‘GUEST_VIRTIO_MMIO_SPI_LAST’ undeclared (first 
use in this function)
   74 |(GUEST_VIRTIO_MMIO_SPI_LAST - GUEST_VIRTIO_MMIO_SPI_FIRST)
  | ^~

as there is an incorrect comparision in include/hw/xen/xen_native.h
which means that settings like GUEST_VIRTIO_MMIO_SPI_LAST
aren't being defined for xen-4.18.0

Signed-off-by: Michael Young 
---
 include/hw/xen/xen_native.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/hw/xen/xen_native.h b/include/hw/xen/xen_native.h
index 6f09c48823..04b1ef4d34 100644
--- a/include/hw/xen/xen_native.h
+++ b/include/hw/xen/xen_native.h
@@ -532,7 +532,7 @@ static inline int 
xendevicemodel_set_irq_level(xendevicemodel_handle *dmod,
 }
 #endif
 
-#if CONFIG_XEN_CTRL_INTERFACE_VERSION <= 41700
+#if CONFIG_XEN_CTRL_INTERFACE_VERSION >= 41700
 #define GUEST_VIRTIO_MMIO_BASE   xen_mk_ullong(0x0200)
 #define GUEST_VIRTIO_MMIO_SIZE   xen_mk_ullong(0x0010)
 #define GUEST_VIRTIO_MMIO_SPI_FIRST   33
-- 
2.43.0




[PATCH v4 27/45] Add GENET register access macros

2023-12-07 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 include/hw/net/bcm2838_genet.h | 76 ++
 1 file changed, 76 insertions(+)

diff --git a/include/hw/net/bcm2838_genet.h b/include/hw/net/bcm2838_genet.h
index 94c2f3ebca..e7a76cda81 100644
--- a/include/hw/net/bcm2838_genet.h
+++ b/include/hw/net/bcm2838_genet.h
@@ -22,9 +22,85 @@ OBJECT_DECLARE_SIMPLE_TYPE(BCM2838GenetState, BCM2838_GENET)
 #define BCM2838_GENET_DMA_RING_CNT  17
 #define BCM2838_GENET_DMA_RING_DEFAULT  (BCM2838_GENET_DMA_RING_CNT - 1)
 
+#define BCM2838_GENET_HFB_FILTER_REGS offsetof(BCM2838GenetRegs, hfb)
+#define BCM2838_GENET_HFB_FILTER_REG(reg) (BCM2838_GENET_HFB_FILTER_REGS \
+   + offsetof(BCM2838GenetRegsHfb, 
reg))
 #define BCM2838_GENET_HFB_FILTER_CNT  48
 #define BCM2838_GENET_HFB_FILTER_SIZE 128
 
+#define BCM2838_GENET_INTRL0_REG(reg)   (offsetof(BCM2838GenetRegs, intrl0) \
++ offsetof(BCM2838GenetRegsIntrl0, 
reg))
+#define BCM2838_GENET_INTRL0_SETBCM2838_GENET_INTRL0_REG(set)
+#define BCM2838_GENET_INTRL0_CLEAR  BCM2838_GENET_INTRL0_REG(clear)
+#define BCM2838_GENET_INTRL0_MASK_SET   BCM2838_GENET_INTRL0_REG(mask_set)
+#define BCM2838_GENET_INTRL0_MASK_CLEAR BCM2838_GENET_INTRL0_REG(mask_clear)
+
+#define BCM2838_GENET_INTRL1_REG(reg)   (offsetof(BCM2838GenetRegs, intrl1) \
++ offsetof(BCM2838GenetRegsIntrl1, 
reg))
+#define BCM2838_GENET_INTRL1_SETBCM2838_GENET_INTRL1_REG(set)
+#define BCM2838_GENET_INTRL1_CLEAR  BCM2838_GENET_INTRL1_REG(clear)
+#define BCM2838_GENET_INTRL1_MASK_SET   BCM2838_GENET_INTRL1_REG(mask_set)
+#define BCM2838_GENET_INTRL1_MASK_CLEAR BCM2838_GENET_INTRL1_REG(mask_clear)
+
+#define BCM2838_GENET_UMAC_REG(reg) (offsetof(BCM2838GenetRegs, umac) \
+ + offsetof(BCM2838GenetRegsUmac, reg))
+#define BCM2838_GENET_UMAC_CMD  BCM2838_GENET_UMAC_REG(cmd)
+#define BCM2838_GENET_UMAC_MAC0 BCM2838_GENET_UMAC_REG(mac0)
+#define BCM2838_GENET_UMAC_MAC1 BCM2838_GENET_UMAC_REG(mac1)
+#define BCM2838_GENET_UMAC_MDIO_CMD BCM2838_GENET_UMAC_REG(mdio_cmd)
+
+#define BCM2838_GENET_TDMA_REGS offsetof(BCM2838GenetRegs, tdma)
+#define BCM2838_GENET_TDMA_REG(reg) (BCM2838_GENET_TDMA_REGS \
+ + offsetof(BCM2838GenetRegsTdma, reg))
+#define BCM2838_GENET_TDMA_RINGSBCM2838_GENET_TDMA_REG(rings)
+#define BCM2838_GENET_TDMA_RING_CFG BCM2838_GENET_TDMA_REG(ring_cfg)
+#define BCM2838_GENET_TDMA_CTRL BCM2838_GENET_TDMA_REG(ctrl)
+
+#define BCM2838_GENET_RDMA_REGS offsetof(BCM2838GenetRegs, rdma)
+#define BCM2838_GENET_RDMA_REG(reg) (BCM2838_GENET_RDMA_REGS \
+ + offsetof(BCM2838GenetRegsRdma, reg))
+#define BCM2838_GENET_RDMA_RINGSBCM2838_GENET_RDMA_REG(rings)
+#define BCM2838_GENET_RDMA_RING_CFG BCM2838_GENET_RDMA_REG(ring_cfg)
+#define BCM2838_GENET_RDMA_CTRL BCM2838_GENET_RDMA_REG(ctrl)
+
+#define BCM2838_GENET_TRING_REG(reg)offsetof(BCM2838GenetTdmaRing, reg)
+#define BCM2838_GENET_TRING_WRITE_PTR BCM2838_GENET_TRING_REG(write_ptr)
+#define BCM2838_GENET_TRING_WRITE_PTR_HI BCM2838_GENET_TRING_REG(write_ptr_hi)
+#define BCM2838_GENET_TRING_PROD_INDEX BCM2838_GENET_TRING_REG(prod_index)
+#define BCM2838_GENET_TRING_CONS_INDEX BCM2838_GENET_TRING_REG(cons_index)
+#define BCM2838_GENET_TRING_RING_BUF_SIZE 
BCM2838_GENET_TRING_REG(ring_buf_size)
+#define BCM2838_GENET_TRING_RING_START_ADDR BCM2838_GENET_TRING_REG(start_addr)
+#define BCM2838_GENET_TRING_RING_START_ADDR_HI 
BCM2838_GENET_TRING_REG(start_addr_hi)
+#define BCM2838_GENET_TRING_RING_END_ADDR BCM2838_GENET_TRING_REG(end_addr)
+#define BCM2838_GENET_TRING_RING_END_ADDR_HI 
BCM2838_GENET_TRING_REG(end_addr_hi)
+#define BCM2838_GENET_TRING_RING_MBUF_DONE_TRESH 
BCM2838_GENET_TRING_REG(mbuf_done_tresh)
+#define BCM2838_GENET_TRING_RING_FLOW_PERIOD 
BCM2838_GENET_TRING_REG(flow_period)
+#define BCM2838_GENET_TRING_RING_READ_PTR BCM2838_GENET_TRING_REG(read_ptr)
+#define BCM2838_GENET_TRING_RING_READ_PTR_HI 
BCM2838_GENET_TRING_REG(read_ptr_hi)
+
+#define BCM2838_GENET_RRING_REG(reg)offsetof(BCM2838GenetRdmaRing, reg)
+#define BCM2838_GENET_RRING_WRITE_PTR BCM2838_GENET_RRING_REG(write_ptr)
+#define BCM2838_GENET_RRING_WRITE_PTR_HI BCM2838_GENET_RRING_REG(write_ptr_hi)
+#define BCM2838_GENET_RRING_PROD_INDEX BCM2838_GENET_RRING_REG(prod_index)
+#define BCM2838_GENET_RRING_CONS_INDEX BCM2838_GENET_RRING_REG(cons_index)
+#define BCM2838_GENET_RRING_RING_BUF_SIZE 
BCM2838_GENET_RRING_REG(ring_buf_size)
+#define BCM2838_GENET_RRING_RING_START_ADDR BCM2838_GENET_RRING_REG(start_addr)
+#define BCM2838_GENET_RRING_RING_START_ADDR_HI 
BCM2838_GENET_RRING_REG(start_addr_hi)
+#define BCM2838_GENET_RRING_RING_END_ADDR BCM2838_GENET_RRING_REG(end_addr)
+#define BCM2838_GENET_RRING_RING_END_ADDR_HI 

[PATCH v4 32/45] Enable BCM2838 GENET controller

2023-12-07 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/arm/bcm2838_peripherals.c | 16 
 hw/arm/raspi4b.c | 17 -
 include/hw/arm/bcm2838_peripherals.h |  2 ++
 3 files changed, 18 insertions(+), 17 deletions(-)

diff --git a/hw/arm/bcm2838_peripherals.c b/hw/arm/bcm2838_peripherals.c
index 65a659c15c..d962999daf 100644
--- a/hw/arm/bcm2838_peripherals.c
+++ b/hw/arm/bcm2838_peripherals.c
@@ -47,6 +47,15 @@ static void bcm2838_peripherals_init(Object *obj)
 object_initialize_child(obj, "pcie-host", >pcie_host,
 TYPE_BCM2838_PCIE_HOST);
 
+/* Gigabit Ethernet */
+object_initialize_child(obj, "genet", >genet, TYPE_BCM2838_GENET);
+for (int i = 0; i < nb_nics; i++) {
+if ((nd_table[i].used && nd_table[i].model) && 
!strcmp(nd_table[i].model, "bcmgenet")) {
+qdev_set_nic_properties(DEVICE(>genet), _table[i]);
+break;
+}
+}
+
 /* Extended Mass Media Controller 2 */
 object_initialize_child(obj, "emmc2", >emmc2, TYPE_SYSBUS_SDHCI);
 
@@ -231,6 +240,13 @@ static void bcm2838_peripherals_realize(DeviceState *dev, 
Error **errp)
 memory_region_add_subregion(get_system_memory(), PCIE_MMIO_ARM_OFFSET,
 >pcie_mmio_alias);
 
+/* Gigabit Ethernet */
+if (!sysbus_realize(SYS_BUS_DEVICE(>genet), errp)) {
+return;
+}
+regs_mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(>genet), 0);
+memory_region_add_subregion(>peri_low_mr, GENET_OFFSET, regs_mr);
+
 create_unimp(s_base, >clkisp, "bcm2835-clkisp", CLOCK_ISP_OFFSET,
  CLOCK_ISP_SIZE);
 
diff --git a/hw/arm/raspi4b.c b/hw/arm/raspi4b.c
index fda27d36cb..8aa8dfb087 100644
--- a/hw/arm/raspi4b.c
+++ b/hw/arm/raspi4b.c
@@ -64,23 +64,6 @@ static int raspi_add_memory_node(void *fdt, hwaddr mem_base, 
hwaddr mem_len)
 
 static void raspi4_modify_dtb(const struct arm_boot_info *info, void *fdt)
 {
-
-/* Temporarily disable following devices until they are implemented*/
-const char *to_be_removed_from_dt_as_wa[] = {
-"brcm,bcm2711-genet-v5",
-};
-
-for (int i = 0; i < ARRAY_SIZE(to_be_removed_from_dt_as_wa); i++) {
-const char *dev_str = to_be_removed_from_dt_as_wa[i];
-
-int offset = fdt_node_offset_by_compatible(fdt, -1, dev_str);
-if (offset >= 0) {
-if (!fdt_nop_node(fdt, offset)) {
-warn_report("bcm2711 dtc: %s has been disabled!", dev_str);
-}
-}
-}
-
 uint64_t ram_size = board_ram_size(info->board_id);
 
 if (info->ram_size > UPPER_RAM_BASE) {
diff --git a/include/hw/arm/bcm2838_peripherals.h 
b/include/hw/arm/bcm2838_peripherals.h
index 20b7d1eb67..1cfcf5dcce 100644
--- a/include/hw/arm/bcm2838_peripherals.h
+++ b/include/hw/arm/bcm2838_peripherals.h
@@ -13,6 +13,7 @@
 #include "hw/misc/bcm2838_rng200.h"
 #include "hw/misc/bcm2838_thermal.h"
 #include "hw/arm/bcm2838_pcie.h"
+#include "hw/net/bcm2838_genet.h"
 #include "hw/sd/sdhci.h"
 #include "hw/gpio/bcm2838_gpio.h"
 
@@ -73,6 +74,7 @@ struct BCM2838PeripheralState {
 UnimplementedDeviceState clkisp;
 BCM2838PcieHostState pcie_host;
 BCM2838GpioState gpio;
+BCM2838GenetState genet;
 
 OrIRQState mmc_irq_orgate;
 OrIRQState dma_7_8_irq_orgate;
-- 
2.34.1




[PATCH v4 45/45] Add RPi4B to paspi4.rst

2023-12-07 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 docs/system/arm/raspi.rst | 11 +++
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/docs/system/arm/raspi.rst b/docs/system/arm/raspi.rst
index 922fe375a6..db9e0949ef 100644
--- a/docs/system/arm/raspi.rst
+++ b/docs/system/arm/raspi.rst
@@ -1,5 +1,5 @@
-Raspberry Pi boards (``raspi0``, ``raspi1ap``, ``raspi2b``, ``raspi3ap``, 
``raspi3b``)
-==
+Raspberry Pi boards (``raspi0``, ``raspi1ap``, ``raspi2b``, ``raspi3ap``, 
``raspi3b``, ``raspi4b-2g``)
+==
 
 
 QEMU provides models of the following Raspberry Pi boards:
@@ -12,12 +12,13 @@ QEMU provides models of the following Raspberry Pi boards:
   Cortex-A53 (4 cores), 512 MiB of RAM
 ``raspi3b``
   Cortex-A53 (4 cores), 1 GiB of RAM
-
+``raspi4b-2g``
+  Cortex-A72 (4 cores), 2 GiB of RAM
 
 Implemented devices
 ---
 
- * ARM1176JZF-S, Cortex-A7 or Cortex-A53 CPU
+ * ARM1176JZF-S, Cortex-A7, Cortex-A53 or Cortex-A72 CPU
  * Interrupt controller
  * DMA controller
  * Clock and reset controller (CPRMAN)
@@ -33,6 +34,8 @@ Implemented devices
  * USB2 host controller (DWC2 and MPHI)
  * MailBox controller (MBOX)
  * VideoCore firmware (property)
+ * PCIE Root Port (raspi4b-2g)
+ * GENET Ethernet Controller (raspi4b-2g)
 
 
 Missing devices
-- 
2.34.1




[PATCH v4 25/45] Add GENET register structs. Part 3

2023-12-07 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/net/bcm2838_genet.c | 88 ++
 include/hw/net/bcm2838_genet.h | 88 ++
 2 files changed, 176 insertions(+)

diff --git a/hw/net/bcm2838_genet.c b/hw/net/bcm2838_genet.c
index 9a99f34c4a..be899b68f8 100644
--- a/hw/net/bcm2838_genet.c
+++ b/hw/net/bcm2838_genet.c
@@ -145,6 +145,94 @@ FIELD(GENET_RDMA_LENGTH_STATUS, OWN,15, 1)
 FIELD(GENET_RDMA_LENGTH_STATUS, BUFLENGTH,  16, 12)
 FIELD(GENET_RDMA_LENGTH_STATUS, RSVD_28_31, 29, 4)
 
+REG32(GENET_TDMA_LENGTH_STATUS, 0)
+FIELD(GENET_TDMA_LENGTH_STATUS, RSVD_0_3,   0, 4)
+FIELD(GENET_TDMA_LENGTH_STATUS, DO_CSUM,4, 1)
+FIELD(GENET_TDMA_LENGTH_STATUS, OW_CRC, 5, 1)
+FIELD(GENET_TDMA_LENGTH_STATUS, APPEND_CRC, 6, 1)
+FIELD(GENET_TDMA_LENGTH_STATUS, RSVD_7_8,   7, 2)
+FIELD(GENET_TDMA_LENGTH_STATUS, UNDERRUN,   9, 1)
+FIELD(GENET_TDMA_LENGTH_STATUS, RSVD_10_11, 10, 2)
+FIELD(GENET_TDMA_LENGTH_STATUS, WRAP,   12, 1)
+FIELD(GENET_TDMA_LENGTH_STATUS, SOP,13, 1)
+FIELD(GENET_TDMA_LENGTH_STATUS, EOP,14, 1)
+FIELD(GENET_TDMA_LENGTH_STATUS, OWN,15, 1)
+FIELD(GENET_TDMA_LENGTH_STATUS, BUFLENGTH,  16, 12)
+FIELD(GENET_TDMA_LENGTH_STATUS, RSVD_28_31, 29, 4)
+
+REG16(GENET_PHY_BMCR,0)
+FIELD(GENET_PHY_BMCR, RSVD_0_5,  0, 6)
+FIELD(GENET_PHY_BMCR, SPEED1000, 6, 1)
+FIELD(GENET_PHY_BMCR, CTST,  7, 1)
+FIELD(GENET_PHY_BMCR, FULLDPLX,  8, 1)
+FIELD(GENET_PHY_BMCR, ANRESTART, 9, 1)
+FIELD(GENET_PHY_BMCR, ISOLATE,   10, 1)
+FIELD(GENET_PHY_BMCR, PDOWN, 11, 1)
+FIELD(GENET_PHY_BMCR, AENABLE,   12, 1)
+FIELD(GENET_PHY_BMCR, SPEED100,  13, 1)
+FIELD(GENET_PHY_BMCR, LOOPBACK,  14, 1)
+FIELD(GENET_PHY_BMCR, RESET, 15, 1)
+
+REG16(GENET_PHY_BMSR,   0)
+FIELD(GENET_PHY_BMSR, ERCAP,0, 1)
+FIELD(GENET_PHY_BMSR, JCD,  1, 1)
+FIELD(GENET_PHY_BMSR, LSTATUS,  2, 1)
+FIELD(GENET_PHY_BMSR, ANEGCAPABLE,  3, 1)
+FIELD(GENET_PHY_BMSR, RFAULT,   4, 1)
+FIELD(GENET_PHY_BMSR, ANEGCOMPLETE, 5, 1)
+FIELD(GENET_PHY_BMSR, RSVD_6_7, 6, 2)
+FIELD(GENET_PHY_BMSR, ESTATEN,  8, 1)
+FIELD(GENET_PHY_BMSR, _100HALF2,9, 1)
+FIELD(GENET_PHY_BMSR, _100FULL2,10, 1)
+FIELD(GENET_PHY_BMSR, _10HALF,  11, 1)
+FIELD(GENET_PHY_BMSR, _10FULL,  12, 1)
+FIELD(GENET_PHY_BMSR, _100HALF, 13, 1)
+FIELD(GENET_PHY_BMSR, _100FULL, 14, 1)
+FIELD(GENET_PHY_BMSR, _10BASE4, 15, 1)
+
+REG16(GENET_PHY_LPA,   0)
+FIELD(GENET_PHY_LPA, SLCT, 0, 5)
+FIELD(GENET_PHY_LPA, _10HALF_1000XFULL,5, 1)
+FIELD(GENET_PHY_LPA, _10FULL_1000XHALF,6, 1)
+FIELD(GENET_PHY_LPA, _100HALF_1000XPAUSE,  7, 1)
+FIELD(GENET_PHY_LPA, _100FULL_1000XPAUSE_ASYM, 8, 1)
+FIELD(GENET_PHY_LPA, _100BASE4,9, 1)
+FIELD(GENET_PHY_LPA, PAUSE_CAP,10, 1)
+FIELD(GENET_PHY_LPA, PAUSE_ASYM,   11, 1)
+FIELD(GENET_PHY_LPA, RSVD_12,  12, 1)
+FIELD(GENET_PHY_LPA, RFAULT,   13, 1)
+FIELD(GENET_PHY_LPA, LPACK,14, 1)
+FIELD(GENET_PHY_LPA, NPAGE,15, 1)
+
+REG16(GENET_PHY_STAT_1000,0)
+FIELD(GENET_PHY_STAT_1000, RSVD_0_9,  0, 10)
+FIELD(GENET_PHY_STAT_1000, HALF,  10, 1)
+FIELD(GENET_PHY_STAT_1000, FULL,  11, 1)
+FIELD(GENET_PHY_STAT_1000, REMRXOK,   12, 1)
+FIELD(GENET_PHY_STAT_1000, LOCALRXOK, 13, 1)
+FIELD(GENET_PHY_STAT_1000, MSRES, 14, 1)
+FIELD(GENET_PHY_STAT_1000, MSFAIL,15, 1)
+
+REG16(GENET_PHY_AUX_CTRL_0,  0)
+FIELD(GENET_PHY_AUX_CTRL_0, REG_ID_MASK, 0, 3)
+FIELD(GENET_PHY_AUX_CTRL_0, RSVD_3,  3, 1)
+FIELD(GENET_PHY_AUX_CTRL_0, REG_DATA,4, 8)
+FIELD(GENET_PHY_AUX_CTRL_0, REG_ID,  12, 3)
+FIELD(GENET_PHY_AUX_CTRL_0, MISC_WREN,   15, 1)
+
+REG16(GENET_PHY_AUX_CTRL_1,   0)
+FIELD(GENET_PHY_AUX_CTRL_1, RSVD_0_3, 0, 4)
+FIELD(GENET_PHY_AUX_CTRL_1, REG_DATA, 4, 12)
+
+REG16(GENET_PHY_SHADOW,   0)
+FIELD(GENET_PHY_SHADOW, REG_DATA, 0, 10)
+FIELD(GENET_PHY_SHADOW, REG_ID,   10, 5)
+FIELD(GENET_PHY_SHADOW, WR,   15, 1)
+
+REG16(GENET_PHY_EXP_SEL,   0)
+FIELD(GENET_PHY_EXP_SEL, REG_ID,   0, 8)
+FIELD(GENET_PHY_EXP_SEL, BLOCK_ID, 8, 8)
+
 static uint64_t bcm2838_genet_read(void *opaque, hwaddr offset, unsigned size)
 {
 uint64_t value = ~0;
diff --git a/include/hw/net/bcm2838_genet.h b/include/hw/net/bcm2838_genet.h
index 736b4d1757..1bd004785a 100644
--- a/include/hw/net/bcm2838_genet.h
+++ b/include/hw/net/bcm2838_genet.h
@@ -22,6 +22,9 @@ OBJECT_DECLARE_SIMPLE_TYPE(BCM2838GenetState, BCM2838_GENET)
 #define BCM2838_GENET_DMA_RING_CNT  17
 #define BCM2838_GENET_DMA_RING_DEFAULT  (BCM2838_GENET_DMA_RING_CNT - 1)
 
+#define BCM2838_GENET_HFB_FILTER_CNT  48
+#define BCM2838_GENET_HFB_FILTER_SIZE 128
+
 typedef struct {
 uint32_t rev_ctrl;
 uint32_t port_ctrl;
@@ -169,6 +172,53 @@ typedef struct {
 uint32_t reserved_0x10D0[972];
 } BCM2838GenetRegsRdma;
 

[PATCH v4 16/45] Enable BCM2838 PCIE

2023-12-07 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/arm/bcm2838_pcie.c|  3 +++
 hw/arm/bcm2838_peripherals.c | 26 ++
 hw/arm/meson.build   |  7 ---
 hw/arm/raspi4b.c |  1 -
 include/hw/arm/bcm2838_peripherals.h |  3 +++
 5 files changed, 36 insertions(+), 4 deletions(-)

diff --git a/hw/arm/bcm2838_pcie.c b/hw/arm/bcm2838_pcie.c
index 75146d6c2e..8e046d0ac7 100644
--- a/hw/arm/bcm2838_pcie.c
+++ b/hw/arm/bcm2838_pcie.c
@@ -239,6 +239,9 @@ static void bcm2838_pcie_root_reg_reset(PCIDevice *dev)
 }
 
 static void bcm2838_pcie_root_realize(PCIDevice *dev, Error **errp) {
+BCM2838PcieRootClass *brpc = BCM2838_PCIE_ROOT_GET_CLASS(dev);
+
+brpc->parent_realize(dev, errp);
 bcm2838_pcie_root_reg_reset(dev);
 }
 
diff --git a/hw/arm/bcm2838_peripherals.c b/hw/arm/bcm2838_peripherals.c
index d3b42cf25b..ee06214715 100644
--- a/hw/arm/bcm2838_peripherals.c
+++ b/hw/arm/bcm2838_peripherals.c
@@ -12,6 +12,11 @@
 #include "hw/arm/raspi_platform.h"
 #include "hw/arm/bcm2838_peripherals.h"
 
+#define PCIE_RC_OFFSET  0x150
+#define PCIE_MMIO_OFFSET0xc000
+#define PCIE_MMIO_ARM_OFFSET0x6
+#define PCIE_MMIO_SIZE  0x4000
+
 /* Lower peripheral base address on the VC (GPU) system bus */
 #define BCM2838_VC_PERI_LOW_BASE 0x7c00
 
@@ -29,6 +34,10 @@ static void bcm2838_peripherals_init(Object *obj)
bc->peri_low_size);
 sysbus_init_mmio(SYS_BUS_DEVICE(s), >peri_low_mr);
 
+/* PCIe Host Bridge */
+object_initialize_child(obj, "pcie-host", >pcie_host,
+TYPE_BCM2838_PCIE_HOST);
+
 /* Extended Mass Media Controller 2 */
 object_initialize_child(obj, "emmc2", >emmc2, TYPE_SYSBUS_SDHCI);
 
@@ -61,6 +70,9 @@ static void bcm2838_peripherals_realize(DeviceState *dev, 
Error **errp)
 MemoryRegion *mphi_mr;
 BCM2838PeripheralState *s = BCM2838_PERIPHERALS(dev);
 BCMSocPeripheralBaseState *s_base = BCM_SOC_PERIPHERALS_BASE(dev);
+MemoryRegion *regs_mr;
+MemoryRegion *mmio_mr;
+
 int n;
 
 bcm_soc_peripherals_common_realize(dev, errp);
@@ -172,6 +184,20 @@ static void bcm2838_peripherals_realize(DeviceState *dev, 
Error **errp)
  BCM2838_MPHI_SIZE);
 memory_region_add_subregion(_base->peri_mr, BCM2838_MPHI_OFFSET,
 >mphi_mr_alias);
+/* PCIe Root Complex */
+if (!sysbus_realize(SYS_BUS_DEVICE(>pcie_host), errp)) {
+return;
+}
+/* RC registers region */
+regs_mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(>pcie_host), 0);
+memory_region_add_subregion(>peri_low_mr, PCIE_RC_OFFSET, regs_mr);
+/* MMIO region */
+mmio_mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(>pcie_host), 1);
+memory_region_init_alias(>pcie_mmio_alias, OBJECT(>pcie_host),
+ "pcie-mmio", mmio_mr, PCIE_MMIO_OFFSET,
+ PCIE_MMIO_SIZE);
+memory_region_add_subregion(get_system_memory(), PCIE_MMIO_ARM_OFFSET,
+>pcie_mmio_alias);
 
 /* GPIO */
 if (!sysbus_realize(SYS_BUS_DEVICE(>gpio), errp)) {
diff --git a/hw/arm/meson.build b/hw/arm/meson.build
index b26ed13c6f..69d199b73e 100644
--- a/hw/arm/meson.build
+++ b/hw/arm/meson.build
@@ -41,7 +41,6 @@ arm_ss.add(when: 'CONFIG_ALLWINNER_R40', if_true: 
files('allwinner-r40.c', 'bana
 arm_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2836.c', 'raspi.c'))
 arm_ss.add(when: ['CONFIG_RASPI', 'TARGET_AARCH64'], if_true: files(
   'bcm2838.c',
-  'bcm2838_pcie.c',
   'raspi4b.c'))
 arm_ss.add(when: 'CONFIG_STM32F100_SOC', if_true: files('stm32f100_soc.c'))
 arm_ss.add(when: 'CONFIG_STM32F205_SOC', if_true: files('stm32f205_soc.c'))
@@ -72,8 +71,10 @@ arm_ss.add(when: 'CONFIG_XEN', if_true: files('xen_arm.c'))
 
 system_ss.add(when: 'CONFIG_ARM_SMMUV3', if_true: files('smmu-common.c'))
 system_ss.add(when: 'CONFIG_EXYNOS4', if_true: files('exynos4_boards.c'))
-system_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2835_peripherals.c'))
-system_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2838_peripherals.c'))
+system_ss.add(when: 'CONFIG_RASPI', if_true: files(
+'bcm2835_peripherals.c',
+'bcm2838_peripherals.c',
+'bcm2838_pcie.c'))
 system_ss.add(when: 'CONFIG_TOSA', if_true: files('tosa.c'))
 
 hw_arch += {'arm': arm_ss}
diff --git a/hw/arm/raspi4b.c b/hw/arm/raspi4b.c
index 10376b62dc..2e8474e1c5 100644
--- a/hw/arm/raspi4b.c
+++ b/hw/arm/raspi4b.c
@@ -67,7 +67,6 @@ static void raspi4_modify_dtb(const struct arm_boot_info 
*info, void *fdt)
 
 /* Temporarily disable following devices until they are implemented*/
 const char *to_be_removed_from_dt_as_wa[] = {
-"brcm,bcm2711-pcie",
 "brcm,bcm2711-rng200",
 "brcm,bcm2711-thermal",
 "brcm,bcm2711-genet-v5",
diff --git a/include/hw/arm/bcm2838_peripherals.h 
b/include/hw/arm/bcm2838_peripherals.h
index 

[PATCH v4 04/45] Introduce BCM2838 SoC

2023-12-07 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/arm/bcm2838.c | 100 +++
 hw/arm/bcm2838_peripherals.c |  72 +++
 hw/arm/meson.build   |   2 +
 include/hw/arm/bcm2838.h |  29 
 include/hw/arm/bcm2838_peripherals.h |  36 ++
 5 files changed, 239 insertions(+)
 create mode 100644 hw/arm/bcm2838.c
 create mode 100644 hw/arm/bcm2838_peripherals.c
 create mode 100644 include/hw/arm/bcm2838.h
 create mode 100644 include/hw/arm/bcm2838_peripherals.h

diff --git a/hw/arm/bcm2838.c b/hw/arm/bcm2838.c
new file mode 100644
index 00..c61c59661b
--- /dev/null
+++ b/hw/arm/bcm2838.c
@@ -0,0 +1,100 @@
+/*
+ * BCM2838 SoC emulation
+ *
+ * Copyright (C) 2022 Ovchinnikov Vitalii 
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu/module.h"
+#include "hw/arm/raspi_platform.h"
+#include "hw/sysbus.h"
+#include "hw/arm/bcm2838.h"
+#include "trace.h"
+
+#define VIRTUAL_PMU_IRQ 7
+
+static void bcm2838_init(Object *obj)
+{
+BCM2838State *s = BCM2838(obj);
+
+object_initialize_child(obj, "peripherals", >peripherals,
+TYPE_BCM2838_PERIPHERALS);
+object_property_add_alias(obj, "board-rev", OBJECT(>peripherals),
+  "board-rev");
+object_property_add_alias(obj, "vcram-size", OBJECT(>peripherals),
+  "vcram-size");
+object_property_add_alias(obj, "command-line", OBJECT(>peripherals),
+  "command-line");
+}
+
+static void bcm2838_realize(DeviceState *dev, Error **errp)
+{
+int n;
+BCM2838State *s = BCM2838(dev);
+BCM283XBaseState *s_base = BCM283X_BASE(dev);
+BCM283XBaseClass *bc_base = BCM283X_BASE_GET_CLASS(dev);
+BCM2838PeripheralState *ps = BCM2838_PERIPHERALS(>peripherals);
+BCMSocPeripheralBaseState *ps_base =
+BCM_SOC_PERIPHERALS_BASE(>peripherals);
+
+if (!bcm283x_common_realize(dev, ps_base, errp)) {
+return;
+}
+sysbus_mmio_map_overlap(SYS_BUS_DEVICE(ps), 1, BCM2838_PERI_LOW_BASE, 1);
+
+/* bcm2836 interrupt controller (and mailboxes, etc.) */
+if (!sysbus_realize(SYS_BUS_DEVICE(_base->control), errp)) {
+return;
+}
+sysbus_mmio_map(SYS_BUS_DEVICE(_base->control), 0, bc_base->ctrl_base);
+
+/* Create cores */
+for (n = 0; n < bc_base->core_count; n++) {
+/* TODO: this should be converted to a property of ARM_CPU */
+s_base->cpu[n].core.mp_affinity = (bc_base->clusterid << 8) | n;
+
+/* start powered off if not enabled */
+if (!object_property_set_bool(OBJECT(_base->cpu[n].core),
+  "start-powered-off",
+  n >= s_base->enabled_cpus,
+  errp)) {
+return;
+}
+
+if (!qdev_realize(DEVICE(_base->cpu[n].core), NULL, errp)) {
+return;
+}
+}
+}
+
+static void bcm2838_class_init(ObjectClass *oc, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(oc);
+BCM283XBaseClass *bc_base = BCM283X_BASE_CLASS(oc);
+
+bc_base->cpu_type = ARM_CPU_TYPE_NAME("cortex-a72");
+bc_base->core_count = BCM283X_NCPUS;
+bc_base->peri_base = 0xfe00;
+bc_base->ctrl_base = 0xff80;
+bc_base->clusterid = 0x0;
+dc->realize = bcm2838_realize;
+}
+
+static const TypeInfo bcm2838_type = {
+.name   = TYPE_BCM2838,
+.parent = TYPE_BCM283X_BASE,
+.instance_size  = sizeof(BCM2838State),
+.instance_init  = bcm2838_init,
+.class_size = sizeof(BCM283XBaseClass),
+.class_init = bcm2838_class_init,
+};
+
+static void bcm2838_register_types(void)
+{
+type_register_static(_type);
+}
+
+type_init(bcm2838_register_types);
diff --git a/hw/arm/bcm2838_peripherals.c b/hw/arm/bcm2838_peripherals.c
new file mode 100644
index 00..06110c724f
--- /dev/null
+++ b/hw/arm/bcm2838_peripherals.c
@@ -0,0 +1,72 @@
+/*
+ * BCM2838 peripherals emulation
+ *
+ * Copyright (C) 2022 Ovchinnikov Vitalii 
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu/module.h"
+#include "hw/arm/raspi_platform.h"
+#include "hw/arm/bcm2838_peripherals.h"
+
+/* Lower peripheral base address on the VC (GPU) system bus */
+#define BCM2838_VC_PERI_LOW_BASE 0x7c00
+
+static void bcm2838_peripherals_init(Object *obj)
+{
+BCM2838PeripheralState *s = BCM2838_PERIPHERALS(obj);
+BCM2838PeripheralClass *bc = BCM2838_PERIPHERALS_GET_CLASS(obj);
+
+/* Lower memory region for peripheral devices (exported to the Soc) */
+memory_region_init(>peri_low_mr, obj, "bcm2838-peripherals",
+   bc->peri_low_size);
+sysbus_init_mmio(SYS_BUS_DEVICE(s), >peri_low_mr);
+
+}
+
+static void bcm2838_peripherals_realize(DeviceState *dev, Error **errp)
+{
+

[PATCH v4 39/45] Add mailbox tests tags. Part 3

2023-12-07 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 tests/qtest/bcm2838-mailbox.h | 78 +++
 1 file changed, 78 insertions(+)

diff --git a/tests/qtest/bcm2838-mailbox.h b/tests/qtest/bcm2838-mailbox.h
index 49668668da..2b140a5d32 100644
--- a/tests/qtest/bcm2838-mailbox.h
+++ b/tests/qtest/bcm2838-mailbox.h
@@ -514,6 +514,84 @@ DECLARE_TAG_TYPE(TAG_GET_DMA_CHANNELS_t,
 uint32_t mask;
 });
 
+DECLARE_TAG_TYPE(TAG_GET_THROTTLED_t,
+struct {},
+struct {
+uint32_t throttled;
+});
+
+DECLARE_TAG_TYPE(TAG_GET_NUM_DISPLAYS_t,
+struct {},
+struct {
+uint32_t num_displays;
+});
+
+DECLARE_TAG_TYPE(TAG_GET_DISPLAY_SETTINGS_t,
+struct {},
+struct {
+uint32_t display_num;
+uint32_t phys_width;
+uint32_t phys_height;
+uint32_t bpp;
+uint16_t pitch;
+uint32_t virt_width;
+uint32_t virt_height;
+uint16_t virt_width_offset;
+uint32_t virt_height_offset;
+uint32_t fb_bus_address_lo;
+uint32_t fb_bus_address_hi;
+});
+
+DECLARE_TAG_TYPE(TAG_GET_GPIO_CONFIG_t,
+struct {
+uint32_t gpio_num;
+},
+struct {
+uint32_t zero;
+uint32_t direction;
+uint32_t polarity;
+uint32_t term_en;
+uint32_t term_pull_up;
+});
+
+
+DECLARE_TAG_TYPE(TAG_SET_GPIO_CONFIG_t,
+struct {
+uint32_t gpio_num;
+uint32_t direction;
+uint32_t polarity;
+uint32_t term_en;
+uint32_t term_pull_up;
+uint32_t state;
+},
+struct {
+uint32_t zero;
+});
+
+DECLARE_TAG_TYPE(TAG_GET_GPIO_STATE_t,
+struct {
+uint32_t gpio_num;
+},
+struct {
+uint32_t zero;
+uint32_t state;
+});
+
+DECLARE_TAG_TYPE(TAG_SET_GPIO_STATE_t,
+struct {
+uint32_t gpio_num;
+uint32_t state;
+},
+struct {
+uint32_t zero;
+});
+
+DECLARE_TAG_TYPE(TAG_INITIALIZE_VCHIQ_t,
+struct {},
+struct {
+uint32_t zero;
+});
+
 int mbox0_has_data(void);
 void mbox0_read_message(uint8_t channel, void *msgbuf, size_t msgbuf_size);
 void mbox1_write_message(uint8_t channel, uint32_t msg_addr);
-- 
2.34.1




[PATCH v4 43/45] Add missed BCM2835 properties

2023-12-07 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/misc/bcm2835_property.c   | 47 
 include/hw/arm/raspberrypi-fw-defs.h | 12 ++-
 2 files changed, 58 insertions(+), 1 deletion(-)

diff --git a/hw/misc/bcm2835_property.c b/hw/misc/bcm2835_property.c
index ff55a4e2cd..dfeb793b3e 100644
--- a/hw/misc/bcm2835_property.c
+++ b/hw/misc/bcm2835_property.c
@@ -19,6 +19,9 @@
 #include "trace.h"
 #include "hw/arm/raspi_platform.h"
 
+#define RPI_EXP_GPIO_BASE   128
+#define VCHI_BUSADDR_SIZE   sizeof(uint32_t)
+
 /* https://github.com/raspberrypi/firmware/wiki/Mailbox-property-interface */
 
 static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
@@ -138,6 +141,13 @@ static void 
bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
 resplen = 8;
 break;
 
+case RPI_FWREQ_GET_CLOCKS:
+/* TODO: add more clock IDs if needed */
+stl_le_phys(>dma_as, value + 12, 0);
+stl_le_phys(>dma_as, value + 16, RPI_FIRMWARE_ARM_CLK_ID);
+resplen = 8;
+break;
+
 case RPI_FWREQ_SET_CLOCK_RATE:
 case RPI_FWREQ_SET_MAX_CLOCK_RATE:
 case RPI_FWREQ_SET_MIN_CLOCK_RATE:
@@ -276,6 +286,7 @@ static void bcm2835_property_mbox_push(BCM2835PropertyState 
*s, uint32_t value)
 stl_le_phys(>dma_as, value + 12, 0);
 resplen = 4;
 break;
+
 case RPI_FWREQ_FRAMEBUFFER_GET_NUM_DISPLAYS:
 stl_le_phys(>dma_as, value + 12, 1);
 resplen = 4;
@@ -301,6 +312,42 @@ static void 
bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
 resplen);
 break;
 
+case RPI_FWREQ_GET_THROTTLED:
+stl_le_phys(>dma_as, value + 12, 0);
+resplen = 4;
+break;
+
+case RPI_FWREQ_FRAMEBUFFER_SET_PITCH:
+qemu_log_mask(LOG_UNIMP, "RPI_FWREQ_FRAMEBUFFER_SET_PITCH "
+  "is not implemented\n");
+break;
+
+case RPI_FWREQ_GET_GPIO_CONFIG:
+qemu_log_mask(LOG_UNIMP, "RPI_FWREQ_GET_GPIO_CONFIG "
+  "is not implemented\n");
+break;
+
+case RPI_FWREQ_SET_GPIO_CONFIG:
+qemu_log_mask(LOG_UNIMP, "RPI_FWREQ_SET_GPIO_CONFIG "
+  "is not implemented\n");
+break;
+
+case RPI_FWREQ_GET_GPIO_STATE:
+qemu_log_mask(LOG_UNIMP, "RPI_FWREQ_GET_GPIO_STATE "
+  "is not implemented\n");
+break;
+
+case RPI_FWREQ_SET_GPIO_STATE:
+qemu_log_mask(LOG_UNIMP, "RPI_FWREQ_SET_GPIO_STATE "
+  "is not implemented\n");
+break;
+
+case RPI_FWREQ_VCHIQ_INIT:
+stl_le_phys(>dma_as,
+value + offsetof(rpi_firmware_prop_request_t, payload),
+0);
+resplen = VCHI_BUSADDR_SIZE;
+break;
 default:
 qemu_log_mask(LOG_UNIMP,
   "bcm2835_property: unhandled tag 0x%08x\n", tag);
diff --git a/include/hw/arm/raspberrypi-fw-defs.h 
b/include/hw/arm/raspberrypi-fw-defs.h
index 4551fe7450..ded7a22f02 100644
--- a/include/hw/arm/raspberrypi-fw-defs.h
+++ b/include/hw/arm/raspberrypi-fw-defs.h
@@ -101,7 +101,6 @@ enum rpi_firmware_property_tag {
 RPI_FWREQ_FRAMEBUFFER_GET_DISPLAY_ID = 0x00040016,
 RPI_FWREQ_FRAMEBUFFER_SET_DISPLAY_NUM =0x00048013,
 RPI_FWREQ_FRAMEBUFFER_GET_NUM_DISPLAYS =   0x00040013,
-RPI_FWREQ_FRAMEBUFFER_GET_DISPLAY_SETTINGS =   0x00040014,
 RPI_FWREQ_FRAMEBUFFER_TEST_PHYSICAL_WIDTH_HEIGHT = 0x00044003,
 RPI_FWREQ_FRAMEBUFFER_TEST_VIRTUAL_WIDTH_HEIGHT =  0x00044004,
 RPI_FWREQ_FRAMEBUFFER_TEST_DEPTH = 0x00044005,
@@ -160,4 +159,15 @@ enum rpi_firmware_clk_id {
 RPI_FIRMWARE_NUM_CLK_ID,
 };
 
+struct rpi_firmware_property_tag_header {
+uint32_t tag;
+uint32_t buf_size;
+uint32_t req_resp_size;
+};
+
+typedef struct rpi_firmware_prop_request {
+struct rpi_firmware_property_tag_header hdr;
+uint8_t payload[0];
+} rpi_firmware_prop_request_t;
+
 #endif /* INCLUDE_HW_MISC_RASPBERRYPI_FW_DEFS_H_ */
-- 
2.34.1




[PATCH v4 44/45] Append added properties to mailbox test

2023-12-07 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 tests/qtest/bcm2838-mbox-property-test.c | 22 --
 1 file changed, 16 insertions(+), 6 deletions(-)

diff --git a/tests/qtest/bcm2838-mbox-property-test.c 
b/tests/qtest/bcm2838-mbox-property-test.c
index 1b4a2ed9cb..3a2e7f9194 100644
--- a/tests/qtest/bcm2838-mbox-property-test.c
+++ b/tests/qtest/bcm2838-mbox-property-test.c
@@ -269,6 +269,12 @@ DECLARE_TEST_CASE_SETUP(GET_MIN_CLOCK_RATE, ANY) {
 tag->request.value.clock_id = CLOCK_ID_UNDEFINED;
 }
 
+/**/
+DECLARE_TEST_CASE(GET_CLOCKS) {
+g_assert_cmphex(tag->response.value.root_clock, ==, CLOCK_ID_ROOT);
+g_assert_cmphex(tag->response.value.arm_clock, ==, CLOCK_ID_ARM);
+}
+
 
/**/
 DECLARE_TEST_CASE(GET_TEMPERATURE) {
 g_assert_cmphex(tag->response.value.temperature_id, ==, 
TEMPERATURE_ID_SOC);
@@ -535,17 +541,19 @@ DECLARE_TEST_CASE(GET_COMMANDLINE) {
 /* No special checks are needed for this test case */
 }
 
+/**/
+DECLARE_TEST_CASE(GET_THROTTLED) {
+g_assert_cmpint(tag->response.value.throttled, ==, 0);
+}
+
 
/**/
 DECLARE_TEST_CASE(GET_NUM_DISPLAYS) {
 g_assert_cmpint(tag->response.value.num_displays, ==, 1);
 }
 
 
/**/
-DECLARE_TEST_CASE(SET_PITCH) {
-/* No special checks are needed for this test case */
-}
-DECLARE_TEST_CASE_SETUP(SET_PITCH) {
-tag->request.value.pitch = DUMMY_VALUE;
+DECLARE_TEST_CASE(INITIALIZE_VCHIQ) {
+g_assert_cmpint(tag->response.value.zero, ==, 0);
 }
 
 
/**/
@@ -571,6 +579,7 @@ int main(int argc, char **argv)
 QTEST_ADD_TEST_CASE(GET_CLOCK_RATE, ANY);
 QTEST_ADD_TEST_CASE(GET_MAX_CLOCK_RATE, ANY);
 QTEST_ADD_TEST_CASE(GET_MIN_CLOCK_RATE, ANY);
+QTEST_ADD_TEST_CASE(GET_CLOCKS);
 QTEST_ADD_TEST_CASE(GET_TEMPERATURE);
 QTEST_ADD_TEST_CASE(GET_MAX_TEMPERATURE);
 QTEST_ADD_TEST_CASE(ALLOCATE_BUFFER);
@@ -604,8 +613,9 @@ int main(int argc, char **argv)
 QTEST_ADD_TEST_CASE(SET_OVERSCAN);
 QTEST_ADD_TEST_CASE(GET_DMA_CHANNELS);
 QTEST_ADD_TEST_CASE(GET_COMMANDLINE);
+QTEST_ADD_TEST_CASE(GET_THROTTLED);
 QTEST_ADD_TEST_CASE(GET_NUM_DISPLAYS);
-QTEST_ADD_TEST_CASE(SET_PITCH);
+QTEST_ADD_TEST_CASE(INITIALIZE_VCHIQ);
 
 return g_test_run();
 }
-- 
2.34.1




[PATCH v4 34/45] Add Rpi4b boot tests

2023-12-07 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 tests/avocado/boot_linux_console.py | 92 +
 1 file changed, 92 insertions(+)

diff --git a/tests/avocado/boot_linux_console.py 
b/tests/avocado/boot_linux_console.py
index 6eab515718..b5c090ae64 100644
--- a/tests/avocado/boot_linux_console.py
+++ b/tests/avocado/boot_linux_console.py
@@ -501,6 +501,98 @@ def test_arm_raspi2_initrd(self):
 # Wait for VM to shut down gracefully
 self.vm.wait()
 
+def test_arm_raspi4(self):
+"""
+:avocado: tags=arch:aarch64
+:avocado: tags=machine:raspi4b-2g
+:avocado: tags=device:pl011
+:avocado: tags=accel:tcg
+:avocado: tags=rpi4b
+
+The kernel can be rebuilt using the kernel source referenced
+and following the instructions on the on:
+https://www.raspberrypi.org/documentation/linux/kernel/building.md
+"""
+
+deb_url = ('http://archive.raspberrypi.org/debian/'
+'pool/main/r/raspberrypi-firmware/'
+'raspberrypi-kernel_1.20230106-1_arm64.deb')
+deb_hash = '08dc55696535b18a6d4fe6fa10d4c0d905cbb2ed'
+deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
+kernel_path = self.extract_from_deb(deb_path, '/boot/kernel8.img')
+dtb_path = self.extract_from_deb(deb_path, '/boot/bcm2711-rpi-4-b.dtb')
+
+self.vm.set_console()
+kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
+   'earlycon=pl011,mmio32,0xfe201000 ' +
+   'console=ttyAMA0,115200 ' +
+   'root=/dev/mmcblk1p2 rootwait ' +
+   'dwc_otg.fiq_fsm_enable=0')
+self.vm.add_args('-kernel', kernel_path,
+ '-dtb', dtb_path,
+ '-append', kernel_command_line,
+ '-device', 'qemu-xhci,bus=pcie.1,id=xhci',
+ '-device', 'usb-kbd,bus=xhci.0')
+self.vm.launch()
+console_pattern = 'Kernel command line: %s' % kernel_command_line
+self.wait_for_console_pattern(console_pattern)
+console_pattern = 'Product: QEMU USB Keyboard'
+self.wait_for_console_pattern(console_pattern)
+
+
+def test_arm_raspi4_initrd(self):
+"""
+:avocado: tags=arch:aarch64
+:avocado: tags=machine:raspi4b-2g
+:avocado: tags=device:pl011
+:avocado: tags=accel:tcg
+:avocado: tags=rpi4b
+
+The kernel can be rebuilt using the kernel source referenced
+and following the instructions on the on:
+https://www.raspberrypi.org/documentation/linux/kernel/building.md
+"""
+deb_url = ('http://archive.raspberrypi.org/debian/'
+'pool/main/r/raspberrypi-firmware/'
+'raspberrypi-kernel_1.20230106-1_arm64.deb')
+deb_hash = '08dc55696535b18a6d4fe6fa10d4c0d905cbb2ed'
+deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
+kernel_path = self.extract_from_deb(deb_path, '/boot/kernel8.img')
+dtb_path = self.extract_from_deb(deb_path, '/boot/bcm2711-rpi-4-b.dtb')
+
+initrd_url = ('https://github.com/groeck/linux-build-test/raw/'
+  '86b2be1384d41c8c388e63078a847f1e1c4cb1de/rootfs/'
+  'arm64/rootfs.cpio.gz')
+initrd_hash = 'f3d4f9fa92a49aa542f1b44d34be77bbf8ca5b9d'
+initrd_path_gz = self.fetch_asset(initrd_url, asset_hash=initrd_hash)
+initrd_path = os.path.join(self.workdir, 'rootfs.cpio')
+archive.gzip_uncompress(initrd_path_gz, initrd_path)
+
+self.vm.set_console()
+kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
+   'earlycon=pl011,mmio32,0xfe201000 ' +
+   'console=ttyAMA0,115200 ' +
+   'panic=-1 noreboot ' +
+   'dwc_otg.fiq_fsm_enable=0')
+self.vm.add_args('-kernel', kernel_path,
+ '-dtb', dtb_path,
+ '-initrd', initrd_path,
+ '-append', kernel_command_line,
+ '-device', 'qemu-xhci,bus=pcie.1,id=xhci',
+ '-device', 'usb-kbd,bus=xhci.0',
+ '-no-reboot')
+self.vm.launch()
+self.wait_for_console_pattern('Boot successful.')
+
+exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo',
+'BCM2835')
+exec_command_and_wait_for_pattern(self, 'cat /proc/iomem',
+'cprman@7e101000')
+exec_command_and_wait_for_pattern(self, 'halt', 'reboot: System 
halted')
+# TODO: Raspberry Pi4 doesn't shut down properly with recent kernels
+# Wait for VM to shut down gracefully
+#self.vm.wait()
+
 def test_arm_exynos4210_initrd(self):

[PATCH v4 30/45] Implement GENET TX path

2023-12-07 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/net/bcm2838_genet.c | 221 -
 include/hw/net/bcm2838_genet.h |  17 +++
 2 files changed, 237 insertions(+), 1 deletion(-)

diff --git a/hw/net/bcm2838_genet.c b/hw/net/bcm2838_genet.c
index 1fae3ecbc2..4c9b39a3ca 100644
--- a/hw/net/bcm2838_genet.c
+++ b/hw/net/bcm2838_genet.c
@@ -234,6 +234,13 @@ REG16(GENET_PHY_EXP_SEL,   0)
 FIELD(GENET_PHY_EXP_SEL, REG_ID,   0, 8)
 FIELD(GENET_PHY_EXP_SEL, BLOCK_ID, 8, 8)
 
+REG32(GENET_TX_CSUM_INFO,0)
+FIELD(GENET_TX_CSUM_INFO, OFFSET,0, 15)
+FIELD(GENET_TX_CSUM_INFO, PROTO_UDP, 15, 1)
+FIELD(GENET_TX_CSUM_INFO, START, 16, 15)
+FIELD(GENET_TX_CSUM_INFO, LV,30, 1)
+
+
 static void bcm2838_genet_set_qemu_mac(BCM2838GenetState *s)
 {
 const MACAddr *addr = >nic_conf.macaddr;
@@ -387,6 +394,218 @@ static uint64_t bcm2838_genet_mdio_cmd(BCM2838GenetState 
*s, uint64_t cmd)
 return cmd;
 }
 
+static void bcm2838_genet_xmit_packet(NetClientState *s, void *packet,
+  size_t size)
+{
+uint8_t *buf = packet + sizeof(BCM2838GenetXmitStatus);
+size_t len = size;
+uint16_t len_type = 0;
+
+len -= sizeof(BCM2838GenetXmitStatus);
+net_checksum_calculate(buf, len, CSUM_ALL);
+
+memcpy(_type, [12], sizeof(len_type));
+len_type = ntohs(len_type);
+if (len_type < MAX_PAYLOAD_SIZE) {
+len_type = len;
+len_type = htons(len_type);
+memcpy([12], _type, sizeof(len_type));
+}
+
+qemu_send_packet(s, buf, len);
+}
+
+static uint64_t bcm2838_genet_tx(BCM2838GenetState *s, unsigned int ring_index,
+ uint32_t prod_index,
+ uint32_t cons_index)
+{
+const unsigned int DESC_SIZE_WORDS
+= sizeof(BCM2838GenetTdmaDesc) / sizeof(uint32_t);
+const uint64_t RING_START_ADDR
+= ((uint64_t)s->regs.tdma.rings[ring_index].start_addr_hi << 32)
++ s->regs.tdma.rings[ring_index].start_addr;
+const uint64_t RING_END_ADDR
+= ((uint64_t)s->regs.tdma.rings[ring_index].end_addr_hi << 32)
++ s->regs.tdma.rings[ring_index].end_addr;
+
+hwaddr data_addr;
+uint64_t desc_index;
+uint32_t desc_status = 0;
+uint32_t buflength = 0;
+uint64_t num_descs = 0;
+uint64_t read_ptr
+= ((uint64_t)s->regs.tdma.rings[ring_index].read_ptr_hi << 32)
++ s->regs.tdma.rings[ring_index].read_ptr;
+off_t packet_off = 0;
+
+uint32_t prod_index_fld = FIELD_EX32(prod_index,
+ GENET_DMA_PROD_INDEX, INDEX);
+uint32_t cons_index_fld = FIELD_EX32(cons_index,
+GENET_DMA_CONS_INDEX, INDEX);
+
+while (cons_index_fld != prod_index_fld) {
+desc_index = read_ptr / DESC_SIZE_WORDS;
+if (desc_index >= BCM2838_GENET_DMA_DESC_CNT) {
+qemu_log_mask(
+LOG_GUEST_ERROR,
+"%s: invalid TX descriptor index %" PRIu64 " (exceeds %u)\n",
+__func__, desc_index, BCM2838_GENET_DMA_DESC_CNT - 1);
+break;
+}
+desc_status = s->regs.tdma.descs[desc_index].length_status;
+data_addr = ((uint64_t)s->regs.tdma.descs[desc_index].address_hi << 32)
++ s->regs.tdma.descs[desc_index].address_lo;
+trace_bcm2838_genet_tx(ring_index, desc_index, desc_status,
+   data_addr);
+
+if (FIELD_EX32(desc_status, GENET_RDMA_LENGTH_STATUS, SOP) != 0) {
+packet_off = 0;
+}
+
+buflength = FIELD_EX32(desc_status,
+   GENET_RDMA_LENGTH_STATUS, BUFLENGTH);
+
+/* TODO: Add address_space_read() return value check */
+address_space_read(>dma_as, data_addr,
+MEMTXATTRS_UNSPECIFIED,
+s->tx_packet + packet_off,
+buflength);
+packet_off += buflength;
+
+if (FIELD_EX32(desc_status, GENET_RDMA_LENGTH_STATUS, EOP) != 0) {
+bcm2838_genet_xmit_packet(qemu_get_queue(s->nic), s->tx_packet,
+ packet_off);
+packet_off = 0;
+}
+
+num_descs++;
+cons_index_fld++;
+s->regs.tdma.descs[desc_index].length_status =
+FIELD_DP32(s->regs.tdma.descs[desc_index].length_status,
+   GENET_RDMA_LENGTH_STATUS, OWN, 1);
+read_ptr = read_ptr == RING_END_ADDR + 1 - DESC_SIZE_WORDS
+? RING_START_ADDR : read_ptr + DESC_SIZE_WORDS;
+}
+
+s->regs.tdma.rings[ring_index].read_ptr = read_ptr;
+s->regs.tdma.rings[ring_index].read_ptr_hi = read_ptr >> 32;
+
+return num_descs;
+}
+
+static bool bcm2838_genet_tdma_ring_active(BCM2838GenetState *s,
+   unsigned int ring_index)
+{
+

[PATCH v4 17/45] Add RNG200 skeleton

2023-12-07 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/misc/bcm2838_rng200.c | 152 +++
 hw/misc/meson.build  |   1 +
 hw/misc/trace-events |   9 ++
 include/hw/misc/bcm2838_rng200.h |  51 +++
 4 files changed, 213 insertions(+)
 create mode 100644 hw/misc/bcm2838_rng200.c
 create mode 100644 include/hw/misc/bcm2838_rng200.h

diff --git a/hw/misc/bcm2838_rng200.c b/hw/misc/bcm2838_rng200.c
new file mode 100644
index 00..8f64e6a20f
--- /dev/null
+++ b/hw/misc/bcm2838_rng200.c
@@ -0,0 +1,152 @@
+/*
+ * BCM2838 Random Number Generator emulation
+ *
+ * Copyright (C) 2022 Sergey Pushkarev 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "hw/qdev-properties.h"
+#include "hw/misc/bcm2838_rng200.h"
+#include "migration/vmstate.h"
+#include "trace.h"
+
+static const VMStateDescription vmstate_bcm2838_rng200_regs = {
+.name = "bcm2838_rng200_regs",
+.version_id = 1,
+.minimum_version_id = 1,
+.fields = (VMStateField[]) {
+VMSTATE_UINT32(ctrl, BCM2838_rng_regs_t),
+VMSTATE_UINT32(int_status, BCM2838_rng_regs_t),
+VMSTATE_UINT32(fifo_count, BCM2838_rng_regs_t),
+VMSTATE_UINT32(fifo_count_threshold, BCM2838_rng_regs_t),
+VMSTATE_UINT32(total_bit_count_threshold, BCM2838_rng_regs_t),
+VMSTATE_END_OF_LIST()
+}
+};
+
+static const VMStateDescription vmstate_bcm2838_rng200 = {
+.name = "bcm2838_rng200",
+.version_id = 1,
+.minimum_version_id = 1,
+.fields = (VMStateField[]) {
+VMSTATE_UINT32(rbg_period, BCM2838Rng200State),
+VMSTATE_UINT32(rng_fifo_cap, BCM2838Rng200State),
+VMSTATE_BOOL(use_timer, BCM2838Rng200State),
+
+VMSTATE_STRUCT(regs, BCM2838Rng200State, 0, 
vmstate_bcm2838_rng200_regs,
+   BCM2838_rng_regs_t),
+
+VMSTATE_END_OF_LIST()
+}
+};
+
+static void bcm2838_rng200_rng_reset(BCM2838Rng200State *state)
+{
+state->regs.ctrl = 0;
+
+trace_bcm2838_rng200_rng_soft_reset();
+}
+
+static uint64_t bcm2838_rng200_read(void *opaque, hwaddr offset,
+unsigned size)
+{
+uint32_t res = 0;
+
+/* will be implemented in upcoming commits */
+return res;
+}
+
+static void bcm2838_rng200_write(void *opaque, hwaddr offset,
+ uint64_t value, unsigned size)
+{
+/* will be implemented in upcoming commits */
+}
+
+static const MemoryRegionOps bcm2838_rng200_ops = {
+.read = bcm2838_rng200_read,
+.write = bcm2838_rng200_write,
+.endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void bcm2838_rng200_realize(DeviceState *dev, Error **errp)
+{
+BCM2838Rng200State *s = BCM2838_RNG200(dev);
+
+if (s->rng == NULL) {
+Object *default_backend = object_new(TYPE_RNG_BUILTIN);
+
+object_property_add_child(OBJECT(dev), "default-backend",
+  default_backend);
+object_unref(default_backend);
+
+object_property_set_link(OBJECT(dev), "rng", default_backend,
+ errp);
+}
+
+sysbus_init_irq(SYS_BUS_DEVICE(dev), >irq);
+}
+
+static void bcm2838_rng200_init(Object *obj)
+{
+BCM2838Rng200State *s = BCM2838_RNG200(obj);
+SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+
+s->rbg_period = 250;
+s->use_timer = true;
+
+s->rng_fifo_cap = 128;
+
+s->clock = qdev_init_clock_in(DEVICE(s), "rbg-clock",
+  NULL, s,
+  ClockPreUpdate);
+if (s->clock == NULL) {
+error_setg(_fatal, "Failed to init RBG clock");
+return;
+}
+
+memory_region_init_io(>iomem, obj, _rng200_ops, s,
+  TYPE_BCM2838_RNG200, 0x28);
+sysbus_init_mmio(sbd, >iomem);
+}
+
+static void bcm2838_rng200_reset(DeviceState *dev)
+{
+BCM2838Rng200State *s = BCM2838_RNG200(dev);
+bcm2838_rng200_rng_reset(s);
+}
+
+static Property bcm2838_rng200_properties[] = {
+DEFINE_PROP_LINK("rng", BCM2838Rng200State, rng,
+ TYPE_RNG_BACKEND, RngBackend *),
+DEFINE_PROP_END_OF_LIST(),
+};
+
+static void bcm2838_rng200_class_init(ObjectClass *klass, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(klass);
+
+dc->realize = bcm2838_rng200_realize;
+dc->reset = bcm2838_rng200_reset;
+dc->vmsd = _bcm2838_rng200;
+
+device_class_set_props(dc, bcm2838_rng200_properties);
+}
+
+static const TypeInfo bcm2838_rng200_info = {
+.name  = TYPE_BCM2838_RNG200,
+.parent= TYPE_SYS_BUS_DEVICE,
+.instance_size = sizeof(BCM2838Rng200State),
+.class_init= bcm2838_rng200_class_init,
+.instance_init = bcm2838_rng200_init,
+};
+
+static void bcm2838_rng200_register_types(void)
+{
+type_register_static(_rng200_info);
+}
+

[PATCH v4 20/45] Implement BCM2838 thermal sensor

2023-12-07 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/arm/bcm2838_peripherals.c | 27 ++--
 hw/arm/raspi4b.c |  1 -
 hw/misc/bcm2838_thermal.c| 98 
 hw/misc/meson.build  |  3 +-
 include/hw/arm/bcm2838_peripherals.h |  2 +
 include/hw/misc/bcm2838_thermal.h| 24 +++
 6 files changed, 147 insertions(+), 8 deletions(-)
 create mode 100644 hw/misc/bcm2838_thermal.c
 create mode 100644 include/hw/misc/bcm2838_thermal.h

diff --git a/hw/arm/bcm2838_peripherals.c b/hw/arm/bcm2838_peripherals.c
index 7c489c8e8a..e9c6d47ba6 100644
--- a/hw/arm/bcm2838_peripherals.c
+++ b/hw/arm/bcm2838_peripherals.c
@@ -37,6 +37,9 @@ static void bcm2838_peripherals_init(Object *obj)
 /* Random Number Generator */
 object_initialize_child(obj, "rng200", >rng200, TYPE_BCM2838_RNG200);
 
+/* Thermal */
+object_initialize_child(obj, "thermal", >thermal, TYPE_BCM2838_THERMAL);
+
 /* PCIe Host Bridge */
 object_initialize_child(obj, "pcie-host", >pcie_host,
 TYPE_BCM2838_PCIE_HOST);
@@ -75,6 +78,9 @@ static void bcm2838_peripherals_realize(DeviceState *dev, 
Error **errp)
 BCMSocPeripheralBaseState *s_base = BCM_SOC_PERIPHERALS_BASE(dev);
 MemoryRegion *regs_mr;
 MemoryRegion *mmio_mr;
+MemoryRegion *rng200_mr;
+MemoryRegion *thermal_mr;
+qemu_irq rng_200_irq;
 
 int n;
 
@@ -92,12 +98,20 @@ static void bcm2838_peripherals_realize(DeviceState *dev, 
Error **errp)
 if (!sysbus_realize(SYS_BUS_DEVICE(>rng200), errp)) {
 return;
 }
-memory_region_add_subregion(
-_base->peri_mr, RNG_OFFSET,
-sysbus_mmio_get_region(SYS_BUS_DEVICE(>rng200), 0));
-sysbus_connect_irq(SYS_BUS_DEVICE(>rng200), 0,
-qdev_get_gpio_in_named(DEVICE(_base->ic), BCM2835_IC_GPU_IRQ,
-   INTERRUPT_RNG));
+rng200_mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(>rng200), 0);
+memory_region_add_subregion(_base->peri_mr, RNG_OFFSET, rng200_mr);
+
+rng_200_irq = qdev_get_gpio_in_named(DEVICE(_base->ic),
+ BCM2835_IC_GPU_IRQ, INTERRUPT_RNG);
+sysbus_connect_irq(SYS_BUS_DEVICE(>rng200), 0, rng_200_irq);
+
+
+/* THERMAL */
+if (!sysbus_realize(SYS_BUS_DEVICE(>thermal), errp)) {
+return;
+}
+thermal_mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(>thermal), 0);
+memory_region_add_subregion( >peri_low_mr, 0x15D2000, thermal_mr);
 
 /* Extended Mass Media Controller 2 */
 object_property_set_uint(OBJECT(>emmc2), "sd-spec-version", 3,
@@ -198,6 +212,7 @@ static void bcm2838_peripherals_realize(DeviceState *dev, 
Error **errp)
  BCM2838_MPHI_SIZE);
 memory_region_add_subregion(_base->peri_mr, BCM2838_MPHI_OFFSET,
 >mphi_mr_alias);
+
 /* PCIe Root Complex */
 if (!sysbus_realize(SYS_BUS_DEVICE(>pcie_host), errp)) {
 return;
diff --git a/hw/arm/raspi4b.c b/hw/arm/raspi4b.c
index 7b5385b8dd..fda27d36cb 100644
--- a/hw/arm/raspi4b.c
+++ b/hw/arm/raspi4b.c
@@ -67,7 +67,6 @@ static void raspi4_modify_dtb(const struct arm_boot_info 
*info, void *fdt)
 
 /* Temporarily disable following devices until they are implemented*/
 const char *to_be_removed_from_dt_as_wa[] = {
-"brcm,bcm2711-thermal",
 "brcm,bcm2711-genet-v5",
 };
 
diff --git a/hw/misc/bcm2838_thermal.c b/hw/misc/bcm2838_thermal.c
new file mode 100644
index 00..2301f657d0
--- /dev/null
+++ b/hw/misc/bcm2838_thermal.c
@@ -0,0 +1,98 @@
+/*
+ * BCM2838 dummy thermal sensor
+ *
+ * Copyright (C) 2022 Maksim Kopusov 
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qapi/error.h"
+#include "hw/misc/bcm2838_thermal.h"
+#include "hw/registerfields.h"
+#include "migration/vmstate.h"
+#include "qemu/error-report.h"
+
+REG32(STAT, 0x200)
+FIELD(STAT, DATA, 0, 10)
+FIELD(STAT, VALID_1, 10, 1)
+FIELD(STAT, VALID_2, 16, 1)
+
+#define BCM2838_THERMAL_SIZE 0xf00
+
+#define THERMAL_OFFSET_C 410040
+#define THERMAL_COEFF  (-487.0f)
+#define MILLIDEGREE_COEFF 1000
+
+static uint16_t bcm2838_thermal_temp2adc(int temp_C)
+{
+return (temp_C * MILLIDEGREE_COEFF - THERMAL_OFFSET_C) / THERMAL_COEFF;
+}
+
+static uint64_t bcm2838_thermal_read(void *opaque, hwaddr addr, unsigned size)
+{
+uint32_t val = 0;
+
+switch (addr) {
+case A_STAT:
+/* Temperature is always 25°C */
+val = FIELD_DP32(val, STAT, DATA, bcm2838_thermal_temp2adc(25));
+val = FIELD_DP32(val, STAT, VALID_1, 1);
+val = FIELD_DP32(val, STAT, VALID_2, 1);
+
+break;
+default:
+qemu_log_mask(LOG_GUEST_ERROR, "%s can't access addr: 0x%"PRIx64,
+ TYPE_BCM2838_THERMAL, addr);
+}
+return val;
+}
+
+static void bcm2838_thermal_write(void *opaque, hwaddr addr,
+  uint64_t 

[PATCH v4 18/45] Add RNG200 RNG and RBG

2023-12-07 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/misc/bcm2838_rng200.c | 292 +--
 include/hw/misc/bcm2838_rng200.h |  10 +-
 2 files changed, 275 insertions(+), 27 deletions(-)

diff --git a/hw/misc/bcm2838_rng200.c b/hw/misc/bcm2838_rng200.c
index 8f64e6a20f..f91ea0754c 100644
--- a/hw/misc/bcm2838_rng200.c
+++ b/hw/misc/bcm2838_rng200.c
@@ -8,25 +8,56 @@
  */
 
 #include "qemu/osdep.h"
+#include "qemu/log.h"
 #include "qapi/error.h"
 #include "hw/qdev-properties.h"
 #include "hw/misc/bcm2838_rng200.h"
+#include "hw/registerfields.h"
 #include "migration/vmstate.h"
 #include "trace.h"
 
-static const VMStateDescription vmstate_bcm2838_rng200_regs = {
-.name = "bcm2838_rng200_regs",
-.version_id = 1,
-.minimum_version_id = 1,
-.fields = (VMStateField[]) {
-VMSTATE_UINT32(ctrl, BCM2838_rng_regs_t),
-VMSTATE_UINT32(int_status, BCM2838_rng_regs_t),
-VMSTATE_UINT32(fifo_count, BCM2838_rng_regs_t),
-VMSTATE_UINT32(fifo_count_threshold, BCM2838_rng_regs_t),
-VMSTATE_UINT32(total_bit_count_threshold, BCM2838_rng_regs_t),
-VMSTATE_END_OF_LIST()
-}
-};
+/* RNG200 registers */
+REG32(RNG_CTRL,   0x00)
+FIELD(RNG_CTRL, RBG_ENABLE,   0 , 1)
+FIELD(RNG_CTRL, RSVD, 1 , 12)
+FIELD(RNG_CTRL, DIV, 13 , 8)
+
+REG32(RNG_SOFT_RESET,0x04)
+REG32(RBG_SOFT_RESET,0x08)
+REG32(RNG_TOTAL_BIT_COUNT,   0x0C)
+REG32(RNG_TOTAL_BIT_COUNT_THRESHOLD, 0x10)
+
+REG32(RNG_INT_STATUS,   0x18)
+FIELD(RNG_INT_STATUS, TOTAL_BITS_COUNT_IRQ, 0, 1)
+FIELD(RNG_INT_STATUS, RSVD0,1, 4)
+FIELD(RNG_INT_STATUS, NIST_FAIL_IRQ,5, 1)
+FIELD(RNG_INT_STATUS, RSVD1,6, 11)
+FIELD(RNG_INT_STATUS, STARTUP_TRANSITIONS_MET_IRQ,  17, 1)
+FIELD(RNG_INT_STATUS, RSVD2,18, 13)
+FIELD(RNG_INT_STATUS, MASTER_FAIL_LOCKOUT_IRQ,  30, 1)
+
+REG32(RNG_INT_ENABLE,   0x1C)
+FIELD(RNG_INT_ENABLE, TOTAL_BITS_COUNT_IRQ, 0, 1)
+FIELD(RNG_INT_ENABLE, RSVD0,1, 4)
+FIELD(RNG_INT_ENABLE, NIST_FAIL_IRQ,5, 1)
+FIELD(RNG_INT_ENABLE, RSVD1,6, 11)
+FIELD(RNG_INT_ENABLE, STARTUP_TRANSITIONS_MET_IRQ,  17, 1)
+FIELD(RNG_INT_ENABLE, RSVD2,18, 13)
+FIELD(RNG_INT_ENABLE, MASTER_FAIL_LOCKOUT_IRQ,  30, 1)
+
+REG32(RNG_FIFO_DATA, 0x20)
+
+REG32(RNG_FIFO_COUNT,  0x24)
+FIELD(RNG_FIFO_COUNT, COUNT,   0, 8)
+FIELD(RNG_FIFO_COUNT, THRESHOLD,   8, 8)
+
+
+#define RNG_WARM_UP_PERIOD_ELAPSED   17
+
+#define SOFT_RESET1
+#define IRQ_PENDING   1
+
+#define BCM2838_RNG200_PTIMER_POLICY (PTIMER_POLICY_CONTINUOUS_TRIGGER)
 
 static const VMStateDescription vmstate_bcm2838_rng200 = {
 .name = "bcm2838_rng200",
@@ -37,33 +68,253 @@ static const VMStateDescription vmstate_bcm2838_rng200 = {
 VMSTATE_UINT32(rng_fifo_cap, BCM2838Rng200State),
 VMSTATE_BOOL(use_timer, BCM2838Rng200State),
 
-VMSTATE_STRUCT(regs, BCM2838Rng200State, 0, 
vmstate_bcm2838_rng200_regs,
-   BCM2838_rng_regs_t),
+VMSTATE_ARRAY(regs, BCM2838Rng200State, N_BCM2838_RNG200_REGS, 0,
+  vmstate_info_uint32, uint32_t),
 
 VMSTATE_END_OF_LIST()
 }
 };
 
-static void bcm2838_rng200_rng_reset(BCM2838Rng200State *state)
+static bool is_rbg_enabled(BCM2838Rng200State *s)
+{
+return FIELD_EX32(s->regs[R_RNG_CTRL], RNG_CTRL, RBG_ENABLE);
+}
+
+static void increment_bit_counter_by(BCM2838Rng200State *s, uint32_t inc_val) {
+s->regs[R_RNG_TOTAL_BIT_COUNT] += inc_val;
+}
+
+static void bcm2838_rng200_update_irq(BCM2838Rng200State *s)
+{ 
+qemu_set_irq(s->irq,
+!!(s->regs[R_RNG_INT_ENABLE] & s->regs[R_RNG_INT_STATUS]));
+}
+
+static void bcm2838_rng200_update_fifo(void *opaque, const void *buf,
+   size_t size)
 {
-state->regs.ctrl = 0;
+BCM2838Rng200State *s = (BCM2838Rng200State *)opaque;
+Fifo8 *fifo = >fifo;
+size_t num = MIN(size, fifo8_num_free(fifo));
+uint32_t num_bits = num * 8;
+uint32_t bit_threshold_left = 0;
+uint32_t bit_count = 0;
+uint32_t bit_count_thld = 0;
+uint32_t fifo_thld = 0;
+
+increment_bit_counter_by(s, num_bits);
+
+bit_count = s->regs[R_RNG_TOTAL_BIT_COUNT];
+bit_count_thld = s->regs[R_RNG_TOTAL_BIT_COUNT_THRESHOLD];
+
+bit_threshold_left = (bit_count < bit_count_thld)
+   ? bit_count_thld - bit_count
+   : 0;
+
+if (bit_threshold_left < num_bits) {
+num_bits -= bit_threshold_left;
+} else {
+num_bits = 0;
+}
+
+num = num_bits / 8;
+if ((num == 0) && (num_bits > 0)) {
+num = 1;
+}
+if (num > 0) {
+

[PATCH v4 01/45] Split out common part of BCM283X classes

2023-12-07 Thread Sergey Kambalin
Pre setup for BCM2838 introduction

Signed-off-by: Sergey Kambalin 
---
 hw/arm/bcm2836.c | 102 ++-
 hw/arm/raspi.c   |   2 +-
 include/hw/arm/bcm2836.h |  26 +-
 3 files changed, 83 insertions(+), 47 deletions(-)

diff --git a/hw/arm/bcm2836.c b/hw/arm/bcm2836.c
index 166dc896c0..66a2b57b38 100644
--- a/hw/arm/bcm2836.c
+++ b/hw/arm/bcm2836.c
@@ -29,12 +29,12 @@ struct BCM283XClass {
 };
 
 static Property bcm2836_enabled_cores_property =
-DEFINE_PROP_UINT32("enabled-cpus", BCM283XState, enabled_cpus, 0);
+DEFINE_PROP_UINT32("enabled-cpus", BCM283XBaseState, enabled_cpus, 0);
 
-static void bcm2836_init(Object *obj)
+static void bcm283x_base_init(Object *obj)
 {
-BCM283XState *s = BCM283X(obj);
-BCM283XClass *bc = BCM283X_GET_CLASS(obj);
+BCM283XBaseState *s = BCM283X_BASE(obj);
+BCM283XBaseClass *bc = BCM283X_BASE_GET_CLASS(obj);
 int n;
 
 for (n = 0; n < bc->core_count; n++) {
@@ -50,6 +50,11 @@ static void bcm2836_init(Object *obj)
 object_initialize_child(obj, "control", >control,
 TYPE_BCM2836_CONTROL);
 }
+}
+
+static void bcm283x_init(Object *obj)
+{
+BCM283XState *s = BCM283X(obj);
 
 object_initialize_child(obj, "peripherals", >peripherals,
 TYPE_BCM2835_PERIPHERALS);
@@ -61,10 +66,11 @@ static void bcm2836_init(Object *obj)
   "vcram-size");
 }
 
-static bool bcm283x_common_realize(DeviceState *dev, Error **errp)
+bool bcm283x_common_realize(DeviceState *dev, Error **errp)
 {
 BCM283XState *s = BCM283X(dev);
-BCM283XClass *bc = BCM283X_GET_CLASS(dev);
+BCM283XBaseState *s_base = BCM283X_BASE(dev);
+BCM283XBaseClass *bc = BCM283X_BASE_GET_CLASS(dev);
 Object *obj;
 
 /* common peripherals from bcm2835 */
@@ -77,96 +83,98 @@ static bool bcm283x_common_realize(DeviceState *dev, Error 
**errp)
 return false;
 }
 
-object_property_add_alias(OBJECT(s), "sd-bus", OBJECT(>peripherals),
-  "sd-bus");
+object_property_add_alias(OBJECT(s_base), "sd-bus",
+  OBJECT(>peripherals), "sd-bus");
 
-sysbus_mmio_map_overlap(SYS_BUS_DEVICE(>peripherals), 0,
-bc->peri_base, 1);
+sysbus_mmio_map_overlap(SYS_BUS_DEVICE(>peripherals),
+0, bc->peri_base, 1);
 return true;
 }
 
 static void bcm2835_realize(DeviceState *dev, Error **errp)
 {
 BCM283XState *s = BCM283X(dev);
+BCM283XBaseState *s_base = BCM283X_BASE(dev);
 
 if (!bcm283x_common_realize(dev, errp)) {
 return;
 }
 
-if (!qdev_realize(DEVICE(>cpu[0].core), NULL, errp)) {
+if (!qdev_realize(DEVICE(_base->cpu[0].core), NULL, errp)) {
 return;
 }
 
 /* Connect irq/fiq outputs from the interrupt controller. */
 sysbus_connect_irq(SYS_BUS_DEVICE(>peripherals), 0,
-qdev_get_gpio_in(DEVICE(>cpu[0].core), ARM_CPU_IRQ));
+qdev_get_gpio_in(DEVICE(_base->cpu[0].core), ARM_CPU_IRQ));
 sysbus_connect_irq(SYS_BUS_DEVICE(>peripherals), 1,
-qdev_get_gpio_in(DEVICE(>cpu[0].core), ARM_CPU_FIQ));
+qdev_get_gpio_in(DEVICE(_base->cpu[0].core), ARM_CPU_FIQ));
 }
 
 static void bcm2836_realize(DeviceState *dev, Error **errp)
 {
-BCM283XState *s = BCM283X(dev);
-BCM283XClass *bc = BCM283X_GET_CLASS(dev);
 int n;
+BCM283XState *s = BCM283X(dev);
+BCM283XBaseState *s_base = BCM283X_BASE(dev);
+BCM283XBaseClass *bc = BCM283X_BASE_GET_CLASS(dev);
 
 if (!bcm283x_common_realize(dev, errp)) {
 return;
 }
 
 /* bcm2836 interrupt controller (and mailboxes, etc.) */
-if (!sysbus_realize(SYS_BUS_DEVICE(>control), errp)) {
+if (!sysbus_realize(SYS_BUS_DEVICE(_base->control), errp)) {
 return;
 }
 
-sysbus_mmio_map(SYS_BUS_DEVICE(>control), 0, bc->ctrl_base);
+sysbus_mmio_map(SYS_BUS_DEVICE(_base->control), 0, bc->ctrl_base);
 
 sysbus_connect_irq(SYS_BUS_DEVICE(>peripherals), 0,
-qdev_get_gpio_in_named(DEVICE(>control), "gpu-irq", 0));
+qdev_get_gpio_in_named(DEVICE(_base->control), "gpu-irq", 0));
 sysbus_connect_irq(SYS_BUS_DEVICE(>peripherals), 1,
-qdev_get_gpio_in_named(DEVICE(>control), "gpu-fiq", 0));
+qdev_get_gpio_in_named(DEVICE(_base->control), "gpu-fiq", 0));
 
 for (n = 0; n < BCM283X_NCPUS; n++) {
 /* TODO: this should be converted to a property of ARM_CPU */
-s->cpu[n].core.mp_affinity = (bc->clusterid << 8) | n;
+s_base->cpu[n].core.mp_affinity = (bc->clusterid << 8) | n;
 
 /* set periphbase/CBAR value for CPU-local registers */
-if (!object_property_set_int(OBJECT(>cpu[n].core), "reset-cbar",
+if (!object_property_set_int(OBJECT(_base->cpu[n].core), 
"reset-cbar",
  bc->peri_base, errp)) {
 return;
   

[PATCH v4 03/45] Split out raspi machine common part

2023-12-07 Thread Sergey Kambalin
Pre-setup for raspberry pi 4 introduction

Signed-off-by: Sergey Kambalin 
---
 hw/arm/raspi.c  | 112 ++--
 include/hw/arm/raspi_platform.h |  21 ++
 2 files changed, 85 insertions(+), 48 deletions(-)

diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
index af866ebce2..7d04734cd2 100644
--- a/hw/arm/raspi.c
+++ b/hw/arm/raspi.c
@@ -18,6 +18,7 @@
 #include "qapi/error.h"
 #include "hw/arm/boot.h"
 #include "hw/arm/bcm2836.h"
+#include "hw/arm/raspi_platform.h"
 #include "hw/registerfields.h"
 #include "qemu/error-report.h"
 #include "hw/boards.h"
@@ -25,6 +26,9 @@
 #include "hw/arm/boot.h"
 #include "qom/object.h"
 
+#define TYPE_RASPI_MACHINE  MACHINE_TYPE_NAME("raspi-common")
+OBJECT_DECLARE_SIMPLE_TYPE(RaspiMachineState, RASPI_MACHINE)
+
 #define SMPBOOT_ADDR0x300 /* this should leave enough space for ATAGS */
 #define MVBAR_ADDR  0x400 /* secure vectors */
 #define BOARDSETUP_ADDR (MVBAR_ADDR + 0x20) /* board setup code */
@@ -37,25 +41,10 @@
 
 struct RaspiMachineState {
 /*< private >*/
-MachineState parent_obj;
+RaspiBaseMachineState parent_obj;
 /*< public >*/
 BCM283XState soc;
-struct arm_boot_info binfo;
-};
-typedef struct RaspiMachineState RaspiMachineState;
-
-struct RaspiMachineClass {
-/*< private >*/
-MachineClass parent_obj;
-/*< public >*/
-uint32_t board_rev;
 };
-typedef struct RaspiMachineClass RaspiMachineClass;
-
-#define TYPE_RASPI_MACHINE   MACHINE_TYPE_NAME("raspi-common")
-DECLARE_OBJ_CHECKERS(RaspiMachineState, RaspiMachineClass,
- RASPI_MACHINE, TYPE_RASPI_MACHINE)
-
 
 /*
  * Board revision codes:
@@ -83,6 +72,11 @@ static const struct {
 [PROCESSOR_ID_BCM2837] = {TYPE_BCM2837, BCM283X_NCPUS},
 };
 
+static void raspi_base_machine_init(MachineState *machine,
+ BCM283XBaseState *soc);
+static void raspi_machine_class_common_init(MachineClass *mc,
+ uint32_t board_rev);
+
 static uint64_t board_ram_size(uint32_t board_rev)
 {
 assert(FIELD_EX32(board_rev, REV_CODE, STYLE)); /* Only new style */
@@ -200,13 +194,12 @@ static void reset_secondary(ARMCPU *cpu, const struct 
arm_boot_info *info)
 cpu_set_pc(cs, info->smp_loader_start);
 }
 
-static void setup_boot(MachineState *machine, RaspiProcessorId processor_id,
-   size_t ram_size)
+static void setup_boot(MachineState *machine, ARMCPU *cpu,
+   RaspiProcessorId processor_id, size_t ram_size)
 {
-RaspiMachineState *s = RASPI_MACHINE(machine);
+RaspiBaseMachineState *s = RASPI_BASE_MACHINE(machine);
 int r;
 
-s->binfo.board_id = MACH_TYPE_BCM2708;
 s->binfo.ram_size = ram_size;
 
 if (processor_id <= PROCESSOR_ID_BCM2836) {
@@ -252,13 +245,13 @@ static void setup_boot(MachineState *machine, 
RaspiProcessorId processor_id,
 s->binfo.firmware_loaded = true;
 }
 
-arm_load_kernel(>soc.parent_obj.cpu[0].core, machine, >binfo);
+arm_load_kernel(cpu, machine, >binfo);
 }
 
-static void raspi_machine_init(MachineState *machine)
+static void raspi_base_machine_init(MachineState *machine,
+ BCM283XBaseState *soc)
 {
-RaspiMachineClass *mc = RASPI_MACHINE_GET_CLASS(machine);
-RaspiMachineState *s = RASPI_MACHINE(machine);
+RaspiBaseMachineClass *mc = RASPI_BASE_MACHINE_GET_CLASS(machine);
 uint32_t board_rev = mc->board_rev;
 uint64_t ram_size = board_ram_size(board_rev);
 uint32_t vcram_size;
@@ -279,19 +272,17 @@ static void raspi_machine_init(MachineState *machine)
 machine->ram, 0);
 
 /* Setup the SOC */
-object_initialize_child(OBJECT(machine), "soc", >soc,
-board_soc_type(board_rev));
-object_property_add_const_link(OBJECT(>soc), "ram", 
OBJECT(machine->ram));
-object_property_set_int(OBJECT(>soc), "board-rev", board_rev,
+object_property_add_const_link(OBJECT(soc), "ram", OBJECT(machine->ram));
+object_property_set_int(OBJECT(soc), "board-rev", board_rev,
 _abort);
-object_property_set_str(OBJECT(>soc), "command-line",
+object_property_set_str(OBJECT(soc), "command-line",
 machine->kernel_cmdline, _abort);
-qdev_realize(DEVICE(>soc), NULL, _fatal);
+qdev_realize(DEVICE(soc), NULL, _fatal);
 
 /* Create and plug in the SD cards */
 di = drive_get(IF_SD, 0, 0);
 blk = di ? blk_by_legacy_dinfo(di) : NULL;
-bus = qdev_get_child_bus(DEVICE(>soc), "sd-bus");
+bus = qdev_get_child_bus(DEVICE(soc), "sd-bus");
 if (bus == NULL) {
 error_report("No SD bus found in SOC object");
 exit(1);
@@ -300,19 +291,32 @@ static void raspi_machine_init(MachineState *machine)
 qdev_prop_set_drive_err(carddev, "drive", blk, _fatal);
 qdev_realize_and_unref(carddev, bus, _fatal);
 
-vcram_size = 

[PATCH v4 29/45] Implement GENET MDIO

2023-12-07 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/net/bcm2838_genet.c | 126 -
 include/hw/net/bcm2838_genet.h |   3 +-
 2 files changed, 126 insertions(+), 3 deletions(-)

diff --git a/hw/net/bcm2838_genet.c b/hw/net/bcm2838_genet.c
index 56ff6a6f39..1fae3ecbc2 100644
--- a/hw/net/bcm2838_genet.c
+++ b/hw/net/bcm2838_genet.c
@@ -213,6 +213,7 @@ FIELD(GENET_PHY_STAT_1000, LOCALRXOK, 13, 1)
 FIELD(GENET_PHY_STAT_1000, MSRES, 14, 1)
 FIELD(GENET_PHY_STAT_1000, MSFAIL,15, 1)
 
+/* There are two data representations for PHY_AUX_CTRL register */
 REG16(GENET_PHY_AUX_CTRL_0,  0)
 FIELD(GENET_PHY_AUX_CTRL_0, REG_ID_MASK, 0, 3)
 FIELD(GENET_PHY_AUX_CTRL_0, RSVD_3,  3, 1)
@@ -269,6 +270,123 @@ static void bcm2838_genet_set_irq_prio(BCM2838GenetState 
*s)
 qemu_set_irq(s->irq_prio, level);
 }
 
+static void bcm2838_genet_phy_aux_ctl_write(BCM2838GenetState *s,
+uint16_t value)
+{
+uint16_t reg_id = FIELD_EX16(value, GENET_PHY_AUX_CTRL_0, REG_ID);
+uint16_t reg_id_mask = FIELD_EX16(value, GENET_PHY_AUX_CTRL_0, 
REG_ID_MASK);
+uint16_t misc_wren = FIELD_EX16(value, GENET_PHY_AUX_CTRL_0, MISC_WREN);
+uint16_t reg_data = FIELD_EX16(value, GENET_PHY_AUX_CTRL_0, REG_DATA);
+uint16_t reg_data12 = FIELD_EX16(value, GENET_PHY_AUX_CTRL_1, REG_DATA);
+
+uint16_t *phy_aux_ctl_shd_reg_id = (uint16_t *)>phy_aux_ctl_shd_regs + 
reg_id;
+uint16_t *phy_aux_ctl_shd_reg_id_mask = (uint16_t 
*)>phy_aux_ctl_shd_regs + reg_id_mask;
+
+if (reg_id_mask == BCM2838_GENET_PHY_AUX_CTL_MISC) {
+if (reg_id == BCM2838_GENET_PHY_AUX_CTL_MISC) {
+if (misc_wren == 0) {
+/* write for subsequent read (8-bit from AUX_CTL_MISC) */
+FIELD_DP16(value, GENET_PHY_AUX_CTRL_0, REG_DATA, 
*phy_aux_ctl_shd_reg_id);
+} else {
+/* write 8 bits to AUX_CTL_MISC */
+*phy_aux_ctl_shd_reg_id_mask = reg_data;
+}
+} else {
+/* write for subsequent read (12-bit) */
+FIELD_DP16(value, GENET_PHY_AUX_CTRL_1, REG_DATA, 
*phy_aux_ctl_shd_reg_id);
+}
+} else {
+/* write 12 bits */
+*phy_aux_ctl_shd_reg_id_mask = reg_data12;
+}
+
+s->phy_regs.aux_ctl = value;
+}
+
+static void bcm2838_genet_phy_shadow_write(BCM2838GenetState *s,
+   uint16_t value)
+{
+uint16_t reg_id = FIELD_EX16(value, GENET_PHY_SHADOW, REG_ID);
+uint16_t wr = FIELD_EX16(value, GENET_PHY_SHADOW, WR);
+uint16_t reg_data = FIELD_EX16(value, GENET_PHY_SHADOW, REG_DATA);
+
+uint16_t *phy_shd_reg = (uint16_t *)>phy_shd_regs + reg_id;
+
+if (wr == 0) {
+FIELD_DP16(value, GENET_PHY_SHADOW, REG_DATA, *phy_shd_reg);
+} else {
+*phy_shd_reg = reg_data;
+}
+
+s->phy_regs.shd = value;
+}
+
+static void bcm2838_genet_phy_exp_shadow_write(BCM2838GenetState *s,
+   uint16_t value)
+{
+/* TODO Stub implementation without side effect,
+just storing registers values */
+uint16_t reg_id = FIELD_EX16(s->phy_regs.exp_ctrl,
+ GENET_PHY_EXP_SEL, REG_ID);
+uint16_t block_id = FIELD_EX16(s->phy_regs.exp_ctrl,
+   GENET_PHY_EXP_SEL, BLOCK_ID);
+
+s->phy_exp_shd_regs.regs[block_id][reg_id] = value;
+}
+
+static uint16_t bcm2838_genet_phy_exp_shadow_read(BCM2838GenetState *s)
+{
+uint16_t reg_id = FIELD_EX16(s->phy_regs.exp_ctrl,
+ GENET_PHY_EXP_SEL, REG_ID);
+uint16_t block_id = FIELD_EX16(s->phy_regs.exp_ctrl,
+   GENET_PHY_EXP_SEL, BLOCK_ID);
+
+return s->phy_exp_shd_regs.regs[block_id][reg_id];
+}
+
+static uint64_t bcm2838_genet_mdio_cmd(BCM2838GenetState *s, uint64_t cmd)
+{
+uint32_t phy_reg_id = FIELD_EX32(cmd, GENET_UMAC_MDIO_CMD, REG_ID);
+uint32_t phy_reg_data = FIELD_EX32(cmd, GENET_UMAC_MDIO_CMD, REG_DATA);
+uint32_t start_busy = FIELD_EX32(cmd, GENET_UMAC_MDIO_CMD, START_BUSY);
+uint32_t rd = FIELD_EX32(cmd, GENET_UMAC_MDIO_CMD, RD);
+uint32_t wr = FIELD_EX32(cmd, GENET_UMAC_MDIO_CMD, WR);
+uint16_t *phy_reg = (uint16_t *)>phy_regs + phy_reg_id;
+
+uint16_t anrestart = FIELD_EX16(phy_reg_data, GENET_PHY_BMCR, ANRESTART);
+
+if (start_busy != 0) {
+cmd = FIELD_DP32(cmd, GENET_UMAC_MDIO_CMD, START_BUSY, 0);
+
+if (rd != 0) {
+if (phy_reg_id == BCM2838_GENET_EXP_DATA) {
+cmd = FIELD_DP32(cmd, GENET_UMAC_MDIO_CMD, REG_DATA,
+ bcm2838_genet_phy_exp_shadow_read(s));
+} else {
+cmd = FIELD_DP32(cmd, GENET_UMAC_MDIO_CMD, REG_DATA, *phy_reg);
+}
+} else if (wr != 0) {
+if (phy_reg_id == BCM2838_GENET_PHY_AUX_CTL) {
+bcm2838_genet_phy_aux_ctl_write(s, 

[PATCH v4 31/45] Implement GENET RX path

2023-12-07 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/net/bcm2838_genet.c | 265 -
 include/hw/net/bcm2838_genet.h |   1 +
 2 files changed, 265 insertions(+), 1 deletion(-)

diff --git a/hw/net/bcm2838_genet.c b/hw/net/bcm2838_genet.c
index 4c9b39a3ca..61c1981e10 100644
--- a/hw/net/bcm2838_genet.c
+++ b/hw/net/bcm2838_genet.c
@@ -511,6 +511,25 @@ static bool 
bcm2838_genet_tdma_ring_active(BCM2838GenetState *s,
 return active;
 }
 
+static bool bcm2838_genet_rdma_ring_active(BCM2838GenetState *s,
+   unsigned int ring_index)
+{
+uint32_t ring_mask = 1 << ring_index;
+
+bool dma_en = FIELD_EX32(s->regs.rdma.ctrl, GENET_DMA_CTRL, EN) != 0;
+bool ring_en = (FIELD_EX32(s->regs.rdma.ring_cfg, GENET_DMA_RING_CFG, EN)
+& ring_mask) != 0;
+bool ring_buf_en = (FIELD_EX32(s->regs.rdma.ctrl,
+   GENET_DMA_CTRL, RING_BUF_EN)
+& ring_mask) != 0;
+bool active = dma_en && ring_en && ring_buf_en;
+
+trace_bcm2838_genet_rx_dma_ring_active(ring_index,
+   active ? "active" : "halted");
+
+return active;
+}
+
 static void bcm2838_genet_tdma(BCM2838GenetState *s, hwaddr offset,
uint64_t value)
 {
@@ -721,9 +740,251 @@ static const MemoryRegionOps bcm2838_genet_ops = {
 .valid = {.min_access_size = 4},
 };
 
+static int32_t bcm2838_genet_filter(BCM2838GenetState *s, const void *buf,
+size_t size)
+{
+qemu_log_mask(LOG_UNIMP,
+  "Packet filtration with HFB isn't implemented yet");
+return -1;
+}
+
+static int32_t bcm2838_genet_filter2ring(BCM2838GenetState *s,
+ uint32_t filter_idx)
+{
+qemu_log_mask(LOG_UNIMP,
+  "Packet filtration with HFB isn't implemented yet");
+return -1;
+}
+
+static bool is_packet_broadcast(const uint8_t *buf, size_t size)
+{
+static const uint8_t bcst_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+
+if (size < sizeof(bcst_addr)) {
+return false;
+}
+
+return !memcmp(buf, bcst_addr, sizeof(bcst_addr));
+}
+
+static bool is_packet_multicast(const uint8_t *buf, size_t size)
+{
+return !!(buf[0] & 0x01);
+}
+
+static ssize_t bcm2838_genet_rdma(BCM2838GenetState *s, uint32_t ring_idx,
+  const void *buf, size_t size)
+{
+const size_t DESC_WORD_SIZE =
+sizeof(BCM2838GenetRdmaDesc) / sizeof(uint32_t);
+
+ssize_t len = 0;
+BCM2838GenetRegsRdma *rdma = >regs.rdma;
+BCM2838GenetRdmaRing *ring = >rings[ring_idx];
+hwaddr write_index =
+(ring->write_ptr + ((hwaddr)ring->write_ptr_hi << 32)) / 
DESC_WORD_SIZE;
+BCM2838GenetRdmaDesc *desc = >descs[write_index];
+
+const hwaddr START_INDEX =
+(ring->start_addr + ((hwaddr)ring->start_addr_hi << 32))
+/ DESC_WORD_SIZE;
+const hwaddr END_INDEX =
+(ring->end_addr + ((hwaddr)ring->end_addr_hi << 32)) / DESC_WORD_SIZE;
+
+if (!bcm2838_genet_rdma_ring_active(s, ring_idx)) {
+return -1;
+}
+
+desc->length_status = FIELD_DP32(desc->length_status,
+ GENET_RDMA_LENGTH_STATUS, SOP, 1);
+
+while (len < size) {
+size_t l = size - len;
+size_t buf_size = ring->ring_buf_size & 0x;
+uint8_t *dma_buf = s->rx_packet;
+hwaddr dma_buf_addr =
+desc->address_lo + ((hwaddr)desc->address_hi << 32);
+MemTxResult mem_tx_result = MEMTX_OK;
+uint8_t *frame_buf = dma_buf + sizeof(BCM2838GenetXmitStatus) + 2;
+BCM2838GenetXmitStatus *xmit_status = (BCM2838GenetXmitStatus 
*)dma_buf;
+struct iovec iov;
+bool isip4, isip6;
+size_t l3hdr_off, l4hdr_off, l5hdr_off;
+eth_ip6_hdr_info ip6hdr_info;
+eth_ip4_hdr_info ip4hdr_info;
+eth_l4_hdr_info  l4hdr_info;
+
+bool crc_fwd = FIELD_EX32(s->regs.umac.cmd, GENET_UMAC_CMD, CRC_FWD);
+size_t buflength;
+uint32_t prod_index;
+
+if (l > ring->ring_buf_size) {
+l = ring->ring_buf_size;
+}
+
+memcpy(frame_buf, buf + len, l);
+iov.iov_base = frame_buf;
+iov.iov_len = l;
+eth_get_protocols(, 1, 0,
+  , ,
+  _off, _off, _off,
+  _info, _info, _info);
+
+len += l;
+
+desc->length_status = FIELD_DP32(desc->length_status,
+ GENET_RDMA_LENGTH_STATUS,
+ EOP, !!(len >= size));
+
+buflength = l + sizeof(BCM2838GenetXmitStatus) + 2;
+if (crc_fwd) {
+buflength += 4;
+}
+
+desc->length_status = FIELD_DP32(desc->length_status,
+ GENET_RDMA_LENGTH_STATUS,
+

[PATCH v4 35/45] Add mailbox test stub

2023-12-07 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 include/hw/arm/bcm2838_peripherals.h |  2 +
 tests/qtest/bcm2838-mailbox.c| 71 
 tests/qtest/bcm2838-mailbox.h| 46 ++
 tests/qtest/meson.build  |  1 +
 4 files changed, 120 insertions(+)
 create mode 100644 tests/qtest/bcm2838-mailbox.c
 create mode 100644 tests/qtest/bcm2838-mailbox.h

diff --git a/include/hw/arm/bcm2838_peripherals.h 
b/include/hw/arm/bcm2838_peripherals.h
index cdeb892f04..2b97e55048 100644
--- a/include/hw/arm/bcm2838_peripherals.h
+++ b/include/hw/arm/bcm2838_peripherals.h
@@ -56,6 +56,8 @@
 #define BCM2838_MPHI_OFFSET 0xb200
 #define BCM2838_MPHI_SIZE   0x200
 
+#define GENET_OFFSET0x158
+
 #define TYPE_BCM2838_PERIPHERALS "bcm2838-peripherals"
 OBJECT_DECLARE_TYPE(BCM2838PeripheralState, BCM2838PeripheralClass,
 BCM2838_PERIPHERALS)
diff --git a/tests/qtest/bcm2838-mailbox.c b/tests/qtest/bcm2838-mailbox.c
new file mode 100644
index 00..2edc24e15e
--- /dev/null
+++ b/tests/qtest/bcm2838-mailbox.c
@@ -0,0 +1,71 @@
+/*
+ * Helper functions to work with BCM2838 mailbox via qtest interface.
+ *
+ * Copyright (c) 2023 Auriga LLC
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/registerfields.h"
+#include "libqtest-single.h"
+#include "bcm2838-mailbox.h"
+
+
+static uint32_t qtest_mbox0_read_reg32(QTestState *s, uint32_t offset)
+{
+return qtest_readl(s, MBOX0_BASE + offset);
+}
+
+static void qtest_mbox1_write_reg32(QTestState *s, uint32_t offset, uint32_t 
value)
+{
+return qtest_writel(s, MBOX1_BASE + offset, value);
+}
+
+static void qtest_mbox1_write(QTestState *s, uint8_t channel, uint32_t data)
+{
+uint32_t reg;
+
+reg = FIELD_DP32(reg, MBOX_WRITE_REG, CHANNEL, channel);
+reg = FIELD_DP32(reg, MBOX_WRITE_REG, DATA, data);
+qtest_mbox1_write_reg32(s, MBOX_REG_WRITE, reg);
+}
+
+int qtest_mbox0_has_data(QTestState *s) {
+return !(qtest_mbox0_read_reg32(s, MBOX_REG_STATUS) & MBOX_READ_EMPTY);
+}
+
+int mbox0_has_data(void) {
+return qtest_mbox0_has_data(global_qtest);
+}
+
+void qtest_mbox0_read_message(QTestState *s,
+  uint8_t channel,
+  void *msgbuf,
+  size_t msgbuf_size)
+{
+uint32_t reg;
+uint32_t msgaddr;
+
+g_assert(qtest_mbox0_has_data(s));
+reg = qtest_mbox0_read_reg32(s, MBOX_REG_READ);
+g_assert_cmphex(FIELD_EX32(reg, MBOX_WRITE_REG, CHANNEL), ==, channel);
+msgaddr = FIELD_EX32(reg, MBOX_WRITE_REG, DATA) << 4;
+qtest_memread(s, msgaddr, msgbuf, msgbuf_size);
+}
+
+void mbox0_read_message(uint8_t channel, void *msgbuf, size_t msgbuf_size) {
+qtest_mbox0_read_message(global_qtest, channel, msgbuf, msgbuf_size);
+}
+
+void qtest_mbox1_write_message(QTestState *s, uint8_t channel, uint32_t 
msg_addr)
+{
+qtest_mbox1_write(s, channel, msg_addr >> 4);
+}
+
+
+void mbox1_write_message(uint8_t channel, uint32_t msg_addr)
+{
+qtest_mbox1_write_message(global_qtest, channel, msg_addr);
+}
diff --git a/tests/qtest/bcm2838-mailbox.h b/tests/qtest/bcm2838-mailbox.h
new file mode 100644
index 00..1d02ca9c2c
--- /dev/null
+++ b/tests/qtest/bcm2838-mailbox.h
@@ -0,0 +1,46 @@
+/*
+ * Declarations for BCM2838 mailbox test.
+ *
+ * Copyright (c) 2023 Auriga LLC
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+
+REG32(MBOX_WRITE_REG, 0)
+FIELD(MBOX_WRITE_REG, CHANNEL, 0, 4)
+FIELD(MBOX_WRITE_REG, DATA, 4, 28)
+
+REG32(MBOX_SIZE_STAT, 0)
+FIELD(MBOX_WRITE_REG, SIZE, 0, 30)
+FIELD(MBOX_WRITE_REG, SUCCESS, 30, 1)
+
+typedef struct {
+uint32_t size;
+uint32_t req_resp_code;
+} MboxBufHeader;
+
+#define DECLARE_TAG_TYPE(TypeName, RequestValueType, ResponseValueType) \
+typedef struct {\
+uint32_t id;\
+uint32_t value_buffer_size; \
+union { \
+struct {\
+uint32_t zero;  \
+RequestValueType value; \
+} request;  \
+struct {\
+uint32_t size_stat; \
+ResponseValueType value;\
+} response; \
+};  \
+} TypeName
+
+
+int 

[PATCH v4 09/45] Add GPIO and SD to BCM2838 periph

2023-12-07 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/arm/bcm2838_peripherals.c | 140 +++
 include/hw/arm/bcm2838_peripherals.h |   9 ++
 2 files changed, 149 insertions(+)

diff --git a/hw/arm/bcm2838_peripherals.c b/hw/arm/bcm2838_peripherals.c
index 06110c724f..c147b6e453 100644
--- a/hw/arm/bcm2838_peripherals.c
+++ b/hw/arm/bcm2838_peripherals.c
@@ -15,22 +15,53 @@
 /* Lower peripheral base address on the VC (GPU) system bus */
 #define BCM2838_VC_PERI_LOW_BASE 0x7c00
 
+/* Capabilities for SD controller: no DMA, high-speed, default clocks etc. */
+#define BCM2835_SDHC_CAPAREG 0x52134b4
+
 static void bcm2838_peripherals_init(Object *obj)
 {
 BCM2838PeripheralState *s = BCM2838_PERIPHERALS(obj);
 BCM2838PeripheralClass *bc = BCM2838_PERIPHERALS_GET_CLASS(obj);
+RaspiPeripheralBaseState *s_base = RASPI_PERIPHERALS_BASE(obj);
 
 /* Lower memory region for peripheral devices (exported to the Soc) */
 memory_region_init(>peri_low_mr, obj, "bcm2838-peripherals",
bc->peri_low_size);
 sysbus_init_mmio(SYS_BUS_DEVICE(s), >peri_low_mr);
 
+/* Extended Mass Media Controller 2 */
+object_initialize_child(obj, "emmc2", >emmc2, TYPE_SYSBUS_SDHCI);
+
+/* GPIO */
+object_initialize_child(obj, "gpio", >gpio, TYPE_BCM2838_GPIO);
+
+object_property_add_const_link(OBJECT(>gpio), "sdbus-sdhci",
+   OBJECT(_base->sdhci.sdbus));
+object_property_add_const_link(OBJECT(>gpio), "sdbus-sdhost",
+   OBJECT(_base->sdhost.sdbus));
+
+object_initialize_child(obj, "mmc_irq_orgate", >mmc_irq_orgate,
+TYPE_OR_IRQ);
+object_property_set_int(OBJECT(>mmc_irq_orgate), "num-lines", 2,
+_abort);
+
+object_initialize_child(obj, "dma_7_8_irq_orgate", >dma_7_8_irq_orgate,
+TYPE_OR_IRQ);
+object_property_set_int(OBJECT(>dma_7_8_irq_orgate), "num-lines", 2,
+_abort);
+
+object_initialize_child(obj, "dma_9_10_irq_orgate", 
>dma_9_10_irq_orgate,
+TYPE_OR_IRQ);
+object_property_set_int(OBJECT(>dma_9_10_irq_orgate), "num-lines", 2,
+_abort);
 }
 
 static void bcm2838_peripherals_realize(DeviceState *dev, Error **errp)
 {
+MemoryRegion *mphi_mr;
 BCM2838PeripheralState *s = BCM2838_PERIPHERALS(dev);
 BCMSocPeripheralBaseState *s_base = BCM_SOC_PERIPHERALS_BASE(dev);
+int n;
 
 bcm_soc_peripherals_common_realize(dev, errp);
 
@@ -42,6 +73,115 @@ static void bcm2838_peripherals_realize(DeviceState *dev, 
Error **errp)
 BCM2838_VC_PERI_LOW_BASE,
 >peri_low_mr_alias, 1);
 
+/* Extended Mass Media Controller 2 */
+object_property_set_uint(OBJECT(>emmc2), "sd-spec-version", 3,
+ _abort);
+object_property_set_uint(OBJECT(>emmc2), "capareg",
+ BCM2835_SDHC_CAPAREG, _abort);
+object_property_set_bool(OBJECT(>emmc2), "pending-insert-quirk", true,
+ _abort);
+if (!sysbus_realize(SYS_BUS_DEVICE(>emmc2), errp)) {
+return;
+}
+
+memory_region_add_subregion(
+_base->peri_mr, EMMC2_OFFSET,
+sysbus_mmio_get_region(SYS_BUS_DEVICE(>emmc2), 0));
+
+/* According to DTS, EMMC and EMMC2 share one irq */
+if (!qdev_realize(DEVICE(>mmc_irq_orgate), NULL, errp)) {
+return;
+}
+
+DeviceState *mmc_irq_orgate = DEVICE(>mmc_irq_orgate);
+sysbus_connect_irq(SYS_BUS_DEVICE(>emmc2), 0,
+qdev_get_gpio_in(mmc_irq_orgate, 0));
+
+sysbus_connect_irq(SYS_BUS_DEVICE(_base->sdhci), 0,
+qdev_get_gpio_in(mmc_irq_orgate, 1));
+
+   /* Connect EMMC and EMMC2 to the interrupt controller */
+qdev_connect_gpio_out(mmc_irq_orgate, 0,
+  qdev_get_gpio_in_named(DEVICE(_base->ic),
+ BCM2835_IC_GPU_IRQ,
+ INTERRUPT_ARASANSDIO));
+
+/* Connect DMA 0-6 to the interrupt controller */
+for (n = 0; n < 7; n++) {
+sysbus_connect_irq(SYS_BUS_DEVICE(_base->dma), n,
+   qdev_get_gpio_in_named(DEVICE(_base->ic),
+  BCM2835_IC_GPU_IRQ,
+  GPU_INTERRUPT_DMA0 + n));
+}
+
+   /* According to DTS, DMA 7 and 8 share one irq */
+if (!qdev_realize(DEVICE(>dma_7_8_irq_orgate), NULL, errp)) {
+return;
+}
+DeviceState *dma_7_8_irq_orgate = DEVICE(>dma_7_8_irq_orgate);
+
+/* Connect DMA 7-8 to the interrupt controller */
+sysbus_connect_irq(SYS_BUS_DEVICE(_base->dma), 7,
+   qdev_get_gpio_in(dma_7_8_irq_orgate, 0));
+

[PATCH v4 41/45] Add mailbox property tests. Part 2

2023-12-07 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 tests/qtest/bcm2838-mbox-property-test.c | 196 ++-
 1 file changed, 195 insertions(+), 1 deletion(-)

diff --git a/tests/qtest/bcm2838-mbox-property-test.c 
b/tests/qtest/bcm2838-mbox-property-test.c
index 80746dbb95..5322c563a0 100644
--- a/tests/qtest/bcm2838-mbox-property-test.c
+++ b/tests/qtest/bcm2838-mbox-property-test.c
@@ -49,7 +49,8 @@ FIELD(GET_CLOCK_STATE_CMD, NPRES, 1, 1)
   (TEST_TAG_TYPE(testname) * tag); 
\
 static void CHECK_FN_NAME(testname, __VA_ARGS__)   
\
  (TEST_TAG_TYPE(testname) *tag);   
\
-static void TEST_FN_NAME(testname, __VA_ARGS__)(void) {
\
+static void TEST_FN_NAME(testname, __VA_ARGS__)(void)  
\
+{  
\
 struct {   
\
 MboxBufHeader header;  
\
 TEST_TAG_TYPE(testname) tag;   
\
@@ -188,6 +189,179 @@ DECLARE_TEST_CASE_SETUP(GET_MIN_CLOCK_RATE, EMMC) {
 }
 
 
/**/
+DECLARE_TEST_CASE(GET_CLOCK_RATE, UART) {
+g_assert_cmphex(tag->response.value.clock_id, ==, CLOCK_ID_UART);
+g_assert_cmphex(tag->response.value.rate, ==, CLOCK_RATE_UART);
+}
+DECLARE_TEST_CASE_SETUP(GET_CLOCK_RATE, UART) {
+tag->request.value.clock_id = CLOCK_ID_UART;
+}
+
+/**/
+DECLARE_TEST_CASE(GET_MAX_CLOCK_RATE, UART) {
+g_assert_cmphex(tag->response.value.clock_id, ==, CLOCK_ID_UART);
+g_assert_cmphex(tag->response.value.rate, ==, CLOCK_RATE_UART);
+}
+DECLARE_TEST_CASE_SETUP(GET_MAX_CLOCK_RATE, UART) {
+tag->request.value.clock_id = CLOCK_ID_UART;
+}
+
+/**/
+DECLARE_TEST_CASE(GET_MIN_CLOCK_RATE, UART) {
+g_assert_cmphex(tag->response.value.clock_id, ==, CLOCK_ID_UART);
+g_assert_cmphex(tag->response.value.rate, ==, CLOCK_RATE_UART);
+}
+DECLARE_TEST_CASE_SETUP(GET_MIN_CLOCK_RATE, UART) {
+tag->request.value.clock_id = CLOCK_ID_UART;
+}
+
+/**/
+DECLARE_TEST_CASE(GET_CLOCK_RATE, CORE) {
+g_assert_cmphex(tag->response.value.clock_id, ==, CLOCK_ID_CORE);
+g_assert_cmphex(tag->response.value.rate, ==, CLOCK_RATE_CORE);
+}
+DECLARE_TEST_CASE_SETUP(GET_CLOCK_RATE, CORE) {
+tag->request.value.clock_id = CLOCK_ID_CORE;
+}
+
+/**/
+DECLARE_TEST_CASE(GET_MAX_CLOCK_RATE, CORE) {
+g_assert_cmphex(tag->response.value.clock_id, ==, CLOCK_ID_CORE);
+g_assert_cmphex(tag->response.value.rate, ==, CLOCK_RATE_CORE);
+}
+DECLARE_TEST_CASE_SETUP(GET_MAX_CLOCK_RATE, CORE) {
+tag->request.value.clock_id = CLOCK_ID_CORE;
+}
+
+/**/
+DECLARE_TEST_CASE(GET_MIN_CLOCK_RATE, CORE) {
+g_assert_cmphex(tag->response.value.clock_id, ==, CLOCK_ID_CORE);
+g_assert_cmphex(tag->response.value.rate, ==, CLOCK_RATE_CORE);
+}
+DECLARE_TEST_CASE_SETUP(GET_MIN_CLOCK_RATE, CORE) {
+tag->request.value.clock_id = CLOCK_ID_CORE;
+}
+
+/**/
+DECLARE_TEST_CASE(GET_CLOCK_RATE, ANY) {
+g_assert_cmphex(tag->response.value.clock_id, ==, CLOCK_ID_UNDEFINED);
+g_assert_cmphex(tag->response.value.rate, ==, CLOCK_RATE_ANY);
+}
+DECLARE_TEST_CASE_SETUP(GET_CLOCK_RATE, ANY) {
+tag->request.value.clock_id = CLOCK_ID_UNDEFINED;
+}
+
+/**/
+DECLARE_TEST_CASE(GET_MAX_CLOCK_RATE, ANY) {
+g_assert_cmphex(tag->response.value.clock_id, ==, CLOCK_ID_UNDEFINED);
+g_assert_cmphex(tag->response.value.rate, ==, CLOCK_RATE_ANY);
+}
+DECLARE_TEST_CASE_SETUP(GET_MAX_CLOCK_RATE, ANY) {
+tag->request.value.clock_id = CLOCK_ID_UNDEFINED;
+}
+
+/**/
+DECLARE_TEST_CASE(GET_MIN_CLOCK_RATE, ANY) {
+g_assert_cmphex(tag->response.value.clock_id, ==, CLOCK_ID_UNDEFINED);
+g_assert_cmphex(tag->response.value.rate, ==, CLOCK_RATE_ANY);
+}
+DECLARE_TEST_CASE_SETUP(GET_MIN_CLOCK_RATE, ANY) {
+tag->request.value.clock_id = CLOCK_ID_UNDEFINED;
+}
+
+/**/
+DECLARE_TEST_CASE(GET_TEMPERATURE) {
+g_assert_cmphex(tag->response.value.temperature_id, ==, 
TEMPERATURE_ID_SOC);
+g_assert_cmpint(tag->response.value.temperature, ==, TEMPERATURE_SOC);
+}

[PATCH v4 33/45] Connect RNG200, PCIE and GENET to GIC

2023-12-07 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/arm/bcm2838.c | 19 +++
 include/hw/arm/bcm2838_peripherals.h |  2 ++
 2 files changed, 21 insertions(+)

diff --git a/hw/arm/bcm2838.c b/hw/arm/bcm2838.c
index 89cd9d5d8c..83f84b22ad 100644
--- a/hw/arm/bcm2838.c
+++ b/hw/arm/bcm2838.c
@@ -210,6 +210,10 @@ static void bcm2838_realize(DeviceState *dev, Error **errp)
 sysbus_connect_irq(SYS_BUS_DEVICE(_base->dwc2), 0,
qdev_get_gpio_in(gicdev, GIC_SPI_INTERRUPT_DWC2));
 
+/* Connect RNG200 to the interrupt controller */
+sysbus_connect_irq(SYS_BUS_DEVICE(>rng200), 0,
+   qdev_get_gpio_in(gicdev, GIC_SPI_INTERRUPT_RNG200));
+
 /* Connect DMA 0-6 to the interrupt controller */
 for (int_n = GIC_SPI_INTERRUPT_DMA_0; int_n <= GIC_SPI_INTERRUPT_DMA_6;
  int_n++) {
@@ -232,6 +236,21 @@ static void bcm2838_realize(DeviceState *dev, Error **errp)
 qdev_connect_gpio_out(dma_9_10_irq_orgate, 0,
   qdev_get_gpio_in(gicdev, 
GIC_SPI_INTERRUPT_DMA_9_10));
 
+/* Connect PCIe host bridge to the interrupt controller */
+for (n = 0; n < BCM2838_PCIE_NUM_IRQS; n++) {
+int_n = GIC_SPI_INTERRUPT_PCI_INT_A + n;
+sysbus_connect_irq(SYS_BUS_DEVICE(>pcie_host), n,
+   qdev_get_gpio_in(gicdev, int_n));
+bcm2838_pcie_host_set_irq_num(BCM2838_PCIE_HOST(>pcie_host), n,
+  int_n);
+}
+
+/* Connect Gigabit Ethernet controller to the interrupt controller */
+sysbus_connect_irq(SYS_BUS_DEVICE(>genet), 0,
+   qdev_get_gpio_in(gicdev, GIC_SPI_INTERRUPT_GENET_A));
+sysbus_connect_irq(SYS_BUS_DEVICE(>genet), 1,
+   qdev_get_gpio_in(gicdev, GIC_SPI_INTERRUPT_GENET_B));
+
 /* Pass through inbound GPIO lines to the GIC */
 qdev_init_gpio_in(dev, bcm2838_gic_set_irq, GIC_NUM_IRQS);
 
diff --git a/include/hw/arm/bcm2838_peripherals.h 
b/include/hw/arm/bcm2838_peripherals.h
index 1cfcf5dcce..cdeb892f04 100644
--- a/include/hw/arm/bcm2838_peripherals.h
+++ b/include/hw/arm/bcm2838_peripherals.h
@@ -17,6 +17,8 @@
 #include "hw/sd/sdhci.h"
 #include "hw/gpio/bcm2838_gpio.h"
 
+#define GENET_OFFSET0x158
+
 /* SPI */
 #define GIC_SPI_INTERRUPT_MBOX 33
 #define GIC_SPI_INTERRUPT_MPHI 40
-- 
2.34.1




[PATCH v4 38/45] Add mailbox tests tags. Part 2

2023-12-07 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 tests/qtest/bcm2838-mailbox.h | 152 ++
 1 file changed, 152 insertions(+)

diff --git a/tests/qtest/bcm2838-mailbox.h b/tests/qtest/bcm2838-mailbox.h
index 04472fe23d..49668668da 100644
--- a/tests/qtest/bcm2838-mailbox.h
+++ b/tests/qtest/bcm2838-mailbox.h
@@ -362,6 +362,158 @@ DECLARE_TAG_TYPE(TAG_SET_FB_VIRT_WIDTH_t,
 uint32_t height;
 });
 
+DECLARE_TAG_TYPE(TAG_GET_FB_DEPTH_t,
+struct {},
+struct {
+uint32_t bpp;
+});
+
+DECLARE_TAG_TYPE(TAG_TEST_FB_DEPTH_t,
+struct {
+uint32_t bpp;
+},
+struct {
+uint32_t bpp;
+});
+
+DECLARE_TAG_TYPE(TAG_SET_FB_DEPTH_t,
+struct {
+uint32_t bpp;
+},
+struct {
+uint32_t bpp;
+});
+
+DECLARE_TAG_TYPE(TAG_GET_PIXEL_ORDER_t,
+struct {},
+struct {
+uint32_t pixel_order;
+});
+
+DECLARE_TAG_TYPE(TAG_TEST_PIXEL_ORDER_t,
+struct {
+uint32_t pixel_order;
+},
+struct {
+uint32_t pixel_order;
+});
+
+DECLARE_TAG_TYPE(TAG_SET_PIXEL_ORDER_t,
+struct {
+uint32_t pixel_order;
+},
+struct {
+uint32_t pixel_order;
+});
+
+DECLARE_TAG_TYPE(TAG_GET_FB_ALPHA_MODE_t,
+struct {},
+struct {
+uint32_t alpha_mode;
+});
+
+DECLARE_TAG_TYPE(TAG_TEST_FB_ALPHA_MODE_t,
+struct {
+uint32_t alpha_mode;
+},
+struct {
+uint32_t alpha_mode;
+});
+
+DECLARE_TAG_TYPE(TAG_SET_FB_ALPHA_MODE_t,
+struct {
+uint32_t alpha_mode;
+},
+struct {
+uint32_t alpha_mode;
+});
+
+DECLARE_TAG_TYPE(TAG_GET_PITCH_t,
+struct {},
+struct {
+uint32_t pitch;
+});
+
+DECLARE_TAG_TYPE(TAG_SET_PITCH_t,
+struct {
+uint32_t pitch;
+},
+struct {});
+
+DECLARE_TAG_TYPE(TAG_GET_VIRTUAL_OFFSET_t,
+struct {},
+struct {
+uint32_t x;
+uint32_t y;
+});
+
+DECLARE_TAG_TYPE(TAG_TEST_VIRTUAL_OFFSET_t,
+struct {
+uint32_t x;
+uint32_t y;
+},
+struct {
+uint32_t x;
+uint32_t y;
+});
+
+DECLARE_TAG_TYPE(TAG_SET_VIRTUAL_OFFSET_t,
+struct {
+uint32_t x;
+uint32_t y;
+},
+struct {
+uint32_t x;
+uint32_t y;
+});
+
+DECLARE_TAG_TYPE(TAG_GET_OVERSCAN_t,
+struct {},
+struct {
+uint32_t top;
+uint32_t bottom;
+uint32_t left;
+uint32_t right;
+});
+
+DECLARE_TAG_TYPE(TAG_TEST_OVERSCAN_t,
+struct {
+uint32_t top;
+uint32_t bottom;
+uint32_t left;
+uint32_t right;
+},
+struct {
+uint32_t top;
+uint32_t bottom;
+uint32_t left;
+uint32_t right;
+});
+
+DECLARE_TAG_TYPE(TAG_SET_OVERSCAN_t,
+struct {
+uint32_t top;
+uint32_t bottom;
+uint32_t left;
+uint32_t right;
+},
+struct {
+uint32_t top;
+uint32_t bottom;
+uint32_t left;
+uint32_t right;
+});
+
+DECLARE_TAG_TYPE(TAG_GET_COMMANDLINE_t,
+struct {},
+struct {});
+
+DECLARE_TAG_TYPE(TAG_GET_DMA_CHANNELS_t,
+struct {},
+struct {
+uint32_t mask;
+});
+
 int mbox0_has_data(void);
 void mbox0_read_message(uint8_t channel, void *msgbuf, size_t msgbuf_size);
 void mbox1_write_message(uint8_t channel, uint32_t msg_addr);
-- 
2.34.1




[PATCH v4 40/45] Add mailbox property tests. Part 1

2023-12-07 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 tests/qtest/bcm2838-mailbox.c|  34 ++--
 tests/qtest/bcm2838-mailbox.h|  18 +-
 tests/qtest/bcm2838-mbox-property-test.c | 206 +++
 tests/qtest/meson.build  |   2 +-
 4 files changed, 220 insertions(+), 40 deletions(-)
 create mode 100644 tests/qtest/bcm2838-mbox-property-test.c

diff --git a/tests/qtest/bcm2838-mailbox.c b/tests/qtest/bcm2838-mailbox.c
index 2edc24e15e..4b160cd56c 100644
--- a/tests/qtest/bcm2838-mailbox.c
+++ b/tests/qtest/bcm2838-mailbox.c
@@ -12,6 +12,10 @@
 #include "libqtest-single.h"
 #include "bcm2838-mailbox.h"
 
+REG32(MBOX_EXCHNG_REG,  0)
+FIELD(MBOX_EXCHNG_REG, CHANNEL, 0, 4)
+FIELD(MBOX_EXCHNG_REG, DATA,4, 28)
+
 
 static uint32_t qtest_mbox0_read_reg32(QTestState *s, uint32_t offset)
 {
@@ -25,47 +29,33 @@ static void qtest_mbox1_write_reg32(QTestState *s, uint32_t 
offset, uint32_t val
 
 static void qtest_mbox1_write(QTestState *s, uint8_t channel, uint32_t data)
 {
-uint32_t reg;
+uint32_t mbox_reg = 0;
 
-reg = FIELD_DP32(reg, MBOX_WRITE_REG, CHANNEL, channel);
-reg = FIELD_DP32(reg, MBOX_WRITE_REG, DATA, data);
-qtest_mbox1_write_reg32(s, MBOX_REG_WRITE, reg);
+mbox_reg = FIELD_DP32(mbox_reg, MBOX_EXCHNG_REG, CHANNEL, channel);
+mbox_reg = FIELD_DP32(mbox_reg, MBOX_EXCHNG_REG, DATA, data);
+qtest_mbox1_write_reg32(s, MBOX_REG_WRITE, mbox_reg);
 }
 
 int qtest_mbox0_has_data(QTestState *s) {
 return !(qtest_mbox0_read_reg32(s, MBOX_REG_STATUS) & MBOX_READ_EMPTY);
 }
 
-int mbox0_has_data(void) {
-return qtest_mbox0_has_data(global_qtest);
-}
-
 void qtest_mbox0_read_message(QTestState *s,
   uint8_t channel,
   void *msgbuf,
   size_t msgbuf_size)
 {
-uint32_t reg;
+uint32_t mbox_reg;
 uint32_t msgaddr;
 
 g_assert(qtest_mbox0_has_data(s));
-reg = qtest_mbox0_read_reg32(s, MBOX_REG_READ);
-g_assert_cmphex(FIELD_EX32(reg, MBOX_WRITE_REG, CHANNEL), ==, channel);
-msgaddr = FIELD_EX32(reg, MBOX_WRITE_REG, DATA) << 4;
+mbox_reg = qtest_mbox0_read_reg32(s, MBOX_REG_READ);
+g_assert_cmphex(FIELD_EX32(mbox_reg, MBOX_EXCHNG_REG, CHANNEL), ==, 
channel);
+msgaddr = FIELD_EX32(mbox_reg, MBOX_EXCHNG_REG, DATA) << 4;
 qtest_memread(s, msgaddr, msgbuf, msgbuf_size);
 }
 
-void mbox0_read_message(uint8_t channel, void *msgbuf, size_t msgbuf_size) {
-qtest_mbox0_read_message(global_qtest, channel, msgbuf, msgbuf_size);
-}
-
 void qtest_mbox1_write_message(QTestState *s, uint8_t channel, uint32_t 
msg_addr)
 {
 qtest_mbox1_write(s, channel, msg_addr >> 4);
 }
-
-
-void mbox1_write_message(uint8_t channel, uint32_t msg_addr)
-{
-qtest_mbox1_write_message(global_qtest, channel, msg_addr);
-}
diff --git a/tests/qtest/bcm2838-mailbox.h b/tests/qtest/bcm2838-mailbox.h
index 2b140a5d32..7e660e65a7 100644
--- a/tests/qtest/bcm2838-mailbox.h
+++ b/tests/qtest/bcm2838-mailbox.h
@@ -77,7 +77,7 @@
 #define TAG_SET_GPIO_STATE 0x00038041
 #define TAG_INITIALIZE_VCHIQ   0x00048010
 
-#define BOARD_REVISION11546898
+#define BOARD_REVISION0xB03115
 #define FIRMWARE_REVISION 346337
 #define FIRMWARE_VARIANT  0x /* TODO: Find the real value */
 
@@ -147,22 +147,6 @@
 /* Used to test stubs that don't perform actual work */
 #define DUMMY_VALUE 0x12345678
 
-REG32(MBOX_WRITE_REG,  0)
-FIELD(MBOX_WRITE_REG, CHANNEL, 0, 4)
-FIELD(MBOX_WRITE_REG, DATA,4, 28)
-
-REG32(MBOX_SIZE_STAT,  0)
-FIELD(MBOX_SIZE_STAT, SIZE,0, 30)
-FIELD(MBOX_SIZE_STAT, SUCCESS, 30, 1)
-
-REG32(SET_DEVICE_POWER_STATE_CMD,0)
-FIELD(SET_DEVICE_POWER_STATE_CMD, EN,0, 1)
-FIELD(SET_DEVICE_POWER_STATE_CMD, WAIT,  1, 1)
-
-REG32(GET_CLOCK_STATE_CMD,0)
-FIELD(GET_CLOCK_STATE_CMD, EN,0, 1)
-FIELD(GET_CLOCK_STATE_CMD, NPRES, 1, 1)
-
 typedef struct {
 uint32_t size;
 uint32_t req_resp_code;
diff --git a/tests/qtest/bcm2838-mbox-property-test.c 
b/tests/qtest/bcm2838-mbox-property-test.c
new file mode 100644
index 00..80746dbb95
--- /dev/null
+++ b/tests/qtest/bcm2838-mbox-property-test.c
@@ -0,0 +1,206 @@
+/*
+ * Tests set for BCM2838 mailbox property interface.
+ *
+ * Copyright (c) 2022 Auriga
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/registerfields.h"
+#include "libqtest-single.h"
+#include "bcm2838-mailbox.h"
+
+REG32(MBOX_SIZE_STAT,  0)
+FIELD(MBOX_SIZE_STAT, SIZE,0, 31)
+FIELD(MBOX_SIZE_STAT, SUCCESS, 31, 1)
+
+REG32(SET_DEVICE_POWER_STATE_CMD,0)
+FIELD(SET_DEVICE_POWER_STATE_CMD, EN,0, 1)
+FIELD(SET_DEVICE_POWER_STATE_CMD, WAIT,  1, 1)
+
+REG32(GET_CLOCK_STATE_CMD,0)
+FIELD(GET_CLOCK_STATE_CMD, EN,0, 1)
+FIELD(GET_CLOCK_STATE_CMD, NPRES, 1, 1)
+
+#define MBOX_TEST_MESSAGE_ADDRESS 0x1000
+

[PATCH v4 10/45] Add BCM2838 checkpoint support

2023-12-07 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/arm/bcm2838_peripherals.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/arm/bcm2838_peripherals.c b/hw/arm/bcm2838_peripherals.c
index c147b6e453..196fb890a2 100644
--- a/hw/arm/bcm2838_peripherals.c
+++ b/hw/arm/bcm2838_peripherals.c
@@ -22,7 +22,7 @@ static void bcm2838_peripherals_init(Object *obj)
 {
 BCM2838PeripheralState *s = BCM2838_PERIPHERALS(obj);
 BCM2838PeripheralClass *bc = BCM2838_PERIPHERALS_GET_CLASS(obj);
-RaspiPeripheralBaseState *s_base = RASPI_PERIPHERALS_BASE(obj);
+BCMSocPeripheralBaseState *s_base = BCM_SOC_PERIPHERALS_BASE(obj);
 
 /* Lower memory region for peripheral devices (exported to the Soc) */
 memory_region_init(>peri_low_mr, obj, "bcm2838-peripherals",
-- 
2.34.1




[PATCH v4 28/45] Implement GENET register ops

2023-12-07 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/net/bcm2838_genet.c | 189 +++--
 include/hw/net/bcm2838_genet.h |   2 +
 2 files changed, 182 insertions(+), 9 deletions(-)

diff --git a/hw/net/bcm2838_genet.c b/hw/net/bcm2838_genet.c
index be899b68f8..56ff6a6f39 100644
--- a/hw/net/bcm2838_genet.c
+++ b/hw/net/bcm2838_genet.c
@@ -233,25 +233,144 @@ REG16(GENET_PHY_EXP_SEL,   0)
 FIELD(GENET_PHY_EXP_SEL, REG_ID,   0, 8)
 FIELD(GENET_PHY_EXP_SEL, BLOCK_ID, 8, 8)
 
+static void bcm2838_genet_set_qemu_mac(BCM2838GenetState *s)
+{
+const MACAddr *addr = >nic_conf.macaddr;
+
+s->regs.umac.mac0 = FIELD_DP32(s->regs.umac.mac0, GENET_UMAC_MAC_0,
+   ADDR_0, addr->a[0]);
+s->regs.umac.mac0 = FIELD_DP32(s->regs.umac.mac0, GENET_UMAC_MAC_0,
+   ADDR_1, addr->a[1]);
+s->regs.umac.mac0 = FIELD_DP32(s->regs.umac.mac0, GENET_UMAC_MAC_0,
+   ADDR_2, addr->a[2]);
+s->regs.umac.mac0 = FIELD_DP32(s->regs.umac.mac0, GENET_UMAC_MAC_0,
+   ADDR_3, addr->a[3]);
+s->regs.umac.mac1 = FIELD_DP32(s->regs.umac.mac1, GENET_UMAC_MAC_1,
+   ADDR_4, addr->a[4]);
+s->regs.umac.mac1 = FIELD_DP32(s->regs.umac.mac1, GENET_UMAC_MAC_1,
+   ADDR_5, addr->a[5]);
+}
+
+static void bcm2838_genet_set_irq_default(BCM2838GenetState *s)
+{
+uint32_t intrl_0_status = s->regs.intrl0.stat;
+uint32_t intrl_0_mask = s->regs.intrl0.mask_status;
+int level = (intrl_0_status & ~intrl_0_mask) == 0 ? 0 : 1;
+
+qemu_set_irq(s->irq_default, level);
+}
+
+static void bcm2838_genet_set_irq_prio(BCM2838GenetState *s)
+{
+uint32_t intrl_1_status = s->regs.intrl1.stat;
+uint32_t intrl_1_mask = s->regs.intrl1.mask_status;
+int level = (intrl_1_status & ~intrl_1_mask) == 0 ? 0 : 1;
+
+qemu_set_irq(s->irq_prio, level);
+}
+
 static uint64_t bcm2838_genet_read(void *opaque, hwaddr offset, unsigned size)
 {
 uint64_t value = ~0;
+BCM2838GenetState *s = opaque;
 
-qemu_log_mask(
-LOG_GUEST_ERROR,
-"%s: out-of-range access, %u bytes @ offset 0x%04" PRIx64 "\n",
-__func__, size, offset);
+if (offset + size < sizeof(s->regs)) {
+memcpy(, (uint8_t *)>regs + offset, size);
+} else {
+qemu_log_mask(
+LOG_GUEST_ERROR,
+"%s: out-of-range access, %u bytes @ offset 0x%04" PRIx64 "\n",
+__func__, size, offset);
+}
 
 trace_bcm2838_genet_read(size, offset, value);
 return value;
 }
 
 static void bcm2838_genet_write(void *opaque, hwaddr offset, uint64_t value,
-unsigned size) {
-qemu_log_mask(
-LOG_GUEST_ERROR,
-"%s: out-of-range access, %u bytes @ offset 0x%04" PRIx64 "\n",
-__func__, size, offset);
+unsigned size)
+{
+BCM2838GenetState *s = opaque;
+MACAddr *mac = >nic_conf.macaddr;
+NetClientState *ncs = qemu_get_queue(s->nic);
+
+trace_bcm2838_genet_write(size, offset, value);
+
+if (offset + size < sizeof(s->regs)) {
+switch (offset) {
+case BCM2838_GENET_INTRL0_SET:
+s->regs.intrl0.stat |= value;
+break;
+case BCM2838_GENET_INTRL0_CLEAR:
+s->regs.intrl0.stat &= ~value;
+break;
+case BCM2838_GENET_INTRL0_MASK_SET:
+s->regs.intrl0.mask_status |= value;
+break;
+case BCM2838_GENET_INTRL0_MASK_CLEAR:
+s->regs.intrl0.mask_status &= ~value;
+break;
+case BCM2838_GENET_INTRL1_SET:
+s->regs.intrl1.stat |= value;
+break;
+case BCM2838_GENET_INTRL1_CLEAR:
+s->regs.intrl1.stat &= ~value;
+break;
+case BCM2838_GENET_INTRL1_MASK_SET:
+s->regs.intrl1.mask_status |= value;
+break;
+case BCM2838_GENET_INTRL1_MASK_CLEAR:
+s->regs.intrl1.mask_status &= ~value;
+break;
+case BCM2838_GENET_UMAC_CMD:
+/* Complete SW reset as soon as it has been requested */
+if (FIELD_EX32(value, GENET_UMAC_CMD, SW_RESET) == 1) {
+device_cold_reset(DEVICE(s));
+value = FIELD_DP32(value, GENET_UMAC_CMD, SW_RESET, 0);
+}
+break;
+/*
+ * TODO: before changing MAC address we'd better inform QEMU
+ * network subsystem about freeing previously used one, but
+ * qemu_macaddr_set_free function isn't accessible for us (marked
+ * as static in net/net.c), see also https://lists.nongnu.org/
+ * archive/html/qemu-devel/2022-07/msg02123.html
+ */
+case BCM2838_GENET_UMAC_MAC0:
+mac->a[0] = FIELD_EX32(value, GENET_UMAC_MAC_0, ADDR_0);
+mac->a[1] = FIELD_EX32(value, GENET_UMAC_MAC_0, ADDR_1);
+ 

[PATCH v4 42/45] Add mailbox property tests. Part 3

2023-12-07 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 tests/qtest/bcm2838-mbox-property-test.c | 213 ++-
 1 file changed, 212 insertions(+), 1 deletion(-)

diff --git a/tests/qtest/bcm2838-mbox-property-test.c 
b/tests/qtest/bcm2838-mbox-property-test.c
index 5322c563a0..1b4a2ed9cb 100644
--- a/tests/qtest/bcm2838-mbox-property-test.c
+++ b/tests/qtest/bcm2838-mbox-property-test.c
@@ -361,7 +361,194 @@ DECLARE_TEST_CASE_SETUP(SET_FB_VIRT_WIDTH) {
 tag->request.value.height = 600;
 }
 
-//==
+/**/
+DECLARE_TEST_CASE(TEST_FB_DEPTH) {
+g_assert_cmpint(tag->response.value.bpp, ==, DUMMY_VALUE);
+}
+DECLARE_TEST_CASE_SETUP(TEST_FB_DEPTH) {
+tag->request.value.bpp = DUMMY_VALUE;
+}
+
+/**/
+DECLARE_TEST_CASE(GET_FB_DEPTH) {
+g_assert_cmpint(tag->response.value.bpp, ==, 16);
+}
+
+/**/
+DECLARE_TEST_CASE(SET_FB_DEPTH) {
+g_assert_cmpint(tag->response.value.bpp, ==, 24);
+}
+DECLARE_TEST_CASE_SETUP(SET_FB_DEPTH) {
+tag->request.value.bpp = 24;
+}
+
+/**/
+DECLARE_TEST_CASE(TEST_PIXEL_ORDER) {
+g_assert_cmphex(tag->response.value.pixel_order, ==, DUMMY_VALUE);
+}
+DECLARE_TEST_CASE_SETUP(TEST_PIXEL_ORDER) {
+tag->request.value.pixel_order = DUMMY_VALUE;
+}
+
+/**/
+DECLARE_TEST_CASE(GET_PIXEL_ORDER) {
+g_assert_cmphex(tag->response.value.pixel_order, ==, PIXEL_ORDER_RGB);
+}
+
+/**/
+DECLARE_TEST_CASE(SET_PIXEL_ORDER, BGR) {
+g_assert_cmphex(tag->response.value.pixel_order, ==, PIXEL_ORDER_BGR);
+}
+DECLARE_TEST_CASE_SETUP(SET_PIXEL_ORDER, BGR) {
+tag->request.value.pixel_order = PIXEL_ORDER_BGR;
+}
+
+/**/
+DECLARE_TEST_CASE(SET_PIXEL_ORDER, RGB) {
+g_assert_cmphex(tag->response.value.pixel_order, ==, PIXEL_ORDER_BGR);
+}
+DECLARE_TEST_CASE_SETUP(SET_PIXEL_ORDER, RGB) {
+tag->request.value.pixel_order = PIXEL_ORDER_BGR;
+}
+
+/**/
+DECLARE_TEST_CASE(TEST_FB_ALPHA_MODE) {
+g_assert_cmphex(tag->response.value.alpha_mode, ==, DUMMY_VALUE);
+}
+DECLARE_TEST_CASE_SETUP(TEST_FB_ALPHA_MODE) {
+tag->request.value.alpha_mode = DUMMY_VALUE;
+}
+
+/**/
+DECLARE_TEST_CASE(GET_FB_ALPHA_MODE) {
+g_assert_cmphex(tag->response.value.alpha_mode, ==, ALPHA_MODE_IGNORED);
+}
+
+/**/
+DECLARE_TEST_CASE(SET_FB_ALPHA_MODE, ENABLED) {
+g_assert_cmphex(tag->response.value.alpha_mode, ==, ALPHA_MODE_ENABLED);
+}
+DECLARE_TEST_CASE_SETUP(SET_FB_ALPHA_MODE, ENABLED) {
+tag->request.value.alpha_mode = ALPHA_MODE_ENABLED;
+}
+
+/**/
+DECLARE_TEST_CASE(SET_FB_ALPHA_MODE, REVERSED) {
+g_assert_cmphex(tag->response.value.alpha_mode, ==, ALPHA_MODE_REVERSED);
+}
+DECLARE_TEST_CASE_SETUP(SET_FB_ALPHA_MODE, REVERSED) {
+tag->request.value.alpha_mode = ALPHA_MODE_REVERSED;
+}
+
+/**/
+DECLARE_TEST_CASE(SET_FB_ALPHA_MODE, IGNORED) {
+g_assert_cmphex(tag->response.value.alpha_mode, ==, ALPHA_MODE_IGNORED);
+}
+DECLARE_TEST_CASE_SETUP(SET_FB_ALPHA_MODE, IGNORED) {
+tag->request.value.alpha_mode = ALPHA_MODE_IGNORED;
+}
+
+/**/
+DECLARE_TEST_CASE(GET_PITCH) {
+g_assert_cmpint(tag->response.value.pitch, ==, 1280);
+}
+
+/**/
+DECLARE_TEST_CASE(TEST_VIRTUAL_OFFSET) {
+g_assert_cmpint(tag->response.value.x, ==, DUMMY_VALUE);
+g_assert_cmpint(tag->response.value.y, ==, DUMMY_VALUE);
+}
+DECLARE_TEST_CASE_SETUP(TEST_VIRTUAL_OFFSET) {
+tag->request.value.x = DUMMY_VALUE;
+tag->request.value.y = DUMMY_VALUE;
+}
+
+/**/
+DECLARE_TEST_CASE(GET_VIRTUAL_OFFSET) {
+g_assert_cmpint(tag->response.value.x, ==, 0);
+g_assert_cmpint(tag->response.value.y, ==, 0);
+}
+
+/**/
+DECLARE_TEST_CASE(SET_VIRTUAL_OFFSET, _0_) {
+g_assert_cmpint(tag->response.value.x, ==, 0);
+g_assert_cmpint(tag->response.value.y, ==, 0);
+}
+DECLARE_TEST_CASE_SETUP(SET_VIRTUAL_OFFSET, _0_) {
+

[PATCH v4 36/45] Add mailbox test constants

2023-12-07 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 tests/qtest/bcm2838-mailbox.h | 139 ++
 1 file changed, 139 insertions(+)

diff --git a/tests/qtest/bcm2838-mailbox.h b/tests/qtest/bcm2838-mailbox.h
index 1d02ca9c2c..8acc4bd2ff 100644
--- a/tests/qtest/bcm2838-mailbox.h
+++ b/tests/qtest/bcm2838-mailbox.h
@@ -7,6 +7,145 @@
  * See the COPYING file in the top-level directory.
  */
 
+#define MBOX0_BASE 0xFE00B880
+#define MBOX1_BASE 0xFE00B8A0
+
+#define MBOX_REG_READ   0x00
+#define MBOX_REG_WRITE  0x00
+#define MBOX_REG_PEEK   0x10
+#define MBOX_REG_SENDER 0x14
+#define MBOX_REG_STATUS 0x18
+#define MBOX_REG_CONFIG 0x1C
+
+#define MBOX_READ_EMPTY 0x4000
+
+#define MBOX_CHANNEL_ID_PROPERTY 8
+
+#define MBOX_PROCESS_REQUEST  0x
+#define MBOX_SUCCESS  0x8000
+#define MBOX_ERROR_PARSING_BUFFER 0x8001
+
+#define TAG_END0x
+#define TAG_GET_FIRMWARE_REVISION  0x0001
+#define TAG_GET_FIRMWARE_VARIANT   0x0002
+#define TAG_GET_BOARD_REVISION 0x00010002
+#define TAG_GET_ARM_MEMORY 0x00010005
+#define TAG_GET_VC_MEMORY  0x00010006
+#define TAG_SET_DEVICE_POWER_STATE 0x00028001
+#define TAG_GET_CLOCK_STATE0x00030001
+#define TAG_GET_CLOCK_RATE 0x00030002
+#define TAG_GET_MAX_CLOCK_RATE 0x00030004
+#define TAG_GET_MIN_CLOCK_RATE 0x00030007
+#define TAG_GET_CLOCKS 0x00010007
+#define TAG_GET_TEMPERATURE0x00030006
+#define TAG_GET_MAX_TEMPERATURE0x0003000a
+#define TAG_ALLOCATE_BUFFER0x00040001
+#define TAG_RELEASE_FRAMEBUFFER0x00048001
+#define TAG_BLANK_FRAMEBUFFER  0x00040002
+#define TAG_GET_FB_PHYS_WIDTH  0x00040003
+#define TAG_TEST_FB_PHYS_WIDTH 0x00044003
+#define TAG_SET_FB_PHYS_WIDTH  0x00048003
+#define TAG_GET_FB_VIRT_WIDTH  0x00040004
+#define TAG_TEST_FB_VIRT_WIDTH 0x00044004
+#define TAG_SET_FB_VIRT_WIDTH  0x00048004
+#define TAG_GET_FB_DEPTH   0x00040005
+#define TAG_TEST_FB_DEPTH  0x00044005
+#define TAG_SET_FB_DEPTH   0x00048005
+#define TAG_GET_PIXEL_ORDER0x00040006
+#define TAG_TEST_PIXEL_ORDER   0x00044006
+#define TAG_SET_PIXEL_ORDER0x00048006
+#define TAG_GET_FB_ALPHA_MODE  0x00040007
+#define TAG_TEST_FB_ALPHA_MODE 0x00044007
+#define TAG_SET_FB_ALPHA_MODE  0x00048007
+#define TAG_GET_PITCH  0x00040008
+#define TAG_SET_PITCH  0x00048008
+#define TAG_GET_VIRTUAL_OFFSET 0x00040009
+#define TAG_TEST_VIRTUAL_OFFSET0x00044009
+#define TAG_SET_VIRTUAL_OFFSET 0x00048009
+#define TAG_GET_OVERSCAN   0x0004000a
+#define TAG_TEST_OVERSCAN  0x0004400a
+#define TAG_SET_OVERSCAN   0x0004800a
+#define TAG_SET_PALETTE0x0004800b
+#define TAG_GET_COMMANDLINE0x00050001
+#define TAG_GET_DMA_CHANNELS   0x00060001
+#define TAG_GET_THROTTLED  0x00030046
+#define TAG_GET_NUM_DISPLAYS   0x00040013
+#define TAG_GET_DISPLAY_SETTINGS   0x00040014
+#define TAG_GET_GPIO_CONFIG0x00030043
+#define TAG_SET_GPIO_CONFIG0x00038043
+#define TAG_GET_GPIO_STATE 0x00030041
+#define TAG_SET_GPIO_STATE 0x00038041
+#define TAG_INITIALIZE_VCHIQ   0x00048010
+
+#define BOARD_REVISION11546898
+#define FIRMWARE_REVISION 346337
+#define FIRMWARE_VARIANT  0x /* TODO: Find the real value */
+
+#define ARM_MEMORY_BASE 0x
+#define ARM_MEMORY_SIZE 0x3c00
+#define VC_MEMORY_BASE  0x3c00
+#define VC_MEMORY_SIZE  0x0400
+#define VC_FB_BASE  0x3c10
+#define VC_FB_SIZE  0x00096000
+
+#define CLOCK_ID_ROOT  0x
+#define CLOCK_ID_EMMC  0x0001
+#define CLOCK_ID_UART  0x0002
+#define CLOCK_ID_ARM   0x0003
+#define CLOCK_ID_CORE  0x0004
+#define CLOCK_ID_UNDEFINED 0x12345678
+
+#define CLOCK_RATE_EMMC 5000
+#define CLOCK_RATE_UART 300
+#define CLOCK_RATE_CORE 35000
+#define CLOCK_RATE_ANY  7
+
+#define DEVICE_ID_SD_CARD   0x
+#define DEVICE_ID_UART0 0x0001
+#define DEVICE_ID_UART1 0x0002
+#define DEVICE_ID_USB HCD   0x0003
+#define DEVICE_ID_I2C0  0x0004
+#define DEVICE_ID_I2C1  0x0005
+#define DEVICE_ID_I2C2  0x0006
+#define DEVICE_ID_SPI   0x0007
+#define DEVICE_ID_CCP2TX0x0008
+#define DEVICE_ID_UNKNOWN_0 0x0009
+#define DEVICE_ID_UNKNOWN_1 0x000a
+
+#define TEMPERATURE_ID_SOC 0x
+
+#define TEMPERATURE_SOC 25000
+#define TEMPERATURE_SOC_MAX 99000
+
+#define ALIGN_4K 4096
+
+#define PIXEL_ORDER_BGR 0
+#define PIXEL_ORDER_RGB 1
+
+#define ALPHA_MODE_ENABLED  0
+#define ALPHA_MODE_REVERSED 1
+#define ALPHA_MODE_IGNORED  2
+
+#define GPIO_MASK 0x003c
+
+#define GPIO_0 0x0080
+
+#define GPIO_DIRECTION_IN  0
+#define GPIO_DIRECTION_OUT 1
+
+#define GPIO_TERMINATION_DISABLED 0
+#define GPIO_TERMINATION_ENABLED  1
+
+#define GPIO_TERMINATION_PULLUP_DISABLED 0
+#define 

[PATCH v4 37/45] Add mailbox tests tags. Part 1

2023-12-07 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 tests/qtest/bcm2838-mailbox.h | 195 +-
 1 file changed, 190 insertions(+), 5 deletions(-)

diff --git a/tests/qtest/bcm2838-mailbox.h b/tests/qtest/bcm2838-mailbox.h
index 8acc4bd2ff..04472fe23d 100644
--- a/tests/qtest/bcm2838-mailbox.h
+++ b/tests/qtest/bcm2838-mailbox.h
@@ -147,13 +147,21 @@
 /* Used to test stubs that don't perform actual work */
 #define DUMMY_VALUE 0x12345678
 
-REG32(MBOX_WRITE_REG, 0)
+REG32(MBOX_WRITE_REG,  0)
 FIELD(MBOX_WRITE_REG, CHANNEL, 0, 4)
-FIELD(MBOX_WRITE_REG, DATA, 4, 28)
+FIELD(MBOX_WRITE_REG, DATA,4, 28)
 
-REG32(MBOX_SIZE_STAT, 0)
-FIELD(MBOX_WRITE_REG, SIZE, 0, 30)
-FIELD(MBOX_WRITE_REG, SUCCESS, 30, 1)
+REG32(MBOX_SIZE_STAT,  0)
+FIELD(MBOX_SIZE_STAT, SIZE,0, 30)
+FIELD(MBOX_SIZE_STAT, SUCCESS, 30, 1)
+
+REG32(SET_DEVICE_POWER_STATE_CMD,0)
+FIELD(SET_DEVICE_POWER_STATE_CMD, EN,0, 1)
+FIELD(SET_DEVICE_POWER_STATE_CMD, WAIT,  1, 1)
+
+REG32(GET_CLOCK_STATE_CMD,0)
+FIELD(GET_CLOCK_STATE_CMD, EN,0, 1)
+FIELD(GET_CLOCK_STATE_CMD, NPRES, 1, 1)
 
 typedef struct {
 uint32_t size;
@@ -176,6 +184,183 @@ typedef struct {  
  \
 };  \
 } TypeName
 
+DECLARE_TAG_TYPE(TAG_GET_FIRMWARE_REVISION_t,
+struct {},
+struct {
+uint32_t revision;
+});
+
+DECLARE_TAG_TYPE(TAG_GET_FIRMWARE_VARIANT_t,
+struct {},
+struct {
+uint32_t variant;
+});
+
+DECLARE_TAG_TYPE(TAG_GET_BOARD_REVISION_t,
+struct {},
+struct {
+uint32_t revision;
+});
+
+DECLARE_TAG_TYPE(TAG_GET_ARM_MEMORY_t,
+struct {},
+struct {
+uint32_t base;
+uint32_t size;
+});
+
+DECLARE_TAG_TYPE(TAG_GET_VC_MEMORY_t,
+struct {},
+struct {
+uint32_t base;
+uint32_t size;
+});
+
+DECLARE_TAG_TYPE(TAG_SET_DEVICE_POWER_STATE_t,
+struct {
+uint32_t device_id;
+uint32_t cmd;
+},
+struct {
+uint32_t device_id;
+uint32_t cmd;
+});
+
+DECLARE_TAG_TYPE(TAG_GET_CLOCK_STATE_t,
+struct {
+uint32_t clock_id;
+},
+struct {
+uint32_t clock_id;
+uint32_t cmd;
+});
+
+DECLARE_TAG_TYPE(TAG_GET_CLOCK_RATE_t,
+struct {
+uint32_t clock_id;
+},
+struct {
+uint32_t clock_id;
+uint32_t rate;
+});
+
+DECLARE_TAG_TYPE(TAG_GET_MAX_CLOCK_RATE_t,
+struct {
+uint32_t clock_id;
+},
+struct {
+uint32_t clock_id;
+uint32_t rate;
+});
+
+DECLARE_TAG_TYPE(TAG_GET_MIN_CLOCK_RATE_t,
+struct {
+uint32_t clock_id;
+},
+struct {
+uint32_t clock_id;
+uint32_t rate;
+});
+
+DECLARE_TAG_TYPE(TAG_GET_CLOCKS_t,
+struct {},
+struct {
+uint32_t root_clock;
+uint32_t arm_clock;
+});
+
+DECLARE_TAG_TYPE(TAG_GET_TEMPERATURE_t,
+struct {
+uint32_t temperature_id;
+},
+struct {
+uint32_t temperature_id;
+uint32_t temperature;
+});
+
+DECLARE_TAG_TYPE(TAG_GET_MAX_TEMPERATURE_t,
+struct {
+uint32_t temperature_id;
+},
+struct {
+uint32_t temperature_id;
+uint32_t temperature;
+});
+
+DECLARE_TAG_TYPE(TAG_ALLOCATE_BUFFER_t,
+struct {
+uint32_t alignment;
+},
+struct {
+uint32_t base;
+uint32_t size;
+});
+
+DECLARE_TAG_TYPE(TAG_RELEASE_FRAMEBUFFER_t,
+struct {},
+struct {});
+
+DECLARE_TAG_TYPE(TAG_BLANK_FRAMEBUFFER_t,
+struct {
+uint32_t on;
+},
+struct {
+uint32_t on;
+});
+
+DECLARE_TAG_TYPE(TAG_GET_FB_PHYS_WIDTH_t,
+struct {},
+struct {
+uint32_t width;
+uint32_t height;
+});
+
+DECLARE_TAG_TYPE(TAG_TEST_FB_PHYS_WIDTH_t,
+struct {
+uint32_t width;
+uint32_t height;
+},
+struct {
+uint32_t width;
+uint32_t height;
+});
+
+DECLARE_TAG_TYPE(TAG_SET_FB_PHYS_WIDTH_t,
+struct {
+uint32_t width;
+uint32_t height;
+},
+struct {
+uint32_t width;
+uint32_t height;
+});
+
+DECLARE_TAG_TYPE(TAG_GET_FB_VIRT_WIDTH_t,
+struct {},
+struct {
+uint32_t width;
+uint32_t height;
+});
+
+DECLARE_TAG_TYPE(TAG_TEST_FB_VIRT_WIDTH_t,
+struct {
+uint32_t width;
+uint32_t height;
+},
+struct {
+uint32_t width;
+uint32_t height;
+});
+
+DECLARE_TAG_TYPE(TAG_SET_FB_VIRT_WIDTH_t,
+struct {
+uint32_t width;
+uint32_t height;
+},
+struct {
+uint32_t width;
+uint32_t height;
+});
 
 int mbox0_has_data(void);
 void mbox0_read_message(uint8_t channel, void *msgbuf, size_t msgbuf_size);
-- 
2.34.1




[PATCH v4 26/45] Add GENET register structs. Part 4

2023-12-07 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 include/hw/net/bcm2838_genet.h | 37 ++
 1 file changed, 37 insertions(+)

diff --git a/include/hw/net/bcm2838_genet.h b/include/hw/net/bcm2838_genet.h
index 1bd004785a..94c2f3ebca 100644
--- a/include/hw/net/bcm2838_genet.h
+++ b/include/hw/net/bcm2838_genet.h
@@ -25,6 +25,12 @@ OBJECT_DECLARE_SIMPLE_TYPE(BCM2838GenetState, BCM2838_GENET)
 #define BCM2838_GENET_HFB_FILTER_CNT  48
 #define BCM2838_GENET_HFB_FILTER_SIZE 128
 
+#define BCM2838_GENET_PHY_AUX_CTL_MISC  0x7
+#define BCM2838_GENET_PHY_AUX_CTL_REGS_SIZE 8
+
+#define BCM2838_GENET_PHY_EXP_SHD_BLOCKS_CNT 256
+#define BCM2838_GENET_PHY_EXP_SHD_REGS_CNT   256
+
 typedef struct {
 uint32_t rev_ctrl;
 uint32_t port_ctrl;
@@ -273,6 +279,34 @@ typedef struct {
 uint16_t rdb_data;
 } BCM2838GenetPhyRegs;
 
+typedef struct {
+uint16_t reserved_0_2[3];
+uint16_t clk_ctl;
+uint16_t scr2;
+uint16_t scr3;
+uint16_t reserved_6_9[4];
+uint16_t apd;
+uint16_t rgmii_mode;
+uint16_t reserved_12;
+uint16_t leds1;
+uint16_t reserved_14_18[5];
+uint16_t _100fx_ctrl;
+uint16_t ssd;
+uint16_t reserved_21_30[10];
+uint16_t mode;
+} BCM2838GenetPhyShdRegs;
+
+typedef struct {
+uint16_t auxctl;
+uint16_t reserved_1_6[BCM2838_GENET_PHY_AUX_CTL_REGS_SIZE - 2];
+uint16_t misc;
+} BCM2838GenetPhyAuxShdRegs;
+
+typedef struct {
+uint16_t regs[BCM2838_GENET_PHY_EXP_SHD_BLOCKS_CNT]
+ [BCM2838_GENET_PHY_EXP_SHD_REGS_CNT];
+} BCM2838GenetPhyExpShdRegs;
+
 struct BCM2838GenetState {
 /*< private >*/
 SysBusDevice parent_obj;
@@ -284,6 +318,9 @@ struct BCM2838GenetState {
 
 BCM2838GenetRegs regs;
 BCM2838GenetPhyRegs phy_regs;
+BCM2838GenetPhyShdRegs phy_shd_regs;
+BCM2838GenetPhyAuxShdRegs phy_aux_ctl_shd_regs;
+BCM2838GenetPhyExpShdRegs phy_exp_shd_regs;
 
 qemu_irq irq_default;
 qemu_irq irq_prio;
-- 
2.34.1




[PATCH v4 23/45] Add GENET register structs. Part 1

2023-12-07 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/net/bcm2838_genet.c | 37 
 include/hw/net/bcm2838_genet.h | 77 +-
 2 files changed, 113 insertions(+), 1 deletion(-)

diff --git a/hw/net/bcm2838_genet.c b/hw/net/bcm2838_genet.c
index 4420486e00..0d98d1b30e 100644
--- a/hw/net/bcm2838_genet.c
+++ b/hw/net/bcm2838_genet.c
@@ -15,9 +15,46 @@
 #include "hw/irq.h"
 #include "net/checksum.h"
 #include "sysemu/dma.h"
+#include "hw/registerfields.h"
 #include "hw/net/bcm2838_genet.h"
 #include "trace.h"
 
+REG32(GENET_SYS_REV_CTRL,  0)
+FIELD(GENET_SYS_REV_CTRL, GPHY_REV,0, 16)
+FIELD(GENET_SYS_REV_CTRL, MINOR_REV,   16, 4)
+FIELD(GENET_SYS_REV_CTRL, RSVD_20_23,  20, 4)
+FIELD(GENET_SYS_REV_CTRL, MAJOR_REV,   24, 4)
+FIELD(GENET_SYS_REV_CTRL, RSVD_28_31,  28, 4)
+
+REG32(GENET_INTRL_0,0)
+FIELD(GENET_INTRL_0, SCB,   0, 1)
+FIELD(GENET_INTRL_0, EPHY,  1, 1)
+FIELD(GENET_INTRL_0, PHY_DET_R, 2, 1)
+FIELD(GENET_INTRL_0, PHY_DET_F, 3, 1)
+FIELD(GENET_INTRL_0, LINK_UP,   4, 1)
+FIELD(GENET_INTRL_0, LINK_DOWN, 5, 1)
+FIELD(GENET_INTRL_0, UMAC,  6, 1)
+FIELD(GENET_INTRL_0, UMAC_TSV,  7, 1)
+FIELD(GENET_INTRL_0, TBUF_UNDERRUN, 8, 1)
+FIELD(GENET_INTRL_0, RBUF_OVERFLOW, 9, 1)
+FIELD(GENET_INTRL_0, HFB_SM,10, 1)
+FIELD(GENET_INTRL_0, HFB_MM,11, 1)
+FIELD(GENET_INTRL_0, MPD_R, 12, 1)
+FIELD(GENET_INTRL_0, RXDMA_MBDONE,  13, 1)
+FIELD(GENET_INTRL_0, RXDMA_PDONE,   14, 1)
+FIELD(GENET_INTRL_0, RXDMA_BDONE,   15, 1)
+FIELD(GENET_INTRL_0, TXDMA_MBDONE,  16, 1)
+FIELD(GENET_INTRL_0, TXDMA_PDONE,   17, 1)
+FIELD(GENET_INTRL_0, TXDMA_BDONE,   18, 1)
+FIELD(GENET_INTRL_0, RSVD_19_22,19, 4)
+FIELD(GENET_INTRL_0, MDIO_DONE, 23, 1)
+FIELD(GENET_INTRL_0, MDIO_ERROR,24, 1)
+FIELD(GENET_INTRL_0, RSVD_25_31,25, 4)
+
+REG32(GENET_INTRL_1,  0)
+FIELD(GENET_INTRL_1, TX_INTRS,0, 16)
+FIELD(GENET_INTRL_1, RX_INTRS,16, 16)
+
 
 static uint64_t bcm2838_genet_read(void *opaque, hwaddr offset, unsigned size)
 {
diff --git a/include/hw/net/bcm2838_genet.h b/include/hw/net/bcm2838_genet.h
index d166a5c24c..f583818399 100644
--- a/include/hw/net/bcm2838_genet.h
+++ b/include/hw/net/bcm2838_genet.h
@@ -19,7 +19,82 @@ OBJECT_DECLARE_SIMPLE_TYPE(BCM2838GenetState, BCM2838_GENET)
 #define BCM2838_GENET_REV_MINOR 0
 
 typedef struct {
-uint8_t stub_area[0x1]; /* temporary stub */
+uint32_t rev_ctrl;
+uint32_t port_ctrl;
+uint32_t rbuf_flush_ctrl;
+uint32_t tbuf_flush_ctrl;
+uint32_t reserved_0x10[12];
+} BCM2838GenetRegsSys;
+
+typedef struct {
+uint32_t reserved_0x0[16];
+} BCM2838GenetRegsGrBridge;
+
+typedef struct {
+uint32_t pwr_mgmt;
+uint32_t reserved_0x4[2];
+uint32_t rgmii_oob_ctrl;
+uint32_t reserved_0x10[3];
+uint32_t gphy_ctrl;
+uint32_t reserved_0x20[24];
+} BCM2838GenetRegsExt;
+
+typedef struct {
+uint32_t stat;
+uint32_t set;
+uint32_t clear;
+uint32_t mask_status;
+uint32_t mask_set;
+uint32_t mask_clear;
+uint32_t reserved_0x18[10];
+} BCM2838GenetRegsIntrl0;
+
+typedef struct {
+uint32_t stat;
+uint32_t set;
+uint32_t clear;
+uint32_t mask_status;
+uint32_t mask_set;
+uint32_t mask_clear;
+uint32_t reserved_0x18[10];
+} BCM2838GenetRegsIntrl1;
+
+typedef struct {
+uint32_t ctrl;
+uint32_t reserved_0x4[2];
+uint32_t status;
+uint32_t reserved_0x10;
+uint32_t chk_ctrl;
+uint32_t reserved_0x18[31];
+uint32_t ovfl_cnt;
+uint32_t err_cnt;
+uint32_t energy_ctrl;
+uint32_t reserved_0xA0[5];
+uint32_t size_ctrl;
+uint32_t reserved_0xB8[18];
+} BCM2838GenetRegsRbuf;
+
+typedef struct {
+uint32_t ctrl;
+uint32_t reserved_0x4[2];
+uint32_t bp_mc;
+uint32_t reserved_0x10;
+uint32_t energy_ctrl;
+uint32_t reserved_0x18[58];
+} BCM2838GenetRegsTbuf;
+
+typedef struct {
+BCM2838GenetRegsSys sys;
+BCM2838GenetRegsGrBridge gr_bridge;
+BCM2838GenetRegsExt ext;
+uint32_t reserved_0x100[64];
+BCM2838GenetRegsIntrl0 intrl0;
+BCM2838GenetRegsIntrl1 intrl1;
+uint32_t reserved_0x280[32];
+BCM2838GenetRegsRbuf rbuf;
+uint32_t reserved_0x400[128];
+BCM2838GenetRegsTbuf tbuf;
+uint32_t reserved_0x700[64];
 } BCM2838GenetRegs;
 
 struct BCM2838GenetState {
-- 
2.34.1




[PATCH v4 13/45] Add memory region for BCM2837 RPiVid ASB

2023-12-07 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/arm/bcm2838_peripherals.c | 3 +++
 include/hw/arm/bcm2838_peripherals.h | 3 ++-
 include/hw/arm/raspi_platform.h  | 1 +
 3 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/hw/arm/bcm2838_peripherals.c b/hw/arm/bcm2838_peripherals.c
index 196fb890a2..d3b42cf25b 100644
--- a/hw/arm/bcm2838_peripherals.c
+++ b/hw/arm/bcm2838_peripherals.c
@@ -182,6 +182,9 @@ static void bcm2838_peripherals_realize(DeviceState *dev, 
Error **errp)
 sysbus_mmio_get_region(SYS_BUS_DEVICE(>gpio), 0));
 
 object_property_add_alias(OBJECT(s), "sd-bus", OBJECT(>gpio), "sd-bus");
+
+/* BCM2838 RPiVid ASB must be mapped to prevent kernel crash */
+create_unimp(s_base, >asb, "bcm2838-asb", RPI4B_ASB_OFFSET, 0x24);
 }
 
 static void bcm2838_peripherals_class_init(ObjectClass *oc, void *data)
diff --git a/include/hw/arm/bcm2838_peripherals.h 
b/include/hw/arm/bcm2838_peripherals.h
index 0a87645e01..af085934c9 100644
--- a/include/hw/arm/bcm2838_peripherals.h
+++ b/include/hw/arm/bcm2838_peripherals.h
@@ -64,12 +64,13 @@ struct BCM2838PeripheralState {
 MemoryRegion mphi_mr_alias;
 
 SDHCIState emmc2;
-UnimplementedDeviceState clkisp;
 BCM2838GpioState gpio;
 
 OrIRQState mmc_irq_orgate;
 OrIRQState dma_7_8_irq_orgate;
 OrIRQState dma_9_10_irq_orgate;
+
+UnimplementedDeviceState asb;
 };
 
 struct BCM2838PeripheralClass {
diff --git a/include/hw/arm/raspi_platform.h b/include/hw/arm/raspi_platform.h
index 0db146e592..537fc6b4af 100644
--- a/include/hw/arm/raspi_platform.h
+++ b/include/hw/arm/raspi_platform.h
@@ -74,6 +74,7 @@ uint64_t board_ram_size(uint32_t board_rev);
 #define DMA_OFFSET  0x7000   /* DMA controller, channels 0-14 */
 #define ARBA_OFFSET 0x9000
 #define BRDG_OFFSET 0xa000
+#define RPI4B_ASB_OFFSET0xa000   /* BCM2838 (BCM2711) RPiVid ASB */
 #define ARM_OFFSET  0xB000   /* ARM control block */
 #define ARMCTRL_OFFSET  (ARM_OFFSET + 0x000)
 #define ARMCTRL_IC_OFFSET   (ARM_OFFSET + 0x200) /* Interrupt controller */
-- 
2.34.1




[PATCH v4 06/45] Add BCM2838 GPIO stub

2023-12-07 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/arm/bcm2838.c |   4 +-
 hw/gpio/bcm2838_gpio.c   | 152 +++
 hw/gpio/meson.build  |   5 +-
 include/hw/arm/bcm2838_peripherals.h |   2 -
 include/hw/gpio/bcm2838_gpio.h   |  40 +++
 5 files changed, 198 insertions(+), 5 deletions(-)
 create mode 100644 hw/gpio/bcm2838_gpio.c
 create mode 100644 include/hw/gpio/bcm2838_gpio.h

diff --git a/hw/arm/bcm2838.c b/hw/arm/bcm2838.c
index 042e543006..8925957c6c 100644
--- a/hw/arm/bcm2838.c
+++ b/hw/arm/bcm2838.c
@@ -14,7 +14,7 @@
 #include "hw/arm/bcm2838.h"
 #include "trace.h"
 
-#define GIC400_MAINTAINANCE_IRQ  9
+#define GIC400_MAINTENANCE_IRQ  9
 #define GIC400_TIMER_NS_EL2_IRQ 10
 #define GIC400_TIMER_VIRT_IRQ   11
 #define GIC400_LEGACY_FIQ   12
@@ -163,7 +163,7 @@ static void bcm2838_realize(DeviceState *dev, Error **errp)
 
 sysbus_connect_irq(SYS_BUS_DEVICE(>gic), n + 4 * BCM283X_NCPUS,
qdev_get_gpio_in(gicdev,
-PPI(n, GIC400_MAINTAINANCE_IRQ)));
+PPI(n, GIC400_MAINTENANCE_IRQ)));
 
 /* Connect timers from the CPU to the interrupt controller */
 qdev_connect_gpio_out(cpudev, GTIMER_PHYS,
diff --git a/hw/gpio/bcm2838_gpio.c b/hw/gpio/bcm2838_gpio.c
new file mode 100644
index 00..15b66cb559
--- /dev/null
+++ b/hw/gpio/bcm2838_gpio.c
@@ -0,0 +1,152 @@
+/*
+ * Raspberry Pi (BCM2838) GPIO Controller
+ * This implementation is based on bcm2835_gpio (hw/gpio/bcm2835_gpio.c)
+ *
+ * Copyright (c) 2022 Auriga LLC
+ *
+ * Authors:
+ *  Lotosh, Aleksey 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qemu/module.h"
+#include "qemu/timer.h"
+#include "qapi/error.h"
+#include "hw/sysbus.h"
+#include "migration/vmstate.h"
+#include "hw/gpio/bcm2838_gpio.h"
+
+#define GPFSEL0   0x00
+#define GPFSEL1   0x04
+#define GPFSEL2   0x08
+#define GPFSEL3   0x0C
+#define GPFSEL4   0x10
+#define GPFSEL5   0x14
+#define GPSET00x1C
+#define GPSET10x20
+#define GPCLR00x28
+#define GPCLR10x2C
+#define GPLEV00x34
+#define GPLEV10x38
+#define GPEDS00x40
+#define GPEDS10x44
+#define GPREN00x4C
+#define GPREN10x50
+#define GPFEN00x58
+#define GPFEN10x5C
+#define GPHEN00x64
+#define GPHEN10x68
+#define GPLEN00x70
+#define GPLEN10x74
+#define GPAREN0   0x7C
+#define GPAREN1   0x80
+#define GPAFEN0   0x88
+#define GPAFEN1   0x8C
+
+#define GPIO_PUP_PDN_CNTRL_REG0 0xE4
+#define GPIO_PUP_PDN_CNTRL_REG1 0xE8
+#define GPIO_PUP_PDN_CNTRL_REG2 0xEC
+#define GPIO_PUP_PDN_CNTRL_REG3 0xF0
+
+#define RESET_VAL_CNTRL_REG0 0xAAA9;
+#define RESET_VAL_CNTRL_REG1 0xA0AA;
+#define RESET_VAL_CNTRL_REG2 0x50AAA95A;
+#define RESET_VAL_CNTRL_REG3 0x0005;
+
+#define BYTES_IN_WORD4
+
+static uint64_t bcm2838_gpio_read(void *opaque, hwaddr offset, unsigned size)
+{
+uint64_t value = 0;
+
+qemu_log_mask(LOG_UNIMP, "%s: %s: not implemented for %"HWADDR_PRIx"\n",
+  TYPE_BCM2838_GPIO, __func__, offset);
+
+return value;
+}
+
+static void bcm2838_gpio_write(void *opaque, hwaddr offset, uint64_t value,
+   unsigned size)
+{
+qemu_log_mask(LOG_UNIMP, "%s: %s: not implemented for %"HWADDR_PRIx"\n",
+  TYPE_BCM2838_GPIO, __func__, offset);
+}
+
+static void bcm2838_gpio_reset(DeviceState *dev)
+{
+BCM2838GpioState *s = BCM2838_GPIO(dev);
+
+s->lev0 = 0;
+s->lev1 = 0;
+
+s->pup_cntrl_reg[0] = RESET_VAL_CNTRL_REG0;
+s->pup_cntrl_reg[1] = RESET_VAL_CNTRL_REG1;
+s->pup_cntrl_reg[2] = RESET_VAL_CNTRL_REG2;
+s->pup_cntrl_reg[3] = RESET_VAL_CNTRL_REG3;
+}
+
+static const MemoryRegionOps bcm2838_gpio_ops = {
+.read = bcm2838_gpio_read,
+.write = bcm2838_gpio_write,
+.endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static const VMStateDescription vmstate_bcm2838_gpio = {
+.name = "bcm2838_gpio",
+.version_id = 1,
+.minimum_version_id = 1,
+.fields = (VMStateField[]) {
+VMSTATE_UINT8_ARRAY(fsel, BCM2838GpioState, BCM2838_GPIO_NUM),
+VMSTATE_UINT32(lev0, BCM2838GpioState),
+VMSTATE_UINT32(lev1, BCM2838GpioState),
+VMSTATE_UINT8(sd_fsel, BCM2838GpioState),
+VMSTATE_UINT32_ARRAY(pup_cntrl_reg, BCM2838GpioState,
+ GPIO_PUP_PDN_CNTRL_NUM),
+VMSTATE_END_OF_LIST()
+}
+};
+
+static void bcm2838_gpio_init(Object *obj)
+{
+BCM2838GpioState *s = BCM2838_GPIO(obj);
+DeviceState *dev = DEVICE(obj);
+SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+
+memory_region_init_io(>iomem, obj, _gpio_ops, s,
+  "bcm2838_gpio", BCM2838_GPIO_REGS_SIZE);
+sysbus_init_mmio(sbd, >iomem);
+

[PATCH v4 02/45] Split out common part of peripherals

2023-12-07 Thread Sergey Kambalin
Pre-setup for BCM2838 introduction

Signed-off-by: Sergey Kambalin 
---
 hw/arm/bcm2835_peripherals.c | 198 +++
 hw/arm/bcm2836.c |  24 ++--
 include/hw/arm/bcm2835_peripherals.h |  29 +++-
 include/hw/arm/bcm2836.h |   3 +-
 4 files changed, 154 insertions(+), 100 deletions(-)

diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c
index 0233038b95..fd70cde123 100644
--- a/hw/arm/bcm2835_peripherals.c
+++ b/hw/arm/bcm2835_peripherals.c
@@ -30,9 +30,9 @@
 #define SEPARATE_DMA_IRQ_MAX 10
 #define ORGATED_DMA_IRQ_COUNT 4
 
-static void create_unimp(BCM2835PeripheralState *ps,
- UnimplementedDeviceState *uds,
- const char *name, hwaddr ofs, hwaddr size)
+void create_unimp(BCMSocPeripheralBaseState *ps,
+  UnimplementedDeviceState *uds,
+  const char *name, hwaddr ofs, hwaddr size)
 {
 object_initialize_child(OBJECT(ps), name, uds, TYPE_UNIMPLEMENTED_DEVICE);
 qdev_prop_set_string(DEVICE(uds), "name", name);
@@ -45,9 +45,36 @@ static void create_unimp(BCM2835PeripheralState *ps,
 static void bcm2835_peripherals_init(Object *obj)
 {
 BCM2835PeripheralState *s = BCM2835_PERIPHERALS(obj);
+BCMSocPeripheralBaseState *s_base = BCM_SOC_PERIPHERALS_BASE(obj);
+
+/* Random Number Generator */
+object_initialize_child(obj, "rng", >rng, TYPE_BCM2835_RNG);
+
+/* Thermal */
+object_initialize_child(obj, "thermal", >thermal, TYPE_BCM2835_THERMAL);
+
+/* GPIO */
+object_initialize_child(obj, "gpio", >gpio, TYPE_BCM2835_GPIO);
+
+object_property_add_const_link(OBJECT(>gpio), "sdbus-sdhci",
+   OBJECT(_base->sdhci.sdbus));
+object_property_add_const_link(OBJECT(>gpio), "sdbus-sdhost",
+   OBJECT(_base->sdhost.sdbus));
+
+/* Gated DMA interrupts */
+object_initialize_child(obj, "orgated-dma-irq",
+_base->orgated_dma_irq, TYPE_OR_IRQ);
+object_property_set_int(OBJECT(_base->orgated_dma_irq), "num-lines",
+ORGATED_DMA_IRQ_COUNT, _abort);
+}
+
+static void raspi_peripherals_base_init(Object *obj)
+{
+BCMSocPeripheralBaseState *s = BCM_SOC_PERIPHERALS_BASE(obj);
+BCMSocPeripheralBaseClass *bc = BCM_SOC_PERIPHERALS_BASE_GET_CLASS(obj);
 
 /* Memory region for peripheral devices, which we export to our parent */
-memory_region_init(>peri_mr, obj,"bcm2835-peripherals", 0x100);
+memory_region_init(>peri_mr, obj, "bcm2835-peripherals", bc->peri_size);
 sysbus_init_mmio(SYS_BUS_DEVICE(s), >peri_mr);
 
 /* Internal memory region for peripheral bus addresses (not exported) */
@@ -98,9 +125,6 @@ static void bcm2835_peripherals_init(Object *obj)
 object_property_add_const_link(OBJECT(>property), "dma-mr",
OBJECT(>gpu_bus_mr));
 
-/* Random Number Generator */
-object_initialize_child(obj, "rng", >rng, TYPE_BCM2835_RNG);
-
 /* Extended Mass Media Controller */
 object_initialize_child(obj, "sdhci", >sdhci, TYPE_SYSBUS_SDHCI);
 
@@ -110,25 +134,9 @@ static void bcm2835_peripherals_init(Object *obj)
 /* DMA Channels */
 object_initialize_child(obj, "dma", >dma, TYPE_BCM2835_DMA);
 
-object_initialize_child(obj, "orgated-dma-irq",
->orgated_dma_irq, TYPE_OR_IRQ);
-object_property_set_int(OBJECT(>orgated_dma_irq), "num-lines",
-ORGATED_DMA_IRQ_COUNT, _abort);
-
 object_property_add_const_link(OBJECT(>dma), "dma-mr",
OBJECT(>gpu_bus_mr));
 
-/* Thermal */
-object_initialize_child(obj, "thermal", >thermal, TYPE_BCM2835_THERMAL);
-
-/* GPIO */
-object_initialize_child(obj, "gpio", >gpio, TYPE_BCM2835_GPIO);
-
-object_property_add_const_link(OBJECT(>gpio), "sdbus-sdhci",
-   OBJECT(>sdhci.sdbus));
-object_property_add_const_link(OBJECT(>gpio), "sdbus-sdhost",
-   OBJECT(>sdhost.sdbus));
-
 /* Mphi */
 object_initialize_child(obj, "mphi", >mphi, TYPE_BCM2835_MPHI);
 
@@ -148,7 +156,72 @@ static void bcm2835_peripherals_init(Object *obj)
 
 static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
 {
+MemoryRegion *mphi_mr;
 BCM2835PeripheralState *s = BCM2835_PERIPHERALS(dev);
+BCMSocPeripheralBaseState *s_base = BCM_SOC_PERIPHERALS_BASE(dev);
+int n;
+
+bcm_soc_peripherals_common_realize(dev, errp);
+
+/* Extended Mass Media Controller */
+sysbus_connect_irq(SYS_BUS_DEVICE(_base->sdhci), 0,
+qdev_get_gpio_in_named(DEVICE(_base->ic), BCM2835_IC_GPU_IRQ,
+   INTERRUPT_ARASANSDIO));
+
+ /* Connect DMA 0-12 to the interrupt controller */
+for (n = 0; n <= SEPARATE_DMA_IRQ_MAX; n++) {
+sysbus_connect_irq(SYS_BUS_DEVICE(_base->dma), n,

[PATCH v4 24/45] Add GENET register structs. Part 2

2023-12-07 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/net/bcm2838_genet.c | 89 ++
 include/hw/net/bcm2838_genet.h | 89 ++
 2 files changed, 178 insertions(+)

diff --git a/hw/net/bcm2838_genet.c b/hw/net/bcm2838_genet.c
index 0d98d1b30e..9a99f34c4a 100644
--- a/hw/net/bcm2838_genet.c
+++ b/hw/net/bcm2838_genet.c
@@ -19,6 +19,7 @@
 #include "hw/net/bcm2838_genet.h"
 #include "trace.h"
 
+/* GENET layouts */
 REG32(GENET_SYS_REV_CTRL,  0)
 FIELD(GENET_SYS_REV_CTRL, GPHY_REV,0, 16)
 FIELD(GENET_SYS_REV_CTRL, MINOR_REV,   16, 4)
@@ -55,6 +56,94 @@ REG32(GENET_INTRL_1,  0)
 FIELD(GENET_INTRL_1, TX_INTRS,0, 16)
 FIELD(GENET_INTRL_1, RX_INTRS,16, 16)
 
+REG32(GENET_UMAC_CMD,  0)
+FIELD(GENET_UMAC_CMD, TX_EN,   0, 1)
+FIELD(GENET_UMAC_CMD, RX_EN,   1, 1)
+FIELD(GENET_UMAC_CMD, SPEED,   2, 2)
+FIELD(GENET_UMAC_CMD, PROMISC, 4, 1)
+FIELD(GENET_UMAC_CMD, PAD_EN,  5, 1)
+FIELD(GENET_UMAC_CMD, CRC_FWD, 6, 1)
+FIELD(GENET_UMAC_CMD, PAUSE_FWD,   7, 1)
+FIELD(GENET_UMAC_CMD, RX_PAUSE_IGNORE, 8, 1)
+FIELD(GENET_UMAC_CMD, TX_ADDR_INS, 9, 1)
+FIELD(GENET_UMAC_CMD, HD_EN,   10, 1)
+FIELD(GENET_UMAC_CMD, SW_RESET_OLD,11, 1)
+FIELD(GENET_UMAC_CMD, RSVD_12, 12, 1)
+FIELD(GENET_UMAC_CMD, SW_RESET,13, 1)
+FIELD(GENET_UMAC_CMD, RSVD_14, 14, 1)
+FIELD(GENET_UMAC_CMD, LCL_LOOP_EN, 15, 1)
+FIELD(GENET_UMAC_CMD, RSVD_16_21,  16, 6)
+FIELD(GENET_UMAC_CMD, AUTO_CONFIG, 22, 1)
+FIELD(GENET_UMAC_CMD, CNTL_FRM_EN, 23, 1)
+FIELD(GENET_UMAC_CMD, NO_LEN_CHK,  24, 1)
+FIELD(GENET_UMAC_CMD, RMT_LOOP_EN, 25, 1)
+FIELD(GENET_UMAC_CMD, RX_ERR_DISC, 26, 1)
+FIELD(GENET_UMAC_CMD, PRBL_EN, 27, 1)
+FIELD(GENET_UMAC_CMD, TX_PAUSE_IGNORE, 28, 1)
+FIELD(GENET_UMAC_CMD, TX_RX_EN,29, 1)
+FIELD(GENET_UMAC_CMD, RUNT_FILTER_DIS, 30, 1)
+FIELD(GENET_UMAC_CMD, RSVD_31, 31, 1)
+
+REG32(GENET_UMAC_MAC_0, 0)
+FIELD(GENET_UMAC_MAC_0, ADDR_3, 0,  8)
+FIELD(GENET_UMAC_MAC_0, ADDR_2, 8,  8)
+FIELD(GENET_UMAC_MAC_0, ADDR_1, 16, 8)
+FIELD(GENET_UMAC_MAC_0, ADDR_0, 24, 8)
+
+REG32(GENET_UMAC_MAC_1, 0)
+FIELD(GENET_UMAC_MAC_1, ADDR_5, 0,  8)
+FIELD(GENET_UMAC_MAC_1, ADDR_4, 8,  8)
+FIELD(GENET_UMAC_MAC_1, RSVD_16_31, 16, 8)
+
+REG32(GENET_UMAC_MDIO_CMD, 0)
+FIELD(GENET_UMAC_MDIO_CMD, REG_DATA,   0, 16)
+FIELD(GENET_UMAC_MDIO_CMD, REG_ID, 16, 5)
+FIELD(GENET_UMAC_MDIO_CMD, PHY_ID, 21, 5)
+FIELD(GENET_UMAC_MDIO_CMD, WR, 26, 1)
+FIELD(GENET_UMAC_MDIO_CMD, RD, 27, 1)
+FIELD(GENET_UMAC_MDIO_CMD, RD_FAIL,28, 1)
+FIELD(GENET_UMAC_MDIO_CMD, START_BUSY, 29, 1)
+FIELD(GENET_UMAC_MDIO_CMD, RSVD_30_31, 30, 2)
+
+REG32(GENET_DMA_RING_CFG, 0)
+FIELD(GENET_DMA_RING_CFG, EN, 0, 17)
+FIELD(GENET_DMA_RING_CFG, RSVD_17_31, 17, 14)
+
+REG32(GENET_DMA_CTRL,  0)
+FIELD(GENET_DMA_CTRL, EN,  0, 1)
+FIELD(GENET_DMA_CTRL, RING_BUF_EN, 1, 17)
+FIELD(GENET_DMA_CTRL, RSVD_18_19,  18, 2)
+FIELD(GENET_DMA_CTRL, TSB_SWAP_EN, 20, 1)
+FIELD(GENET_DMA_CTRL, RSVD_21_31,  21, 11)
+
+REG32(GENET_DMA_PROD_INDEX,  0)
+FIELD(GENET_DMA_PROD_INDEX, INDEX,   0, 16)
+FIELD(GENET_DMA_PROD_INDEX, DISCARD_CNT, 16, 16)
+
+REG32(GENET_DMA_CONS_INDEX, 0)
+FIELD(GENET_DMA_CONS_INDEX, INDEX,  0, 16)
+FIELD(GENET_DMA_CONS_INDEX, RSVD_16_31, 16, 16)
+
+REG32(GENET_DMA_STATUS, 0)
+FIELD(GENET_DMA_STATUS, DISABLED,   0, 1)
+FIELD(GENET_DMA_STATUS, DESC_RAM_INIT_BUSY, 1, 1)
+FIELD(GENET_DMA_STATUS, RSVD_2_31,  2, 30)
+
+REG32(GENET_RDMA_LENGTH_STATUS, 0)
+FIELD(GENET_RDMA_LENGTH_STATUS, OVERRUN,0, 1)
+FIELD(GENET_RDMA_LENGTH_STATUS, CRC_ERROR,  1, 1)
+FIELD(GENET_RDMA_LENGTH_STATUS, RXERR,  2, 1)
+FIELD(GENET_RDMA_LENGTH_STATUS, NO, 3, 1)
+FIELD(GENET_RDMA_LENGTH_STATUS, LG, 4, 1)
+FIELD(GENET_RDMA_LENGTH_STATUS, MULTICAST,  5, 1)
+FIELD(GENET_RDMA_LENGTH_STATUS, BROADCAST,  6, 1)
+FIELD(GENET_RDMA_LENGTH_STATUS, RSVD_7_11,  7, 5)
+FIELD(GENET_RDMA_LENGTH_STATUS, WRAP,   12, 1)
+FIELD(GENET_RDMA_LENGTH_STATUS, SOP,13, 1)
+FIELD(GENET_RDMA_LENGTH_STATUS, EOP,14, 1)
+FIELD(GENET_RDMA_LENGTH_STATUS, OWN,15, 1)
+FIELD(GENET_RDMA_LENGTH_STATUS, BUFLENGTH,  16, 12)
+FIELD(GENET_RDMA_LENGTH_STATUS, RSVD_28_31, 29, 4)
 
 static uint64_t bcm2838_genet_read(void *opaque, hwaddr offset, unsigned size)
 {
diff --git a/include/hw/net/bcm2838_genet.h b/include/hw/net/bcm2838_genet.h
index f583818399..736b4d1757 100644
--- a/include/hw/net/bcm2838_genet.h
+++ b/include/hw/net/bcm2838_genet.h
@@ -18,6 +18,10 @@ OBJECT_DECLARE_SIMPLE_TYPE(BCM2838GenetState, BCM2838_GENET)
 #define BCM2838_GENET_REV_MAJOR 6
 #define BCM2838_GENET_REV_MINOR 0
 
+#define BCM2838_GENET_DMA_DESC_CNT  256
+#define BCM2838_GENET_DMA_RING_CNT  17
+#define 

[PATCH v4 22/45] Add GENET stub

2023-12-07 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/misc/bcm2838_thermal.c  |  2 +-
 hw/net/bcm2838_genet.c | 99 ++
 hw/net/meson.build |  2 +
 hw/net/trace-events| 16 ++
 include/hw/net/bcm2838_genet.h | 40 ++
 5 files changed, 158 insertions(+), 1 deletion(-)
 create mode 100644 hw/net/bcm2838_genet.c
 create mode 100644 include/hw/net/bcm2838_genet.h

diff --git a/hw/misc/bcm2838_thermal.c b/hw/misc/bcm2838_thermal.c
index 2301f657d0..372962b9ba 100644
--- a/hw/misc/bcm2838_thermal.c
+++ b/hw/misc/bcm2838_thermal.c
@@ -80,7 +80,7 @@ static void bcm2838_thermal_class_init(ObjectClass *klass, 
void *data)
 
 dc->realize = bcm2838_thermal_realize;
 
-/* This device has no state: no need for vmstate or reset */
+/* This device has nothing to save: no need for vmstate or reset */
 }
 
 static const TypeInfo bcm2838_thermal_info = {
diff --git a/hw/net/bcm2838_genet.c b/hw/net/bcm2838_genet.c
new file mode 100644
index 00..4420486e00
--- /dev/null
+++ b/hw/net/bcm2838_genet.c
@@ -0,0 +1,99 @@
+/*
+ * BCM2838 Gigabit Ethernet emulation
+ *
+ * Copyright (C) 2022 Ovchinnikov Vitalii 
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/module.h"
+#include "qemu/log.h"
+#include "qemu/error-report.h"
+#include "net/eth.h"
+#include "qapi/error.h"
+#include "hw/irq.h"
+#include "net/checksum.h"
+#include "sysemu/dma.h"
+#include "hw/net/bcm2838_genet.h"
+#include "trace.h"
+
+
+static uint64_t bcm2838_genet_read(void *opaque, hwaddr offset, unsigned size)
+{
+uint64_t value = ~0;
+
+qemu_log_mask(
+LOG_GUEST_ERROR,
+"%s: out-of-range access, %u bytes @ offset 0x%04" PRIx64 "\n",
+__func__, size, offset);
+
+trace_bcm2838_genet_read(size, offset, value);
+return value;
+}
+
+static void bcm2838_genet_write(void *opaque, hwaddr offset, uint64_t value,
+unsigned size) {
+qemu_log_mask(
+LOG_GUEST_ERROR,
+"%s: out-of-range access, %u bytes @ offset 0x%04" PRIx64 "\n",
+__func__, size, offset);
+}
+
+static const MemoryRegionOps bcm2838_genet_ops = {
+.read = bcm2838_genet_read,
+.write = bcm2838_genet_write,
+.endianness = DEVICE_NATIVE_ENDIAN,
+.impl = {.max_access_size = 4},
+.valid = {.min_access_size = 4},
+};
+
+
+static void bcm2838_genet_realize(DeviceState *dev, Error **errp)
+{
+BCM2838GenetState *s = BCM2838_GENET(dev);
+SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+
+/* Controller registers */
+memory_region_init_io(>regs_mr, OBJECT(s), _genet_ops, s,
+  "bcm2838_genet_regs", sizeof(s->regs));
+sysbus_init_mmio(sbd, >regs_mr);
+}
+
+static void bcm2838_genet_phy_reset(BCM2838GenetState *s)
+{
+trace_bcm2838_genet_phy_reset("done");
+}
+
+static void bcm2838_genet_reset(DeviceState *d)
+{
+BCM2838GenetState *s = BCM2838_GENET(d);
+
+memset(>regs, 0x00, sizeof(s->regs));
+
+trace_bcm2838_genet_reset("done");
+
+bcm2838_genet_phy_reset(s);
+}
+
+static void bcm2838_genet_class_init(ObjectClass *class, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(class);
+
+dc->realize = bcm2838_genet_realize;
+dc->reset = bcm2838_genet_reset;
+}
+
+static const TypeInfo bcm2838_genet_info = {
+.name   = TYPE_BCM2838_GENET,
+.parent = TYPE_SYS_BUS_DEVICE,
+.instance_size = sizeof(BCM2838GenetState),
+.class_init = bcm2838_genet_class_init,
+};
+
+static void bcm2838_genet_register(void)
+{
+type_register_static(_genet_info);
+}
+
+type_init(bcm2838_genet_register)
diff --git a/hw/net/meson.build b/hw/net/meson.build
index f64651c467..d513a8d029 100644
--- a/hw/net/meson.build
+++ b/hw/net/meson.build
@@ -72,4 +72,6 @@ system_ss.add(when: 'CONFIG_ROCKER', if_true: files(
 system_ss.add(when: 'CONFIG_ALL', if_true: files('rocker/qmp-norocker.c'))
 system_ss.add(files('rocker/rocker-hmp-cmds.c'))
 
+system_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2838_genet.c'))
+
 subdir('can')
diff --git a/hw/net/trace-events b/hw/net/trace-events
index 387e32e153..4081bd09d6 100644
--- a/hw/net/trace-events
+++ b/hw/net/trace-events
@@ -494,3 +494,19 @@ xen_netdev_connect(int dev, unsigned int tx, unsigned int 
rx, int port) "vif%u t
 xen_netdev_frontend_changed(const char *dev, int state) "vif%s state %d"
 xen_netdev_tx(int dev, int ref, int off, int len, unsigned int flags, const 
char *c, const char *d, const char *m, const char *e) "vif%u ref %u off %u len 
%u flags 0x%x%s%s%s%s"
 xen_netdev_rx(int dev, int idx, int status, int flags) "vif%u idx %d status %d 
flags 0x%x"
+# bcm2838_genet.c
+bcm2838_genet_read(unsigned int size, uint64_t offset, uint64_t value) "%u 
bytes @ 0x%04" PRIx64 ": 0x%016" PRIx64
+bcm2838_genet_write(unsigned int size, uint64_t offset, uint64_t value) "%u 
bytes @ 0x%04" PRIx64 ": 0x%016" PRIx64
+bcm2838_genet_can_receive(const char *state) "receive is 

[PATCH v4 19/45] Get rid of RNG200 timer

2023-12-07 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/arm/bcm2838_peripherals.c | 14 +
 hw/arm/raspi4b.c |  1 -
 hw/misc/bcm2838_rng200.c | 78 
 include/hw/arm/bcm2838_peripherals.h |  2 +
 include/hw/misc/bcm2838_rng200.h |  4 +-
 5 files changed, 63 insertions(+), 36 deletions(-)

diff --git a/hw/arm/bcm2838_peripherals.c b/hw/arm/bcm2838_peripherals.c
index ee06214715..7c489c8e8a 100644
--- a/hw/arm/bcm2838_peripherals.c
+++ b/hw/arm/bcm2838_peripherals.c
@@ -34,6 +34,9 @@ static void bcm2838_peripherals_init(Object *obj)
bc->peri_low_size);
 sysbus_init_mmio(SYS_BUS_DEVICE(s), >peri_low_mr);
 
+/* Random Number Generator */
+object_initialize_child(obj, "rng200", >rng200, TYPE_BCM2838_RNG200);
+
 /* PCIe Host Bridge */
 object_initialize_child(obj, "pcie-host", >pcie_host,
 TYPE_BCM2838_PCIE_HOST);
@@ -85,6 +88,17 @@ static void bcm2838_peripherals_realize(DeviceState *dev, 
Error **errp)
 BCM2838_VC_PERI_LOW_BASE,
 >peri_low_mr_alias, 1);
 
+/* Random Number Generator */
+if (!sysbus_realize(SYS_BUS_DEVICE(>rng200), errp)) {
+return;
+}
+memory_region_add_subregion(
+_base->peri_mr, RNG_OFFSET,
+sysbus_mmio_get_region(SYS_BUS_DEVICE(>rng200), 0));
+sysbus_connect_irq(SYS_BUS_DEVICE(>rng200), 0,
+qdev_get_gpio_in_named(DEVICE(_base->ic), BCM2835_IC_GPU_IRQ,
+   INTERRUPT_RNG));
+
 /* Extended Mass Media Controller 2 */
 object_property_set_uint(OBJECT(>emmc2), "sd-spec-version", 3,
  _abort);
diff --git a/hw/arm/raspi4b.c b/hw/arm/raspi4b.c
index 2e8474e1c5..7b5385b8dd 100644
--- a/hw/arm/raspi4b.c
+++ b/hw/arm/raspi4b.c
@@ -67,7 +67,6 @@ static void raspi4_modify_dtb(const struct arm_boot_info 
*info, void *fdt)
 
 /* Temporarily disable following devices until they are implemented*/
 const char *to_be_removed_from_dt_as_wa[] = {
-"brcm,bcm2711-rng200",
 "brcm,bcm2711-thermal",
 "brcm,bcm2711-genet-v5",
 };
diff --git a/hw/misc/bcm2838_rng200.c b/hw/misc/bcm2838_rng200.c
index f91ea0754c..1b334b94d5 100644
--- a/hw/misc/bcm2838_rng200.c
+++ b/hw/misc/bcm2838_rng200.c
@@ -9,6 +9,7 @@
 
 #include "qemu/osdep.h"
 #include "qemu/log.h"
+#include "qom/object_interfaces.h"
 #include "qapi/error.h"
 #include "hw/qdev-properties.h"
 #include "hw/misc/bcm2838_rng200.h"
@@ -64,10 +65,7 @@ static const VMStateDescription vmstate_bcm2838_rng200 = {
 .version_id = 1,
 .minimum_version_id = 1,
 .fields = (VMStateField[]) {
-VMSTATE_UINT32(rbg_period, BCM2838Rng200State),
 VMSTATE_UINT32(rng_fifo_cap, BCM2838Rng200State),
-VMSTATE_BOOL(use_timer, BCM2838Rng200State),
-
 VMSTATE_ARRAY(regs, BCM2838Rng200State, N_BCM2838_RNG200_REGS, 0,
   vmstate_info_uint32, uint32_t),
 
@@ -90,6 +88,15 @@ static void bcm2838_rng200_update_irq(BCM2838Rng200State *s)
 !!(s->regs[R_RNG_INT_ENABLE] & s->regs[R_RNG_INT_STATUS]));
 }
 
+static void bcm2838_rng200_update_rbg_period(void *opaque, ClockEvent event)
+{
+BCM2838Rng200State *s = (BCM2838Rng200State *)opaque;
+
+ptimer_transaction_begin(s->ptimer);
+ptimer_set_period_from_clock(s->ptimer, s->clock, s->rng_fifo_cap * 8);
+ptimer_transaction_commit(s->ptimer);
+}
+
 static void bcm2838_rng200_update_fifo(void *opaque, const void *buf,
size_t size)
 {
@@ -121,18 +128,17 @@ static void bcm2838_rng200_update_fifo(void *opaque, 
const void *buf,
 if ((num == 0) && (num_bits > 0)) {
 num = 1;
 }
-if (num > 0) {
-fifo8_push_all(fifo, buf, num);
 
+fifo8_push_all(fifo, buf, num);
 
-fifo_thld = FIELD_EX32(s->regs[R_RNG_FIFO_COUNT],
-   RNG_FIFO_COUNT, THRESHOLD);
 
-if (fifo8_num_used(fifo) > fifo_thld) {
-s->regs[R_RNG_INT_STATUS] = FIELD_DP32(s->regs[R_RNG_INT_STATUS],
-   RNG_INT_STATUS,
-   TOTAL_BITS_COUNT_IRQ, 1);
-}
+fifo_thld = FIELD_EX32(s->regs[R_RNG_FIFO_COUNT],
+RNG_FIFO_COUNT, THRESHOLD);
+
+if (fifo8_num_used(fifo) > fifo_thld) {
+s->regs[R_RNG_INT_STATUS] = FIELD_DP32(s->regs[R_RNG_INT_STATUS],
+RNG_INT_STATUS,
+TOTAL_BITS_COUNT_IRQ, 1);
 }
 
 s->regs[R_RNG_FIFO_COUNT] = FIELD_DP32(s->regs[R_RNG_FIFO_COUNT],
@@ -149,9 +155,7 @@ static void bcm2838_rng200_fill_fifo(BCM2838Rng200State *s)
 bcm2838_rng200_update_fifo, s);
 }
 
-/* This function will be implemnented in upcoming commits */
-static void 

[PATCH v4 15/45] Add BCM2838 PCIE host

2023-12-07 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/arm/bcm2838_pcie.c | 216 +-
 include/hw/arm/bcm2838_pcie.h |  22 
 2 files changed, 236 insertions(+), 2 deletions(-)

diff --git a/hw/arm/bcm2838_pcie.c b/hw/arm/bcm2838_pcie.c
index 3b4373c6a6..75146d6c2e 100644
--- a/hw/arm/bcm2838_pcie.c
+++ b/hw/arm/bcm2838_pcie.c
@@ -12,11 +12,222 @@
 #include "hw/irq.h"
 #include "hw/pci-host/gpex.h"
 #include "hw/qdev-properties.h"
-#include "migration/vmstate.h"
-#include "qemu/module.h"
 #include "hw/arm/bcm2838_pcie.h"
 #include "trace.h"
 
+/*
+ * RC host part
+ */
+
+static uint64_t bcm2838_pcie_host_read(void *opaque, hwaddr offset,
+   unsigned size) {
+hwaddr mmcfg_addr;
+uint64_t value = ~0;
+BCM2838PcieHostState *s = opaque;
+PCIExpressHost *pcie_hb = PCIE_HOST_BRIDGE(s);
+PCIDevice *root_pci_dev = PCI_DEVICE(>root_port);
+uint8_t *root_regs = s->root_port.regs;
+uint32_t *cfg_idx = (uint32_t *)(root_regs + BCM2838_PCIE_EXT_CFG_INDEX
+ - PCIE_CONFIG_SPACE_SIZE);
+
+if (offset < PCIE_CONFIG_SPACE_SIZE) {
+value = pci_host_config_read_common(root_pci_dev, offset,
+PCIE_CONFIG_SPACE_SIZE, size);
+} else if (offset - PCIE_CONFIG_SPACE_SIZE + size
+   <= sizeof(s->root_port.regs)) {
+switch (offset) {
+case BCM2838_PCIE_EXT_CFG_DATA
+... BCM2838_PCIE_EXT_CFG_DATA + PCIE_CONFIG_SPACE_SIZE - 1:
+mmcfg_addr = *cfg_idx
+| PCIE_MMCFG_CONFOFFSET(offset - BCM2838_PCIE_EXT_CFG_DATA);
+value = pcie_hb->mmio.ops->read(opaque, mmcfg_addr, size);
+break;
+default:
+memcpy(, root_regs + offset - PCIE_CONFIG_SPACE_SIZE, size);
+}
+} else {
+qemu_log_mask(
+LOG_GUEST_ERROR,
+"%s: out-of-range access, %u bytes @ offset 0x%04" PRIx64 "\n",
+__func__, size, offset);
+}
+
+trace_bcm2838_pcie_host_read(size, offset, value);
+return value;
+}
+
+static void bcm2838_pcie_host_write(void *opaque, hwaddr offset,
+uint64_t value, unsigned size) {
+hwaddr mmcfg_addr;
+BCM2838PcieHostState *s = opaque;
+PCIExpressHost *pcie_hb = PCIE_HOST_BRIDGE(s);
+PCIDevice *root_pci_dev = PCI_DEVICE(>root_port);
+uint8_t *root_regs = s->root_port.regs;
+uint32_t *cfg_idx = (uint32_t *)(root_regs + BCM2838_PCIE_EXT_CFG_INDEX
+ - PCIE_CONFIG_SPACE_SIZE);
+
+trace_bcm2838_pcie_host_write(size, offset, value);
+
+if (offset < PCIE_CONFIG_SPACE_SIZE) {
+pci_host_config_write_common(root_pci_dev, offset,
+ PCIE_CONFIG_SPACE_SIZE, value, size);
+} else if (offset - PCIE_CONFIG_SPACE_SIZE + size
+   <= sizeof(s->root_port.regs)) {
+switch (offset) {
+case BCM2838_PCIE_EXT_CFG_DATA
+... BCM2838_PCIE_EXT_CFG_DATA + PCIE_CONFIG_SPACE_SIZE - 1:
+mmcfg_addr = *cfg_idx
+| PCIE_MMCFG_CONFOFFSET(offset - BCM2838_PCIE_EXT_CFG_DATA);
+pcie_hb->mmio.ops->write(opaque, mmcfg_addr, value, size);
+break;
+default:
+memcpy(root_regs + offset - PCIE_CONFIG_SPACE_SIZE, , size);
+}
+} else {
+qemu_log_mask(
+LOG_GUEST_ERROR,
+"%s: out-of-range access, %u bytes @ offset 0x%04" PRIx64 "\n",
+__func__, size, offset);
+}
+}
+
+static const MemoryRegionOps bcm2838_pcie_host_ops = {
+.read = bcm2838_pcie_host_read,
+.write = bcm2838_pcie_host_write,
+.endianness = DEVICE_NATIVE_ENDIAN,
+.impl = {.max_access_size = sizeof(uint64_t)},
+};
+
+int bcm2838_pcie_host_set_irq_num(BCM2838PcieHostState *s, int index, int spi)
+{
+if (index >= BCM2838_PCIE_NUM_IRQS) {
+return -EINVAL;
+}
+
+s->irq_num[index] = spi;
+return 0;
+}
+
+static void bcm2838_pcie_host_set_irq(void *opaque, int irq_num, int level)
+{
+BCM2838PcieHostState *s = opaque;
+
+qemu_set_irq(s->irq[irq_num], level);
+}
+
+static PCIINTxRoute bcm2838_pcie_host_route_intx_pin_to_irq(void *opaque,
+int pin)
+{
+PCIINTxRoute route;
+BCM2838PcieHostState *s = opaque;
+
+route.irq = s->irq_num[pin];
+route.mode = route.irq < 0 ? PCI_INTX_DISABLED : PCI_INTX_ENABLED;
+
+return route;
+}
+
+static int bcm2838_pcie_host_map_irq(PCIDevice *pci_dev, int pin)
+{
+return pin;
+}
+
+static void bcm2838_pcie_host_realize(DeviceState *dev, Error **errp)
+{
+PCIHostState *pci = PCI_HOST_BRIDGE(dev);
+BCM2838PcieHostState *s = BCM2838_PCIE_HOST(dev);
+SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+
+int i;
+
+memory_region_init_io(>cfg_regs, OBJECT(s), _pcie_host_ops, s,
+  

[PATCH v4 08/45] Connect SD controller to BCM2838 GPIO

2023-12-07 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/gpio/bcm2838_gpio.c | 59 +++---
 include/hw/gpio/bcm2838_gpio.h |  5 +++
 2 files changed, 60 insertions(+), 4 deletions(-)

diff --git a/hw/gpio/bcm2838_gpio.c b/hw/gpio/bcm2838_gpio.c
index 51eb55b00a..f166ce7959 100644
--- a/hw/gpio/bcm2838_gpio.c
+++ b/hw/gpio/bcm2838_gpio.c
@@ -17,9 +17,10 @@
 #include "qemu/timer.h"
 #include "qapi/error.h"
 #include "hw/sysbus.h"
-#include "migration/vmstate.h"
+#include "hw/sd/sd.h"
 #include "hw/gpio/bcm2838_gpio.h"
 #include "hw/irq.h"
+#include "migration/vmstate.h"
 
 #define GPFSEL0   0x00
 #define GPFSEL1   0x04
@@ -64,6 +65,16 @@
 
 #define BYTES_IN_WORD4
 
+/* bcm,function property */
+#define BCM2838_FSEL_GPIO_IN0
+#define BCM2838_FSEL_GPIO_OUT   1
+#define BCM2838_FSEL_ALT5   2
+#define BCM2838_FSEL_ALT4   3
+#define BCM2838_FSEL_ALT0   4
+#define BCM2838_FSEL_ALT1   5
+#define BCM2838_FSEL_ALT2   6
+#define BCM2838_FSEL_ALT3   7
+
 static uint32_t gpfsel_get(BCM2838GpioState *s, uint8_t reg)
 {
 int i;
@@ -87,6 +98,31 @@ static void gpfsel_set(BCM2838GpioState *s, uint8_t reg, 
uint32_t value)
 s->fsel[index] = fsel;
 }
 }
+
+/* SD controller selection (48-53) */
+if (s->sd_fsel != BCM2838_FSEL_GPIO_IN
+&& (s->fsel[48] == BCM2838_FSEL_GPIO_IN)
+&& (s->fsel[49] == BCM2838_FSEL_GPIO_IN)
+&& (s->fsel[50] == BCM2838_FSEL_GPIO_IN)
+&& (s->fsel[51] == BCM2838_FSEL_GPIO_IN)
+&& (s->fsel[52] == BCM2838_FSEL_GPIO_IN)
+&& (s->fsel[53] == BCM2838_FSEL_GPIO_IN)
+   ) {
+/* SDHCI controller selected */
+sdbus_reparent_card(s->sdbus_sdhost, s->sdbus_sdhci);
+s->sd_fsel = BCM2838_FSEL_GPIO_IN;
+} else if (s->sd_fsel != BCM2838_FSEL_ALT0
+   && (s->fsel[48] == BCM2838_FSEL_ALT0) /* SD_CLK_R */
+   && (s->fsel[49] == BCM2838_FSEL_ALT0) /* SD_CMD_R */
+   && (s->fsel[50] == BCM2838_FSEL_ALT0) /* SD_DATA0_R */
+   && (s->fsel[51] == BCM2838_FSEL_ALT0) /* SD_DATA1_R */
+   && (s->fsel[52] == BCM2838_FSEL_ALT0) /* SD_DATA2_R */
+   && (s->fsel[53] == BCM2838_FSEL_ALT0) /* SD_DATA3_R */
+  ) {
+/* SDHost controller selected */
+sdbus_reparent_card(s->sdbus_sdhci, s->sdbus_sdhost);
+s->sd_fsel = BCM2838_FSEL_ALT0;
+}
 }
 
 static int gpfsel_is_out(BCM2838GpioState *s, int index)
@@ -266,6 +302,11 @@ static void bcm2838_gpio_reset(DeviceState *dev)
 
 memset(s->fsel, 0, sizeof(s->fsel));
 
+s->sd_fsel = 0;
+
+/* SDHCI is selected by default */
+sdbus_reparent_card(>sdbus, s->sdbus_sdhci);
+
 s->lev0 = 0;
 s->lev1 = 0;
 
@@ -302,15 +343,25 @@ static void bcm2838_gpio_init(Object *obj)
 DeviceState *dev = DEVICE(obj);
 SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
 
-memory_region_init_io(>iomem, obj, _gpio_ops, s,
-  "bcm2838_gpio", BCM2838_GPIO_REGS_SIZE);
+qbus_init(>sdbus, sizeof(s->sdbus), TYPE_SD_BUS, DEVICE(s), "sd-bus");
+
+memory_region_init_io(
+>iomem, obj,
+_gpio_ops, s, "bcm2838_gpio", BCM2838_GPIO_REGS_SIZE);
 sysbus_init_mmio(sbd, >iomem);
 qdev_init_gpio_out(dev, s->out, BCM2838_GPIO_NUM);
 }
 
 static void bcm2838_gpio_realize(DeviceState *dev, Error **errp)
 {
-/* Temporary stub. Do nothing */
+BCM2838GpioState *s = BCM2838_GPIO(dev);
+Object *obj;
+
+obj = object_property_get_link(OBJECT(dev), "sdbus-sdhci", _abort);
+s->sdbus_sdhci = SD_BUS(obj);
+
+obj = object_property_get_link(OBJECT(dev), "sdbus-sdhost", _abort);
+s->sdbus_sdhost = SD_BUS(obj);
 }
 
 static void bcm2838_gpio_class_init(ObjectClass *klass, void *data)
diff --git a/include/hw/gpio/bcm2838_gpio.h b/include/hw/gpio/bcm2838_gpio.h
index 06d48e0c19..f2a57a697f 100644
--- a/include/hw/gpio/bcm2838_gpio.h
+++ b/include/hw/gpio/bcm2838_gpio.h
@@ -14,6 +14,7 @@
 #ifndef BCM2838_GPIO_H
 #define BCM2838_GPIO_H
 
+#include "hw/sd/sd.h"
 #include "hw/sysbus.h"
 #include "qom/object.h"
 
@@ -29,6 +30,10 @@ struct BCM2838GpioState {
 
 MemoryRegion iomem;
 
+/* SDBus selector */
+SDBus sdbus;
+SDBus *sdbus_sdhci;
+SDBus *sdbus_sdhost;
 
 uint8_t fsel[BCM2838_GPIO_NUM];
 uint32_t lev0, lev1;
-- 
2.34.1




[PATCH v4 07/45] Implement BCM2838 GPIO functionality

2023-12-07 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/gpio/bcm2838_gpio.c | 192 -
 1 file changed, 189 insertions(+), 3 deletions(-)

diff --git a/hw/gpio/bcm2838_gpio.c b/hw/gpio/bcm2838_gpio.c
index 15b66cb559..51eb55b00a 100644
--- a/hw/gpio/bcm2838_gpio.c
+++ b/hw/gpio/bcm2838_gpio.c
@@ -19,6 +19,7 @@
 #include "hw/sysbus.h"
 #include "migration/vmstate.h"
 #include "hw/gpio/bcm2838_gpio.h"
+#include "hw/irq.h"
 
 #define GPFSEL0   0x00
 #define GPFSEL1   0x04
@@ -57,14 +58,139 @@
 #define RESET_VAL_CNTRL_REG2 0x50AAA95A;
 #define RESET_VAL_CNTRL_REG3 0x0005;
 
+#define NUM_FSELN_IN_GPFSELN 10
+#define NUM_BITS_FSELN   3
+#define MASK_FSELN   0x7
+
 #define BYTES_IN_WORD4
 
+static uint32_t gpfsel_get(BCM2838GpioState *s, uint8_t reg)
+{
+int i;
+uint32_t value = 0;
+for (i = 0; i < NUM_FSELN_IN_GPFSELN; i++) {
+uint32_t index = NUM_FSELN_IN_GPFSELN * reg + i;
+if (index < sizeof(s->fsel)) {
+value |= (s->fsel[index] & MASK_FSELN) << (NUM_BITS_FSELN * i);
+}
+}
+return value;
+}
+
+static void gpfsel_set(BCM2838GpioState *s, uint8_t reg, uint32_t value)
+{
+int i;
+for (i = 0; i < NUM_FSELN_IN_GPFSELN; i++) {
+uint32_t index = NUM_FSELN_IN_GPFSELN * reg + i;
+if (index < sizeof(s->fsel)) {
+int fsel = (value >> (NUM_BITS_FSELN * i)) & MASK_FSELN;
+s->fsel[index] = fsel;
+}
+}
+}
+
+static int gpfsel_is_out(BCM2838GpioState *s, int index)
+{
+if (index >= 0 && index < BCM2838_GPIO_NUM) {
+return s->fsel[index] == 1;
+}
+return 0;
+}
+
+static void gpset(BCM2838GpioState *s, uint32_t val, uint8_t start,
+  uint8_t count, uint32_t *lev)
+{
+uint32_t changes = val & ~*lev;
+uint32_t cur = 1;
+
+int i;
+for (i = 0; i < count; i++) {
+if ((changes & cur) && (gpfsel_is_out(s, start + i))) {
+qemu_set_irq(s->out[start + i], 1);
+}
+cur <<= 1;
+}
+
+*lev |= val;
+}
+
+static void gpclr(BCM2838GpioState *s, uint32_t val, uint8_t start,
+  uint8_t count, uint32_t *lev)
+{
+uint32_t changes = val & *lev;
+uint32_t cur = 1;
+
+int i;
+for (i = 0; i < count; i++) {
+if ((changes & cur) && (gpfsel_is_out(s, start + i))) {
+qemu_set_irq(s->out[start + i], 0);
+}
+cur <<= 1;
+}
+
+*lev &= ~val;
+}
+
 static uint64_t bcm2838_gpio_read(void *opaque, hwaddr offset, unsigned size)
 {
+BCM2838GpioState *s = (BCM2838GpioState *)opaque;
 uint64_t value = 0;
 
-qemu_log_mask(LOG_UNIMP, "%s: %s: not implemented for %"HWADDR_PRIx"\n",
-  TYPE_BCM2838_GPIO, __func__, offset);
+switch (offset) {
+case GPFSEL0:
+case GPFSEL1:
+case GPFSEL2:
+case GPFSEL3:
+case GPFSEL4:
+case GPFSEL5:
+value = gpfsel_get(s, offset / BYTES_IN_WORD);
+break;
+case GPSET0:
+case GPSET1:
+case GPCLR0:
+case GPCLR1:
+/* Write Only */
+qemu_log_mask(LOG_GUEST_ERROR, "%s: %s: Attempt reading from write 
only"
+  " register. %lu will be returned. Address 0x%"HWADDR_PRIx
+  ", size %u\n", TYPE_BCM2838_GPIO, __func__, value, 
offset,
+  size);
+break;
+case GPLEV0:
+value = s->lev0;
+break;
+case GPLEV1:
+value = s->lev1;
+break;
+case GPEDS0:
+case GPEDS1:
+case GPREN0:
+case GPREN1:
+case GPFEN0:
+case GPFEN1:
+case GPHEN0:
+case GPHEN1:
+case GPLEN0:
+case GPLEN1:
+case GPAREN0:
+case GPAREN1:
+case GPAFEN0:
+case GPAFEN1:
+/* Not implemented */
+qemu_log_mask(LOG_UNIMP, "%s: %s: not implemented for 
%"HWADDR_PRIx"\n",
+  TYPE_BCM2838_GPIO, __func__, offset);
+break;
+case GPIO_PUP_PDN_CNTRL_REG0:
+case GPIO_PUP_PDN_CNTRL_REG1:
+case GPIO_PUP_PDN_CNTRL_REG2:
+case GPIO_PUP_PDN_CNTRL_REG3:
+value = s->pup_cntrl_reg[(offset - GPIO_PUP_PDN_CNTRL_REG0)
+ / sizeof(s->pup_cntrl_reg[0])];
+break;
+default:
+qemu_log_mask(LOG_GUEST_ERROR, "%s: %s: bad offset %"HWADDR_PRIx"\n",
+  TYPE_BCM2838_GPIO, __func__, offset);
+break;
+}
 
 return value;
 }
@@ -72,14 +198,74 @@ static uint64_t bcm2838_gpio_read(void *opaque, hwaddr 
offset, unsigned size)
 static void bcm2838_gpio_write(void *opaque, hwaddr offset, uint64_t value,
unsigned size)
 {
-qemu_log_mask(LOG_UNIMP, "%s: %s: not implemented for %"HWADDR_PRIx"\n",
+BCM2838GpioState *s = (BCM2838GpioState *)opaque;
+
+switch (offset) {
+case GPFSEL0:
+case GPFSEL1:
+case GPFSEL2:
+case GPFSEL3:
+case GPFSEL4:
+case GPFSEL5:
+gpfsel_set(s, offset / BYTES_IN_WORD, value);
+break;
+

[PATCH v4 12/45] Temporarily disable unimplemented rpi4b devices

2023-12-07 Thread Sergey Kambalin
This commit adds RPi4B device tree modifications:
- disable pcie, rng200, thermal sensor and genet devices
  (they're going to be re-enabled in the following commits)
- create additional memory region in device tree
  if RAM amount exceeds VC base address.

Signed-off-by: Sergey Kambalin 
---
 hw/arm/raspi.c  |  5 +--
 hw/arm/raspi4b.c| 60 +
 include/hw/arm/raspi_platform.h |  4 +++
 3 files changed, 65 insertions(+), 4 deletions(-)

diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
index da1e9e7c13..895c305122 100644
--- a/hw/arm/raspi.c
+++ b/hw/arm/raspi.c
@@ -37,9 +37,6 @@ OBJECT_DECLARE_SIMPLE_TYPE(RaspiMachineState, RASPI_MACHINE)
 #define FIRMWARE_ADDR_3 0x8 /* Pi 3 loads kernel.img here by default */
 #define SPINTABLE_ADDR  0xd8 /* Pi 3 bootloader spintable */
 
-/* Registered machine type (matches RPi Foundation bootloader and U-Boot) */
-#define MACH_TYPE_BCM2708   3138
-
 struct RaspiMachineState {
 /*< private >*/
 RaspiBaseMachineState parent_obj;
@@ -75,7 +72,7 @@ static const struct {
 [PROCESSOR_ID_BCM2838] = {TYPE_BCM2838, BCM283X_NCPUS},
 };
 
-static uint64_t board_ram_size(uint32_t board_rev)
+uint64_t board_ram_size(uint32_t board_rev)
 {
 assert(FIELD_EX32(board_rev, REV_CODE, STYLE)); /* Only new style */
 return 256 * MiB << FIELD_EX32(board_rev, REV_CODE, MEMORY_SIZE);
diff --git a/hw/arm/raspi4b.c b/hw/arm/raspi4b.c
index 2d33861c57..10376b62dc 100644
--- a/hw/arm/raspi4b.c
+++ b/hw/arm/raspi4b.c
@@ -21,6 +21,7 @@
 #include "hw/arm/boot.h"
 #include "qom/object.h"
 #include "hw/arm/bcm2838.h"
+#include 
 
 #define TYPE_RASPI4B_MACHINE MACHINE_TYPE_NAME("raspi4b-2g")
 OBJECT_DECLARE_SIMPLE_TYPE(Raspi4bMachineState, RASPI4B_MACHINE)
@@ -32,6 +33,64 @@ struct Raspi4bMachineState {
 BCM2838State soc;
 };
 
+/* Add second memory region if board RAM amount exceeds VC base address
+ * (see https://datasheets.raspberrypi.com/bcm2711/bcm2711-peripherals.pdf
+ * 1.2 Address Map)
+ */
+static int raspi_add_memory_node(void *fdt, hwaddr mem_base, hwaddr mem_len)
+{
+int ret;
+uint32_t acells, scells;
+char *nodename = g_strdup_printf("/memory@%" PRIx64, mem_base);
+
+acells = qemu_fdt_getprop_cell(fdt, "/", "#address-cells",
+   NULL, _fatal);
+scells = qemu_fdt_getprop_cell(fdt, "/", "#size-cells",
+   NULL, _fatal);
+if (acells == 0 || scells == 0) {
+fprintf(stderr, "dtb file invalid (#address-cells or #size-cells 
0)\n");
+ret = -1;
+} else {
+qemu_fdt_add_subnode(fdt, nodename);
+qemu_fdt_setprop_string(fdt, nodename, "device_type", "memory");
+ret = qemu_fdt_setprop_sized_cells(fdt, nodename, "reg",
+   acells, mem_base,
+   scells, mem_len);
+}
+
+g_free(nodename);
+return ret;
+}
+
+static void raspi4_modify_dtb(const struct arm_boot_info *info, void *fdt)
+{
+
+/* Temporarily disable following devices until they are implemented*/
+const char *to_be_removed_from_dt_as_wa[] = {
+"brcm,bcm2711-pcie",
+"brcm,bcm2711-rng200",
+"brcm,bcm2711-thermal",
+"brcm,bcm2711-genet-v5",
+};
+
+for (int i = 0; i < ARRAY_SIZE(to_be_removed_from_dt_as_wa); i++) {
+const char *dev_str = to_be_removed_from_dt_as_wa[i];
+
+int offset = fdt_node_offset_by_compatible(fdt, -1, dev_str);
+if (offset >= 0) {
+if (!fdt_nop_node(fdt, offset)) {
+warn_report("bcm2711 dtc: %s has been disabled!", dev_str);
+}
+}
+}
+
+uint64_t ram_size = board_ram_size(info->board_id);
+
+if (info->ram_size > UPPER_RAM_BASE) {
+raspi_add_memory_node(fdt, UPPER_RAM_BASE, ram_size - UPPER_RAM_BASE);
+}
+}
+
 static void raspi4b_machine_init(MachineState *machine)
 {
 Raspi4bMachineState *s = RASPI4B_MACHINE(machine);
@@ -39,6 +98,7 @@ static void raspi4b_machine_init(MachineState *machine)
 RaspiBaseMachineClass *mc = RASPI_BASE_MACHINE_GET_CLASS(machine);
 BCM2838State *soc = >soc;
 
+s_base->binfo.modify_dtb = raspi4_modify_dtb;
 s_base->binfo.board_id = mc->board_rev;
 
 object_initialize_child(OBJECT(machine), "soc", soc,
diff --git a/include/hw/arm/raspi_platform.h b/include/hw/arm/raspi_platform.h
index 45003e2425..0db146e592 100644
--- a/include/hw/arm/raspi_platform.h
+++ b/include/hw/arm/raspi_platform.h
@@ -31,6 +31,9 @@
 #include "hw/boards.h"
 #include "hw/arm/boot.h"
 
+/* Registered machine type (matches RPi Foundation bootloader and U-Boot) */
+#define MACH_TYPE_BCM2708   3138
+
 #define TYPE_RASPI_BASE_MACHINE MACHINE_TYPE_NAME("raspi-base")
 OBJECT_DECLARE_TYPE(RaspiBaseMachineState, RaspiBaseMachineClass,
 RASPI_BASE_MACHINE)
@@ -59,6 +62,7 @@ void raspi_base_machine_init(MachineState *machine,
 
 void 

[PATCH v4 05/45] Add GIC-400 to BCM2838 SoC

2023-12-07 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/arm/bcm2838.c | 167 +++
 hw/arm/trace-events  |   2 +
 include/hw/arm/bcm2838.h |   2 +
 include/hw/arm/bcm2838_peripherals.h |  39 +++
 4 files changed, 210 insertions(+)

diff --git a/hw/arm/bcm2838.c b/hw/arm/bcm2838.c
index c61c59661b..042e543006 100644
--- a/hw/arm/bcm2838.c
+++ b/hw/arm/bcm2838.c
@@ -14,8 +14,36 @@
 #include "hw/arm/bcm2838.h"
 #include "trace.h"
 
+#define GIC400_MAINTAINANCE_IRQ  9
+#define GIC400_TIMER_NS_EL2_IRQ 10
+#define GIC400_TIMER_VIRT_IRQ   11
+#define GIC400_LEGACY_FIQ   12
+#define GIC400_TIMER_S_EL1_IRQ  13
+#define GIC400_TIMER_NS_EL1_IRQ 14
+#define GIC400_LEGACY_IRQ   15
+
+/* Number of external interrupt lines to configure the GIC with */
+#define GIC_NUM_IRQS192
+
+#define PPI(cpu, irq) (GIC_NUM_IRQS + (cpu) * GIC_INTERNAL + GIC_NR_SGIS + irq)
+
+#define GIC_BASE_OFS0x
+#define GIC_DIST_OFS0x1000
+#define GIC_CPU_OFS 0x2000
+#define GIC_VIFACE_THIS_OFS 0x4000
+#define GIC_VIFACE_OTHER_OFS(cpu)  (0x5000 + (cpu) * 0x200)
+#define GIC_VCPU_OFS0x6000
+
 #define VIRTUAL_PMU_IRQ 7
 
+static void bcm2838_gic_set_irq(void *opaque, int irq, int level)
+{
+BCM2838State *s = (BCM2838State *)opaque;
+
+trace_bcm2838_gic_set_irq(irq, level);
+qemu_set_irq(qdev_get_gpio_in(DEVICE(>gic), irq), level);
+}
+
 static void bcm2838_init(Object *obj)
 {
 BCM2838State *s = BCM2838(obj);
@@ -28,11 +56,14 @@ static void bcm2838_init(Object *obj)
   "vcram-size");
 object_property_add_alias(obj, "command-line", OBJECT(>peripherals),
   "command-line");
+
+object_initialize_child(obj, "gic", >gic, TYPE_ARM_GIC);
 }
 
 static void bcm2838_realize(DeviceState *dev, Error **errp)
 {
 int n;
+int int_n;
 BCM2838State *s = BCM2838(dev);
 BCM283XBaseState *s_base = BCM283X_BASE(dev);
 BCM283XBaseClass *bc_base = BCM283X_BASE_GET_CLASS(dev);
@@ -56,6 +87,13 @@ static void bcm2838_realize(DeviceState *dev, Error **errp)
 /* TODO: this should be converted to a property of ARM_CPU */
 s_base->cpu[n].core.mp_affinity = (bc_base->clusterid << 8) | n;
 
+/* set periphbase/CBAR value for CPU-local registers */
+if (!object_property_set_int(OBJECT(_base->cpu[n].core), 
"reset-cbar",
+ bc_base->ctrl_base + BCM2838_GIC_BASE,
+ errp)) {
+return;
+}
+
 /* start powered off if not enabled */
 if (!object_property_set_bool(OBJECT(_base->cpu[n].core),
   "start-powered-off",
@@ -68,6 +106,135 @@ static void bcm2838_realize(DeviceState *dev, Error **errp)
 return;
 }
 }
+
+if (!object_property_set_uint(OBJECT(>gic), "revision", 2, errp)) {
+return;
+}
+
+if (!object_property_set_uint(OBJECT(>gic), "num-cpu", BCM283X_NCPUS,
+  errp)) {
+return;
+}
+
+if (!object_property_set_uint(OBJECT(>gic), "num-irq",
+  GIC_NUM_IRQS + GIC_INTERNAL, errp)) {
+return;
+}
+
+if (!object_property_set_bool(OBJECT(>gic),
+  "has-virtualization-extensions", true,
+  errp)) {
+return;
+}
+
+if (!sysbus_realize(SYS_BUS_DEVICE(>gic), errp)) {
+return;
+}
+
+sysbus_mmio_map(SYS_BUS_DEVICE(>gic), 0,
+bc_base->ctrl_base + BCM2838_GIC_BASE + GIC_DIST_OFS);
+sysbus_mmio_map(SYS_BUS_DEVICE(>gic), 1,
+bc_base->ctrl_base + BCM2838_GIC_BASE + GIC_CPU_OFS);
+sysbus_mmio_map(SYS_BUS_DEVICE(>gic), 2,
+bc_base->ctrl_base + BCM2838_GIC_BASE + 
GIC_VIFACE_THIS_OFS);
+sysbus_mmio_map(SYS_BUS_DEVICE(>gic), 3,
+bc_base->ctrl_base + BCM2838_GIC_BASE + GIC_VCPU_OFS);
+
+for (n = 0; n < BCM283X_NCPUS; n++) {
+sysbus_mmio_map(SYS_BUS_DEVICE(>gic), 4 + n,
+bc_base->ctrl_base + BCM2838_GIC_BASE
++ GIC_VIFACE_OTHER_OFS(n));
+}
+
+DeviceState *gicdev = DEVICE(>gic);
+
+for (n = 0; n < BCM283X_NCPUS; n++) {
+DeviceState *cpudev = DEVICE(_base->cpu[n]);
+
+/* Connect the GICv2 outputs to the CPU */
+sysbus_connect_irq(SYS_BUS_DEVICE(>gic), n,
+   qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
+sysbus_connect_irq(SYS_BUS_DEVICE(>gic), n + BCM283X_NCPUS,
+   qdev_get_gpio_in(cpudev, ARM_CPU_FIQ));
+sysbus_connect_irq(SYS_BUS_DEVICE(>gic), n + 2 * BCM283X_NCPUS,
+   qdev_get_gpio_in(cpudev, ARM_CPU_VIRQ));
+sysbus_connect_irq(SYS_BUS_DEVICE(>gic), n 

[PATCH v4 00/45] Raspberry Pi 4B machine

2023-12-07 Thread Sergey Kambalin
Introducing Raspberry Pi 4B model.
It contains new BCM2838 SoC, PCIE subsystem,
RNG200, Thermal sensor and Genet network controller.

It can work with recent linux kernels 6.x.x.
Two avocado tests was added to check that.

Unit tests has been made as read/write operations
via mailbox properties.

Genet integration test is under development.

Every single commit
1) builds without errors
2) passes regression tests
3) passes style check*
*the only exception is bcm2838-mbox-property-test.c file
containing heavy macros usage which cause a lot of
false-positives of checkpatch.pl.

I did my best to keep the commits less than 200 changes,
but had to make some of them a bit more in order to
keep their integrity.

This is v2 patchset with the most of v1 remarks fixed.
I named it as 'v4' because of mistakes while attempts to send previous patchsets
Please ignore all other v1...v3 patchsets except the very first one.

Sergey Kambalin (45):
  Split out common part of BCM283X classes
  Split out common part of peripherals
  Split out raspi machine common part
  Introduce BCM2838 SoC
  Add GIC-400 to BCM2838 SoC
  Add BCM2838 GPIO stub
  Implement BCM2838 GPIO functionality
  Connect SD controller to BCM2838 GPIO
  Add GPIO and SD to BCM2838 periph
  Add BCM2838 checkpoint support
  Introduce Raspberry PI 4 machine
  Temporarily disable unimplemented rpi4b devices
  Add memory region for BCM2837 RPiVid ASB
  Add BCM2838 PCIE Root Complex
  Add BCM2838 PCIE host
  Enable BCM2838 PCIE
  Add RNG200 skeleton
  Add RNG200 RNG and RBG
  Get rid of RNG200 timer
  Implement BCM2838 thermal sensor
  Add clock_isp stub
  Add GENET stub
  Add GENET register structs. Part 1
  Add GENET register structs. Part 2
  Add GENET register structs. Part 3
  Add GENET register structs. Part 4
  Add GENET register access macros
  Implement GENET register ops
  Implement GENET MDIO
  Implement GENET TX path
  Implement GENET RX path
  Enable BCM2838 GENET controller
  Connect RNG200, PCIE and GENET to GIC
  Add Rpi4b boot tests
  Add mailbox test stub
  Add mailbox test constants
  Add mailbox tests tags. Part 1
  Add mailbox tests tags. Part 2
  Add mailbox tests tags. Part 3
  Add mailbox property tests. Part 1
  Add mailbox property tests. Part 2
  Add mailbox property tests. Part 3
  Add missed BCM2835 properties
  Append added properties to mailbox test
  Add RPi4B to paspi4.rst

 docs/system/arm/raspi.rst|   11 +-
 hw/arm/bcm2835_peripherals.c |  218 +++--
 hw/arm/bcm2836.c |  116 ++-
 hw/arm/bcm2838.c |  288 ++
 hw/arm/bcm2838_pcie.c|  289 ++
 hw/arm/bcm2838_peripherals.c |  292 ++
 hw/arm/meson.build   |8 +-
 hw/arm/raspi.c   |  131 +--
 hw/arm/raspi4b.c |  112 +++
 hw/arm/trace-events  |6 +
 hw/gpio/bcm2838_gpio.c   |  389 
 hw/gpio/meson.build  |5 +-
 hw/misc/bcm2835_property.c   |   47 +
 hw/misc/bcm2838_rng200.c |  420 +
 hw/misc/bcm2838_thermal.c|   98 ++
 hw/misc/meson.build  |2 +
 hw/misc/trace-events |9 +
 hw/net/bcm2838_genet.c   | 1088 ++
 hw/net/meson.build   |2 +
 hw/net/trace-events  |   16 +
 include/hw/arm/bcm2835_peripherals.h |   29 +-
 include/hw/arm/bcm2836.h |   27 +-
 include/hw/arm/bcm2838.h |   31 +
 include/hw/arm/bcm2838_pcie.h|   75 ++
 include/hw/arm/bcm2838_peripherals.h |   97 ++
 include/hw/arm/raspberrypi-fw-defs.h |   12 +-
 include/hw/arm/raspi_platform.h  |   37 +
 include/hw/display/bcm2835_fb.h  |2 +
 include/hw/gpio/bcm2838_gpio.h   |   45 +
 include/hw/misc/bcm2838_rng200.h |   43 +
 include/hw/misc/bcm2838_thermal.h|   24 +
 include/hw/net/bcm2838_genet.h   |  426 +
 tests/avocado/boot_linux_console.py  |   92 ++
 tests/qtest/bcm2838-mailbox.c|   61 ++
 tests/qtest/bcm2838-mailbox.h|  584 
 tests/qtest/bcm2838-mbox-property-test.c |  621 
 tests/qtest/meson.build  |3 +-
 37 files changed, 5551 insertions(+), 205 deletions(-)
 create mode 100644 hw/arm/bcm2838.c
 create mode 100644 hw/arm/bcm2838_pcie.c
 create mode 100644 hw/arm/bcm2838_peripherals.c
 create mode 100644 hw/arm/raspi4b.c
 create mode 100644 hw/gpio/bcm2838_gpio.c
 create mode 100644 hw/misc/bcm2838_rng200.c
 create mode 100644 hw/misc/bcm2838_thermal.c
 create mode 100644 hw/net/bcm2838_genet.c
 create mode 100644 include/hw/arm/bcm2838.h
 create mode 100644 include/hw/arm/bcm2838_pcie.h
 create mode 100644 include/hw/arm/bcm2838_peripherals.h
 create mode 100644 include/hw/gpio/bcm2838_gpio.h
 create mode 

[PATCH v4 14/45] Add BCM2838 PCIE Root Complex

2023-12-07 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/arm/bcm2838_pcie.c | 74 +++
 hw/arm/meson.build|  5 ++-
 hw/arm/trace-events   |  4 ++
 include/hw/arm/bcm2838_pcie.h | 53 +
 4 files changed, 135 insertions(+), 1 deletion(-)
 create mode 100644 hw/arm/bcm2838_pcie.c
 create mode 100644 include/hw/arm/bcm2838_pcie.h

diff --git a/hw/arm/bcm2838_pcie.c b/hw/arm/bcm2838_pcie.c
new file mode 100644
index 00..3b4373c6a6
--- /dev/null
+++ b/hw/arm/bcm2838_pcie.c
@@ -0,0 +1,74 @@
+/*
+ * BCM2838 PCIe Root Complex emulation
+ *
+ * Copyright (C) 2022 Ovchinnikov Vitalii 
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qapi/error.h"
+#include "hw/irq.h"
+#include "hw/pci-host/gpex.h"
+#include "hw/qdev-properties.h"
+#include "migration/vmstate.h"
+#include "qemu/module.h"
+#include "hw/arm/bcm2838_pcie.h"
+#include "trace.h"
+
+/*
+ * RC root part (D0:F0)
+ */
+
+static void bcm2838_pcie_root_reg_reset(PCIDevice *dev)
+{
+BCM2838PcieRootState *s = BCM2838_PCIE_ROOT(dev);
+memset(s->regs, 0xFF, sizeof(s->regs));
+}
+
+static void bcm2838_pcie_root_realize(PCIDevice *dev, Error **errp) {
+bcm2838_pcie_root_reg_reset(dev);
+}
+
+static void bcm2838_pcie_root_init(Object *obj)
+{
+PCIBridge *br = PCI_BRIDGE(obj);
+br->bus_name = "pcie.1";
+}
+
+static void bcm2838_pcie_root_class_init(ObjectClass *class, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(class);
+PCIDeviceClass *k = PCI_DEVICE_CLASS(class);
+BCM2838PcieRootClass *brpc = BCM2838_PCIE_ROOT_CLASS(class);
+
+dc->desc = "BCM2711 PCIe Bridge";
+/*
+ * PCI-facing part of the host bridge, not usable without the host-facing
+ * part, which can't be device_add'ed.
+ */
+dc->user_creatable = false;
+k->vendor_id = BCM2838_PCIE_VENDOR_ID;
+k->device_id = BCM2838_PCIE_DEVICE_ID;
+k->revision = BCM2838_PCIE_REVISION;
+brpc->parent_obj.exp_offset = BCM2838_PCIE_EXP_CAP_OFFSET;
+brpc->parent_obj.aer_offset = BCM2838_PCIE_AER_CAP_OFFSET;
+brpc->parent_realize = k->realize;
+k->realize = bcm2838_pcie_root_realize;
+}
+
+static const TypeInfo bcm2838_pcie_root_info = {
+.name = TYPE_BCM2838_PCIE_ROOT,
+.parent = TYPE_PCIE_ROOT_PORT,
+.instance_size = sizeof(BCM2838PcieRootState),
+.instance_init = bcm2838_pcie_root_init,
+.class_init = bcm2838_pcie_root_class_init,
+};
+
+static void bcm2838_pcie_register(void)
+{
+type_register_static(_pcie_root_info);
+}
+
+type_init(bcm2838_pcie_register)
diff --git a/hw/arm/meson.build b/hw/arm/meson.build
index 27e6797de2..b26ed13c6f 100644
--- a/hw/arm/meson.build
+++ b/hw/arm/meson.build
@@ -39,7 +39,10 @@ arm_ss.add(when: 'CONFIG_ALLWINNER_A10', if_true: 
files('allwinner-a10.c', 'cubi
 arm_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-h3.c', 
'orangepi.c'))
 arm_ss.add(when: 'CONFIG_ALLWINNER_R40', if_true: files('allwinner-r40.c', 
'bananapi_m2u.c'))
 arm_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2836.c', 'raspi.c'))
-arm_ss.add(when: ['CONFIG_RASPI', 'TARGET_AARCH64'], if_true: 
files('bcm2838.c', 'raspi4b.c'))
+arm_ss.add(when: ['CONFIG_RASPI', 'TARGET_AARCH64'], if_true: files(
+  'bcm2838.c',
+  'bcm2838_pcie.c',
+  'raspi4b.c'))
 arm_ss.add(when: 'CONFIG_STM32F100_SOC', if_true: files('stm32f100_soc.c'))
 arm_ss.add(when: 'CONFIG_STM32F205_SOC', if_true: files('stm32f205_soc.c'))
 arm_ss.add(when: 'CONFIG_STM32F405_SOC', if_true: files('stm32f405_soc.c'))
diff --git a/hw/arm/trace-events b/hw/arm/trace-events
index 4f0167e638..6cfab31539 100644
--- a/hw/arm/trace-events
+++ b/hw/arm/trace-events
@@ -55,5 +55,9 @@ smmuv3_notify_flag_add(const char *iommu) "ADD SMMUNotifier 
node for iommu mr=%s
 smmuv3_notify_flag_del(const char *iommu) "DEL SMMUNotifier node for iommu 
mr=%s"
 smmuv3_inv_notifiers_iova(const char *name, uint16_t asid, uint16_t vmid, 
uint64_t iova, uint8_t tg, uint64_t num_pages) "iommu mr=%s asid=%d vmid=%d 
iova=0x%"PRIx64" tg=%d num_pages=0x%"PRIx64
 
+# bcm2838_pcie.c
+bcm2838_pcie_host_read(unsigned int size, uint64_t offset, uint64_t value) "%u 
bytes @ 0x%04"PRIx64": 0x%016"PRIx64
+bcm2838_pcie_host_write(unsigned int size, uint64_t offset, uint64_t value) 
"%u bytes @ 0x%04"PRIx64": 0x%016"PRIx64
+
 # bcm2838.c
 bcm2838_gic_set_irq(int irq, int level) "gic irq:%d lvl:%d"
diff --git a/include/hw/arm/bcm2838_pcie.h b/include/hw/arm/bcm2838_pcie.h
new file mode 100644
index 00..39828f817f
--- /dev/null
+++ b/include/hw/arm/bcm2838_pcie.h
@@ -0,0 +1,53 @@
+/*
+ * BCM2838 PCIe Root Complex emulation
+ *
+ * Copyright (C) 2022 Ovchinnikov Vitalii 
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef BCM2838_PCIE_H
+#define BCM2838_PCIE_H
+
+#include "exec/hwaddr.h"
+#include "hw/sysbus.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pcie_host.h"
+#include "hw/pci/pcie_port.h"
+#include "qom/object.h"
+
+#define 

[PATCH v4 21/45] Add clock_isp stub

2023-12-07 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/arm/bcm2838_peripherals.c | 6 ++
 include/hw/arm/bcm2838_peripherals.h | 1 +
 2 files changed, 7 insertions(+)

diff --git a/hw/arm/bcm2838_peripherals.c b/hw/arm/bcm2838_peripherals.c
index e9c6d47ba6..65a659c15c 100644
--- a/hw/arm/bcm2838_peripherals.c
+++ b/hw/arm/bcm2838_peripherals.c
@@ -17,6 +17,9 @@
 #define PCIE_MMIO_ARM_OFFSET0x6
 #define PCIE_MMIO_SIZE  0x4000
 
+#define CLOCK_ISP_OFFSET0xc11000
+#define CLOCK_ISP_SIZE  0x100
+
 /* Lower peripheral base address on the VC (GPU) system bus */
 #define BCM2838_VC_PERI_LOW_BASE 0x7c00
 
@@ -228,6 +231,9 @@ static void bcm2838_peripherals_realize(DeviceState *dev, 
Error **errp)
 memory_region_add_subregion(get_system_memory(), PCIE_MMIO_ARM_OFFSET,
 >pcie_mmio_alias);
 
+create_unimp(s_base, >clkisp, "bcm2835-clkisp", CLOCK_ISP_OFFSET,
+ CLOCK_ISP_SIZE);
+
 /* GPIO */
 if (!sysbus_realize(SYS_BUS_DEVICE(>gpio), errp)) {
 return;
diff --git a/include/hw/arm/bcm2838_peripherals.h 
b/include/hw/arm/bcm2838_peripherals.h
index 0e8465ba34..20b7d1eb67 100644
--- a/include/hw/arm/bcm2838_peripherals.h
+++ b/include/hw/arm/bcm2838_peripherals.h
@@ -70,6 +70,7 @@ struct BCM2838PeripheralState {
 BCM2838Rng200State rng200;
 Bcm2838ThermalState thermal;
 SDHCIState emmc2;
+UnimplementedDeviceState clkisp;
 BCM2838PcieHostState pcie_host;
 BCM2838GpioState gpio;
 
-- 
2.34.1




[PATCH v4 11/45] Introduce Raspberry PI 4 machine

2023-12-07 Thread Sergey Kambalin
Signed-off-by: Sergey Kambalin 
---
 hw/arm/bcm2835_peripherals.c| 20 +++--
 hw/arm/bcm2836.c|  2 +
 hw/arm/bcm2838.c|  2 +
 hw/arm/meson.build  |  2 +-
 hw/arm/raspi.c  | 28 -
 hw/arm/raspi4b.c| 72 +
 include/hw/arm/raspi_platform.h | 11 +
 include/hw/display/bcm2835_fb.h |  2 +
 8 files changed, 125 insertions(+), 14 deletions(-)
 create mode 100644 hw/arm/raspi4b.c

diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c
index fd70cde123..ae8117961e 100644
--- a/hw/arm/bcm2835_peripherals.c
+++ b/hw/arm/bcm2835_peripherals.c
@@ -108,6 +108,7 @@ static void raspi_peripherals_base_init(Object *obj)
 /* Framebuffer */
 object_initialize_child(obj, "fb", >fb, TYPE_BCM2835_FB);
 object_property_add_alias(obj, "vcram-size", OBJECT(>fb), "vcram-size");
+object_property_add_alias(obj, "vcram-base", OBJECT(>fb), "vcram-base");
 
 object_property_add_const_link(OBJECT(>fb), "dma-mr",
OBJECT(>gpu_bus_mr));
@@ -225,7 +226,7 @@ void bcm_soc_peripherals_common_realize(DeviceState *dev, 
Error **errp)
 Object *obj;
 MemoryRegion *ram;
 Error *err = NULL;
-uint64_t ram_size, vcram_size;
+uint64_t ram_size, vcram_size, vcram_base;
 int n;
 
 obj = object_property_get_link(OBJECT(dev), "ram", _abort);
@@ -329,11 +330,24 @@ void bcm_soc_peripherals_common_realize(DeviceState *dev, 
Error **errp)
 return;
 }
 
-if (!object_property_set_uint(OBJECT(>fb), "vcram-base",
-  ram_size - vcram_size, errp)) {
+vcram_base = object_property_get_uint(OBJECT(s), "vcram-base", );
+if (err) {
+error_propagate(errp, err);
 return;
 }
 
+if (vcram_base == 0) {
+vcram_base = (ram_size > UPPER_RAM_BASE ? UPPER_RAM_BASE : ram_size)
+- vcram_size;
+} else {
+if (vcram_base + vcram_size > UPPER_RAM_BASE) {
+vcram_base = UPPER_RAM_BASE - vcram_size;
+}
+}
+if (!object_property_set_uint(OBJECT(>fb), "vcram-base", vcram_base,
+  errp)) {
+return;
+}
 if (!sysbus_realize(SYS_BUS_DEVICE(>fb), errp)) {
 return;
 }
diff --git a/hw/arm/bcm2836.c b/hw/arm/bcm2836.c
index 18675c896c..ee890f3d35 100644
--- a/hw/arm/bcm2836.c
+++ b/hw/arm/bcm2836.c
@@ -64,6 +64,8 @@ static void bcm283x_init(Object *obj)
   "command-line");
 object_property_add_alias(obj, "vcram-size", OBJECT(>peripherals),
   "vcram-size");
+object_property_add_alias(obj, "vcram-base", OBJECT(>peripherals),
+  "vcram-base");
 }
 
 bool bcm283x_common_realize(DeviceState *dev, BCMSocPeripheralBaseState *ps,
diff --git a/hw/arm/bcm2838.c b/hw/arm/bcm2838.c
index 8925957c6c..89cd9d5d8c 100644
--- a/hw/arm/bcm2838.c
+++ b/hw/arm/bcm2838.c
@@ -54,6 +54,8 @@ static void bcm2838_init(Object *obj)
   "board-rev");
 object_property_add_alias(obj, "vcram-size", OBJECT(>peripherals),
   "vcram-size");
+object_property_add_alias(obj, "vcram-base", OBJECT(>peripherals),
+  "vcram-base");
 object_property_add_alias(obj, "command-line", OBJECT(>peripherals),
   "command-line");
 
diff --git a/hw/arm/meson.build b/hw/arm/meson.build
index 551ab6abf5..27e6797de2 100644
--- a/hw/arm/meson.build
+++ b/hw/arm/meson.build
@@ -39,7 +39,7 @@ arm_ss.add(when: 'CONFIG_ALLWINNER_A10', if_true: 
files('allwinner-a10.c', 'cubi
 arm_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-h3.c', 
'orangepi.c'))
 arm_ss.add(when: 'CONFIG_ALLWINNER_R40', if_true: files('allwinner-r40.c', 
'bananapi_m2u.c'))
 arm_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2836.c', 'raspi.c'))
-arm_ss.add(when: ['CONFIG_RASPI', 'TARGET_AARCH64'], if_true: 
files('bcm2838.c'))
+arm_ss.add(when: ['CONFIG_RASPI', 'TARGET_AARCH64'], if_true: 
files('bcm2838.c', 'raspi4b.c'))
 arm_ss.add(when: 'CONFIG_STM32F100_SOC', if_true: files('stm32f100_soc.c'))
 arm_ss.add(when: 'CONFIG_STM32F205_SOC', if_true: files('stm32f205_soc.c'))
 arm_ss.add(when: 'CONFIG_STM32F405_SOC', if_true: files('stm32f405_soc.c'))
diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
index 7d04734cd2..da1e9e7c13 100644
--- a/hw/arm/raspi.c
+++ b/hw/arm/raspi.c
@@ -18,6 +18,7 @@
 #include "qapi/error.h"
 #include "hw/arm/boot.h"
 #include "hw/arm/bcm2836.h"
+#include "hw/arm/bcm2838.h"
 #include "hw/arm/raspi_platform.h"
 #include "hw/registerfields.h"
 #include "qemu/error-report.h"
@@ -61,6 +62,7 @@ typedef enum RaspiProcessorId {
 PROCESSOR_ID_BCM2835 = 0,
 PROCESSOR_ID_BCM2836 = 1,
 PROCESSOR_ID_BCM2837 = 2,
+PROCESSOR_ID_BCM2838 = 3,
 } RaspiProcessorId;
 
 static const struct {
@@ -70,13 +72,9 @@ static const 

Re: [PATCH v6] crypto: Introduce SM4 symmetric cipher algorithm

2023-12-07 Thread Yong Huang
I'll post the changelog between versions in the next version if needed. :)

v6:
- modify the comment about how to enable sm4 crypto feature
v5:
- drop the crypto-sm4 option in build system
v4
- refactor the error report info, change "sm4"->"libsm4"

On Fri, Dec 8, 2023 at 12:02 AM Philippe Mathieu-Daudé 
wrote:

> Hi Hyman,
>
> On 7/12/23 16:47, Hyman Huang wrote:
> > Introduce the SM4 cipher algorithms (OSCCA GB/T 32907-2016).
> >
> > SM4 (GBT.32907-2016) is a cryptographic standard issued by the
> > Organization of State Commercial Administration of China (OSCCA)
> > as an authorized cryptographic algorithms for the use within China.
> >
> > Detect the SM4 cipher algorithms and enable the feature silently
> > if it is available.
> >
> > Signed-off-by: Hyman Huang 
> > Reviewed-by: Philippe Mathieu-Daudé 
> > ---
>
> What are the changes since v4/v5?
>
> >   crypto/block-luks.c | 11 
> >   crypto/cipher-gcrypt.c.inc  |  8 ++
> >   crypto/cipher-nettle.c.inc  | 49 +
> >   crypto/cipher.c |  6 
> >   meson.build | 26 +
> >   qapi/crypto.json|  5 +++-
> >   tests/unit/test-crypto-cipher.c | 13 +
> >   7 files changed, 117 insertions(+), 1 deletion(-)
> >
> > diff --git a/crypto/block-luks.c b/crypto/block-luks.c
> > index fb01ec38bb..f0813d69b4 100644
> > --- a/crypto/block-luks.c
> > +++ b/crypto/block-luks.c
> > @@ -95,12 +95,23 @@ qcrypto_block_luks_cipher_size_map_twofish[] = {
> >   { 0, 0 },
> >   };
> >
> > +#ifdef CONFIG_CRYPTO_SM4
> > +static const QCryptoBlockLUKSCipherSizeMap
> > +qcrypto_block_luks_cipher_size_map_sm4[] = {
> > +{ 16, QCRYPTO_CIPHER_ALG_SM4},
> > +{ 0, 0 },
> > +};
> > +#endif
> > +
> >   static const QCryptoBlockLUKSCipherNameMap
> >   qcrypto_block_luks_cipher_name_map[] = {
> >   { "aes", qcrypto_block_luks_cipher_size_map_aes },
> >   { "cast5", qcrypto_block_luks_cipher_size_map_cast5 },
> >   { "serpent", qcrypto_block_luks_cipher_size_map_serpent },
> >   { "twofish", qcrypto_block_luks_cipher_size_map_twofish },
> > +#ifdef CONFIG_CRYPTO_SM4
> > +{ "sm4", qcrypto_block_luks_cipher_size_map_sm4},
> > +#endif
> >   };
> >
> >   QEMU_BUILD_BUG_ON(sizeof(struct QCryptoBlockLUKSKeySlot) != 48);
> > diff --git a/crypto/cipher-gcrypt.c.inc b/crypto/cipher-gcrypt.c.inc
> > index a6a0117717..1377cbaf14 100644
> > --- a/crypto/cipher-gcrypt.c.inc
> > +++ b/crypto/cipher-gcrypt.c.inc
> > @@ -35,6 +35,9 @@ bool qcrypto_cipher_supports(QCryptoCipherAlgorithm
> alg,
> >   case QCRYPTO_CIPHER_ALG_SERPENT_256:
> >   case QCRYPTO_CIPHER_ALG_TWOFISH_128:
> >   case QCRYPTO_CIPHER_ALG_TWOFISH_256:
> > +#ifdef CONFIG_CRYPTO_SM4
> > +case QCRYPTO_CIPHER_ALG_SM4:
> > +#endif
> >   break;
> >   default:
> >   return false;
> > @@ -219,6 +222,11 @@ static QCryptoCipher
> *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
> >   case QCRYPTO_CIPHER_ALG_TWOFISH_256:
> >   gcryalg = GCRY_CIPHER_TWOFISH;
> >   break;
> > +#ifdef CONFIG_CRYPTO_SM4
> > +case QCRYPTO_CIPHER_ALG_SM4:
> > +gcryalg = GCRY_CIPHER_SM4;
> > +break;
> > +#endif
> >   default:
> >   error_setg(errp, "Unsupported cipher algorithm %s",
> >  QCryptoCipherAlgorithm_str(alg));
> > diff --git a/crypto/cipher-nettle.c.inc b/crypto/cipher-nettle.c.inc
> > index 24cc61f87b..42b39e18a2 100644
> > --- a/crypto/cipher-nettle.c.inc
> > +++ b/crypto/cipher-nettle.c.inc
> > @@ -33,6 +33,9 @@
> >   #ifndef CONFIG_QEMU_PRIVATE_XTS
> >   #include 
> >   #endif
> > +#ifdef CONFIG_CRYPTO_SM4
> > +#include 
> > +#endif
> >
> >   static inline bool qcrypto_length_check(size_t len, size_t blocksize,
> >   Error **errp)
> > @@ -426,6 +429,30 @@ DEFINE_ECB_CBC_CTR_XTS(qcrypto_nettle_twofish,
> >  QCryptoNettleTwofish, TWOFISH_BLOCK_SIZE,
> >  twofish_encrypt_native, twofish_decrypt_native)
> >
> > +#ifdef CONFIG_CRYPTO_SM4
> > +typedef struct QCryptoNettleSm4 {
> > +QCryptoCipher base;
> > +struct sm4_ctx key[2];
> > +} QCryptoNettleSm4;
> > +
> > +static void sm4_encrypt_native(void *ctx, size_t length,
> > +   uint8_t *dst, const uint8_t *src)
> > +{
> > +struct sm4_ctx *keys = ctx;
> > +sm4_crypt([0], length, dst, src);
> > +}
> > +
> > +static void sm4_decrypt_native(void *ctx, size_t length,
> > +   uint8_t *dst, const uint8_t *src)
> > +{
> > +struct sm4_ctx *keys = ctx;
> > +sm4_crypt([1], length, dst, src);
> > +}
> > +
> > +DEFINE_ECB(qcrypto_nettle_sm4,
> > +   QCryptoNettleSm4, SM4_BLOCK_SIZE,
> > +   sm4_encrypt_native, sm4_decrypt_native)
> > +#endif
> >
> >   bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg,
> >QCryptoCipherMode mode)
> > 

[PATCH for 8.2] accel/tcg/cputlb: Fix iotlb page alignment check

2023-12-07 Thread LIU Zhiwei
For ram memory region the iotlb(which will be filled into the xlat_section
of CPUTLBEntryFull) is calculated as:

iotlb = memory_region_get_ram_addr(section->mr) + xlat;

1) xlat here is the offset_within_region of a MemoryRegionSection, which maybe
not TARGET_PAGE_BITS aligned.
2) The ram_addr_t returned by memory_region_get_ram_addr is always
HOST PAGE ALIGNED.

So we cann't assert the sum of them is TARGET_PAGE_BITS aligend.
A fail case has been give by the link:
https://lore.kernel.org/all/b68ab7d3-d3d3-9f81-569d-454ae9c11...@linaro.org/T/

Fixes: dff1ab68d8c5 ("accel/tcg: Fix the comment for CPUTLBEntryFull")
Signed-off-by: LIU Zhiwei 
---
 accel/tcg/cputlb.c | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
index db3f93fda9..7a50a21a2e 100644
--- a/accel/tcg/cputlb.c
+++ b/accel/tcg/cputlb.c
@@ -1168,7 +1168,6 @@ void tlb_set_page_full(CPUState *cpu, int mmu_idx,
 write_flags = read_flags;
 if (is_ram) {
 iotlb = memory_region_get_ram_addr(section->mr) + xlat;
-assert(!(iotlb & ~TARGET_PAGE_MASK));
 /*
  * Computing is_clean is expensive; avoid all that unless
  * the page is actually writable.
@@ -1231,9 +1230,8 @@ void tlb_set_page_full(CPUState *cpu, int mmu_idx,
 
 /* refill the tlb */
 /*
- * When memory region is ram, iotlb contains a TARGET_PAGE_BITS
- * aligned ram_addr_t of the page base of the target RAM.
- * Otherwise, iotlb contains
+ * When memory region is ram, iotlb contains ram_addr_t of the page base
+ * of the target RAM. Otherwise, iotlb contains
  *  - a physical section number in the lower TARGET_PAGE_BITS
  *  - the offset within section->mr of the page base (I/O, ROMD) with the
  *TARGET_PAGE_BITS masked off.
-- 
2.17.1




Re: make: *** No rule to make target 'i386/fp87.c', needed by 'i386/fp87.o'. Stop.

2023-12-07 Thread Liu Jaloo
Thanks, I'll check it out.
it does be a very old version, almost the first version of QEMU

$ git checkout initial -b initial

I will try it on my own, thanks a lot.

On Thu, Dec 7, 2023 at 7:32 PM Peter Maydell 
wrote:

> On Thu, 7 Dec 2023 at 11:20, Liu Jaloo  wrote:
> >
> > qemu checkout tag "initial" version, then
> > $ make
> >
> > report error, like this:
> > make: *** No rule to make target 'i386/fp87.c', needed by
> 'i386/fp87.o'.  Stop.
> >
> > How or where can I get the resource about folder "i386", just like OBJS
> in Makefile
> >
> > OBJS= i386/fp87.o i386/interp_main.o i386/interp_modrm.o
> i386/interp_16_32.o \
> >   i386/interp_32_16.o i386/interp_32_32.o i386/emu-utils.o \
> >   i386/dis8086.o i386/emu-ldt.o
>
> What version of QEMU are you trying to build? These lines
> have not been in Makefile since 2003 !
>
> If you're deliberately trying to build a very old version of
> QEMU, then you are on your own for that. You'll probably
> find it does not compile at all on a modern Linux with a
> modern C compiler.
>
> thanks
> -- PMM
>


[PATCH v3 4/4] accel/tcg: Move perf and debuginfo support to tcg

2023-12-07 Thread Ilya Leoshkevich
tcg/ should not depend on accel/tcg/, but perf and debuginfo
support provided by the latter are being used by tcg/tcg.c.

Since that's the only user, move both to tcg/.

Suggested-by: Philippe Mathieu-Daudé 
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Ilya Leoshkevich 
---
 accel/tcg/meson.build  | 2 --
 accel/tcg/translate-all.c  | 2 +-
 hw/core/loader.c   | 2 +-
 linux-user/elfload.c   | 2 +-
 linux-user/exit.c  | 2 +-
 linux-user/main.c  | 2 +-
 system/vl.c| 2 +-
 {accel/tcg => tcg}/debuginfo.c | 0
 {accel/tcg => tcg}/debuginfo.h | 4 ++--
 tcg/meson.build| 3 +++
 {accel/tcg => tcg}/perf.c  | 2 +-
 {accel/tcg => tcg}/perf.h  | 4 ++--
 tcg/tcg.c  | 2 +-
 13 files changed, 15 insertions(+), 14 deletions(-)
 rename {accel/tcg => tcg}/debuginfo.c (100%)
 rename {accel/tcg => tcg}/debuginfo.h (96%)
 rename {accel/tcg => tcg}/perf.c (99%)
 rename {accel/tcg => tcg}/perf.h (95%)

diff --git a/accel/tcg/meson.build b/accel/tcg/meson.build
index 8783edd06ee..a7cb724edb2 100644
--- a/accel/tcg/meson.build
+++ b/accel/tcg/meson.build
@@ -16,8 +16,6 @@ tcg_ss.add(when: 'CONFIG_SYSTEM_ONLY', if_false: 
files('user-exec-stub.c'))
 if get_option('plugins')
   tcg_ss.add(files('plugin-gen.c'))
 endif
-tcg_ss.add(when: libdw, if_true: files('debuginfo.c'))
-tcg_ss.add(when: 'CONFIG_LINUX', if_true: files('perf.c'))
 specific_ss.add_all(when: 'CONFIG_TCG', if_true: tcg_ss)
 
 specific_ss.add(when: ['CONFIG_SYSTEM_ONLY', 'CONFIG_TCG'], if_true: files(
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
index 79a88f5fb75..3c1ce69ff36 100644
--- a/accel/tcg/translate-all.c
+++ b/accel/tcg/translate-all.c
@@ -63,7 +63,7 @@
 #include "tb-context.h"
 #include "internal-common.h"
 #include "internal-target.h"
-#include "perf.h"
+#include "tcg/perf.h"
 #include "tcg/insn-start-words.h"
 
 TBContext tb_ctx;
diff --git a/hw/core/loader.c b/hw/core/loader.c
index e7a9b3775bb..b8e52f3fb0f 100644
--- a/hw/core/loader.c
+++ b/hw/core/loader.c
@@ -62,7 +62,7 @@
 #include "hw/boards.h"
 #include "qemu/cutils.h"
 #include "sysemu/runstate.h"
-#include "accel/tcg/debuginfo.h"
+#include "tcg/debuginfo.h"
 
 #include 
 
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index cf9e74468b1..62120c76151 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -21,7 +21,7 @@
 #include "qapi/error.h"
 #include "qemu/error-report.h"
 #include "target_signal.h"
-#include "accel/tcg/debuginfo.h"
+#include "tcg/debuginfo.h"
 
 #ifdef TARGET_ARM
 #include "target/arm/cpu-features.h"
diff --git a/linux-user/exit.c b/linux-user/exit.c
index 50266314e0a..1ff8fe4f072 100644
--- a/linux-user/exit.c
+++ b/linux-user/exit.c
@@ -17,7 +17,7 @@
  *  along with this program; if not, see .
  */
 #include "qemu/osdep.h"
-#include "accel/tcg/perf.h"
+#include "tcg/perf.h"
 #include "gdbstub/syscalls.h"
 #include "qemu.h"
 #include "user-internals.h"
diff --git a/linux-user/main.c b/linux-user/main.c
index 0cdaf30d346..2e075ae1e69 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -54,7 +54,7 @@
 #include "signal-common.h"
 #include "loader.h"
 #include "user-mmap.h"
-#include "accel/tcg/perf.h"
+#include "tcg/perf.h"
 
 #ifdef CONFIG_SEMIHOSTING
 #include "semihosting/semihost.h"
diff --git a/system/vl.c b/system/vl.c
index 2bcd9efb9a6..56baa1c81f2 100644
--- a/system/vl.c
+++ b/system/vl.c
@@ -96,7 +96,7 @@
 #endif
 #include "sysemu/qtest.h"
 #ifdef CONFIG_TCG
-#include "accel/tcg/perf.h"
+#include "tcg/perf.h"
 #endif
 
 #include "disas/disas.h"
diff --git a/accel/tcg/debuginfo.c b/tcg/debuginfo.c
similarity index 100%
rename from accel/tcg/debuginfo.c
rename to tcg/debuginfo.c
diff --git a/accel/tcg/debuginfo.h b/tcg/debuginfo.h
similarity index 96%
rename from accel/tcg/debuginfo.h
rename to tcg/debuginfo.h
index f064e1c144b..858535b5da5 100644
--- a/accel/tcg/debuginfo.h
+++ b/tcg/debuginfo.h
@@ -4,8 +4,8 @@
  * SPDX-License-Identifier: GPL-2.0-or-later
  */
 
-#ifndef ACCEL_TCG_DEBUGINFO_H
-#define ACCEL_TCG_DEBUGINFO_H
+#ifndef TCG_DEBUGINFO_H
+#define TCG_DEBUGINFO_H
 
 #include "qemu/bitops.h"
 
diff --git a/tcg/meson.build b/tcg/meson.build
index 895a11d3fa2..28a699b4228 100644
--- a/tcg/meson.build
+++ b/tcg/meson.build
@@ -22,6 +22,9 @@ if get_option('tcg_interpreter')
   tcg_ss.add(files('tci.c'))
 endif
 
+tcg_ss.add(when: libdw, if_true: files('debuginfo.c'))
+tcg_ss.add(when: 'CONFIG_LINUX', if_true: files('perf.c'))
+
 tcg_ss = tcg_ss.apply(config_targetos, strict: false)
 
 libtcg_user = static_library('tcg_user',
diff --git a/accel/tcg/perf.c b/tcg/perf.c
similarity index 99%
rename from accel/tcg/perf.c
rename to tcg/perf.c
index 68a46b1b524..de34248d92d 100644
--- a/accel/tcg/perf.c
+++ b/tcg/perf.c
@@ -11,7 +11,7 @@
 #include "qemu/osdep.h"
 #include "elf.h"
 #include "exec/target_page.h"
-#include "exec/exec-all.h"
+#include "exec/translation-block.h"
 

[PATCH v3 0/4] accel/tcg: Move perf and debuginfo support to tcg

2023-12-07 Thread Ilya Leoshkevich
v2: https://patchew.org/QEMU/20230630234230.596193-1-...@linux.ibm.com/
v2 -> v3: Rebased.
  This series was lost and forgotten until Philippe reminded me
  about it.

v1: https://lists.gnu.org/archive/html/qemu-devel/2023-06/msg07037.html
v1 -> v2: Move qemu_target_page_mask() hunk to patch 1.
  Fix typos.

Hi,

This series is a follow-up to discussion in [1]; the goal is to build
perf and debuginfo support only one time.

Best regards,
Ilya

[1] https://lists.gnu.org/archive/html/qemu-devel/2023-06/msg06510.html

Ilya Leoshkevich (4):
  target: Make qemu_target_page_mask() available for *-user
  tcg: Make tb_cflags() usable from target-agnostic code
  accel/tcg: Remove #ifdef TARGET_I386 from perf.c
  accel/tcg: Move perf and debuginfo support to tcg

 accel/tcg/meson.build|  2 --
 accel/tcg/translate-all.c|  2 +-
 hw/core/loader.c |  2 +-
 include/exec/exec-all.h  |  6 --
 include/exec/translation-block.h |  6 ++
 linux-user/elfload.c |  2 +-
 linux-user/exit.c|  2 +-
 linux-user/main.c|  2 +-
 system/physmem.c |  5 -
 system/vl.c  |  2 +-
 target/meson.build   |  2 ++
 target/target-common.c   | 10 ++
 {accel/tcg => tcg}/debuginfo.c   |  0
 {accel/tcg => tcg}/debuginfo.h   |  4 ++--
 tcg/meson.build  |  3 +++
 {accel/tcg => tcg}/perf.c|  9 +++--
 {accel/tcg => tcg}/perf.h|  4 ++--
 tcg/tcg.c|  2 +-
 18 files changed, 35 insertions(+), 30 deletions(-)
 create mode 100644 target/target-common.c
 rename {accel/tcg => tcg}/debuginfo.c (100%)
 rename {accel/tcg => tcg}/debuginfo.h (96%)
 rename {accel/tcg => tcg}/perf.c (98%)
 rename {accel/tcg => tcg}/perf.h (95%)

-- 
2.43.0




[PATCH v3 2/4] tcg: Make tb_cflags() usable from target-agnostic code

2023-12-07 Thread Ilya Leoshkevich
Currently tb_cflags() is defined in exec-all.h, which is not usable
from target-agnostic code. Move it to translation-block.h, which is.

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Ilya Leoshkevich 
---
 include/exec/exec-all.h  | 6 --
 include/exec/translation-block.h | 6 ++
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
index ee90ef122bc..8d615b60c14 100644
--- a/include/exec/exec-all.h
+++ b/include/exec/exec-all.h
@@ -459,12 +459,6 @@ int probe_access_full_mmu(CPUArchState *env, vaddr addr, 
int size,
 
 #endif
 
-/* Hide the qatomic_read to make code a little easier on the eyes */
-static inline uint32_t tb_cflags(const TranslationBlock *tb)
-{
-return qatomic_read(>cflags);
-}
-
 static inline tb_page_addr_t tb_page_addr0(const TranslationBlock *tb)
 {
 #ifdef CONFIG_USER_ONLY
diff --git a/include/exec/translation-block.h b/include/exec/translation-block.h
index e2b26e16da1..48211c890a7 100644
--- a/include/exec/translation-block.h
+++ b/include/exec/translation-block.h
@@ -145,4 +145,10 @@ struct TranslationBlock {
 /* The alignment given to TranslationBlock during allocation. */
 #define CODE_GEN_ALIGN  16
 
+/* Hide the qatomic_read to make code a little easier on the eyes */
+static inline uint32_t tb_cflags(const TranslationBlock *tb)
+{
+return qatomic_read(>cflags);
+}
+
 #endif /* EXEC_TRANSLATION_BLOCK_H */
-- 
2.43.0




[PATCH v3 1/4] target: Make qemu_target_page_mask() available for *-user

2023-12-07 Thread Ilya Leoshkevich
Currently qemu_target_page_mask() is usable only from the softmmu
code. Make it possible to use it from the *-user code as well.

Make use of it in perf.c.

Signed-off-by: Ilya Leoshkevich 
---
 accel/tcg/perf.c   |  3 ++-
 system/physmem.c   |  5 -
 target/meson.build |  2 ++
 target/target-common.c | 10 ++
 4 files changed, 14 insertions(+), 6 deletions(-)
 create mode 100644 target/target-common.c

diff --git a/accel/tcg/perf.c b/accel/tcg/perf.c
index cd1aa99a7ee..ba75c1bbe45 100644
--- a/accel/tcg/perf.c
+++ b/accel/tcg/perf.c
@@ -10,6 +10,7 @@
 
 #include "qemu/osdep.h"
 #include "elf.h"
+#include "exec/target_page.h"
 #include "exec/exec-all.h"
 #include "qemu/timer.h"
 #include "tcg/tcg.h"
@@ -335,7 +336,7 @@ void perf_report_code(uint64_t guest_pc, TranslationBlock 
*tb,
 /* FIXME: This replicates the restore_state_to_opc() logic. */
 q[insn].address = gen_insn_data[insn * start_words + 0];
 if (tb_cflags(tb) & CF_PCREL) {
-q[insn].address |= (guest_pc & TARGET_PAGE_MASK);
+q[insn].address |= (guest_pc & qemu_target_page_mask());
 } else {
 #if defined(TARGET_I386)
 q[insn].address -= tb->cs_base;
diff --git a/system/physmem.c b/system/physmem.c
index a63853a7bc9..7cf4a735c3b 100644
--- a/system/physmem.c
+++ b/system/physmem.c
@@ -3431,11 +3431,6 @@ size_t qemu_target_page_size(void)
 return TARGET_PAGE_SIZE;
 }
 
-int qemu_target_page_mask(void)
-{
-return TARGET_PAGE_MASK;
-}
-
 int qemu_target_page_bits(void)
 {
 return TARGET_PAGE_BITS;
diff --git a/target/meson.build b/target/meson.build
index a53a60486fc..dee2ac47e02 100644
--- a/target/meson.build
+++ b/target/meson.build
@@ -19,3 +19,5 @@ subdir('sh4')
 subdir('sparc')
 subdir('tricore')
 subdir('xtensa')
+
+specific_ss.add(files('target-common.c'))
diff --git a/target/target-common.c b/target/target-common.c
new file mode 100644
index 000..903b10cfe4b
--- /dev/null
+++ b/target/target-common.c
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+#include "qemu/osdep.h"
+
+#include "cpu.h"
+#include "exec/target_page.h"
+
+int qemu_target_page_mask(void)
+{
+return TARGET_PAGE_MASK;
+}
-- 
2.43.0




[PATCH v3 3/4] accel/tcg: Remove #ifdef TARGET_I386 from perf.c

2023-12-07 Thread Ilya Leoshkevich
Preparation for moving perf.c to tcg/.

This affects only profiling guest code, which has code in a non-0 based
segment, e.g., 16-bit code, which is not particularly important.

Suggested-by: Richard Henderson 
Signed-off-by: Ilya Leoshkevich 
---
 accel/tcg/perf.c | 4 
 1 file changed, 4 deletions(-)

diff --git a/accel/tcg/perf.c b/accel/tcg/perf.c
index ba75c1bbe45..68a46b1b524 100644
--- a/accel/tcg/perf.c
+++ b/accel/tcg/perf.c
@@ -337,10 +337,6 @@ void perf_report_code(uint64_t guest_pc, TranslationBlock 
*tb,
 q[insn].address = gen_insn_data[insn * start_words + 0];
 if (tb_cflags(tb) & CF_PCREL) {
 q[insn].address |= (guest_pc & qemu_target_page_mask());
-} else {
-#if defined(TARGET_I386)
-q[insn].address -= tb->cs_base;
-#endif
 }
 q[insn].flags = DEBUGINFO_SYMBOL | (jitdump ? DEBUGINFO_LINE : 0);
 }
-- 
2.43.0




Re: [PATCH v2 4/5] system/vl: Restrict icount to TCG emulation

2023-12-07 Thread Richard Henderson

On 12/7/23 07:45, Philippe Mathieu-Daudé wrote:

Signed-off-by: Philippe Mathieu-Daudé 
---
  stubs/icount.c | 6 --
  system/vl.c| 6 +-
  2 files changed, 5 insertions(+), 7 deletions(-)

diff --git a/stubs/icount.c b/stubs/icount.c
index a5202e2dd9..b060b03a73 100644
--- a/stubs/icount.c
+++ b/stubs/icount.c
@@ -1,5 +1,4 @@
  #include "qemu/osdep.h"
-#include "qapi/error.h"
  #include "sysemu/cpu-timers.h"
  
  /* icount - Instruction Counter API */

@@ -10,11 +9,6 @@ void icount_update(CPUState *cpu)
  {
  abort();
  }
-void icount_configure(QemuOpts *opts, Error **errp)
-{
-/* signal error */
-error_setg(errp, "cannot configure icount, TCG support not available");
-}
  int64_t icount_get_raw(void)
  {
  abort();
diff --git a/system/vl.c b/system/vl.c
index 2bcd9efb9a..8c99c5f681 100644
--- a/system/vl.c
+++ b/system/vl.c
@@ -2270,7 +2270,11 @@ static void user_register_global_props(void)
  
  static int do_configure_icount(void *opaque, QemuOpts *opts, Error **errp)

  {
-icount_configure(opts, errp);
+if (tcg_enabled()) {
+icount_configure(opts, errp);
+} else {
+error_setg(errp, "cannot configure icount, TCG support not available");
+}
  return 0;
  }


This is called before the accelerator is chosen -- even before the set of available 
accelerators is even found.  Indeed, that's the very next thing that 
configure_accelerators does.


OTOH, I don't see why icount_configure is being called so early.


r~

  





Re: [PATCH v2 3/5] util/async: Only call icount_notify_exit() if icount is enabled

2023-12-07 Thread Richard Henderson

On 12/7/23 07:45, Philippe Mathieu-Daudé wrote:

Signed-off-by: Philippe Mathieu-Daudé 
---
  stubs/icount.c |  2 +-
  util/async.c   | 16 +---
  2 files changed, 10 insertions(+), 8 deletions(-)

diff --git a/stubs/icount.c b/stubs/icount.c
index f8e6a014b8..a5202e2dd9 100644
--- a/stubs/icount.c
+++ b/stubs/icount.c
@@ -43,7 +43,7 @@ void icount_account_warp_timer(void)
  {
  abort();
  }
-
  void icount_notify_exit(void)
  {
+abort();
  }
diff --git a/util/async.c b/util/async.c
index 8f90ddc304..9007642c27 100644
--- a/util/async.c
+++ b/util/async.c
@@ -94,13 +94,15 @@ static void aio_bh_enqueue(QEMUBH *bh, unsigned new_flags)
  }
  
  aio_notify(ctx);

-/*
- * Workaround for record/replay.
- * vCPU execution should be suspended when new BH is set.
- * This is needed to avoid guest timeouts caused
- * by the long cycles of the execution.
- */
-icount_notify_exit();
+if (unlikely(icount_enabled())) {
+/*
+ * Workaround for record/replay.
+ * vCPU execution should be suspended when new BH is set.
+ * This is needed to avoid guest timeouts caused
+ * by the long cycles of the execution.
+ */
+icount_notify_exit();
+}


If you're going to do this, remove the test in the non-stub icount_notify_exit.


r~



Re: [PATCH v2 2/5] target/arm: Ensure icount is enabled when emulating INST_RETIRED

2023-12-07 Thread Richard Henderson

On 12/7/23 07:45, Philippe Mathieu-Daudé wrote:

pmu_init() register its event checking the pm_event::supported()
handler. For INST_RETIRED, the event is only registered and the
bit enabled in the PMU Common Event Identification register when
icount is enabled as ICOUNT_PRECISE.

Assert the pm_event::get_count() and pm_event::ns_per_count()
handler will only be called under this icount mode.

Signed-off-by: Philippe Mathieu-Daudé 
---
  target/arm/helper.c | 2 ++
  1 file changed, 2 insertions(+)

diff --git a/target/arm/helper.c b/target/arm/helper.c
index adb0960bba..333fd5f4bf 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -940,11 +940,13 @@ static bool instructions_supported(CPUARMState *env)
  
  static uint64_t instructions_get_count(CPUARMState *env)

  {
+assert(icount_enabled() == ICOUNT_PRECISE);
  return (uint64_t)icount_get_raw();
  }
  
  static int64_t instructions_ns_per(uint64_t icount)

  {
+assert(icount_enabled() == ICOUNT_PRECISE);
  return icount_to_ns((int64_t)icount);
  }
  #endif


I don't think an assert is required -- that's exactly what the .supported field is for. 
If you think this needs additional clarification, a comment is sufficient.



r~



Re: [PATCH v2 1/5] sysemu/cpu-timers: Introduce ICountMode enumerator

2023-12-07 Thread Richard Henderson

On 12/7/23 07:45, Philippe Mathieu-Daudé wrote:

Rather than having to lookup for what the 0, 1, 2, ...
icount values are, use a enum definition.

Signed-off-by: Philippe Mathieu-Daudé 
---
  include/sysemu/cpu-timers.h | 20 +---
  accel/tcg/icount-common.c   | 16 +++-
  stubs/icount.c  |  2 +-
  system/cpu-timers.c |  2 +-
  target/arm/helper.c |  3 ++-
  5 files changed, 24 insertions(+), 19 deletions(-)

diff --git a/include/sysemu/cpu-timers.h b/include/sysemu/cpu-timers.h
index 2e786fe7fb..e909ffae47 100644
--- a/include/sysemu/cpu-timers.h
+++ b/include/sysemu/cpu-timers.h
@@ -17,18 +17,24 @@ void cpu_timers_init(void);
  
  /* icount - Instruction Counter API */
  
-/*

- * icount enablement state:
+/**
+ * ICountMode: icount enablement state:
   *
- * 0 = Disabled - Do not count executed instructions.
- * 1 = Enabled - Fixed conversion of insn to ns via "shift" option
- * 2 = Enabled - Runtime adaptive algorithm to compute shift
+ * @ICOUNT_DISABLED: Disabled - Do not count executed instructions.
+ * @ICOUNT_PRECISE: Enabled - Fixed conversion of insn to ns via "shift" option
+ * @ICOUNT_ADAPTATIVE: Enabled - Runtime adaptive algorithm to compute shift
   */
+typedef enum {
+ICOUNT_DISABLED = 0,
+ICOUNT_PRECISE = 1,
+ICOUNT_ADAPTATIVE = 2,


No need for the assignments.  Otherwise,
Reviewed-by: Richard Henderson 


r~



[PATCH qemu v2 1/2] hw/arm: Add minimal support for the STM32L4x5 SoC

2023-12-07 Thread ~inesvarhol
From: Inès Varhol 

This patch adds a new STM32L4x5 SoC, it is necessary to add support for
the B-L475E-IOT01A board.
The implementation is derived from the STM32F405 SoC.
The implementation contains no peripherals, only memory regions are
implemented.

Reviewed-by: Philippe Mathieu-Daudé 

Signed-off-by: Arnaud Minier 
Signed-off-by: Inès Varhol 
---
 MAINTAINERS|   8 +
 hw/arm/Kconfig |   5 +
 hw/arm/meson.build |   1 +
 hw/arm/stm32l4x5_soc.c | 277 +
 include/hw/arm/stm32l4x5_soc.h |  68 
 5 files changed, 359 insertions(+)
 create mode 100644 hw/arm/stm32l4x5_soc.c
 create mode 100644 include/hw/arm/stm32l4x5_soc.h

diff --git a/MAINTAINERS b/MAINTAINERS
index ff1238bb98..32458d41dd 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1122,6 +1122,14 @@ L: qemu-...@nongnu.org
 S: Maintained
 F: hw/arm/olimex-stm32-h405.c
 
+STM32L4x5 SoC Family
+M: Arnaud Minier 
+M: Inès Varhol 
+L: qemu-...@nongnu.org
+S: Maintained
+F: hw/arm/stm32l4x5_soc.c
+F: include/hw/arm/stm32l4x5_soc.h
+
 SmartFusion2
 M: Subbaraya Sundeep 
 M: Peter Maydell 
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 3ada335a24..d2b94d9a47 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -448,6 +448,11 @@ config STM32F405_SOC
 select STM32F4XX_SYSCFG
 select STM32F4XX_EXTI
 
+config STM32L4X5_SOC
+bool
+select ARM_V7M
+select OR_IRQ
+
 config XLNX_ZYNQMP_ARM
 bool
 default y if PIXMAN
diff --git a/hw/arm/meson.build b/hw/arm/meson.build
index 68245d3ad1..9766da10c4 100644
--- a/hw/arm/meson.build
+++ b/hw/arm/meson.build
@@ -42,6 +42,7 @@ arm_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2836.c', 
'raspi.c'))
 arm_ss.add(when: 'CONFIG_STM32F100_SOC', if_true: files('stm32f100_soc.c'))
 arm_ss.add(when: 'CONFIG_STM32F205_SOC', if_true: files('stm32f205_soc.c'))
 arm_ss.add(when: 'CONFIG_STM32F405_SOC', if_true: files('stm32f405_soc.c'))
+arm_ss.add(when: 'CONFIG_STM32L4X5_SOC', if_true: files('stm32l4x5_soc.c'))
 arm_ss.add(when: 'CONFIG_XLNX_ZYNQMP_ARM', if_true: files('xlnx-zynqmp.c', 
'xlnx-zcu102.c'))
 arm_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files('xlnx-versal.c', 
'xlnx-versal-virt.c'))
 arm_ss.add(when: 'CONFIG_FSL_IMX25', if_true: files('fsl-imx25.c', 
'imx25_pdk.c'))
diff --git a/hw/arm/stm32l4x5_soc.c b/hw/arm/stm32l4x5_soc.c
new file mode 100644
index 00..f6dbd72084
--- /dev/null
+++ b/hw/arm/stm32l4x5_soc.c
@@ -0,0 +1,277 @@
+/*
+ * STM32L4x5 SoC family
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * Copyright (c) 2023 Arnaud Minier 
+ * Copyright (c) 2023 Inès Varhol 
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * Heavily inspired by the stm32f405_soc by Alistair Francis.
+ * The reference used is the STMicroElectronics RM0351 Reference manual
+ * for STM32L4x5 and STM32L4x6 advanced Arm ® -based 32-bit MCUs.
+ * 
https://www.st.com/en/microcontrollers-microprocessors/stm32l4x5/documentation.html
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/units.h"
+#include "qapi/error.h"
+#include "exec/address-spaces.h"
+#include "sysemu/sysemu.h"
+#include "hw/arm/stm32l4x5_soc.h"
+#include "hw/qdev-clock.h"
+#include "hw/misc/unimp.h"
+
+#define FLASH_BASE_ADDRESS 0x0800
+#define SRAM1_BASE_ADDRESS 0x2000
+#define SRAM1_SIZE (96 * KiB)
+#define SRAM2_BASE_ADDRESS 0x1000
+#define SRAM2_SIZE (32 * KiB)
+
+static void stm32l4x5_soc_initfn(Object *obj)
+{
+Stm32l4x5SocState *s = STM32L4X5_SOC(obj);
+
+s->sysclk = qdev_init_clock_in(DEVICE(s), "sysclk", NULL, NULL, 0);
+s->refclk = qdev_init_clock_in(DEVICE(s), "refclk", NULL, NULL, 0);
+}
+
+static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
+{
+ERRP_GUARD();
+Stm32l4x5SocState *s = STM32L4X5_SOC(dev_soc);
+const Stm32l4x5SocClass *sc = STM32L4X5_SOC_GET_CLASS(dev_soc);
+MemoryRegion *system_memory = get_system_memory();
+DeviceState 

[PATCH qemu v2 2/2] hw/arm: Add minimal support for the B-L475E-IOT01A board

2023-12-07 Thread ~inesvarhol
From: Inès Varhol 

This commit adds a new B-L475E-IOT01A board using the STM32L475VG SoC.
The implementation is derived from the Netduino Plus 2 machine.
There are no peripherals implemented yet, only memory regions.

Reviewed-by: Philippe Mathieu-Daudé 

Signed-off-by: Arnaud Minier 
Signed-off-by: Inès Varhol 
---
 MAINTAINERS |  7 +++
 configs/devices/arm-softmmu/default.mak |  1 +
 hw/arm/Kconfig  |  6 ++
 hw/arm/b-l475e-iot01a.c | 79 +
 hw/arm/meson.build  |  1 +
 5 files changed, 94 insertions(+)
 create mode 100644 hw/arm/b-l475e-iot01a.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 32458d41dd..6ae9ca3ef4 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1130,6 +1130,13 @@ S: Maintained
 F: hw/arm/stm32l4x5_soc.c
 F: include/hw/arm/stm32l4x5_soc.h
 
+B-L475E-IOT01A IoT Node
+M: Arnaud Minier 
+M: Inès Varhol 
+L: qemu-...@nongnu.org
+S: Maintained
+F: hw/arm/b-l475e-iot01a.c
+
 SmartFusion2
 M: Subbaraya Sundeep 
 M: Peter Maydell 
diff --git a/configs/devices/arm-softmmu/default.mak 
b/configs/devices/arm-softmmu/default.mak
index 980c48a7d9..023faa2f75 100644
--- a/configs/devices/arm-softmmu/default.mak
+++ b/configs/devices/arm-softmmu/default.mak
@@ -19,6 +19,7 @@ CONFIG_ARM_VIRT=y
 # CONFIG_NSERIES=n
 # CONFIG_STELLARIS=n
 # CONFIG_STM32VLDISCOVERY=n
+# CONFIG_B_L475E_IOT01A=n
 # CONFIG_REALVIEW=n
 # CONFIG_VERSATILE=n
 # CONFIG_VEXPRESS=n
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index d2b94d9a47..7520dc5cc0 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -448,6 +448,12 @@ config STM32F405_SOC
 select STM32F4XX_SYSCFG
 select STM32F4XX_EXTI
 
+config B_L475E_IOT01A
+bool
+default y
+depends on TCG && ARM
+select STM32L4X5_SOC
+
 config STM32L4X5_SOC
 bool
 select ARM_V7M
diff --git a/hw/arm/b-l475e-iot01a.c b/hw/arm/b-l475e-iot01a.c
new file mode 100644
index 00..72fdb6f0f8
--- /dev/null
+++ b/hw/arm/b-l475e-iot01a.c
@@ -0,0 +1,79 @@
+/*
+ * B-L475E-IOT01A Discovery Kit machine
+ * (B-L475E-IOT01A IoT Node)
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * Copyright (c) 2023 Arnaud Minier 
+ * Copyright (c) 2023 Ines Varhol 
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * Heavily inspired by the netduinoplus2 by Alistair Francis.
+ * The reference used is the STMicroElectronics UM2153 User manual
+ * Discovery kit for IoT node, multi-channel communication with STM32L4.
+ * https://www.st.com/en/evaluation-tools/b-l475e-iot01a.html#documentation
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "hw/boards.h"
+#include "hw/qdev-properties.h"
+#include "hw/qdev-clock.h"
+#include "qemu/error-report.h"
+#include "hw/arm/stm32l4x5_soc.h"
+#include "hw/arm/boot.h"
+
+/* Main SYSCLK frequency in Hz (80MHz) */
+#define SYSCLK_FRQ 8000ULL
+
+static void b_l475e_iot01a_init(MachineState *machine)
+{
+const Stm32l4x5SocClass *sc;
+DeviceState *dev;
+Clock *sysclk;
+
+/* This clock doesn't need migration because it is fixed-frequency */
+sysclk = clock_new(OBJECT(machine), "SYSCLK");
+clock_set_hz(sysclk, SYSCLK_FRQ);
+
+dev = qdev_new(TYPE_STM32L4X5XG_SOC);
+sc = STM32L4X5_SOC_GET_CLASS(dev);
+qdev_connect_clock_in(dev, "sysclk", sysclk);
+sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), _fatal);
+
+armv7m_load_kernel(ARM_CPU(first_cpu),
+   machine->kernel_filename,
+   0, sc->flash_size);
+}
+
+static void b_l475e_iot01a_machine_init(MachineClass *mc)
+{
+static const char *machine_valid_cpu_types[] = {
+ARM_CPU_TYPE_NAME("cortex-m4"),
+NULL};
+mc->desc = "B-L475E-IOT01A Discovery Kit (Cortex-M4)";
+mc->init = b_l475e_iot01a_init;
+mc->valid_cpu_types = machine_valid_cpu_types;
+
+/* SRAM pre-allocated as part of the SoC instantiation */
+mc->default_ram_size = 0;

[PATCH qemu v2 0/2] hw/arm: Add minimal support for the B-L475E-IOT01A board

2023-12-07 Thread ~inesvarhol
This patch adds a new STM32L4x5 SoC, it is necessary to add support for
the B-L475E-IOT01A board.
The implementation is derived from the STM32F405 SoC and NetduinoPlus2
board.
The implementation contains no peripherals, only memory regions are
implemented.

Changes from v1 to v2:
Thank you Alistair and Alex for your comments on the license.
Just to be safe I changed the MIT license to GPL.

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Arnaud Minier 
Signed-off-by: Inès Varhol 

Inès Varhol (2):
  hw/arm: Add minimal support for the STM32L4x5 SoC
  hw/arm: Add minimal support for the B-L475E-IOT01A board

 MAINTAINERS |  15 ++
 configs/devices/arm-softmmu/default.mak |   1 +
 hw/arm/Kconfig  |  11 +
 hw/arm/b-l475e-iot01a.c |  79 +++
 hw/arm/meson.build  |   2 +
 hw/arm/stm32l4x5_soc.c  | 277 
 include/hw/arm/stm32l4x5_soc.h  |  68 ++
 7 files changed, 453 insertions(+)
 create mode 100644 hw/arm/b-l475e-iot01a.c
 create mode 100644 hw/arm/stm32l4x5_soc.c
 create mode 100644 include/hw/arm/stm32l4x5_soc.h

-- 
2.38.5



[PATCH qemu 2/3] hw/arm: Add STM32L4x5 EXTI QTest testcase

2023-12-07 Thread ~inesvarhol
From: Inès Varhol 

Signed-off-by: Arnaud Minier 
Signed-off-by: Inès Varhol 
---
 tests/qtest/meson.build   |   5 +
 tests/qtest/stm32l4x5_exti-test.c | 485 ++
 2 files changed, 490 insertions(+)
 create mode 100644 tests/qtest/stm32l4x5_exti-test.c

diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
index c9945e69b1..bc62f201a8 100644
--- a/tests/qtest/meson.build
+++ b/tests/qtest/meson.build
@@ -194,6 +194,10 @@ qtests_aspeed = \
   ['aspeed_hace-test',
'aspeed_smc-test',
'aspeed_gpio-test']
+
+qtests_stm32l4x5 = \
+  ['stm32l4x5_exti-test']
+
 qtests_arm = \
   (config_all_devices.has_key('CONFIG_MPS2') ? ['sse-timer-test'] : []) + \
   (config_all_devices.has_key('CONFIG_CMSDK_APB_DUALTIMER') ? 
['cmsdk-apb-dualtimer-test'] : []) + \
@@ -207,6 +211,7 @@ qtests_arm = \
   (config_all_devices.has_key('CONFIG_TPM_TIS_I2C') ? ['tpm-tis-i2c-test'] : 
[]) + \
   (config_all_devices.has_key('CONFIG_VEXPRESS') ? ['test-arm-mptimer'] : []) 
+ \
   (config_all_devices.has_key('CONFIG_MICROBIT') ? ['microbit-test'] : []) + \
+  (config_all_devices.has_key('CONFIG_STM32L4X5_SOC') ? qtests_stm32l4x5 : []) 
+ \
   ['arm-cpu-features',
'boot-serial-test']
 
diff --git a/tests/qtest/stm32l4x5_exti-test.c 
b/tests/qtest/stm32l4x5_exti-test.c
new file mode 100644
index 00..e105b3dea3
--- /dev/null
+++ b/tests/qtest/stm32l4x5_exti-test.c
@@ -0,0 +1,485 @@
+/*
+ * QTest testcase for STM32L4x5_EXTI
+ *
+ * Copyright (c) 2023 Arnaud Minier 
+ * Copyright (c) 2023 Inès Varhol 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "libqtest-single.h"
+
+#define EXTI_BASE_ADDR 0x40010400
+#define EXTI_IMR1 0x00
+#define EXTI_EMR1 0x04
+#define EXTI_RTSR1 0x08
+#define EXTI_FTSR1 0x0C
+#define EXTI_SWIER1 0x10
+#define EXTI_PR1 0x14
+#define EXTI_IMR2 0x20
+#define EXTI_EMR2 0x24
+#define EXTI_RTSR2 0x28
+#define EXTI_FTSR2 0x2C
+#define EXTI_SWIER2 0x30
+#define EXTI_PR2 0x34
+
+#define NVIC_ISER 0xE000E100
+#define NVIC_ISPR 0xE000E200
+#define NVIC_ICPR 0xE000E280
+
+#define EXTI0_IRQ 6
+#define EXTI1_IRQ 7
+#define EXTI35_IRQ 1
+
+static void enable_nvic_irq(unsigned int n)
+{
+writel(NVIC_ISER, 1 << n);
+}
+
+static void unpend_nvic_irq(unsigned int n)
+{
+writel(NVIC_ICPR, 1 << n);
+}
+
+static bool check_nvic_pending(unsigned int n)
+{
+return readl(NVIC_ISPR) & (1 << n);
+}
+
+static void exti_writel(unsigned int offset, uint32_t value)
+{
+writel(EXTI_BASE_ADDR + offset, value);
+}
+
+static uint32_t exti_readl(unsigned int offset)
+{
+return readl(EXTI_BASE_ADDR + offset);
+}
+
+static void test_reg_write_read(void)
+{
+/* Test that non-reserved bits in xMR and xTSR can be set and cleared */
+
+exti_writel(EXTI_IMR1, 0x);
+uint32_t imr1 = exti_readl(EXTI_IMR1);
+g_assert_cmpuint(imr1, ==, 0x);
+exti_writel(EXTI_IMR1, 0x);
+imr1 = exti_readl(EXTI_IMR1);
+g_assert_cmpuint(imr1, ==, 0x);
+
+exti_writel(EXTI_EMR1, 0x);
+uint32_t emr1 = exti_readl(EXTI_EMR1);
+g_assert_cmpuint(emr1, ==, 0x);
+exti_writel(EXTI_EMR1, 0x);
+emr1 = exti_readl(EXTI_EMR1);
+g_assert_cmpuint(emr1, ==, 0x);
+
+exti_writel(EXTI_RTSR1, 0x);
+uint32_t rtsr1 = exti_readl(EXTI_RTSR1);
+g_assert_cmpuint(rtsr1, ==, 0x007D);
+exti_writel(EXTI_RTSR1, 0x);
+rtsr1 = exti_readl(EXTI_RTSR1);
+g_assert_cmpuint(rtsr1, ==, 0x);
+
+exti_writel(EXTI_FTSR1, 0x);
+uint32_t ftsr1 = exti_readl(EXTI_FTSR1);
+g_assert_cmpuint(ftsr1, ==, 0x007D);
+exti_writel(EXTI_FTSR1, 0x);
+ftsr1 = exti_readl(EXTI_FTSR1);
+g_assert_cmpuint(ftsr1, ==, 0x);
+
+exti_writel(EXTI_IMR2, 0x);
+uint32_t imr2 = exti_readl(EXTI_IMR2);
+g_assert_cmpuint(imr2, ==, 0x00FF);
+exti_writel(EXTI_IMR2, 0x);
+imr2 = exti_readl(EXTI_IMR2);
+g_assert_cmpuint(imr2, ==, 0x);
+
+exti_writel(EXTI_EMR2, 0x);
+uint32_t emr2 = exti_readl(EXTI_EMR2);
+g_assert_cmpuint(emr2, ==, 0x00FF);
+exti_writel(EXTI_EMR2, 0x);
+emr2 = exti_readl(EXTI_EMR2);
+g_assert_cmpuint(emr2, ==, 0x);
+
+exti_writel(EXTI_RTSR2, 0x);
+uint32_t rtsr2 = exti_readl(EXTI_RTSR2);
+g_assert_cmpuint(rtsr2, ==, 0x0078);
+exti_writel(EXTI_RTSR2, 0x);
+rtsr2 = exti_readl(EXTI_RTSR2);
+g_assert_cmpuint(rtsr2, ==, 0x);
+
+exti_writel(EXTI_FTSR2, 0x);
+uint32_t ftsr2 = exti_readl(EXTI_FTSR2);
+g_assert_cmpuint(ftsr2, ==, 0x0078);
+exti_writel(EXTI_FTSR2, 0x);
+ftsr2 = exti_readl(EXTI_FTSR2);
+g_assert_cmpuint(ftsr2, ==, 0x);
+}
+
+static void test_direct_lines_write(void)
+{
+/* Test that direct lines reserved bits 

[PATCH qemu 1/3] hw/arm: Implement STM32L4x5 EXTI

2023-12-07 Thread ~inesvarhol
From: Inès Varhol 

Although very similar to the STM32F4xx EXTI, STM32L4x5 EXTI generates
more than 32 event/interrupt requests and thus uses more registers
than STM32F4xx EXTI which generates 23 event/interrupt requests.

Signed-off-by: Arnaud Minier 
Signed-off-by: Inès Varhol 
---
 hw/misc/Kconfig  |   3 +
 hw/misc/meson.build  |   1 +
 hw/misc/stm32l4x5_exti.c | 299 +++
 hw/misc/trace-events |   5 +
 include/hw/misc/stm32l4x5_exti.h |  61 +++
 5 files changed, 369 insertions(+)
 create mode 100644 hw/misc/stm32l4x5_exti.c
 create mode 100644 include/hw/misc/stm32l4x5_exti.h

diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
index cc8a8c1418..3efe3dc2cc 100644
--- a/hw/misc/Kconfig
+++ b/hw/misc/Kconfig
@@ -87,6 +87,9 @@ config STM32F4XX_SYSCFG
 config STM32F4XX_EXTI
 bool
 
+config STM32L4X5_EXTI
+bool
+
 config MIPS_ITU
 bool
 
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
index 36c20d5637..16db6e228d 100644
--- a/hw/misc/meson.build
+++ b/hw/misc/meson.build
@@ -110,6 +110,7 @@ system_ss.add(when: 'CONFIG_XLNX_VERSAL_TRNG', if_true: 
files(
 system_ss.add(when: 'CONFIG_STM32F2XX_SYSCFG', if_true: 
files('stm32f2xx_syscfg.c'))
 system_ss.add(when: 'CONFIG_STM32F4XX_SYSCFG', if_true: 
files('stm32f4xx_syscfg.c'))
 system_ss.add(when: 'CONFIG_STM32F4XX_EXTI', if_true: 
files('stm32f4xx_exti.c'))
+system_ss.add(when: 'CONFIG_STM32L4X5_EXTI', if_true: 
files('stm32l4x5_exti.c'))
 system_ss.add(when: 'CONFIG_MPS2_FPGAIO', if_true: files('mps2-fpgaio.c'))
 system_ss.add(when: 'CONFIG_MPS2_SCC', if_true: files('mps2-scc.c'))
 
diff --git a/hw/misc/stm32l4x5_exti.c b/hw/misc/stm32l4x5_exti.c
new file mode 100644
index 00..4ab4f334aa
--- /dev/null
+++ b/hw/misc/stm32l4x5_exti.c
@@ -0,0 +1,299 @@
+/*
+ * STM32L4x5 EXTI (Extended interrupts and events controller)
+ *
+ * Copyright (c) 2014 Alistair Francis 
+ * Copyright (c) 2023 Arnaud Minier 
+ * Copyright (c) 2023 Samuel Tardieu 
+ * Copyright (c) 2023 Inès Varhol 
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * Based on the stm32f4xx_exti by Alistair Francis.
+ * The reference used is the STMicroElectronics RM0351 Reference manual
+ * for STM32L4x5 and STM32L4x6 advanced Arm ® -based 32-bit MCUs.
+ * 
https://www.st.com/en/microcontrollers-microprocessors/stm32l4x5/documentation.html
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "trace.h"
+#include "hw/irq.h"
+#include "migration/vmstate.h"
+#include "hw/misc/stm32l4x5_exti.h"
+
+#define EXTI_IMR1   0x00
+#define EXTI_EMR1   0x04
+#define EXTI_RTSR1  0x08
+#define EXTI_FTSR1  0x0C
+#define EXTI_SWIER1 0x10
+#define EXTI_PR10x14
+#define EXTI_IMR2   0x20
+#define EXTI_EMR2   0x24
+#define EXTI_RTSR2  0x28
+#define EXTI_FTSR2  0x2C
+#define EXTI_SWIER2 0x30
+#define EXTI_PR20x34
+
+#define EXTI_NUM_GPIO_EVENT_IN_LINES 16
+
+/* 0b_1010__ */
+#define DIRECT_LINE_MASK1 0xFF82
+/* 0b___1111 */
+#define DIRECT_LINE_MASK2 0x0087
+/* 0b___ */
+#define RESERVED_BITS_MASK2 0xFF00
+
+/* 0b___0000 */
+#define ACTIVABLE_MASK2 (~DIRECT_LINE_MASK2 & ~RESERVED_BITS_MASK2)
+
+static void stm32l4x5_exti_reset_hold(Object *obj)
+{
+Stm32l4x5ExtiState *s = STM32L4X5_EXTI(obj);
+
+s->imr[0] = DIRECT_LINE_MASK1;
+s->emr[0] = 0x;
+s->rtsr[0] = 0x;
+s->ftsr[0] = 0x;
+s->swier[0] = 0x;
+s->pr[0] = 0x;
+
+s->imr[1] = DIRECT_LINE_MASK2;
+s->emr[1] = 0x;
+s->rtsr[1] = 0x;
+s->ftsr[1] = 0x;
+s->swier[1] = 0x;
+s->pr[1] = 0x;
+}
+
+static void stm32l4x5_exti_set_irq(void *opaque, int irq, int level)
+{
+Stm32l4x5ExtiState *s = opaque;
+const unsigned n = irq >= 

[PATCH qemu 0/3] hw/arm: Add device STM32L4x5 EXTI

2023-12-07 Thread ~inesvarhol
This patch adds a new STM32L4x5 EXTI device and is part
of a series implementing the STM32L4x5 with a few peripherals.

The patch is split up in 3 commits :
- implementing the EXTI device
- adding tests (that fail in this commit)
- connecting the EXTI device to the SoC (the tests pass in this commit)

Thank you Alistair for the review and very helpful answers !

Sincerely,
Ines Varhol

Changes from v3 to non-RFC v1:
- separating the patch in 3 commits
- justifying in the commit message why we implement a new
model instead of changing the existing stm32f4xx_exti
- changed irq_raise to irq_pulse in register SWIERx write (in
stm32l4x5_exti_write)
to be consistent with the irq_pulse in stm32l4x5_exti_set_irq (and also
both these interrupts
are edge-triggered)
- changed the license to GPL

Changes from v2 to v3:
- adding more tests writing/reading in exti registers
- adding tests checking that interrupt work by reading NVIC registers
- correcting exti_write in SWIER (so it sets an irq only when a bit goes
from '0' to '1')
- correcting exti_set_irq (so it never writes in PR when the relevant
bit in IMR is '0')

Changes from v1 to v2:
- use arrays to deduplicate code and logic
- move internal constant EXTI_NUM_GPIO_EVENT_IN_LINES from the header
to the .c file
- Improve copyright headers
- replace static const with #define
- use the DEFINE_TYPES macro
- fill the impl and valid field of the exti's MemoryRegionOps
- fix invalid test caused by a last minute change

Based-on: <170100975340.4879.58441084840923...@git.sr.ht>
([PATCH qemu 0/2] hw/arm: Add minimal support for the B-L475E-IOT01A
board)

Inès Varhol (3):
  hw/arm: Implement STM32L4x5 EXTI
  hw/arm: Add STM32L4x5 EXTI QTest testcase
  hw/arm: Connect STM32L4x5 EXTI to STM32L4x5 SoC

 hw/arm/Kconfig|   1 +
 hw/arm/stm32l4x5_soc.c|  65 +++-
 hw/misc/Kconfig   |   3 +
 hw/misc/meson.build   |   1 +
 hw/misc/stm32l4x5_exti.c  | 299 ++
 hw/misc/trace-events  |   5 +
 include/hw/arm/stm32l4x5_soc.h|   3 +
 include/hw/misc/stm32l4x5_exti.h  |  61 
 tests/qtest/meson.build   |   5 +
 tests/qtest/stm32l4x5_exti-test.c | 485 ++
 10 files changed, 926 insertions(+), 2 deletions(-)
 create mode 100644 hw/misc/stm32l4x5_exti.c
 create mode 100644 include/hw/misc/stm32l4x5_exti.h
 create mode 100644 tests/qtest/stm32l4x5_exti-test.c

-- 
2.38.5



[PATCH qemu 3/3] hw/arm: Connect STM32L4x5 EXTI to STM32L4x5 SoC

2023-12-07 Thread ~inesvarhol
From: Inès Varhol 

Signed-off-by: Arnaud Minier 
Signed-off-by: Inès Varhol 
---
 hw/arm/Kconfig |  1 +
 hw/arm/stm32l4x5_soc.c | 65 --
 include/hw/arm/stm32l4x5_soc.h |  3 ++
 3 files changed, 67 insertions(+), 2 deletions(-)

diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index b95576fb0c..28d378ed83 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -458,6 +458,7 @@ config STM32L4X5_SOC
 bool
 select ARM_V7M
 select OR_IRQ
+select STM32L4X5_EXTI
 
 config XLNX_ZYNQMP_ARM
 bool
diff --git a/hw/arm/stm32l4x5_soc.c b/hw/arm/stm32l4x5_soc.c
index f476878b2c..cf786eac1d 100644
--- a/hw/arm/stm32l4x5_soc.c
+++ b/hw/arm/stm32l4x5_soc.c
@@ -45,10 +45,51 @@
 #define SRAM2_BASE_ADDRESS 0x1000
 #define SRAM2_SIZE (32 * KiB)
 
+#define EXTI_ADDR 0x40010400
+
+#define NUM_EXTI_IRQ 40
+/* Match exti line connections with their CPU IRQ number */
+/* See Vector Table (Reference Manual p.396) */
+static const int exti_irq[NUM_EXTI_IRQ] = {
+6,  /* GPIO[0] */
+7,  /* GPIO[1] */
+8,  /* GPIO[2] */
+9,  /* GPIO[3] */
+10, /* GPIO[4] */
+23, 23, 23, 23, 23, /* GPIO[5..9]  */
+40, 40, 40, 40, 40, 40, /* GPIO[10..15]*/
+1,  /* PVD */
+67, /* OTG_FS_WKUP, Direct */
+41, /* RTC_ALARM   */
+2,  /* RTC_TAMP_STAMP2/CSS_LSE */
+3,  /* RTC wakeup timer*/
+63, /* COMP1   */
+63, /* COMP2   */
+31, /* I2C1 wakeup, Direct */
+33, /* I2C2 wakeup, Direct */
+72, /* I2C3 wakeup, Direct */
+37, /* USART1 wakeup, Direct   */
+38, /* USART2 wakeup, Direct   */
+39, /* USART3 wakeup, Direct   */
+52, /* UART4 wakeup, Direct*/
+53, /* UART4 wakeup, Direct*/
+70, /* LPUART1 wakeup, Direct  */
+65, /* LPTIM1, Direct  */
+66, /* LPTIM2, Direct  */
+76, /* SWPMI1 wakeup, Direct   */
+1,  /* PVM1 wakeup */
+1,  /* PVM2 wakeup */
+1,  /* PVM3 wakeup */
+1,  /* PVM4 wakeup */
+78  /* LCD wakeup, Direct  */
+};
+
 static void stm32l4x5_soc_initfn(Object *obj)
 {
 Stm32l4x5SocState *s = STM32L4X5_SOC(obj);
 
+object_initialize_child(obj, "exti", >exti, TYPE_STM32L4X5_EXTI);
+
 s->sysclk = qdev_init_clock_in(DEVICE(s), "sysclk", NULL, NULL, 0);
 s->refclk = qdev_init_clock_in(DEVICE(s), "refclk", NULL, NULL, 0);
 }
@@ -59,7 +100,9 @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, 
Error **errp)
 Stm32l4x5SocState *s = STM32L4X5_SOC(dev_soc);
 const Stm32l4x5SocClass *sc = STM32L4X5_SOC_GET_CLASS(dev_soc);
 MemoryRegion *system_memory = get_system_memory();
-DeviceState *armv7m;
+DeviceState *dev, *armv7m;
+SysBusDevice *busdev;
+int i;
 
 /*
  * We use s->refclk internally and only define it with qdev_init_clock_in()
@@ -124,6 +167,25 @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, 
Error **errp)
 return;
 }
 
+dev = DEVICE(>exti);
+if (!sysbus_realize(SYS_BUS_DEVICE(>exti), errp)) {
+return;
+}
+busdev = SYS_BUS_DEVICE(dev);
+sysbus_mmio_map(busdev, 0, EXTI_ADDR);
+for (i = 0; i < NUM_EXTI_IRQ; i++) {
+/* IRQ seems not to be connected ? */
+sysbus_connect_irq(busdev, i, qdev_get_gpio_in(armv7m, exti_irq[i]));
+}
+
+/*
+ * Uncomment when Syscfg is implemented
+ * for (i = 0; i < 16; i++) {
+ * qdev_connect_gpio_out(DEVICE(>syscfg), i,
+ *   qdev_get_gpio_in(dev, i));
+ * }
+ */
+
 /* APB1 BUS */
 create_unimplemented_device("TIM2",  0x4000, 0x400);
 create_unimplemented_device("TIM3",  0x4400, 0x400);
@@ -164,7 +226,6 @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, 
Error **errp)
 create_unimplemented_device("SYSCFG",0x4001, 0x30);
 create_unimplemented_device("VREFBUF",   0x40010030, 0x1D0);
 create_unimplemented_device("COMP",  0x40010200, 0x200);
-create_unimplemented_device("EXTI",  0x40010400, 0x400);
 /* RESERVED:0x40010800, 0x1400 */
 create_unimplemented_device("FIREWALL",  0x40011C00, 0x400);
 /* RESERVED:0x40012000, 0x800 */
diff 

[PATCH v4 06/17] mcdstub: -mcd start option added, mcd specific defines added

2023-12-07 Thread Nicolas Eder
---
 debug/mcdstub/mcdstub.c  | 201 +++
 debug/mcdstub/meson.build|  12 ++
 debug/meson.build|   1 +
 include/mcdstub/mcdstub.h| 152 +++
 include/mcdstub/mcdstub_common.h |  46 +++
 qemu-options.hx  |  18 +++
 system/vl.c  |  13 ++
 7 files changed, 443 insertions(+)

diff --git a/debug/mcdstub/mcdstub.c b/debug/mcdstub/mcdstub.c
index c24aaf1202..32f4d1980f 100644
--- a/debug/mcdstub/mcdstub.c
+++ b/debug/mcdstub/mcdstub.c
@@ -16,3 +16,204 @@
  *
  * SPDX-License-Identifier: LGPL-2.0+
  */
+
+#include "qemu/osdep.h"
+#include "qemu/ctype.h"
+#include "qemu/cutils.h"
+#include "qemu/module.h"
+#include "qemu/error-report.h"
+#include "qapi/error.h"
+#include "chardev/char.h"
+#include "chardev/char-fe.h"
+#include "sysemu/cpus.h"
+#include "sysemu/hw_accel.h"
+#include "sysemu/runstate.h"
+
+#include "mcdstub/mcd_shared_defines.h"
+#include "mcdstub/mcdstub.h"
+
+typedef struct {
+CharBackend chr;
+} MCDSystemState;
+
+MCDSystemState mcdserver_system_state;
+
+MCDState mcdserver_state;
+
+/**
+ * mcd_supports_guest_debug() - Returns true if debugging the selected
+ * accelerator is supported.
+ */
+static bool mcd_supports_guest_debug(void)
+{
+const AccelOpsClass *ops = cpus_get_accel();
+if (ops->supports_guest_debug) {
+return ops->supports_guest_debug();
+}
+return false;
+}
+
+#ifndef _WIN32
+static void mcd_sigterm_handler(int signal)
+{
+if (runstate_is_running()) {
+vm_stop(RUN_STATE_PAUSED);
+}
+}
+#endif
+
+/**
+ * mcd_vm_state_change() - Handles a state change of the QEMU VM.
+ *
+ * This function is called when the QEMU VM goes through a state transition.
+ * It stores the runstate the CPU is in to the cpu_state and when in
+ * RUN_STATE_DEBUG it collects additional data on what watchpoint was hit.
+ * This function also resets the singlestep behavior.
+ * @running: True if he VM is running.
+ * @state: The new (and active) VM run state.
+ */
+static void mcd_vm_state_change(void *opaque, bool running, RunState state)
+{
+}
+
+/**
+ * mcd_chr_can_receive() - Returns the maximum packet length of a TCP packet.
+ */
+static int mcd_chr_can_receive(void *opaque)
+{
+return MAX_PACKET_LENGTH;
+}
+
+/**
+ * mcd_chr_receive() - Handles receiving a TCP packet.
+ *
+ * This function gets called by QEMU when a TCP packet is received.
+ * It iterates over that packet an calls :c:func:`mcd_read_byte` for each char
+ * of the packet.
+ * @buf: Content of the packet.
+ * @size: Length of the packet.
+ */
+static void mcd_chr_receive(void *opaque, const uint8_t *buf, int size)
+{
+}
+
+/**
+ * mcd_chr_event() - Handles a TCP client connect.
+ *
+ * This function gets called by QEMU when a TCP cliet connects to the opened
+ * TCP port. It attaches the first process. From here on TCP packets can be
+ * exchanged.
+ * @event: Type of event.
+ */
+static void mcd_chr_event(void *opaque, QEMUChrEvent event)
+{
+}
+
+/**
+ * mcd_init_mcdserver_state() - Initializes the mcdserver_state struct.
+ *
+ * This function allocates memory for the mcdserver_state struct and sets
+ * all of its members to their inital values. This includes setting the
+ * cpu_state to halted and initializing the query functions with
+ * :c:func:`init_query_cmds_table`.
+ */
+static void mcd_init_mcdserver_state(void)
+{
+}
+
+/**
+ * reset_mcdserver_state() - Resets the mcdserver_state struct.
+ *
+ * This function deletes all processes connected to the mcdserver_state.
+ */
+static void reset_mcdserver_state(void)
+{
+}
+
+/**
+ * create_processes() - Sorts all processes and calls
+ * :c:func:`mcd_create_default_process`.
+ *
+ * This function sorts all connected processes with the qsort function.
+ * Afterwards, it creates a new process with
+ * :c:func:`mcd_create_default_process`.
+ * @s: A MCDState object.
+ */
+static void create_processes(MCDState *s)
+{
+}
+
+int mcdserver_start(const char *device)
+{
+char mcd_device_config[TCP_CONFIG_STRING_LENGTH];
+char mcd_tcp_port[TCP_CONFIG_STRING_LENGTH];
+Chardev *chr = NULL;
+
+if (!first_cpu) {
+error_report("mcdstub: meaningless to attach to a "
+ "machine without any CPU.");
+return -1;
+}
+
+if (!mcd_supports_guest_debug()) {
+error_report("mcdstub: current accelerator doesn't "
+ "support guest debugging");
+return -1;
+}
+
+if (!device) {
+return -1;
+}
+
+/* if device == default -> set tcp_port = tcp:: */
+if (strcmp(device, "default") == 0) {
+snprintf(mcd_tcp_port, sizeof(mcd_tcp_port), "tcp::%s",
+MCD_DEFAULT_TCP_PORT);
+device = mcd_tcp_port;
+}
+
+if (strcmp(device, "none") != 0) {
+if (strstart(device, "tcp:", NULL)) {
+/* enforce required TCP attributes */
+snprintf(mcd_device_config, sizeof(mcd_device_config),
+   

[PATCH v4 16/17] mcdstub: register access added

2023-12-07 Thread Nicolas Eder
---
 debug/mcdstub/arm_mcdstub.c   |  28 +++
 debug/mcdstub/mcdstub.c   | 369 ++
 include/mcdstub/arm_mcdstub.h |  15 ++
 3 files changed, 412 insertions(+)

diff --git a/debug/mcdstub/arm_mcdstub.c b/debug/mcdstub/arm_mcdstub.c
index f14e677480..6d46e1bd7a 100644
--- a/debug/mcdstub/arm_mcdstub.c
+++ b/debug/mcdstub/arm_mcdstub.c
@@ -18,6 +18,7 @@
  */
 
 #include "qemu/osdep.h"
+#include "exec/memory.h"
 #include "mcdstub/arm_mcdstub.h"
 
 int arm_mcd_store_mem_spaces(CPUState *cpu, GArray *memspaces)
@@ -259,3 +260,30 @@ uint16_t arm_mcd_get_opcode(CPUState *cs, uint32_t n)
 /* TODO: not working with current build structure */
 return 0;
 }
+
+AddressSpace *arm_mcd_get_address_space(uint32_t cpu_id,
+mcd_mem_space_st mem_space)
+{
+/* get correct address space name */
+char as_name[ARGUMENT_STRING_LENGTH] = {0};
+if (mem_space.is_secure) {
+sprintf(as_name, "cpu-secure-memory-%u", cpu_id);
+} else {
+sprintf(as_name, "cpu-memory-%u", cpu_id);
+}
+/* return correct address space */
+AddressSpace *as = mcd_find_address_space(as_name);
+return as;
+}
+
+MemTxAttrs arm_mcd_get_memtxattrs(mcd_mem_space_st mem_space)
+{
+MemTxAttrs attributes = {0};
+if (mem_space.is_secure) {
+attributes.secure = 1;
+attributes.space = 2;
+} else {
+attributes.space = 1;
+}
+return attributes;
+}
diff --git a/debug/mcdstub/mcdstub.c b/debug/mcdstub/mcdstub.c
index cc1587396d..e5fd575834 100644
--- a/debug/mcdstub/mcdstub.c
+++ b/debug/mcdstub/mcdstub.c
@@ -857,6 +857,326 @@ static void handle_reset(GArray *params, void *user_ctx)
  */
 }
 
+/**
+ * mcd_memtohex() - Converts a byte array into a hex string.
+ *
+ * @mem: Pointer to byte array.
+ * @buf: Pointer to hex string.
+ * @len: Number of bytes.
+ */
+static void mcd_memtohex(GString *buf, const uint8_t *mem, int len)
+{
+int i, c;
+for (i = 0; i < len; i++) {
+c = mem[i];
+g_string_append_c(buf, nibble_to_hexchar(c >> 4));
+g_string_append_c(buf, nibble_to_hexchar(c & 0xf));
+}
+g_string_append_c(buf, '\0');
+}
+
+/**
+ * mcd_hextomem() - Converts a hex string into a byte array.
+ *
+ * @mem: Pointer to byte array.
+ * @buf: Pointer to hex string.
+ * @len: Number of bytes.
+ */
+static void mcd_hextomem(GByteArray *mem, const char *buf, int len)
+{
+int i;
+
+for (i = 0; i < len; i++) {
+guint8 byte = hexchar_to_nibble(buf[0]) << 4 |
+  hexchar_to_nibble(buf[1]);
+g_byte_array_append(mem, , 1);
+buf += 2;
+}
+}
+
+/**
+ * mcd_read_register() - Reads a registers data and stores it into the buf.
+ *
+ * This function collects the register type and internal ID
+ * (depending on the XML file). Then it calls the architecture specific
+ * read function. For ARM this is :c:func:`arm_mcd_read_register`.
+ * @cpu: CPU to which the register belongs.
+ * @buf: Byte array with register data.
+ * @reg: General ID of the register.
+ */
+static int mcd_read_register(CPUState *cpu, GByteArray *buf, int reg)
+{
+CPUClass *cc = CPU_GET_CLASS(cpu);
+CPUArchState *env = cpu_env(cpu);
+GDBRegisterState *r;
+
+if (reg < cc->gdb_num_core_regs) {
+return cc->gdb_read_register(cpu, buf, reg);
+}
+
+for (guint i = 0; i < cpu->gdb_regs->len; i++) {
+r = _array_index(cpu->gdb_regs, GDBRegisterState, i);
+if (r->base_reg <= reg && reg < r->base_reg + r->num_regs) {
+return r->get_reg(env, buf, reg - r->base_reg);
+}
+}
+return 0;
+}
+
+/**
+ * mcd_write_register() - Writes data from the buf to a register.
+ *
+ * This function collects the register type and internal ID
+ * (depending on the XML file). Then it calls the architecture specific
+ * write function. For ARM this is :c:func:`arm_mcd_write_register`.
+ * @cpu: CPU to which the register belongs.
+ * @mem_buf: Byte array with register data.
+ * @reg: General ID of the register.
+ */
+static int mcd_write_register(CPUState *cpu, uint8_t *mem_buf, int reg)
+{
+CPUClass *cc = CPU_GET_CLASS(cpu);
+CPUArchState *env = cpu_env(cpu);
+GDBRegisterState *r;
+
+if (reg < cc->gdb_num_core_regs) {
+return cc->gdb_write_register(cpu, mem_buf, reg);
+}
+
+for (guint i = 0; i < cpu->gdb_regs->len; i++) {
+r = _array_index(cpu->gdb_regs, GDBRegisterState, i);
+if (r->base_reg <= reg && reg < r->base_reg + r->num_regs) {
+return r->set_reg(env, mem_buf, reg - r->base_reg);
+}
+}
+return 0;
+}
+
+/**
+ * handle_read_register() - Handler for reading a register.
+ *
+ * This function calls :c:func:`mcd_read_register` to read a register. The
+ * register data gets stored in the mem_buf byte array. The data then gets
+ * converted into a hex string with :c:func:`mcd_memtohex` and then send.
+ * @params: GArray with all TCP packet parameters.
+ */
+static void 

[PATCH v4 00/17] first version of mcdstub

2023-12-07 Thread Nicolas Eder
SUMMARY
===

This patch-set introduces the first version of the mcdstub.
The mcdstub is a debug interface, which enables debugging QEMU
using the MCD (Multi-Core Debug) API.
The mcdstub uses TCP to communicate with the host debug software. However,
because MCD is merely an API, the TCP communication is not part of
the MCD spec but specific to this project.

To translate between the MCD API and the TCP data stream coming from the 
mcdstub,
the host has to use a shared library (.dll/.so).
Such a shared library is available at: https://gitlab.com/lauterbach/mcdrefsrv
The MCD API itself can be downloaded here: 
https://repo.lauterbach.com/sprint_mcd_api_v1_0.zip

QUICK START
===

Attention: MCD is currently only supported for qemu-system-arm !

Three components are required to Debug QEMU via MCD:

1. qemu-system-arm (built with this patch series applied).
2. MCD shared library (translates between the MCD API and TCP data).
3. Host debugging software with support for the MCD API (e.g. Lauterbach 
TRACE32).

To activate the mcdstub, just use the "mcd" launch option in combination with
a TCP port.

With the default TCP port 1235:

$ qemu-system-arm -M virt -cpu cortex-a15 -mcd default

With a custom TCP port:

$ qemu-system-arm -M virt -cpu cortex-a15 -mcd tcp::1235

QEMU will listen for an MCD host to connect to the specified port.

IMPORTANT CHANGES
=

1. DebugClass:

This patch-set introduces the DebugClass to the QOM, which is used to abstract
GDB/MCD specific debugger details.
It is declared in include/qemu/debug.h, defined in debug/common/debug.c
It currently only offers one function: set_stop_cpu, which gets called
in cpu_handle_guest_debug in softmmu/cpus.c.
In the future, other functions could be moved from the mcd/gdbstub
to the DebugClass.

2. mcd launch option:

This patch-set introduces the mcd launch option to QEMU. The quick start
section describes how to use it.

3. MCD debugging features:

* Go, break, step
* Read/write memory (user space only)
* Read/write registers (GPR and CP)
* Set breakpoints and watchpoints.

=

Signed-off-by: Nicolas Eder 

Nicolas Eder (17):
  gdbstub, mcdstub: file and build structure adapted to accomodate for
the mcdstub
  gdbstub: hex conversion functions moved to cutils.h
  gdbstub: GDBRegisterState moved to gdbstub.h so it can be used outside
of the gdbstub
  gdbstub: DebugClass added to system mode.
  mcdstub: memory helper functions added
  mcdstub: -mcd start option added, mcd specific defines added
  mcdstub: mcdserver initialization functions added
  cutils: qemu_strtou32 function added
  mcdstub: TCP packet plumbing added
  mcdstub: open and close server funcitons added
  mcdstub: system and core queries added
  mcdstub: all core specific queries added
  mcdstub: go, step and break added
  mcdstub: state query added
  mcdstub: skeleton for reset handling added
  mcdstub: register access added
  mcdstub: break/watchpoints added

 MAINTAINERS  |   11 +-
 debug/common/debug.c |   51 +
 debug/common/meson.build |1 +
 {gdbstub => debug/gdbstub}/gdbstub.c |   27 +-
 {gdbstub => debug/gdbstub}/internals.h   |   26 -
 {gdbstub => debug/gdbstub}/meson.build   |0
 {gdbstub => debug/gdbstub}/syscalls.c|0
 {gdbstub => debug/gdbstub}/system.c  |   18 +
 {gdbstub => debug/gdbstub}/trace-events  |0
 debug/gdbstub/trace.h|1 +
 {gdbstub => debug/gdbstub}/user-target.c |0
 {gdbstub => debug/gdbstub}/user.c|0
 debug/mcdstub/arm_mcdstub.c  |  289 +++
 debug/mcdstub/mcdstub.c  | 2494 ++
 debug/mcdstub/meson.build|   12 +
 debug/meson.build|3 +
 gdbstub/trace.h  |1 -
 include/exec/cpu-common.h|3 +
 include/exec/gdbstub.h   |8 +
 include/exec/memory.h|9 +
 include/hw/boards.h  |1 +
 include/mcdstub/arm_mcdstub.h|  118 +
 include/mcdstub/mcd_shared_defines.h |  132 ++
 include/mcdstub/mcdstub.h|  165 ++
 include/mcdstub/mcdstub_common.h |   83 +
 include/qemu/cutils.h|   32 +
 include/qemu/debug.h |   38 +
 include/qemu/typedefs.h  |2 +
 meson.build  |4 +-
 qemu-options.hx  |   18 +
 system/cpus.c|9 +-
 system/memory.c  |   11 +
 system/physmem.c |   26 +
 system/vl.c  |   13 +
 util/cutils.c|   30 +
 35 files changed, 3588 insertions(+), 48 deletions(-)
 create mode 100644 debug/common/debug.c
 create mode 100644 debug/common/meson.build
 rename {gdbstub => debug/gdbstub}/gdbstub.c (98%)
 rename {gdbstub => 

[PATCH v4 05/17] mcdstub: memory helper functions added

2023-12-07 Thread Nicolas Eder
---
 include/exec/cpu-common.h |  3 +++
 include/exec/memory.h |  9 +
 system/memory.c   | 11 +++
 system/physmem.c  | 26 ++
 4 files changed, 49 insertions(+)

diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h
index 41115d8919..dd989b5ab2 100644
--- a/include/exec/cpu-common.h
+++ b/include/exec/cpu-common.h
@@ -182,6 +182,9 @@ int ram_block_discard_range(RAMBlock *rb, uint64_t start, 
size_t length);
 int cpu_memory_rw_debug(CPUState *cpu, vaddr addr,
 void *ptr, size_t len, bool is_write);
 
+int cpu_memory_get_physical_address(CPUState *cpu, vaddr *addr, size_t *len);
+
+
 /* vl.c */
 void list_cpus(void);
 
diff --git a/include/exec/memory.h b/include/exec/memory.h
index 831f7c996d..174de807d5 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -3142,6 +3142,15 @@ bool ram_block_discard_is_disabled(void);
  */
 bool ram_block_discard_is_required(void);
 
+/*
+ * mcd_find_address_space() - Find the address spaces with the corresponding
+ * name.
+ *
+ * Currently only used by the mcd debugger.
+ * @as_name: Name to look for.
+ */
+AddressSpace *mcd_find_address_space(const char *as_name);
+
 #endif
 
 #endif
diff --git a/system/memory.c b/system/memory.c
index 798b6c0a17..9a8fa79e0c 100644
--- a/system/memory.c
+++ b/system/memory.c
@@ -3562,6 +3562,17 @@ void mtree_info(bool flatview, bool dispatch_tree, bool 
owner, bool disabled)
 }
 }
 
+AddressSpace *mcd_find_address_space(const char *as_name)
+{
+AddressSpace *as;
+QTAILQ_FOREACH(as, _spaces, address_spaces_link) {
+if (strcmp(as->name, as_name) == 0) {
+return as;
+}
+}
+return NULL;
+}
+
 void memory_region_init_ram(MemoryRegion *mr,
 Object *owner,
 const char *name,
diff --git a/system/physmem.c b/system/physmem.c
index a63853a7bc..70733c67c7 100644
--- a/system/physmem.c
+++ b/system/physmem.c
@@ -3422,6 +3422,32 @@ int cpu_memory_rw_debug(CPUState *cpu, vaddr addr,
 return 0;
 }
 
+int cpu_memory_get_physical_address(CPUState *cpu, vaddr *addr, size_t *len)
+{
+hwaddr phys_addr;
+vaddr l, page;
+
+cpu_synchronize_state(cpu);
+MemTxAttrs attrs;
+
+page = *addr & TARGET_PAGE_MASK;
+phys_addr = cpu_get_phys_page_attrs_debug(cpu, page, );
+/* if no physical page mapped, return an error */
+if (phys_addr == -1) {
+return -1;
+}
+l = (page + TARGET_PAGE_SIZE) - *addr;
+if (l > *len) {
+l = *len;
+}
+phys_addr += (*addr & ~TARGET_PAGE_MASK);
+
+/* set output values */
+*addr = phys_addr;
+*len = l;
+return 0;
+}
+
 /*
  * Allows code that needs to deal with migration bitmaps etc to still be built
  * target independent.
-- 
2.34.1




[PATCH v4 11/17] mcdstub: system and core queries added

2023-12-07 Thread Nicolas Eder
---
 debug/mcdstub/arm_mcdstub.c  | 243 
 debug/mcdstub/mcdstub.c  | 373 ++-
 debug/mcdstub/meson.build|   2 +-
 include/mcdstub/arm_mcdstub.h|  85 +++
 include/mcdstub/mcdstub.h|   5 -
 include/mcdstub/mcdstub_common.h |  19 ++
 6 files changed, 720 insertions(+), 7 deletions(-)

diff --git a/debug/mcdstub/arm_mcdstub.c b/debug/mcdstub/arm_mcdstub.c
index c24aaf1202..f14e677480 100644
--- a/debug/mcdstub/arm_mcdstub.c
+++ b/debug/mcdstub/arm_mcdstub.c
@@ -16,3 +16,246 @@
  *
  * SPDX-License-Identifier: LGPL-2.0+
  */
+
+#include "qemu/osdep.h"
+#include "mcdstub/arm_mcdstub.h"
+
+int arm_mcd_store_mem_spaces(CPUState *cpu, GArray *memspaces)
+{
+int nr_address_spaces = cpu->num_ases;
+uint32_t mem_space_id = 0;
+
+mem_space_id++;
+mcd_mem_space_st non_secure = {
+.name = "Non Secure",
+.id = mem_space_id,
+.type = 34,
+.bits_per_mau = 8,
+.invariance = 1,
+.endian = 1,
+.min_addr = 0,
+.max_addr = -1,
+.supported_access_options = 0,
+.is_secure = false,
+.is_physical = false,
+};
+g_array_append_vals(memspaces, (gconstpointer)_secure, 1);
+mem_space_id++;
+mcd_mem_space_st phys_non_secure = {
+.name = "Physical (Non Secure)",
+.id = mem_space_id,
+.type = 18,
+.bits_per_mau = 8,
+.invariance = 1,
+.endian = 1,
+.min_addr = 0,
+.max_addr = -1,
+.supported_access_options = 0,
+.is_secure = false,
+.is_physical = true,
+};
+g_array_append_vals(memspaces, (gconstpointer)_non_secure, 1);
+if (nr_address_spaces > 1) {
+mem_space_id++;
+mcd_mem_space_st secure = {
+.name = "Secure",
+.id = mem_space_id,
+.type = 34,
+.bits_per_mau = 8,
+.invariance = 1,
+.endian = 1,
+.min_addr = 0,
+.max_addr = -1,
+.supported_access_options = 0,
+.is_secure = true,
+.is_physical = false,
+};
+g_array_append_vals(memspaces, (gconstpointer), 1);
+mem_space_id++;
+mcd_mem_space_st phys_secure = {
+.name = "Physical (Secure)",
+.id = mem_space_id,
+.type = 18,
+.bits_per_mau = 8,
+.invariance = 1,
+.endian = 1,
+.min_addr = 0,
+.max_addr = -1,
+.supported_access_options = 0,
+.is_secure = true,
+.is_physical = true,
+};
+g_array_append_vals(memspaces, (gconstpointer)_secure, 1);
+}
+mem_space_id++;
+mcd_mem_space_st gpr = {
+.name = "GPR Registers",
+.id = mem_space_id,
+.type = 1,
+.bits_per_mau = 8,
+.invariance = 1,
+.endian = 1,
+.min_addr = 0,
+.max_addr = -1,
+.supported_access_options = 0,
+};
+g_array_append_vals(memspaces, (gconstpointer), 1);
+mem_space_id++;
+mcd_mem_space_st cpr = {
+.name = "CP15 Registers",
+.id = mem_space_id,
+.type = 1,
+.bits_per_mau = 8,
+.invariance = 1,
+.endian = 1,
+.min_addr = 0,
+.max_addr = -1,
+.supported_access_options = 0,
+};
+g_array_append_vals(memspaces, (gconstpointer), 1);
+return 0;
+}
+
+int arm_mcd_parse_core_xml_file(CPUClass *cc, GArray *reggroups,
+GArray *registers, int *current_group_id)
+{
+const char *xml_filename = NULL;
+const char *current_xml_filename = NULL;
+const char *xml_content = NULL;
+int i = 0;
+
+/* 1. get correct file */
+xml_filename = cc->gdb_core_xml_file;
+for (i = 0; ; i++) {
+current_xml_filename = gdb_static_features[i].xmlname;
+if (!current_xml_filename || (strncmp(current_xml_filename,
+xml_filename, strlen(xml_filename)) == 0
+&& strlen(current_xml_filename) == strlen(xml_filename)))
+break;
+}
+/* without gpr registers we can do nothing */
+if (!current_xml_filename) {
+return -1;
+}
+
+/* 2. add group for gpr registers */
+mcd_reg_group_st gprregs = {
+.name = "GPR Registers",
+.id = *current_group_id
+};
+g_array_append_vals(reggroups, (gconstpointer), 1);
+*current_group_id = *current_group_id + 1;
+
+/* 3. parse xml */
+/* the offset for gpr is always zero */
+xml_content = gdb_static_features[i].xml;
+parse_reg_xml(xml_content, strlen(xml_content), registers,
+MCD_ARM_REG_TYPE_GPR, 0);
+return 0;
+}
+
+int arm_mcd_parse_general_xml_files(CPUState *cpu, GArray *reggroups,
+GArray *registers, int *current_group_id) {
+const char *xml_filename = NULL;
+const char *current_xml_filename = NULL;
+const char *xml_content = NULL;
+uint8_t reg_type;
+

[PATCH v4 03/17] gdbstub: GDBRegisterState moved to gdbstub.h so it can be used outside of the gdbstub

2023-12-07 Thread Nicolas Eder
---
 debug/gdbstub/gdbstub.c | 8 
 include/exec/gdbstub.h  | 8 
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/debug/gdbstub/gdbstub.c b/debug/gdbstub/gdbstub.c
index f43d4355c0..5df7841878 100644
--- a/debug/gdbstub/gdbstub.c
+++ b/debug/gdbstub/gdbstub.c
@@ -45,14 +45,6 @@
 
 #include "internals.h"
 
-typedef struct GDBRegisterState {
-int base_reg;
-int num_regs;
-gdb_get_reg_cb get_reg;
-gdb_set_reg_cb set_reg;
-const char *xml;
-} GDBRegisterState;
-
 GDBState gdbserver_state;
 
 void gdb_init_gdbserver_state(void)
diff --git a/include/exec/gdbstub.h b/include/exec/gdbstub.h
index d8a3c56fa2..cdbad65930 100644
--- a/include/exec/gdbstub.h
+++ b/include/exec/gdbstub.h
@@ -27,6 +27,14 @@ typedef struct GDBFeatureBuilder {
 typedef int (*gdb_get_reg_cb)(CPUArchState *env, GByteArray *buf, int reg);
 typedef int (*gdb_set_reg_cb)(CPUArchState *env, uint8_t *buf, int reg);
 
+typedef struct GDBRegisterState {
+int base_reg;
+int num_regs;
+gdb_get_reg_cb get_reg;
+gdb_set_reg_cb set_reg;
+const char *xml;
+} GDBRegisterState;
+
 /**
  * gdb_register_coprocessor() - register a supplemental set of registers
  * @cpu - the CPU associated with registers
-- 
2.34.1




[PATCH v4 01/17] gdbstub, mcdstub: file and build structure adapted to accomodate for the mcdstub

2023-12-07 Thread Nicolas Eder
mcdstub files created including the shared header between the mcd shared 
library and the mcdstub.
MAINTAINERS file updated
---
 MAINTAINERS  |  11 +-
 debug/common/debug.c |  18 
 debug/common/meson.build |   0
 {gdbstub => debug/gdbstub}/gdbstub.c |   0
 {gdbstub => debug/gdbstub}/internals.h   |   0
 {gdbstub => debug/gdbstub}/meson.build   |   0
 {gdbstub => debug/gdbstub}/syscalls.c|   0
 {gdbstub => debug/gdbstub}/system.c  |   0
 {gdbstub => debug/gdbstub}/trace-events  |   0
 debug/gdbstub/trace.h|   1 +
 {gdbstub => debug/gdbstub}/user-target.c |   0
 {gdbstub => debug/gdbstub}/user.c|   0
 debug/mcdstub/arm_mcdstub.c  |  18 
 debug/mcdstub/mcdstub.c  |  18 
 debug/mcdstub/meson.build|   0
 debug/meson.build|   1 +
 gdbstub/trace.h  |   1 -
 include/mcdstub/arm_mcdstub.h|  18 
 include/mcdstub/mcd_shared_defines.h | 132 +++
 include/mcdstub/mcdstub.h|  18 
 include/mcdstub/mcdstub_common.h |  18 
 include/qemu/debug.h |  18 
 meson.build  |   4 +-
 23 files changed, 272 insertions(+), 4 deletions(-)
 create mode 100644 debug/common/debug.c
 create mode 100644 debug/common/meson.build
 rename {gdbstub => debug/gdbstub}/gdbstub.c (100%)
 rename {gdbstub => debug/gdbstub}/internals.h (100%)
 rename {gdbstub => debug/gdbstub}/meson.build (100%)
 rename {gdbstub => debug/gdbstub}/syscalls.c (100%)
 rename {gdbstub => debug/gdbstub}/system.c (100%)
 rename {gdbstub => debug/gdbstub}/trace-events (100%)
 create mode 100644 debug/gdbstub/trace.h
 rename {gdbstub => debug/gdbstub}/user-target.c (100%)
 rename {gdbstub => debug/gdbstub}/user.c (100%)
 create mode 100644 debug/mcdstub/arm_mcdstub.c
 create mode 100644 debug/mcdstub/mcdstub.c
 create mode 100644 debug/mcdstub/meson.build
 create mode 100644 debug/meson.build
 delete mode 100644 gdbstub/trace.h
 create mode 100644 include/mcdstub/arm_mcdstub.h
 create mode 100644 include/mcdstub/mcd_shared_defines.h
 create mode 100644 include/mcdstub/mcdstub.h
 create mode 100644 include/mcdstub/mcdstub_common.h
 create mode 100644 include/qemu/debug.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 695e0bd34f..467da56a38 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2955,7 +2955,7 @@ M: Alex Bennée 
 R: Philippe Mathieu-Daudé 
 S: Maintained
 F: docs/system/gdb.rst
-F: gdbstub/*
+F: debug/gdbstub/*
 F: include/exec/gdbstub.h
 F: include/gdbstub/*
 F: gdb-xml/
@@ -2963,6 +2963,15 @@ F: tests/tcg/multiarch/gdbstub/*
 F: scripts/feature_to_c.py
 F: scripts/probe-gdb-support.py
 
+MCD stub
+M: Nicolas Eder 
+R: Alex Bennée 
+S: Maintained
+F: debug/mcdstub/*
+F: debug/common/*
+F: include/mcdstub/*
+F: include/qemu/debug.h
+
 Memory API
 M: Paolo Bonzini 
 M: Peter Xu 
diff --git a/debug/common/debug.c b/debug/common/debug.c
new file mode 100644
index 00..c24aaf1202
--- /dev/null
+++ b/debug/common/debug.c
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2023 Nicolas Eder
+ *
+ * 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 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 .
+ *
+ * SPDX-License-Identifier: LGPL-2.0+
+ */
diff --git a/debug/common/meson.build b/debug/common/meson.build
new file mode 100644
index 00..e69de29bb2
diff --git a/gdbstub/gdbstub.c b/debug/gdbstub/gdbstub.c
similarity index 100%
rename from gdbstub/gdbstub.c
rename to debug/gdbstub/gdbstub.c
diff --git a/gdbstub/internals.h b/debug/gdbstub/internals.h
similarity index 100%
rename from gdbstub/internals.h
rename to debug/gdbstub/internals.h
diff --git a/gdbstub/meson.build b/debug/gdbstub/meson.build
similarity index 100%
rename from gdbstub/meson.build
rename to debug/gdbstub/meson.build
diff --git a/gdbstub/syscalls.c b/debug/gdbstub/syscalls.c
similarity index 100%
rename from gdbstub/syscalls.c
rename to debug/gdbstub/syscalls.c
diff --git a/gdbstub/system.c b/debug/gdbstub/system.c
similarity index 100%
rename from gdbstub/system.c
rename to debug/gdbstub/system.c
diff --git a/gdbstub/trace-events b/debug/gdbstub/trace-events
similarity index 100%
rename from gdbstub/trace-events
rename to debug/gdbstub/trace-events
diff --git a/debug/gdbstub/trace.h b/debug/gdbstub/trace.h
new file 

[PATCH v4 13/17] mcdstub: go, step and break added

2023-12-07 Thread Nicolas Eder
---
 debug/mcdstub/mcdstub.c | 220 
 1 file changed, 220 insertions(+)

diff --git a/debug/mcdstub/mcdstub.c b/debug/mcdstub/mcdstub.c
index a5256eeb56..83582f7fa5 100644
--- a/debug/mcdstub/mcdstub.c
+++ b/debug/mcdstub/mcdstub.c
@@ -28,6 +28,7 @@
 #include "chardev/char-fe.h"
 #include "hw/cpu/cluster.h"
 #include "hw/boards.h"
+#include "exec/tb-flush.h"
 #include "sysemu/cpus.h"
 #include "sysemu/hw_accel.h"
 #include "sysemu/runstate.h"
@@ -182,6 +183,96 @@ static CPUState *mcd_get_cpu(uint32_t cpu_index)
  */
 static void mcd_vm_state_change(void *opaque, bool running, RunState state)
 {
+CPUState *cpu = mcdserver_state.c_cpu;
+
+if (mcdserver_state.state == RS_INACTIVE) {
+return;
+}
+
+if (cpu == NULL) {
+if (running) {
+/*
+ * this is the case if qemu starts the vm
+ * before a mcd client is connected
+ */
+const char *mcd_state;
+mcd_state = CORE_STATE_RUNNING;
+const char *info_str;
+info_str = STATE_STR_INIT_RUNNING;
+mcdserver_state.cpu_state.state = mcd_state;
+mcdserver_state.cpu_state.info_str = info_str;
+}
+return;
+}
+
+const char *mcd_state;
+const char *stop_str;
+const char *info_str;
+uint32_t bp_type = 0;
+uint64_t bp_address = 0;
+switch (state) {
+case RUN_STATE_RUNNING:
+mcd_state = CORE_STATE_RUNNING;
+info_str = STATE_STR_RUNNING(cpu->cpu_index);
+stop_str = "";
+break;
+case RUN_STATE_DEBUG:
+mcd_state = CORE_STATE_DEBUG;
+info_str = STATE_STR_DEBUG(cpu->cpu_index);
+if (cpu->watchpoint_hit) {
+switch (cpu->watchpoint_hit->flags & BP_MEM_ACCESS) {
+case BP_MEM_READ:
+bp_type = MCD_BREAKPOINT_READ;
+stop_str = STATE_STR_BREAK_READ(cpu->watchpoint_hit->hitaddr);
+break;
+case BP_MEM_WRITE:
+bp_type = MCD_BREAKPOINT_WRITE;
+stop_str = STATE_STR_BREAK_WRITE(cpu->watchpoint_hit->hitaddr);
+break;
+case BP_MEM_ACCESS:
+bp_type = MCD_BREAKPOINT_RW;
+stop_str = STATE_STR_BREAK_RW(cpu->watchpoint_hit->hitaddr);
+break;
+default:
+stop_str = STATE_STR_BREAK_UNKNOWN;
+break;
+}
+bp_address = cpu->watchpoint_hit->hitaddr;
+cpu->watchpoint_hit = NULL;
+} else if (cpu->singlestep_enabled) {
+/* we land here when a single step is performed */
+stop_str = STATE_STEP_PERFORMED;
+} else {
+bp_type = MCD_BREAKPOINT_HW;
+stop_str = STATE_STR_BREAK_HW;
+tb_flush(cpu);
+}
+/* deactivate single step */
+cpu_single_step(cpu, 0);
+break;
+case RUN_STATE_PAUSED:
+info_str = STATE_STR_HALTED(cpu->cpu_index);
+mcd_state = CORE_STATE_HALTED;
+stop_str = "";
+break;
+case RUN_STATE_WATCHDOG:
+info_str = STATE_STR_UNKNOWN(cpu->cpu_index);
+mcd_state = CORE_STATE_UNKNOWN;
+stop_str = "";
+break;
+default:
+info_str = STATE_STR_UNKNOWN(cpu->cpu_index);
+mcd_state = CORE_STATE_UNKNOWN;
+stop_str = "";
+break;
+}
+
+/* set state for c_cpu */
+mcdserver_state.cpu_state.state = mcd_state;
+mcdserver_state.cpu_state.bp_type = bp_type;
+mcdserver_state.cpu_state.bp_address = bp_address;
+mcdserver_state.cpu_state.stop_str = stop_str;
+mcdserver_state.cpu_state.info_str = info_str;
 }
 
 /**
@@ -637,6 +728,104 @@ static void handle_close_core(GArray *params, void 
*user_ctx)
 g_array_free(registers, TRUE);
 }
 
+/**
+ * mcd_cpu_start() - Starts the selected CPU with the cpu_resume function.
+ *
+ * @cpu: The CPU about to be started.
+ */
+static void mcd_cpu_start(CPUState *cpu)
+{
+if (!runstate_needs_reset() && !runstate_is_running() &&
+!vm_prepare_start(false)) {
+mcdserver_state.c_cpu = cpu;
+qemu_clock_enable(QEMU_CLOCK_VIRTUAL, true);
+cpu_resume(cpu);
+}
+}
+
+/**
+ * mcd_cpu_sstep() - Performes a step on the selected CPU.
+ *
+ * This function first sets the correct single step flags for the CPU with
+ * cpu_single_step and then starts the CPU with cpu_resume.
+ * @cpu: The CPU about to be stepped.
+ */
+static int mcd_cpu_sstep(CPUState *cpu)
+{
+mcdserver_state.c_cpu = cpu;
+cpu_single_step(cpu, mcdserver_state.sstep_flags);
+if (!runstate_needs_reset() && !runstate_is_running() &&
+!vm_prepare_start(true)) {
+qemu_clock_enable(QEMU_CLOCK_VIRTUAL, true);
+cpu_resume(cpu);
+}
+return 0;
+}
+
+/**
+ * mcd_vm_stop() - Brings all CPUs in debug state with the vm_stop function.
+ */
+static void mcd_vm_stop(void)
+{
+if 

[PATCH v4 04/17] gdbstub: DebugClass added to system mode.

2023-12-07 Thread Nicolas Eder
This class is used to abstract debug features between different debuggers
---
 debug/common/debug.c | 33 +
 debug/common/meson.build |  1 +
 debug/gdbstub/system.c   | 18 ++
 debug/meson.build|  1 +
 include/hw/boards.h  |  1 +
 include/qemu/debug.h | 20 
 include/qemu/typedefs.h  |  2 ++
 system/cpus.c|  9 -
 8 files changed, 84 insertions(+), 1 deletion(-)

diff --git a/debug/common/debug.c b/debug/common/debug.c
index c24aaf1202..476c969c98 100644
--- a/debug/common/debug.c
+++ b/debug/common/debug.c
@@ -16,3 +16,36 @@
  *
  * SPDX-License-Identifier: LGPL-2.0+
  */
+
+#include "qemu/osdep.h"
+#include "qemu/debug.h"
+#include "qom/object_interfaces.h"
+
+static void debug_instance_init(Object *obj)
+{
+}
+
+static void debug_finalize(Object *obj)
+{
+}
+
+static void debug_class_init(ObjectClass *oc, void *data)
+{
+}
+
+static const TypeInfo debug_info = {
+.name = TYPE_DEBUG,
+.parent = TYPE_OBJECT,
+.instance_size = sizeof(DebugState),
+.instance_init = debug_instance_init,
+.instance_finalize = debug_finalize,
+.class_size = sizeof(DebugClass),
+.class_init = debug_class_init
+};
+
+static void debug_register_types(void)
+{
+type_register_static(_info);
+}
+
+type_init(debug_register_types);
diff --git a/debug/common/meson.build b/debug/common/meson.build
index e69de29bb2..815cb6f0fc 100644
--- a/debug/common/meson.build
+++ b/debug/common/meson.build
@@ -0,0 +1 @@
+system_ss.add(files('debug.c'))
diff --git a/debug/gdbstub/system.c b/debug/gdbstub/system.c
index 83fd452800..06bc580147 100644
--- a/debug/gdbstub/system.c
+++ b/debug/gdbstub/system.c
@@ -14,6 +14,7 @@
 #include "qapi/error.h"
 #include "qemu/error-report.h"
 #include "qemu/cutils.h"
+#include "qemu/debug.h"
 #include "exec/gdbstub.h"
 #include "gdbstub/syscalls.h"
 #include "exec/hwaddr.h"
@@ -46,6 +47,20 @@ static void reset_gdbserver_state(void)
 gdbserver_state.allow_stop_reply = false;
 }
 
+/**
+ * gdb_init_debug_class() - initialize gdb-specific DebugClass
+ */
+static void gdb_init_debug_class(void)
+{
+Object *obj;
+obj = object_new(TYPE_DEBUG);
+DebugState *ds = DEBUG(obj);
+DebugClass *dc = DEBUG_GET_CLASS(ds);
+dc->set_stop_cpu = gdb_set_stop_cpu;
+MachineState *ms = MACHINE(qdev_get_machine());
+ms->debug_state = ds;
+}
+
 /*
  * Return the GDB index for a given vCPU state.
  *
@@ -405,6 +420,9 @@ int gdbserver_start(const char *device)
 gdbserver_system_state.mon_chr = mon_chr;
 gdb_syscall_reset();
 
+/* create new debug object */
+gdb_init_debug_class();
+
 return 0;
 }
 
diff --git a/debug/meson.build b/debug/meson.build
index a5b093f31e..f46ab14af9 100644
--- a/debug/meson.build
+++ b/debug/meson.build
@@ -1 +1,2 @@
+subdir('common')
 subdir('gdbstub')
diff --git a/include/hw/boards.h b/include/hw/boards.h
index da85f86efb..2e28913afc 100644
--- a/include/hw/boards.h
+++ b/include/hw/boards.h
@@ -400,6 +400,7 @@ struct MachineState {
 CpuTopology smp;
 struct NVDIMMState *nvdimms_state;
 struct NumaState *numa_state;
+DebugState *debug_state;
 };
 
 #define DEFINE_MACHINE(namestr, machine_initfn) \
diff --git a/include/qemu/debug.h b/include/qemu/debug.h
index c24aaf1202..9526f9fb48 100644
--- a/include/qemu/debug.h
+++ b/include/qemu/debug.h
@@ -16,3 +16,23 @@
  *
  * SPDX-License-Identifier: LGPL-2.0+
  */
+
+#ifndef QEMU_DEBUG_H
+#define QEMU_DEBUG_H
+
+#include "qom/object.h"
+#include "qemu/typedefs.h"
+
+struct DebugClass {
+ObjectClass parent_class;
+void (*set_stop_cpu)(CPUState *cpu);
+};
+
+struct DebugState {
+Object parent_obj;
+};
+
+#define TYPE_DEBUG "debug"
+OBJECT_DECLARE_TYPE(DebugState, DebugClass, DEBUG)
+
+#endif /* QEMU_DEBUG_H */
diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h
index 5abdbc3874..e48b544173 100644
--- a/include/qemu/typedefs.h
+++ b/include/qemu/typedefs.h
@@ -46,6 +46,8 @@ typedef struct CpuInfoFast CpuInfoFast;
 typedef struct CPUJumpCache CPUJumpCache;
 typedef struct CPUState CPUState;
 typedef struct CPUTLBEntryFull CPUTLBEntryFull;
+typedef struct DebugClass DebugClass;
+typedef struct DebugState DebugState;
 typedef struct DeviceListener DeviceListener;
 typedef struct DeviceState DeviceState;
 typedef struct DirtyBitmapSnapshot DirtyBitmapSnapshot;
diff --git a/system/cpus.c b/system/cpus.c
index a444a747f0..7a7fff14bc 100644
--- a/system/cpus.c
+++ b/system/cpus.c
@@ -25,6 +25,7 @@
 #include "qemu/osdep.h"
 #include "monitor/monitor.h"
 #include "qemu/coroutine-tls.h"
+#include "qemu/debug.h"
 #include "qapi/error.h"
 #include "qapi/qapi-commands-machine.h"
 #include "qapi/qapi-commands-misc.h"
@@ -313,7 +314,13 @@ void cpu_handle_guest_debug(CPUState *cpu)
 cpu_single_step(cpu, 0);
 }
 } else {
-gdb_set_stop_cpu(cpu);
+MachineState *ms = MACHINE(qdev_get_machine());
+DebugState *ds = 

[PATCH v4 17/17] mcdstub: break/watchpoints added

2023-12-07 Thread Nicolas Eder
---
 debug/mcdstub/mcdstub.c | 154 
 1 file changed, 154 insertions(+)

diff --git a/debug/mcdstub/mcdstub.c b/debug/mcdstub/mcdstub.c
index e5fd575834..dadd79034b 100644
--- a/debug/mcdstub/mcdstub.c
+++ b/debug/mcdstub/mcdstub.c
@@ -1177,6 +1177,134 @@ static void handle_write_memory(GArray *params, void 
*user_ctx)
 mcd_put_packet(TCP_EXECUTION_SUCCESS);
 }
 
+/**
+ * mcd_breakpoint_insert() - Inserts a break- or watchpoint.
+ *
+ * This function evaluates the received breakpoint type and translates it
+ * to a known GDB breakpoint type.
+ * Then it calls cpu_breakpoint_insert or cpu_watchpoint_insert depending on
+ * the type.
+ * @cpu: CPU to which the breakpoint should be added.
+ * @addr: Address of the breakpoint.
+ * @type: Breakpoint type.
+ */
+static int mcd_breakpoint_insert(CPUState *cpu, int type, vaddr addr)
+{
+/* translate the type to known gdb types and function call*/
+int bp_type = 0;
+CPUClass *cc = CPU_GET_CLASS(cpu);
+if (cc->gdb_stop_before_watchpoint) {
+/* bp_type |= BP_STOP_BEFORE_ACCESS; */
+}
+int return_value = 0;
+switch (type) {
+case MCD_BREAKPOINT_HW:
+return_value = cpu_breakpoint_insert(cpu, addr, BP_GDB, NULL);
+return return_value;
+case MCD_BREAKPOINT_READ:
+bp_type |= BP_GDB | BP_MEM_READ;
+return_value = cpu_watchpoint_insert(cpu, addr, 4, bp_type, NULL);
+return return_value;
+case MCD_BREAKPOINT_WRITE:
+bp_type |= BP_GDB | BP_MEM_WRITE;
+return_value = cpu_watchpoint_insert(cpu, addr, 4, bp_type, NULL);
+return return_value;
+case MCD_BREAKPOINT_RW:
+bp_type |= BP_GDB | BP_MEM_ACCESS;
+return_value = cpu_watchpoint_insert(cpu, addr, 4, bp_type, NULL);
+return return_value;
+default:
+return -ENOSYS;
+}
+}
+
+/**
+ * mcd_breakpoint_remove() - Removes a break- or watchpoint.
+ *
+ * This function evaluates the received breakpoint type and translates it
+ * to a known GDB breakpoint type.
+ * Then it calls cpu_breakpoint_remove or cpu_watchpoint_remove depending on
+ * the type.
+ * @cpu: CPU from which the breakpoint should be removed.
+ * @addr: Address of the breakpoint.
+ * @type: Breakpoint type.
+ */
+static int mcd_breakpoint_remove(CPUState *cpu, int type, vaddr addr)
+{
+/* translate the type to known gdb types and function call*/
+int bp_type = 0;
+CPUClass *cc = CPU_GET_CLASS(cpu);
+if (cc->gdb_stop_before_watchpoint) {
+/* bp_type |= BP_STOP_BEFORE_ACCESS; */
+}
+int return_value = 0;
+switch (type) {
+case MCD_BREAKPOINT_HW:
+return_value = cpu_breakpoint_remove(cpu, addr, BP_GDB);
+return return_value;
+case MCD_BREAKPOINT_READ:
+bp_type |= BP_GDB | BP_MEM_READ;
+return_value = cpu_watchpoint_remove(cpu, addr, 4, bp_type);
+return return_value;
+case MCD_BREAKPOINT_WRITE:
+bp_type |= BP_GDB | BP_MEM_WRITE;
+return_value = cpu_watchpoint_remove(cpu, addr, 4, bp_type);
+return return_value;
+case MCD_BREAKPOINT_RW:
+bp_type |= BP_GDB | BP_MEM_ACCESS;
+return_value = cpu_watchpoint_remove(cpu, addr, 4, bp_type);
+return return_value;
+default:
+return -ENOSYS;
+}
+}
+
+/**
+ * handle_breakpoint_insert() - Handler for inserting a break- or watchpoint.
+ *
+ * This function extracts the CPU, breakpoint type and address from the
+ * parameters and calls :c:func:`mcd_breakpoint_insert` to insert the
+ * breakpoint.
+ * @params: GArray with all TCP packet parameters.
+ */
+static void handle_breakpoint_insert(GArray *params, void *user_ctx)
+{
+/* 1. get parameter data */
+uint32_t cpu_id = get_param(params, 0)->cpu_id;
+uint32_t type = get_param(params, 1)->data_uint32_t;
+uint64_t address = get_param(params, 2)->data_uint64_t;
+/* 2. insert breakpoint and send reply */
+CPUState *cpu = mcd_get_cpu(cpu_id);
+if (mcd_breakpoint_insert(cpu, type, address) != 0) {
+mcd_put_packet(TCP_EXECUTION_ERROR);
+} else {
+mcd_put_packet(TCP_EXECUTION_SUCCESS);
+}
+}
+
+/**
+ * handle_breakpoint_remove() - Handler for inserting a break- or watchpoint.
+ *
+ * This function extracts the CPU, breakpoint type and address from the
+ * parameters and calls :c:func:`mcd_breakpoint_remove` to insert the
+ * breakpoint.
+ * @params: GArray with all TCP packet parameters.
+ */
+static void handle_breakpoint_remove(GArray *params, void *user_ctx)
+{
+/* 1. get parameter data */
+uint32_t cpu_id = get_param(params, 0)->cpu_id;
+uint32_t type = get_param(params, 1)->data_uint32_t;
+uint64_t address = get_param(params, 2)->data_uint64_t;
+/* 2. remove breakpoint and send reply */
+CPUState *cpu = mcd_get_cpu(cpu_id);
+if (mcd_breakpoint_remove(cpu, type, address) != 0) {
+mcd_put_packet(TCP_EXECUTION_ERROR);
+} else {
+

[PATCH v4 15/17] mcdstub: skeleton for reset handling added

2023-12-07 Thread Nicolas Eder
---
 debug/mcdstub/mcdstub.c | 46 +
 1 file changed, 46 insertions(+)

diff --git a/debug/mcdstub/mcdstub.c b/debug/mcdstub/mcdstub.c
index 794e7d1312..cc1587396d 100644
--- a/debug/mcdstub/mcdstub.c
+++ b/debug/mcdstub/mcdstub.c
@@ -826,6 +826,37 @@ static void handle_vm_stop(GArray *params, void *user_ctx)
 mcd_vm_stop();
 }
 
+/**
+ * mcd_exit() - Terminates QEMU.
+ *
+ * If the mcdserver_state has not been initialized the function exits before
+ * terminating QEMU. Terminting is done with the qemu_chr_fe_deinit function.
+ * @code: An exitcode, which can be used in the future.
+ */
+static void mcd_exit(int code)
+{
+/* terminate qemu */
+if (!mcdserver_state.init) {
+return;
+}
+
+qemu_chr_fe_deinit(_system_state.chr, true);
+}
+
+/**
+ * handle_reset() - Handler for performing resets.
+ *
+ * This function is currently not in use.
+ * @params: GArray with all TCP packet parameters.
+ */
+static void handle_reset(GArray *params, void *user_ctx)
+{
+/*
+ * int reset_id = get_param(params, 0)->data_int;
+ * TODO: implement resets
+ */
+}
+
 /**
  * mcd_handle_packet() - Evaluates the type of received packet and chooses the
  * correct handler.
@@ -927,6 +958,21 @@ static int mcd_handle_packet(const char *line_buf)
 cmd_parser = _cmd_desc;
 }
 break;
+case TCP_CHAR_KILLQEMU:
+/* kill qemu completely */
+error_report("QEMU: Terminated via MCDstub");
+mcd_exit(0);
+exit(0);
+case TCP_CHAR_RESET:
+{
+static MCDCmdParseEntry reset_cmd_desc = {
+.handler = handle_reset,
+};
+reset_cmd_desc.cmd = (char[2]) { TCP_CHAR_RESET, '\0' };
+strcpy(reset_cmd_desc.schema, (char[2]) { ARG_SCHEMA_INT, '\0' });
+cmd_parser = _cmd_desc;
+}
+break;
 default:
 /* command not supported */
 mcd_put_packet("");
-- 
2.34.1




[PATCH v4 02/17] gdbstub: hex conversion functions moved to cutils.h

2023-12-07 Thread Nicolas Eder
---
 debug/gdbstub/gdbstub.c   | 19 ++-
 debug/gdbstub/internals.h | 26 --
 include/qemu/cutils.h | 30 ++
 3 files changed, 40 insertions(+), 35 deletions(-)

diff --git a/debug/gdbstub/gdbstub.c b/debug/gdbstub/gdbstub.c
index 46d752bbc2..f43d4355c0 100644
--- a/debug/gdbstub/gdbstub.c
+++ b/debug/gdbstub/gdbstub.c
@@ -80,8 +80,8 @@ void gdb_memtohex(GString *buf, const uint8_t *mem, int len)
 int i, c;
 for(i = 0; i < len; i++) {
 c = mem[i];
-g_string_append_c(buf, tohex(c >> 4));
-g_string_append_c(buf, tohex(c & 0xf));
+g_string_append_c(buf, nibble_to_hexchar(c >> 4));
+g_string_append_c(buf, nibble_to_hexchar(c & 0xf));
 }
 g_string_append_c(buf, '\0');
 }
@@ -91,7 +91,8 @@ void gdb_hextomem(GByteArray *mem, const char *buf, int len)
 int i;
 
 for(i = 0; i < len; i++) {
-guint8 byte = fromhex(buf[0]) << 4 | fromhex(buf[1]);
+guint8 byte = hexchar_to_nibble(buf[0]) << 4 |
+  hexchar_to_nibble(buf[1]);
 g_byte_array_append(mem, , 1);
 buf += 2;
 }
@@ -118,8 +119,8 @@ static void hexdump(const char *buf, int len,
 if (i < len) {
 char value = buf[i];
 
-line_buffer[hex_col + 0] = tohex((value >> 4) & 0xF);
-line_buffer[hex_col + 1] = tohex((value >> 0) & 0xF);
+line_buffer[hex_col + 0] = nibble_to_hexchar((value >> 4) & 0xF);
+line_buffer[hex_col + 1] = nibble_to_hexchar((value >> 0) & 0xF);
 line_buffer[txt_col + 0] = (value >= ' ' && value < 127)
 ? value
 : '.';
@@ -151,8 +152,8 @@ int gdb_put_packet_binary(const char *buf, int len, bool 
dump)
 csum += buf[i];
 }
 footer[0] = '#';
-footer[1] = tohex((csum >> 4) & 0xf);
-footer[2] = tohex((csum) & 0xf);
+footer[1] = nibble_to_hexchar((csum >> 4) & 0xf);
+footer[2] = nibble_to_hexchar((csum) & 0xf);
 g_byte_array_append(gdbserver_state.last_packet, footer, 3);
 
 gdb_put_buffer(gdbserver_state.last_packet->data,
@@ -2267,7 +2268,7 @@ void gdb_read_byte(uint8_t ch)
 break;
 }
 gdbserver_state.line_buf[gdbserver_state.line_buf_index] = '\0';
-gdbserver_state.line_csum = fromhex(ch) << 4;
+gdbserver_state.line_csum = hexchar_to_nibble(ch) << 4;
 gdbserver_state.state = RS_CHKSUM2;
 break;
 case RS_CHKSUM2:
@@ -2277,7 +2278,7 @@ void gdb_read_byte(uint8_t ch)
 gdbserver_state.state = RS_GETLINE;
 break;
 }
-gdbserver_state.line_csum |= fromhex(ch);
+gdbserver_state.line_csum |= hexchar_to_nibble(ch);
 
 if (gdbserver_state.line_csum != (gdbserver_state.line_sum & 
0xff)) {
 trace_gdbstub_err_checksum_incorrect(gdbserver_state.line_sum, 
gdbserver_state.line_csum);
diff --git a/debug/gdbstub/internals.h b/debug/gdbstub/internals.h
index 5c0c725e54..4b67adfeda 100644
--- a/debug/gdbstub/internals.h
+++ b/debug/gdbstub/internals.h
@@ -75,32 +75,6 @@ typedef struct GDBState {
 /* lives in main gdbstub.c */
 extern GDBState gdbserver_state;
 
-/*
- * Inline utility function, convert from int to hex and back
- */
-
-static inline int fromhex(int v)
-{
-if (v >= '0' && v <= '9') {
-return v - '0';
-} else if (v >= 'A' && v <= 'F') {
-return v - 'A' + 10;
-} else if (v >= 'a' && v <= 'f') {
-return v - 'a' + 10;
-} else {
-return 0;
-}
-}
-
-static inline int tohex(int v)
-{
-if (v < 10) {
-return v + '0';
-} else {
-return v - 10 + 'a';
-}
-}
-
 /*
  * Connection helpers for both system and user backends
  */
diff --git a/include/qemu/cutils.h b/include/qemu/cutils.h
index 92c927a6a3..5ab1a4ffb0 100644
--- a/include/qemu/cutils.h
+++ b/include/qemu/cutils.h
@@ -267,4 +267,34 @@ void qemu_hexdump_line(char *line, unsigned int b, const 
void *bufptr,
 void qemu_hexdump(FILE *fp, const char *prefix,
   const void *bufptr, size_t size);
 
+
+/**
+ * hexchar_to_nibble() - Converts hex character to nibble.
+ */
+static inline int hexchar_to_nibble(int v)
+{
+if (v >= '0' && v <= '9') {
+return v - '0';
+} else if (v >= 'A' && v <= 'F') {
+return v - 'A' + 10;
+} else if (v >= 'a' && v <= 'f') {
+return v - 'a' + 10;
+} else {
+g_assert_not_reached();
+}
+}
+
+/**
+ * nibble_to_hexchar() - Converts nibble to hex character.
+ */
+static inline int nibble_to_hexchar(int v)
+{
+g_assert(v <= 0xf);
+if (v < 10) {
+return v + '0';
+} else {
+return v - 10 + 'a';
+}
+}
+
 #endif
-- 
2.34.1




[PATCH v4 10/17] mcdstub: open and close server funcitons added

2023-12-07 Thread Nicolas Eder
---
 debug/mcdstub/mcdstub.c | 300 
 1 file changed, 215 insertions(+), 85 deletions(-)

diff --git a/debug/mcdstub/mcdstub.c b/debug/mcdstub/mcdstub.c
index f97bccf409..d59c4ac078 100644
--- a/debug/mcdstub/mcdstub.c
+++ b/debug/mcdstub/mcdstub.c
@@ -65,6 +65,91 @@ static void mcd_sigterm_handler(int signal)
 }
 #endif
 
+/**
+ * mcd_get_process() - Returns the process of the provided pid.
+ *
+ * @pid: The process ID.
+ */
+static MCDProcess *mcd_get_process(uint32_t pid)
+{
+int i;
+
+if (!pid) {
+/* 0 means any process, we take the first one */
+return _state.processes[0];
+}
+
+for (i = 0; i < mcdserver_state.process_num; i++) {
+if (mcdserver_state.processes[i].pid == pid) {
+return _state.processes[i];
+}
+}
+
+return NULL;
+}
+
+/**
+ * mcd_get_cpu_pid() - Returns the process ID of the provided CPU.
+ *
+ * @cpu: The CPU state.
+ */
+static uint32_t mcd_get_cpu_pid(CPUState *cpu)
+{
+if (cpu->cluster_index == UNASSIGNED_CLUSTER_INDEX) {
+/* Return the default process' PID */
+int index = mcdserver_state.process_num - 1;
+return mcdserver_state.processes[index].pid;
+}
+return cpu->cluster_index + 1;
+}
+
+/**
+ * mcd_get_cpu_process() - Returns the process of the provided CPU.
+ *
+ * @cpu: The CPU state.
+ */
+static MCDProcess *mcd_get_cpu_process(CPUState *cpu)
+{
+return mcd_get_process(mcd_get_cpu_pid(cpu));
+}
+
+/**
+ * mcd_next_attached_cpu() - Returns the first CPU with an attached process
+ * starting after the
+ * provided cpu.
+ *
+ * @cpu: The CPU to start from.
+ */
+static CPUState *mcd_next_attached_cpu(CPUState *cpu)
+{
+cpu = CPU_NEXT(cpu);
+
+while (cpu) {
+if (mcd_get_cpu_process(cpu)->attached) {
+break;
+}
+
+cpu = CPU_NEXT(cpu);
+}
+
+return cpu;
+}
+
+/**
+ * mcd_first_attached_cpu() - Returns the first CPU with an attached process.
+ */
+static CPUState *mcd_first_attached_cpu(void)
+{
+CPUState *cpu = first_cpu;
+MCDProcess *process = mcd_get_cpu_process(cpu);
+
+if (!process->attached) {
+return mcd_next_attached_cpu(cpu);
+}
+
+return cpu;
+}
+
 /**
  * mcd_vm_state_change() - Handles a state change of the QEMU VM.
  *
@@ -284,6 +369,117 @@ static void run_cmd_parser(const char *data, const 
MCDCmdParseEntry *cmd)
 }
 }
 
+/**
+ * init_resets() - Initializes the resets info.
+ *
+ * This function currently only adds all theoretical possible resets to the
+ * resets GArray. None of the resets work at the moment. The resets are:
+ * "full_system_reset", "gpr_reset" and "memory_reset".
+ * @resets: GArray with possible resets.
+ */
+static int init_resets(GArray *resets)
+{
+mcd_reset_st system_reset = { .id = 0, .name = RESET_SYSTEM};
+mcd_reset_st gpr_reset = { .id = 1, .name = RESET_GPR};
+mcd_reset_st memory_reset = { .id = 2, .name = RESET_MEMORY};
+g_array_append_vals(resets, (gconstpointer)_reset, 1);
+g_array_append_vals(resets, (gconstpointer)_reset, 1);
+g_array_append_vals(resets, (gconstpointer)_reset, 1);
+return 0;
+}
+
+/**
+ * init_trigger() - Initializes the trigger info.
+ *
+ * This function adds the types of trigger, their possible options and actions
+ * to the trigger struct.
+ * @trigger: Struct with all trigger info.
+ */
+static int init_trigger(mcd_trigger_into_st *trigger)
+{
+snprintf(trigger->type, sizeof(trigger->type),
+"%d,%d,%d,%d", MCD_BREAKPOINT_HW, MCD_BREAKPOINT_READ,
+MCD_BREAKPOINT_WRITE, MCD_BREAKPOINT_RW);
+snprintf(trigger->option, sizeof(trigger->option),
+"%s", MCD_TRIG_OPT_VALUE);
+snprintf(trigger->action, sizeof(trigger->action),
+"%s", MCD_TRIG_ACT_BREAK);
+/* there can be 16 breakpoints and 16 watchpoints each */
+trigger->nr_trigger = 16;
+return 0;
+}
+
+/**
+ * handle_open_server() - Handler for opening the MCD server.
+ *
+ * This is the first function that gets called from the MCD Shared Library.
+ * It initializes core indepent data with the :c:func:`init_resets` and
+ * \reg init_trigger functions. It also send the TCP_HANDSHAKE_SUCCESS
+ * packet back to the library to confirm the mcdstub is ready for further
+ * communication.
+ * @params: GArray with all TCP packet parameters.
+ */
+static void handle_open_server(GArray *params, void *user_ctx)
+{
+/* initialize core-independent data */
+int return_value = 0;
+mcdserver_state.resets = g_array_new(false, true, sizeof(mcd_reset_st));
+return_value = init_resets(mcdserver_state.resets);
+if (return_value != 0) {
+g_assert_not_reached();
+}
+return_value = init_trigger(_state.trigger);
+if (return_value != 0) {
+g_assert_not_reached();
+}
+
+mcd_put_packet(TCP_HANDSHAKE_SUCCESS);
+}
+
+/**
+ * mcd_vm_start() - Starts all CPUs with the vm_start function.
+ */
+static void mcd_vm_start(void)
+{
+if 

[PATCH v4 08/17] cutils: qemu_strtou32 function added

2023-12-07 Thread Nicolas Eder
---
 include/qemu/cutils.h |  2 ++
 util/cutils.c | 30 ++
 2 files changed, 32 insertions(+)

diff --git a/include/qemu/cutils.h b/include/qemu/cutils.h
index 5ab1a4ffb0..14f492ba61 100644
--- a/include/qemu/cutils.h
+++ b/include/qemu/cutils.h
@@ -158,6 +158,8 @@ int qemu_strtoul(const char *nptr, const char **endptr, int 
base,
  unsigned long *result);
 int qemu_strtoi64(const char *nptr, const char **endptr, int base,
   int64_t *result);
+int qemu_strtou32(const char *nptr, const char **endptr, int base,
+  uint32_t *result);
 int qemu_strtou64(const char *nptr, const char **endptr, int base,
   uint64_t *result);
 int qemu_strtod(const char *nptr, const char **endptr, double *result);
diff --git a/util/cutils.c b/util/cutils.c
index 42364039a5..5e00a4ec14 100644
--- a/util/cutils.c
+++ b/util/cutils.c
@@ -665,6 +665,36 @@ int qemu_strtoi64(const char *nptr, const char **endptr, 
int base,
 return check_strtox_error(nptr, ep, endptr, *result == 0, errno);
 }
 
+/**
+ * Convert string @nptr to an uint32_t.
+ *
+ * Works like qemu_strtoul(), except it stores UINT32_MAX on overflow.
+ * (If you want to prohibit negative numbers that wrap around to
+ * positive, use parse_uint()).
+ */
+int qemu_strtou32(const char *nptr, const char **endptr, int base,
+  uint32_t *result)
+{
+char *ep;
+
+assert((unsigned) base <= 36 && base != 1);
+if (!nptr) {
+*result = 0;
+if (endptr) {
+*endptr = nptr;
+}
+return -EINVAL;
+}
+
+errno = 0;
+*result = strtoul(nptr, , base);
+/* Windows returns 1 for negative out-of-range values.  */
+if (errno == ERANGE) {
+*result = -1;
+}
+return check_strtox_error(nptr, ep, endptr, *result == 0, errno);
+}
+
 /**
  * Convert string @nptr to an uint64_t.
  *
-- 
2.34.1




[PATCH v4 07/17] mcdstub: mcdserver initialization functions added

2023-12-07 Thread Nicolas Eder
---
 debug/mcdstub/mcdstub.c | 154 
 1 file changed, 154 insertions(+)

diff --git a/debug/mcdstub/mcdstub.c b/debug/mcdstub/mcdstub.c
index 32f4d1980f..176d5d2311 100644
--- a/debug/mcdstub/mcdstub.c
+++ b/debug/mcdstub/mcdstub.c
@@ -22,9 +22,12 @@
 #include "qemu/cutils.h"
 #include "qemu/module.h"
 #include "qemu/error-report.h"
+#include "qemu/debug.h"
 #include "qapi/error.h"
 #include "chardev/char.h"
 #include "chardev/char-fe.h"
+#include "hw/cpu/cluster.h"
+#include "hw/boards.h"
 #include "sysemu/cpus.h"
 #include "sysemu/hw_accel.h"
 #include "sysemu/runstate.h"
@@ -109,6 +112,39 @@ static void mcd_chr_event(void *opaque, QEMUChrEvent event)
 {
 }
 
+/**
+ * init_query_cmds_table() - Initializes all query functions.
+ *
+ * This function adds all query functions to the mcd_query_cmds_table. This
+ * includes their command string, handler function and parameter schema.
+ * @mcd_query_cmds_table: Lookup table with all query commands.
+ */
+static void init_query_cmds_table(MCDCmdParseEntry *mcd_query_cmds_table)
+{}
+
+/**
+ * mcd_set_stop_cpu() - Sets c_cpu to the just stopped CPU.
+ *
+ * @cpu: The CPU state.
+ */
+static void mcd_set_stop_cpu(CPUState *cpu)
+{
+mcdserver_state.c_cpu = cpu;
+}
+
+/**
+ * mcd_init_debug_class() - initialize mcd-specific DebugClass
+ */
+static void mcd_init_debug_class(void){
+Object *obj;
+obj = object_new(TYPE_DEBUG);
+DebugState *ds = DEBUG(obj);
+DebugClass *dc = DEBUG_GET_CLASS(ds);
+dc->set_stop_cpu = mcd_set_stop_cpu;
+MachineState *ms = MACHINE(qdev_get_machine());
+ms->debug_state = ds;
+}
+
 /**
  * mcd_init_mcdserver_state() - Initializes the mcdserver_state struct.
  *
@@ -119,6 +155,35 @@ static void mcd_chr_event(void *opaque, QEMUChrEvent event)
  */
 static void mcd_init_mcdserver_state(void)
 {
+g_assert(!mcdserver_state.init);
+memset(_state, 0, sizeof(MCDState));
+mcdserver_state.init = true;
+mcdserver_state.str_buf = g_string_new(NULL);
+mcdserver_state.mem_buf = g_byte_array_sized_new(MAX_PACKET_LENGTH);
+mcdserver_state.last_packet = g_byte_array_sized_new(MAX_PACKET_LENGTH + 
4);
+
+/*
+ * What single-step modes are supported is accelerator dependent.
+ * By default try to use no IRQs and no timers while single
+ * stepping so as to make single stepping like a typical ICE HW step.
+ */
+mcdserver_state.supported_sstep_flags =
+accel_supported_gdbstub_sstep_flags();
+mcdserver_state.sstep_flags = SSTEP_ENABLE | SSTEP_NOIRQ | SSTEP_NOTIMER;
+mcdserver_state.sstep_flags &= mcdserver_state.supported_sstep_flags;
+
+/* init query table */
+init_query_cmds_table(mcdserver_state.mcd_query_cmds_table);
+
+/* at this time the cpu hans't been started! -> set cpu_state */
+mcd_cpu_state_st cpu_state =  {
+.state = CORE_STATE_HALTED,
+.info_str = STATE_STR_INIT_HALTED,
+};
+mcdserver_state.cpu_state = cpu_state;
+
+/* create new debug object */
+mcd_init_debug_class();
 }
 
 /**
@@ -128,6 +193,84 @@ static void mcd_init_mcdserver_state(void)
  */
 static void reset_mcdserver_state(void)
 {
+g_free(mcdserver_state.processes);
+mcdserver_state.processes = NULL;
+mcdserver_state.process_num = 0;
+}
+
+/**
+ * mcd_create_default_process() - Creates a default process for debugging.
+ *
+ * This function creates a new, not yet attached, process with an ID one above
+ * the previous maximum ID.
+ * @s: A MCDState object.
+ */
+static void mcd_create_default_process(MCDState *s)
+{
+MCDProcess *process;
+int max_pid = 0;
+
+if (mcdserver_state.process_num) {
+max_pid = s->processes[s->process_num - 1].pid;
+}
+
+s->processes = g_renew(MCDProcess, s->processes, ++s->process_num);
+process = >processes[s->process_num - 1];
+
+/* We need an available PID slot for this process */
+assert(max_pid < UINT32_MAX);
+
+process->pid = max_pid + 1;
+process->attached = false;
+}
+
+/**
+ * find_cpu_clusters() - Returns the CPU cluster of the child object.
+ *
+ * @param[in] child Object with unknown CPU cluster.
+ * @param[in] opaque Pointer to an MCDState object.
+ */
+static int find_cpu_clusters(Object *child, void *opaque)
+{
+if (object_dynamic_cast(child, TYPE_CPU_CLUSTER)) {
+MCDState *s = (MCDState *) opaque;
+CPUClusterState *cluster = CPU_CLUSTER(child);
+MCDProcess *process;
+
+s->processes = g_renew(MCDProcess, s->processes, ++s->process_num);
+
+process = >processes[s->process_num - 1];
+assert(cluster->cluster_id != UINT32_MAX);
+process->pid = cluster->cluster_id + 1;
+process->attached = false;
+
+return 0;
+}
+
+return object_child_foreach(child, find_cpu_clusters, opaque);
+}
+
+/**
+ * pid_order() - Compares process IDs.
+ *
+ * This function returns -1 if process "a" has a ower process ID than "b".
+ * If "b" has a lower 

[PATCH v4 12/17] mcdstub: all core specific queries added

2023-12-07 Thread Nicolas Eder
---
 debug/mcdstub/mcdstub.c | 365 
 1 file changed, 365 insertions(+)

diff --git a/debug/mcdstub/mcdstub.c b/debug/mcdstub/mcdstub.c
index 48da2e043c..a5256eeb56 100644
--- a/debug/mcdstub/mcdstub.c
+++ b/debug/mcdstub/mcdstub.c
@@ -897,6 +897,301 @@ static void handle_query_cores(GArray *params, void 
*user_ctx)
 mcd_put_strbuf();
 }
 
+/**
+ * handle_query_reset_f() - Handler for the first reset query.
+ *
+ * This function sends the first reset name and ID.
+ * @params: GArray with all TCP packet parameters.
+ */
+static void handle_query_reset_f(GArray *params, void *user_ctx)
+{
+/* 1. check length */
+int nb_resets = mcdserver_state.resets->len;
+if (nb_resets == 1) {
+/* indicates this is the last packet */
+g_string_printf(mcdserver_state.str_buf, "0%s", QUERY_END_INDEX);
+} else {
+g_string_printf(mcdserver_state.str_buf, "1%s", QUERY_END_INDEX);
+}
+/* 2. send data */
+mcd_reset_st reset = g_array_index(mcdserver_state.resets, mcd_reset_st, 
0);
+g_string_append_printf(mcdserver_state.str_buf, "%s=%s.%s=%u.",
+TCP_ARGUMENT_NAME, reset.name, TCP_ARGUMENT_ID, reset.id);
+mcd_put_strbuf();
+}
+
+/**
+ * handle_query_reset_c() - Handler for all consecutive reset queries.
+ *
+ * This functions sends all consecutive reset names and IDs. It uses the
+ * query_index parameter to determine which reset is queried next.
+ * @params: GArray with all TCP packet parameters.
+ */
+static void handle_query_reset_c(GArray *params, void *user_ctx)
+{
+/* reset options are the same for every cpu! */
+uint32_t query_index = get_param(params, 0)->query_handle;
+
+/* 1. check weather this was the last mem space */
+int nb_groups = mcdserver_state.resets->len;
+if (query_index + 1 == nb_groups) {
+/* indicates this is the last packet */
+g_string_printf(mcdserver_state.str_buf, "0%s", QUERY_END_INDEX);
+} else {
+g_string_printf(mcdserver_state.str_buf, "%u!", query_index + 1);
+}
+
+/* 2. send data */
+mcd_reset_st reset = g_array_index(mcdserver_state.resets,
+mcd_reset_st, query_index);
+g_string_append_printf(mcdserver_state.str_buf, "%s=%s.%s=%u.",
+TCP_ARGUMENT_NAME, reset.name, TCP_ARGUMENT_ID, reset.id);
+mcd_put_strbuf();
+}
+
+/**
+ * handle_query_trigger() - Handler for trigger query.
+ *
+ * Sends data on the different types of trigger and their options and actions.
+ * @params: GArray with all TCP packet parameters.
+ */
+static void handle_query_trigger(GArray *params, void *user_ctx)
+{
+mcd_trigger_into_st trigger = mcdserver_state.trigger;
+g_string_printf(mcdserver_state.str_buf, "%s=%u.%s=%s.%s=%s.%s=%s.",
+TCP_ARGUMENT_AMOUNT_TRIGGER, trigger.nr_trigger,
+TCP_ARGUMENT_TYPE, trigger.type,
+TCP_ARGUMENT_OPTION, trigger.option,
+TCP_ARGUMENT_ACTION, trigger.action);
+mcd_put_strbuf();
+}
+
+/**
+ * handle_query_mem_spaces_f() Handler for the first memory space query.
+ *
+ * This function sends the first memory space name, ID, type and accessing
+ * options.
+ * @params: GArray with all TCP packet parameters.
+ */
+static void handle_query_mem_spaces_f(GArray *params, void *user_ctx)
+{
+/* 1. get correct memspaces and set the query_cpu */
+uint32_t cpu_id = get_param(params, 0)->cpu_id;
+mcdserver_state.query_cpu_id = cpu_id;
+GArray *memspaces = g_list_nth_data(mcdserver_state.all_memspaces, cpu_id);
+
+/* 2. check length */
+int nb_groups = memspaces->len;
+if (nb_groups == 1) {
+/* indicates this is the last packet */
+g_string_printf(mcdserver_state.str_buf, "0%s", QUERY_END_INDEX);
+} else {
+g_string_printf(mcdserver_state.str_buf, "1%s", QUERY_END_INDEX);
+}
+
+/* 3. send data */
+mcd_mem_space_st space = g_array_index(memspaces, mcd_mem_space_st, 0);
+g_string_append_printf(mcdserver_state.str_buf,
+"%s=%s.%s=%u.%s=%u.%s=%u.%s=%u.%s=%u.%s=%ld.%s=%ld.%s=%u.",
+TCP_ARGUMENT_NAME, space.name,
+TCP_ARGUMENT_ID, space.id,
+TCP_ARGUMENT_TYPE, space.type,
+TCP_ARGUMENT_BITS_PER_MAU, space.bits_per_mau,
+TCP_ARGUMENT_INVARIANCE, space.invariance,
+TCP_ARGUMENT_ENDIAN, space.endian,
+TCP_ARGUMENT_MIN, space.min_addr,
+TCP_ARGUMENT_MAX, space.max_addr,
+TCP_ARGUMENT_SUPPORTED_ACCESS_OPTIONS, space.supported_access_options);
+mcd_put_strbuf();
+}
+
+/**
+ * handle_query_mem_spaces_c() - Handler for all consecutive memory space
+ * queries.
+ *
+ * This function sends all consecutive memory space names, IDs, types and
+ * accessing options.
+ * It uses the query_index parameter to determine
+ * which memory space is queried next.
+ * @params: GArray with all TCP packet parameters.
+ */
+static void handle_query_mem_spaces_c(GArray *params, void *user_ctx)
+{
+/*
+ * this funcitons send all mem spaces 

[PATCH v4 14/17] mcdstub: state query added

2023-12-07 Thread Nicolas Eder
---
 debug/mcdstub/mcdstub.c | 44 +
 1 file changed, 44 insertions(+)

diff --git a/debug/mcdstub/mcdstub.c b/debug/mcdstub/mcdstub.c
index 83582f7fa5..794e7d1312 100644
--- a/debug/mcdstub/mcdstub.c
+++ b/debug/mcdstub/mcdstub.c
@@ -1412,6 +1412,43 @@ static void handle_query_regs_c(GArray *params, void 
*user_ctx)
 mcd_put_strbuf();
 }
 
+/**
+ * handle_query_state() - Handler for the state query.
+ *
+ * This function collects all data stored in the
+ * cpu_state member of the mcdserver_state and formats and sends it to the
+ * library.
+ * @params: GArray with all TCP packet parameters.
+ */
+static void handle_query_state(GArray *params, void *user_ctx)
+{
+/*
+ * TODO: multicore support
+ * get state info
+ */
+mcd_cpu_state_st state_info = mcdserver_state.cpu_state;
+/* TODO: add event information */
+uint32_t event = 0;
+/* send data */
+g_string_printf(mcdserver_state.str_buf,
+"%s=%s.%s=%u.%s=%u.%s=%u.%s=%lu.%s=%s.%s=%s.",
+TCP_ARGUMENT_STATE, state_info.state,
+TCP_ARGUMENT_EVENT, event, TCP_ARGUMENT_THREAD, 0,
+TCP_ARGUMENT_TYPE, state_info.bp_type,
+TCP_ARGUMENT_ADDRESS, state_info.bp_address,
+TCP_ARGUMENT_STOP_STRING, state_info.stop_str,
+TCP_ARGUMENT_INFO_STRING, state_info.info_str);
+mcd_put_strbuf();
+
+/* reset debug info after first query */
+if (strcmp(state_info.state, CORE_STATE_DEBUG) == 0) {
+mcdserver_state.cpu_state.stop_str = "";
+mcdserver_state.cpu_state.info_str = "";
+mcdserver_state.cpu_state.bp_type = 0;
+mcdserver_state.cpu_state.bp_address = 0;
+}
+}
+
 /**
  * init_query_cmds_table() - Initializes all query functions.
  *
@@ -1507,6 +1544,13 @@ static void init_query_cmds_table(MCDCmdParseEntry 
*mcd_query_cmds_table)
 strcpy(query_regs_c.schema, (char[2]) { ARG_SCHEMA_QRYHANDLE, '\0' });
 mcd_query_cmds_table[cmd_number] = query_regs_c;
 cmd_number++;
+
+MCDCmdParseEntry query_state = {
+.handler = handle_query_state,
+.cmd = QUERY_ARG_STATE,
+};
+strcpy(query_state.schema, (char[2]) { ARG_SCHEMA_CORENUM, '\0' });
+mcd_query_cmds_table[cmd_number] = query_state;
 }
 
 /**
-- 
2.34.1




[PATCH v4 09/17] mcdstub: TCP packet plumbing added

2023-12-07 Thread Nicolas Eder
---
 debug/mcdstub/mcdstub.c | 422 
 1 file changed, 422 insertions(+)

diff --git a/debug/mcdstub/mcdstub.c b/debug/mcdstub/mcdstub.c
index 176d5d2311..f97bccf409 100644
--- a/debug/mcdstub/mcdstub.c
+++ b/debug/mcdstub/mcdstub.c
@@ -87,6 +87,320 @@ static int mcd_chr_can_receive(void *opaque)
 return MAX_PACKET_LENGTH;
 }
 
+/**
+ * mcd_put_buffer() - Sends the buf as TCP packet with qemu_chr_fe_write_all.
+ *
+ * @buf: TCP packet data.
+ * @len: TCP packet length.
+ */
+static void mcd_put_buffer(const uint8_t *buf, int len)
+{
+qemu_chr_fe_write_all(_system_state.chr, buf, len);
+}
+
+/**
+ * mcd_put_packet_binary() - Adds footer and header to the TCP packet data in
+ * buf.
+ *
+ * Besides adding header and footer, this function also stores the complete TCP
+ * packet in the last_packet member of the mcdserver_state. Then the packet
+ * gets send with the :c:func:`mcd_put_buffer` function.
+ * @buf: TCP packet data.
+ * @len: TCP packet length.
+ */
+static int mcd_put_packet_binary(const char *buf, int len)
+{
+g_byte_array_set_size(mcdserver_state.last_packet, 0);
+g_byte_array_append(mcdserver_state.last_packet,
+(const uint8_t *) (char[2]) { TCP_COMMAND_START, '\0' }, 1);
+g_byte_array_append(mcdserver_state.last_packet,
+(const uint8_t *) buf, len);
+g_byte_array_append(mcdserver_state.last_packet,
+(const uint8_t *) (char[2]) { TCP_COMMAND_END, '\0' }, 1);
+g_byte_array_append(mcdserver_state.last_packet,
+(const uint8_t *) (char[2]) { TCP_WAS_LAST, '\0' }, 1);
+
+mcd_put_buffer(mcdserver_state.last_packet->data,
+mcdserver_state.last_packet->len);
+return 0;
+}
+
+/**
+ * mcd_put_packet() - Calls :c:func:`mcd_put_packet_binary` with buf and length
+ * of buf.
+ *
+ * @buf: TCP packet data.
+ */
+static int mcd_put_packet(const char *buf)
+{
+return mcd_put_packet_binary(buf, strlen(buf));
+}
+
+/**
+ * cmd_parse_params() - Extracts all parameters from a TCP packet.
+ *
+ * This function uses the schema parameter to determine which type of parameter
+ * to expect. It then extracts that parameter from the data and stores it in
+ * the params GArray.
+ * @data: TCP packet data.
+ * @schema: List of expected parameters for the packet.
+ * @params: GArray with all extracted parameters.
+ */
+static int cmd_parse_params(const char *data, const char *schema,
+GArray *params)
+{
+char data_buffer[64] = {0};
+const char *remaining_data = data;
+
+for (int i = 0; i < strlen(schema); i++) {
+/* get correct part of data */
+char *separator = strchr(remaining_data, ARGUMENT_SEPARATOR);
+
+if (separator) {
+/* multiple arguments */
+int seperator_index = (int)(separator - remaining_data);
+strncpy(data_buffer, remaining_data, seperator_index);
+data_buffer[seperator_index] = 0;
+} else {
+strncpy(data_buffer, remaining_data, strlen(remaining_data));
+data_buffer[strlen(remaining_data)] = 0;
+}
+
+/* store right data */
+MCDCmdVariant this_param;
+switch (schema[i]) {
+case ARG_SCHEMA_STRING:
+/* this has to be the last argument */
+this_param.data = remaining_data;
+g_array_append_val(params, this_param);
+break;
+case ARG_SCHEMA_HEXDATA:
+g_string_printf(mcdserver_state.str_buf, "%s", data_buffer);
+break;
+case ARG_SCHEMA_INT:
+if (qemu_strtou32(remaining_data, _data, 10,
+  (uint32_t *)_param.data_uint32_t)) {
+return -1;
+}
+g_array_append_val(params, this_param);
+break;
+case ARG_SCHEMA_UINT64_T:
+if (qemu_strtou64(remaining_data, _data, 10,
+  (uint64_t *)_param.data_uint64_t)) {
+return -1;
+}
+g_array_append_val(params, this_param);
+break;
+case ARG_SCHEMA_QRYHANDLE:
+if (qemu_strtou32(remaining_data, _data, 10,
+  (uint32_t *)_param.query_handle)) {
+return -1;
+}
+g_array_append_val(params, this_param);
+break;
+case ARG_SCHEMA_CORENUM:
+if (qemu_strtou32(remaining_data, _data, 10,
+  (uint32_t *)_param.cpu_id)) {
+return -1;
+}
+g_array_append_val(params, this_param);
+break;
+default:
+return -1;
+}
+/* update remaining data for the next run */
+remaining_data = &(remaining_data[1]);
+}
+return 0;
+}
+
+/**
+ * process_string_cmd() - Collects all parameters from the data and calls the
+ * correct handler.
+ *
+ 

Re: [PATCH for 8.2] docs: clean-up the xenpvh documentation

2023-12-07 Thread Alex Bennée
Stefan Hajnoczi  writes:

> On Thu, 7 Dec 2023 at 08:07, Alex Bennée  wrote:
>>
>> I noticed the code blocks where not rendering properly so thought I'd
>> better fix things up. So:
>>
>>   - Use better title for the machine type
>>   - Explain why Xen is a little different
>>   - Add a proper anchor to the tpm-device link
>>   - add newline so code block properly renders
>>   - add some indentation to make continuation clearer
>>
>> Signed-off-by: Alex Bennée 
>> ---
>>  docs/specs/tpm.rst |  2 ++
>>  docs/system/arm/xenpvh.rst | 39 +-
>>  2 files changed, 24 insertions(+), 17 deletions(-)
>
> QEMU 8.2.0-rc3 has already been tagged. At this stage only critical
> bugs (crashes during startup, security issues, serious memory leaks,
> etc).
>
> This patch looks like a nice documentation fix but it has a limited
> scope and I don't think it warrants rolling an -rc4 tag next week.
>
> Do you agree with deferring this patch until after the 8.2 release?

Sure - but if you do end up rolling an rc4 it would be a low risk fix.

>
> Stefan
>
>>
>> diff --git a/docs/specs/tpm.rst b/docs/specs/tpm.rst
>> index efe124a148..c96776a369 100644
>> --- a/docs/specs/tpm.rst
>> +++ b/docs/specs/tpm.rst
>> @@ -1,3 +1,5 @@
>> +.. _tpm-device:
>> +
>>  ===
>>  QEMU TPM Device
>>  ===
>> diff --git a/docs/system/arm/xenpvh.rst b/docs/system/arm/xenpvh.rst
>> index e1655c7ab8..430ac2c02e 100644
>> --- a/docs/system/arm/xenpvh.rst
>> +++ b/docs/system/arm/xenpvh.rst
>> @@ -1,34 +1,39 @@
>> -XENPVH (``xenpvh``)
>> +Xen Device Emulation Backend (``xenpvh``)
>>  =
>> -This machine creates a IOREQ server to register/connect with Xen Hypervisor.
>>
>> -When TPM is enabled, this machine also creates a tpm-tis-device at a user 
>> input
>> -tpm base address, adds a TPM emulator and connects to a swtpm application
>> -running on host machine via chardev socket. This enables xenpvh to support 
>> TPM
>> -functionalities for a guest domain.
>> +This machine is a little unusual compared to others as QEMU just acts
>> +as an IOREQ server to register/connect with Xen Hypervisor. Control of
>> +the VMs themselves is left to the Xen tooling.
>>
>> -More information about TPM use and installing swtpm linux application can be
>> -found at: docs/specs/tpm.rst.
>> +When TPM is enabled, this machine also creates a tpm-tis-device at a
>> +user input tpm base address, adds a TPM emulator and connects to a
>> +swtpm application running on host machine via chardev socket. This
>> +enables xenpvh to support TPM functionalities for a guest domain.
>> +
>> +More information about TPM use and installing swtpm linux application
>> +can be found in the :ref:`tpm-device` section.
>>
>>  Example for starting swtpm on host machine:
>> +
>>  .. code-block:: console
>>
>>  mkdir /tmp/vtpm2
>>  swtpm socket --tpmstate dir=/tmp/vtpm2 \
>> ---ctrl type=unixio,path=/tmp/vtpm2/swtpm-sock &
>> +  --ctrl type=unixio,path=/tmp/vtpm2/swtpm-sock &
>>
>>  Sample QEMU xenpvh commands for running and connecting with Xen:
>> +
>>  .. code-block:: console
>>
>>  qemu-system-aarch64 -xen-domid 1 \
>> --chardev socket,id=libxl-cmd,path=qmp-libxl-1,server=on,wait=off \
>> --mon chardev=libxl-cmd,mode=control \
>> --chardev 
>> socket,id=libxenstat-cmd,path=qmp-libxenstat-1,server=on,wait=off \
>> --mon chardev=libxenstat-cmd,mode=control \
>> --xen-attach -name guest0 -vnc none -display none -nographic \
>> --machine xenpvh -m 1301 \
>> --chardev socket,id=chrtpm,path=tmp/vtpm2/swtpm-sock \
>> --tpmdev emulator,id=tpm0,chardev=chrtpm -machine 
>> tpm-base-addr=0x0C00
>> +  -chardev socket,id=libxl-cmd,path=qmp-libxl-1,server=on,wait=off \
>> +  -mon chardev=libxl-cmd,mode=control \
>> +  -chardev 
>> socket,id=libxenstat-cmd,path=qmp-libxenstat-1,server=on,wait=off \
>> +  -mon chardev=libxenstat-cmd,mode=control \
>> +  -xen-attach -name guest0 -vnc none -display none -nographic \
>> +  -machine xenpvh -m 1301 \
>> +  -chardev socket,id=chrtpm,path=tmp/vtpm2/swtpm-sock \
>> +  -tpmdev emulator,id=tpm0,chardev=chrtpm -machine 
>> tpm-base-addr=0x0C00
>>
>>  In above QEMU command, last two lines are for connecting xenpvh QEMU to 
>> swtpm
>>  via chardev socket.
>> --
>> 2.39.2
>>
>>

-- 
Alex Bennée
Virtualisation Tech Lead @ Linaro



Re: [PATCH for 8.2] docs: clean-up the xenpvh documentation

2023-12-07 Thread Stefan Hajnoczi
On Thu, 7 Dec 2023 at 08:07, Alex Bennée  wrote:
>
> I noticed the code blocks where not rendering properly so thought I'd
> better fix things up. So:
>
>   - Use better title for the machine type
>   - Explain why Xen is a little different
>   - Add a proper anchor to the tpm-device link
>   - add newline so code block properly renders
>   - add some indentation to make continuation clearer
>
> Signed-off-by: Alex Bennée 
> ---
>  docs/specs/tpm.rst |  2 ++
>  docs/system/arm/xenpvh.rst | 39 +-
>  2 files changed, 24 insertions(+), 17 deletions(-)

QEMU 8.2.0-rc3 has already been tagged. At this stage only critical
bugs (crashes during startup, security issues, serious memory leaks,
etc).

This patch looks like a nice documentation fix but it has a limited
scope and I don't think it warrants rolling an -rc4 tag next week.

Do you agree with deferring this patch until after the 8.2 release?

Stefan

>
> diff --git a/docs/specs/tpm.rst b/docs/specs/tpm.rst
> index efe124a148..c96776a369 100644
> --- a/docs/specs/tpm.rst
> +++ b/docs/specs/tpm.rst
> @@ -1,3 +1,5 @@
> +.. _tpm-device:
> +
>  ===
>  QEMU TPM Device
>  ===
> diff --git a/docs/system/arm/xenpvh.rst b/docs/system/arm/xenpvh.rst
> index e1655c7ab8..430ac2c02e 100644
> --- a/docs/system/arm/xenpvh.rst
> +++ b/docs/system/arm/xenpvh.rst
> @@ -1,34 +1,39 @@
> -XENPVH (``xenpvh``)
> +Xen Device Emulation Backend (``xenpvh``)
>  =
> -This machine creates a IOREQ server to register/connect with Xen Hypervisor.
>
> -When TPM is enabled, this machine also creates a tpm-tis-device at a user 
> input
> -tpm base address, adds a TPM emulator and connects to a swtpm application
> -running on host machine via chardev socket. This enables xenpvh to support 
> TPM
> -functionalities for a guest domain.
> +This machine is a little unusual compared to others as QEMU just acts
> +as an IOREQ server to register/connect with Xen Hypervisor. Control of
> +the VMs themselves is left to the Xen tooling.
>
> -More information about TPM use and installing swtpm linux application can be
> -found at: docs/specs/tpm.rst.
> +When TPM is enabled, this machine also creates a tpm-tis-device at a
> +user input tpm base address, adds a TPM emulator and connects to a
> +swtpm application running on host machine via chardev socket. This
> +enables xenpvh to support TPM functionalities for a guest domain.
> +
> +More information about TPM use and installing swtpm linux application
> +can be found in the :ref:`tpm-device` section.
>
>  Example for starting swtpm on host machine:
> +
>  .. code-block:: console
>
>  mkdir /tmp/vtpm2
>  swtpm socket --tpmstate dir=/tmp/vtpm2 \
> ---ctrl type=unixio,path=/tmp/vtpm2/swtpm-sock &
> +  --ctrl type=unixio,path=/tmp/vtpm2/swtpm-sock &
>
>  Sample QEMU xenpvh commands for running and connecting with Xen:
> +
>  .. code-block:: console
>
>  qemu-system-aarch64 -xen-domid 1 \
> --chardev socket,id=libxl-cmd,path=qmp-libxl-1,server=on,wait=off \
> --mon chardev=libxl-cmd,mode=control \
> --chardev 
> socket,id=libxenstat-cmd,path=qmp-libxenstat-1,server=on,wait=off \
> --mon chardev=libxenstat-cmd,mode=control \
> --xen-attach -name guest0 -vnc none -display none -nographic \
> --machine xenpvh -m 1301 \
> --chardev socket,id=chrtpm,path=tmp/vtpm2/swtpm-sock \
> --tpmdev emulator,id=tpm0,chardev=chrtpm -machine tpm-base-addr=0x0C00
> +  -chardev socket,id=libxl-cmd,path=qmp-libxl-1,server=on,wait=off \
> +  -mon chardev=libxl-cmd,mode=control \
> +  -chardev 
> socket,id=libxenstat-cmd,path=qmp-libxenstat-1,server=on,wait=off \
> +  -mon chardev=libxenstat-cmd,mode=control \
> +  -xen-attach -name guest0 -vnc none -display none -nographic \
> +  -machine xenpvh -m 1301 \
> +  -chardev socket,id=chrtpm,path=tmp/vtpm2/swtpm-sock \
> +  -tpmdev emulator,id=tpm0,chardev=chrtpm -machine 
> tpm-base-addr=0x0C00
>
>  In above QEMU command, last two lines are for connecting xenpvh QEMU to swtpm
>  via chardev socket.
> --
> 2.39.2
>
>



Re: Request for New PPC Machine Supporting Multiple SMP Cores

2023-12-07 Thread BALATON Zoltan

On Thu, 7 Dec 2023, Peter Maydell wrote:

On Thu, 7 Dec 2023 at 17:40, BALATON Zoltan  wrote:


On Thu, 7 Dec 2023, aziz tlili wrote:

Dear QEMU Team,

I hope this message finds you well. I've been a user of QEMU for well over
a year.

I wanted to share an idea for a potential enhancement that I believe could
benefit many users, including myself. It would be fantastic to have a new
PPC machine model similar to the existing mac99, but with support for
multiple SMP cores for both qemu-system-ppc and qemu-system-ppc64.


There are several machines in qemu-system-ppc64 that support SMP such as
pseries and powernv I think. For qemu-system-ppc maybe only ppce500. The
mac99 may create multiple CPUs (G4 when ron with qemu-system-ppc or G5
with qemu-system-ppc64) but not sure if there's an OS that can actually
use that. Linux support for mac99 may not be the best.


I think our mac99 machine refuses to create more than one CPU, because
it sets mc->max_cpus to 1 in core99_machine_class_init(). This in


Right. I remembered there was some quirk about that but it still has a 
loop when creating CPUs that's then apparently disabled. I've tried to 
send patches before to detangle this machine a bit as it also behaves 
differently depending if it's called from qemu-system-ppc or 
qemu-system-ppc64 or if machine properties are set which can be confusing 
but we could not agree on some naming so those patches were dropped at the 
end.



turn is probably because nobody has ever implemented and tested
whatever the SMP support handling would need to be for this machine
type.


It's likely that chipset support needed for SMP is missing although not 
sure how much of that would Linux need. So for now better try the others 
I've mentioned which may work better than mac99.



Problem is not in understanding the potential advantages but the lack of
people interested in working on that so progress depends on somebody doing
it and sending patches.


Entirely agreed. This is a feature request from two years ago about
adding SMP support to the newworld machines:
https://gitlab.com/qemu-project/qemu/-/issues/672
Nobody has done that work in two years, but anybody who has the
interest and time to do so is welcome to.


One thing that makes it a bit difficult is that there aren't much 
documentation available so those interested may need to consult Linux and 
XNU sources to find out what would need to be emulated.


Regards,
BALATON Zoltan



[PATCH 31/40] vdpa: batch map and unmap around cvq svq start/stop

2023-12-07 Thread Si-Wei Liu
Coalesce map or unmap operations to exact one DMA
batch to reduce potential impact on performance.

Signed-off-by: Si-Wei Liu 
---
 net/vhost-vdpa.c | 8 +++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c
index bc72345..1c1d61f 100644
--- a/net/vhost-vdpa.c
+++ b/net/vhost-vdpa.c
@@ -715,10 +715,11 @@ out:
v->shared->iova_range.last);
 }
 
+vhost_vdpa_dma_batch_begin_once(v->shared, v->address_space_id);
 r = vhost_vdpa_cvq_map_buf(>vhost_vdpa, s->cvq_cmd_out_buffer,
vhost_vdpa_net_cvq_cmd_page_len(), false);
 if (unlikely(r < 0)) {
-return r;
+goto err;
 }
 
 r = vhost_vdpa_cvq_map_buf(>vhost_vdpa, s->status,
@@ -727,18 +728,23 @@ out:
 vhost_vdpa_cvq_unmap_buf(>vhost_vdpa, s->cvq_cmd_out_buffer);
 }
 
+err:
+vhost_vdpa_dma_batch_end_once(v->shared, v->address_space_id);
 return r;
 }
 
 static void vhost_vdpa_net_cvq_stop(NetClientState *nc)
 {
 VhostVDPAState *s = DO_UPCAST(VhostVDPAState, nc, nc);
+struct vhost_vdpa *v = >vhost_vdpa;
 
 assert(nc->info->type == NET_CLIENT_DRIVER_VHOST_VDPA);
 
 if (s->vhost_vdpa.shadow_vqs_enabled) {
+vhost_vdpa_dma_batch_begin_once(v->shared, v->address_space_id);
 vhost_vdpa_cvq_unmap_buf(>vhost_vdpa, s->cvq_cmd_out_buffer);
 vhost_vdpa_cvq_unmap_buf(>vhost_vdpa, s->status);
+vhost_vdpa_dma_batch_end_once(v->shared, v->address_space_id);
 }
 
 vhost_vdpa_net_client_stop(nc);
-- 
1.8.3.1




[PATCH 28/40] vdpa: support iotlb_batch_asid

2023-12-07 Thread Si-Wei Liu
Then it's possible to specify ASID when calling the DMA
batching API. If the ASID to work on doesn't align with
the ASID for ongoing transaction, the API will fail the
request and return negative, and the transaction will
remain intact as if no failed request ever had occured.

Signed-off-by: Si-Wei Liu 
---
 hw/virtio/vhost-vdpa.c | 25 +++--
 include/hw/virtio/vhost-vdpa.h |  1 +
 net/vhost-vdpa.c   |  1 +
 3 files changed, 21 insertions(+), 6 deletions(-)

diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c
index d3f5721..b7896a8 100644
--- a/hw/virtio/vhost-vdpa.c
+++ b/hw/virtio/vhost-vdpa.c
@@ -189,15 +189,25 @@ static bool vhost_vdpa_map_batch_begin(VhostVDPAShared 
*s, uint32_t asid)
 
 static int vhost_vdpa_dma_batch_begin_once(VhostVDPAShared *s, uint32_t asid)
 {
-if (!(s->backend_cap & (0x1ULL << VHOST_BACKEND_F_IOTLB_BATCH)) ||
-s->iotlb_batch_begin_sent) {
+if (!(s->backend_cap & (0x1ULL << VHOST_BACKEND_F_IOTLB_BATCH))) {
 return 0;
 }
 
-if (vhost_vdpa_map_batch_begin(s, asid)) {
-s->iotlb_batch_begin_sent = true;
+if (s->iotlb_batch_begin_sent && s->iotlb_batch_asid != asid) {
+return -1;
+}
+
+if (s->iotlb_batch_begin_sent) {
+return 0;
 }
 
+if (!vhost_vdpa_map_batch_begin(s, asid)) {
+return 0;
+}
+
+s->iotlb_batch_begin_sent = true;
+s->iotlb_batch_asid = asid;
+
 return 0;
 }
 
@@ -237,10 +247,13 @@ static int vhost_vdpa_dma_batch_end_once(VhostVDPAShared 
*s, uint32_t asid)
 return 0;
 }
 
-if (vhost_vdpa_dma_batch_end(s, asid)) {
-s->iotlb_batch_begin_sent = false;
+if (!vhost_vdpa_dma_batch_end(s, asid)) {
+return 0;
 }
 
+s->iotlb_batch_begin_sent = false;
+s->iotlb_batch_asid = -1;
+
 return 0;
 }
 
diff --git a/include/hw/virtio/vhost-vdpa.h b/include/hw/virtio/vhost-vdpa.h
index 0fe0f60..219316f 100644
--- a/include/hw/virtio/vhost-vdpa.h
+++ b/include/hw/virtio/vhost-vdpa.h
@@ -61,6 +61,7 @@ typedef struct vhost_vdpa_shared {
 bool map_thread_enabled;
 
 bool iotlb_batch_begin_sent;
+uint32_t iotlb_batch_asid;
 
 /*
  * The memory listener has been registered, so DMA maps have been sent to
diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c
index e9b96ed..bc72345 100644
--- a/net/vhost-vdpa.c
+++ b/net/vhost-vdpa.c
@@ -1933,6 +1933,7 @@ static NetClientState *net_vhost_vdpa_init(NetClientState 
*peer,
 s->vhost_vdpa.shared->device_fd = vdpa_device_fd;
 s->vhost_vdpa.shared->iova_range = iova_range;
 s->vhost_vdpa.shared->shadow_data = svq;
+s->vhost_vdpa.shared->iotlb_batch_asid = -1;
 s->vhost_vdpa.shared->refcnt++;
 } else if (!is_datapath) {
 s->cvq_cmd_out_buffer = mmap(NULL, vhost_vdpa_net_cvq_cmd_page_len(),
-- 
1.8.3.1




[PATCH 40/40] vdpa: add trace event for vhost_vdpa_net_load_mq

2023-12-07 Thread Si-Wei Liu
For better debuggability and observability.

Signed-off-by: Si-Wei Liu 
---
 net/trace-events | 1 +
 net/vhost-vdpa.c | 2 ++
 2 files changed, 3 insertions(+)

diff --git a/net/trace-events b/net/trace-events
index be087e6..c128cc4 100644
--- a/net/trace-events
+++ b/net/trace-events
@@ -30,3 +30,4 @@ vhost_vdpa_net_data_eval_flush(void *s, int qindex, int 
svq_switch, bool svq_flu
 vhost_vdpa_net_cvq_eval_flush(void *s, int qindex, int svq_switch, bool 
svq_flush) "vhost_vdpa: %p qp: %d svq_switch: %d flush_map: %d"
 vhost_vdpa_net_load_cmd(void *s, uint8_t class, uint8_t cmd, int data_num, int 
data_size) "vdpa state: %p class: %u cmd: %u sg_num: %d size: %d"
 vhost_vdpa_net_load_cmd_retval(void *s, uint8_t class, uint8_t cmd, int r) 
"vdpa state: %p class: %u cmd: %u retval: %d"
+vhost_vdpa_net_load_mq(void *s, int ncurqps) "vdpa state: %p current_qpairs: 
%d"
diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c
index 61da8b4..17b8d01 100644
--- a/net/vhost-vdpa.c
+++ b/net/vhost-vdpa.c
@@ -1109,6 +1109,8 @@ static int vhost_vdpa_net_load_mq(VhostVDPAState *s,
 return 0;
 }
 
+trace_vhost_vdpa_net_load_mq(s, n->curr_queue_pairs);
+
 mq.virtqueue_pairs = cpu_to_le16(n->curr_queue_pairs);
 const struct iovec data = {
 .iov_base = ,
-- 
1.8.3.1




[PATCH 07/40] vdpa: move around vhost_vdpa_set_address_space_id

2023-12-07 Thread Si-Wei Liu
Move it a few lines ahead to make function call easier for those
before it.  No funtional change involved.

Signed-off-by: Si-Wei Liu 
---
 net/vhost-vdpa.c | 36 ++--
 1 file changed, 18 insertions(+), 18 deletions(-)

diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c
index 1a738b2..dbfa192 100644
--- a/net/vhost-vdpa.c
+++ b/net/vhost-vdpa.c
@@ -335,6 +335,24 @@ static void vdpa_net_migration_state_notifier(Notifier 
*notifier, void *data)
 }
 }
 
+static int vhost_vdpa_set_address_space_id(struct vhost_vdpa *v,
+   unsigned vq_group,
+   unsigned asid_num)
+{
+struct vhost_vring_state asid = {
+.index = vq_group,
+.num = asid_num,
+};
+int r;
+
+r = ioctl(v->shared->device_fd, VHOST_VDPA_SET_GROUP_ASID, );
+if (unlikely(r < 0)) {
+error_report("Can't set vq group %u asid %u, errno=%d (%s)",
+ asid.index, asid.num, errno, g_strerror(errno));
+}
+return r;
+}
+
 static void vhost_vdpa_net_data_start_first(VhostVDPAState *s)
 {
 struct vhost_vdpa *v = >vhost_vdpa;
@@ -490,24 +508,6 @@ static int64_t vhost_vdpa_get_vring_desc_group(int 
device_fd,
 return state.num;
 }
 
-static int vhost_vdpa_set_address_space_id(struct vhost_vdpa *v,
-   unsigned vq_group,
-   unsigned asid_num)
-{
-struct vhost_vring_state asid = {
-.index = vq_group,
-.num = asid_num,
-};
-int r;
-
-r = ioctl(v->shared->device_fd, VHOST_VDPA_SET_GROUP_ASID, );
-if (unlikely(r < 0)) {
-error_report("Can't set vq group %u asid %u, errno=%d (%s)",
- asid.index, asid.num, errno, g_strerror(errno));
-}
-return r;
-}
-
 static void vhost_vdpa_cvq_unmap_buf(struct vhost_vdpa *v, void *addr)
 {
 VhostIOVATree *tree = v->shared->iova_tree;
-- 
1.8.3.1




[PATCH 22/40] vdpa: factor out vhost_vdpa_map_batch_begin

2023-12-07 Thread Si-Wei Liu
Refactoring only. No functional change.

Signed-off-by: Si-Wei Liu 
---
 hw/virtio/trace-events |  2 +-
 hw/virtio/vhost-vdpa.c | 25 -
 2 files changed, 17 insertions(+), 10 deletions(-)

diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events
index 9725d44..b0239b8 100644
--- a/hw/virtio/trace-events
+++ b/hw/virtio/trace-events
@@ -32,7 +32,7 @@ vhost_user_create_notifier(int idx, void *n) "idx:%d n:%p"
 # vhost-vdpa.c
 vhost_vdpa_dma_map(void *vdpa, int fd, uint32_t msg_type, uint32_t asid, 
uint64_t iova, uint64_t size, uint64_t uaddr, uint8_t perm, uint8_t type) 
"vdpa_shared:%p fd: %d msg_type: %"PRIu32" asid: %"PRIu32" iova: 0x%"PRIx64" 
size: 0x%"PRIx64" uaddr: 0x%"PRIx64" perm: 0x%"PRIx8" type: %"PRIu8
 vhost_vdpa_dma_unmap(void *vdpa, int fd, uint32_t msg_type, uint32_t asid, 
uint64_t iova, uint64_t size, uint8_t type) "vdpa_shared:%p fd: %d msg_type: 
%"PRIu32" asid: %"PRIu32" iova: 0x%"PRIx64" size: 0x%"PRIx64" type: %"PRIu8
-vhost_vdpa_listener_begin_batch(void *v, int fd, uint32_t msg_type, uint8_t 
type)  "vdpa_shared:%p fd: %d msg_type: %"PRIu32" type: %"PRIu8
+vhost_vdpa_map_batch_begin(void *v, int fd, uint32_t msg_type, uint8_t type)  
"vdpa_shared:%p fd: %d msg_type: %"PRIu32" type: %"PRIu8
 vhost_vdpa_listener_commit(void *v, int fd, uint32_t msg_type, uint8_t type)  
"vdpa_shared:%p fd: %d msg_type: %"PRIu32" type: %"PRIu8
 vhost_vdpa_listener_region_add_unaligned(void *v, const char *name, uint64_t 
offset_as, uint64_t offset_page) "vdpa_shared: %p region %s 
offset_within_address_space %"PRIu64" offset_within_region %"PRIu64
 vhost_vdpa_listener_region_add(void *vdpa, uint64_t iova, uint64_t llend, void 
*vaddr, bool readonly) "vdpa: %p iova 0x%"PRIx64" llend 0x%"PRIx64" vaddr: %p 
read-only: %d"
diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c
index 013bfa2..7a1b7f4 100644
--- a/hw/virtio/vhost-vdpa.c
+++ b/hw/virtio/vhost-vdpa.c
@@ -161,7 +161,7 @@ int vhost_vdpa_dma_unmap(VhostVDPAShared *s, uint32_t asid, 
hwaddr iova,
 return ret;
 }
 
-static void vhost_vdpa_iotlb_batch_begin_once(VhostVDPAShared *s)
+static bool vhost_vdpa_map_batch_begin(VhostVDPAShared *s)
 {
 int fd = s->device_fd;
 struct vhost_msg_v2 msg = {
@@ -169,26 +169,33 @@ static void 
vhost_vdpa_iotlb_batch_begin_once(VhostVDPAShared *s)
 .iotlb.type = VHOST_IOTLB_BATCH_BEGIN,
 };
 
-if (!(s->backend_cap & (0x1ULL << VHOST_BACKEND_F_IOTLB_BATCH)) ||
-s->iotlb_batch_begin_sent) {
-return;
-}
-
 if (s->map_thread_enabled && !qemu_thread_is_self(>map_thread)) {
 struct vhost_msg_v2 *new_msg = g_new(struct vhost_msg_v2, 1);
 
 *new_msg = msg;
 g_async_queue_push(s->map_queue, new_msg);
 
-return;
+return false;
 }
 
-trace_vhost_vdpa_listener_begin_batch(s, fd, msg.type, msg.iotlb.type);
+trace_vhost_vdpa_map_batch_begin(s, fd, msg.type, msg.iotlb.type);
 if (write(fd, , sizeof(msg)) != sizeof(msg)) {
 error_report("failed to write, fd=%d, errno=%d (%s)",
  fd, errno, strerror(errno));
 }
-s->iotlb_batch_begin_sent = true;
+return true;
+}
+
+static void vhost_vdpa_iotlb_batch_begin_once(VhostVDPAShared *s)
+{
+if (!(s->backend_cap & (0x1ULL << VHOST_BACKEND_F_IOTLB_BATCH)) ||
+s->iotlb_batch_begin_sent) {
+return;
+}
+
+if (vhost_vdpa_map_batch_begin(s)) {
+s->iotlb_batch_begin_sent = true;
+}
 }
 
 static void vhost_vdpa_dma_batch_end_once(VhostVDPAShared *s)
-- 
1.8.3.1




[PATCH 12/40] vdpa: check map_thread_enabled before join maps thread

2023-12-07 Thread Si-Wei Liu
The next patches will also register memory listener on
demand, hence the need to differentiate the map_thread
case from the rest.

Signed-off-by: Si-Wei Liu 
---
 hw/virtio/vhost-vdpa.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c
index 2b1cc14..4f026db 100644
--- a/hw/virtio/vhost-vdpa.c
+++ b/hw/virtio/vhost-vdpa.c
@@ -1450,7 +1450,7 @@ static int vhost_vdpa_dev_start(struct vhost_dev *dev, 
bool started)
 if (!v->shared->listener_registered) {
 memory_listener_register(>shared->listener, dev->vdev->dma_as);
 v->shared->listener_registered = true;
-} else {
+} else if (v->shared->map_thread_enabled) {
 ok = vhost_vdpa_join_maps_thread(v->shared);
 if (unlikely(!ok)) {
 goto out_stop;
-- 
1.8.3.1




[PATCH 06/40] vhost: make svq work with gpa without iova translation

2023-12-07 Thread Si-Wei Liu
Make vhost_svq_vring_write_descs able to work with GPA directly
without going through iova tree for translation. This will be
needed in the next few patches where the SVQ has dedicated
address space to host its virtqueues. Instead of having to
translate qemu's VA to IOVA via the iova tree, with dedicated
or isolated address space for SVQ descriptors, the IOVA is
exactly same as the guest GPA space where translation would
not be needed any more.

Signed-off-by: Si-Wei Liu 
---
 hw/virtio/vhost-shadow-virtqueue.c | 35 +++
 1 file changed, 23 insertions(+), 12 deletions(-)

diff --git a/hw/virtio/vhost-shadow-virtqueue.c 
b/hw/virtio/vhost-shadow-virtqueue.c
index fc5f408..97ccd45 100644
--- a/hw/virtio/vhost-shadow-virtqueue.c
+++ b/hw/virtio/vhost-shadow-virtqueue.c
@@ -136,8 +136,8 @@ static bool vhost_svq_translate_addr(const 
VhostShadowVirtqueue *svq,
  * Return true if success, false otherwise and print error.
  */
 static bool vhost_svq_vring_write_descs(VhostShadowVirtqueue *svq, hwaddr *sg,
-const struct iovec *iovec, size_t num,
-bool more_descs, bool write)
+const struct iovec *iovec, hwaddr 
*addr,
+size_t num, bool more_descs, bool 
write)
 {
 uint16_t i = svq->free_head, last = svq->free_head;
 unsigned n;
@@ -149,8 +149,15 @@ static bool 
vhost_svq_vring_write_descs(VhostShadowVirtqueue *svq, hwaddr *sg,
 return true;
 }
 
-ok = vhost_svq_translate_addr(svq, sg, iovec, num);
-if (unlikely(!ok)) {
+if (svq->iova_tree) {
+ok = vhost_svq_translate_addr(svq, sg, iovec, num);
+if (unlikely(!ok)) {
+return false;
+}
+} else if (!addr) {
+qemu_log_mask(LOG_GUEST_ERROR,
+  "No translation found for vaddr 0x%p\n",
+  iovec[0].iov_base);
 return false;
 }
 
@@ -161,7 +168,7 @@ static bool 
vhost_svq_vring_write_descs(VhostShadowVirtqueue *svq, hwaddr *sg,
 } else {
 descs[i].flags = flags;
 }
-descs[i].addr = cpu_to_le64(sg[n]);
+descs[i].addr = cpu_to_le64(svq->iova_tree ? sg[n] : addr[n]);
 descs[i].len = cpu_to_le32(iovec[n].iov_len);
 
 last = i;
@@ -173,9 +180,10 @@ static bool 
vhost_svq_vring_write_descs(VhostShadowVirtqueue *svq, hwaddr *sg,
 }
 
 static bool vhost_svq_add_split(VhostShadowVirtqueue *svq,
-const struct iovec *out_sg, size_t out_num,
-const struct iovec *in_sg, size_t in_num,
-unsigned *head)
+const struct iovec *out_sg, hwaddr *out_addr,
+size_t out_num,
+const struct iovec *in_sg, hwaddr *in_addr,
+size_t in_num, unsigned *head)
 {
 unsigned avail_idx;
 vring_avail_t *avail = svq->vring.avail;
@@ -191,13 +199,14 @@ static bool vhost_svq_add_split(VhostShadowVirtqueue *svq,
 return false;
 }
 
-ok = vhost_svq_vring_write_descs(svq, sgs, out_sg, out_num, in_num > 0,
- false);
+ok = vhost_svq_vring_write_descs(svq, sgs, out_sg, out_addr, out_num,
+ in_num > 0, false);
 if (unlikely(!ok)) {
 return false;
 }
 
-ok = vhost_svq_vring_write_descs(svq, sgs, in_sg, in_num, false, true);
+ok = vhost_svq_vring_write_descs(svq, sgs, in_sg, in_addr, in_num,
+ false, true);
 if (unlikely(!ok)) {
 return false;
 }
@@ -258,7 +267,9 @@ int vhost_svq_add(VhostShadowVirtqueue *svq, const struct 
iovec *out_sg,
 return -ENOSPC;
 }
 
-ok = vhost_svq_add_split(svq, out_sg, out_num, in_sg, in_num, _head);
+ok = vhost_svq_add_split(svq, out_sg, elem ? elem->out_addr : NULL,
+ out_num, in_sg, elem ? elem->in_addr : NULL,
+ in_num, _head);
 if (unlikely(!ok)) {
 return -EINVAL;
 }
-- 
1.8.3.1




[PATCH 04/40] vdpa: piggyback desc_group index when probing isolated cvq

2023-12-07 Thread Si-Wei Liu
Same as the previous commit, but do it for cvq instead of data vqs.

Signed-off-by: Si-Wei Liu 
---
 net/vhost-vdpa.c | 21 +
 1 file changed, 17 insertions(+), 4 deletions(-)

diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c
index 0cf3147..cb5705d 100644
--- a/net/vhost-vdpa.c
+++ b/net/vhost-vdpa.c
@@ -1601,16 +1601,19 @@ static const VhostShadowVirtqueueOps 
vhost_vdpa_net_svq_ops = {
 };
 
 /**
- * Probe if CVQ is isolated
+ * Probe if CVQ is isolated, and piggyback its descriptor group
+ * index if supported
  *
  * @device_fd The vdpa device fd
  * @features  Features offered by the device.
  * @cvq_index The control vq pair index
+ * @desc_grpidx   The CVQ's descriptor group index to return
  *
- * Returns <0 in case of failure, 0 if false and 1 if true.
+ * Returns <0 in case of failure, 0 if false and 1 if true (isolated).
  */
 static int vhost_vdpa_probe_cvq_isolation(int device_fd, uint64_t features,
-  int cvq_index, Error **errp)
+  int cvq_index, int64_t *desc_grpidx,
+  Error **errp)
 {
 uint64_t backend_features;
 int64_t cvq_group;
@@ -1667,6 +1670,13 @@ static int vhost_vdpa_probe_cvq_isolation(int device_fd, 
uint64_t features,
 goto out;
 }
 
+if (backend_features & BIT_ULL(VHOST_BACKEND_F_DESC_ASID)) {
+int64_t desc_group = vhost_vdpa_get_vring_desc_group(device_fd,
+ cvq_index, errp);
+if (likely(desc_group >= 0) && desc_group != cvq_group)
+*desc_grpidx = desc_group;
+}
+
 for (int i = 0; i < cvq_index; ++i) {
 int64_t group = vhost_vdpa_get_vring_group(device_fd, i, errp);
 if (unlikely(group < 0)) {
@@ -1685,6 +1695,8 @@ static int vhost_vdpa_probe_cvq_isolation(int device_fd, 
uint64_t features,
 out:
 status = 0;
 ioctl(device_fd, VHOST_VDPA_SET_STATUS, );
+status = VIRTIO_CONFIG_S_ACKNOWLEDGE | VIRTIO_CONFIG_S_DRIVER;
+ioctl(device_fd, VHOST_VDPA_SET_STATUS, );
 return r;
 }
 
@@ -1791,6 +1803,7 @@ static NetClientState *net_vhost_vdpa_init(NetClientState 
*peer,
Error **errp)
 {
 NetClientState *nc = NULL;
+int64_t desc_group = -1;
 VhostVDPAState *s;
 int ret = 0;
 assert(name);
@@ -1802,7 +1815,7 @@ static NetClientState *net_vhost_vdpa_init(NetClientState 
*peer,
 } else {
 cvq_isolated = vhost_vdpa_probe_cvq_isolation(vdpa_device_fd, features,
   queue_pair_index * 2,
-  errp);
+  _group, errp);
 if (unlikely(cvq_isolated < 0)) {
 return NULL;
 }
-- 
1.8.3.1




[PATCH 25/40] vdpa: add asid to dma_batch_once API

2023-12-07 Thread Si-Wei Liu
So that DMA batching API can operate on other ASID than 0.

Signed-off-by: Si-Wei Liu 
---
 hw/virtio/trace-events |  4 ++--
 hw/virtio/vhost-vdpa.c | 14 --
 2 files changed, 10 insertions(+), 8 deletions(-)

diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events
index 3411a07..196f32f 100644
--- a/hw/virtio/trace-events
+++ b/hw/virtio/trace-events
@@ -32,8 +32,8 @@ vhost_user_create_notifier(int idx, void *n) "idx:%d n:%p"
 # vhost-vdpa.c
 vhost_vdpa_dma_map(void *vdpa, int fd, uint32_t msg_type, uint32_t asid, 
uint64_t iova, uint64_t size, uint64_t uaddr, uint8_t perm, uint8_t type) 
"vdpa_shared:%p fd: %d msg_type: %"PRIu32" asid: %"PRIu32" iova: 0x%"PRIx64" 
size: 0x%"PRIx64" uaddr: 0x%"PRIx64" perm: 0x%"PRIx8" type: %"PRIu8
 vhost_vdpa_dma_unmap(void *vdpa, int fd, uint32_t msg_type, uint32_t asid, 
uint64_t iova, uint64_t size, uint8_t type) "vdpa_shared:%p fd: %d msg_type: 
%"PRIu32" asid: %"PRIu32" iova: 0x%"PRIx64" size: 0x%"PRIx64" type: %"PRIu8
-vhost_vdpa_map_batch_begin(void *v, int fd, uint32_t msg_type, uint8_t type)  
"vdpa_shared:%p fd: %d msg_type: %"PRIu32" type: %"PRIu8
-vhost_vdpa_dma_batch_end(void *v, int fd, uint32_t msg_type, uint8_t type)  
"vdpa_shared:%p fd: %d msg_type: %"PRIu32" type: %"PRIu8
+vhost_vdpa_map_batch_begin(void *v, int fd, uint32_t msg_type, uint8_t type, 
uint32_t asid)  "vdpa_shared:%p fd: %d msg_type: %"PRIu32" type: %"PRIu8" asid: 
%"PRIu32
+vhost_vdpa_dma_batch_end(void *v, int fd, uint32_t msg_type, uint8_t type, 
uint32_t asid)  "vdpa_shared:%p fd: %d msg_type: %"PRIu32" type: %"PRIu8" asid: 
%"PRIu32
 vhost_vdpa_listener_region_add_unaligned(void *v, const char *name, uint64_t 
offset_as, uint64_t offset_page) "vdpa_shared: %p region %s 
offset_within_address_space %"PRIu64" offset_within_region %"PRIu64
 vhost_vdpa_listener_region_add(void *vdpa, uint64_t iova, uint64_t llend, void 
*vaddr, bool readonly) "vdpa: %p iova 0x%"PRIx64" llend 0x%"PRIx64" vaddr: %p 
read-only: %d"
 vhost_vdpa_listener_region_del_unaligned(void *v, const char *name, uint64_t 
offset_as, uint64_t offset_page) "vdpa_shared: %p region %s 
offset_within_address_space %"PRIu64" offset_within_region %"PRIu64
diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c
index 999a97a..2db2832 100644
--- a/hw/virtio/vhost-vdpa.c
+++ b/hw/virtio/vhost-vdpa.c
@@ -161,11 +161,12 @@ int vhost_vdpa_dma_unmap(VhostVDPAShared *s, uint32_t 
asid, hwaddr iova,
 return ret;
 }
 
-static bool vhost_vdpa_map_batch_begin(VhostVDPAShared *s)
+static bool vhost_vdpa_map_batch_begin(VhostVDPAShared *s, uint32_t asid)
 {
 int fd = s->device_fd;
 struct vhost_msg_v2 msg = {
 .type = VHOST_IOTLB_MSG_V2,
+.asid = asid,
 .iotlb.type = VHOST_IOTLB_BATCH_BEGIN,
 };
 
@@ -178,7 +179,7 @@ static bool vhost_vdpa_map_batch_begin(VhostVDPAShared *s)
 return false;
 }
 
-trace_vhost_vdpa_map_batch_begin(s, fd, msg.type, msg.iotlb.type);
+trace_vhost_vdpa_map_batch_begin(s, fd, msg.type, msg.iotlb.type, 
msg.asid);
 if (write(fd, , sizeof(msg)) != sizeof(msg)) {
 error_report("failed to write, fd=%d, errno=%d (%s)",
  fd, errno, strerror(errno));
@@ -193,17 +194,18 @@ static void 
vhost_vdpa_dma_batch_begin_once(VhostVDPAShared *s)
 return;
 }
 
-if (vhost_vdpa_map_batch_begin(s)) {
+if (vhost_vdpa_map_batch_begin(s, 0)) {
 s->iotlb_batch_begin_sent = true;
 }
 }
 
-static bool vhost_vdpa_dma_batch_end(VhostVDPAShared *s)
+static bool vhost_vdpa_dma_batch_end(VhostVDPAShared *s, uint32_t asid)
 {
 struct vhost_msg_v2 msg = {};
 int fd = s->device_fd;
 
 msg.type = VHOST_IOTLB_MSG_V2;
+msg.asid = asid;
 msg.iotlb.type = VHOST_IOTLB_BATCH_END;
 
 if (s->map_thread_enabled && !qemu_thread_is_self(>map_thread)) {
@@ -215,7 +217,7 @@ static bool vhost_vdpa_dma_batch_end(VhostVDPAShared *s)
 return false;
 }
 
-trace_vhost_vdpa_dma_batch_end(s, fd, msg.type, msg.iotlb.type);
+trace_vhost_vdpa_dma_batch_end(s, fd, msg.type, msg.iotlb.type, msg.asid);
 if (write(fd, , sizeof(msg)) != sizeof(msg)) {
 error_report("failed to write, fd=%d, errno=%d (%s)",
  fd, errno, strerror(errno));
@@ -233,7 +235,7 @@ static void vhost_vdpa_dma_batch_end_once(VhostVDPAShared 
*s)
 return;
 }
 
-if (vhost_vdpa_dma_batch_end(s)) {
+if (vhost_vdpa_dma_batch_end(s, 0)) {
 s->iotlb_batch_begin_sent = false;
 }
 }
-- 
1.8.3.1




[PATCH 35/40] vdpa: add vhost_vdpa_set_address_space_id trace

2023-12-07 Thread Si-Wei Liu
For better debuggability and observability.

Signed-off-by: Si-Wei Liu 
---
 net/trace-events | 3 +++
 net/vhost-vdpa.c | 3 +++
 2 files changed, 6 insertions(+)

diff --git a/net/trace-events b/net/trace-events
index 823a071..aab666a 100644
--- a/net/trace-events
+++ b/net/trace-events
@@ -23,3 +23,6 @@ colo_compare_tcp_info(const char *pkt, uint32_t seq, uint32_t 
ack, int hdlen, in
 # filter-rewriter.c
 colo_filter_rewriter_pkt_info(const char *func, const char *src, const char 
*dst, uint32_t seq, uint32_t ack, uint32_t flag) "%s: src/dst: %s/%s p: 
seq/ack=%u/%u  flags=0x%x"
 colo_filter_rewriter_conn_offset(uint32_t offset) ": offset=%u"
+
+# vhost-vdpa.c
+vhost_vdpa_set_address_space_id(void *v, unsigned vq_group, unsigned asid_num) 
"vhost_vdpa: %p vq_group: %u asid: %u"
diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c
index 41714d1..84876b0 100644
--- a/net/vhost-vdpa.c
+++ b/net/vhost-vdpa.c
@@ -30,6 +30,7 @@
 #include "migration/misc.h"
 #include "hw/virtio/vhost.h"
 #include "hw/virtio/vhost-vdpa.h"
+#include "trace.h"
 
 /* Todo:need to add the multiqueue support here */
 typedef struct VhostVDPAState {
@@ -365,6 +366,8 @@ static int vhost_vdpa_set_address_space_id(struct 
vhost_vdpa *v,
 };
 int r;
 
+trace_vhost_vdpa_set_address_space_id(v, vq_group, asid_num);
+
 r = ioctl(v->shared->device_fd, VHOST_VDPA_SET_GROUP_ASID, );
 if (unlikely(r < 0)) {
 error_report("Can't set vq group %u asid %u, errno=%d (%s)",
-- 
1.8.3.1




  1   2   >