Re: [PATCH 16/21] hw/net/can/versal: Prefer object_initialize_child over object_initialize

2024-02-23 Thread Francisco Iglesias

On 2024-02-16 12:03, Philippe Mathieu-Daudé wrote:

When the QOM parent is available, prefer object_initialize_child()
over object_initialize(), since it create the parent relationship.

Signed-off-by: Philippe Mathieu-Daudé 


Reviewed-by: Francisco Iglesias 



---
  hw/net/can/xlnx-versal-canfd.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/net/can/xlnx-versal-canfd.c b/hw/net/can/xlnx-versal-canfd.c
index 47a14cfe63..f8e4bd75e4 100644
--- a/hw/net/can/xlnx-versal-canfd.c
+++ b/hw/net/can/xlnx-versal-canfd.c
@@ -1900,7 +1900,7 @@ static int canfd_populate_regarray(XlnxVersalCANFDState 
*s,
  int index = rae[i].addr / 4;
  RegisterInfo *r = >reg_info[index];
  
-object_initialize(r, sizeof(*r), TYPE_REGISTER);

+object_initialize_child(OBJECT(s), "reg[*]", r, TYPE_REGISTER);
  
  *r = (RegisterInfo) {

  .data = >regs[index],




Re: [PATCH 1/2] block: m25p80: Add support of mt35xu02gbba

2023-12-05 Thread Francisco Iglesias
On [2023 Dec 05] Tue 15:22:25, Sai Pavan Boddu wrote:
> Add Micro 2Gb OSPI flash part with sfdp data.
> 
> Signed-off-by: Sai Pavan Boddu 

Reviewed-by: Francisco Iglesias 


> ---
>  hw/block/m25p80_sfdp.h |  1 +
>  hw/block/m25p80.c  |  3 +++
>  hw/block/m25p80_sfdp.c | 36 
>  3 files changed, 40 insertions(+)
> 
> diff --git a/hw/block/m25p80_sfdp.h b/hw/block/m25p80_sfdp.h
> index 011a880f66..1733b56950 100644
> --- a/hw/block/m25p80_sfdp.h
> +++ b/hw/block/m25p80_sfdp.h
> @@ -16,6 +16,7 @@
>  #define M25P80_SFDP_MAX_SIZE  (1 << 24)
>  
>  uint8_t m25p80_sfdp_n25q256a(uint32_t addr);
> +uint8_t m25p80_sfdp_mt35xu02g(uint32_t addr);
>  
>  uint8_t m25p80_sfdp_mx25l25635e(uint32_t addr);
>  uint8_t m25p80_sfdp_mx25l25635f(uint32_t addr);
> diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c
> index afc3fdf4d6..c8c7f6c1c3 100644
> --- a/hw/block/m25p80.c
> +++ b/hw/block/m25p80.c
> @@ -267,6 +267,9 @@ static const FlashPartInfo known_devices[] = {
>  { INFO("mt25ql512ab", 0x20ba20, 0x1044, 64 << 10, 1024, ER_4K | ER_32K) 
> },
>  { INFO_STACKED("mt35xu01g", 0x2c5b1b, 0x104100, 128 << 10, 1024,
> ER_4K | ER_32K, 2) },
> +{ INFO_STACKED("mt35xu02gbba", 0x2c5b1c, 0x104100, 128 << 10, 2048,
> +   ER_4K | ER_32K, 4),
> +   .sfdp_read = m25p80_sfdp_mt35xu02g },
>  { INFO_STACKED("n25q00",0x20ba21, 0x1000, 64 << 10, 2048, ER_4K, 4) 
> },
>  { INFO_STACKED("n25q00a",   0x20bb21, 0x1000, 64 << 10, 2048, ER_4K, 4) 
> },
>  { INFO_STACKED("mt25ql01g", 0x20ba21, 0x1040, 64 << 10, 2048, ER_4K, 2) 
> },
> diff --git a/hw/block/m25p80_sfdp.c b/hw/block/m25p80_sfdp.c
> index b33811a4f5..6ee2cfaf11 100644
> --- a/hw/block/m25p80_sfdp.c
> +++ b/hw/block/m25p80_sfdp.c
> @@ -57,6 +57,42 @@ static const uint8_t sfdp_n25q256a[] = {
>  };
>  define_sfdp_read(n25q256a);
>  
> +static const uint8_t sfdp_mt35xu02g[] = {
> +0x53, 0x46, 0x44, 0x50, 0x06, 0x01, 0x01, 0xff,
> +0x00, 0x06, 0x01, 0x10, 0x30, 0x00, 0x00, 0xff,
> +0x84, 0x00, 0x01, 0x02, 0x80, 0x00, 0x00, 0xff,
> +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +0xe5, 0x20, 0x8a, 0xff, 0xff, 0xff, 0xff, 0x7f,
> +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +0xee, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
> +0xff, 0xff, 0x00, 0x00, 0x0c, 0x20, 0x11, 0xd8,
> +0x0f, 0x52, 0x00, 0x00, 0x24, 0x5a, 0x99, 0x00,
> +0x8b, 0x8e, 0x03, 0xe1, 0xac, 0x01, 0x27, 0x38,
> +0x7a, 0x75, 0x7a, 0x75, 0xfb, 0xbd, 0xd5, 0x5c,
> +0x00, 0x00, 0x70, 0xff, 0x81, 0xb0, 0x38, 0x36,
> +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +0x43, 0x0e, 0xff, 0xff, 0x21, 0xdc, 0x5c, 0xff,
> +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +};
> +
> +define_sfdp_read(mt35xu02g);
>  
>  /*
>   * Matronix
> -- 
> 2.25.1
> 



Re: [PATCH 2/2] arm: xlnx-versal-virt: Add machine property ospi-flash

2023-12-05 Thread Francisco Iglesias
On [2023 Dec 05] Tue 15:22:26, Sai Pavan Boddu wrote:
> This property allows users to change flash model on command line as
> below.
> 
>ex: "-M xlnx-versal-virt,ospi-flash=mt35xu02gbba"
> 
> Signed-off-by: Sai Pavan Boddu 

Reviewed-by: Francisco Iglesias 

> ---
>  hw/arm/xlnx-versal-virt.c | 31 ++-
>  1 file changed, 30 insertions(+), 1 deletion(-)
> 
> diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
> index 537118224f..c57cff74d8 100644
> --- a/hw/arm/xlnx-versal-virt.c
> +++ b/hw/arm/xlnx-versal-virt.c
> @@ -49,6 +49,7 @@ struct VersalVirt {
>  struct {
>  bool secure;
>  } cfg;
> +char *ospi_model;
>  };
>  
>  static void fdt_create(VersalVirt *s)
> @@ -637,6 +638,22 @@ static void sd_plugin_card(SDHCIState *sd, DriveInfo *di)
> _fatal);
>  }
>  
> +static char *versal_get_ospi_model(Object *obj, Error **errp)
> +{
> +VersalVirt *s = XLNX_VERSAL_VIRT_MACHINE(obj);
> +
> +return g_strdup(s->ospi_model);
> +}
> +
> +static void versal_set_ospi_model(Object *obj, const char *value, Error 
> **errp)
> +{
> +VersalVirt *s = XLNX_VERSAL_VIRT_MACHINE(obj);
> +
> +g_free(s->ospi_model);
> +s->ospi_model = g_strdup(value);
> +}
> +
> +
>  static void versal_virt_init(MachineState *machine)
>  {
>  VersalVirt *s = XLNX_VERSAL_VIRT_MACHINE(machine);
> @@ -736,7 +753,7 @@ static void versal_virt_init(MachineState *machine)
>  
>  spi_bus = qdev_get_child_bus(DEVICE(>soc.pmc.iou.ospi), "spi0");
>  
> -flash_dev = qdev_new("mt35xu01g");
> +flash_dev = qdev_new(s->ospi_model ? s->ospi_model : "mt35xu01g");
>  if (dinfo) {
>  qdev_prop_set_drive_err(flash_dev, "drive",
>  blk_by_legacy_dinfo(dinfo), 
> _fatal);
> @@ -769,6 +786,13 @@ static void versal_virt_machine_instance_init(Object 
> *obj)
>   0);
>  }
>  
> +static void versal_virt_machine_finalize(Object *obj)
> +{
> +VersalVirt *s = XLNX_VERSAL_VIRT_MACHINE(obj);
> +
> +g_free(s->ospi_model);
> +}
> +
>  static void versal_virt_machine_class_init(ObjectClass *oc, void *data)
>  {
>  MachineClass *mc = MACHINE_CLASS(oc);
> @@ -780,6 +804,10 @@ static void versal_virt_machine_class_init(ObjectClass 
> *oc, void *data)
>  mc->default_cpus = XLNX_VERSAL_NR_ACPUS + XLNX_VERSAL_NR_RCPUS;
>  mc->no_cdrom = true;
>  mc->default_ram_id = "ddr";
> +object_class_property_add_str(oc, "ospi-flash", versal_get_ospi_model,
> +   versal_set_ospi_model);
> +object_class_property_set_description(oc, "ospi-flash",
> +  "Change the OSPI Flash model");
>  }
>  
>  static const TypeInfo versal_virt_machine_init_typeinfo = {
> @@ -788,6 +816,7 @@ static const TypeInfo versal_virt_machine_init_typeinfo = 
> {
>  .class_init = versal_virt_machine_class_init,
>  .instance_init = versal_virt_machine_instance_init,
>  .instance_size = sizeof(VersalVirt),
> +.instance_finalize = versal_virt_machine_finalize,
>  };
>  
>  static void versal_virt_machine_init_register_types(void)
> -- 
> 2.25.1
> 



Re: [PATCH 1/1] xlnx-versal-ospi: disable reentrancy detection for iomem_dac

2023-12-05 Thread Francisco Iglesias
On [2023 Dec 05] Tue 15:18:02, Sai Pavan Boddu wrote:
> The OSPI DMA reads flash data through the OSPI linear address space (the
> iomem_dac region), because of this the reentrancy guard introduced in
> commit a2e1753b ("memory: prevent dma-reentracy issues") is disabled for
> the memory region.
> 
> Signed-off-by: Sai Pavan Boddu 

Reviewed-by: Francisco Iglesias 
Tested-by: Francisco Iglesias 


> ---
>  hw/ssi/xlnx-versal-ospi.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/hw/ssi/xlnx-versal-ospi.c b/hw/ssi/xlnx-versal-ospi.c
> index 1a61679c2f..5123e7dde7 100644
> --- a/hw/ssi/xlnx-versal-ospi.c
> +++ b/hw/ssi/xlnx-versal-ospi.c
> @@ -1772,6 +1772,7 @@ static void xlnx_versal_ospi_init(Object *obj)
>  memory_region_init_io(>iomem_dac, obj, _dac_ops, s,
>TYPE_XILINX_VERSAL_OSPI "-dac", 0x2000);
>  sysbus_init_mmio(sbd, >iomem_dac);
> +s->iomem_dac.disable_reentrancy_guard = true;
>  
>  sysbus_init_irq(sbd, >irq);
>  
> -- 
> 2.25.1
> 
> 



Re: [PATCH v1 3/3] hw/dma/xlnx_csu_dma: don't throw guest errors when stopping the SRC DMA

2023-11-24 Thread Francisco Iglesias




On 2023-11-24 15:35, Frederic Konrad wrote:

UG1087 states for the source channel that: if SIZE is programmed to 0, and the
DMA is started, the interrupts DONE and MEM_DONE will be asserted.

This implies that it is allowed for the guest to stop the source DMA by writing
a size of 0 to the SIZE register, so remove the LOG_GUEST_ERROR in that case.

While at it remove the comment marking the SIZE register as write-only.

See: 
https://docs.xilinx.com/r/en-US/ug1087-zynq-ultrascale-registers/CSUDMA_SRC_SIZE-CSUDMA-Register

Signed-off-by: Frederic Konrad 


Reviewed-by: Francisco Iglesias 


---
  hw/dma/xlnx_csu_dma.c | 12 
  1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/hw/dma/xlnx_csu_dma.c b/hw/dma/xlnx_csu_dma.c
index 531013f35a..bc1505aade 100644
--- a/hw/dma/xlnx_csu_dma.c
+++ b/hw/dma/xlnx_csu_dma.c
@@ -39,7 +39,7 @@
  REG32(ADDR, 0x0)
  FIELD(ADDR, ADDR, 2, 30) /* wo */
  REG32(SIZE, 0x4)
-FIELD(SIZE, SIZE, 2, 27) /* wo */
+FIELD(SIZE, SIZE, 2, 27)
  FIELD(SIZE, LAST_WORD, 0, 1) /* rw, only exists in SRC */
  REG32(STATUS, 0x8)
  FIELD(STATUS, DONE_CNT, 13, 3) /* wtc */
@@ -335,10 +335,14 @@ static uint64_t addr_pre_write(RegisterInfo *reg, 
uint64_t val)
  static uint64_t size_pre_write(RegisterInfo *reg, uint64_t val)
  {
  XlnxCSUDMA *s = XLNX_CSU_DMA(reg->opaque);
+uint64_t size = val & R_SIZE_SIZE_MASK;
  
  if (s->regs[R_SIZE] != 0) {

-qemu_log_mask(LOG_GUEST_ERROR,
-  "%s: Starting DMA while already running.\n", __func__);
+if (size || s->is_dst) {
+qemu_log_mask(LOG_GUEST_ERROR,
+  "%s: Starting DMA while already running.\n",
+  __func__);
+}
  }
  
  if (!s->is_dst) {

@@ -346,7 +350,7 @@ static uint64_t size_pre_write(RegisterInfo *reg, uint64_t 
val)
  }
  
  /* Size is word aligned */

-return val & R_SIZE_SIZE_MASK;
+return size;
  }
  
  static uint64_t size_post_read(RegisterInfo *reg, uint64_t val)




Re: [PATCH v1 2/3] fix some url for amd / xilinx models

2023-11-24 Thread Francisco Iglesias




On 2023-11-24 15:35, Frederic Konrad wrote:

It seems that the url changed a bit, and it triggers an error.  Fix the URLs so
the documentation can be reached again.

Signed-off-by: Frederic Konrad 

Reviewed-by: Francisco Iglesias 



---
  hw/dma/xlnx_csu_dma.c  | 2 +-
  include/hw/misc/xlnx-versal-cframe-reg.h   | 2 +-
  include/hw/misc/xlnx-versal-cfu.h  | 2 +-
  include/hw/misc/xlnx-versal-pmc-iou-slcr.h | 2 +-
  include/hw/ssi/xlnx-versal-ospi.h  | 2 +-
  5 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/hw/dma/xlnx_csu_dma.c b/hw/dma/xlnx_csu_dma.c
index e89089821a..531013f35a 100644
--- a/hw/dma/xlnx_csu_dma.c
+++ b/hw/dma/xlnx_csu_dma.c
@@ -33,7 +33,7 @@
  
  /*

   * Ref: UG1087 (v1.7) February 8, 2019
- * 
https://www.xilinx.com/html_docs/registers/ug1087/ug1087-zynq-ultrascale-registers.html
+ * 
https://www.xilinx.com/html_docs/registers/ug1087/ug1087-zynq-ultrascale-registers
   * CSUDMA Module section
   */
  REG32(ADDR, 0x0)
diff --git a/include/hw/misc/xlnx-versal-cframe-reg.h 
b/include/hw/misc/xlnx-versal-cframe-reg.h
index a14fbd7fe4..0091505246 100644
--- a/include/hw/misc/xlnx-versal-cframe-reg.h
+++ b/include/hw/misc/xlnx-versal-cframe-reg.h
@@ -12,7 +12,7 @@
   * 
https://www.xilinx.com/support/documentation/architecture-manuals/am011-versal-acap-trm.pdf
   *
   * [2] Versal ACAP Register Reference,
- * 
https://www.xilinx.com/htmldocs/registers/am012/am012-versal-register-reference.html
+ * 
https://docs.xilinx.com/r/en-US/am012-versal-register-reference/CFRAME_REG-Module
   */
  #ifndef HW_MISC_XLNX_VERSAL_CFRAME_REG_H
  #define HW_MISC_XLNX_VERSAL_CFRAME_REG_H
diff --git a/include/hw/misc/xlnx-versal-cfu.h 
b/include/hw/misc/xlnx-versal-cfu.h
index 86fb841053..be62bab8c8 100644
--- a/include/hw/misc/xlnx-versal-cfu.h
+++ b/include/hw/misc/xlnx-versal-cfu.h
@@ -12,7 +12,7 @@
   * 
https://www.xilinx.com/support/documentation/architecture-manuals/am011-versal-acap-trm.pdf
   *
   * [2] Versal ACAP Register Reference,
- * 
https://www.xilinx.com/htmldocs/registers/am012/am012-versal-register-reference.html
+ * 
https://docs.xilinx.com/r/en-US/am012-versal-register-reference/CFU_CSR-Module
   */
  #ifndef HW_MISC_XLNX_VERSAL_CFU_APB_H
  #define HW_MISC_XLNX_VERSAL_CFU_APB_H
diff --git a/include/hw/misc/xlnx-versal-pmc-iou-slcr.h 
b/include/hw/misc/xlnx-versal-pmc-iou-slcr.h
index f7d24c93c4..0c4a4fd66d 100644
--- a/include/hw/misc/xlnx-versal-pmc-iou-slcr.h
+++ b/include/hw/misc/xlnx-versal-pmc-iou-slcr.h
@@ -34,7 +34,7 @@
   * 
https://www.xilinx.com/support/documentation/architecture-manuals/am011-versal-acap-trm.pdf
   *
   * [2] Versal ACAP Register Reference,
- * 
https://www.xilinx.com/html_docs/registers/am012/am012-versal-register-reference.html#mod___pmc_iop_slcr.html
+ * 
https://docs.xilinx.com/r/en-US/am012-versal-register-reference/PMC_IOP_SLCR-Module
   *
   * QEMU interface:
   * + sysbus MMIO region 0: MemoryRegion for the device's registers
diff --git a/include/hw/ssi/xlnx-versal-ospi.h 
b/include/hw/ssi/xlnx-versal-ospi.h
index 5d131d351d..4ac975aa2f 100644
--- a/include/hw/ssi/xlnx-versal-ospi.h
+++ b/include/hw/ssi/xlnx-versal-ospi.h
@@ -34,7 +34,7 @@
   * 
https://www.xilinx.com/support/documentation/architecture-manuals/am011-versal-acap-trm.pdf
   *
   * [2] Versal ACAP Register Reference,
- * 
https://www.xilinx.com/html_docs/registers/am012/am012-versal-register-reference.html#mod___ospi.html
+ * 
https://docs.xilinx.com/r/en-US/am012-versal-register-reference/OSPI-Module
   *
   *
   * QEMU interface:




Re: [PATCH v1 1/3] hw/ssi/xilinx_spips: fix an out of bound access

2023-11-24 Thread Francisco Iglesias




On 2023-11-24 15:35, Frederic Konrad wrote:

The spips, qspips, and zynqmp-qspips share the same realize function
(xilinx_spips_realize) and initialize their io memory region with different
mmio_ops passed through the class.  The size of the memory region is set to
the largest area (0x200 bytes for zynqmp-qspips) thus it is possible to write
out of s->regs[addr] in xilinx_spips_write for spips and qspips.

This fixes that wrong behavior.

Reviewed-by: Luc Michel 
Signed-off-by: Frederic Konrad 


Reviewed-by: Francisco Iglesias 



---
  hw/ssi/xilinx_spips.c | 7 ++-
  include/hw/ssi/xilinx_spips.h | 3 +++
  2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c
index a3955c6c50..0bdfad7e2e 100644
--- a/hw/ssi/xilinx_spips.c
+++ b/hw/ssi/xilinx_spips.c
@@ -973,6 +973,8 @@ static void xilinx_spips_write(void *opaque, hwaddr addr,
  
  DB_PRINT_L(0, "addr=" HWADDR_FMT_plx " = %x\n", addr, (unsigned)value);

  addr >>= 2;
+assert(addr < XLNX_SPIPS_R_MAX);
+
  switch (addr) {
  case R_CONFIG:
  mask = ~(R_CONFIG_RSVD | MAN_START_COM);
@@ -1299,7 +1301,7 @@ static void xilinx_spips_realize(DeviceState *dev, Error 
**errp)
  }
  
  memory_region_init_io(>iomem, OBJECT(s), xsc->reg_ops, s,

-  "spi", XLNX_ZYNQMP_SPIPS_R_MAX * 4);
+  "spi", xsc->reg_size);
  sysbus_init_mmio(sbd, >iomem);
  
  s->irqline = -1;

@@ -1435,6 +1437,7 @@ static void xilinx_qspips_class_init(ObjectClass *klass, 
void * data)
  
  dc->realize = xilinx_qspips_realize;

  xsc->reg_ops = _ops;
+xsc->reg_size = XLNX_SPIPS_R_MAX * 4;
  xsc->rx_fifo_size = RXFF_A_Q;
  xsc->tx_fifo_size = TXFF_A_Q;
  }
@@ -1450,6 +1453,7 @@ static void xilinx_spips_class_init(ObjectClass *klass, 
void *data)
  dc->vmsd = _xilinx_spips;
  
  xsc->reg_ops = _ops;

+xsc->reg_size = XLNX_SPIPS_R_MAX * 4;
  xsc->rx_fifo_size = RXFF_A;
  xsc->tx_fifo_size = TXFF_A;
  }
@@ -1464,6 +1468,7 @@ static void xlnx_zynqmp_qspips_class_init(ObjectClass 
*klass, void * data)
  dc->vmsd = _xlnx_zynqmp_qspips;
  device_class_set_props(dc, xilinx_zynqmp_qspips_properties);
  xsc->reg_ops = _zynqmp_qspips_ops;
+xsc->reg_size = XLNX_ZYNQMP_SPIPS_R_MAX * 4;
  xsc->rx_fifo_size = RXFF_A_Q;
  xsc->tx_fifo_size = TXFF_A_Q;
  }
diff --git a/include/hw/ssi/xilinx_spips.h b/include/hw/ssi/xilinx_spips.h
index 1386d5ac8f..7a754bf67a 100644
--- a/include/hw/ssi/xilinx_spips.h
+++ b/include/hw/ssi/xilinx_spips.h
@@ -33,7 +33,9 @@
  
  typedef struct XilinxSPIPS XilinxSPIPS;
  
+/* For SPIPS, QSPIPS.  */

  #define XLNX_SPIPS_R_MAX(0x100 / 4)
+/* For ZYNQMP_QSPIPS.  */
  #define XLNX_ZYNQMP_SPIPS_R_MAX (0x200 / 4)
  
  /* Bite off 4k chunks at a time */

@@ -125,6 +127,7 @@ struct XilinxSPIPSClass {
  SysBusDeviceClass parent_class;
  
  const MemoryRegionOps *reg_ops;

+uint64_t reg_size;
  
  uint32_t rx_fifo_size;

  uint32_t tx_fifo_size;




Re: [PATCH-for-8.2 v2 2/2] hw/net/can/xlnx-zynqmp: Avoid underflow while popping RX FIFO

2023-11-22 Thread Francisco Iglesias
On Sun, Nov 19, 2023 at 11:51:02PM +0100, Philippe Mathieu-Daudé wrote:
> Per https://docs.xilinx.com/r/en-US/ug1085-zynq-ultrascale-trm/Message-Format
> 
>   Message Format
> 
>   The same message format is used for RXFIFO, TXFIFO, and TXHPB.
>   Each message includes four words (16 bytes). Software must read
>   and write all four words regardless of the actual number of data
>   bytes and valid fields in the message.
> 
> There is no mention in this reference manual about what the
> hardware does when not all four words are read. To fix the
> reported underflow behavior, I choose to fill the 4 frame data
> registers when the first register (ID) is accessed, which is how
> I expect hardware would do.
> 
> Reported-by: Qiang Liu 
> Fixes: 98e5d7a2b7 ("hw/net/can: Introduce Xilinx ZynqMP CAN controller")
> Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1427
> Signed-off-by: Philippe Mathieu-Daudé 

Reviewed-by: Francisco Iglesias 


> ---
>  hw/net/can/xlnx-zynqmp-can.c | 17 +
>  1 file changed, 9 insertions(+), 8 deletions(-)
> 
> diff --git a/hw/net/can/xlnx-zynqmp-can.c b/hw/net/can/xlnx-zynqmp-can.c
> index 58938b574e..c63fb4a83c 100644
> --- a/hw/net/can/xlnx-zynqmp-can.c
> +++ b/hw/net/can/xlnx-zynqmp-can.c
> @@ -777,14 +777,18 @@ static void update_rx_fifo(XlnxZynqMPCANState *s, const 
> qemu_can_frame *frame)
>  }
>  }
>  
> -static uint64_t can_rxfifo_pre_read(RegisterInfo *reg, uint64_t val)
> +static uint64_t can_rxfifo_post_read_id(RegisterInfo *reg, uint64_t val)
>  {
>  XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
> +unsigned used = fifo32_num_used(>rx_fifo);
>  
> -if (!fifo32_is_empty(>rx_fifo)) {
> -val = fifo32_pop(>rx_fifo);
> -} else {
> +if (used < CAN_FRAME_SIZE) {
>  ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXUFLW, 1);
> +} else {
> +val = s->regs[R_RXFIFO_ID] = fifo32_pop(>rx_fifo);
> +s->regs[R_RXFIFO_DLC] = fifo32_pop(>rx_fifo);
> +s->regs[R_RXFIFO_DATA1] = fifo32_pop(>rx_fifo);
> +s->regs[R_RXFIFO_DATA2] = fifo32_pop(>rx_fifo);
>  }
>  
>  can_update_irq(s);
> @@ -945,14 +949,11 @@ static const RegisterAccessInfo can_regs_info[] = {
>  .post_write = can_tx_post_write,
>  },{ .name = "RXFIFO_ID",  .addr = A_RXFIFO_ID,
>  .ro = 0x,
> -.post_read = can_rxfifo_pre_read,
> +.post_read = can_rxfifo_post_read_id,
>  },{ .name = "RXFIFO_DLC",  .addr = A_RXFIFO_DLC,
>  .rsvd = 0xfff,
> -.post_read = can_rxfifo_pre_read,
>  },{ .name = "RXFIFO_DATA1",  .addr = A_RXFIFO_DATA1,
> -.post_read = can_rxfifo_pre_read,
>  },{ .name = "RXFIFO_DATA2",  .addr = A_RXFIFO_DATA2,
> -.post_read = can_rxfifo_pre_read,
>  },{ .name = "AFR",  .addr = A_AFR,
>  .rsvd = 0xfff0,
>  .post_write = can_filter_enable_post_write,
> -- 
> 2.41.0
> 



Re: [PATCH-for-8.2 v2 1/2] hw/net/can/xlnx-zynqmp: Avoid underflow while popping TX FIFOs

2023-11-22 Thread Francisco Iglesias
On Sun, Nov 19, 2023 at 11:51:01PM +0100, Philippe Mathieu-Daudé wrote:
> Per https://docs.xilinx.com/r/en-US/ug1085-zynq-ultrascale-trm/Message-Format
> 
>   Message Format
> 
>   The same message format is used for RXFIFO, TXFIFO, and TXHPB.
>   Each message includes four words (16 bytes). Software must read
>   and write all four words regardless of the actual number of data
>   bytes and valid fields in the message.
> 
> There is no mention in this reference manual about what the
> hardware does when not all four words are written. To fix the
> reported underflow behavior when DATA2 register is written,
> I choose to fill the data with the previous content of the
> ID / DLC / DATA1 registers, which is how I expect hardware
> would do.
> 
> Note there is no hardware flag raised under such condition.
> 
> Reported-by: Qiang Liu 
> Fixes: 98e5d7a2b7 ("hw/net/can: Introduce Xilinx ZynqMP CAN controller")
> Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1425
> Signed-off-by: Philippe Mathieu-Daudé 
> Francisco Iglesias 

-above line
+below line

Reviewed-by: Francisco Iglesias 


> ---
>  hw/net/can/xlnx-zynqmp-can.c | 49 +---
>  1 file changed, 46 insertions(+), 3 deletions(-)
> 
> diff --git a/hw/net/can/xlnx-zynqmp-can.c b/hw/net/can/xlnx-zynqmp-can.c
> index e93e6c5e19..58938b574e 100644
> --- a/hw/net/can/xlnx-zynqmp-can.c
> +++ b/hw/net/can/xlnx-zynqmp-can.c
> @@ -434,6 +434,51 @@ static bool tx_ready_check(XlnxZynqMPCANState *s)
>  return true;
>  }
>  
> +static void read_tx_frame(XlnxZynqMPCANState *s, Fifo32 *fifo, uint32_t 
> *data)
> +{
> +unsigned used = fifo32_num_used(fifo);
> +bool is_txhpb = fifo == >txhpb_fifo;
> +
> +assert(used > 0);
> +used %= CAN_FRAME_SIZE;
> +
> +/*
> + * Frame Message Format
> + *
> + * Each frame includes four words (16 bytes). Software must read and 
> write
> + * all four words regardless of the actual number of data bytes and valid
> + * fields in the message.
> + * If software misbehave (not writting all four words), we use the 
> previous
> + * registers content to initialize each missing word.
> + */
> +if (used > 0) {
> +/* ID, DLC, DATA1 missing */
> +data[0] = s->regs[is_txhpb ? R_TXHPB_ID : R_TXFIFO_ID];
> +} else {
> +data[0] = fifo32_pop(fifo);
> +}
> +if (used == 1 || used == 2) {
> +/* DLC, DATA1 missing */
> +data[1] = s->regs[is_txhpb ? R_TXHPB_DLC : R_TXFIFO_DLC];
> +} else {
> +data[1] = fifo32_pop(fifo);
> +}
> +if (used == 1) {
> +/* DATA1 missing */
> +data[2] = s->regs[is_txhpb ? R_TXHPB_DATA1 : R_TXFIFO_DATA1];
> +} else {
> +data[2] = fifo32_pop(fifo);
> +}
> +/* DATA2 triggered the transfer thus is always available */
> +data[3] = fifo32_pop(fifo);
> +
> +if (used) {
> +qemu_log_mask(LOG_GUEST_ERROR,
> +  "%s: Incomplete CAN frame (only %u/%u slots used)\n",
> +  TYPE_XLNX_ZYNQMP_CAN, used, CAN_FRAME_SIZE);
> +}
> +}
> +
>  static void transfer_fifo(XlnxZynqMPCANState *s, Fifo32 *fifo)
>  {
>  qemu_can_frame frame;
> @@ -451,9 +496,7 @@ static void transfer_fifo(XlnxZynqMPCANState *s, Fifo32 
> *fifo)
>  }
>  
>  while (!fifo32_is_empty(fifo)) {
> -for (i = 0; i < CAN_FRAME_SIZE; i++) {
> -data[i] = fifo32_pop(fifo);
> -}
> +read_tx_frame(s, fifo, data);
>  
>  if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, LBACK)) {
>  /*
> -- 
> 2.41.0
> 



Re: [PATCH-for-8.2] hw/net/can/xlnx-zynqmp: Avoid underflow while popping TX FIFO

2023-11-16 Thread Francisco Iglesias

Hi Philippe,

On 2023-11-16 16:44, Philippe Mathieu-Daudé wrote:

Hi Francisco,

On 16/11/23 15:17, Francisco Iglesias wrote:

Hi Philippe, good catch!


Well this was fuzzed by Qiang Liu.


On 2023-11-15 16:17, Philippe Mathieu-Daudé wrote:
Per 
https://docs.xilinx.com/r/en-US/ug1085-zynq-ultrascale-trm/Message-Format


   Message Format

   The same message format is used for RXFIFO, TXFIFO, and TXHPB.
   Each message includes four words (16 bytes). Software must read
   and write all four words regardless of the actual number of data
   bytes and valid fields in the message.

There is no mention in this reference manual about what the
hardware does when not all four words are written. To fix the
reported underflow behavior when DATA2 register is written,
I choose to fill the data with the previous content of the
ID / DLC / DATA1 registers, which is how I expect hardware
would do.

Note there is no hardware flag raised under such condition.

Reported-by: Qiang Liu 
Fixes: 98e5d7a2b7 ("hw/net/can: Introduce Xilinx ZynqMP CAN controller")
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1425
Signed-off-by: Philippe Mathieu-Daudé 
---
Tested with the CAN tests from 'make check-qtest-aarch64'
---
  hw/net/can/xlnx-zynqmp-can.c | 49 +---
  1 file changed, 46 insertions(+), 3 deletions(-)

diff --git a/hw/net/can/xlnx-zynqmp-can.c b/hw/net/can/xlnx-zynqmp-can.c
index e93e6c5e19..58938b574e 100644
--- a/hw/net/can/xlnx-zynqmp-can.c
+++ b/hw/net/can/xlnx-zynqmp-can.c
@@ -434,6 +434,51 @@ static bool tx_ready_check(XlnxZynqMPCANState *s)
  return true;
  }
+static void read_tx_frame(XlnxZynqMPCANState *s, Fifo32 *fifo, 
uint32_t *data)

+{
+    unsigned used = fifo32_num_used(fifo);


For the case when there are multiple frames in the fifo we need to 
swap above to:


unsigned used = fifo32_num_used(fifo) > CAN_FRAME_SIZE ? 0 : 
fifo32_num_used(fifo);


Isn't this ...


With above minor modification:

Reviewed-by: Francisco Iglesias 

Best regards,
Francisco


+    bool is_txhpb = fifo == >txhpb_fifo;
+
+    assert(used > 0);
+    used %= CAN_FRAME_SIZE;


... done here?


Ah yes, I was thinking that the first frame would be correct if for 
example used == 6, but yes that is not possible to know (can be the 
second frame that is ok). Feel free to add my reviewed-by to patch.


Thanks,
Best regards,
Francisco




+    /*
+ * Frame Message Format
+ *
+ * Each frame includes four words (16 bytes). Software must read 
and write
+ * all four words regardless of the actual number of data bytes 
and valid

+ * fields in the message.
+ * If software misbehave (not writting all four words), we use 
the previous

+ * registers content to initialize each missing word.
+ */
+    if (used > 0) {
+    /* ID, DLC, DATA1 missing */
+    data[0] = s->regs[is_txhpb ? R_TXHPB_ID : R_TXFIFO_ID];
+    } else {
+    data[0] = fifo32_pop(fifo);
+    }
+    if (used == 1 || used == 2) {
+    /* DLC, DATA1 missing */
+    data[1] = s->regs[is_txhpb ? R_TXHPB_DLC : R_TXFIFO_DLC];
+    } else {
+    data[1] = fifo32_pop(fifo);
+    }
+    if (used == 1) {
+    /* DATA1 missing */
+    data[2] = s->regs[is_txhpb ? R_TXHPB_DATA1 : R_TXFIFO_DATA1];
+    } else {
+    data[2] = fifo32_pop(fifo);
+    }
+    /* DATA2 triggered the transfer thus is always available */
+    data[3] = fifo32_pop(fifo);
+
+    if (used) {
+    qemu_log_mask(LOG_GUEST_ERROR,
+  "%s: Incomplete CAN frame (only %u/%u slots 
used)\n",

+  TYPE_XLNX_ZYNQMP_CAN, used, CAN_FRAME_SIZE);
+    }
+}






Re: [PATCH-for-8.2] hw/net/can/xlnx-zynqmp: Avoid underflow while popping TX FIFO

2023-11-16 Thread Francisco Iglesias

Hi Philippe, good catch!

On 2023-11-15 16:17, Philippe Mathieu-Daudé wrote:

Per https://docs.xilinx.com/r/en-US/ug1085-zynq-ultrascale-trm/Message-Format

   Message Format

   The same message format is used for RXFIFO, TXFIFO, and TXHPB.
   Each message includes four words (16 bytes). Software must read
   and write all four words regardless of the actual number of data
   bytes and valid fields in the message.

There is no mention in this reference manual about what the
hardware does when not all four words are written. To fix the
reported underflow behavior when DATA2 register is written,
I choose to fill the data with the previous content of the
ID / DLC / DATA1 registers, which is how I expect hardware
would do.

Note there is no hardware flag raised under such condition.

Reported-by: Qiang Liu 
Fixes: 98e5d7a2b7 ("hw/net/can: Introduce Xilinx ZynqMP CAN controller")
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1425
Signed-off-by: Philippe Mathieu-Daudé 
---
Tested with the CAN tests from 'make check-qtest-aarch64'
---
  hw/net/can/xlnx-zynqmp-can.c | 49 +---
  1 file changed, 46 insertions(+), 3 deletions(-)

diff --git a/hw/net/can/xlnx-zynqmp-can.c b/hw/net/can/xlnx-zynqmp-can.c
index e93e6c5e19..58938b574e 100644
--- a/hw/net/can/xlnx-zynqmp-can.c
+++ b/hw/net/can/xlnx-zynqmp-can.c
@@ -434,6 +434,51 @@ static bool tx_ready_check(XlnxZynqMPCANState *s)
  return true;
  }
  
+static void read_tx_frame(XlnxZynqMPCANState *s, Fifo32 *fifo, uint32_t *data)

+{
+unsigned used = fifo32_num_used(fifo);


For the case when there are multiple frames in the fifo we need to swap 
above to:


unsigned used = fifo32_num_used(fifo) > CAN_FRAME_SIZE ? 0 : 
fifo32_num_used(fifo);


With above minor modification:

Reviewed-by: Francisco Iglesias 

Best regards,
Francisco


+bool is_txhpb = fifo == >txhpb_fifo;
+
+assert(used > 0);
+used %= CAN_FRAME_SIZE;
+
+/*
+ * Frame Message Format
+ *
+ * Each frame includes four words (16 bytes). Software must read and write
+ * all four words regardless of the actual number of data bytes and valid
+ * fields in the message.
+ * If software misbehave (not writting all four words), we use the previous
+ * registers content to initialize each missing word.
+ */
+if (used > 0) {
+/* ID, DLC, DATA1 missing */
+data[0] = s->regs[is_txhpb ? R_TXHPB_ID : R_TXFIFO_ID];
+} else {
+data[0] = fifo32_pop(fifo);
+}
+if (used == 1 || used == 2) {
+/* DLC, DATA1 missing */
+data[1] = s->regs[is_txhpb ? R_TXHPB_DLC : R_TXFIFO_DLC];
+} else {
+data[1] = fifo32_pop(fifo);
+}
+if (used == 1) {
+/* DATA1 missing */
+data[2] = s->regs[is_txhpb ? R_TXHPB_DATA1 : R_TXFIFO_DATA1];
+} else {
+data[2] = fifo32_pop(fifo);
+}
+/* DATA2 triggered the transfer thus is always available */
+data[3] = fifo32_pop(fifo);
+
+if (used) {
+qemu_log_mask(LOG_GUEST_ERROR,
+  "%s: Incomplete CAN frame (only %u/%u slots used)\n",
+  TYPE_XLNX_ZYNQMP_CAN, used, CAN_FRAME_SIZE);
+}
+}
+
  static void transfer_fifo(XlnxZynqMPCANState *s, Fifo32 *fifo)
  {
  qemu_can_frame frame;
@@ -451,9 +496,7 @@ static void transfer_fifo(XlnxZynqMPCANState *s, Fifo32 
*fifo)
  }
  
  while (!fifo32_is_empty(fifo)) {

-for (i = 0; i < CAN_FRAME_SIZE; i++) {
-data[i] = fifo32_pop(fifo);
-}
+read_tx_frame(s, fifo, data);
  
  if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, LBACK)) {

  /*




Re: [PATCH 2/2] hw: Replace anti-social QOM type names (again)

2023-11-13 Thread Francisco Iglesias




On 2023-11-13 14:43, Markus Armbruster wrote:

QOM type names containing ',' result in awful UI.  We got rid of them
in v6.0.0 (commit e178113ff64 hw: Replace anti-social QOM type names).
A few have crept back since:

 xlnx,cframe-reg
 xlnx,efuse
 xlnx,pmc-efuse-cache
 xlnx,versal-cfu-apb
 xlnx,versal-cfu-fdro
 xlnx,versal-cfu-sfr
 xlnx,versal-crl
 xlnx,versal-efuse
 xlnx,zynqmp-efuse

These are all device types.  They can't be plugged with -device /
device_add, except for "xlnx,efuse" (I'm not sure that one is
intentional).

They *can* be used with -device / device_add to request help.
Usability is poor, though: you have to double the comma, like this:

 $ qemu-system-aarch64 -device xlnx,,pmc-efuse-cache,help

They can also be used with -global, where you must *not* double the
comma:

 $ qemu-system-aarch64 -global xlnx,efuse.drive-index=2

Trap for the unwary.

"xlnx,efuse", "xlnx,versal-efuse", "xlnx,pmc-efuse-cache",
"xlnx-zynqmp-efuse" are from v6.2.0, "xlnx,versal-crl" is from v7.1.0,
and the remainder are new.

Rename them all to "xlnx-FOO", like commit e178113ff64 did.

Reported-by: Thomas Huth 
Signed-off-by: Markus Armbruster 


Reviewed-by: Francisco Iglesias 


---
  docs/system/arm/xlnx-versal-virt.rst | 2 +-
  include/hw/misc/xlnx-versal-cframe-reg.h | 2 +-
  include/hw/misc/xlnx-versal-cfu.h| 6 +++---
  include/hw/misc/xlnx-versal-crl.h| 2 +-
  include/hw/nvram/xlnx-efuse.h| 2 +-
  include/hw/nvram/xlnx-versal-efuse.h | 4 ++--
  include/hw/nvram/xlnx-zynqmp-efuse.h | 2 +-
  7 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/docs/system/arm/xlnx-versal-virt.rst 
b/docs/system/arm/xlnx-versal-virt.rst
index a6a77b3799..edf2e48109 100644
--- a/docs/system/arm/xlnx-versal-virt.rst
+++ b/docs/system/arm/xlnx-versal-virt.rst
@@ -212,7 +212,7 @@ To use a different index value, N, from default of 1, add:
  
  .. code-block:: bash
  
-  -global xlnx,efuse.drive-index=N

+  -global xlnx-efuse.drive-index=N
  
  .. warning::

In actual physical Versal, BBRAM and eFUSE contain sensitive data.
diff --git a/include/hw/misc/xlnx-versal-cframe-reg.h 
b/include/hw/misc/xlnx-versal-cframe-reg.h
index a14fbd7fe4..f403b00e31 100644
--- a/include/hw/misc/xlnx-versal-cframe-reg.h
+++ b/include/hw/misc/xlnx-versal-cframe-reg.h
@@ -23,7 +23,7 @@
  #include "hw/misc/xlnx-versal-cfu.h"
  #include "qemu/fifo32.h"
  
-#define TYPE_XLNX_VERSAL_CFRAME_REG "xlnx,cframe-reg"

+#define TYPE_XLNX_VERSAL_CFRAME_REG "xlnx-cframe-reg"
  OBJECT_DECLARE_SIMPLE_TYPE(XlnxVersalCFrameReg, XLNX_VERSAL_CFRAME_REG)
  
  #define TYPE_XLNX_VERSAL_CFRAME_BCAST_REG "xlnx.cframe-bcast-reg"

diff --git a/include/hw/misc/xlnx-versal-cfu.h 
b/include/hw/misc/xlnx-versal-cfu.h
index 86fb841053..8c581c0797 100644
--- a/include/hw/misc/xlnx-versal-cfu.h
+++ b/include/hw/misc/xlnx-versal-cfu.h
@@ -22,13 +22,13 @@
  #include "hw/misc/xlnx-cfi-if.h"
  #include "qemu/fifo32.h"
  
-#define TYPE_XLNX_VERSAL_CFU_APB "xlnx,versal-cfu-apb"

+#define TYPE_XLNX_VERSAL_CFU_APB "xlnx-versal-cfu-apb"
  OBJECT_DECLARE_SIMPLE_TYPE(XlnxVersalCFUAPB, XLNX_VERSAL_CFU_APB)
  
-#define TYPE_XLNX_VERSAL_CFU_FDRO "xlnx,versal-cfu-fdro"

+#define TYPE_XLNX_VERSAL_CFU_FDRO "xlnx-versal-cfu-fdro"
  OBJECT_DECLARE_SIMPLE_TYPE(XlnxVersalCFUFDRO, XLNX_VERSAL_CFU_FDRO)
  
-#define TYPE_XLNX_VERSAL_CFU_SFR "xlnx,versal-cfu-sfr"

+#define TYPE_XLNX_VERSAL_CFU_SFR "xlnx-versal-cfu-sfr"
  OBJECT_DECLARE_SIMPLE_TYPE(XlnxVersalCFUSFR, XLNX_VERSAL_CFU_SFR)
  
  REG32(CFU_ISR, 0x0)

diff --git a/include/hw/misc/xlnx-versal-crl.h 
b/include/hw/misc/xlnx-versal-crl.h
index 2857f4169a..dfb8dff197 100644
--- a/include/hw/misc/xlnx-versal-crl.h
+++ b/include/hw/misc/xlnx-versal-crl.h
@@ -13,7 +13,7 @@
  #include "hw/register.h"
  #include "target/arm/cpu.h"
  
-#define TYPE_XLNX_VERSAL_CRL "xlnx,versal-crl"

+#define TYPE_XLNX_VERSAL_CRL "xlnx-versal-crl"
  OBJECT_DECLARE_SIMPLE_TYPE(XlnxVersalCRL, XLNX_VERSAL_CRL)
  
  REG32(ERR_CTRL, 0x0)

diff --git a/include/hw/nvram/xlnx-efuse.h b/include/hw/nvram/xlnx-efuse.h
index 58414e468b..cff7924106 100644
--- a/include/hw/nvram/xlnx-efuse.h
+++ b/include/hw/nvram/xlnx-efuse.h
@@ -30,7 +30,7 @@
  #include "sysemu/block-backend.h"
  #include "hw/qdev-core.h"
  
-#define TYPE_XLNX_EFUSE "xlnx,efuse"

+#define TYPE_XLNX_EFUSE "xlnx-efuse"
  OBJECT_DECLARE_SIMPLE_TYPE(XlnxEFuse, XLNX_EFUSE);
  
  struct XlnxEFuse {

diff --git a/include/hw/nvram/xlnx-versal-efuse.h 
b/include/hw/nvram/xlnx-versal-efuse.h
index a873dc5cb0..86e2261b9a 100644
--- a/include/hw/nvram/xlnx-versal-efuse.h
+++ b/include/hw/nvram/xlnx-versal-efuse.h
@@ -29,8 +29,8 @@
  
  #define XLNX_VE

Re: [PATCH 1/2] docs/system/arm: Fix for rename of type "xlnx.bbram-ctrl"

2023-11-13 Thread Francisco Iglesias




On 2023-11-13 14:43, Markus Armbruster wrote:

Fixes: b65b4b7ae3c8 (xlnx-bbram: hw/nvram: Use dot in device type name)
Signed-off-by: Markus Armbruster 


Reviewed-by: Francisco Iglesias 



---
  docs/system/arm/xlnx-versal-virt.rst | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/system/arm/xlnx-versal-virt.rst 
b/docs/system/arm/xlnx-versal-virt.rst
index d2d1b26692..a6a77b3799 100644
--- a/docs/system/arm/xlnx-versal-virt.rst
+++ b/docs/system/arm/xlnx-versal-virt.rst
@@ -194,7 +194,7 @@ To use a different index value, N, from default of 0, add:
  
  .. code-block:: bash
  
-  -global xlnx,bbram-ctrl.drive-index=N

+  -global xlnx.bbram-ctrl.drive-index=N
  
  eFUSE File Backend

  """"""""""""""""""




Re: [PATCH] xlnx-bbram: hw/nvram: Use dot in device type name

2023-10-04 Thread Francisco Iglesias
On [2023 Oct 02] Mon 22:21:39, Tong Ho wrote:
> This replaces the comma (,) to dot (.) in the device type name
> so the name can be used with the 'driver=' command line option.
> 
> Signed-off-by: Tong Ho 

Reviewed-by: Francisco Iglesias 

> ---
>  include/hw/nvram/xlnx-bbram.h | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/include/hw/nvram/xlnx-bbram.h b/include/hw/nvram/xlnx-bbram.h
> index 87d59ef3c0..6fc13f8cc1 100644
> --- a/include/hw/nvram/xlnx-bbram.h
> +++ b/include/hw/nvram/xlnx-bbram.h
> @@ -34,7 +34,7 @@
>  
>  #define RMAX_XLNX_BBRAM ((0x4c / 4) + 1)
>  
> -#define TYPE_XLNX_BBRAM "xlnx,bbram-ctrl"
> +#define TYPE_XLNX_BBRAM "xlnx.bbram-ctrl"
>  OBJECT_DECLARE_SIMPLE_TYPE(XlnxBBRam, XLNX_BBRAM);
>  
>  struct XlnxBBRam {
> -- 
> 2.25.1
> 
> 



Re: [PATCH] xlnx-zynqmp-efuse: hw/nvram: Remove deprecated device reset

2023-10-04 Thread Francisco Iglesias
On [2023 Oct 03] Tue 22:57:13, Tong Ho wrote:
> This change implements the ResettableClass interface for the device.
> 
> Signed-off-by: Tong Ho 

Reviewed-by: Francisco Iglesias 

> ---
>  hw/nvram/xlnx-zynqmp-efuse.c | 8 +---
>  1 file changed, 5 insertions(+), 3 deletions(-)
> 
> diff --git a/hw/nvram/xlnx-zynqmp-efuse.c b/hw/nvram/xlnx-zynqmp-efuse.c
> index 228ba0bbfa..3db5f98ec1 100644
> --- a/hw/nvram/xlnx-zynqmp-efuse.c
> +++ b/hw/nvram/xlnx-zynqmp-efuse.c
> @@ -2,6 +2,7 @@
>   * QEMU model of the ZynqMP eFuse
>   *
>   * Copyright (c) 2015 Xilinx Inc.
> + * Copyright (c) 2023 Advanced Micro Devices, Inc.
>   *
>   * Written by Edgar E. Iglesias 
>   *
> @@ -769,9 +770,9 @@ static void zynqmp_efuse_register_reset(RegisterInfo *reg)
>  register_reset(reg);
>  }
>  
> -static void zynqmp_efuse_reset(DeviceState *dev)
> +static void zynqmp_efuse_reset_hold(Object *obj)
>  {
> -XlnxZynqMPEFuse *s = XLNX_ZYNQMP_EFUSE(dev);
> +XlnxZynqMPEFuse *s = XLNX_ZYNQMP_EFUSE(obj);
>  unsigned int i;
>  
>  for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
> @@ -837,8 +838,9 @@ static Property zynqmp_efuse_props[] = {
>  static void zynqmp_efuse_class_init(ObjectClass *klass, void *data)
>  {
>  DeviceClass *dc = DEVICE_CLASS(klass);
> +ResettableClass *rc = RESETTABLE_CLASS(klass);
>  
> -dc->reset = zynqmp_efuse_reset;
> +rc->phases.hold = zynqmp_efuse_reset_hold;
>  dc->realize = zynqmp_efuse_realize;
>  dc->vmsd = _efuse;
>  device_class_set_props(dc, zynqmp_efuse_props);
> -- 
> 2.25.1
> 
> 



Re: [PATCH] xlnx-versal-efuse: hw/nvram: Remove deprecated device reset

2023-10-04 Thread Francisco Iglesias
On [2023 Oct 03] Tue 22:53:39, Tong Ho wrote:
> This change implements the ResettableClass interface for the device.
> 
> Signed-off-by: Tong Ho 

Reviewed-by: Francisco Iglesias 

> ---
>  hw/nvram/xlnx-versal-efuse-ctrl.c | 8 +---
>  1 file changed, 5 insertions(+), 3 deletions(-)
> 
> diff --git a/hw/nvram/xlnx-versal-efuse-ctrl.c 
> b/hw/nvram/xlnx-versal-efuse-ctrl.c
> index b35ba65ab5..beb5661c35 100644
> --- a/hw/nvram/xlnx-versal-efuse-ctrl.c
> +++ b/hw/nvram/xlnx-versal-efuse-ctrl.c
> @@ -2,6 +2,7 @@
>   * QEMU model of the Versal eFuse controller
>   *
>   * Copyright (c) 2020 Xilinx Inc.
> + * Copyright (c) 2023 Advanced Micro Devices, Inc.
>   *
>   * Permission is hereby granted, free of charge, to any person obtaining a 
> copy
>   * of this software and associated documentation files (the "Software"), to 
> deal
> @@ -657,9 +658,9 @@ static void efuse_ctrl_register_reset(RegisterInfo *reg)
>  register_reset(reg);
>  }
>  
> -static void efuse_ctrl_reset(DeviceState *dev)
> +static void efuse_ctrl_reset_hold(Object *obj)
>  {
> -XlnxVersalEFuseCtrl *s = XLNX_VERSAL_EFUSE_CTRL(dev);
> +XlnxVersalEFuseCtrl *s = XLNX_VERSAL_EFUSE_CTRL(obj);
>  unsigned int i;
>  
>  for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
> @@ -749,8 +750,9 @@ static Property efuse_ctrl_props[] = {
>  static void efuse_ctrl_class_init(ObjectClass *klass, void *data)
>  {
>  DeviceClass *dc = DEVICE_CLASS(klass);
> +ResettableClass *rc = RESETTABLE_CLASS(klass);
>  
> -dc->reset = efuse_ctrl_reset;
> +rc->phases.hold = efuse_ctrl_reset_hold;
>  dc->realize = efuse_ctrl_realize;
>  dc->vmsd = _efuse_ctrl;
>  device_class_set_props(dc, efuse_ctrl_props);
> -- 
> 2.25.1
> 
> 



Re: [PATCH v3 2/3] hw/arm: xlnx-versal-virt: Add AMD/Xilinx TRNG device

2023-10-04 Thread Francisco Iglesias
On [2023 Oct 04] Wed 07:27:45, Tong Ho wrote:
> Connect the support for Versal True Random Number Generator
> (TRNG) device.
> 
> Warning: unlike the TRNG component in a real device from the
> Versal device familiy, the connected TRNG model is not of
> cryptographic grade and is not intended for use cases when
> cryptograpically strong TRNG is needed.
> 
> Signed-off-by: Tong Ho 

Reviewed-by: Francisco Iglesias 

> ---
>  hw/arm/Kconfig   |  1 +
>  hw/arm/xlnx-versal.c | 16 
>  include/hw/arm/xlnx-versal.h |  5 +
>  3 files changed, 22 insertions(+)
> 
> diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
> index 7e68348440..0a3ff6748d 100644
> --- a/hw/arm/Kconfig
> +++ b/hw/arm/Kconfig
> @@ -482,6 +482,7 @@ config XLNX_VERSAL
>  select XLNX_BBRAM
>  select XLNX_EFUSE_VERSAL
>  select XLNX_USB_SUBSYS
> +select XLNX_VERSAL_TRNG
>  
>  config NPCM7XX
>  bool
> diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
> index fa556d8764..4f74a64a0d 100644
> --- a/hw/arm/xlnx-versal.c
> +++ b/hw/arm/xlnx-versal.c
> @@ -373,6 +373,21 @@ static void versal_create_rtc(Versal *s, qemu_irq *pic)
> qdev_get_gpio_in(DEVICE(>pmc.apb_irq_orgate), 0));
>  }
>  
> +static void versal_create_trng(Versal *s, qemu_irq *pic)
> +{
> +SysBusDevice *sbd;
> +MemoryRegion *mr;
> +
> +object_initialize_child(OBJECT(s), "trng", >pmc.trng,
> +TYPE_XLNX_VERSAL_TRNG);
> +sbd = SYS_BUS_DEVICE(>pmc.trng);
> +sysbus_realize(sbd, _fatal);
> +
> +mr = sysbus_mmio_get_region(sbd, 0);
> +memory_region_add_subregion(>mr_ps, MM_PMC_TRNG, mr);
> +sysbus_connect_irq(sbd, 0, pic[VERSAL_TRNG_IRQ]);
> +}
> +
>  static void versal_create_xrams(Versal *s, qemu_irq *pic)
>  {
>  int nr_xrams = ARRAY_SIZE(s->lpd.xram.ctrl);
> @@ -909,6 +924,7 @@ static void versal_realize(DeviceState *dev, Error **errp)
>  versal_create_sds(s, pic);
>  versal_create_pmc_apb_irq_orgate(s, pic);
>  versal_create_rtc(s, pic);
> +versal_create_trng(s, pic);
>  versal_create_xrams(s, pic);
>  versal_create_bbram(s, pic);
>  versal_create_efuse(s, pic);
> diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
> index 7b419f88c2..54f4b98d9d 100644
> --- a/include/hw/arm/xlnx-versal.h
> +++ b/include/hw/arm/xlnx-versal.h
> @@ -31,6 +31,7 @@
>  #include "hw/dma/xlnx_csu_dma.h"
>  #include "hw/misc/xlnx-versal-crl.h"
>  #include "hw/misc/xlnx-versal-pmc-iou-slcr.h"
> +#include "hw/misc/xlnx-versal-trng.h"
>  #include "hw/net/xlnx-versal-canfd.h"
>  #include "hw/misc/xlnx-versal-cfu.h"
>  #include "hw/misc/xlnx-versal-cframe-reg.h"
> @@ -116,6 +117,7 @@ struct Versal {
>  } iou;
>  
>  XlnxZynqMPRTC rtc;
> +XlnxVersalTRng trng;
>  XlnxBBRam bbram;
>  XlnxEFuse efuse;
>  XlnxVersalEFuseCtrl efuse_ctrl;
> @@ -160,6 +162,7 @@ struct Versal {
>  #define VERSAL_OSPI_IRQ124
>  #define VERSAL_SD0_IRQ_0   126
>  #define VERSAL_EFUSE_IRQ   139
> +#define VERSAL_TRNG_IRQ141
>  #define VERSAL_RTC_ALARM_IRQ   142
>  #define VERSAL_RTC_SECONDS_IRQ 143
>  
> @@ -329,4 +332,6 @@ struct Versal {
>  #define MM_PMC_CRP_SIZE 0x1
>  #define MM_PMC_RTC  0xf12a
>  #define MM_PMC_RTC_SIZE 0x1
> +#define MM_PMC_TRNG 0xf123
> +#define MM_PMC_TRNG_SIZE0x1
>  #endif
> -- 
> 2.25.1
> 



Re: [PATCH v3 3/3] tests/qtest: Introduce tests for AMD/Xilinx Versal TRNG device

2023-10-04 Thread Francisco Iglesias
On [2023 Oct 04] Wed 07:27:46, Tong Ho wrote:
> Signed-off-by: Tong Ho 

Reviewed-by: Francisco Iglesias 

> ---
>  tests/qtest/meson.build |   2 +-
>  tests/qtest/xlnx-versal-trng-test.c | 490 
>  2 files changed, 491 insertions(+), 1 deletion(-)
>  create mode 100644 tests/qtest/xlnx-versal-trng-test.c
> 
> diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
> index 1fba07f4ed..215d20e8cf 100644
> --- a/tests/qtest/meson.build
> +++ b/tests/qtest/meson.build
> @@ -216,7 +216,7 @@ qtests_aarch64 = \
>(config_all.has_key('CONFIG_TCG') and 
> config_all_devices.has_key('CONFIG_TPM_TIS_SYSBUS') ?\
>  ['tpm-tis-device-test', 'tpm-tis-device-swtpm-test'] : []) + 
> \
>(config_all_devices.has_key('CONFIG_XLNX_ZYNQMP_ARM') ? ['xlnx-can-test', 
> 'fuzz-xlnx-dp-test'] : []) + \
> -  (config_all_devices.has_key('CONFIG_XLNX_VERSAL') ? ['xlnx-canfd-test'] : 
> []) + \
> +  (config_all_devices.has_key('CONFIG_XLNX_VERSAL') ? ['xlnx-canfd-test', 
> 'xlnx-versal-trng-test'] : []) + \
>(config_all_devices.has_key('CONFIG_RASPI') ? ['bcm2835-dma-test'] : []) + 
>  \
>(config_all.has_key('CONFIG_TCG') and  
>   \
> config_all_devices.has_key('CONFIG_TPM_TIS_I2C') ? ['tpm-tis-i2c-test'] : 
> []) + \
> diff --git a/tests/qtest/xlnx-versal-trng-test.c 
> b/tests/qtest/xlnx-versal-trng-test.c
> new file mode 100644
> index 00..ddafaee72b
> --- /dev/null
> +++ b/tests/qtest/xlnx-versal-trng-test.c
> @@ -0,0 +1,490 @@
> +/*
> + * QTests for the Xilinx Versal True Random Number Generator device
> + *
> + * Copyright (c) 2023 Advanced Micro Devices, Inc.
> + *
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + */
> +
> +#include "qemu/osdep.h"
> +#include "libqtest-single.h"
> +
> +/* Base Address */
> +#define TRNG_BASEADDR  (0xf123)
> +
> +/* TRNG_INT_CTRL */
> +#define R_TRNG_INT_CTRL (0x)
> +#define   TRNG_INT_CTRL_CERTF_RST_MASK  (1 << 5)
> +#define   TRNG_INT_CTRL_DTF_RST_MASK(1 << 4)
> +#define   TRNG_INT_CTRL_DONE_RST_MASK   (1 << 3)
> +#define   TRNG_INT_CTRL_CERTF_EN_MASK   (1 << 2)
> +#define   TRNG_INT_CTRL_DTF_EN_MASK (1 << 1)
> +#define   TRNG_INT_CTRL_DONE_EN_MASK(1)
> +
> +/* TRNG_STATUS */
> +#define R_TRNG_STATUS  (0x0004)
> +#define   TRNG_STATUS_QCNT_SHIFT   (9)
> +#define   TRNG_STATUS_QCNT_MASK(7 << TRNG_STATUS_QCNT_SHIFT)
> +#define   TRNG_STATUS_CERTF_MASK   (1 << 3)
> +#define   TRNG_STATUS_DTF_MASK (1 << 1)
> +#define   TRNG_STATUS_DONE_MASK(1)
> +
> +/* TRNG_CTRL */
> +#define R_TRNG_CTRL(0x0008)
> +#define   TRNG_CTRL_PERSODISABLE_MASK   (1 << 10)
> +#define   TRNG_CTRL_SINGLEGENMODE_MASK  (1 << 9)
> +#define   TRNG_CTRL_PRNGMODE_MASK   (1 << 7)
> +#define   TRNG_CTRL_TSTMODE_MASK(1 << 6)
> +#define   TRNG_CTRL_PRNGSTART_MASK  (1 << 5)
> +#define   TRNG_CTRL_PRNGXS_MASK (1 << 3)
> +#define   TRNG_CTRL_TRSSEN_MASK (1 << 2)
> +#define   TRNG_CTRL_QERTUEN_MASK(1 << 1)
> +#define   TRNG_CTRL_PRNGSRST_MASK   (1)
> +
> +/* TRNG_EXT_SEED_0 ... _11 */
> +#define R_TRNG_EXT_SEED_0  (0x0040)
> +#define R_TRNG_EXT_SEED_11 (R_TRNG_EXT_SEED_0 + 4 * 11)
> +
> +/* TRNG_PER_STRNG_0 ... 11 */
> +#define R_TRNG_PER_STRNG_0 (0x0080)
> +#define R_TRNG_PER_STRNG_11(R_TRNG_PER_STRNG_0 + 4 * 11)
> +
> +/* TRNG_CORE_OUTPUT */
> +#define R_TRNG_CORE_OUTPUT (0x00c0)
> +
> +/* TRNG_RESET */
> +#define R_TRNG_RESET   (0x00d0)
> +#define   TRNG_RESET_VAL_MASK  (1)
> +
> +/* TRNG_OSC_EN */
> +#define R_TRNG_OSC_EN  (0x00d4)
> +#define   TRNG_OSC_EN_VAL_MASK (1)
> +
> +/* TRNG_TRNG_ISR, _IMR, _IER, _IDR */
> +#define R_TRNG_ISR (0x00e0)
> +#define R_TRNG_IMR (0x00e4)
> +#define R_TRNG_IER (0x00e8)
> +#define R_TRNG_IDR (0x00ec)
> +#define   TRNG_IRQ_SLVERR_MASK (1 << 1)
> +#define   TRNG_IRQ_CORE_INT_MASK   (1)
> +
> +#define FAILED(FMT, ...) g_error("%s(): " FMT, __func__, ## __VA_ARGS__)
> +
> +static const uint32_t prng_seed[12] = {
> +0x01234567, 0x12345678, 0x23456789, 0x3456789a, 0x456789ab, 0x56789abc,
> +0x76543210, 0x87654321, 0x98765432, 0xa9876543, 0xba987654, 0xfedcba98,
> +};
> +
> +static const uint32_t pers_str[12] = {
> +0x76543210, 0x87654321, 0x98765432, 0xa9876543, 0xba987654, 0x

Re: [PATCH v2 3/3] tests/qtest: Introduce tests for AMD/Xilinx Versal TRNG device

2023-09-26 Thread Francisco Iglesias
ctl &= ~TRNG_CTRL_PRNGXS_MASK;
> +}
> +
> +trng_ctrl_set(ctl);
> +trng_wait_done(act);
> +trng_ctrl_clr(TRNG_CTRL_PRNGSTART_MASK);
> +}
> +
> +static void trng_generate(bool auto_enb)
> +{
> +uint32_t ctl;
> +
> +ctl = TRNG_CTRL_PRNGSTART_MASK | TRNG_CTRL_SINGLEGENMODE_MASK;
> +trng_ctrl_clr(ctl);
> +
> +if (auto_enb) {
> +ctl &= ~TRNG_CTRL_SINGLEGENMODE_MASK;
> +}
> +
> +trng_ctrl_set(ctl | TRNG_CTRL_PRNGMODE_MASK);
> +
> +trng_wait_done("Generate");
> +g_assert(trng_qcnt() != 7);
> +}
> +
> +static size_t trng_collect(uint32_t *rnd, size_t cnt)
> +{
> +size_t i;
> +
> +for (i = 0; i < cnt; i++) {
> +if (trng_qcnt() == 0) {
> +return i;
> +}
> +
> +rnd[i] = trng_read(R_TRNG_CORE_OUTPUT);
> +}
> +
> +return i;
> +}
> +
> +static void trng_test_autogen(void)
> +{
> +const size_t cnt = 512 / 32;
> +uint32_t rng[cnt], prng[cnt];
> +size_t n;
> +
> +trng_reset();
> +
> +/* PRNG run #1 */
> +trng_reseed(prng_seed);
> +trng_generate(true);
> +
> +n = trng_collect(prng, cnt);
> +if (n != cnt) {
> +FAILED("PRNG_1 Auto-gen test failed: expected = %u, got = %u",
> +   (unsigned)cnt, (unsigned)n);
> +}
> +
> +/* TRNG, should not match PRNG */
> +trng_reseed(NULL);
> +trng_generate(true);
> +
> +n = trng_collect(rng, cnt);
> +if (n != cnt) {
> +FAILED("TRNG Auto-gen test failed: expected = %u, got = %u",
> +   (unsigned)cnt, (unsigned)n);
> +}
> +
> +if (!memcmp(rng, prng, sizeof(rng))) {
> +FAILED("TRNG test failed: matching PRNG");
> +}
> +
> +/* PRNG #2: should matches run #1 */
> +trng_reseed(prng_seed);
> +trng_generate(true);
> +
> +n = trng_collect(rng, cnt);
> +if (n != cnt) {
> +FAILED("PRNG_2 Auto-gen test failed: expected = %u, got = %u",
> +   (unsigned)cnt, (unsigned)n);
> +}
> +
> +if (memcmp(rng, prng, sizeof(rng))) {
> +FAILED("PRNG_2 Auto-gen test failed: does not match PRNG_1");
> +}
> +}
> +
> +static void trng_test_oneshot(void)
> +{
> +const size_t cnt = 512 / 32;
> +uint32_t rng[cnt];
> +size_t n;
> +
> +trng_reset();
> +
> +/* PRNG run #1 */
> +trng_reseed(prng_seed);
> +trng_generate(false);
> +
> +n = trng_collect(rng, cnt);
> +if (n == cnt) {
> +FAILED("PRNG_1 One-shot gen test failed");
> +}
> +
> +/* TRNG, should not match PRNG */
> +trng_reseed(NULL);
> +trng_generate(false);
> +
> +n = trng_collect(rng, cnt);
> +if (n == cnt) {
> +FAILED("TRNG One-shot test failed");
> +}
> +}
> +
> +static void trng_test_per_str(void)
> +{
> +const size_t cnt = 512 / 32;
> +uint32_t rng[cnt], prng[cnt];
> +size_t n;
> +
> +trng_reset();
> +
> +/* #1: disabled */
> +trng_ctrl_set(TRNG_CTRL_PERSODISABLE_MASK);
> +trng_reseed(prng_seed);
> +trng_ctrl_clr(TRNG_CTRL_PERSODISABLE_MASK);
> +
> +trng_generate(true);
> +n = trng_collect(prng, cnt);
> +g_assert_cmpuint(n, ==, cnt);
> +
> +/* #2: zero string should match personalization disabled */
> +trng_load(R_TRNG_PER_STRNG_0, NULL);
> +trng_reseed(prng_seed);
> +
> +trng_generate(true);
> +n = trng_collect(rng, cnt);
> +g_assert_cmpuint(n, ==, cnt);
> +
> +if (memcmp(rng, prng, sizeof(rng))) {
> +FAILED("Failed: PER_DISABLE != PER_STRNG_ALL_ZERO");
> +}
> +
> +/* #3: non-zero string should not match personalization disabled */
> +trng_load(R_TRNG_PER_STRNG_0, pers_str);
> +trng_reseed(prng_seed);
> +
> +trng_generate(true);
> +n = trng_collect(rng, cnt);
> +g_assert_cmpuint(n, ==, cnt);
> +
> +if (!memcmp(rng, prng, sizeof(rng))) {
> +FAILED("Failed: PER_DISABLE == PER_STRNG_NON_ZERO");
> +}
> +}
> +
> +static void trng_test_forced_prng(void)
> +{
> +const char *prop = "forced-prng";
> +const uint64_t seed = 0xdeadbeefbad1bad0ULL;
> +
> +trng_reset();

We need to move above line below the variable initialization below.

> +const size_t cnt = 512 / 32;
> +uint32_t rng[cnt], prng[cnt];
> +size_t n;

Looks good to me otherwise!

Best regards,
Francisco Iglesias

> +
> +trng_test_set_uint_prop(prop, seed);
> +
> +/* TRNG run #1 */
&g

Re: [PATCH] hw/intc/arm_gicv3: Simplify gicv3_class_name() logic

2023-09-06 Thread Francisco Iglesias
On [2023 Sep 05] Tue 16:56:51, Philippe Mathieu-Daudé wrote:
> Simplify gicv3_class_name() logic. No functional change intended.
> 
> Signed-off-by: Philippe Mathieu-Daudé 

Reviewed-by: Francisco Iglesias 

> ---
>  hw/intc/arm_gicv3_common.c | 9 -
>  1 file changed, 4 insertions(+), 5 deletions(-)
> 
> diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
> index 2ebf880ead..8863f06b67 100644
> --- a/hw/intc/arm_gicv3_common.c
> +++ b/hw/intc/arm_gicv3_common.c
> @@ -612,13 +612,12 @@ type_init(register_types)
>  
>  const char *gicv3_class_name(void)
>  {
> -if (kvm_irqchip_in_kernel()) {
> -return "kvm-arm-gicv3";
> -} else {
> -if (kvm_enabled()) {
> +if (kvm_enabled()) {
> +if (!kvm_irqchip_in_kernel()) {
>  error_report("Userspace GICv3 is not supported with KVM");
>  exit(1);
>  }
> -return "arm-gicv3";
> +return "kvm-arm-gicv3";
>  }
> +return "arm-gicv3";
>  }
> -- 
> 2.41.0
> 
> 



[PATCH v5 7/8] hw/arm/xlnx-versal: Connect the CFU_APB, CFU_FDRO and CFU_SFR

2023-08-31 Thread Francisco Iglesias
Connect the Configuration Frame Unit (CFU_APB, CFU_FDRO and CFU_SFR) to
the Versal machine.

Signed-off-by: Francisco Iglesias 
Acked-by: Edgar E. Iglesias 
Reviewed-by: Peter Maydell 
---
 hw/arm/xlnx-versal.c | 42 
 include/hw/arm/xlnx-versal.h | 16 ++
 2 files changed, 58 insertions(+)

diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
index 60bf5fe657..3f4b4b1560 100644
--- a/hw/arm/xlnx-versal.c
+++ b/hw/arm/xlnx-versal.c
@@ -570,6 +570,47 @@ static void versal_create_ospi(Versal *s, qemu_irq *pic)
 qdev_connect_gpio_out(orgate, 0, pic[VERSAL_OSPI_IRQ]);
 }
 
+static void versal_create_cfu(Versal *s, qemu_irq *pic)
+{
+SysBusDevice *sbd;
+
+/* CFU FDRO */
+object_initialize_child(OBJECT(s), "cfu-fdro", >pmc.cfu_fdro,
+TYPE_XLNX_VERSAL_CFU_FDRO);
+sbd = SYS_BUS_DEVICE(>pmc.cfu_fdro);
+
+sysbus_realize(sbd, _fatal);
+memory_region_add_subregion(>mr_ps, MM_PMC_CFU_FDRO,
+sysbus_mmio_get_region(sbd, 0));
+
+/* CFU APB */
+object_initialize_child(OBJECT(s), "cfu-apb", >pmc.cfu_apb,
+TYPE_XLNX_VERSAL_CFU_APB);
+sbd = SYS_BUS_DEVICE(>pmc.cfu_apb);
+
+sysbus_realize(sbd, _fatal);
+memory_region_add_subregion(>mr_ps, MM_PMC_CFU_APB,
+sysbus_mmio_get_region(sbd, 0));
+memory_region_add_subregion(>mr_ps, MM_PMC_CFU_STREAM,
+sysbus_mmio_get_region(sbd, 1));
+memory_region_add_subregion(>mr_ps, MM_PMC_CFU_STREAM_2,
+sysbus_mmio_get_region(sbd, 2));
+sysbus_connect_irq(sbd, 0, pic[VERSAL_CFU_IRQ_0]);
+
+/* CFU SFR */
+object_initialize_child(OBJECT(s), "cfu-sfr", >pmc.cfu_sfr,
+TYPE_XLNX_VERSAL_CFU_SFR);
+
+sbd = SYS_BUS_DEVICE(>pmc.cfu_sfr);
+
+object_property_set_link(OBJECT(>pmc.cfu_sfr),
+"cfu", OBJECT(>pmc.cfu_apb), _abort);
+
+sysbus_realize(sbd, _fatal);
+memory_region_add_subregion(>mr_ps, MM_PMC_CFU_SFR,
+sysbus_mmio_get_region(sbd, 0));
+}
+
 static void versal_create_crl(Versal *s, qemu_irq *pic)
 {
 SysBusDevice *sbd;
@@ -763,6 +804,7 @@ static void versal_realize(DeviceState *dev, Error **errp)
 versal_create_pmc_iou_slcr(s, pic);
 versal_create_ospi(s, pic);
 versal_create_crl(s, pic);
+versal_create_cfu(s, pic);
 versal_map_ddr(s);
 versal_unimp(s);
 
diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
index 39ee31185c..29b9c60301 100644
--- a/include/hw/arm/xlnx-versal.h
+++ b/include/hw/arm/xlnx-versal.h
@@ -32,6 +32,7 @@
 #include "hw/misc/xlnx-versal-crl.h"
 #include "hw/misc/xlnx-versal-pmc-iou-slcr.h"
 #include "hw/net/xlnx-versal-canfd.h"
+#include "hw/misc/xlnx-versal-cfu.h"
 
 #define TYPE_XLNX_VERSAL "xlnx-versal"
 OBJECT_DECLARE_SIMPLE_TYPE(Versal, XLNX_VERSAL)
@@ -117,6 +118,9 @@ struct Versal {
 XlnxEFuse efuse;
 XlnxVersalEFuseCtrl efuse_ctrl;
 XlnxVersalEFuseCache efuse_cache;
+XlnxVersalCFUAPB cfu_apb;
+XlnxVersalCFUFDRO cfu_fdro;
+XlnxVersalCFUSFR cfu_sfr;
 
 OrIRQState apb_irq_orgate;
 } pmc;
@@ -147,6 +151,7 @@ struct Versal {
 #define VERSAL_GEM1_WAKE_IRQ_0 59
 #define VERSAL_ADMA_IRQ_0  60
 #define VERSAL_XRAM_IRQ_0  79
+#define VERSAL_CFU_IRQ_0   120
 #define VERSAL_PMC_APB_IRQ 121
 #define VERSAL_OSPI_IRQ124
 #define VERSAL_SD0_IRQ_0   126
@@ -240,6 +245,17 @@ struct Versal {
 #define MM_PMC_EFUSE_CACHE  0xf125
 #define MM_PMC_EFUSE_CACHE_SIZE 0x00C00
 
+#define MM_PMC_CFU_APB  0xf12b
+#define MM_PMC_CFU_APB_SIZE 0x1
+#define MM_PMC_CFU_STREAM   0xf12c
+#define MM_PMC_CFU_STREAM_SIZE  0x1000
+#define MM_PMC_CFU_SFR  0xf12c1000
+#define MM_PMC_CFU_SFR_SIZE 0x1000
+#define MM_PMC_CFU_FDRO 0xf12c2000
+#define MM_PMC_CFU_FDRO_SIZE0x1000
+#define MM_PMC_CFU_STREAM_2 0xf1f8
+#define MM_PMC_CFU_STREAM_2_SIZE0x4
+
 #define MM_PMC_CRP  0xf126U
 #define MM_PMC_CRP_SIZE 0x1
 #define MM_PMC_RTC  0xf12a
-- 
2.34.1




[PATCH v5 4/8] hw/misc/xlnx-versal-cfu: Introduce a model of Xilinx Versal's CFU_SFR

2023-08-31 Thread Francisco Iglesias
Introduce a model of Xilinx Versal's Configuration Frame Unit's Single
Frame Read port (CFU_SFR).

Signed-off-by: Francisco Iglesias 
Reviewed-by: Peter Maydell 
---
 hw/misc/xlnx-versal-cfu.c | 87 +++
 include/hw/misc/xlnx-versal-cfu.h | 15 ++
 2 files changed, 102 insertions(+)

diff --git a/hw/misc/xlnx-versal-cfu.c b/hw/misc/xlnx-versal-cfu.c
index 255c1bf4b8..8e588ac1d8 100644
--- a/hw/misc/xlnx-versal-cfu.c
+++ b/hw/misc/xlnx-versal-cfu.c
@@ -264,6 +264,31 @@ static void cfu_stream_write(void *opaque, hwaddr addr, 
uint64_t value,
 }
 }
 
+static uint64_t cfu_sfr_read(void *opaque, hwaddr addr, unsigned size)
+{
+qemu_log_mask(LOG_GUEST_ERROR, "%s: Unsupported read from addr=%"
+  HWADDR_PRIx "\n", __func__, addr);
+return 0;
+}
+
+static void cfu_sfr_write(void *opaque, hwaddr addr, uint64_t value,
+  unsigned size)
+{
+XlnxVersalCFUSFR *s = XLNX_VERSAL_CFU_SFR(opaque);
+uint32_t wfifo[WFIFO_SZ];
+
+if (update_wfifo(addr, value, s->wfifo, wfifo)) {
+uint8_t row_addr = extract32(wfifo[0], 23, 5);
+uint32_t frame_addr = extract32(wfifo[0], 0, 23);
+XlnxCfiPacket pkt = { .reg_addr = CFRAME_SFR,
+  .data[0] = frame_addr };
+
+if (s->cfg.cfu) {
+cfu_transfer_cfi_packet(s->cfg.cfu, row_addr, );
+}
+}
+}
+
 static uint64_t cfu_fdro_read(void *opaque, hwaddr addr, unsigned size)
 {
 XlnxVersalCFUFDRO *s = XLNX_VERSAL_CFU_FDRO(opaque);
@@ -293,6 +318,16 @@ static const MemoryRegionOps cfu_stream_ops = {
 },
 };
 
+static const MemoryRegionOps cfu_sfr_ops = {
+.read = cfu_sfr_read,
+.write = cfu_sfr_write,
+.endianness = DEVICE_LITTLE_ENDIAN,
+.valid = {
+.min_access_size = 4,
+.max_access_size = 4,
+},
+};
+
 static const MemoryRegionOps cfu_fdro_ops = {
 .read = cfu_fdro_read,
 .write = cfu_fdro_write,
@@ -334,6 +369,23 @@ static void cfu_apb_init(Object *obj)
 sysbus_init_irq(sbd, >irq_cfu_imr);
 }
 
+static void cfu_sfr_init(Object *obj)
+{
+XlnxVersalCFUSFR *s = XLNX_VERSAL_CFU_SFR(obj);
+SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+
+memory_region_init_io(>iomem_sfr, obj, _sfr_ops, s,
+  TYPE_XLNX_VERSAL_CFU_SFR, KEYHOLE_STREAM_4K);
+sysbus_init_mmio(sbd, >iomem_sfr);
+}
+
+static void cfu_sfr_reset_enter(Object *obj, ResetType type)
+{
+XlnxVersalCFUSFR *s = XLNX_VERSAL_CFU_SFR(obj);
+
+memset(s->wfifo, 0, WFIFO_SZ * sizeof(uint32_t));
+}
+
 static void cfu_fdro_init(Object *obj)
 {
 XlnxVersalCFUFDRO *s = XLNX_VERSAL_CFU_FDRO(obj);
@@ -401,6 +453,12 @@ static Property cfu_props[] = {
 DEFINE_PROP_END_OF_LIST(),
 };
 
+static Property cfu_sfr_props[] = {
+DEFINE_PROP_LINK("cfu", XlnxVersalCFUSFR, cfg.cfu,
+ TYPE_XLNX_VERSAL_CFU_APB, XlnxVersalCFUAPB *),
+DEFINE_PROP_END_OF_LIST(),
+};
+
 static const VMStateDescription vmstate_cfu_apb = {
 .name = TYPE_XLNX_VERSAL_CFU_APB,
 .version_id = 1,
@@ -423,6 +481,16 @@ static const VMStateDescription vmstate_cfu_fdro = {
 }
 };
 
+static const VMStateDescription vmstate_cfu_sfr = {
+.name = TYPE_XLNX_VERSAL_CFU_SFR,
+.version_id = 1,
+.minimum_version_id = 1,
+.fields = (VMStateField[]) {
+VMSTATE_UINT32_ARRAY(wfifo, XlnxVersalCFUSFR, 4),
+VMSTATE_END_OF_LIST(),
+}
+};
+
 static void cfu_apb_class_init(ObjectClass *klass, void *data)
 {
 DeviceClass *dc = DEVICE_CLASS(klass);
@@ -443,6 +511,16 @@ static void cfu_fdro_class_init(ObjectClass *klass, void 
*data)
 rc->phases.enter = cfu_fdro_reset_enter;
 }
 
+static void cfu_sfr_class_init(ObjectClass *klass, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(klass);
+ResettableClass *rc = RESETTABLE_CLASS(klass);
+
+device_class_set_props(dc, cfu_sfr_props);
+dc->vmsd = _cfu_sfr;
+rc->phases.enter = cfu_sfr_reset_enter;
+}
+
 static const TypeInfo cfu_apb_info = {
 .name  = TYPE_XLNX_VERSAL_CFU_APB,
 .parent= TYPE_SYS_BUS_DEVICE,
@@ -467,10 +545,19 @@ static const TypeInfo cfu_fdro_info = {
 }
 };
 
+static const TypeInfo cfu_sfr_info = {
+.name  = TYPE_XLNX_VERSAL_CFU_SFR,
+.parent= TYPE_SYS_BUS_DEVICE,
+.instance_size = sizeof(XlnxVersalCFUSFR),
+.class_init= cfu_sfr_class_init,
+.instance_init = cfu_sfr_init,
+};
+
 static void cfu_apb_register_types(void)
 {
 type_register_static(_apb_info);
 type_register_static(_fdro_info);
+type_register_static(_sfr_info);
 }
 
 type_init(cfu_apb_register_types)
diff --git a/include/hw/misc/xlnx-versal-cfu.h 
b/include/hw/misc/xlnx-versal-cfu.h
index 73e9a21af4..86fb841053 100644
--- a/include/hw/misc/xlnx-versal-cfu.h
+++ b/include/hw/misc/xlnx-versal-cfu.h
@@ -28,6 +28,9 @@ OBJECT_DECLARE_SIMPLE_TYPE(XlnxVersalCFUAPB, 
XLNX_VER

[PATCH v5 2/8] hw/misc: Introduce a model of Xilinx Versal's CFU_APB

2023-08-31 Thread Francisco Iglesias
Introduce a model of the software programming interface (CFU_APB) of
Xilinx Versal's Configuration Frame Unit.

Signed-off-by: Francisco Iglesias 
Reviewed-by: Peter Maydell 
---
 MAINTAINERS   |   2 +
 hw/misc/meson.build   |   1 +
 hw/misc/xlnx-versal-cfu.c | 380 ++
 include/hw/misc/xlnx-versal-cfu.h | 231 ++
 4 files changed, 614 insertions(+)
 create mode 100644 hw/misc/xlnx-versal-cfu.c
 create mode 100644 include/hw/misc/xlnx-versal-cfu.h

diff --git a/MAINTAINERS b/MAINTAINERS
index e0cd365462..847b997d73 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1039,6 +1039,8 @@ M: Francisco Iglesias 
 S: Maintained
 F: hw/misc/xlnx-cfi-if.c
 F: include/hw/misc/xlnx-cfi-if.h
+F: hw/misc/xlnx-versal-cfu.c
+F: include/hw/misc/xlnx-versal-cfu.h
 
 STM32F100
 M: Alexandre Iooss 
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
index 0c562f5e3e..d95cc3fd87 100644
--- a/hw/misc/meson.build
+++ b/hw/misc/meson.build
@@ -97,6 +97,7 @@ specific_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: 
files('xlnx-versal-crl.c'))
 system_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files(
   'xlnx-versal-xramc.c',
   'xlnx-versal-pmc-iou-slcr.c',
+  'xlnx-versal-cfu.c',
   'xlnx-cfi-if.c',
 ))
 system_ss.add(when: 'CONFIG_STM32F2XX_SYSCFG', if_true: 
files('stm32f2xx_syscfg.c'))
diff --git a/hw/misc/xlnx-versal-cfu.c b/hw/misc/xlnx-versal-cfu.c
new file mode 100644
index 00..b2dc6ab211
--- /dev/null
+++ b/hw/misc/xlnx-versal-cfu.c
@@ -0,0 +1,380 @@
+/*
+ * QEMU model of the CFU Configuration Unit.
+ *
+ * Copyright (C) 2023, Advanced Micro Devices, Inc.
+ *
+ * Written by Edgar E. Iglesias ,
+ *Sai Pavan Boddu ,
+ *Francisco Iglesias 
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "hw/sysbus.h"
+#include "hw/register.h"
+#include "hw/irq.h"
+#include "qemu/bitops.h"
+#include "qemu/log.h"
+#include "qemu/units.h"
+#include "migration/vmstate.h"
+#include "hw/qdev-properties.h"
+#include "hw/qdev-properties-system.h"
+#include "hw/misc/xlnx-versal-cfu.h"
+
+#ifndef XLNX_VERSAL_CFU_APB_ERR_DEBUG
+#define XLNX_VERSAL_CFU_APB_ERR_DEBUG 0
+#endif
+
+#define KEYHOLE_STREAM_4K (4 * KiB)
+#define KEYHOLE_STREAM_256K (256 * KiB)
+#define CFRAME_BROADCAST_ROW 0x1F
+
+bool update_wfifo(hwaddr addr, uint64_t value,
+  uint32_t *wfifo, uint32_t *wfifo_ret)
+{
+unsigned int idx = extract32(addr, 2, 2);
+
+wfifo[idx] = value;
+
+if (idx == 3) {
+memcpy(wfifo_ret, wfifo, WFIFO_SZ * sizeof(uint32_t));
+memset(wfifo, 0, WFIFO_SZ * sizeof(uint32_t));
+return true;
+}
+
+return false;
+}
+
+static void cfu_imr_update_irq(XlnxVersalCFUAPB *s)
+{
+bool pending = s->regs[R_CFU_ISR] & ~s->regs[R_CFU_IMR];
+qemu_set_irq(s->irq_cfu_imr, pending);
+}
+
+static void cfu_isr_postw(RegisterInfo *reg, uint64_t val64)
+{
+XlnxVersalCFUAPB *s = XLNX_VERSAL_CFU_APB(reg->opaque);
+cfu_imr_update_irq(s);
+}
+
+static uint64_t cfu_ier_prew(RegisterInfo *reg, uint64_t val64)
+{
+XlnxVersalCFUAPB *s = XLNX_VERSAL_CFU_APB(reg->opaque);
+uint32_t val = val64;
+
+s->regs[R_CFU_IMR] &= ~val;
+cfu_imr_update_irq(s);
+return 0;
+}
+
+static uint64_t cfu_idr_prew(RegisterInfo *reg, uint64_t val64)
+{
+XlnxVersalCFUAPB *s = XLNX_VERSAL_CFU_APB(reg->opaque);
+uint32_t val = val64;
+
+s->regs[R_CFU_IMR] |= val;
+cfu_imr_update_irq(s);
+return 0;
+}
+
+static uint64_t cfu_itr_prew(RegisterInfo *reg, uint64_t val64)
+{
+XlnxVersalCFUAPB *s = XLNX_VERSAL_CFU_APB(reg->opaque);
+uint32_t val = val64;
+
+s->regs[R_CFU_ISR] |= val;
+cfu_imr_update_irq(s);
+return 0;
+}
+
+static void cfu_fgcr_postw(RegisterInfo *reg, uint64_t val64)
+{
+XlnxVersalCFUAPB *s = XLNX_VERSAL_CFU_APB(reg->opaque);
+uint32_t val = (uint32_t)val64;
+
+/* Do a scan. It always looks good. */
+if (FIELD_EX32(val, CFU_FGCR, SC_HBC_TRIGGER)) {
+ARRAY_FIELD_DP32(s->regs, CFU_STATUS, SCAN_CLEAR_PASS, 1);
+ARRAY_FIELD_DP32(s->regs, CFU_STATUS, SCAN_CLEAR_DONE, 1);
+}
+}
+
+static const RegisterAccessInfo cfu_apb_regs_info[] = {
+{   .name = "CFU_ISR",  .addr = A_CFU_ISR,
+.rsvd = 0xfc00,
+.w1c = 0x3ff,
+.post_write = cfu_isr_postw,
+},{ .name = "CFU_IMR",  .addr = A_CFU_IMR,
+.reset = 0x3ff,
+.rsvd = 0xfc00,
+.ro = 0x3ff,
+},{ .name = "CFU_IER",  .addr = A_CFU_IER,
+.rsvd = 0xfc00,
+.pre_write = cfu_ier_prew,
+},{ .name = "CFU_IDR",  .addr = A_CFU_IDR,
+.rsvd = 0xfc00,
+.pre_write = cfu_idr_prew,
+},{ .name = "CFU_ITR",  .addr = A_CFU_ITR,
+.rsvd

[PATCH v5 6/8] hw/misc: Introduce a model of Xilinx Versal's CFRAME_BCAST_REG

2023-08-31 Thread Francisco Iglesias
Introduce a model of Xilinx Versal's Configuration Frame broadcast
controller (CFRAME_BCAST_REG).

Signed-off-by: Francisco Iglesias 
Reviewed-by: Peter Maydell 
---
 hw/misc/xlnx-versal-cframe-reg.c | 161 +++
 include/hw/misc/xlnx-versal-cframe-reg.h |  17 +++
 2 files changed, 178 insertions(+)

diff --git a/hw/misc/xlnx-versal-cframe-reg.c b/hw/misc/xlnx-versal-cframe-reg.c
index 78db68f10c..8e8ec0715a 100644
--- a/hw/misc/xlnx-versal-cframe-reg.c
+++ b/hw/misc/xlnx-versal-cframe-reg.c
@@ -569,6 +569,83 @@ static const MemoryRegionOps cframe_reg_fdri_ops = {
 },
 };
 
+static uint64_t cframes_bcast_reg_read(void *opaque, hwaddr addr, unsigned 
size)
+{
+qemu_log_mask(LOG_GUEST_ERROR, "%s: Unsupported read from addr=%"
+  HWADDR_PRIx "\n", __func__, addr);
+return 0;
+}
+
+static void cframes_bcast_write(XlnxVersalCFrameBcastReg *s, uint8_t reg_addr,
+uint32_t *wfifo)
+{
+XlnxCfiPacket pkt = {
+.reg_addr = reg_addr,
+.data[0] = wfifo[0],
+.data[1] = wfifo[1],
+.data[2] = wfifo[2],
+.data[3] = wfifo[3]
+};
+
+for (int i = 0; i < ARRAY_SIZE(s->cfg.cframe); i++) {
+if (s->cfg.cframe[i]) {
+xlnx_cfi_transfer_packet(s->cfg.cframe[i], );
+}
+}
+}
+
+static void cframes_bcast_reg_write(void *opaque, hwaddr addr, uint64_t value,
+  unsigned size)
+{
+XlnxVersalCFrameBcastReg *s = XLNX_VERSAL_CFRAME_BCAST_REG(opaque);
+uint32_t wfifo[WFIFO_SZ];
+
+if (update_wfifo(addr, value, s->wfifo, wfifo)) {
+uint8_t reg_addr = extract32(addr, 4, 6);
+
+cframes_bcast_write(s, reg_addr, wfifo);
+}
+}
+
+static uint64_t cframes_bcast_fdri_read(void *opaque, hwaddr addr,
+unsigned size)
+{
+qemu_log_mask(LOG_GUEST_ERROR, "%s: Unsupported read from addr=%"
+  HWADDR_PRIx "\n", __func__, addr);
+return 0;
+}
+
+static void cframes_bcast_fdri_write(void *opaque, hwaddr addr, uint64_t value,
+  unsigned size)
+{
+XlnxVersalCFrameBcastReg *s = XLNX_VERSAL_CFRAME_BCAST_REG(opaque);
+uint32_t wfifo[WFIFO_SZ];
+
+if (update_wfifo(addr, value, s->wfifo, wfifo)) {
+cframes_bcast_write(s, CFRAME_FDRI, wfifo);
+}
+}
+
+static const MemoryRegionOps cframes_bcast_reg_reg_ops = {
+.read = cframes_bcast_reg_read,
+.write = cframes_bcast_reg_write,
+.endianness = DEVICE_LITTLE_ENDIAN,
+.valid = {
+.min_access_size = 4,
+.max_access_size = 4,
+},
+};
+
+static const MemoryRegionOps cframes_bcast_reg_fdri_ops = {
+.read = cframes_bcast_fdri_read,
+.write = cframes_bcast_fdri_write,
+.endianness = DEVICE_LITTLE_ENDIAN,
+.valid = {
+.min_access_size = 4,
+.max_access_size = 4,
+},
+};
+
 static void cframe_reg_realize(DeviceState *dev, Error **errp)
 {
 XlnxVersalCFrameReg *s = XLNX_VERSAL_CFRAME_REG(dev);
@@ -663,6 +740,71 @@ static Property cframe_regs_props[] = {
 DEFINE_PROP_END_OF_LIST(),
 };
 
+static void cframe_bcast_reg_init(Object *obj)
+{
+XlnxVersalCFrameBcastReg *s = XLNX_VERSAL_CFRAME_BCAST_REG(obj);
+SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+
+memory_region_init_io(>iomem_reg, obj, _bcast_reg_reg_ops, s,
+  TYPE_XLNX_VERSAL_CFRAME_BCAST_REG, 
KEYHOLE_STREAM_4K);
+memory_region_init_io(>iomem_fdri, obj, _bcast_reg_fdri_ops, s,
+  TYPE_XLNX_VERSAL_CFRAME_BCAST_REG "-fdri",
+  KEYHOLE_STREAM_4K);
+sysbus_init_mmio(sbd, >iomem_reg);
+sysbus_init_mmio(sbd, >iomem_fdri);
+}
+
+static void cframe_bcast_reg_reset_enter(Object *obj, ResetType type)
+{
+XlnxVersalCFrameBcastReg *s = XLNX_VERSAL_CFRAME_BCAST_REG(obj);
+
+memset(s->wfifo, 0, WFIFO_SZ * sizeof(uint32_t));
+}
+
+static const VMStateDescription vmstate_cframe_bcast_reg = {
+.name = TYPE_XLNX_VERSAL_CFRAME_BCAST_REG,
+.version_id = 1,
+.minimum_version_id = 1,
+.fields = (VMStateField[]) {
+VMSTATE_UINT32_ARRAY(wfifo, XlnxVersalCFrameBcastReg, 4),
+VMSTATE_END_OF_LIST(),
+}
+};
+
+static Property cframe_bcast_regs_props[] = {
+DEFINE_PROP_LINK("cframe0", XlnxVersalCFrameBcastReg, cfg.cframe[0],
+ TYPE_XLNX_CFI_IF, XlnxCfiIf *),
+DEFINE_PROP_LINK("cframe1", XlnxVersalCFrameBcastReg, cfg.cframe[1],
+ TYPE_XLNX_CFI_IF, XlnxCfiIf *),
+DEFINE_PROP_LINK("cframe2", XlnxVersalCFrameBcastReg, cfg.cframe[2],
+ TYPE_XLNX_CFI_IF, XlnxCfiIf *),
+DEFINE_PROP_LINK("cframe3", XlnxVersalCFrameBcastReg, cfg.cframe[3],
+ TYPE_XLNX_CFI_IF, XlnxCfiIf *),
+DEFINE_PROP_LINK("cframe4", XlnxVersalCFrameBcastReg, cfg.cfr

[PATCH v5 5/8] hw/misc: Introduce a model of Xilinx Versal's CFRAME_REG

2023-08-31 Thread Francisco Iglesias
Introduce a model of Xilinx Versal's Configuration Frame controller
(CFRAME_REG).

Signed-off-by: Francisco Iglesias 
---
 MAINTAINERS  |   2 +
 hw/misc/meson.build  |   1 +
 hw/misc/xlnx-versal-cframe-reg.c | 697 +++
 include/hw/misc/xlnx-versal-cframe-reg.h | 286 ++
 4 files changed, 986 insertions(+)
 create mode 100644 hw/misc/xlnx-versal-cframe-reg.c
 create mode 100644 include/hw/misc/xlnx-versal-cframe-reg.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 847b997d73..645374c1d9 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1041,6 +1041,8 @@ F: hw/misc/xlnx-cfi-if.c
 F: include/hw/misc/xlnx-cfi-if.h
 F: hw/misc/xlnx-versal-cfu.c
 F: include/hw/misc/xlnx-versal-cfu.h
+F: hw/misc/xlnx-versal-cframe-reg.c
+F: include/hw/misc/xlnx-versal-cframe-reg.h
 
 STM32F100
 M: Alexandre Iooss 
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
index d95cc3fd87..1b425b03bd 100644
--- a/hw/misc/meson.build
+++ b/hw/misc/meson.build
@@ -99,6 +99,7 @@ system_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files(
   'xlnx-versal-pmc-iou-slcr.c',
   'xlnx-versal-cfu.c',
   'xlnx-cfi-if.c',
+  'xlnx-versal-cframe-reg.c',
 ))
 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'))
diff --git a/hw/misc/xlnx-versal-cframe-reg.c b/hw/misc/xlnx-versal-cframe-reg.c
new file mode 100644
index 00..78db68f10c
--- /dev/null
+++ b/hw/misc/xlnx-versal-cframe-reg.c
@@ -0,0 +1,697 @@
+/*
+ * QEMU model of the Configuration Frame Control module
+ *
+ * Copyright (C) 2023, Advanced Micro Devices, Inc.
+ *
+ * Written by Francisco Iglesias 
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "hw/sysbus.h"
+#include "hw/register.h"
+#include "hw/registerfields.h"
+#include "qemu/bitops.h"
+#include "qemu/log.h"
+#include "qemu/units.h"
+#include "qapi/error.h"
+#include "hw/qdev-properties.h"
+#include "migration/vmstate.h"
+#include "hw/irq.h"
+#include "hw/misc/xlnx-versal-cframe-reg.h"
+
+#ifndef XLNX_VERSAL_CFRAME_REG_ERR_DEBUG
+#define XLNX_VERSAL_CFRAME_REG_ERR_DEBUG 0
+#endif
+
+#define KEYHOLE_STREAM_4K (4 * KiB)
+#define N_WORDS_128BIT 4
+
+#define MAX_BLOCKTYPE 6
+#define MAX_BLOCKTYPE_FRAMES 0xF
+
+enum {
+CFRAME_CMD_WCFG = 1,
+CFRAME_CMD_ROWON = 2,
+CFRAME_CMD_ROWOFF = 3,
+CFRAME_CMD_RCFG = 4,
+CFRAME_CMD_DLPARK = 5,
+};
+
+static gint int_cmp(gconstpointer a, gconstpointer b, gpointer user_data)
+{
+guint ua = GPOINTER_TO_UINT(a);
+guint ub = GPOINTER_TO_UINT(b);
+return (ua > ub) - (ua < ub);
+}
+
+static void cfrm_imr_update_irq(XlnxVersalCFrameReg *s)
+{
+bool pending = s->regs[R_CFRM_ISR0] & ~s->regs[R_CFRM_IMR0];
+qemu_set_irq(s->irq_cfrm_imr, pending);
+}
+
+static void cfrm_isr_postw(RegisterInfo *reg, uint64_t val64)
+{
+XlnxVersalCFrameReg *s = XLNX_VERSAL_CFRAME_REG(reg->opaque);
+cfrm_imr_update_irq(s);
+}
+
+static uint64_t cfrm_ier_prew(RegisterInfo *reg, uint64_t val64)
+{
+XlnxVersalCFrameReg *s = XLNX_VERSAL_CFRAME_REG(reg->opaque);
+
+s->regs[R_CFRM_IMR0] &= ~s->regs[R_CFRM_IER0];
+s->regs[R_CFRM_IER0] = 0;
+cfrm_imr_update_irq(s);
+return 0;
+}
+
+static uint64_t cfrm_idr_prew(RegisterInfo *reg, uint64_t val64)
+{
+XlnxVersalCFrameReg *s = XLNX_VERSAL_CFRAME_REG(reg->opaque);
+
+s->regs[R_CFRM_IMR0] |= s->regs[R_CFRM_IDR0];
+s->regs[R_CFRM_IDR0] = 0;
+cfrm_imr_update_irq(s);
+return 0;
+}
+
+static uint64_t cfrm_itr_prew(RegisterInfo *reg, uint64_t val64)
+{
+XlnxVersalCFrameReg *s = XLNX_VERSAL_CFRAME_REG(reg->opaque);
+
+s->regs[R_CFRM_ISR0] |= s->regs[R_CFRM_ITR0];
+s->regs[R_CFRM_ITR0] = 0;
+cfrm_imr_update_irq(s);
+return 0;
+}
+
+static void cframe_incr_far(XlnxVersalCFrameReg *s)
+{
+uint32_t faddr = ARRAY_FIELD_EX32(s->regs, FAR0, FRAME_ADDR);
+uint32_t blktype = ARRAY_FIELD_EX32(s->regs, FAR0, BLOCKTYPE);
+
+assert(blktype <= MAX_BLOCKTYPE);
+
+faddr++;
+if (faddr > s->cfg.blktype_num_frames[blktype]) {
+/* Restart from 0 and increment block type */
+faddr = 0;
+blktype++;
+
+assert(blktype <= MAX_BLOCKTYPE);
+
+ARRAY_FIELD_DP32(s->regs, FAR0, BLOCKTYPE, blktype);
+}
+
+ARRAY_FIELD_DP32(s->regs, FAR0, FRAME_ADDR, faddr);
+}
+
+static void cfrm_fdri_post_write(RegisterInfo *reg, uint64_t val)
+{
+XlnxVersalCFrameReg *s = XLNX_VERSAL_CFRAME_REG(reg->opaque);
+
+if (s->row_configured && s->rowon && s->wcfg) {
+
+if (fifo32_num_free(>new_f_data) >= N_WORDS_128BIT) {
+fifo32_push(>new_f_data,

[PATCH v5 8/8] hw/arm/versal: Connect the CFRAME_REG and CFRAME_BCAST_REG

2023-08-31 Thread Francisco Iglesias
Connect the Configuration Frame controller (CFRAME_REG) and the
Configuration Frame broadcast controller (CFRAME_BCAST_REG) to the
Versal machine.

Signed-off-by: Francisco Iglesias 
Reviewed-by: Peter Maydell 
---
 hw/arm/xlnx-versal.c | 113 ++-
 include/hw/arm/xlnx-versal.h |  69 +
 2 files changed, 181 insertions(+), 1 deletion(-)

diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
index 3f4b4b1560..fa556d8764 100644
--- a/hw/arm/xlnx-versal.c
+++ b/hw/arm/xlnx-versal.c
@@ -27,7 +27,7 @@
 #define XLNX_VERSAL_RCPU_TYPE ARM_CPU_TYPE_NAME("cortex-r5f")
 #define GEM_REVISION0x40070106
 
-#define VERSAL_NUM_PMC_APB_IRQS 3
+#define VERSAL_NUM_PMC_APB_IRQS 18
 #define NUM_OSPI_IRQ_LINES 3
 
 static void versal_create_apu_cpus(Versal *s)
@@ -341,6 +341,7 @@ static void versal_create_pmc_apb_irq_orgate(Versal *s, 
qemu_irq *pic)
  *  - RTC
  *  - BBRAM
  *  - PMC SLCR
+ *  - CFRAME regs (input 3 - 17 to the orgate)
  */
 object_initialize_child(OBJECT(s), "pmc-apb-irq-orgate",
 >pmc.apb_irq_orgate, TYPE_OR_IRQ);
@@ -573,6 +574,42 @@ static void versal_create_ospi(Versal *s, qemu_irq *pic)
 static void versal_create_cfu(Versal *s, qemu_irq *pic)
 {
 SysBusDevice *sbd;
+DeviceState *dev;
+int i;
+const struct {
+uint64_t reg_base;
+uint64_t fdri_base;
+} cframe_addr[] = {
+{ MM_PMC_CFRAME0_REG, MM_PMC_CFRAME0_FDRI },
+{ MM_PMC_CFRAME1_REG, MM_PMC_CFRAME1_FDRI },
+{ MM_PMC_CFRAME2_REG, MM_PMC_CFRAME2_FDRI },
+{ MM_PMC_CFRAME3_REG, MM_PMC_CFRAME3_FDRI },
+{ MM_PMC_CFRAME4_REG, MM_PMC_CFRAME4_FDRI },
+{ MM_PMC_CFRAME5_REG, MM_PMC_CFRAME5_FDRI },
+{ MM_PMC_CFRAME6_REG, MM_PMC_CFRAME6_FDRI },
+{ MM_PMC_CFRAME7_REG, MM_PMC_CFRAME7_FDRI },
+{ MM_PMC_CFRAME8_REG, MM_PMC_CFRAME8_FDRI },
+{ MM_PMC_CFRAME9_REG, MM_PMC_CFRAME9_FDRI },
+{ MM_PMC_CFRAME10_REG, MM_PMC_CFRAME10_FDRI },
+{ MM_PMC_CFRAME11_REG, MM_PMC_CFRAME11_FDRI },
+{ MM_PMC_CFRAME12_REG, MM_PMC_CFRAME12_FDRI },
+{ MM_PMC_CFRAME13_REG, MM_PMC_CFRAME13_FDRI },
+{ MM_PMC_CFRAME14_REG, MM_PMC_CFRAME14_FDRI },
+};
+const struct {
+uint32_t blktype0_frames;
+uint32_t blktype1_frames;
+uint32_t blktype2_frames;
+uint32_t blktype3_frames;
+uint32_t blktype4_frames;
+uint32_t blktype5_frames;
+uint32_t blktype6_frames;
+} cframe_cfg[] = {
+[0] = { 34111, 3528, 12800, 11, 5, 1, 1 },
+[1] = { 38498, 3841, 15361, 13, 7, 3, 1 },
+[2] = { 38498, 3841, 15361, 13, 7, 3, 1 },
+[3] = { 38498, 3841, 15361, 13, 7, 3, 1 },
+};
 
 /* CFU FDRO */
 object_initialize_child(OBJECT(s), "cfu-fdro", >pmc.cfu_fdro,
@@ -583,10 +620,84 @@ static void versal_create_cfu(Versal *s, qemu_irq *pic)
 memory_region_add_subregion(>mr_ps, MM_PMC_CFU_FDRO,
 sysbus_mmio_get_region(sbd, 0));
 
+/* CFRAME REG */
+for (i = 0; i < ARRAY_SIZE(s->pmc.cframe); i++) {
+g_autofree char *name = g_strdup_printf("cframe%d", i);
+
+object_initialize_child(OBJECT(s), name, >pmc.cframe[i],
+TYPE_XLNX_VERSAL_CFRAME_REG);
+
+sbd = SYS_BUS_DEVICE(>pmc.cframe[i]);
+dev = DEVICE(>pmc.cframe[i]);
+
+if (i < ARRAY_SIZE(cframe_cfg)) {
+object_property_set_int(OBJECT(dev), "blktype0-frames",
+cframe_cfg[i].blktype0_frames,
+_abort);
+object_property_set_int(OBJECT(dev), "blktype1-frames",
+cframe_cfg[i].blktype1_frames,
+_abort);
+object_property_set_int(OBJECT(dev), "blktype2-frames",
+cframe_cfg[i].blktype2_frames,
+_abort);
+object_property_set_int(OBJECT(dev), "blktype3-frames",
+cframe_cfg[i].blktype3_frames,
+_abort);
+object_property_set_int(OBJECT(dev), "blktype4-frames",
+cframe_cfg[i].blktype4_frames,
+_abort);
+object_property_set_int(OBJECT(dev), "blktype5-frames",
+cframe_cfg[i].blktype5_frames,
+_abort);
+object_property_set_int(OBJECT(dev), "blktype6-frames",
+cframe_cfg[i].blktype6_frames,
+_abort);
+}
+object_property_set_link(OBJECT(dev), "cfu-fdro",
+   

[PATCH v5 3/8] hw/misc/xlnx-versal-cfu: Introduce a model of Xilinx Versal CFU_FDRO

2023-08-31 Thread Francisco Iglesias
Introduce a model of Xilinx Versal's Configuration Frame Unit's data out
port (CFU_FDRO).

Signed-off-by: Francisco Iglesias 
Reviewed-by: Peter Maydell 
---
 hw/misc/xlnx-versal-cfu.c | 96 +++
 include/hw/misc/xlnx-versal-cfu.h | 12 
 2 files changed, 108 insertions(+)

diff --git a/hw/misc/xlnx-versal-cfu.c b/hw/misc/xlnx-versal-cfu.c
index b2dc6ab211..255c1bf4b8 100644
--- a/hw/misc/xlnx-versal-cfu.c
+++ b/hw/misc/xlnx-versal-cfu.c
@@ -264,6 +264,25 @@ static void cfu_stream_write(void *opaque, hwaddr addr, 
uint64_t value,
 }
 }
 
+static uint64_t cfu_fdro_read(void *opaque, hwaddr addr, unsigned size)
+{
+XlnxVersalCFUFDRO *s = XLNX_VERSAL_CFU_FDRO(opaque);
+uint64_t ret = 0;
+
+if (!fifo32_is_empty(>fdro_data)) {
+ret = fifo32_pop(>fdro_data);
+}
+
+return ret;
+}
+
+static void cfu_fdro_write(void *opaque, hwaddr addr, uint64_t value,
+   unsigned size)
+{
+qemu_log_mask(LOG_GUEST_ERROR, "%s: Unsupported write from addr=%"
+  HWADDR_PRIx "\n", __func__, addr);
+}
+
 static const MemoryRegionOps cfu_stream_ops = {
 .read = cfu_stream_read,
 .write = cfu_stream_write,
@@ -274,6 +293,16 @@ static const MemoryRegionOps cfu_stream_ops = {
 },
 };
 
+static const MemoryRegionOps cfu_fdro_ops = {
+.read = cfu_fdro_read,
+.write = cfu_fdro_write,
+.endianness = DEVICE_LITTLE_ENDIAN,
+.valid = {
+.min_access_size = 4,
+.max_access_size = 4,
+},
+};
+
 static void cfu_apb_init(Object *obj)
 {
 XlnxVersalCFUAPB *s = XLNX_VERSAL_CFU_APB(obj);
@@ -305,6 +334,39 @@ static void cfu_apb_init(Object *obj)
 sysbus_init_irq(sbd, >irq_cfu_imr);
 }
 
+static void cfu_fdro_init(Object *obj)
+{
+XlnxVersalCFUFDRO *s = XLNX_VERSAL_CFU_FDRO(obj);
+SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+
+memory_region_init_io(>iomem_fdro, obj, _fdro_ops, s,
+  TYPE_XLNX_VERSAL_CFU_FDRO, KEYHOLE_STREAM_4K);
+sysbus_init_mmio(sbd, >iomem_fdro);
+fifo32_create(>fdro_data, 8 * KiB / sizeof(uint32_t));
+}
+
+static void cfu_fdro_reset_enter(Object *obj, ResetType type)
+{
+XlnxVersalCFUFDRO *s = XLNX_VERSAL_CFU_FDRO(obj);
+
+fifo32_reset(>fdro_data);
+}
+
+static void cfu_fdro_cfi_transfer_packet(XlnxCfiIf *cfi_if, XlnxCfiPacket *pkt)
+{
+XlnxVersalCFUFDRO *s = XLNX_VERSAL_CFU_FDRO(cfi_if);
+
+if (fifo32_num_free(>fdro_data) >= ARRAY_SIZE(pkt->data)) {
+for (int i = 0; i < ARRAY_SIZE(pkt->data); i++) {
+fifo32_push(>fdro_data, pkt->data[i]);
+}
+} else {
+/* It is a programming error to fill the fifo. */
+qemu_log_mask(LOG_GUEST_ERROR,
+  "CFU_FDRO: CFI data dropped due to full read fifo\n");
+}
+}
+
 static Property cfu_props[] = {
 DEFINE_PROP_LINK("cframe0", XlnxVersalCFUAPB, cfg.cframe[0],
  TYPE_XLNX_CFI_IF, XlnxCfiIf *),
@@ -351,6 +413,16 @@ static const VMStateDescription vmstate_cfu_apb = {
 }
 };
 
+static const VMStateDescription vmstate_cfu_fdro = {
+.name = TYPE_XLNX_VERSAL_CFU_FDRO,
+.version_id = 1,
+.minimum_version_id = 1,
+.fields = (VMStateField[]) {
+VMSTATE_FIFO32(fdro_data, XlnxVersalCFUFDRO),
+VMSTATE_END_OF_LIST(),
+}
+};
+
 static void cfu_apb_class_init(ObjectClass *klass, void *data)
 {
 DeviceClass *dc = DEVICE_CLASS(klass);
@@ -360,6 +432,17 @@ static void cfu_apb_class_init(ObjectClass *klass, void 
*data)
 device_class_set_props(dc, cfu_props);
 }
 
+static void cfu_fdro_class_init(ObjectClass *klass, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(klass);
+ResettableClass *rc = RESETTABLE_CLASS(klass);
+XlnxCfiIfClass *xcic = XLNX_CFI_IF_CLASS(klass);
+
+dc->vmsd = _cfu_fdro;
+xcic->cfi_transfer_packet = cfu_fdro_cfi_transfer_packet;
+rc->phases.enter = cfu_fdro_reset_enter;
+}
+
 static const TypeInfo cfu_apb_info = {
 .name  = TYPE_XLNX_VERSAL_CFU_APB,
 .parent= TYPE_SYS_BUS_DEVICE,
@@ -372,9 +455,22 @@ static const TypeInfo cfu_apb_info = {
 }
 };
 
+static const TypeInfo cfu_fdro_info = {
+.name  = TYPE_XLNX_VERSAL_CFU_FDRO,
+.parent= TYPE_SYS_BUS_DEVICE,
+.instance_size = sizeof(XlnxVersalCFUFDRO),
+.class_init= cfu_fdro_class_init,
+.instance_init = cfu_fdro_init,
+.interfaces = (InterfaceInfo[]) {
+{ TYPE_XLNX_CFI_IF },
+{ }
+}
+};
+
 static void cfu_apb_register_types(void)
 {
 type_register_static(_apb_info);
+type_register_static(_fdro_info);
 }
 
 type_init(cfu_apb_register_types)
diff --git a/include/hw/misc/xlnx-versal-cfu.h 
b/include/hw/misc/xlnx-versal-cfu.h
index 62d10caf27..73e9a21af4 100644
--- a/include/hw/misc/xlnx-versal-cfu.h
+++ b/include/hw/misc/xlnx-versal-cfu.h
@@ -20,10 +20,14 @@
 #include "h

[PATCH v5 1/8] hw/misc: Introduce the Xilinx CFI interface

2023-08-31 Thread Francisco Iglesias
Introduce the Xilinx Configuration Frame Interface (CFI) for transmitting
CFI data packets between the Xilinx Configuration Frame Unit models
(CFU_APB, CFU_FDRO and CFU_SFR), the Xilinx CFRAME controller (CFRAME_REG)
and the Xilinx CFRAME broadcast controller (CFRAME_BCAST_REG) models (when
emulating bitstream programming and readback).

Signed-off-by: Francisco Iglesias 
Reviewed-by: Sai Pavan Boddu 
Acked-by: Edgar E. Iglesias 
---
 MAINTAINERS   |  6 
 hw/misc/meson.build   |  1 +
 hw/misc/xlnx-cfi-if.c | 34 
 include/hw/misc/xlnx-cfi-if.h | 59 +++
 4 files changed, 100 insertions(+)
 create mode 100644 hw/misc/xlnx-cfi-if.c
 create mode 100644 include/hw/misc/xlnx-cfi-if.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 6111b6b4d9..e0cd365462 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1034,6 +1034,12 @@ S: Maintained
 F: hw/ssi/xlnx-versal-ospi.c
 F: include/hw/ssi/xlnx-versal-ospi.h
 
+Xilinx Versal CFI
+M: Francisco Iglesias 
+S: Maintained
+F: hw/misc/xlnx-cfi-if.c
+F: include/hw/misc/xlnx-cfi-if.h
+
 STM32F100
 M: Alexandre Iooss 
 L: qemu-...@nongnu.org
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
index 892f8b91c5..0c562f5e3e 100644
--- a/hw/misc/meson.build
+++ b/hw/misc/meson.build
@@ -97,6 +97,7 @@ specific_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: 
files('xlnx-versal-crl.c'))
 system_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files(
   'xlnx-versal-xramc.c',
   'xlnx-versal-pmc-iou-slcr.c',
+  'xlnx-cfi-if.c',
 ))
 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'))
diff --git a/hw/misc/xlnx-cfi-if.c b/hw/misc/xlnx-cfi-if.c
new file mode 100644
index 00..c45f05c4aa
--- /dev/null
+++ b/hw/misc/xlnx-cfi-if.c
@@ -0,0 +1,34 @@
+/*
+ * Xilinx CFI interface
+ *
+ * Copyright (C) 2023, Advanced Micro Devices, Inc.
+ *
+ * Written by Francisco Iglesias 
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#include "qemu/osdep.h"
+#include "hw/misc/xlnx-cfi-if.h"
+
+void xlnx_cfi_transfer_packet(XlnxCfiIf *cfi_if, XlnxCfiPacket *pkt)
+{
+XlnxCfiIfClass *xcic = XLNX_CFI_IF_GET_CLASS(cfi_if);
+
+if (xcic->cfi_transfer_packet) {
+xcic->cfi_transfer_packet(cfi_if, pkt);
+}
+}
+
+static const TypeInfo xlnx_cfi_if_info = {
+.name  = TYPE_XLNX_CFI_IF,
+.parent= TYPE_INTERFACE,
+.class_size = sizeof(XlnxCfiIfClass),
+};
+
+static void xlnx_cfi_if_register_types(void)
+{
+type_register_static(_cfi_if_info);
+}
+
+type_init(xlnx_cfi_if_register_types)
+
diff --git a/include/hw/misc/xlnx-cfi-if.h b/include/hw/misc/xlnx-cfi-if.h
new file mode 100644
index 00..f9bd12292d
--- /dev/null
+++ b/include/hw/misc/xlnx-cfi-if.h
@@ -0,0 +1,59 @@
+/*
+ * Xilinx CFI interface
+ *
+ * Copyright (C) 2023, Advanced Micro Devices, Inc.
+ *
+ * Written by Francisco Iglesias 
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#ifndef XLNX_CFI_IF_H
+#define XLNX_CFI_IF_H 1
+
+#include "qemu/help-texts.h"
+#include "hw/hw.h"
+#include "qom/object.h"
+
+#define TYPE_XLNX_CFI_IF "xlnx-cfi-if"
+typedef struct XlnxCfiIfClass XlnxCfiIfClass;
+DECLARE_CLASS_CHECKERS(XlnxCfiIfClass, XLNX_CFI_IF, TYPE_XLNX_CFI_IF)
+
+#define XLNX_CFI_IF(obj) \
+ INTERFACE_CHECK(XlnxCfiIf, (obj), TYPE_XLNX_CFI_IF)
+
+typedef enum {
+PACKET_TYPE_CFU = 0x52,
+PACKET_TYPE_CFRAME = 0xA1,
+} xlnx_cfi_packet_type;
+
+typedef enum {
+CFRAME_FAR = 1,
+CFRAME_SFR = 2,
+CFRAME_FDRI = 4,
+CFRAME_CMD = 6,
+} xlnx_cfi_reg_addr;
+
+typedef struct XlnxCfiPacket {
+uint8_t reg_addr;
+uint32_t data[4];
+} XlnxCfiPacket;
+
+typedef struct XlnxCfiIf {
+Object Parent;
+} XlnxCfiIf;
+
+typedef struct XlnxCfiIfClass {
+InterfaceClass parent;
+
+void (*cfi_transfer_packet)(XlnxCfiIf *cfi_if, XlnxCfiPacket *pkt);
+} XlnxCfiIfClass;
+
+/**
+ * Transfer a XlnxCfiPacket.
+ *
+ * @cfi_if: the object implementing this interface
+ * @XlnxCfiPacket: a pointer to the XlnxCfiPacket to transfer
+ */
+void xlnx_cfi_transfer_packet(XlnxCfiIf *cfi_if, XlnxCfiPacket *pkt);
+
+#endif /* XLNX_CFI_IF_H */
-- 
2.34.1




[PATCH v5 0/8] Xilinx Versal CFI support

2023-08-31 Thread Francisco Iglesias
Hi,

This series adds support for the Configuration Frame Unit (CFU) and the
Configuration Frame controllers (CFRAME) to the Xilinx Versal machine
([1], chapter 21) for emulaing bitstream loading and readback.

The series starts by introducing the Xilinx CFI interface that is
thereafter used by the Xilinx CFU components, the Xilinx CFRAME and Xilinx
CFRAME broadcast models for transfering CFI packets between each other.
Thereafter a model of the CFU_APB, CFU_FDRO and CFU_SFR are introduced and
also models of the CFRAME controller and CFRAME broadcast controller.

The series thereafter ends with connecting the models to Xilinx Versal
machine.

Best regards,
Francisco Iglesias

References:
[1] https://docs.xilinx.com/r/en-US/am011-versal-acap-trm/PSM-Local-Registers


Changelog:
v4->v5:
   * Identical to v4 (resend of v4 due to an smtp problem)
v3->v4:
 [PATCH 5]
   * Swap to pop out the fifo32 data instead of using memcpy
   * Use g_tree_nnodes instead of g_tree_height
   * Take reference before g_tree_destroy (for keeping the GTree around)
   * Remove stray whitespace (in cframe_reg_init before g_free)

v2->v3:
 [PATCH 5]
   * Swap to store the CFrames in a GTree instead of GArray
   * Rename new_f to new_f_data and also add it to the vmstate 
   * Removed unnecessary 'switch' braces in cframe_reg_cfi_transfer_packet
   * Correct the reset of new_f_data and the cframes GTree


v1->v2:
 [PATCH 2]
   * Use KiB when defining KEYHOLE_STREAM_4K/KEYHOLE_STREAM_256K
   * Updated to be able to share wfifo code 
 [PATCH 3]
   * Swap to use Fifo32 instead of GArray in the CFU_FDRO model
   * Add device reset to the CFU_FDRO model
 [PATCH 4]
   * Add device reset to the CFU_SFR model
 [PATCH 5]
   * Use KiB when defining KEYHOLE_STREAM_4K
   * Add comma after CFRAME_CMD_DLPARK
   * Remove backwards compatibility comment (and the 'cfu' alias propname for
 cfg.cfu_fdro)
   * Use Fifo32 inside the XlnxCFrame structure
   * Reworked cframes_reg_pre_save / cframes_reg_post_load
 [PATCH 6]
   * Add device reset to the CFrame broadcast reg model
 [PATCH 8]
   * Switch to use g_autofree instead of explicit g_free

Francisco Iglesias (8):
  hw/misc: Introduce the Xilinx CFI interface
  hw/misc: Introduce a model of Xilinx Versal's CFU_APB
  hw/misc/xlnx-versal-cfu: Introduce a model of Xilinx Versal CFU_FDRO
  hw/misc/xlnx-versal-cfu: Introduce a model of Xilinx Versal's CFU_SFR
  hw/misc: Introduce a model of Xilinx Versal's CFRAME_REG
  hw/misc: Introduce a model of Xilinx Versal's CFRAME_BCAST_REG
  hw/arm/xlnx-versal: Connect the CFU_APB, CFU_FDRO and CFU_SFR
  hw/arm/versal: Connect the CFRAME_REG and CFRAME_BCAST_REG

 MAINTAINERS  |  10 +
 hw/arm/xlnx-versal.c | 155 +++-
 hw/misc/meson.build  |   3 +
 hw/misc/xlnx-cfi-if.c|  34 +
 hw/misc/xlnx-versal-cframe-reg.c | 858 +++
 hw/misc/xlnx-versal-cfu.c| 563 +++
 include/hw/arm/xlnx-versal.h |  85 +++
 include/hw/misc/xlnx-cfi-if.h|  59 ++
 include/hw/misc/xlnx-versal-cframe-reg.h | 303 
 include/hw/misc/xlnx-versal-cfu.h| 258 +++
 10 files changed, 2327 insertions(+), 1 deletion(-)
 create mode 100644 hw/misc/xlnx-cfi-if.c
 create mode 100644 hw/misc/xlnx-versal-cframe-reg.c
 create mode 100644 hw/misc/xlnx-versal-cfu.c
 create mode 100644 include/hw/misc/xlnx-cfi-if.h
 create mode 100644 include/hw/misc/xlnx-versal-cframe-reg.h
 create mode 100644 include/hw/misc/xlnx-versal-cfu.h

-- 
2.34.1




[PATCH v4 6/8] hw/misc: Introduce a model of Xilinx Versal's CFRAME_BCAST_REG

2023-08-31 Thread Francisco Iglesias
Introduce a model of Xilinx Versal's Configuration Frame broadcast
controller (CFRAME_BCAST_REG).

Signed-off-by: Francisco Iglesias 
Reviewed-by: Peter Maydell 
---
 hw/misc/xlnx-versal-cframe-reg.c | 161 +++
 include/hw/misc/xlnx-versal-cframe-reg.h |  17 +++
 2 files changed, 178 insertions(+)

diff --git a/hw/misc/xlnx-versal-cframe-reg.c b/hw/misc/xlnx-versal-cframe-reg.c
index 78db68f10c..8e8ec0715a 100644
--- a/hw/misc/xlnx-versal-cframe-reg.c
+++ b/hw/misc/xlnx-versal-cframe-reg.c
@@ -569,6 +569,83 @@ static const MemoryRegionOps cframe_reg_fdri_ops = {
 },
 };
 
+static uint64_t cframes_bcast_reg_read(void *opaque, hwaddr addr, unsigned 
size)
+{
+qemu_log_mask(LOG_GUEST_ERROR, "%s: Unsupported read from addr=%"
+  HWADDR_PRIx "\n", __func__, addr);
+return 0;
+}
+
+static void cframes_bcast_write(XlnxVersalCFrameBcastReg *s, uint8_t reg_addr,
+uint32_t *wfifo)
+{
+XlnxCfiPacket pkt = {
+.reg_addr = reg_addr,
+.data[0] = wfifo[0],
+.data[1] = wfifo[1],
+.data[2] = wfifo[2],
+.data[3] = wfifo[3]
+};
+
+for (int i = 0; i < ARRAY_SIZE(s->cfg.cframe); i++) {
+if (s->cfg.cframe[i]) {
+xlnx_cfi_transfer_packet(s->cfg.cframe[i], );
+}
+}
+}
+
+static void cframes_bcast_reg_write(void *opaque, hwaddr addr, uint64_t value,
+  unsigned size)
+{
+XlnxVersalCFrameBcastReg *s = XLNX_VERSAL_CFRAME_BCAST_REG(opaque);
+uint32_t wfifo[WFIFO_SZ];
+
+if (update_wfifo(addr, value, s->wfifo, wfifo)) {
+uint8_t reg_addr = extract32(addr, 4, 6);
+
+cframes_bcast_write(s, reg_addr, wfifo);
+}
+}
+
+static uint64_t cframes_bcast_fdri_read(void *opaque, hwaddr addr,
+unsigned size)
+{
+qemu_log_mask(LOG_GUEST_ERROR, "%s: Unsupported read from addr=%"
+  HWADDR_PRIx "\n", __func__, addr);
+return 0;
+}
+
+static void cframes_bcast_fdri_write(void *opaque, hwaddr addr, uint64_t value,
+  unsigned size)
+{
+XlnxVersalCFrameBcastReg *s = XLNX_VERSAL_CFRAME_BCAST_REG(opaque);
+uint32_t wfifo[WFIFO_SZ];
+
+if (update_wfifo(addr, value, s->wfifo, wfifo)) {
+cframes_bcast_write(s, CFRAME_FDRI, wfifo);
+}
+}
+
+static const MemoryRegionOps cframes_bcast_reg_reg_ops = {
+.read = cframes_bcast_reg_read,
+.write = cframes_bcast_reg_write,
+.endianness = DEVICE_LITTLE_ENDIAN,
+.valid = {
+.min_access_size = 4,
+.max_access_size = 4,
+},
+};
+
+static const MemoryRegionOps cframes_bcast_reg_fdri_ops = {
+.read = cframes_bcast_fdri_read,
+.write = cframes_bcast_fdri_write,
+.endianness = DEVICE_LITTLE_ENDIAN,
+.valid = {
+.min_access_size = 4,
+.max_access_size = 4,
+},
+};
+
 static void cframe_reg_realize(DeviceState *dev, Error **errp)
 {
 XlnxVersalCFrameReg *s = XLNX_VERSAL_CFRAME_REG(dev);
@@ -663,6 +740,71 @@ static Property cframe_regs_props[] = {
 DEFINE_PROP_END_OF_LIST(),
 };
 
+static void cframe_bcast_reg_init(Object *obj)
+{
+XlnxVersalCFrameBcastReg *s = XLNX_VERSAL_CFRAME_BCAST_REG(obj);
+SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+
+memory_region_init_io(>iomem_reg, obj, _bcast_reg_reg_ops, s,
+  TYPE_XLNX_VERSAL_CFRAME_BCAST_REG, 
KEYHOLE_STREAM_4K);
+memory_region_init_io(>iomem_fdri, obj, _bcast_reg_fdri_ops, s,
+  TYPE_XLNX_VERSAL_CFRAME_BCAST_REG "-fdri",
+  KEYHOLE_STREAM_4K);
+sysbus_init_mmio(sbd, >iomem_reg);
+sysbus_init_mmio(sbd, >iomem_fdri);
+}
+
+static void cframe_bcast_reg_reset_enter(Object *obj, ResetType type)
+{
+XlnxVersalCFrameBcastReg *s = XLNX_VERSAL_CFRAME_BCAST_REG(obj);
+
+memset(s->wfifo, 0, WFIFO_SZ * sizeof(uint32_t));
+}
+
+static const VMStateDescription vmstate_cframe_bcast_reg = {
+.name = TYPE_XLNX_VERSAL_CFRAME_BCAST_REG,
+.version_id = 1,
+.minimum_version_id = 1,
+.fields = (VMStateField[]) {
+VMSTATE_UINT32_ARRAY(wfifo, XlnxVersalCFrameBcastReg, 4),
+VMSTATE_END_OF_LIST(),
+}
+};
+
+static Property cframe_bcast_regs_props[] = {
+DEFINE_PROP_LINK("cframe0", XlnxVersalCFrameBcastReg, cfg.cframe[0],
+ TYPE_XLNX_CFI_IF, XlnxCfiIf *),
+DEFINE_PROP_LINK("cframe1", XlnxVersalCFrameBcastReg, cfg.cframe[1],
+ TYPE_XLNX_CFI_IF, XlnxCfiIf *),
+DEFINE_PROP_LINK("cframe2", XlnxVersalCFrameBcastReg, cfg.cframe[2],
+ TYPE_XLNX_CFI_IF, XlnxCfiIf *),
+DEFINE_PROP_LINK("cframe3", XlnxVersalCFrameBcastReg, cfg.cframe[3],
+ TYPE_XLNX_CFI_IF, XlnxCfiIf *),
+DEFINE_PROP_LINK("cframe4", XlnxVersalCFrameBcastReg, cfg.cfr

[PATCH v4 8/8] hw/arm/versal: Connect the CFRAME_REG and CFRAME_BCAST_REG

2023-08-31 Thread Francisco Iglesias
Connect the Configuration Frame controller (CFRAME_REG) and the
Configuration Frame broadcast controller (CFRAME_BCAST_REG) to the
Versal machine.

Signed-off-by: Francisco Iglesias 
Reviewed-by: Peter Maydell 
---
 hw/arm/xlnx-versal.c | 113 ++-
 include/hw/arm/xlnx-versal.h |  69 +
 2 files changed, 181 insertions(+), 1 deletion(-)

diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
index 3f4b4b1560..fa556d8764 100644
--- a/hw/arm/xlnx-versal.c
+++ b/hw/arm/xlnx-versal.c
@@ -27,7 +27,7 @@
 #define XLNX_VERSAL_RCPU_TYPE ARM_CPU_TYPE_NAME("cortex-r5f")
 #define GEM_REVISION0x40070106
 
-#define VERSAL_NUM_PMC_APB_IRQS 3
+#define VERSAL_NUM_PMC_APB_IRQS 18
 #define NUM_OSPI_IRQ_LINES 3
 
 static void versal_create_apu_cpus(Versal *s)
@@ -341,6 +341,7 @@ static void versal_create_pmc_apb_irq_orgate(Versal *s, 
qemu_irq *pic)
  *  - RTC
  *  - BBRAM
  *  - PMC SLCR
+ *  - CFRAME regs (input 3 - 17 to the orgate)
  */
 object_initialize_child(OBJECT(s), "pmc-apb-irq-orgate",
 >pmc.apb_irq_orgate, TYPE_OR_IRQ);
@@ -573,6 +574,42 @@ static void versal_create_ospi(Versal *s, qemu_irq *pic)
 static void versal_create_cfu(Versal *s, qemu_irq *pic)
 {
 SysBusDevice *sbd;
+DeviceState *dev;
+int i;
+const struct {
+uint64_t reg_base;
+uint64_t fdri_base;
+} cframe_addr[] = {
+{ MM_PMC_CFRAME0_REG, MM_PMC_CFRAME0_FDRI },
+{ MM_PMC_CFRAME1_REG, MM_PMC_CFRAME1_FDRI },
+{ MM_PMC_CFRAME2_REG, MM_PMC_CFRAME2_FDRI },
+{ MM_PMC_CFRAME3_REG, MM_PMC_CFRAME3_FDRI },
+{ MM_PMC_CFRAME4_REG, MM_PMC_CFRAME4_FDRI },
+{ MM_PMC_CFRAME5_REG, MM_PMC_CFRAME5_FDRI },
+{ MM_PMC_CFRAME6_REG, MM_PMC_CFRAME6_FDRI },
+{ MM_PMC_CFRAME7_REG, MM_PMC_CFRAME7_FDRI },
+{ MM_PMC_CFRAME8_REG, MM_PMC_CFRAME8_FDRI },
+{ MM_PMC_CFRAME9_REG, MM_PMC_CFRAME9_FDRI },
+{ MM_PMC_CFRAME10_REG, MM_PMC_CFRAME10_FDRI },
+{ MM_PMC_CFRAME11_REG, MM_PMC_CFRAME11_FDRI },
+{ MM_PMC_CFRAME12_REG, MM_PMC_CFRAME12_FDRI },
+{ MM_PMC_CFRAME13_REG, MM_PMC_CFRAME13_FDRI },
+{ MM_PMC_CFRAME14_REG, MM_PMC_CFRAME14_FDRI },
+};
+const struct {
+uint32_t blktype0_frames;
+uint32_t blktype1_frames;
+uint32_t blktype2_frames;
+uint32_t blktype3_frames;
+uint32_t blktype4_frames;
+uint32_t blktype5_frames;
+uint32_t blktype6_frames;
+} cframe_cfg[] = {
+[0] = { 34111, 3528, 12800, 11, 5, 1, 1 },
+[1] = { 38498, 3841, 15361, 13, 7, 3, 1 },
+[2] = { 38498, 3841, 15361, 13, 7, 3, 1 },
+[3] = { 38498, 3841, 15361, 13, 7, 3, 1 },
+};
 
 /* CFU FDRO */
 object_initialize_child(OBJECT(s), "cfu-fdro", >pmc.cfu_fdro,
@@ -583,10 +620,84 @@ static void versal_create_cfu(Versal *s, qemu_irq *pic)
 memory_region_add_subregion(>mr_ps, MM_PMC_CFU_FDRO,
 sysbus_mmio_get_region(sbd, 0));
 
+/* CFRAME REG */
+for (i = 0; i < ARRAY_SIZE(s->pmc.cframe); i++) {
+g_autofree char *name = g_strdup_printf("cframe%d", i);
+
+object_initialize_child(OBJECT(s), name, >pmc.cframe[i],
+TYPE_XLNX_VERSAL_CFRAME_REG);
+
+sbd = SYS_BUS_DEVICE(>pmc.cframe[i]);
+dev = DEVICE(>pmc.cframe[i]);
+
+if (i < ARRAY_SIZE(cframe_cfg)) {
+object_property_set_int(OBJECT(dev), "blktype0-frames",
+cframe_cfg[i].blktype0_frames,
+_abort);
+object_property_set_int(OBJECT(dev), "blktype1-frames",
+cframe_cfg[i].blktype1_frames,
+_abort);
+object_property_set_int(OBJECT(dev), "blktype2-frames",
+cframe_cfg[i].blktype2_frames,
+_abort);
+object_property_set_int(OBJECT(dev), "blktype3-frames",
+cframe_cfg[i].blktype3_frames,
+_abort);
+object_property_set_int(OBJECT(dev), "blktype4-frames",
+cframe_cfg[i].blktype4_frames,
+_abort);
+object_property_set_int(OBJECT(dev), "blktype5-frames",
+cframe_cfg[i].blktype5_frames,
+_abort);
+object_property_set_int(OBJECT(dev), "blktype6-frames",
+cframe_cfg[i].blktype6_frames,
+_abort);
+}
+object_property_set_link(OBJECT(dev), "cfu-fdro",
+   

[PATCH v4 5/8] hw/misc: Introduce a model of Xilinx Versal's CFRAME_REG

2023-08-31 Thread Francisco Iglesias
Introduce a model of Xilinx Versal's Configuration Frame controller
(CFRAME_REG).

Signed-off-by: Francisco Iglesias 
---
 MAINTAINERS  |   2 +
 hw/misc/meson.build  |   1 +
 hw/misc/xlnx-versal-cframe-reg.c | 697 +++
 include/hw/misc/xlnx-versal-cframe-reg.h | 286 ++
 4 files changed, 986 insertions(+)
 create mode 100644 hw/misc/xlnx-versal-cframe-reg.c
 create mode 100644 include/hw/misc/xlnx-versal-cframe-reg.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 847b997d73..645374c1d9 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1041,6 +1041,8 @@ F: hw/misc/xlnx-cfi-if.c
 F: include/hw/misc/xlnx-cfi-if.h
 F: hw/misc/xlnx-versal-cfu.c
 F: include/hw/misc/xlnx-versal-cfu.h
+F: hw/misc/xlnx-versal-cframe-reg.c
+F: include/hw/misc/xlnx-versal-cframe-reg.h
 
 STM32F100
 M: Alexandre Iooss 
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
index d95cc3fd87..1b425b03bd 100644
--- a/hw/misc/meson.build
+++ b/hw/misc/meson.build
@@ -99,6 +99,7 @@ system_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files(
   'xlnx-versal-pmc-iou-slcr.c',
   'xlnx-versal-cfu.c',
   'xlnx-cfi-if.c',
+  'xlnx-versal-cframe-reg.c',
 ))
 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'))
diff --git a/hw/misc/xlnx-versal-cframe-reg.c b/hw/misc/xlnx-versal-cframe-reg.c
new file mode 100644
index 00..78db68f10c
--- /dev/null
+++ b/hw/misc/xlnx-versal-cframe-reg.c
@@ -0,0 +1,697 @@
+/*
+ * QEMU model of the Configuration Frame Control module
+ *
+ * Copyright (C) 2023, Advanced Micro Devices, Inc.
+ *
+ * Written by Francisco Iglesias 
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "hw/sysbus.h"
+#include "hw/register.h"
+#include "hw/registerfields.h"
+#include "qemu/bitops.h"
+#include "qemu/log.h"
+#include "qemu/units.h"
+#include "qapi/error.h"
+#include "hw/qdev-properties.h"
+#include "migration/vmstate.h"
+#include "hw/irq.h"
+#include "hw/misc/xlnx-versal-cframe-reg.h"
+
+#ifndef XLNX_VERSAL_CFRAME_REG_ERR_DEBUG
+#define XLNX_VERSAL_CFRAME_REG_ERR_DEBUG 0
+#endif
+
+#define KEYHOLE_STREAM_4K (4 * KiB)
+#define N_WORDS_128BIT 4
+
+#define MAX_BLOCKTYPE 6
+#define MAX_BLOCKTYPE_FRAMES 0xF
+
+enum {
+CFRAME_CMD_WCFG = 1,
+CFRAME_CMD_ROWON = 2,
+CFRAME_CMD_ROWOFF = 3,
+CFRAME_CMD_RCFG = 4,
+CFRAME_CMD_DLPARK = 5,
+};
+
+static gint int_cmp(gconstpointer a, gconstpointer b, gpointer user_data)
+{
+guint ua = GPOINTER_TO_UINT(a);
+guint ub = GPOINTER_TO_UINT(b);
+return (ua > ub) - (ua < ub);
+}
+
+static void cfrm_imr_update_irq(XlnxVersalCFrameReg *s)
+{
+bool pending = s->regs[R_CFRM_ISR0] & ~s->regs[R_CFRM_IMR0];
+qemu_set_irq(s->irq_cfrm_imr, pending);
+}
+
+static void cfrm_isr_postw(RegisterInfo *reg, uint64_t val64)
+{
+XlnxVersalCFrameReg *s = XLNX_VERSAL_CFRAME_REG(reg->opaque);
+cfrm_imr_update_irq(s);
+}
+
+static uint64_t cfrm_ier_prew(RegisterInfo *reg, uint64_t val64)
+{
+XlnxVersalCFrameReg *s = XLNX_VERSAL_CFRAME_REG(reg->opaque);
+
+s->regs[R_CFRM_IMR0] &= ~s->regs[R_CFRM_IER0];
+s->regs[R_CFRM_IER0] = 0;
+cfrm_imr_update_irq(s);
+return 0;
+}
+
+static uint64_t cfrm_idr_prew(RegisterInfo *reg, uint64_t val64)
+{
+XlnxVersalCFrameReg *s = XLNX_VERSAL_CFRAME_REG(reg->opaque);
+
+s->regs[R_CFRM_IMR0] |= s->regs[R_CFRM_IDR0];
+s->regs[R_CFRM_IDR0] = 0;
+cfrm_imr_update_irq(s);
+return 0;
+}
+
+static uint64_t cfrm_itr_prew(RegisterInfo *reg, uint64_t val64)
+{
+XlnxVersalCFrameReg *s = XLNX_VERSAL_CFRAME_REG(reg->opaque);
+
+s->regs[R_CFRM_ISR0] |= s->regs[R_CFRM_ITR0];
+s->regs[R_CFRM_ITR0] = 0;
+cfrm_imr_update_irq(s);
+return 0;
+}
+
+static void cframe_incr_far(XlnxVersalCFrameReg *s)
+{
+uint32_t faddr = ARRAY_FIELD_EX32(s->regs, FAR0, FRAME_ADDR);
+uint32_t blktype = ARRAY_FIELD_EX32(s->regs, FAR0, BLOCKTYPE);
+
+assert(blktype <= MAX_BLOCKTYPE);
+
+faddr++;
+if (faddr > s->cfg.blktype_num_frames[blktype]) {
+/* Restart from 0 and increment block type */
+faddr = 0;
+blktype++;
+
+assert(blktype <= MAX_BLOCKTYPE);
+
+ARRAY_FIELD_DP32(s->regs, FAR0, BLOCKTYPE, blktype);
+}
+
+ARRAY_FIELD_DP32(s->regs, FAR0, FRAME_ADDR, faddr);
+}
+
+static void cfrm_fdri_post_write(RegisterInfo *reg, uint64_t val)
+{
+XlnxVersalCFrameReg *s = XLNX_VERSAL_CFRAME_REG(reg->opaque);
+
+if (s->row_configured && s->rowon && s->wcfg) {
+
+if (fifo32_num_free(>new_f_data) >= N_WORDS_128BIT) {
+fifo32_push(>new_f_data,

[PATCH v4 7/8] hw/arm/xlnx-versal: Connect the CFU_APB, CFU_FDRO and CFU_SFR

2023-08-31 Thread Francisco Iglesias
Connect the Configuration Frame Unit (CFU_APB, CFU_FDRO and CFU_SFR) to
the Versal machine.

Signed-off-by: Francisco Iglesias 
Acked-by: Edgar E. Iglesias 
Reviewed-by: Peter Maydell 
---
 hw/arm/xlnx-versal.c | 42 
 include/hw/arm/xlnx-versal.h | 16 ++
 2 files changed, 58 insertions(+)

diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
index 60bf5fe657..3f4b4b1560 100644
--- a/hw/arm/xlnx-versal.c
+++ b/hw/arm/xlnx-versal.c
@@ -570,6 +570,47 @@ static void versal_create_ospi(Versal *s, qemu_irq *pic)
 qdev_connect_gpio_out(orgate, 0, pic[VERSAL_OSPI_IRQ]);
 }
 
+static void versal_create_cfu(Versal *s, qemu_irq *pic)
+{
+SysBusDevice *sbd;
+
+/* CFU FDRO */
+object_initialize_child(OBJECT(s), "cfu-fdro", >pmc.cfu_fdro,
+TYPE_XLNX_VERSAL_CFU_FDRO);
+sbd = SYS_BUS_DEVICE(>pmc.cfu_fdro);
+
+sysbus_realize(sbd, _fatal);
+memory_region_add_subregion(>mr_ps, MM_PMC_CFU_FDRO,
+sysbus_mmio_get_region(sbd, 0));
+
+/* CFU APB */
+object_initialize_child(OBJECT(s), "cfu-apb", >pmc.cfu_apb,
+TYPE_XLNX_VERSAL_CFU_APB);
+sbd = SYS_BUS_DEVICE(>pmc.cfu_apb);
+
+sysbus_realize(sbd, _fatal);
+memory_region_add_subregion(>mr_ps, MM_PMC_CFU_APB,
+sysbus_mmio_get_region(sbd, 0));
+memory_region_add_subregion(>mr_ps, MM_PMC_CFU_STREAM,
+sysbus_mmio_get_region(sbd, 1));
+memory_region_add_subregion(>mr_ps, MM_PMC_CFU_STREAM_2,
+sysbus_mmio_get_region(sbd, 2));
+sysbus_connect_irq(sbd, 0, pic[VERSAL_CFU_IRQ_0]);
+
+/* CFU SFR */
+object_initialize_child(OBJECT(s), "cfu-sfr", >pmc.cfu_sfr,
+TYPE_XLNX_VERSAL_CFU_SFR);
+
+sbd = SYS_BUS_DEVICE(>pmc.cfu_sfr);
+
+object_property_set_link(OBJECT(>pmc.cfu_sfr),
+"cfu", OBJECT(>pmc.cfu_apb), _abort);
+
+sysbus_realize(sbd, _fatal);
+memory_region_add_subregion(>mr_ps, MM_PMC_CFU_SFR,
+sysbus_mmio_get_region(sbd, 0));
+}
+
 static void versal_create_crl(Versal *s, qemu_irq *pic)
 {
 SysBusDevice *sbd;
@@ -763,6 +804,7 @@ static void versal_realize(DeviceState *dev, Error **errp)
 versal_create_pmc_iou_slcr(s, pic);
 versal_create_ospi(s, pic);
 versal_create_crl(s, pic);
+versal_create_cfu(s, pic);
 versal_map_ddr(s);
 versal_unimp(s);
 
diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
index 39ee31185c..29b9c60301 100644
--- a/include/hw/arm/xlnx-versal.h
+++ b/include/hw/arm/xlnx-versal.h
@@ -32,6 +32,7 @@
 #include "hw/misc/xlnx-versal-crl.h"
 #include "hw/misc/xlnx-versal-pmc-iou-slcr.h"
 #include "hw/net/xlnx-versal-canfd.h"
+#include "hw/misc/xlnx-versal-cfu.h"
 
 #define TYPE_XLNX_VERSAL "xlnx-versal"
 OBJECT_DECLARE_SIMPLE_TYPE(Versal, XLNX_VERSAL)
@@ -117,6 +118,9 @@ struct Versal {
 XlnxEFuse efuse;
 XlnxVersalEFuseCtrl efuse_ctrl;
 XlnxVersalEFuseCache efuse_cache;
+XlnxVersalCFUAPB cfu_apb;
+XlnxVersalCFUFDRO cfu_fdro;
+XlnxVersalCFUSFR cfu_sfr;
 
 OrIRQState apb_irq_orgate;
 } pmc;
@@ -147,6 +151,7 @@ struct Versal {
 #define VERSAL_GEM1_WAKE_IRQ_0 59
 #define VERSAL_ADMA_IRQ_0  60
 #define VERSAL_XRAM_IRQ_0  79
+#define VERSAL_CFU_IRQ_0   120
 #define VERSAL_PMC_APB_IRQ 121
 #define VERSAL_OSPI_IRQ124
 #define VERSAL_SD0_IRQ_0   126
@@ -240,6 +245,17 @@ struct Versal {
 #define MM_PMC_EFUSE_CACHE  0xf125
 #define MM_PMC_EFUSE_CACHE_SIZE 0x00C00
 
+#define MM_PMC_CFU_APB  0xf12b
+#define MM_PMC_CFU_APB_SIZE 0x1
+#define MM_PMC_CFU_STREAM   0xf12c
+#define MM_PMC_CFU_STREAM_SIZE  0x1000
+#define MM_PMC_CFU_SFR  0xf12c1000
+#define MM_PMC_CFU_SFR_SIZE 0x1000
+#define MM_PMC_CFU_FDRO 0xf12c2000
+#define MM_PMC_CFU_FDRO_SIZE0x1000
+#define MM_PMC_CFU_STREAM_2 0xf1f8
+#define MM_PMC_CFU_STREAM_2_SIZE0x4
+
 #define MM_PMC_CRP  0xf126U
 #define MM_PMC_CRP_SIZE 0x1
 #define MM_PMC_RTC  0xf12a
-- 
2.34.1




[PATCH v4 1/8] hw/misc: Introduce the Xilinx CFI interface

2023-08-31 Thread Francisco Iglesias
Introduce the Xilinx Configuration Frame Interface (CFI) for transmitting
CFI data packets between the Xilinx Configuration Frame Unit models
(CFU_APB, CFU_FDRO and CFU_SFR), the Xilinx CFRAME controller (CFRAME_REG)
and the Xilinx CFRAME broadcast controller (CFRAME_BCAST_REG) models (when
emulating bitstream programming and readback).

Signed-off-by: Francisco Iglesias 
Reviewed-by: Sai Pavan Boddu 
Acked-by: Edgar E. Iglesias 
---
 MAINTAINERS   |  6 
 hw/misc/meson.build   |  1 +
 hw/misc/xlnx-cfi-if.c | 34 
 include/hw/misc/xlnx-cfi-if.h | 59 +++
 4 files changed, 100 insertions(+)
 create mode 100644 hw/misc/xlnx-cfi-if.c
 create mode 100644 include/hw/misc/xlnx-cfi-if.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 6111b6b4d9..e0cd365462 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1034,6 +1034,12 @@ S: Maintained
 F: hw/ssi/xlnx-versal-ospi.c
 F: include/hw/ssi/xlnx-versal-ospi.h
 
+Xilinx Versal CFI
+M: Francisco Iglesias 
+S: Maintained
+F: hw/misc/xlnx-cfi-if.c
+F: include/hw/misc/xlnx-cfi-if.h
+
 STM32F100
 M: Alexandre Iooss 
 L: qemu-...@nongnu.org
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
index 892f8b91c5..0c562f5e3e 100644
--- a/hw/misc/meson.build
+++ b/hw/misc/meson.build
@@ -97,6 +97,7 @@ specific_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: 
files('xlnx-versal-crl.c'))
 system_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files(
   'xlnx-versal-xramc.c',
   'xlnx-versal-pmc-iou-slcr.c',
+  'xlnx-cfi-if.c',
 ))
 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'))
diff --git a/hw/misc/xlnx-cfi-if.c b/hw/misc/xlnx-cfi-if.c
new file mode 100644
index 00..c45f05c4aa
--- /dev/null
+++ b/hw/misc/xlnx-cfi-if.c
@@ -0,0 +1,34 @@
+/*
+ * Xilinx CFI interface
+ *
+ * Copyright (C) 2023, Advanced Micro Devices, Inc.
+ *
+ * Written by Francisco Iglesias 
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#include "qemu/osdep.h"
+#include "hw/misc/xlnx-cfi-if.h"
+
+void xlnx_cfi_transfer_packet(XlnxCfiIf *cfi_if, XlnxCfiPacket *pkt)
+{
+XlnxCfiIfClass *xcic = XLNX_CFI_IF_GET_CLASS(cfi_if);
+
+if (xcic->cfi_transfer_packet) {
+xcic->cfi_transfer_packet(cfi_if, pkt);
+}
+}
+
+static const TypeInfo xlnx_cfi_if_info = {
+.name  = TYPE_XLNX_CFI_IF,
+.parent= TYPE_INTERFACE,
+.class_size = sizeof(XlnxCfiIfClass),
+};
+
+static void xlnx_cfi_if_register_types(void)
+{
+type_register_static(_cfi_if_info);
+}
+
+type_init(xlnx_cfi_if_register_types)
+
diff --git a/include/hw/misc/xlnx-cfi-if.h b/include/hw/misc/xlnx-cfi-if.h
new file mode 100644
index 00..f9bd12292d
--- /dev/null
+++ b/include/hw/misc/xlnx-cfi-if.h
@@ -0,0 +1,59 @@
+/*
+ * Xilinx CFI interface
+ *
+ * Copyright (C) 2023, Advanced Micro Devices, Inc.
+ *
+ * Written by Francisco Iglesias 
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#ifndef XLNX_CFI_IF_H
+#define XLNX_CFI_IF_H 1
+
+#include "qemu/help-texts.h"
+#include "hw/hw.h"
+#include "qom/object.h"
+
+#define TYPE_XLNX_CFI_IF "xlnx-cfi-if"
+typedef struct XlnxCfiIfClass XlnxCfiIfClass;
+DECLARE_CLASS_CHECKERS(XlnxCfiIfClass, XLNX_CFI_IF, TYPE_XLNX_CFI_IF)
+
+#define XLNX_CFI_IF(obj) \
+ INTERFACE_CHECK(XlnxCfiIf, (obj), TYPE_XLNX_CFI_IF)
+
+typedef enum {
+PACKET_TYPE_CFU = 0x52,
+PACKET_TYPE_CFRAME = 0xA1,
+} xlnx_cfi_packet_type;
+
+typedef enum {
+CFRAME_FAR = 1,
+CFRAME_SFR = 2,
+CFRAME_FDRI = 4,
+CFRAME_CMD = 6,
+} xlnx_cfi_reg_addr;
+
+typedef struct XlnxCfiPacket {
+uint8_t reg_addr;
+uint32_t data[4];
+} XlnxCfiPacket;
+
+typedef struct XlnxCfiIf {
+Object Parent;
+} XlnxCfiIf;
+
+typedef struct XlnxCfiIfClass {
+InterfaceClass parent;
+
+void (*cfi_transfer_packet)(XlnxCfiIf *cfi_if, XlnxCfiPacket *pkt);
+} XlnxCfiIfClass;
+
+/**
+ * Transfer a XlnxCfiPacket.
+ *
+ * @cfi_if: the object implementing this interface
+ * @XlnxCfiPacket: a pointer to the XlnxCfiPacket to transfer
+ */
+void xlnx_cfi_transfer_packet(XlnxCfiIf *cfi_if, XlnxCfiPacket *pkt);
+
+#endif /* XLNX_CFI_IF_H */
-- 
2.34.1




[PATCH v4 2/8] hw/misc: Introduce a model of Xilinx Versal's CFU_APB

2023-08-31 Thread Francisco Iglesias
Introduce a model of the software programming interface (CFU_APB) of
Xilinx Versal's Configuration Frame Unit.

Signed-off-by: Francisco Iglesias 
Reviewed-by: Peter Maydell 
---
 MAINTAINERS   |   2 +
 hw/misc/meson.build   |   1 +
 hw/misc/xlnx-versal-cfu.c | 380 ++
 include/hw/misc/xlnx-versal-cfu.h | 231 ++
 4 files changed, 614 insertions(+)
 create mode 100644 hw/misc/xlnx-versal-cfu.c
 create mode 100644 include/hw/misc/xlnx-versal-cfu.h

diff --git a/MAINTAINERS b/MAINTAINERS
index e0cd365462..847b997d73 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1039,6 +1039,8 @@ M: Francisco Iglesias 
 S: Maintained
 F: hw/misc/xlnx-cfi-if.c
 F: include/hw/misc/xlnx-cfi-if.h
+F: hw/misc/xlnx-versal-cfu.c
+F: include/hw/misc/xlnx-versal-cfu.h
 
 STM32F100
 M: Alexandre Iooss 
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
index 0c562f5e3e..d95cc3fd87 100644
--- a/hw/misc/meson.build
+++ b/hw/misc/meson.build
@@ -97,6 +97,7 @@ specific_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: 
files('xlnx-versal-crl.c'))
 system_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files(
   'xlnx-versal-xramc.c',
   'xlnx-versal-pmc-iou-slcr.c',
+  'xlnx-versal-cfu.c',
   'xlnx-cfi-if.c',
 ))
 system_ss.add(when: 'CONFIG_STM32F2XX_SYSCFG', if_true: 
files('stm32f2xx_syscfg.c'))
diff --git a/hw/misc/xlnx-versal-cfu.c b/hw/misc/xlnx-versal-cfu.c
new file mode 100644
index 00..b2dc6ab211
--- /dev/null
+++ b/hw/misc/xlnx-versal-cfu.c
@@ -0,0 +1,380 @@
+/*
+ * QEMU model of the CFU Configuration Unit.
+ *
+ * Copyright (C) 2023, Advanced Micro Devices, Inc.
+ *
+ * Written by Edgar E. Iglesias ,
+ *Sai Pavan Boddu ,
+ *Francisco Iglesias 
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "hw/sysbus.h"
+#include "hw/register.h"
+#include "hw/irq.h"
+#include "qemu/bitops.h"
+#include "qemu/log.h"
+#include "qemu/units.h"
+#include "migration/vmstate.h"
+#include "hw/qdev-properties.h"
+#include "hw/qdev-properties-system.h"
+#include "hw/misc/xlnx-versal-cfu.h"
+
+#ifndef XLNX_VERSAL_CFU_APB_ERR_DEBUG
+#define XLNX_VERSAL_CFU_APB_ERR_DEBUG 0
+#endif
+
+#define KEYHOLE_STREAM_4K (4 * KiB)
+#define KEYHOLE_STREAM_256K (256 * KiB)
+#define CFRAME_BROADCAST_ROW 0x1F
+
+bool update_wfifo(hwaddr addr, uint64_t value,
+  uint32_t *wfifo, uint32_t *wfifo_ret)
+{
+unsigned int idx = extract32(addr, 2, 2);
+
+wfifo[idx] = value;
+
+if (idx == 3) {
+memcpy(wfifo_ret, wfifo, WFIFO_SZ * sizeof(uint32_t));
+memset(wfifo, 0, WFIFO_SZ * sizeof(uint32_t));
+return true;
+}
+
+return false;
+}
+
+static void cfu_imr_update_irq(XlnxVersalCFUAPB *s)
+{
+bool pending = s->regs[R_CFU_ISR] & ~s->regs[R_CFU_IMR];
+qemu_set_irq(s->irq_cfu_imr, pending);
+}
+
+static void cfu_isr_postw(RegisterInfo *reg, uint64_t val64)
+{
+XlnxVersalCFUAPB *s = XLNX_VERSAL_CFU_APB(reg->opaque);
+cfu_imr_update_irq(s);
+}
+
+static uint64_t cfu_ier_prew(RegisterInfo *reg, uint64_t val64)
+{
+XlnxVersalCFUAPB *s = XLNX_VERSAL_CFU_APB(reg->opaque);
+uint32_t val = val64;
+
+s->regs[R_CFU_IMR] &= ~val;
+cfu_imr_update_irq(s);
+return 0;
+}
+
+static uint64_t cfu_idr_prew(RegisterInfo *reg, uint64_t val64)
+{
+XlnxVersalCFUAPB *s = XLNX_VERSAL_CFU_APB(reg->opaque);
+uint32_t val = val64;
+
+s->regs[R_CFU_IMR] |= val;
+cfu_imr_update_irq(s);
+return 0;
+}
+
+static uint64_t cfu_itr_prew(RegisterInfo *reg, uint64_t val64)
+{
+XlnxVersalCFUAPB *s = XLNX_VERSAL_CFU_APB(reg->opaque);
+uint32_t val = val64;
+
+s->regs[R_CFU_ISR] |= val;
+cfu_imr_update_irq(s);
+return 0;
+}
+
+static void cfu_fgcr_postw(RegisterInfo *reg, uint64_t val64)
+{
+XlnxVersalCFUAPB *s = XLNX_VERSAL_CFU_APB(reg->opaque);
+uint32_t val = (uint32_t)val64;
+
+/* Do a scan. It always looks good. */
+if (FIELD_EX32(val, CFU_FGCR, SC_HBC_TRIGGER)) {
+ARRAY_FIELD_DP32(s->regs, CFU_STATUS, SCAN_CLEAR_PASS, 1);
+ARRAY_FIELD_DP32(s->regs, CFU_STATUS, SCAN_CLEAR_DONE, 1);
+}
+}
+
+static const RegisterAccessInfo cfu_apb_regs_info[] = {
+{   .name = "CFU_ISR",  .addr = A_CFU_ISR,
+.rsvd = 0xfc00,
+.w1c = 0x3ff,
+.post_write = cfu_isr_postw,
+},{ .name = "CFU_IMR",  .addr = A_CFU_IMR,
+.reset = 0x3ff,
+.rsvd = 0xfc00,
+.ro = 0x3ff,
+},{ .name = "CFU_IER",  .addr = A_CFU_IER,
+.rsvd = 0xfc00,
+.pre_write = cfu_ier_prew,
+},{ .name = "CFU_IDR",  .addr = A_CFU_IDR,
+.rsvd = 0xfc00,
+.pre_write = cfu_idr_prew,
+},{ .name = "CFU_ITR",  .addr = A_CFU_ITR,
+.rsvd

[PATCH v4 3/8] hw/misc/xlnx-versal-cfu: Introduce a model of Xilinx Versal CFU_FDRO

2023-08-31 Thread Francisco Iglesias
Introduce a model of Xilinx Versal's Configuration Frame Unit's data out
port (CFU_FDRO).

Signed-off-by: Francisco Iglesias 
Reviewed-by: Peter Maydell 
---
 hw/misc/xlnx-versal-cfu.c | 96 +++
 include/hw/misc/xlnx-versal-cfu.h | 12 
 2 files changed, 108 insertions(+)

diff --git a/hw/misc/xlnx-versal-cfu.c b/hw/misc/xlnx-versal-cfu.c
index b2dc6ab211..255c1bf4b8 100644
--- a/hw/misc/xlnx-versal-cfu.c
+++ b/hw/misc/xlnx-versal-cfu.c
@@ -264,6 +264,25 @@ static void cfu_stream_write(void *opaque, hwaddr addr, 
uint64_t value,
 }
 }
 
+static uint64_t cfu_fdro_read(void *opaque, hwaddr addr, unsigned size)
+{
+XlnxVersalCFUFDRO *s = XLNX_VERSAL_CFU_FDRO(opaque);
+uint64_t ret = 0;
+
+if (!fifo32_is_empty(>fdro_data)) {
+ret = fifo32_pop(>fdro_data);
+}
+
+return ret;
+}
+
+static void cfu_fdro_write(void *opaque, hwaddr addr, uint64_t value,
+   unsigned size)
+{
+qemu_log_mask(LOG_GUEST_ERROR, "%s: Unsupported write from addr=%"
+  HWADDR_PRIx "\n", __func__, addr);
+}
+
 static const MemoryRegionOps cfu_stream_ops = {
 .read = cfu_stream_read,
 .write = cfu_stream_write,
@@ -274,6 +293,16 @@ static const MemoryRegionOps cfu_stream_ops = {
 },
 };
 
+static const MemoryRegionOps cfu_fdro_ops = {
+.read = cfu_fdro_read,
+.write = cfu_fdro_write,
+.endianness = DEVICE_LITTLE_ENDIAN,
+.valid = {
+.min_access_size = 4,
+.max_access_size = 4,
+},
+};
+
 static void cfu_apb_init(Object *obj)
 {
 XlnxVersalCFUAPB *s = XLNX_VERSAL_CFU_APB(obj);
@@ -305,6 +334,39 @@ static void cfu_apb_init(Object *obj)
 sysbus_init_irq(sbd, >irq_cfu_imr);
 }
 
+static void cfu_fdro_init(Object *obj)
+{
+XlnxVersalCFUFDRO *s = XLNX_VERSAL_CFU_FDRO(obj);
+SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+
+memory_region_init_io(>iomem_fdro, obj, _fdro_ops, s,
+  TYPE_XLNX_VERSAL_CFU_FDRO, KEYHOLE_STREAM_4K);
+sysbus_init_mmio(sbd, >iomem_fdro);
+fifo32_create(>fdro_data, 8 * KiB / sizeof(uint32_t));
+}
+
+static void cfu_fdro_reset_enter(Object *obj, ResetType type)
+{
+XlnxVersalCFUFDRO *s = XLNX_VERSAL_CFU_FDRO(obj);
+
+fifo32_reset(>fdro_data);
+}
+
+static void cfu_fdro_cfi_transfer_packet(XlnxCfiIf *cfi_if, XlnxCfiPacket *pkt)
+{
+XlnxVersalCFUFDRO *s = XLNX_VERSAL_CFU_FDRO(cfi_if);
+
+if (fifo32_num_free(>fdro_data) >= ARRAY_SIZE(pkt->data)) {
+for (int i = 0; i < ARRAY_SIZE(pkt->data); i++) {
+fifo32_push(>fdro_data, pkt->data[i]);
+}
+} else {
+/* It is a programming error to fill the fifo. */
+qemu_log_mask(LOG_GUEST_ERROR,
+  "CFU_FDRO: CFI data dropped due to full read fifo\n");
+}
+}
+
 static Property cfu_props[] = {
 DEFINE_PROP_LINK("cframe0", XlnxVersalCFUAPB, cfg.cframe[0],
  TYPE_XLNX_CFI_IF, XlnxCfiIf *),
@@ -351,6 +413,16 @@ static const VMStateDescription vmstate_cfu_apb = {
 }
 };
 
+static const VMStateDescription vmstate_cfu_fdro = {
+.name = TYPE_XLNX_VERSAL_CFU_FDRO,
+.version_id = 1,
+.minimum_version_id = 1,
+.fields = (VMStateField[]) {
+VMSTATE_FIFO32(fdro_data, XlnxVersalCFUFDRO),
+VMSTATE_END_OF_LIST(),
+}
+};
+
 static void cfu_apb_class_init(ObjectClass *klass, void *data)
 {
 DeviceClass *dc = DEVICE_CLASS(klass);
@@ -360,6 +432,17 @@ static void cfu_apb_class_init(ObjectClass *klass, void 
*data)
 device_class_set_props(dc, cfu_props);
 }
 
+static void cfu_fdro_class_init(ObjectClass *klass, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(klass);
+ResettableClass *rc = RESETTABLE_CLASS(klass);
+XlnxCfiIfClass *xcic = XLNX_CFI_IF_CLASS(klass);
+
+dc->vmsd = _cfu_fdro;
+xcic->cfi_transfer_packet = cfu_fdro_cfi_transfer_packet;
+rc->phases.enter = cfu_fdro_reset_enter;
+}
+
 static const TypeInfo cfu_apb_info = {
 .name  = TYPE_XLNX_VERSAL_CFU_APB,
 .parent= TYPE_SYS_BUS_DEVICE,
@@ -372,9 +455,22 @@ static const TypeInfo cfu_apb_info = {
 }
 };
 
+static const TypeInfo cfu_fdro_info = {
+.name  = TYPE_XLNX_VERSAL_CFU_FDRO,
+.parent= TYPE_SYS_BUS_DEVICE,
+.instance_size = sizeof(XlnxVersalCFUFDRO),
+.class_init= cfu_fdro_class_init,
+.instance_init = cfu_fdro_init,
+.interfaces = (InterfaceInfo[]) {
+{ TYPE_XLNX_CFI_IF },
+{ }
+}
+};
+
 static void cfu_apb_register_types(void)
 {
 type_register_static(_apb_info);
+type_register_static(_fdro_info);
 }
 
 type_init(cfu_apb_register_types)
diff --git a/include/hw/misc/xlnx-versal-cfu.h 
b/include/hw/misc/xlnx-versal-cfu.h
index 62d10caf27..73e9a21af4 100644
--- a/include/hw/misc/xlnx-versal-cfu.h
+++ b/include/hw/misc/xlnx-versal-cfu.h
@@ -20,10 +20,14 @@
 #include "h

[PATCH v4 4/8] hw/misc/xlnx-versal-cfu: Introduce a model of Xilinx Versal's CFU_SFR

2023-08-31 Thread Francisco Iglesias
Introduce a model of Xilinx Versal's Configuration Frame Unit's Single
Frame Read port (CFU_SFR).

Signed-off-by: Francisco Iglesias 
Reviewed-by: Peter Maydell 
---
 hw/misc/xlnx-versal-cfu.c | 87 +++
 include/hw/misc/xlnx-versal-cfu.h | 15 ++
 2 files changed, 102 insertions(+)

diff --git a/hw/misc/xlnx-versal-cfu.c b/hw/misc/xlnx-versal-cfu.c
index 255c1bf4b8..8e588ac1d8 100644
--- a/hw/misc/xlnx-versal-cfu.c
+++ b/hw/misc/xlnx-versal-cfu.c
@@ -264,6 +264,31 @@ static void cfu_stream_write(void *opaque, hwaddr addr, 
uint64_t value,
 }
 }
 
+static uint64_t cfu_sfr_read(void *opaque, hwaddr addr, unsigned size)
+{
+qemu_log_mask(LOG_GUEST_ERROR, "%s: Unsupported read from addr=%"
+  HWADDR_PRIx "\n", __func__, addr);
+return 0;
+}
+
+static void cfu_sfr_write(void *opaque, hwaddr addr, uint64_t value,
+  unsigned size)
+{
+XlnxVersalCFUSFR *s = XLNX_VERSAL_CFU_SFR(opaque);
+uint32_t wfifo[WFIFO_SZ];
+
+if (update_wfifo(addr, value, s->wfifo, wfifo)) {
+uint8_t row_addr = extract32(wfifo[0], 23, 5);
+uint32_t frame_addr = extract32(wfifo[0], 0, 23);
+XlnxCfiPacket pkt = { .reg_addr = CFRAME_SFR,
+  .data[0] = frame_addr };
+
+if (s->cfg.cfu) {
+cfu_transfer_cfi_packet(s->cfg.cfu, row_addr, );
+}
+}
+}
+
 static uint64_t cfu_fdro_read(void *opaque, hwaddr addr, unsigned size)
 {
 XlnxVersalCFUFDRO *s = XLNX_VERSAL_CFU_FDRO(opaque);
@@ -293,6 +318,16 @@ static const MemoryRegionOps cfu_stream_ops = {
 },
 };
 
+static const MemoryRegionOps cfu_sfr_ops = {
+.read = cfu_sfr_read,
+.write = cfu_sfr_write,
+.endianness = DEVICE_LITTLE_ENDIAN,
+.valid = {
+.min_access_size = 4,
+.max_access_size = 4,
+},
+};
+
 static const MemoryRegionOps cfu_fdro_ops = {
 .read = cfu_fdro_read,
 .write = cfu_fdro_write,
@@ -334,6 +369,23 @@ static void cfu_apb_init(Object *obj)
 sysbus_init_irq(sbd, >irq_cfu_imr);
 }
 
+static void cfu_sfr_init(Object *obj)
+{
+XlnxVersalCFUSFR *s = XLNX_VERSAL_CFU_SFR(obj);
+SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+
+memory_region_init_io(>iomem_sfr, obj, _sfr_ops, s,
+  TYPE_XLNX_VERSAL_CFU_SFR, KEYHOLE_STREAM_4K);
+sysbus_init_mmio(sbd, >iomem_sfr);
+}
+
+static void cfu_sfr_reset_enter(Object *obj, ResetType type)
+{
+XlnxVersalCFUSFR *s = XLNX_VERSAL_CFU_SFR(obj);
+
+memset(s->wfifo, 0, WFIFO_SZ * sizeof(uint32_t));
+}
+
 static void cfu_fdro_init(Object *obj)
 {
 XlnxVersalCFUFDRO *s = XLNX_VERSAL_CFU_FDRO(obj);
@@ -401,6 +453,12 @@ static Property cfu_props[] = {
 DEFINE_PROP_END_OF_LIST(),
 };
 
+static Property cfu_sfr_props[] = {
+DEFINE_PROP_LINK("cfu", XlnxVersalCFUSFR, cfg.cfu,
+ TYPE_XLNX_VERSAL_CFU_APB, XlnxVersalCFUAPB *),
+DEFINE_PROP_END_OF_LIST(),
+};
+
 static const VMStateDescription vmstate_cfu_apb = {
 .name = TYPE_XLNX_VERSAL_CFU_APB,
 .version_id = 1,
@@ -423,6 +481,16 @@ static const VMStateDescription vmstate_cfu_fdro = {
 }
 };
 
+static const VMStateDescription vmstate_cfu_sfr = {
+.name = TYPE_XLNX_VERSAL_CFU_SFR,
+.version_id = 1,
+.minimum_version_id = 1,
+.fields = (VMStateField[]) {
+VMSTATE_UINT32_ARRAY(wfifo, XlnxVersalCFUSFR, 4),
+VMSTATE_END_OF_LIST(),
+}
+};
+
 static void cfu_apb_class_init(ObjectClass *klass, void *data)
 {
 DeviceClass *dc = DEVICE_CLASS(klass);
@@ -443,6 +511,16 @@ static void cfu_fdro_class_init(ObjectClass *klass, void 
*data)
 rc->phases.enter = cfu_fdro_reset_enter;
 }
 
+static void cfu_sfr_class_init(ObjectClass *klass, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(klass);
+ResettableClass *rc = RESETTABLE_CLASS(klass);
+
+device_class_set_props(dc, cfu_sfr_props);
+dc->vmsd = _cfu_sfr;
+rc->phases.enter = cfu_sfr_reset_enter;
+}
+
 static const TypeInfo cfu_apb_info = {
 .name  = TYPE_XLNX_VERSAL_CFU_APB,
 .parent= TYPE_SYS_BUS_DEVICE,
@@ -467,10 +545,19 @@ static const TypeInfo cfu_fdro_info = {
 }
 };
 
+static const TypeInfo cfu_sfr_info = {
+.name  = TYPE_XLNX_VERSAL_CFU_SFR,
+.parent= TYPE_SYS_BUS_DEVICE,
+.instance_size = sizeof(XlnxVersalCFUSFR),
+.class_init= cfu_sfr_class_init,
+.instance_init = cfu_sfr_init,
+};
+
 static void cfu_apb_register_types(void)
 {
 type_register_static(_apb_info);
 type_register_static(_fdro_info);
+type_register_static(_sfr_info);
 }
 
 type_init(cfu_apb_register_types)
diff --git a/include/hw/misc/xlnx-versal-cfu.h 
b/include/hw/misc/xlnx-versal-cfu.h
index 73e9a21af4..86fb841053 100644
--- a/include/hw/misc/xlnx-versal-cfu.h
+++ b/include/hw/misc/xlnx-versal-cfu.h
@@ -28,6 +28,9 @@ OBJECT_DECLARE_SIMPLE_TYPE(XlnxVersalCFUAPB, 
XLNX_VER

[PATCH v4 0/8] Xilinx Versal CFI support

2023-08-31 Thread Francisco Iglesias
Hi,

This series adds support for the Configuration Frame Unit (CFU) and the
Configuration Frame controllers (CFRAME) to the Xilinx Versal machine
([1], chapter 21) for emulaing bitstream loading and readback.

The series starts by introducing the Xilinx CFI interface that is
thereafter used by the Xilinx CFU components, the Xilinx CFRAME and Xilinx
CFRAME broadcast models for transfering CFI packets between each other.
Thereafter a model of the CFU_APB, CFU_FDRO and CFU_SFR are introduced and
also models of the CFRAME controller and CFRAME broadcast controller.

The series thereafter ends with connecting the models to Xilinx Versal
machine.

Best regards,
Francisco Iglesias

References:
[1] https://docs.xilinx.com/r/en-US/am011-versal-acap-trm/PSM-Local-Registers


Changelog:
v3->v4:
 [PATCH 5]
   * Swap to pop out the fifo32 data instead of using memcpy
   * Use g_tree_nnodes instead of g_tree_height
   * Take reference before g_tree_destroy (for keeping the GTree around)
   * Remove stray whitespace (in cframe_reg_init before g_free)

v2->v3:
 [PATCH 5]
   * Swap to store the CFrames in a GTree instead of GArray
   * Rename new_f to new_f_data and also add it to the vmstate 
   * Removed unnecessary 'switch' braces in cframe_reg_cfi_transfer_packet
   * Correct the reset of new_f_data and the cframes GTree
v1->v2:
 [PATCH 2]
   * Use KiB when defining KEYHOLE_STREAM_4K/KEYHOLE_STREAM_256K
   * Updated to be able to share wfifo code 
 [PATCH 3]
   * Swap to use Fifo32 instead of GArray in the CFU_FDRO model
   * Add device reset to the CFU_FDRO model
 [PATCH 4]
   * Add device reset to the CFU_SFR model
 [PATCH 5]
   * Use KiB when defining KEYHOLE_STREAM_4K
   * Add comma after CFRAME_CMD_DLPARK
   * Remove backwards compatibility comment (and the 'cfu' alias propname for
 cfg.cfu_fdro)
   * Use Fifo32 inside the XlnxCFrame structure
   * Reworked cframes_reg_pre_save / cframes_reg_post_load
 [PATCH 6]
   * Add device reset to the CFrame broadcast reg model
 [PATCH 8]
   * Switch to use g_autofree instead of explicit g_free


Francisco Iglesias (8):
  hw/misc: Introduce the Xilinx CFI interface
  hw/misc: Introduce a model of Xilinx Versal's CFU_APB
  hw/misc/xlnx-versal-cfu: Introduce a model of Xilinx Versal CFU_FDRO
  hw/misc/xlnx-versal-cfu: Introduce a model of Xilinx Versal's CFU_SFR
  hw/misc: Introduce a model of Xilinx Versal's CFRAME_REG
  hw/misc: Introduce a model of Xilinx Versal's CFRAME_BCAST_REG
  hw/arm/xlnx-versal: Connect the CFU_APB, CFU_FDRO and CFU_SFR
  hw/arm/versal: Connect the CFRAME_REG and CFRAME_BCAST_REG

 MAINTAINERS  |  10 +
 hw/arm/xlnx-versal.c | 155 +++-
 hw/misc/meson.build  |   3 +
 hw/misc/xlnx-cfi-if.c|  34 +
 hw/misc/xlnx-versal-cframe-reg.c | 858 +++
 hw/misc/xlnx-versal-cfu.c| 563 +++
 include/hw/arm/xlnx-versal.h |  85 +++
 include/hw/misc/xlnx-cfi-if.h|  59 ++
 include/hw/misc/xlnx-versal-cframe-reg.h | 303 
 include/hw/misc/xlnx-versal-cfu.h| 258 +++
 10 files changed, 2327 insertions(+), 1 deletion(-)
 create mode 100644 hw/misc/xlnx-cfi-if.c
 create mode 100644 hw/misc/xlnx-versal-cframe-reg.c
 create mode 100644 hw/misc/xlnx-versal-cfu.c
 create mode 100644 include/hw/misc/xlnx-cfi-if.h
 create mode 100644 include/hw/misc/xlnx-versal-cframe-reg.h
 create mode 100644 include/hw/misc/xlnx-versal-cfu.h

-- 
2.34.1




Re: [PATCH v3 5/8] hw/misc: Introduce a model of Xilinx Versal's CFRAME_REG

2023-08-31 Thread Francisco Iglesias

Hi Peter,

On 2023-08-29 18:44, Peter Maydell wrote:

On Thu, 24 Aug 2023 at 19:35, Francisco Iglesias
 wrote:


Introduce a model of Xilinx Versal's Configuration Frame controller
(CFRAME_REG).

Signed-off-by: Francisco Iglesias 



+static void cfrm_fdri_post_write(RegisterInfo *reg, uint64_t val)
+{
+XlnxVersalCFrameReg *s = XLNX_VERSAL_CFRAME_REG(reg->opaque);
+
+if (s->row_configured && s->rowon && s->wcfg) {
+
+if (fifo32_num_free(>new_f_data) >= N_WORDS_128BIT) {
+fifo32_push(>new_f_data, s->regs[R_FDRI0]);
+fifo32_push(>new_f_data, s->regs[R_FDRI1]);
+fifo32_push(>new_f_data, s->regs[R_FDRI2]);
+fifo32_push(>new_f_data, s->regs[R_FDRI3]);
+}
+
+if (fifo32_is_full(>new_f_data)) {
+uint32_t addr = extract32(s->regs[R_FAR0], 0, 23);
+XlnxCFrame *f = g_new(XlnxCFrame, 1);
+
+memcpy(f->data, s->new_f_data.fifo.data, sizeof(f->data));


This works, but it's going under the hood of the Fifo32 abstraction
and makes the assumptions that (a) if you only push to the fifo
and never pop then the data is going to be contiguous from the
start of the fifo internal buffer and (b) that fifo32_push()
pushes the bytes of the 32 bit value in little endian order.
Those are both true at the moment, but fifo32 doesn't explicitly
guarantee either of them...



Undestood, to be safe I changed to pop the values from the fifo instead 
of using memcpy.



+
+g_tree_replace(s->cframes, GUINT_TO_POINTER(addr), f);
+
+cframe_incr_far(s);
+
+fifo32_reset(>new_f_data);
+}
+}
+}
+
+static void cfrm_readout_frames(XlnxVersalCFrameReg *s, uint32_t start_addr,
+uint32_t end_addr)
+{
+for (uint32_t addr = start_addr; addr < end_addr; addr++) {
+XlnxCFrame *f = g_tree_lookup(s->cframes, GUINT_TO_POINTER(addr));


You don't need to g_tree_lookup() for every address. If
you use g_tree_lookup_node() you get a GTreeNode* back,
and you can then iterate through the tree from that point using
g_tree_node_next(), something like this:

  for (node = g_tree_lookup_node(s->cframes, GUINT_TO_POINTER(addr));
   node && GPOINTER_TO_UINT(g_tree_node_key(node)) < end_addr;
   node = g_tree_node_next(node)) {
  XlnxCFrame *f = g_tree_node_value(node);  // definitely not NULL
  /* Transmit the data */
  for (int i = 0; i < FRAME_NUM_WORDS; i += 4) {
  ... etc ...
  }
  }



I tried above but it looks to require glib 2.68 so added a comment 
instead (didn't compile on my machine with glib-2.64 :/, if I understand 
meson.build correctly the min glib version supported is 2.56). Let me 
know if some other solution would be preferred.


/*
 * NB: when our minimum glib version is at least 2.68 we can improve the
 * performance of the cframe traversal by using g_tree_lookup_node and
 * g_tree_node_next (instead of calling g_tree_lookup for finding each
 * cframe).
 */


I also added in the other improvements and correction below!

Thank you for the help again!

Best regards,
Francisco





+
+/* Transmit the data if a frame was found */
+if (f) {
+for (int i = 0; i < FRAME_NUM_WORDS; i += 4) {
+XlnxCfiPacket pkt = {};
+
+pkt.data[0] = f->data[i];
+pkt.data[1] = f->data[i + 1];
+pkt.data[2] = f->data[i + 2];
+pkt.data[3] = f->data[i + 3];
+
+if (s->cfg.cfu_fdro) {
+xlnx_cfi_transfer_packet(s->cfg.cfu_fdro, );
+}
+}
+}
+}
+}




+static void cframe_reg_reset_enter(Object *obj, ResetType type)
+{
+XlnxVersalCFrameReg *s = XLNX_VERSAL_CFRAME_REG(obj);
+unsigned int i;
+

j>> +for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {

+register_reset(>regs_info[i]);
+}
+memset(s->wfifo, 0, WFIFO_SZ * sizeof(uint32_t));
+fifo32_reset(>new_f_data);
+
+if (g_tree_height(s->cframes)) {


Calculating g_tree_height() requires walking the tree.
Using g_tree_nnodes() is faster because that's just a field
in the GTree struct.


+g_tree_destroy(s->cframes);
+s->cframes = g_tree_new_full((GCompareDataFunc)int_cmp, NULL,
+  NULL, (GDestroyNotify) g_free);


Faster to do
 /*
  * Take a reference so when g_tree_destroy() unrefs it we keep the
  * GTree and only destroy its contents. NB: when our minimum
  * glib version is at least 2.70 we could use g_tree_remove_all().
  */
 g_tree_ref(s->cframes);
 g_tree_destroy(s->cframes);


+}
+}



+
+static void cframe_reg_init(Object *obj)
+{
+XlnxVersalCFrameReg *s = XLNX_VERSAL_CFRAM

Re: [PATCH 3/4] net/dump: Avoid variable length array

2023-08-25 Thread Francisco Iglesias
On [2023 Aug 24] Thu 16:32:23, Peter Maydell wrote:
> Use a g_autofree heap allocation instead of a variable length
> array in dump_receive_iov().
> 
> The codebase has very few VLAs, and if we can get rid of them all we
> can make the compiler error on new additions.  This is a defensive
> measure against security bugs where an on-stack dynamic allocation
> isn't correctly size-checked (e.g.  CVE-2021-3527).
> 
> Signed-off-by: Peter Maydell 

Reviewed-by: Francisco Iglesias 

> ---
>  net/dump.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/net/dump.c b/net/dump.c
> index 7d05f16ca7a..16073f24582 100644
> --- a/net/dump.c
> +++ b/net/dump.c
> @@ -68,7 +68,7 @@ static ssize_t dump_receive_iov(DumpState *s, const struct 
> iovec *iov, int cnt,
>  int64_t ts;
>  int caplen;
>  size_t size = iov_size(iov, cnt) - offset;
> -struct iovec dumpiov[cnt + 1];
> +g_autofree struct iovec *dumpiov = g_new(struct iovec, cnt + 1);
>  
>  /* Early return in case of previous error. */
>  if (s->fd < 0) {
> -- 
> 2.34.1
> 
> 



Re: [PATCH 4/4] net/tap: Avoid variable-length array

2023-08-25 Thread Francisco Iglesias
On [2023 Aug 24] Thu 16:32:24, Peter Maydell wrote:
> Use a heap allocation instead of a variable length array in
> tap_receive_iov().
> 
> The codebase has very few VLAs, and if we can get rid of them all we
> can make the compiler error on new additions.  This is a defensive
> measure against security bugs where an on-stack dynamic allocation
> isn't correctly size-checked (e.g.  CVE-2021-3527).
> 
> Signed-off-by: Peter Maydell 

Reviewed-by: Francisco Iglesias 

> ---
>  net/tap.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/net/tap.c b/net/tap.c
> index 1bf085d4228..34b1e3f0918 100644
> --- a/net/tap.c
> +++ b/net/tap.c
> @@ -117,10 +117,11 @@ static ssize_t tap_receive_iov(NetClientState *nc, 
> const struct iovec *iov,
>  {
>  TAPState *s = DO_UPCAST(TAPState, nc, nc);
>  const struct iovec *iovp = iov;
> -struct iovec iov_copy[iovcnt + 1];
> +g_autofree struct iovec *iov_copy = NULL;
>  struct virtio_net_hdr_mrg_rxbuf hdr = { };
>  
>  if (s->host_vnet_hdr_len && !s->using_vnet_hdr) {
> +iov_copy = g_new(struct iovec, iovcnt + 1);
>  iov_copy[0].iov_base = 
>  iov_copy[0].iov_len =  s->host_vnet_hdr_len;
>  memcpy(_copy[1], iov, iovcnt * sizeof(*iov));
> -- 
> 2.34.1
> 
> 



Re: [PATCH 2/4] hw/net/rocker: Avoid variable length array

2023-08-25 Thread Francisco Iglesias
On [2023 Aug 24] Thu 16:32:22, Peter Maydell wrote:
> Replace an on-stack variable length array in of_dpa_ig() with
> a g_autofree heap allocation.
> 
> The codebase has very few VLAs, and if we can get rid of them all we
> can make the compiler error on new additions.  This is a defensive
> measure against security bugs where an on-stack dynamic allocation
> isn't correctly size-checked (e.g.  CVE-2021-3527).
> 
> Signed-off-by: Peter Maydell 

Reviewed-by: Francisco Iglesias 

> ---
>  hw/net/rocker/rocker_of_dpa.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/hw/net/rocker/rocker_of_dpa.c b/hw/net/rocker/rocker_of_dpa.c
> index dfe47544694..5e16056be66 100644
> --- a/hw/net/rocker/rocker_of_dpa.c
> +++ b/hw/net/rocker/rocker_of_dpa.c
> @@ -1043,7 +1043,7 @@ static void of_dpa_flow_ig_tbl(OfDpaFlowContext *fc, 
> uint32_t tbl_id)
>  static ssize_t of_dpa_ig(World *world, uint32_t pport,
>   const struct iovec *iov, int iovcnt)
>  {
> -struct iovec iov_copy[iovcnt + 2];
> +g_autofree struct iovec *iov_copy = g_new(struct iovec, iovcnt + 2);
>  OfDpaFlowContext fc = {
>  .of_dpa = world_private(world),
>  .in_pport = pport,
> -- 
> 2.34.1
> 
> 



[PATCH v3 4/8] hw/misc/xlnx-versal-cfu: Introduce a model of Xilinx Versal's CFU_SFR

2023-08-24 Thread Francisco Iglesias
Introduce a model of Xilinx Versal's Configuration Frame Unit's Single
Frame Read port (CFU_SFR).

Signed-off-by: Francisco Iglesias 
Reviewed-by: Peter Maydell 
---
 hw/misc/xlnx-versal-cfu.c | 87 +++
 include/hw/misc/xlnx-versal-cfu.h | 15 ++
 2 files changed, 102 insertions(+)

diff --git a/hw/misc/xlnx-versal-cfu.c b/hw/misc/xlnx-versal-cfu.c
index 255c1bf4b8..8e588ac1d8 100644
--- a/hw/misc/xlnx-versal-cfu.c
+++ b/hw/misc/xlnx-versal-cfu.c
@@ -264,6 +264,31 @@ static void cfu_stream_write(void *opaque, hwaddr addr, 
uint64_t value,
 }
 }
 
+static uint64_t cfu_sfr_read(void *opaque, hwaddr addr, unsigned size)
+{
+qemu_log_mask(LOG_GUEST_ERROR, "%s: Unsupported read from addr=%"
+  HWADDR_PRIx "\n", __func__, addr);
+return 0;
+}
+
+static void cfu_sfr_write(void *opaque, hwaddr addr, uint64_t value,
+  unsigned size)
+{
+XlnxVersalCFUSFR *s = XLNX_VERSAL_CFU_SFR(opaque);
+uint32_t wfifo[WFIFO_SZ];
+
+if (update_wfifo(addr, value, s->wfifo, wfifo)) {
+uint8_t row_addr = extract32(wfifo[0], 23, 5);
+uint32_t frame_addr = extract32(wfifo[0], 0, 23);
+XlnxCfiPacket pkt = { .reg_addr = CFRAME_SFR,
+  .data[0] = frame_addr };
+
+if (s->cfg.cfu) {
+cfu_transfer_cfi_packet(s->cfg.cfu, row_addr, );
+}
+}
+}
+
 static uint64_t cfu_fdro_read(void *opaque, hwaddr addr, unsigned size)
 {
 XlnxVersalCFUFDRO *s = XLNX_VERSAL_CFU_FDRO(opaque);
@@ -293,6 +318,16 @@ static const MemoryRegionOps cfu_stream_ops = {
 },
 };
 
+static const MemoryRegionOps cfu_sfr_ops = {
+.read = cfu_sfr_read,
+.write = cfu_sfr_write,
+.endianness = DEVICE_LITTLE_ENDIAN,
+.valid = {
+.min_access_size = 4,
+.max_access_size = 4,
+},
+};
+
 static const MemoryRegionOps cfu_fdro_ops = {
 .read = cfu_fdro_read,
 .write = cfu_fdro_write,
@@ -334,6 +369,23 @@ static void cfu_apb_init(Object *obj)
 sysbus_init_irq(sbd, >irq_cfu_imr);
 }
 
+static void cfu_sfr_init(Object *obj)
+{
+XlnxVersalCFUSFR *s = XLNX_VERSAL_CFU_SFR(obj);
+SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+
+memory_region_init_io(>iomem_sfr, obj, _sfr_ops, s,
+  TYPE_XLNX_VERSAL_CFU_SFR, KEYHOLE_STREAM_4K);
+sysbus_init_mmio(sbd, >iomem_sfr);
+}
+
+static void cfu_sfr_reset_enter(Object *obj, ResetType type)
+{
+XlnxVersalCFUSFR *s = XLNX_VERSAL_CFU_SFR(obj);
+
+memset(s->wfifo, 0, WFIFO_SZ * sizeof(uint32_t));
+}
+
 static void cfu_fdro_init(Object *obj)
 {
 XlnxVersalCFUFDRO *s = XLNX_VERSAL_CFU_FDRO(obj);
@@ -401,6 +453,12 @@ static Property cfu_props[] = {
 DEFINE_PROP_END_OF_LIST(),
 };
 
+static Property cfu_sfr_props[] = {
+DEFINE_PROP_LINK("cfu", XlnxVersalCFUSFR, cfg.cfu,
+ TYPE_XLNX_VERSAL_CFU_APB, XlnxVersalCFUAPB *),
+DEFINE_PROP_END_OF_LIST(),
+};
+
 static const VMStateDescription vmstate_cfu_apb = {
 .name = TYPE_XLNX_VERSAL_CFU_APB,
 .version_id = 1,
@@ -423,6 +481,16 @@ static const VMStateDescription vmstate_cfu_fdro = {
 }
 };
 
+static const VMStateDescription vmstate_cfu_sfr = {
+.name = TYPE_XLNX_VERSAL_CFU_SFR,
+.version_id = 1,
+.minimum_version_id = 1,
+.fields = (VMStateField[]) {
+VMSTATE_UINT32_ARRAY(wfifo, XlnxVersalCFUSFR, 4),
+VMSTATE_END_OF_LIST(),
+}
+};
+
 static void cfu_apb_class_init(ObjectClass *klass, void *data)
 {
 DeviceClass *dc = DEVICE_CLASS(klass);
@@ -443,6 +511,16 @@ static void cfu_fdro_class_init(ObjectClass *klass, void 
*data)
 rc->phases.enter = cfu_fdro_reset_enter;
 }
 
+static void cfu_sfr_class_init(ObjectClass *klass, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(klass);
+ResettableClass *rc = RESETTABLE_CLASS(klass);
+
+device_class_set_props(dc, cfu_sfr_props);
+dc->vmsd = _cfu_sfr;
+rc->phases.enter = cfu_sfr_reset_enter;
+}
+
 static const TypeInfo cfu_apb_info = {
 .name  = TYPE_XLNX_VERSAL_CFU_APB,
 .parent= TYPE_SYS_BUS_DEVICE,
@@ -467,10 +545,19 @@ static const TypeInfo cfu_fdro_info = {
 }
 };
 
+static const TypeInfo cfu_sfr_info = {
+.name  = TYPE_XLNX_VERSAL_CFU_SFR,
+.parent= TYPE_SYS_BUS_DEVICE,
+.instance_size = sizeof(XlnxVersalCFUSFR),
+.class_init= cfu_sfr_class_init,
+.instance_init = cfu_sfr_init,
+};
+
 static void cfu_apb_register_types(void)
 {
 type_register_static(_apb_info);
 type_register_static(_fdro_info);
+type_register_static(_sfr_info);
 }
 
 type_init(cfu_apb_register_types)
diff --git a/include/hw/misc/xlnx-versal-cfu.h 
b/include/hw/misc/xlnx-versal-cfu.h
index 73e9a21af4..86fb841053 100644
--- a/include/hw/misc/xlnx-versal-cfu.h
+++ b/include/hw/misc/xlnx-versal-cfu.h
@@ -28,6 +28,9 @@ OBJECT_DECLARE_SIMPLE_TYPE(XlnxVersalCFUAPB, 
XLNX_VER

[PATCH v3 7/8] hw/arm/xlnx-versal: Connect the CFU_APB, CFU_FDRO and CFU_SFR

2023-08-24 Thread Francisco Iglesias
Connect the Configuration Frame Unit (CFU_APB, CFU_FDRO and CFU_SFR) to
the Versal machine.

Signed-off-by: Francisco Iglesias 
Acked-by: Edgar E. Iglesias 
Reviewed-by: Peter Maydell 
---
 hw/arm/xlnx-versal.c | 42 
 include/hw/arm/xlnx-versal.h | 16 ++
 2 files changed, 58 insertions(+)

diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
index 60bf5fe657..3f4b4b1560 100644
--- a/hw/arm/xlnx-versal.c
+++ b/hw/arm/xlnx-versal.c
@@ -570,6 +570,47 @@ static void versal_create_ospi(Versal *s, qemu_irq *pic)
 qdev_connect_gpio_out(orgate, 0, pic[VERSAL_OSPI_IRQ]);
 }
 
+static void versal_create_cfu(Versal *s, qemu_irq *pic)
+{
+SysBusDevice *sbd;
+
+/* CFU FDRO */
+object_initialize_child(OBJECT(s), "cfu-fdro", >pmc.cfu_fdro,
+TYPE_XLNX_VERSAL_CFU_FDRO);
+sbd = SYS_BUS_DEVICE(>pmc.cfu_fdro);
+
+sysbus_realize(sbd, _fatal);
+memory_region_add_subregion(>mr_ps, MM_PMC_CFU_FDRO,
+sysbus_mmio_get_region(sbd, 0));
+
+/* CFU APB */
+object_initialize_child(OBJECT(s), "cfu-apb", >pmc.cfu_apb,
+TYPE_XLNX_VERSAL_CFU_APB);
+sbd = SYS_BUS_DEVICE(>pmc.cfu_apb);
+
+sysbus_realize(sbd, _fatal);
+memory_region_add_subregion(>mr_ps, MM_PMC_CFU_APB,
+sysbus_mmio_get_region(sbd, 0));
+memory_region_add_subregion(>mr_ps, MM_PMC_CFU_STREAM,
+sysbus_mmio_get_region(sbd, 1));
+memory_region_add_subregion(>mr_ps, MM_PMC_CFU_STREAM_2,
+sysbus_mmio_get_region(sbd, 2));
+sysbus_connect_irq(sbd, 0, pic[VERSAL_CFU_IRQ_0]);
+
+/* CFU SFR */
+object_initialize_child(OBJECT(s), "cfu-sfr", >pmc.cfu_sfr,
+TYPE_XLNX_VERSAL_CFU_SFR);
+
+sbd = SYS_BUS_DEVICE(>pmc.cfu_sfr);
+
+object_property_set_link(OBJECT(>pmc.cfu_sfr),
+"cfu", OBJECT(>pmc.cfu_apb), _abort);
+
+sysbus_realize(sbd, _fatal);
+memory_region_add_subregion(>mr_ps, MM_PMC_CFU_SFR,
+sysbus_mmio_get_region(sbd, 0));
+}
+
 static void versal_create_crl(Versal *s, qemu_irq *pic)
 {
 SysBusDevice *sbd;
@@ -763,6 +804,7 @@ static void versal_realize(DeviceState *dev, Error **errp)
 versal_create_pmc_iou_slcr(s, pic);
 versal_create_ospi(s, pic);
 versal_create_crl(s, pic);
+versal_create_cfu(s, pic);
 versal_map_ddr(s);
 versal_unimp(s);
 
diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
index 39ee31185c..29b9c60301 100644
--- a/include/hw/arm/xlnx-versal.h
+++ b/include/hw/arm/xlnx-versal.h
@@ -32,6 +32,7 @@
 #include "hw/misc/xlnx-versal-crl.h"
 #include "hw/misc/xlnx-versal-pmc-iou-slcr.h"
 #include "hw/net/xlnx-versal-canfd.h"
+#include "hw/misc/xlnx-versal-cfu.h"
 
 #define TYPE_XLNX_VERSAL "xlnx-versal"
 OBJECT_DECLARE_SIMPLE_TYPE(Versal, XLNX_VERSAL)
@@ -117,6 +118,9 @@ struct Versal {
 XlnxEFuse efuse;
 XlnxVersalEFuseCtrl efuse_ctrl;
 XlnxVersalEFuseCache efuse_cache;
+XlnxVersalCFUAPB cfu_apb;
+XlnxVersalCFUFDRO cfu_fdro;
+XlnxVersalCFUSFR cfu_sfr;
 
 OrIRQState apb_irq_orgate;
 } pmc;
@@ -147,6 +151,7 @@ struct Versal {
 #define VERSAL_GEM1_WAKE_IRQ_0 59
 #define VERSAL_ADMA_IRQ_0  60
 #define VERSAL_XRAM_IRQ_0  79
+#define VERSAL_CFU_IRQ_0   120
 #define VERSAL_PMC_APB_IRQ 121
 #define VERSAL_OSPI_IRQ124
 #define VERSAL_SD0_IRQ_0   126
@@ -240,6 +245,17 @@ struct Versal {
 #define MM_PMC_EFUSE_CACHE  0xf125
 #define MM_PMC_EFUSE_CACHE_SIZE 0x00C00
 
+#define MM_PMC_CFU_APB  0xf12b
+#define MM_PMC_CFU_APB_SIZE 0x1
+#define MM_PMC_CFU_STREAM   0xf12c
+#define MM_PMC_CFU_STREAM_SIZE  0x1000
+#define MM_PMC_CFU_SFR  0xf12c1000
+#define MM_PMC_CFU_SFR_SIZE 0x1000
+#define MM_PMC_CFU_FDRO 0xf12c2000
+#define MM_PMC_CFU_FDRO_SIZE0x1000
+#define MM_PMC_CFU_STREAM_2 0xf1f8
+#define MM_PMC_CFU_STREAM_2_SIZE0x4
+
 #define MM_PMC_CRP  0xf126U
 #define MM_PMC_CRP_SIZE 0x1
 #define MM_PMC_RTC  0xf12a
-- 
2.34.1




[PATCH v3 1/8] hw/misc: Introduce the Xilinx CFI interface

2023-08-24 Thread Francisco Iglesias
Introduce the Xilinx Configuration Frame Interface (CFI) for transmitting
CFI data packets between the Xilinx Configuration Frame Unit models
(CFU_APB, CFU_FDRO and CFU_SFR), the Xilinx CFRAME controller (CFRAME_REG)
and the Xilinx CFRAME broadcast controller (CFRAME_BCAST_REG) models (when
emulating bitstream programming and readback).

Signed-off-by: Francisco Iglesias 
Reviewed-by: Sai Pavan Boddu 
Acked-by: Edgar E. Iglesias 
---
 MAINTAINERS   |  6 
 hw/misc/meson.build   |  1 +
 hw/misc/xlnx-cfi-if.c | 34 
 include/hw/misc/xlnx-cfi-if.h | 59 +++
 4 files changed, 100 insertions(+)
 create mode 100644 hw/misc/xlnx-cfi-if.c
 create mode 100644 include/hw/misc/xlnx-cfi-if.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 6111b6b4d9..e0cd365462 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1034,6 +1034,12 @@ S: Maintained
 F: hw/ssi/xlnx-versal-ospi.c
 F: include/hw/ssi/xlnx-versal-ospi.h
 
+Xilinx Versal CFI
+M: Francisco Iglesias 
+S: Maintained
+F: hw/misc/xlnx-cfi-if.c
+F: include/hw/misc/xlnx-cfi-if.h
+
 STM32F100
 M: Alexandre Iooss 
 L: qemu-...@nongnu.org
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
index 892f8b91c5..0c562f5e3e 100644
--- a/hw/misc/meson.build
+++ b/hw/misc/meson.build
@@ -97,6 +97,7 @@ specific_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: 
files('xlnx-versal-crl.c'))
 system_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files(
   'xlnx-versal-xramc.c',
   'xlnx-versal-pmc-iou-slcr.c',
+  'xlnx-cfi-if.c',
 ))
 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'))
diff --git a/hw/misc/xlnx-cfi-if.c b/hw/misc/xlnx-cfi-if.c
new file mode 100644
index 00..c45f05c4aa
--- /dev/null
+++ b/hw/misc/xlnx-cfi-if.c
@@ -0,0 +1,34 @@
+/*
+ * Xilinx CFI interface
+ *
+ * Copyright (C) 2023, Advanced Micro Devices, Inc.
+ *
+ * Written by Francisco Iglesias 
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#include "qemu/osdep.h"
+#include "hw/misc/xlnx-cfi-if.h"
+
+void xlnx_cfi_transfer_packet(XlnxCfiIf *cfi_if, XlnxCfiPacket *pkt)
+{
+XlnxCfiIfClass *xcic = XLNX_CFI_IF_GET_CLASS(cfi_if);
+
+if (xcic->cfi_transfer_packet) {
+xcic->cfi_transfer_packet(cfi_if, pkt);
+}
+}
+
+static const TypeInfo xlnx_cfi_if_info = {
+.name  = TYPE_XLNX_CFI_IF,
+.parent= TYPE_INTERFACE,
+.class_size = sizeof(XlnxCfiIfClass),
+};
+
+static void xlnx_cfi_if_register_types(void)
+{
+type_register_static(_cfi_if_info);
+}
+
+type_init(xlnx_cfi_if_register_types)
+
diff --git a/include/hw/misc/xlnx-cfi-if.h b/include/hw/misc/xlnx-cfi-if.h
new file mode 100644
index 00..f9bd12292d
--- /dev/null
+++ b/include/hw/misc/xlnx-cfi-if.h
@@ -0,0 +1,59 @@
+/*
+ * Xilinx CFI interface
+ *
+ * Copyright (C) 2023, Advanced Micro Devices, Inc.
+ *
+ * Written by Francisco Iglesias 
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#ifndef XLNX_CFI_IF_H
+#define XLNX_CFI_IF_H 1
+
+#include "qemu/help-texts.h"
+#include "hw/hw.h"
+#include "qom/object.h"
+
+#define TYPE_XLNX_CFI_IF "xlnx-cfi-if"
+typedef struct XlnxCfiIfClass XlnxCfiIfClass;
+DECLARE_CLASS_CHECKERS(XlnxCfiIfClass, XLNX_CFI_IF, TYPE_XLNX_CFI_IF)
+
+#define XLNX_CFI_IF(obj) \
+ INTERFACE_CHECK(XlnxCfiIf, (obj), TYPE_XLNX_CFI_IF)
+
+typedef enum {
+PACKET_TYPE_CFU = 0x52,
+PACKET_TYPE_CFRAME = 0xA1,
+} xlnx_cfi_packet_type;
+
+typedef enum {
+CFRAME_FAR = 1,
+CFRAME_SFR = 2,
+CFRAME_FDRI = 4,
+CFRAME_CMD = 6,
+} xlnx_cfi_reg_addr;
+
+typedef struct XlnxCfiPacket {
+uint8_t reg_addr;
+uint32_t data[4];
+} XlnxCfiPacket;
+
+typedef struct XlnxCfiIf {
+Object Parent;
+} XlnxCfiIf;
+
+typedef struct XlnxCfiIfClass {
+InterfaceClass parent;
+
+void (*cfi_transfer_packet)(XlnxCfiIf *cfi_if, XlnxCfiPacket *pkt);
+} XlnxCfiIfClass;
+
+/**
+ * Transfer a XlnxCfiPacket.
+ *
+ * @cfi_if: the object implementing this interface
+ * @XlnxCfiPacket: a pointer to the XlnxCfiPacket to transfer
+ */
+void xlnx_cfi_transfer_packet(XlnxCfiIf *cfi_if, XlnxCfiPacket *pkt);
+
+#endif /* XLNX_CFI_IF_H */
-- 
2.34.1




[PATCH v3 5/8] hw/misc: Introduce a model of Xilinx Versal's CFRAME_REG

2023-08-24 Thread Francisco Iglesias
Introduce a model of Xilinx Versal's Configuration Frame controller
(CFRAME_REG).

Signed-off-by: Francisco Iglesias 
---
 MAINTAINERS  |   2 +
 hw/misc/meson.build  |   1 +
 hw/misc/xlnx-versal-cframe-reg.c | 685 +++
 include/hw/misc/xlnx-versal-cframe-reg.h | 286 ++
 4 files changed, 974 insertions(+)
 create mode 100644 hw/misc/xlnx-versal-cframe-reg.c
 create mode 100644 include/hw/misc/xlnx-versal-cframe-reg.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 847b997d73..645374c1d9 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1041,6 +1041,8 @@ F: hw/misc/xlnx-cfi-if.c
 F: include/hw/misc/xlnx-cfi-if.h
 F: hw/misc/xlnx-versal-cfu.c
 F: include/hw/misc/xlnx-versal-cfu.h
+F: hw/misc/xlnx-versal-cframe-reg.c
+F: include/hw/misc/xlnx-versal-cframe-reg.h
 
 STM32F100
 M: Alexandre Iooss 
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
index d95cc3fd87..1b425b03bd 100644
--- a/hw/misc/meson.build
+++ b/hw/misc/meson.build
@@ -99,6 +99,7 @@ system_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files(
   'xlnx-versal-pmc-iou-slcr.c',
   'xlnx-versal-cfu.c',
   'xlnx-cfi-if.c',
+  'xlnx-versal-cframe-reg.c',
 ))
 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'))
diff --git a/hw/misc/xlnx-versal-cframe-reg.c b/hw/misc/xlnx-versal-cframe-reg.c
new file mode 100644
index 00..4c9afb184d
--- /dev/null
+++ b/hw/misc/xlnx-versal-cframe-reg.c
@@ -0,0 +1,685 @@
+/*
+ * QEMU model of the Configuration Frame Control module
+ *
+ * Copyright (C) 2023, Advanced Micro Devices, Inc.
+ *
+ * Written by Francisco Iglesias 
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "hw/sysbus.h"
+#include "hw/register.h"
+#include "hw/registerfields.h"
+#include "qemu/bitops.h"
+#include "qemu/log.h"
+#include "qemu/units.h"
+#include "qapi/error.h"
+#include "hw/qdev-properties.h"
+#include "migration/vmstate.h"
+#include "hw/irq.h"
+#include "hw/misc/xlnx-versal-cframe-reg.h"
+
+#ifndef XLNX_VERSAL_CFRAME_REG_ERR_DEBUG
+#define XLNX_VERSAL_CFRAME_REG_ERR_DEBUG 0
+#endif
+
+#define KEYHOLE_STREAM_4K (4 * KiB)
+#define N_WORDS_128BIT 4
+
+#define MAX_BLOCKTYPE 6
+#define MAX_BLOCKTYPE_FRAMES 0xF
+
+enum {
+CFRAME_CMD_WCFG = 1,
+CFRAME_CMD_ROWON = 2,
+CFRAME_CMD_ROWOFF = 3,
+CFRAME_CMD_RCFG = 4,
+CFRAME_CMD_DLPARK = 5,
+};
+
+static gint int_cmp(gconstpointer a, gconstpointer b, gpointer user_data)
+{
+guint ua = GPOINTER_TO_UINT(a);
+guint ub = GPOINTER_TO_UINT(b);
+return (ua > ub) - (ua < ub);
+}
+
+static void cfrm_imr_update_irq(XlnxVersalCFrameReg *s)
+{
+bool pending = s->regs[R_CFRM_ISR0] & ~s->regs[R_CFRM_IMR0];
+qemu_set_irq(s->irq_cfrm_imr, pending);
+}
+
+static void cfrm_isr_postw(RegisterInfo *reg, uint64_t val64)
+{
+XlnxVersalCFrameReg *s = XLNX_VERSAL_CFRAME_REG(reg->opaque);
+cfrm_imr_update_irq(s);
+}
+
+static uint64_t cfrm_ier_prew(RegisterInfo *reg, uint64_t val64)
+{
+XlnxVersalCFrameReg *s = XLNX_VERSAL_CFRAME_REG(reg->opaque);
+
+s->regs[R_CFRM_IMR0] &= ~s->regs[R_CFRM_IER0];
+s->regs[R_CFRM_IER0] = 0;
+cfrm_imr_update_irq(s);
+return 0;
+}
+
+static uint64_t cfrm_idr_prew(RegisterInfo *reg, uint64_t val64)
+{
+XlnxVersalCFrameReg *s = XLNX_VERSAL_CFRAME_REG(reg->opaque);
+
+s->regs[R_CFRM_IMR0] |= s->regs[R_CFRM_IDR0];
+s->regs[R_CFRM_IDR0] = 0;
+cfrm_imr_update_irq(s);
+return 0;
+}
+
+static uint64_t cfrm_itr_prew(RegisterInfo *reg, uint64_t val64)
+{
+XlnxVersalCFrameReg *s = XLNX_VERSAL_CFRAME_REG(reg->opaque);
+
+s->regs[R_CFRM_ISR0] |= s->regs[R_CFRM_ITR0];
+s->regs[R_CFRM_ITR0] = 0;
+cfrm_imr_update_irq(s);
+return 0;
+}
+
+static void cframe_incr_far(XlnxVersalCFrameReg *s)
+{
+uint32_t faddr = ARRAY_FIELD_EX32(s->regs, FAR0, FRAME_ADDR);
+uint32_t blktype = ARRAY_FIELD_EX32(s->regs, FAR0, BLOCKTYPE);
+
+assert(blktype <= MAX_BLOCKTYPE);
+
+faddr++;
+if (faddr > s->cfg.blktype_num_frames[blktype]) {
+/* Restart from 0 and increment block type */
+faddr = 0;
+blktype++;
+
+assert(blktype <= MAX_BLOCKTYPE);
+
+ARRAY_FIELD_DP32(s->regs, FAR0, BLOCKTYPE, blktype);
+}
+
+ARRAY_FIELD_DP32(s->regs, FAR0, FRAME_ADDR, faddr);
+}
+
+static void cfrm_fdri_post_write(RegisterInfo *reg, uint64_t val)
+{
+XlnxVersalCFrameReg *s = XLNX_VERSAL_CFRAME_REG(reg->opaque);
+
+if (s->row_configured && s->rowon && s->wcfg) {
+
+if (fifo32_num_free(>new_f_data) >= N_WORDS_128BIT) {
+fifo32_push(>new_f_data,

Re: [PATCH v2 5/8] hw/misc: Introduce a model of Xilinx Versal's CFRAME_REG

2023-08-24 Thread Francisco Iglesias

Hi Peter,

On 2023-08-21 15:34, Peter Maydell wrote:

On Thu, 10 Aug 2023 at 20:16, Francisco Iglesias
 wrote:


Introduce a model of Xilinx Versal's Configuration Frame controller
(CFRAME_REG).

Signed-off-by: Francisco Iglesias 
---
  MAINTAINERS  |   2 +
  hw/misc/meson.build  |   1 +
  hw/misc/xlnx-versal-cframe-reg.c | 753 +++
  include/hw/misc/xlnx-versal-cframe-reg.h | 289 +
  4 files changed, 1045 insertions(+)
  create mode 100644 hw/misc/xlnx-versal-cframe-reg.c
  create mode 100644 include/hw/misc/xlnx-versal-cframe-reg.h



+static XlnxCFrame *cframes_get_frame(XlnxVersalCFrameReg *s, uint32_t addr)
+{
+for (int i = 0; i < s->cframes->len; i++) {
+XlnxCFrame *f = _array_index(s->cframes, XlnxCFrame, i);
+
+if (f->addr == addr) {
+return f;
+}
+}
+return NULL;
+}


The handling of this and especially how it turns out in
the migration support still feels quite awkward to me.

The operations we want here seem to be:
  * find a cframe given the 'addr'
  * insert a new cframe for a given 'addr', overwriting any
old data
  * iterate through n cframes starting at a given 'addr'

You can do this with a GTree
https://developer-old.gnome.org/glib/stable/glib-Balanced-Binary-Trees.html
You can use GUINT_TO_POINTER(addr) as the keys, and use
a Fifo32 as your data. Insert-with-overwrite is
g_tree_replace_node(). Find-a-frame is g_tree_lookup().
Iterate through n cframes is
  for (node = g_tree_lookup(...), i = 0; i < n; node =
g_tree_node_next(node), i++) {
 ...
  }

GTrees are supported by the migration code, there is a
VMSTATE_GTREE_DIRECT_KEY_V() macro, so you don't need to
do any pre-save or post-load hooks. (This to me is one
of the main benefits of using it rather than a GArray.)

Is the data in each cframe fixed-size, or can it vary?
The impression I get is that each cframe is always the
same amount of data, and we use a fifo purely to handle
the "guest writes the frame data a word at a time and
when it's all arrived we put it into the cframe data
structure". If so, it might be simpler to use a fifo32
for the new_f, but have the data in the gtree structure
be a simple fixed-size block of memory.



Thank you very much for the suggestionA I'll switch to a GTree in v3! 
(And it is correct above, both regarding required operations and that 
the cframes are fixed sized).



+
+static void cframe_alloc(XlnxCFrame *f)
+{
+f->addr = 0;
+fifo32_create(>data, FRAME_NUM_WORDS);
+}
+
+static void cframe_move(XlnxCFrame *dst, XlnxCFrame *src)
+{
+fifo32_destroy(>data);
+dst[0] = src[0];
+}
+
+static void cfrm_fdri_post_write(RegisterInfo *reg, uint64_t val)
+{
+XlnxVersalCFrameReg *s = XLNX_VERSAL_CFRAME_REG(reg->opaque);
+
+if (s->row_configured && s->rowon && s->wcfg) {
+XlnxCFrame *new_f = >new_f;
+
+if (fifo32_num_free(_f->data) >= N_WORDS_128BIT) {
+fifo32_push(_f->data, s->regs[R_FDRI0]);
+fifo32_push(_f->data, s->regs[R_FDRI1]);
+fifo32_push(_f->data, s->regs[R_FDRI2]);
+fifo32_push(_f->data, s->regs[R_FDRI3]);
+}
+
+if (fifo32_is_full(_f->data)) {
+XlnxCFrame *cur_f;
+
+/* Include block type and frame address */
+new_f->addr = extract32(s->regs[R_FAR0], 0, 23);
+
+cur_f = cframes_get_frame(s, new_f->addr);
+
+if (cur_f) {
+cframe_move(cur_f, new_f);
+} else {
+g_array_append_val(s->cframes, new_f[0]);
+}
+
+cframe_incr_far(s);
+
+/* Realloc new_f */
+cframe_alloc(new_f);
+}
+}
+}
+
+static void cfrm_readout_frames(XlnxVersalCFrameReg *s, uint32_t start_addr,
+uint32_t end_addr)
+{
+for (uint32_t addr = start_addr; addr < end_addr; addr++) {
+XlnxCFrame *f = cframes_get_frame(s, addr);
+
+/* Transmit the data if a frame was found */
+if (f) {
+Fifo32 data = f->data;
+
+while (!fifo32_is_empty()) {
+XlnxCfiPacket pkt = {};
+
+g_assert(fifo32_num_used() >= N_WORDS_128BIT);
+
+pkt.data[0] = fifo32_pop();
+pkt.data[1] = fifo32_pop();
+pkt.data[2] = fifo32_pop();
+pkt.data[3] = fifo32_pop();
+
+if (s->cfg.cfu_fdro) {
+xlnx_cfi_transfer_packet(s->cfg.cfu_fdro, );
+}
+}
+}
+}
+}
+
+static void cfrm_frcnt_post_write(RegisterInfo *reg, uint64_t val)
+{
+XlnxVersalCFrameReg *s = XLNX_VERSAL_CFRAME_REG(reg->opaque);
+
+if (s->row_configured && s->rowon && s->rcfg) {
+uint32_t start_addr = ext

[PATCH v3 6/8] hw/misc: Introduce a model of Xilinx Versal's CFRAME_BCAST_REG

2023-08-24 Thread Francisco Iglesias
Introduce a model of Xilinx Versal's Configuration Frame broadcast
controller (CFRAME_BCAST_REG).

Signed-off-by: Francisco Iglesias 
Reviewed-by: Peter Maydell 
---
 hw/misc/xlnx-versal-cframe-reg.c | 161 +++
 include/hw/misc/xlnx-versal-cframe-reg.h |  17 +++
 2 files changed, 178 insertions(+)

diff --git a/hw/misc/xlnx-versal-cframe-reg.c b/hw/misc/xlnx-versal-cframe-reg.c
index 4c9afb184d..2ce62c1b2e 100644
--- a/hw/misc/xlnx-versal-cframe-reg.c
+++ b/hw/misc/xlnx-versal-cframe-reg.c
@@ -557,6 +557,83 @@ static const MemoryRegionOps cframe_reg_fdri_ops = {
 },
 };
 
+static uint64_t cframes_bcast_reg_read(void *opaque, hwaddr addr, unsigned 
size)
+{
+qemu_log_mask(LOG_GUEST_ERROR, "%s: Unsupported read from addr=%"
+  HWADDR_PRIx "\n", __func__, addr);
+return 0;
+}
+
+static void cframes_bcast_write(XlnxVersalCFrameBcastReg *s, uint8_t reg_addr,
+uint32_t *wfifo)
+{
+XlnxCfiPacket pkt = {
+.reg_addr = reg_addr,
+.data[0] = wfifo[0],
+.data[1] = wfifo[1],
+.data[2] = wfifo[2],
+.data[3] = wfifo[3]
+};
+
+for (int i = 0; i < ARRAY_SIZE(s->cfg.cframe); i++) {
+if (s->cfg.cframe[i]) {
+xlnx_cfi_transfer_packet(s->cfg.cframe[i], );
+}
+}
+}
+
+static void cframes_bcast_reg_write(void *opaque, hwaddr addr, uint64_t value,
+  unsigned size)
+{
+XlnxVersalCFrameBcastReg *s = XLNX_VERSAL_CFRAME_BCAST_REG(opaque);
+uint32_t wfifo[WFIFO_SZ];
+
+if (update_wfifo(addr, value, s->wfifo, wfifo)) {
+uint8_t reg_addr = extract32(addr, 4, 6);
+
+cframes_bcast_write(s, reg_addr, wfifo);
+}
+}
+
+static uint64_t cframes_bcast_fdri_read(void *opaque, hwaddr addr,
+unsigned size)
+{
+qemu_log_mask(LOG_GUEST_ERROR, "%s: Unsupported read from addr=%"
+  HWADDR_PRIx "\n", __func__, addr);
+return 0;
+}
+
+static void cframes_bcast_fdri_write(void *opaque, hwaddr addr, uint64_t value,
+  unsigned size)
+{
+XlnxVersalCFrameBcastReg *s = XLNX_VERSAL_CFRAME_BCAST_REG(opaque);
+uint32_t wfifo[WFIFO_SZ];
+
+if (update_wfifo(addr, value, s->wfifo, wfifo)) {
+cframes_bcast_write(s, CFRAME_FDRI, wfifo);
+}
+}
+
+static const MemoryRegionOps cframes_bcast_reg_reg_ops = {
+.read = cframes_bcast_reg_read,
+.write = cframes_bcast_reg_write,
+.endianness = DEVICE_LITTLE_ENDIAN,
+.valid = {
+.min_access_size = 4,
+.max_access_size = 4,
+},
+};
+
+static const MemoryRegionOps cframes_bcast_reg_fdri_ops = {
+.read = cframes_bcast_fdri_read,
+.write = cframes_bcast_fdri_write,
+.endianness = DEVICE_LITTLE_ENDIAN,
+.valid = {
+.min_access_size = 4,
+.max_access_size = 4,
+},
+};
+
 static void cframe_reg_realize(DeviceState *dev, Error **errp)
 {
 XlnxVersalCFrameReg *s = XLNX_VERSAL_CFRAME_REG(dev);
@@ -651,6 +728,71 @@ static Property cframe_regs_props[] = {
 DEFINE_PROP_END_OF_LIST(),
 };
 
+static void cframe_bcast_reg_init(Object *obj)
+{
+XlnxVersalCFrameBcastReg *s = XLNX_VERSAL_CFRAME_BCAST_REG(obj);
+SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+
+memory_region_init_io(>iomem_reg, obj, _bcast_reg_reg_ops, s,
+  TYPE_XLNX_VERSAL_CFRAME_BCAST_REG, 
KEYHOLE_STREAM_4K);
+memory_region_init_io(>iomem_fdri, obj, _bcast_reg_fdri_ops, s,
+  TYPE_XLNX_VERSAL_CFRAME_BCAST_REG "-fdri",
+  KEYHOLE_STREAM_4K);
+sysbus_init_mmio(sbd, >iomem_reg);
+sysbus_init_mmio(sbd, >iomem_fdri);
+}
+
+static void cframe_bcast_reg_reset_enter(Object *obj, ResetType type)
+{
+XlnxVersalCFrameBcastReg *s = XLNX_VERSAL_CFRAME_BCAST_REG(obj);
+
+memset(s->wfifo, 0, WFIFO_SZ * sizeof(uint32_t));
+}
+
+static const VMStateDescription vmstate_cframe_bcast_reg = {
+.name = TYPE_XLNX_VERSAL_CFRAME_BCAST_REG,
+.version_id = 1,
+.minimum_version_id = 1,
+.fields = (VMStateField[]) {
+VMSTATE_UINT32_ARRAY(wfifo, XlnxVersalCFrameBcastReg, 4),
+VMSTATE_END_OF_LIST(),
+}
+};
+
+static Property cframe_bcast_regs_props[] = {
+DEFINE_PROP_LINK("cframe0", XlnxVersalCFrameBcastReg, cfg.cframe[0],
+ TYPE_XLNX_CFI_IF, XlnxCfiIf *),
+DEFINE_PROP_LINK("cframe1", XlnxVersalCFrameBcastReg, cfg.cframe[1],
+ TYPE_XLNX_CFI_IF, XlnxCfiIf *),
+DEFINE_PROP_LINK("cframe2", XlnxVersalCFrameBcastReg, cfg.cframe[2],
+ TYPE_XLNX_CFI_IF, XlnxCfiIf *),
+DEFINE_PROP_LINK("cframe3", XlnxVersalCFrameBcastReg, cfg.cframe[3],
+ TYPE_XLNX_CFI_IF, XlnxCfiIf *),
+DEFINE_PROP_LINK("cframe4", XlnxVersalCFrameBcastReg, cfg.cfr

[PATCH v3 0/8] Xilinx Versal CFI support

2023-08-24 Thread Francisco Iglesias
Hi,

This series adds support for the Configuration Frame Unit (CFU) and the
Configuration Frame controllers (CFRAME) to the Xilinx Versal machine
([1], chapter 21) for emulaing bitstream loading and readback.

The series starts by introducing the Xilinx CFI interface that is
thereafter used by the Xilinx CFU components, the Xilinx CFRAME and Xilinx
CFRAME broadcast models for transfering CFI packets between each other.
Thereafter a model of the CFU_APB, CFU_FDRO and CFU_SFR are introduced and
also models of the CFRAME controller and CFRAME broadcast controller.

The series thereafter ends with connecting the models to Xilinx Versal
machine.

Best regards,
Francisco Iglesias

References:
[1] https://docs.xilinx.com/r/en-US/am011-versal-acap-trm/PSM-Local-Registers


Changelog:
v2->v3:
 [PATCH 5]
   * Swap to store the CFrames in a GTree instead of GArray
   * Rename new_f to new_f_data and also add it to the vmstate 
   * Removed unnecessary 'switch' braces in cframe_reg_cfi_transfer_packet
   * Correct the reset of new_f_data and the cframes GTree


v1->v2:
 [PATCH 2]
   * Use KiB when defining KEYHOLE_STREAM_4K/KEYHOLE_STREAM_256K
   * Updated to be able to share wfifo code 
 [PATCH 3]
   * Swap to use Fifo32 instead of GArray in the CFU_FDRO model
   * Add device reset to the CFU_FDRO model
 [PATCH 4]
   * Add device reset to the CFU_SFR model
 [PATCH 5]
   * Use KiB when defining KEYHOLE_STREAM_4K
   * Add comma after CFRAME_CMD_DLPARK
   * Remove backwards compatibility comment (and the 'cfu' alias propname for
 cfg.cfu_fdro)
   * Use Fifo32 inside the XlnxCFrame structure
   * Reworked cframes_reg_pre_save / cframes_reg_post_load
 [PATCH 6]
   * Add device reset to the CFrame broadcast reg model
 [PATCH 8]
   * Switch to use g_autofree instead of explicit g_free


Francisco Iglesias (8):
  hw/misc: Introduce the Xilinx CFI interface
  hw/misc: Introduce a model of Xilinx Versal's CFU_APB
  hw/misc/xlnx-versal-cfu: Introduce a model of Xilinx Versal CFU_FDRO
  hw/misc/xlnx-versal-cfu: Introduce a model of Xilinx Versal's CFU_SFR
  hw/misc: Introduce a model of Xilinx Versal's CFRAME_REG
  hw/misc: Introduce a model of Xilinx Versal's CFRAME_BCAST_REG
  hw/arm/xlnx-versal: Connect the CFU_APB, CFU_FDRO and CFU_SFR
  hw/arm/versal: Connect the CFRAME_REG and CFRAME_BCAST_REG

 MAINTAINERS  |  10 +
 hw/arm/xlnx-versal.c | 155 -
 hw/misc/meson.build  |   3 +
 hw/misc/xlnx-cfi-if.c|  34 +
 hw/misc/xlnx-versal-cframe-reg.c | 846 +++
 hw/misc/xlnx-versal-cfu.c| 563 +++
 include/hw/arm/xlnx-versal.h |  85 +++
 include/hw/misc/xlnx-cfi-if.h|  59 ++
 include/hw/misc/xlnx-versal-cframe-reg.h | 303 
 include/hw/misc/xlnx-versal-cfu.h| 258 +++
 10 files changed, 2315 insertions(+), 1 deletion(-)
 create mode 100644 hw/misc/xlnx-cfi-if.c
 create mode 100644 hw/misc/xlnx-versal-cframe-reg.c
 create mode 100644 hw/misc/xlnx-versal-cfu.c
 create mode 100644 include/hw/misc/xlnx-cfi-if.h
 create mode 100644 include/hw/misc/xlnx-versal-cframe-reg.h
 create mode 100644 include/hw/misc/xlnx-versal-cfu.h

-- 
2.34.1




[PATCH v3 2/8] hw/misc: Introduce a model of Xilinx Versal's CFU_APB

2023-08-24 Thread Francisco Iglesias
Introduce a model of the software programming interface (CFU_APB) of
Xilinx Versal's Configuration Frame Unit.

Signed-off-by: Francisco Iglesias 
Reviewed-by: Peter Maydell 
---
 MAINTAINERS   |   2 +
 hw/misc/meson.build   |   1 +
 hw/misc/xlnx-versal-cfu.c | 380 ++
 include/hw/misc/xlnx-versal-cfu.h | 231 ++
 4 files changed, 614 insertions(+)
 create mode 100644 hw/misc/xlnx-versal-cfu.c
 create mode 100644 include/hw/misc/xlnx-versal-cfu.h

diff --git a/MAINTAINERS b/MAINTAINERS
index e0cd365462..847b997d73 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1039,6 +1039,8 @@ M: Francisco Iglesias 
 S: Maintained
 F: hw/misc/xlnx-cfi-if.c
 F: include/hw/misc/xlnx-cfi-if.h
+F: hw/misc/xlnx-versal-cfu.c
+F: include/hw/misc/xlnx-versal-cfu.h
 
 STM32F100
 M: Alexandre Iooss 
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
index 0c562f5e3e..d95cc3fd87 100644
--- a/hw/misc/meson.build
+++ b/hw/misc/meson.build
@@ -97,6 +97,7 @@ specific_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: 
files('xlnx-versal-crl.c'))
 system_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files(
   'xlnx-versal-xramc.c',
   'xlnx-versal-pmc-iou-slcr.c',
+  'xlnx-versal-cfu.c',
   'xlnx-cfi-if.c',
 ))
 system_ss.add(when: 'CONFIG_STM32F2XX_SYSCFG', if_true: 
files('stm32f2xx_syscfg.c'))
diff --git a/hw/misc/xlnx-versal-cfu.c b/hw/misc/xlnx-versal-cfu.c
new file mode 100644
index 00..b2dc6ab211
--- /dev/null
+++ b/hw/misc/xlnx-versal-cfu.c
@@ -0,0 +1,380 @@
+/*
+ * QEMU model of the CFU Configuration Unit.
+ *
+ * Copyright (C) 2023, Advanced Micro Devices, Inc.
+ *
+ * Written by Edgar E. Iglesias ,
+ *Sai Pavan Boddu ,
+ *Francisco Iglesias 
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "hw/sysbus.h"
+#include "hw/register.h"
+#include "hw/irq.h"
+#include "qemu/bitops.h"
+#include "qemu/log.h"
+#include "qemu/units.h"
+#include "migration/vmstate.h"
+#include "hw/qdev-properties.h"
+#include "hw/qdev-properties-system.h"
+#include "hw/misc/xlnx-versal-cfu.h"
+
+#ifndef XLNX_VERSAL_CFU_APB_ERR_DEBUG
+#define XLNX_VERSAL_CFU_APB_ERR_DEBUG 0
+#endif
+
+#define KEYHOLE_STREAM_4K (4 * KiB)
+#define KEYHOLE_STREAM_256K (256 * KiB)
+#define CFRAME_BROADCAST_ROW 0x1F
+
+bool update_wfifo(hwaddr addr, uint64_t value,
+  uint32_t *wfifo, uint32_t *wfifo_ret)
+{
+unsigned int idx = extract32(addr, 2, 2);
+
+wfifo[idx] = value;
+
+if (idx == 3) {
+memcpy(wfifo_ret, wfifo, WFIFO_SZ * sizeof(uint32_t));
+memset(wfifo, 0, WFIFO_SZ * sizeof(uint32_t));
+return true;
+}
+
+return false;
+}
+
+static void cfu_imr_update_irq(XlnxVersalCFUAPB *s)
+{
+bool pending = s->regs[R_CFU_ISR] & ~s->regs[R_CFU_IMR];
+qemu_set_irq(s->irq_cfu_imr, pending);
+}
+
+static void cfu_isr_postw(RegisterInfo *reg, uint64_t val64)
+{
+XlnxVersalCFUAPB *s = XLNX_VERSAL_CFU_APB(reg->opaque);
+cfu_imr_update_irq(s);
+}
+
+static uint64_t cfu_ier_prew(RegisterInfo *reg, uint64_t val64)
+{
+XlnxVersalCFUAPB *s = XLNX_VERSAL_CFU_APB(reg->opaque);
+uint32_t val = val64;
+
+s->regs[R_CFU_IMR] &= ~val;
+cfu_imr_update_irq(s);
+return 0;
+}
+
+static uint64_t cfu_idr_prew(RegisterInfo *reg, uint64_t val64)
+{
+XlnxVersalCFUAPB *s = XLNX_VERSAL_CFU_APB(reg->opaque);
+uint32_t val = val64;
+
+s->regs[R_CFU_IMR] |= val;
+cfu_imr_update_irq(s);
+return 0;
+}
+
+static uint64_t cfu_itr_prew(RegisterInfo *reg, uint64_t val64)
+{
+XlnxVersalCFUAPB *s = XLNX_VERSAL_CFU_APB(reg->opaque);
+uint32_t val = val64;
+
+s->regs[R_CFU_ISR] |= val;
+cfu_imr_update_irq(s);
+return 0;
+}
+
+static void cfu_fgcr_postw(RegisterInfo *reg, uint64_t val64)
+{
+XlnxVersalCFUAPB *s = XLNX_VERSAL_CFU_APB(reg->opaque);
+uint32_t val = (uint32_t)val64;
+
+/* Do a scan. It always looks good. */
+if (FIELD_EX32(val, CFU_FGCR, SC_HBC_TRIGGER)) {
+ARRAY_FIELD_DP32(s->regs, CFU_STATUS, SCAN_CLEAR_PASS, 1);
+ARRAY_FIELD_DP32(s->regs, CFU_STATUS, SCAN_CLEAR_DONE, 1);
+}
+}
+
+static const RegisterAccessInfo cfu_apb_regs_info[] = {
+{   .name = "CFU_ISR",  .addr = A_CFU_ISR,
+.rsvd = 0xfc00,
+.w1c = 0x3ff,
+.post_write = cfu_isr_postw,
+},{ .name = "CFU_IMR",  .addr = A_CFU_IMR,
+.reset = 0x3ff,
+.rsvd = 0xfc00,
+.ro = 0x3ff,
+},{ .name = "CFU_IER",  .addr = A_CFU_IER,
+.rsvd = 0xfc00,
+.pre_write = cfu_ier_prew,
+},{ .name = "CFU_IDR",  .addr = A_CFU_IDR,
+.rsvd = 0xfc00,
+.pre_write = cfu_idr_prew,
+},{ .name = "CFU_ITR",  .addr = A_CFU_ITR,
+.rsvd

[PATCH v3 3/8] hw/misc/xlnx-versal-cfu: Introduce a model of Xilinx Versal CFU_FDRO

2023-08-24 Thread Francisco Iglesias
Introduce a model of Xilinx Versal's Configuration Frame Unit's data out
port (CFU_FDRO).

Signed-off-by: Francisco Iglesias 
Reviewed-by: Peter Maydell 
---
 hw/misc/xlnx-versal-cfu.c | 96 +++
 include/hw/misc/xlnx-versal-cfu.h | 12 
 2 files changed, 108 insertions(+)

diff --git a/hw/misc/xlnx-versal-cfu.c b/hw/misc/xlnx-versal-cfu.c
index b2dc6ab211..255c1bf4b8 100644
--- a/hw/misc/xlnx-versal-cfu.c
+++ b/hw/misc/xlnx-versal-cfu.c
@@ -264,6 +264,25 @@ static void cfu_stream_write(void *opaque, hwaddr addr, 
uint64_t value,
 }
 }
 
+static uint64_t cfu_fdro_read(void *opaque, hwaddr addr, unsigned size)
+{
+XlnxVersalCFUFDRO *s = XLNX_VERSAL_CFU_FDRO(opaque);
+uint64_t ret = 0;
+
+if (!fifo32_is_empty(>fdro_data)) {
+ret = fifo32_pop(>fdro_data);
+}
+
+return ret;
+}
+
+static void cfu_fdro_write(void *opaque, hwaddr addr, uint64_t value,
+   unsigned size)
+{
+qemu_log_mask(LOG_GUEST_ERROR, "%s: Unsupported write from addr=%"
+  HWADDR_PRIx "\n", __func__, addr);
+}
+
 static const MemoryRegionOps cfu_stream_ops = {
 .read = cfu_stream_read,
 .write = cfu_stream_write,
@@ -274,6 +293,16 @@ static const MemoryRegionOps cfu_stream_ops = {
 },
 };
 
+static const MemoryRegionOps cfu_fdro_ops = {
+.read = cfu_fdro_read,
+.write = cfu_fdro_write,
+.endianness = DEVICE_LITTLE_ENDIAN,
+.valid = {
+.min_access_size = 4,
+.max_access_size = 4,
+},
+};
+
 static void cfu_apb_init(Object *obj)
 {
 XlnxVersalCFUAPB *s = XLNX_VERSAL_CFU_APB(obj);
@@ -305,6 +334,39 @@ static void cfu_apb_init(Object *obj)
 sysbus_init_irq(sbd, >irq_cfu_imr);
 }
 
+static void cfu_fdro_init(Object *obj)
+{
+XlnxVersalCFUFDRO *s = XLNX_VERSAL_CFU_FDRO(obj);
+SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+
+memory_region_init_io(>iomem_fdro, obj, _fdro_ops, s,
+  TYPE_XLNX_VERSAL_CFU_FDRO, KEYHOLE_STREAM_4K);
+sysbus_init_mmio(sbd, >iomem_fdro);
+fifo32_create(>fdro_data, 8 * KiB / sizeof(uint32_t));
+}
+
+static void cfu_fdro_reset_enter(Object *obj, ResetType type)
+{
+XlnxVersalCFUFDRO *s = XLNX_VERSAL_CFU_FDRO(obj);
+
+fifo32_reset(>fdro_data);
+}
+
+static void cfu_fdro_cfi_transfer_packet(XlnxCfiIf *cfi_if, XlnxCfiPacket *pkt)
+{
+XlnxVersalCFUFDRO *s = XLNX_VERSAL_CFU_FDRO(cfi_if);
+
+if (fifo32_num_free(>fdro_data) >= ARRAY_SIZE(pkt->data)) {
+for (int i = 0; i < ARRAY_SIZE(pkt->data); i++) {
+fifo32_push(>fdro_data, pkt->data[i]);
+}
+} else {
+/* It is a programming error to fill the fifo. */
+qemu_log_mask(LOG_GUEST_ERROR,
+  "CFU_FDRO: CFI data dropped due to full read fifo\n");
+}
+}
+
 static Property cfu_props[] = {
 DEFINE_PROP_LINK("cframe0", XlnxVersalCFUAPB, cfg.cframe[0],
  TYPE_XLNX_CFI_IF, XlnxCfiIf *),
@@ -351,6 +413,16 @@ static const VMStateDescription vmstate_cfu_apb = {
 }
 };
 
+static const VMStateDescription vmstate_cfu_fdro = {
+.name = TYPE_XLNX_VERSAL_CFU_FDRO,
+.version_id = 1,
+.minimum_version_id = 1,
+.fields = (VMStateField[]) {
+VMSTATE_FIFO32(fdro_data, XlnxVersalCFUFDRO),
+VMSTATE_END_OF_LIST(),
+}
+};
+
 static void cfu_apb_class_init(ObjectClass *klass, void *data)
 {
 DeviceClass *dc = DEVICE_CLASS(klass);
@@ -360,6 +432,17 @@ static void cfu_apb_class_init(ObjectClass *klass, void 
*data)
 device_class_set_props(dc, cfu_props);
 }
 
+static void cfu_fdro_class_init(ObjectClass *klass, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(klass);
+ResettableClass *rc = RESETTABLE_CLASS(klass);
+XlnxCfiIfClass *xcic = XLNX_CFI_IF_CLASS(klass);
+
+dc->vmsd = _cfu_fdro;
+xcic->cfi_transfer_packet = cfu_fdro_cfi_transfer_packet;
+rc->phases.enter = cfu_fdro_reset_enter;
+}
+
 static const TypeInfo cfu_apb_info = {
 .name  = TYPE_XLNX_VERSAL_CFU_APB,
 .parent= TYPE_SYS_BUS_DEVICE,
@@ -372,9 +455,22 @@ static const TypeInfo cfu_apb_info = {
 }
 };
 
+static const TypeInfo cfu_fdro_info = {
+.name  = TYPE_XLNX_VERSAL_CFU_FDRO,
+.parent= TYPE_SYS_BUS_DEVICE,
+.instance_size = sizeof(XlnxVersalCFUFDRO),
+.class_init= cfu_fdro_class_init,
+.instance_init = cfu_fdro_init,
+.interfaces = (InterfaceInfo[]) {
+{ TYPE_XLNX_CFI_IF },
+{ }
+}
+};
+
 static void cfu_apb_register_types(void)
 {
 type_register_static(_apb_info);
+type_register_static(_fdro_info);
 }
 
 type_init(cfu_apb_register_types)
diff --git a/include/hw/misc/xlnx-versal-cfu.h 
b/include/hw/misc/xlnx-versal-cfu.h
index 62d10caf27..73e9a21af4 100644
--- a/include/hw/misc/xlnx-versal-cfu.h
+++ b/include/hw/misc/xlnx-versal-cfu.h
@@ -20,10 +20,14 @@
 #include "h

[PATCH v3 8/8] hw/arm/versal: Connect the CFRAME_REG and CFRAME_BCAST_REG

2023-08-24 Thread Francisco Iglesias
Connect the Configuration Frame controller (CFRAME_REG) and the
Configuration Frame broadcast controller (CFRAME_BCAST_REG) to the
Versal machine.

Signed-off-by: Francisco Iglesias 
Reviewed-by: Peter Maydell 
---
 hw/arm/xlnx-versal.c | 113 ++-
 include/hw/arm/xlnx-versal.h |  69 +
 2 files changed, 181 insertions(+), 1 deletion(-)

diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
index 3f4b4b1560..fa556d8764 100644
--- a/hw/arm/xlnx-versal.c
+++ b/hw/arm/xlnx-versal.c
@@ -27,7 +27,7 @@
 #define XLNX_VERSAL_RCPU_TYPE ARM_CPU_TYPE_NAME("cortex-r5f")
 #define GEM_REVISION0x40070106
 
-#define VERSAL_NUM_PMC_APB_IRQS 3
+#define VERSAL_NUM_PMC_APB_IRQS 18
 #define NUM_OSPI_IRQ_LINES 3
 
 static void versal_create_apu_cpus(Versal *s)
@@ -341,6 +341,7 @@ static void versal_create_pmc_apb_irq_orgate(Versal *s, 
qemu_irq *pic)
  *  - RTC
  *  - BBRAM
  *  - PMC SLCR
+ *  - CFRAME regs (input 3 - 17 to the orgate)
  */
 object_initialize_child(OBJECT(s), "pmc-apb-irq-orgate",
 >pmc.apb_irq_orgate, TYPE_OR_IRQ);
@@ -573,6 +574,42 @@ static void versal_create_ospi(Versal *s, qemu_irq *pic)
 static void versal_create_cfu(Versal *s, qemu_irq *pic)
 {
 SysBusDevice *sbd;
+DeviceState *dev;
+int i;
+const struct {
+uint64_t reg_base;
+uint64_t fdri_base;
+} cframe_addr[] = {
+{ MM_PMC_CFRAME0_REG, MM_PMC_CFRAME0_FDRI },
+{ MM_PMC_CFRAME1_REG, MM_PMC_CFRAME1_FDRI },
+{ MM_PMC_CFRAME2_REG, MM_PMC_CFRAME2_FDRI },
+{ MM_PMC_CFRAME3_REG, MM_PMC_CFRAME3_FDRI },
+{ MM_PMC_CFRAME4_REG, MM_PMC_CFRAME4_FDRI },
+{ MM_PMC_CFRAME5_REG, MM_PMC_CFRAME5_FDRI },
+{ MM_PMC_CFRAME6_REG, MM_PMC_CFRAME6_FDRI },
+{ MM_PMC_CFRAME7_REG, MM_PMC_CFRAME7_FDRI },
+{ MM_PMC_CFRAME8_REG, MM_PMC_CFRAME8_FDRI },
+{ MM_PMC_CFRAME9_REG, MM_PMC_CFRAME9_FDRI },
+{ MM_PMC_CFRAME10_REG, MM_PMC_CFRAME10_FDRI },
+{ MM_PMC_CFRAME11_REG, MM_PMC_CFRAME11_FDRI },
+{ MM_PMC_CFRAME12_REG, MM_PMC_CFRAME12_FDRI },
+{ MM_PMC_CFRAME13_REG, MM_PMC_CFRAME13_FDRI },
+{ MM_PMC_CFRAME14_REG, MM_PMC_CFRAME14_FDRI },
+};
+const struct {
+uint32_t blktype0_frames;
+uint32_t blktype1_frames;
+uint32_t blktype2_frames;
+uint32_t blktype3_frames;
+uint32_t blktype4_frames;
+uint32_t blktype5_frames;
+uint32_t blktype6_frames;
+} cframe_cfg[] = {
+[0] = { 34111, 3528, 12800, 11, 5, 1, 1 },
+[1] = { 38498, 3841, 15361, 13, 7, 3, 1 },
+[2] = { 38498, 3841, 15361, 13, 7, 3, 1 },
+[3] = { 38498, 3841, 15361, 13, 7, 3, 1 },
+};
 
 /* CFU FDRO */
 object_initialize_child(OBJECT(s), "cfu-fdro", >pmc.cfu_fdro,
@@ -583,10 +620,84 @@ static void versal_create_cfu(Versal *s, qemu_irq *pic)
 memory_region_add_subregion(>mr_ps, MM_PMC_CFU_FDRO,
 sysbus_mmio_get_region(sbd, 0));
 
+/* CFRAME REG */
+for (i = 0; i < ARRAY_SIZE(s->pmc.cframe); i++) {
+g_autofree char *name = g_strdup_printf("cframe%d", i);
+
+object_initialize_child(OBJECT(s), name, >pmc.cframe[i],
+TYPE_XLNX_VERSAL_CFRAME_REG);
+
+sbd = SYS_BUS_DEVICE(>pmc.cframe[i]);
+dev = DEVICE(>pmc.cframe[i]);
+
+if (i < ARRAY_SIZE(cframe_cfg)) {
+object_property_set_int(OBJECT(dev), "blktype0-frames",
+cframe_cfg[i].blktype0_frames,
+_abort);
+object_property_set_int(OBJECT(dev), "blktype1-frames",
+cframe_cfg[i].blktype1_frames,
+_abort);
+object_property_set_int(OBJECT(dev), "blktype2-frames",
+cframe_cfg[i].blktype2_frames,
+_abort);
+object_property_set_int(OBJECT(dev), "blktype3-frames",
+cframe_cfg[i].blktype3_frames,
+_abort);
+object_property_set_int(OBJECT(dev), "blktype4-frames",
+cframe_cfg[i].blktype4_frames,
+_abort);
+object_property_set_int(OBJECT(dev), "blktype5-frames",
+cframe_cfg[i].blktype5_frames,
+_abort);
+object_property_set_int(OBJECT(dev), "blktype6-frames",
+cframe_cfg[i].blktype6_frames,
+_abort);
+}
+object_property_set_link(OBJECT(dev), "cfu-fdro",
+   

Re: [PATCH 2/2] audio/jackaudio: Avoid dynamic stack allocation in qjack_process()

2023-08-21 Thread Francisco Iglesias
On [2023 Aug 18] Fri 16:58:46, Peter Maydell wrote:
> Avoid a dynamic stack allocation in qjack_process().  Since this
> function is a JACK process callback, we are not permitted to malloc()
> here, so we allocate a working buffer in qjack_client_init() instead.
> 
> The codebase has very few VLAs, and if we can get rid of them all we
> can make the compiler error on new additions.  This is a defensive
> measure against security bugs where an on-stack dynamic allocation
> isn't correctly size-checked (e.g.  CVE-2021-3527).
> 
> Signed-off-by: Peter Maydell 

Reviewed-by: Francisco Iglesias 

> ---
> This feels like we ought to be able to say "we know there are at most
> X channels, so allocate an array of size X on the stack", but I
> couldn't find anything in the audio subsystem from a quick look that
> set an obvious bound on the number of channels.  Is there some
> straightforward constant MAX_CHANNELS somewhere?
> ---
>  audio/jackaudio.c | 16 +++-
>  1 file changed, 11 insertions(+), 5 deletions(-)
> 
> diff --git a/audio/jackaudio.c b/audio/jackaudio.c
> index 7cb2a49f971..e1eaa3477dc 100644
> --- a/audio/jackaudio.c
> +++ b/audio/jackaudio.c
> @@ -70,6 +70,9 @@ typedef struct QJackClient {
>  int buffersize;
>  jack_port_t   **port;
>  QJackBuffer fifo;
> +
> +/* Used as workspace by qjack_process() */
> +float **process_buffers;
>  }
>  QJackClient;
>  
> @@ -267,22 +270,21 @@ static int qjack_process(jack_nframes_t nframes, void 
> *arg)
>  }
>  
>  /* get the buffers for the ports */
> -float *buffers[c->nchannels];
>  for (int i = 0; i < c->nchannels; ++i) {
> -buffers[i] = jack_port_get_buffer(c->port[i], nframes);
> +c->process_buffers[i] = jack_port_get_buffer(c->port[i], nframes);
>  }
>  
>  if (c->out) {
>  if (likely(c->enabled)) {
> -qjack_buffer_read_l(>fifo, buffers, nframes);
> +qjack_buffer_read_l(>fifo, c->process_buffers, nframes);
>  } else {
>  for (int i = 0; i < c->nchannels; ++i) {
> -memset(buffers[i], 0, nframes * sizeof(float));
> +memset(c->process_buffers[i], 0, nframes * sizeof(float));
>  }
>  }
>  } else {
>  if (likely(c->enabled)) {
> -qjack_buffer_write_l(>fifo, buffers, nframes);
> +qjack_buffer_write_l(>fifo, c->process_buffers, nframes);
>  }
>  }
>  
> @@ -448,6 +450,9 @@ static int qjack_client_init(QJackClient *c)
>jack_get_client_name(c->client));
>  }
>  
> +/* Allocate working buffer for process callback */
> +c->process_buffers = g_new(float *, c->nchannels);
> +
>  jack_set_process_callback(c->client, qjack_process , c);
>  jack_set_port_registration_callback(c->client, qjack_port_registration, 
> c);
>  jack_set_xrun_callback(c->client, qjack_xrun, c);
> @@ -579,6 +584,7 @@ static void qjack_client_fini_locked(QJackClient *c)
>  
>  qjack_buffer_free(>fifo);
>  g_free(c->port);
> +g_free(c->process_buffers);
>  
>  c->state = QJACK_STATE_DISCONNECTED;
>  /* fallthrough */
> -- 
> 2.34.1
> 
> 



Re: [PATCH 3/3] ui/vnc-enc-tight: Avoid dynamic stack allocation

2023-08-21 Thread Francisco Iglesias
On [2023 Aug 18] Fri 16:10:57, Peter Maydell wrote:
> From: Philippe Mathieu-Daudé 
> 
> Use autofree heap allocation instead of variable-length
> array on the stack.
> 
> The codebase has very few VLAs, and if we can get rid of them all we
> can make the compiler error on new additions.  This is a defensive
> measure against security bugs where an on-stack dynamic allocation
> isn't correctly size-checked (e.g.  CVE-2021-3527).
> 
> Signed-off-by: Philippe Mathieu-Daudé 
> [PMM: expanded commit message]
> Signed-off-by: Peter Maydell 

Reviewed-by: Francisco Iglesias 

> ---
>  ui/vnc-enc-tight.c | 11 ++-
>  1 file changed, 6 insertions(+), 5 deletions(-)
> 
> diff --git a/ui/vnc-enc-tight.c b/ui/vnc-enc-tight.c
> index ee853dcfcb8..41f559eb837 100644
> --- a/ui/vnc-enc-tight.c
> +++ b/ui/vnc-enc-tight.c
> @@ -1097,13 +1097,13 @@ static int send_palette_rect(VncState *vs, int x, int 
> y,
>  switch (vs->client_pf.bytes_per_pixel) {
>  case 4:
>  {
> -size_t old_offset, offset;
> -uint32_t header[palette_size(palette)];
> +size_t old_offset, offset, palette_sz = palette_size(palette);
> +g_autofree uint32_t *header = g_new(uint32_t, palette_sz);
>  struct palette_cb_priv priv = { vs, (uint8_t *)header };
>  
>  old_offset = vs->output.offset;
>  palette_iter(palette, write_palette, );
> -vnc_write(vs, header, sizeof(header));
> +vnc_write(vs, header, palette_sz * sizeof(uint32_t));
>  
>  if (vs->tight->pixel24) {
>  tight_pack24(vs, vs->output.buffer + old_offset, colors, 
> );
> @@ -1115,11 +1115,12 @@ static int send_palette_rect(VncState *vs, int x, int 
> y,
>  }
>  case 2:
>  {
> -uint16_t header[palette_size(palette)];
> +size_t palette_sz = palette_size(palette);
> +g_autofree uint16_t *header = g_new(uint16_t, palette_sz);
>  struct palette_cb_priv priv = { vs, (uint8_t *)header };
>  
>  palette_iter(palette, write_palette, );
> -vnc_write(vs, header, sizeof(header));
> +vnc_write(vs, header, palette_sz * sizeof(uint16_t));
>  tight_encode_indexed_rect16(vs->tight->tight.buffer, w * h, palette);
>  break;
>  }
> -- 
> 2.34.1
> 
> 



Re: [PATCH 1/2] audio/jackaudio: Avoid dynamic stack allocation in qjack_client_init

2023-08-21 Thread Francisco Iglesias
On [2023 Aug 18] Fri 16:58:45, Peter Maydell wrote:
> Avoid a dynamic stack allocation in qjack_client_init(), by using
> a g_autofree heap allocation instead.
> 
> (We stick with allocate + snprintf() because the JACK API requires
> the name to be no more than its maximum size, so g_strdup_printf()
> would require an extra truncation step.)
> 
> The codebase has very few VLAs, and if we can get rid of them all we
> can make the compiler error on new additions.  This is a defensive
> measure against security bugs where an on-stack dynamic allocation
> isn't correctly size-checked (e.g.  CVE-2021-3527).
> 
> Signed-off-by: Peter Maydell 

Reviewed-by: Francisco Iglesias 

> ---
>  audio/jackaudio.c | 5 +++--
>  1 file changed, 3 insertions(+), 2 deletions(-)
> 
> diff --git a/audio/jackaudio.c b/audio/jackaudio.c
> index 5bdf3d7a78d..7cb2a49f971 100644
> --- a/audio/jackaudio.c
> +++ b/audio/jackaudio.c
> @@ -400,7 +400,8 @@ static void qjack_client_connect_ports(QJackClient *c)
>  static int qjack_client_init(QJackClient *c)
>  {
>  jack_status_t status;
> -char client_name[jack_client_name_size()];
> +int client_name_len = jack_client_name_size(); /* includes NUL */
> +g_autofree char *client_name = g_new(char, client_name_len);
>  jack_options_t options = JackNullOption;
>  
>  if (c->state == QJACK_STATE_RUNNING) {
> @@ -409,7 +410,7 @@ static int qjack_client_init(QJackClient *c)
>  
>  c->connect_ports = true;
>  
> -snprintf(client_name, sizeof(client_name), "%s-%s",
> +snprintf(client_name, client_name_len, "%s-%s",
>  c->out ? "out" : "in",
>  c->opt->client_name ? c->opt->client_name : 
> audio_application_name());
>  
> -- 
> 2.34.1
> 
> 



Re: [PATCH] block/vpc: Avoid dynamic stack allocation

2023-08-18 Thread Francisco Iglesias
On [2023 Aug 11] Fri 18:52:29, Peter Maydell wrote:
> From: Philippe Mathieu-Daudé 
> 
> Use autofree heap allocation instead of variable-length array on the
> stack. Here we don't expect the bitmap size to be enormous, and
> since we're about to read/write it to disk the overhead of the
> allocation should be fine.
> 
> The codebase has very few VLAs, and if we can get rid of them all we
> can make the compiler error on new additions.  This is a defensive
> measure against security bugs where an on-stack dynamic allocation
> isn't correctly size-checked (e.g.  CVE-2021-3527).
> 
> Signed-off-by: Philippe Mathieu-Daudé 
> [PMM: expanded commit message]
> Signed-off-by: Peter Maydell 

Reviewed-by: Francisco Iglesias 

> ---
>  block/vpc.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/block/vpc.c b/block/vpc.c
> index 3810a601a38..ceb87dd3d8e 100644
> --- a/block/vpc.c
> +++ b/block/vpc.c
> @@ -510,7 +510,7 @@ get_image_offset(BlockDriverState *bs, uint64_t offset, 
> bool write, int *err)
> miss sparse read optimization, but it's not a problem in terms of
> correctness. */
>  if (write && (s->last_bitmap_offset != bitmap_offset)) {
> -uint8_t bitmap[s->bitmap_size];
> +g_autofree uint8_t *bitmap = g_malloc(s->bitmap_size);
>  int r;
>  
>  s->last_bitmap_offset = bitmap_offset;
> @@ -558,7 +558,7 @@ alloc_block(BlockDriverState *bs, int64_t offset)
>  int64_t bat_offset;
>  uint32_t index, bat_value;
>  int ret;
> -uint8_t bitmap[s->bitmap_size];
> +g_autofree uint8_t *bitmap = g_malloc(s->bitmap_size);
>  
>  /* Check if sector_num is valid */
>  if ((offset < 0) || (offset > bs->total_sectors * BDRV_SECTOR_SIZE)) {
> -- 
> 2.34.1
> 
> 



Re: [PATCH v1 3/8] hw/misc/xlnx-versal-cfu: Introduce a model of Xilinx Versal CFU_FDRO

2023-08-10 Thread Francisco Iglesias

Hi Peter,

On 2023-08-03 15:48, Peter Maydell wrote:

On Mon, 10 Jul 2023 at 15:03, Francisco Iglesias
 wrote:


Introduce a model of Xilinx Versal's Configuration Frame Unit's data out
port (CFU_FDRO).

Signed-off-by: Francisco Iglesias 
---
  hw/misc/xlnx-versal-cfu.c | 105 ++
  include/hw/misc/xlnx-versal-cfu.h |  11 
  2 files changed, 116 insertions(+)

diff --git a/hw/misc/xlnx-versal-cfu.c b/hw/misc/xlnx-versal-cfu.c
index cbd17d2351..528090ef1b 100644
--- a/hw/misc/xlnx-versal-cfu.c
+++ b/hw/misc/xlnx-versal-cfu.c
@@ -257,6 +257,26 @@ static void cfu_stream_write(void *opaque, hwaddr addr, 
uint64_t value,
  }
  }

+static uint64_t cfu_fdro_read(void *opaque, hwaddr addr, unsigned size)
+{
+XlnxVersalCFUFDRO *s = XLNX_VERSAL_CFU_FDRO(opaque);
+uint64_t ret = 0;
+
+if (s->fdro_data->len) {
+ret = g_array_index(s->fdro_data, uint32_t, 0);
+g_array_remove_index(s->fdro_data, 0);


This is pretty expensive because everything in the GArray
after element 0 must be copied downwards. Are you sure you
don't want a different data structure ?

What actually is this, and what are the operations we want
to do on it ?


Thank you very much for reviewing! Regarding above, it is a fifo so 
changed to use a Fifo32 in v2 and I also tried to update according to 
all other comments!


Best regards,
Francisco Iglesias




+}
+
+return ret;
+}
+
+static void cfu_fdro_write(void *opaque, hwaddr addr, uint64_t value,
+   unsigned size)
+{
+qemu_log_mask(LOG_GUEST_ERROR, "%s: Unsupported write from addr=%"
+  HWADDR_PRIx "\n", __func__, addr);
+}
+
  static const MemoryRegionOps cfu_stream_ops = {
  .read = cfu_stream_read,
  .write = cfu_stream_write,
@@ -267,6 +287,16 @@ static const MemoryRegionOps cfu_stream_ops = {
  },
  };

+static const MemoryRegionOps cfu_fdro_ops = {
+.read = cfu_fdro_read,
+.write = cfu_fdro_write,
+.endianness = DEVICE_LITTLE_ENDIAN,
+.valid = {
+.min_access_size = 4,
+.max_access_size = 4,
+},
+};
+
  static void cfu_apb_init(Object *obj)
  {
  XlnxVersalCFUAPB *s = XLNX_VERSAL_CFU_APB(obj);
@@ -298,6 +328,24 @@ static void cfu_apb_init(Object *obj)
  sysbus_init_irq(sbd, >irq_cfu_imr);
  }

+static void cfu_fdro_init(Object *obj)
+{
+XlnxVersalCFUFDRO *s = XLNX_VERSAL_CFU_FDRO(obj);
+SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+
+memory_region_init_io(>iomem_fdro, obj, _fdro_ops, s,
+  TYPE_XLNX_VERSAL_CFU_FDRO, KEYHOLE_STREAM_4K);
+sysbus_init_mmio(sbd, >iomem_fdro);
+s->fdro_data = g_array_new(FALSE, FALSE, sizeof(uint32_t));
+}
+
+static void cfu_fdro_cfi_transfer_packet(XlnxCfiIf *cfi_if, XlnxCfiPacket *pkt)
+{
+XlnxVersalCFUFDRO *s = XLNX_VERSAL_CFU_FDRO(cfi_if);
+
+g_array_append_vals(s->fdro_data, >data[0], 4);
+}
+
  static Property cfu_props[] = {
  DEFINE_PROP_LINK("cframe0", XlnxVersalCFUAPB, cfg.cframe[0],
   TYPE_XLNX_CFI_IF, XlnxCfiIf *),
@@ -344,6 +392,41 @@ static const VMStateDescription vmstate_cfu_apb = {
  }
  };

+static int cfdro_reg_pre_save(void *opaque)
+{
+XlnxVersalCFUFDRO *s = XLNX_VERSAL_CFU_FDRO(opaque);
+
+if (s->fdro_data->len) {
+s->ro_data = (uint32_t *) s->fdro_data->data;
+s->ro_dlen = s->fdro_data->len;
+}


I think we need to initialise ro_data and ro_dlen in
the else case here as well. Otherwise they might have old
stale stuff in them that then goes into the migration stream.


+
+return 0;
+}
+
+static int cfdro_reg_post_load(void *opaque, int version_id)
+{
+XlnxVersalCFUFDRO *s = XLNX_VERSAL_CFU_FDRO(opaque);
+
+if (s->ro_dlen) {
+g_array_append_vals(s->fdro_data, s->ro_data, s->ro_dlen);
+}
+return 0;
+}
+
+static const VMStateDescription vmstate_cfu_fdro = {
+.name = TYPE_XLNX_VERSAL_CFU_FDRO,
+.version_id = 1,
+.minimum_version_id = 1,
+.pre_save = cfdro_reg_pre_save,
+.post_load = cfdro_reg_post_load,
+.fields = (VMStateField[]) {
+VMSTATE_VARRAY_UINT32_ALLOC(ro_data, XlnxVersalCFUFDRO, ro_dlen,
+0, vmstate_info_uint32, uint32_t),


This kind of _ALLOC vmstate will cause the migration core
code to g_malloc() you a buffer for the data. We don't
free that anywhere (and if we have a subsequent vmsave
then we will overwrite the ro-data pointer, and leak the
memory).

It might be better to avoid the GArray and just directly
work with a g_malloc()'d buffer of our own, to fit better
with how the _ALLOC vmstate wants to work.


+VMSTATE_END_OF_LIST(),
+}
+};
+
  static void cfu_apb_class_init(ObjectClass *klass, void *data)
  {
  DeviceClass *dc = DEVICE_CLASS(klass);
@@ -353,6 +436,15 @@ static void cfu_apb_class_init(ObjectClass *klass, void 
*data)
 

[PATCH v2 5/8] hw/misc: Introduce a model of Xilinx Versal's CFRAME_REG

2023-08-10 Thread Francisco Iglesias
Introduce a model of Xilinx Versal's Configuration Frame controller
(CFRAME_REG).

Signed-off-by: Francisco Iglesias 
---
 MAINTAINERS  |   2 +
 hw/misc/meson.build  |   1 +
 hw/misc/xlnx-versal-cframe-reg.c | 753 +++
 include/hw/misc/xlnx-versal-cframe-reg.h | 289 +
 4 files changed, 1045 insertions(+)
 create mode 100644 hw/misc/xlnx-versal-cframe-reg.c
 create mode 100644 include/hw/misc/xlnx-versal-cframe-reg.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 847b997d73..645374c1d9 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1041,6 +1041,8 @@ F: hw/misc/xlnx-cfi-if.c
 F: include/hw/misc/xlnx-cfi-if.h
 F: hw/misc/xlnx-versal-cfu.c
 F: include/hw/misc/xlnx-versal-cfu.h
+F: hw/misc/xlnx-versal-cframe-reg.c
+F: include/hw/misc/xlnx-versal-cframe-reg.h
 
 STM32F100
 M: Alexandre Iooss 
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
index d95cc3fd87..1b425b03bd 100644
--- a/hw/misc/meson.build
+++ b/hw/misc/meson.build
@@ -99,6 +99,7 @@ system_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files(
   'xlnx-versal-pmc-iou-slcr.c',
   'xlnx-versal-cfu.c',
   'xlnx-cfi-if.c',
+  'xlnx-versal-cframe-reg.c',
 ))
 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'))
diff --git a/hw/misc/xlnx-versal-cframe-reg.c b/hw/misc/xlnx-versal-cframe-reg.c
new file mode 100644
index 00..401bd7a4a9
--- /dev/null
+++ b/hw/misc/xlnx-versal-cframe-reg.c
@@ -0,0 +1,753 @@
+/*
+ * QEMU model of the Configuration Frame Control module
+ *
+ * Copyright (C) 2023, Advanced Micro Devices, Inc.
+ *
+ * Written by Francisco Iglesias 
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "hw/sysbus.h"
+#include "hw/register.h"
+#include "hw/registerfields.h"
+#include "qemu/bitops.h"
+#include "qemu/log.h"
+#include "qemu/units.h"
+#include "qapi/error.h"
+#include "hw/qdev-properties.h"
+#include "migration/vmstate.h"
+#include "hw/irq.h"
+#include "hw/misc/xlnx-versal-cframe-reg.h"
+
+#ifndef XLNX_VERSAL_CFRAME_REG_ERR_DEBUG
+#define XLNX_VERSAL_CFRAME_REG_ERR_DEBUG 0
+#endif
+
+#define KEYHOLE_STREAM_4K (4 * KiB)
+#define N_WORDS_128BIT 4
+#define MIG_CFRAME_SZ ((FRAME_NUM_WORDS + 1) * sizeof(uint32_t))
+
+#define MAX_BLOCKTYPE 6
+#define MAX_BLOCKTYPE_FRAMES 0xF
+
+enum {
+CFRAME_CMD_WCFG = 1,
+CFRAME_CMD_ROWON = 2,
+CFRAME_CMD_ROWOFF = 3,
+CFRAME_CMD_RCFG = 4,
+CFRAME_CMD_DLPARK = 5,
+};
+
+static void cfrm_imr_update_irq(XlnxVersalCFrameReg *s)
+{
+bool pending = s->regs[R_CFRM_ISR0] & ~s->regs[R_CFRM_IMR0];
+qemu_set_irq(s->irq_cfrm_imr, pending);
+}
+
+static void cfrm_isr_postw(RegisterInfo *reg, uint64_t val64)
+{
+XlnxVersalCFrameReg *s = XLNX_VERSAL_CFRAME_REG(reg->opaque);
+cfrm_imr_update_irq(s);
+}
+
+static uint64_t cfrm_ier_prew(RegisterInfo *reg, uint64_t val64)
+{
+XlnxVersalCFrameReg *s = XLNX_VERSAL_CFRAME_REG(reg->opaque);
+
+s->regs[R_CFRM_IMR0] &= ~s->regs[R_CFRM_IER0];
+s->regs[R_CFRM_IER0] = 0;
+cfrm_imr_update_irq(s);
+return 0;
+}
+
+static uint64_t cfrm_idr_prew(RegisterInfo *reg, uint64_t val64)
+{
+XlnxVersalCFrameReg *s = XLNX_VERSAL_CFRAME_REG(reg->opaque);
+
+s->regs[R_CFRM_IMR0] |= s->regs[R_CFRM_IDR0];
+s->regs[R_CFRM_IDR0] = 0;
+cfrm_imr_update_irq(s);
+return 0;
+}
+
+static uint64_t cfrm_itr_prew(RegisterInfo *reg, uint64_t val64)
+{
+XlnxVersalCFrameReg *s = XLNX_VERSAL_CFRAME_REG(reg->opaque);
+
+s->regs[R_CFRM_ISR0] |= s->regs[R_CFRM_ITR0];
+s->regs[R_CFRM_ITR0] = 0;
+cfrm_imr_update_irq(s);
+return 0;
+}
+
+static void cframe_incr_far(XlnxVersalCFrameReg *s)
+{
+uint32_t faddr = ARRAY_FIELD_EX32(s->regs, FAR0, FRAME_ADDR);
+uint32_t blktype = ARRAY_FIELD_EX32(s->regs, FAR0, BLOCKTYPE);
+
+assert(blktype <= MAX_BLOCKTYPE);
+
+faddr++;
+if (faddr > s->cfg.blktype_num_frames[blktype]) {
+/* Restart from 0 and increment block type */
+faddr = 0;
+blktype++;
+
+assert(blktype <= MAX_BLOCKTYPE);
+
+ARRAY_FIELD_DP32(s->regs, FAR0, BLOCKTYPE, blktype);
+}
+
+ARRAY_FIELD_DP32(s->regs, FAR0, FRAME_ADDR, faddr);
+}
+
+static XlnxCFrame *cframes_get_frame(XlnxVersalCFrameReg *s, uint32_t addr)
+{
+for (int i = 0; i < s->cframes->len; i++) {
+XlnxCFrame *f = _array_index(s->cframes, XlnxCFrame, i);
+
+if (f->addr == addr) {
+return f;
+}
+}
+return NULL;
+}
+
+static void cframe_alloc(XlnxCFrame *f)
+{
+f->addr = 0;
+fifo32_create(>data, FRAME_NUM_WORDS);
+}
+
+static void cframe_move(XlnxCFrame *dst, XlnxCFrame *src)
+{

[PATCH v2 3/8] hw/misc/xlnx-versal-cfu: Introduce a model of Xilinx Versal CFU_FDRO

2023-08-10 Thread Francisco Iglesias
Introduce a model of Xilinx Versal's Configuration Frame Unit's data out
port (CFU_FDRO).

Signed-off-by: Francisco Iglesias 
---
 hw/misc/xlnx-versal-cfu.c | 96 +++
 include/hw/misc/xlnx-versal-cfu.h | 12 
 2 files changed, 108 insertions(+)

diff --git a/hw/misc/xlnx-versal-cfu.c b/hw/misc/xlnx-versal-cfu.c
index b2dc6ab211..255c1bf4b8 100644
--- a/hw/misc/xlnx-versal-cfu.c
+++ b/hw/misc/xlnx-versal-cfu.c
@@ -264,6 +264,25 @@ static void cfu_stream_write(void *opaque, hwaddr addr, 
uint64_t value,
 }
 }
 
+static uint64_t cfu_fdro_read(void *opaque, hwaddr addr, unsigned size)
+{
+XlnxVersalCFUFDRO *s = XLNX_VERSAL_CFU_FDRO(opaque);
+uint64_t ret = 0;
+
+if (!fifo32_is_empty(>fdro_data)) {
+ret = fifo32_pop(>fdro_data);
+}
+
+return ret;
+}
+
+static void cfu_fdro_write(void *opaque, hwaddr addr, uint64_t value,
+   unsigned size)
+{
+qemu_log_mask(LOG_GUEST_ERROR, "%s: Unsupported write from addr=%"
+  HWADDR_PRIx "\n", __func__, addr);
+}
+
 static const MemoryRegionOps cfu_stream_ops = {
 .read = cfu_stream_read,
 .write = cfu_stream_write,
@@ -274,6 +293,16 @@ static const MemoryRegionOps cfu_stream_ops = {
 },
 };
 
+static const MemoryRegionOps cfu_fdro_ops = {
+.read = cfu_fdro_read,
+.write = cfu_fdro_write,
+.endianness = DEVICE_LITTLE_ENDIAN,
+.valid = {
+.min_access_size = 4,
+.max_access_size = 4,
+},
+};
+
 static void cfu_apb_init(Object *obj)
 {
 XlnxVersalCFUAPB *s = XLNX_VERSAL_CFU_APB(obj);
@@ -305,6 +334,39 @@ static void cfu_apb_init(Object *obj)
 sysbus_init_irq(sbd, >irq_cfu_imr);
 }
 
+static void cfu_fdro_init(Object *obj)
+{
+XlnxVersalCFUFDRO *s = XLNX_VERSAL_CFU_FDRO(obj);
+SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+
+memory_region_init_io(>iomem_fdro, obj, _fdro_ops, s,
+  TYPE_XLNX_VERSAL_CFU_FDRO, KEYHOLE_STREAM_4K);
+sysbus_init_mmio(sbd, >iomem_fdro);
+fifo32_create(>fdro_data, 8 * KiB / sizeof(uint32_t));
+}
+
+static void cfu_fdro_reset_enter(Object *obj, ResetType type)
+{
+XlnxVersalCFUFDRO *s = XLNX_VERSAL_CFU_FDRO(obj);
+
+fifo32_reset(>fdro_data);
+}
+
+static void cfu_fdro_cfi_transfer_packet(XlnxCfiIf *cfi_if, XlnxCfiPacket *pkt)
+{
+XlnxVersalCFUFDRO *s = XLNX_VERSAL_CFU_FDRO(cfi_if);
+
+if (fifo32_num_free(>fdro_data) >= ARRAY_SIZE(pkt->data)) {
+for (int i = 0; i < ARRAY_SIZE(pkt->data); i++) {
+fifo32_push(>fdro_data, pkt->data[i]);
+}
+} else {
+/* It is a programming error to fill the fifo. */
+qemu_log_mask(LOG_GUEST_ERROR,
+  "CFU_FDRO: CFI data dropped due to full read fifo\n");
+}
+}
+
 static Property cfu_props[] = {
 DEFINE_PROP_LINK("cframe0", XlnxVersalCFUAPB, cfg.cframe[0],
  TYPE_XLNX_CFI_IF, XlnxCfiIf *),
@@ -351,6 +413,16 @@ static const VMStateDescription vmstate_cfu_apb = {
 }
 };
 
+static const VMStateDescription vmstate_cfu_fdro = {
+.name = TYPE_XLNX_VERSAL_CFU_FDRO,
+.version_id = 1,
+.minimum_version_id = 1,
+.fields = (VMStateField[]) {
+VMSTATE_FIFO32(fdro_data, XlnxVersalCFUFDRO),
+VMSTATE_END_OF_LIST(),
+}
+};
+
 static void cfu_apb_class_init(ObjectClass *klass, void *data)
 {
 DeviceClass *dc = DEVICE_CLASS(klass);
@@ -360,6 +432,17 @@ static void cfu_apb_class_init(ObjectClass *klass, void 
*data)
 device_class_set_props(dc, cfu_props);
 }
 
+static void cfu_fdro_class_init(ObjectClass *klass, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(klass);
+ResettableClass *rc = RESETTABLE_CLASS(klass);
+XlnxCfiIfClass *xcic = XLNX_CFI_IF_CLASS(klass);
+
+dc->vmsd = _cfu_fdro;
+xcic->cfi_transfer_packet = cfu_fdro_cfi_transfer_packet;
+rc->phases.enter = cfu_fdro_reset_enter;
+}
+
 static const TypeInfo cfu_apb_info = {
 .name  = TYPE_XLNX_VERSAL_CFU_APB,
 .parent= TYPE_SYS_BUS_DEVICE,
@@ -372,9 +455,22 @@ static const TypeInfo cfu_apb_info = {
 }
 };
 
+static const TypeInfo cfu_fdro_info = {
+.name  = TYPE_XLNX_VERSAL_CFU_FDRO,
+.parent= TYPE_SYS_BUS_DEVICE,
+.instance_size = sizeof(XlnxVersalCFUFDRO),
+.class_init= cfu_fdro_class_init,
+.instance_init = cfu_fdro_init,
+.interfaces = (InterfaceInfo[]) {
+{ TYPE_XLNX_CFI_IF },
+{ }
+}
+};
+
 static void cfu_apb_register_types(void)
 {
 type_register_static(_apb_info);
+type_register_static(_fdro_info);
 }
 
 type_init(cfu_apb_register_types)
diff --git a/include/hw/misc/xlnx-versal-cfu.h 
b/include/hw/misc/xlnx-versal-cfu.h
index 62d10caf27..73e9a21af4 100644
--- a/include/hw/misc/xlnx-versal-cfu.h
+++ b/include/hw/misc/xlnx-versal-cfu.h
@@ -20,10 +20,14 @@
 #include "hw/sysbus.h&q

[PATCH v2 8/8] hw/arm/versal: Connect the CFRAME_REG and CFRAME_BCAST_REG

2023-08-10 Thread Francisco Iglesias
Connect the Configuration Frame controller (CFRAME_REG) and the
Configuration Frame broadcast controller (CFRAME_BCAST_REG) to the
Versal machine.

Signed-off-by: Francisco Iglesias 
---
 hw/arm/xlnx-versal.c | 113 ++-
 include/hw/arm/xlnx-versal.h |  69 +
 2 files changed, 181 insertions(+), 1 deletion(-)

diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
index 3f4b4b1560..fa556d8764 100644
--- a/hw/arm/xlnx-versal.c
+++ b/hw/arm/xlnx-versal.c
@@ -27,7 +27,7 @@
 #define XLNX_VERSAL_RCPU_TYPE ARM_CPU_TYPE_NAME("cortex-r5f")
 #define GEM_REVISION0x40070106
 
-#define VERSAL_NUM_PMC_APB_IRQS 3
+#define VERSAL_NUM_PMC_APB_IRQS 18
 #define NUM_OSPI_IRQ_LINES 3
 
 static void versal_create_apu_cpus(Versal *s)
@@ -341,6 +341,7 @@ static void versal_create_pmc_apb_irq_orgate(Versal *s, 
qemu_irq *pic)
  *  - RTC
  *  - BBRAM
  *  - PMC SLCR
+ *  - CFRAME regs (input 3 - 17 to the orgate)
  */
 object_initialize_child(OBJECT(s), "pmc-apb-irq-orgate",
 >pmc.apb_irq_orgate, TYPE_OR_IRQ);
@@ -573,6 +574,42 @@ static void versal_create_ospi(Versal *s, qemu_irq *pic)
 static void versal_create_cfu(Versal *s, qemu_irq *pic)
 {
 SysBusDevice *sbd;
+DeviceState *dev;
+int i;
+const struct {
+uint64_t reg_base;
+uint64_t fdri_base;
+} cframe_addr[] = {
+{ MM_PMC_CFRAME0_REG, MM_PMC_CFRAME0_FDRI },
+{ MM_PMC_CFRAME1_REG, MM_PMC_CFRAME1_FDRI },
+{ MM_PMC_CFRAME2_REG, MM_PMC_CFRAME2_FDRI },
+{ MM_PMC_CFRAME3_REG, MM_PMC_CFRAME3_FDRI },
+{ MM_PMC_CFRAME4_REG, MM_PMC_CFRAME4_FDRI },
+{ MM_PMC_CFRAME5_REG, MM_PMC_CFRAME5_FDRI },
+{ MM_PMC_CFRAME6_REG, MM_PMC_CFRAME6_FDRI },
+{ MM_PMC_CFRAME7_REG, MM_PMC_CFRAME7_FDRI },
+{ MM_PMC_CFRAME8_REG, MM_PMC_CFRAME8_FDRI },
+{ MM_PMC_CFRAME9_REG, MM_PMC_CFRAME9_FDRI },
+{ MM_PMC_CFRAME10_REG, MM_PMC_CFRAME10_FDRI },
+{ MM_PMC_CFRAME11_REG, MM_PMC_CFRAME11_FDRI },
+{ MM_PMC_CFRAME12_REG, MM_PMC_CFRAME12_FDRI },
+{ MM_PMC_CFRAME13_REG, MM_PMC_CFRAME13_FDRI },
+{ MM_PMC_CFRAME14_REG, MM_PMC_CFRAME14_FDRI },
+};
+const struct {
+uint32_t blktype0_frames;
+uint32_t blktype1_frames;
+uint32_t blktype2_frames;
+uint32_t blktype3_frames;
+uint32_t blktype4_frames;
+uint32_t blktype5_frames;
+uint32_t blktype6_frames;
+} cframe_cfg[] = {
+[0] = { 34111, 3528, 12800, 11, 5, 1, 1 },
+[1] = { 38498, 3841, 15361, 13, 7, 3, 1 },
+[2] = { 38498, 3841, 15361, 13, 7, 3, 1 },
+[3] = { 38498, 3841, 15361, 13, 7, 3, 1 },
+};
 
 /* CFU FDRO */
 object_initialize_child(OBJECT(s), "cfu-fdro", >pmc.cfu_fdro,
@@ -583,10 +620,84 @@ static void versal_create_cfu(Versal *s, qemu_irq *pic)
 memory_region_add_subregion(>mr_ps, MM_PMC_CFU_FDRO,
 sysbus_mmio_get_region(sbd, 0));
 
+/* CFRAME REG */
+for (i = 0; i < ARRAY_SIZE(s->pmc.cframe); i++) {
+g_autofree char *name = g_strdup_printf("cframe%d", i);
+
+object_initialize_child(OBJECT(s), name, >pmc.cframe[i],
+TYPE_XLNX_VERSAL_CFRAME_REG);
+
+sbd = SYS_BUS_DEVICE(>pmc.cframe[i]);
+dev = DEVICE(>pmc.cframe[i]);
+
+if (i < ARRAY_SIZE(cframe_cfg)) {
+object_property_set_int(OBJECT(dev), "blktype0-frames",
+cframe_cfg[i].blktype0_frames,
+_abort);
+object_property_set_int(OBJECT(dev), "blktype1-frames",
+cframe_cfg[i].blktype1_frames,
+_abort);
+object_property_set_int(OBJECT(dev), "blktype2-frames",
+cframe_cfg[i].blktype2_frames,
+_abort);
+object_property_set_int(OBJECT(dev), "blktype3-frames",
+cframe_cfg[i].blktype3_frames,
+_abort);
+object_property_set_int(OBJECT(dev), "blktype4-frames",
+cframe_cfg[i].blktype4_frames,
+_abort);
+object_property_set_int(OBJECT(dev), "blktype5-frames",
+cframe_cfg[i].blktype5_frames,
+_abort);
+object_property_set_int(OBJECT(dev), "blktype6-frames",
+cframe_cfg[i].blktype6_frames,
+_abort);
+}
+object_property_set_link(OBJECT(dev), "cfu-fdro",
+ OBJECT(>

[PATCH v2 7/8] hw/arm/xlnx-versal: Connect the CFU_APB, CFU_FDRO and CFU_SFR

2023-08-10 Thread Francisco Iglesias
Connect the Configuration Frame Unit (CFU_APB, CFU_FDRO and CFU_SFR) to
the Versal machine.

Signed-off-by: Francisco Iglesias 
Acked-by: Edgar E. Iglesias 
Reviewed-by: Peter Maydell 
---
 hw/arm/xlnx-versal.c | 42 
 include/hw/arm/xlnx-versal.h | 16 ++
 2 files changed, 58 insertions(+)

diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
index 60bf5fe657..3f4b4b1560 100644
--- a/hw/arm/xlnx-versal.c
+++ b/hw/arm/xlnx-versal.c
@@ -570,6 +570,47 @@ static void versal_create_ospi(Versal *s, qemu_irq *pic)
 qdev_connect_gpio_out(orgate, 0, pic[VERSAL_OSPI_IRQ]);
 }
 
+static void versal_create_cfu(Versal *s, qemu_irq *pic)
+{
+SysBusDevice *sbd;
+
+/* CFU FDRO */
+object_initialize_child(OBJECT(s), "cfu-fdro", >pmc.cfu_fdro,
+TYPE_XLNX_VERSAL_CFU_FDRO);
+sbd = SYS_BUS_DEVICE(>pmc.cfu_fdro);
+
+sysbus_realize(sbd, _fatal);
+memory_region_add_subregion(>mr_ps, MM_PMC_CFU_FDRO,
+sysbus_mmio_get_region(sbd, 0));
+
+/* CFU APB */
+object_initialize_child(OBJECT(s), "cfu-apb", >pmc.cfu_apb,
+TYPE_XLNX_VERSAL_CFU_APB);
+sbd = SYS_BUS_DEVICE(>pmc.cfu_apb);
+
+sysbus_realize(sbd, _fatal);
+memory_region_add_subregion(>mr_ps, MM_PMC_CFU_APB,
+sysbus_mmio_get_region(sbd, 0));
+memory_region_add_subregion(>mr_ps, MM_PMC_CFU_STREAM,
+sysbus_mmio_get_region(sbd, 1));
+memory_region_add_subregion(>mr_ps, MM_PMC_CFU_STREAM_2,
+sysbus_mmio_get_region(sbd, 2));
+sysbus_connect_irq(sbd, 0, pic[VERSAL_CFU_IRQ_0]);
+
+/* CFU SFR */
+object_initialize_child(OBJECT(s), "cfu-sfr", >pmc.cfu_sfr,
+TYPE_XLNX_VERSAL_CFU_SFR);
+
+sbd = SYS_BUS_DEVICE(>pmc.cfu_sfr);
+
+object_property_set_link(OBJECT(>pmc.cfu_sfr),
+"cfu", OBJECT(>pmc.cfu_apb), _abort);
+
+sysbus_realize(sbd, _fatal);
+memory_region_add_subregion(>mr_ps, MM_PMC_CFU_SFR,
+sysbus_mmio_get_region(sbd, 0));
+}
+
 static void versal_create_crl(Versal *s, qemu_irq *pic)
 {
 SysBusDevice *sbd;
@@ -763,6 +804,7 @@ static void versal_realize(DeviceState *dev, Error **errp)
 versal_create_pmc_iou_slcr(s, pic);
 versal_create_ospi(s, pic);
 versal_create_crl(s, pic);
+versal_create_cfu(s, pic);
 versal_map_ddr(s);
 versal_unimp(s);
 
diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
index 39ee31185c..29b9c60301 100644
--- a/include/hw/arm/xlnx-versal.h
+++ b/include/hw/arm/xlnx-versal.h
@@ -32,6 +32,7 @@
 #include "hw/misc/xlnx-versal-crl.h"
 #include "hw/misc/xlnx-versal-pmc-iou-slcr.h"
 #include "hw/net/xlnx-versal-canfd.h"
+#include "hw/misc/xlnx-versal-cfu.h"
 
 #define TYPE_XLNX_VERSAL "xlnx-versal"
 OBJECT_DECLARE_SIMPLE_TYPE(Versal, XLNX_VERSAL)
@@ -117,6 +118,9 @@ struct Versal {
 XlnxEFuse efuse;
 XlnxVersalEFuseCtrl efuse_ctrl;
 XlnxVersalEFuseCache efuse_cache;
+XlnxVersalCFUAPB cfu_apb;
+XlnxVersalCFUFDRO cfu_fdro;
+XlnxVersalCFUSFR cfu_sfr;
 
 OrIRQState apb_irq_orgate;
 } pmc;
@@ -147,6 +151,7 @@ struct Versal {
 #define VERSAL_GEM1_WAKE_IRQ_0 59
 #define VERSAL_ADMA_IRQ_0  60
 #define VERSAL_XRAM_IRQ_0  79
+#define VERSAL_CFU_IRQ_0   120
 #define VERSAL_PMC_APB_IRQ 121
 #define VERSAL_OSPI_IRQ124
 #define VERSAL_SD0_IRQ_0   126
@@ -240,6 +245,17 @@ struct Versal {
 #define MM_PMC_EFUSE_CACHE  0xf125
 #define MM_PMC_EFUSE_CACHE_SIZE 0x00C00
 
+#define MM_PMC_CFU_APB  0xf12b
+#define MM_PMC_CFU_APB_SIZE 0x1
+#define MM_PMC_CFU_STREAM   0xf12c
+#define MM_PMC_CFU_STREAM_SIZE  0x1000
+#define MM_PMC_CFU_SFR  0xf12c1000
+#define MM_PMC_CFU_SFR_SIZE 0x1000
+#define MM_PMC_CFU_FDRO 0xf12c2000
+#define MM_PMC_CFU_FDRO_SIZE0x1000
+#define MM_PMC_CFU_STREAM_2 0xf1f8
+#define MM_PMC_CFU_STREAM_2_SIZE0x4
+
 #define MM_PMC_CRP  0xf126U
 #define MM_PMC_CRP_SIZE 0x1
 #define MM_PMC_RTC  0xf12a
-- 
2.34.1




[PATCH v2 6/8] hw/misc: Introduce a model of Xilinx Versal's CFRAME_BCAST_REG

2023-08-10 Thread Francisco Iglesias
Introduce a model of Xilinx Versal's Configuration Frame broadcast
controller (CFRAME_BCAST_REG).

Signed-off-by: Francisco Iglesias 
---
 hw/misc/xlnx-versal-cframe-reg.c | 161 +++
 include/hw/misc/xlnx-versal-cframe-reg.h |  17 +++
 2 files changed, 178 insertions(+)

diff --git a/hw/misc/xlnx-versal-cframe-reg.c b/hw/misc/xlnx-versal-cframe-reg.c
index 401bd7a4a9..686425756b 100644
--- a/hw/misc/xlnx-versal-cframe-reg.c
+++ b/hw/misc/xlnx-versal-cframe-reg.c
@@ -582,6 +582,83 @@ static const MemoryRegionOps cframe_reg_fdri_ops = {
 },
 };
 
+static uint64_t cframes_bcast_reg_read(void *opaque, hwaddr addr, unsigned 
size)
+{
+qemu_log_mask(LOG_GUEST_ERROR, "%s: Unsupported read from addr=%"
+  HWADDR_PRIx "\n", __func__, addr);
+return 0;
+}
+
+static void cframes_bcast_write(XlnxVersalCFrameBcastReg *s, uint8_t reg_addr,
+uint32_t *wfifo)
+{
+XlnxCfiPacket pkt = {
+.reg_addr = reg_addr,
+.data[0] = wfifo[0],
+.data[1] = wfifo[1],
+.data[2] = wfifo[2],
+.data[3] = wfifo[3]
+};
+
+for (int i = 0; i < ARRAY_SIZE(s->cfg.cframe); i++) {
+if (s->cfg.cframe[i]) {
+xlnx_cfi_transfer_packet(s->cfg.cframe[i], );
+}
+}
+}
+
+static void cframes_bcast_reg_write(void *opaque, hwaddr addr, uint64_t value,
+  unsigned size)
+{
+XlnxVersalCFrameBcastReg *s = XLNX_VERSAL_CFRAME_BCAST_REG(opaque);
+uint32_t wfifo[WFIFO_SZ];
+
+if (update_wfifo(addr, value, s->wfifo, wfifo)) {
+uint8_t reg_addr = extract32(addr, 4, 6);
+
+cframes_bcast_write(s, reg_addr, wfifo);
+}
+}
+
+static uint64_t cframes_bcast_fdri_read(void *opaque, hwaddr addr,
+unsigned size)
+{
+qemu_log_mask(LOG_GUEST_ERROR, "%s: Unsupported read from addr=%"
+  HWADDR_PRIx "\n", __func__, addr);
+return 0;
+}
+
+static void cframes_bcast_fdri_write(void *opaque, hwaddr addr, uint64_t value,
+  unsigned size)
+{
+XlnxVersalCFrameBcastReg *s = XLNX_VERSAL_CFRAME_BCAST_REG(opaque);
+uint32_t wfifo[WFIFO_SZ];
+
+if (update_wfifo(addr, value, s->wfifo, wfifo)) {
+cframes_bcast_write(s, CFRAME_FDRI, wfifo);
+}
+}
+
+static const MemoryRegionOps cframes_bcast_reg_reg_ops = {
+.read = cframes_bcast_reg_read,
+.write = cframes_bcast_reg_write,
+.endianness = DEVICE_LITTLE_ENDIAN,
+.valid = {
+.min_access_size = 4,
+.max_access_size = 4,
+},
+};
+
+static const MemoryRegionOps cframes_bcast_reg_fdri_ops = {
+.read = cframes_bcast_fdri_read,
+.write = cframes_bcast_fdri_write,
+.endianness = DEVICE_LITTLE_ENDIAN,
+.valid = {
+.min_access_size = 4,
+.max_access_size = 4,
+},
+};
+
 static void cframe_reg_realize(DeviceState *dev, Error **errp)
 {
 XlnxVersalCFrameReg *s = XLNX_VERSAL_CFRAME_REG(dev);
@@ -719,6 +796,71 @@ static Property cframe_regs_props[] = {
 DEFINE_PROP_END_OF_LIST(),
 };
 
+static void cframe_bcast_reg_init(Object *obj)
+{
+XlnxVersalCFrameBcastReg *s = XLNX_VERSAL_CFRAME_BCAST_REG(obj);
+SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+
+memory_region_init_io(>iomem_reg, obj, _bcast_reg_reg_ops, s,
+  TYPE_XLNX_VERSAL_CFRAME_BCAST_REG, 
KEYHOLE_STREAM_4K);
+memory_region_init_io(>iomem_fdri, obj, _bcast_reg_fdri_ops, s,
+  TYPE_XLNX_VERSAL_CFRAME_BCAST_REG "-fdri",
+  KEYHOLE_STREAM_4K);
+sysbus_init_mmio(sbd, >iomem_reg);
+sysbus_init_mmio(sbd, >iomem_fdri);
+}
+
+static void cframe_bcast_reg_reset_enter(Object *obj, ResetType type)
+{
+XlnxVersalCFrameBcastReg *s = XLNX_VERSAL_CFRAME_BCAST_REG(obj);
+
+memset(s->wfifo, 0, WFIFO_SZ * sizeof(uint32_t));
+}
+
+static const VMStateDescription vmstate_cframe_bcast_reg = {
+.name = TYPE_XLNX_VERSAL_CFRAME_BCAST_REG,
+.version_id = 1,
+.minimum_version_id = 1,
+.fields = (VMStateField[]) {
+VMSTATE_UINT32_ARRAY(wfifo, XlnxVersalCFrameBcastReg, 4),
+VMSTATE_END_OF_LIST(),
+}
+};
+
+static Property cframe_bcast_regs_props[] = {
+DEFINE_PROP_LINK("cframe0", XlnxVersalCFrameBcastReg, cfg.cframe[0],
+ TYPE_XLNX_CFI_IF, XlnxCfiIf *),
+DEFINE_PROP_LINK("cframe1", XlnxVersalCFrameBcastReg, cfg.cframe[1],
+ TYPE_XLNX_CFI_IF, XlnxCfiIf *),
+DEFINE_PROP_LINK("cframe2", XlnxVersalCFrameBcastReg, cfg.cframe[2],
+ TYPE_XLNX_CFI_IF, XlnxCfiIf *),
+DEFINE_PROP_LINK("cframe3", XlnxVersalCFrameBcastReg, cfg.cframe[3],
+ TYPE_XLNX_CFI_IF, XlnxCfiIf *),
+DEFINE_PROP_LINK("cframe4", XlnxVersalCFrameBcastReg, cfg.cframe[4],
+ TYPE_XLNX_C

[PATCH v2 2/8] hw/misc: Introduce a model of Xilinx Versal's CFU_APB

2023-08-10 Thread Francisco Iglesias
Introduce a model of the software programming interface (CFU_APB) of
Xilinx Versal's Configuration Frame Unit.

Signed-off-by: Francisco Iglesias 
---
 MAINTAINERS   |   2 +
 hw/misc/meson.build   |   1 +
 hw/misc/xlnx-versal-cfu.c | 380 ++
 include/hw/misc/xlnx-versal-cfu.h | 231 ++
 4 files changed, 614 insertions(+)
 create mode 100644 hw/misc/xlnx-versal-cfu.c
 create mode 100644 include/hw/misc/xlnx-versal-cfu.h

diff --git a/MAINTAINERS b/MAINTAINERS
index e0cd365462..847b997d73 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1039,6 +1039,8 @@ M: Francisco Iglesias 
 S: Maintained
 F: hw/misc/xlnx-cfi-if.c
 F: include/hw/misc/xlnx-cfi-if.h
+F: hw/misc/xlnx-versal-cfu.c
+F: include/hw/misc/xlnx-versal-cfu.h
 
 STM32F100
 M: Alexandre Iooss 
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
index 0c562f5e3e..d95cc3fd87 100644
--- a/hw/misc/meson.build
+++ b/hw/misc/meson.build
@@ -97,6 +97,7 @@ specific_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: 
files('xlnx-versal-crl.c'))
 system_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files(
   'xlnx-versal-xramc.c',
   'xlnx-versal-pmc-iou-slcr.c',
+  'xlnx-versal-cfu.c',
   'xlnx-cfi-if.c',
 ))
 system_ss.add(when: 'CONFIG_STM32F2XX_SYSCFG', if_true: 
files('stm32f2xx_syscfg.c'))
diff --git a/hw/misc/xlnx-versal-cfu.c b/hw/misc/xlnx-versal-cfu.c
new file mode 100644
index 00..b2dc6ab211
--- /dev/null
+++ b/hw/misc/xlnx-versal-cfu.c
@@ -0,0 +1,380 @@
+/*
+ * QEMU model of the CFU Configuration Unit.
+ *
+ * Copyright (C) 2023, Advanced Micro Devices, Inc.
+ *
+ * Written by Edgar E. Iglesias ,
+ *Sai Pavan Boddu ,
+ *Francisco Iglesias 
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "hw/sysbus.h"
+#include "hw/register.h"
+#include "hw/irq.h"
+#include "qemu/bitops.h"
+#include "qemu/log.h"
+#include "qemu/units.h"
+#include "migration/vmstate.h"
+#include "hw/qdev-properties.h"
+#include "hw/qdev-properties-system.h"
+#include "hw/misc/xlnx-versal-cfu.h"
+
+#ifndef XLNX_VERSAL_CFU_APB_ERR_DEBUG
+#define XLNX_VERSAL_CFU_APB_ERR_DEBUG 0
+#endif
+
+#define KEYHOLE_STREAM_4K (4 * KiB)
+#define KEYHOLE_STREAM_256K (256 * KiB)
+#define CFRAME_BROADCAST_ROW 0x1F
+
+bool update_wfifo(hwaddr addr, uint64_t value,
+  uint32_t *wfifo, uint32_t *wfifo_ret)
+{
+unsigned int idx = extract32(addr, 2, 2);
+
+wfifo[idx] = value;
+
+if (idx == 3) {
+memcpy(wfifo_ret, wfifo, WFIFO_SZ * sizeof(uint32_t));
+memset(wfifo, 0, WFIFO_SZ * sizeof(uint32_t));
+return true;
+}
+
+return false;
+}
+
+static void cfu_imr_update_irq(XlnxVersalCFUAPB *s)
+{
+bool pending = s->regs[R_CFU_ISR] & ~s->regs[R_CFU_IMR];
+qemu_set_irq(s->irq_cfu_imr, pending);
+}
+
+static void cfu_isr_postw(RegisterInfo *reg, uint64_t val64)
+{
+XlnxVersalCFUAPB *s = XLNX_VERSAL_CFU_APB(reg->opaque);
+cfu_imr_update_irq(s);
+}
+
+static uint64_t cfu_ier_prew(RegisterInfo *reg, uint64_t val64)
+{
+XlnxVersalCFUAPB *s = XLNX_VERSAL_CFU_APB(reg->opaque);
+uint32_t val = val64;
+
+s->regs[R_CFU_IMR] &= ~val;
+cfu_imr_update_irq(s);
+return 0;
+}
+
+static uint64_t cfu_idr_prew(RegisterInfo *reg, uint64_t val64)
+{
+XlnxVersalCFUAPB *s = XLNX_VERSAL_CFU_APB(reg->opaque);
+uint32_t val = val64;
+
+s->regs[R_CFU_IMR] |= val;
+cfu_imr_update_irq(s);
+return 0;
+}
+
+static uint64_t cfu_itr_prew(RegisterInfo *reg, uint64_t val64)
+{
+XlnxVersalCFUAPB *s = XLNX_VERSAL_CFU_APB(reg->opaque);
+uint32_t val = val64;
+
+s->regs[R_CFU_ISR] |= val;
+cfu_imr_update_irq(s);
+return 0;
+}
+
+static void cfu_fgcr_postw(RegisterInfo *reg, uint64_t val64)
+{
+XlnxVersalCFUAPB *s = XLNX_VERSAL_CFU_APB(reg->opaque);
+uint32_t val = (uint32_t)val64;
+
+/* Do a scan. It always looks good. */
+if (FIELD_EX32(val, CFU_FGCR, SC_HBC_TRIGGER)) {
+ARRAY_FIELD_DP32(s->regs, CFU_STATUS, SCAN_CLEAR_PASS, 1);
+ARRAY_FIELD_DP32(s->regs, CFU_STATUS, SCAN_CLEAR_DONE, 1);
+}
+}
+
+static const RegisterAccessInfo cfu_apb_regs_info[] = {
+{   .name = "CFU_ISR",  .addr = A_CFU_ISR,
+.rsvd = 0xfc00,
+.w1c = 0x3ff,
+.post_write = cfu_isr_postw,
+},{ .name = "CFU_IMR",  .addr = A_CFU_IMR,
+.reset = 0x3ff,
+.rsvd = 0xfc00,
+.ro = 0x3ff,
+},{ .name = "CFU_IER",  .addr = A_CFU_IER,
+.rsvd = 0xfc00,
+.pre_write = cfu_ier_prew,
+},{ .name = "CFU_IDR",  .addr = A_CFU_IDR,
+.rsvd = 0xfc00,
+.pre_write = cfu_idr_prew,
+},{ .name = "CFU_ITR",  .addr = A_CFU_ITR,
+.rsvd = 0xfc00,
+.pre_write = cf

[PATCH v2 4/8] hw/misc/xlnx-versal-cfu: Introduce a model of Xilinx Versal's CFU_SFR

2023-08-10 Thread Francisco Iglesias
Introduce a model of Xilinx Versal's Configuration Frame Unit's Single
Frame Read port (CFU_SFR).

Signed-off-by: Francisco Iglesias 
---
 hw/misc/xlnx-versal-cfu.c | 87 +++
 include/hw/misc/xlnx-versal-cfu.h | 15 ++
 2 files changed, 102 insertions(+)

diff --git a/hw/misc/xlnx-versal-cfu.c b/hw/misc/xlnx-versal-cfu.c
index 255c1bf4b8..8e588ac1d8 100644
--- a/hw/misc/xlnx-versal-cfu.c
+++ b/hw/misc/xlnx-versal-cfu.c
@@ -264,6 +264,31 @@ static void cfu_stream_write(void *opaque, hwaddr addr, 
uint64_t value,
 }
 }
 
+static uint64_t cfu_sfr_read(void *opaque, hwaddr addr, unsigned size)
+{
+qemu_log_mask(LOG_GUEST_ERROR, "%s: Unsupported read from addr=%"
+  HWADDR_PRIx "\n", __func__, addr);
+return 0;
+}
+
+static void cfu_sfr_write(void *opaque, hwaddr addr, uint64_t value,
+  unsigned size)
+{
+XlnxVersalCFUSFR *s = XLNX_VERSAL_CFU_SFR(opaque);
+uint32_t wfifo[WFIFO_SZ];
+
+if (update_wfifo(addr, value, s->wfifo, wfifo)) {
+uint8_t row_addr = extract32(wfifo[0], 23, 5);
+uint32_t frame_addr = extract32(wfifo[0], 0, 23);
+XlnxCfiPacket pkt = { .reg_addr = CFRAME_SFR,
+  .data[0] = frame_addr };
+
+if (s->cfg.cfu) {
+cfu_transfer_cfi_packet(s->cfg.cfu, row_addr, );
+}
+}
+}
+
 static uint64_t cfu_fdro_read(void *opaque, hwaddr addr, unsigned size)
 {
 XlnxVersalCFUFDRO *s = XLNX_VERSAL_CFU_FDRO(opaque);
@@ -293,6 +318,16 @@ static const MemoryRegionOps cfu_stream_ops = {
 },
 };
 
+static const MemoryRegionOps cfu_sfr_ops = {
+.read = cfu_sfr_read,
+.write = cfu_sfr_write,
+.endianness = DEVICE_LITTLE_ENDIAN,
+.valid = {
+.min_access_size = 4,
+.max_access_size = 4,
+},
+};
+
 static const MemoryRegionOps cfu_fdro_ops = {
 .read = cfu_fdro_read,
 .write = cfu_fdro_write,
@@ -334,6 +369,23 @@ static void cfu_apb_init(Object *obj)
 sysbus_init_irq(sbd, >irq_cfu_imr);
 }
 
+static void cfu_sfr_init(Object *obj)
+{
+XlnxVersalCFUSFR *s = XLNX_VERSAL_CFU_SFR(obj);
+SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+
+memory_region_init_io(>iomem_sfr, obj, _sfr_ops, s,
+  TYPE_XLNX_VERSAL_CFU_SFR, KEYHOLE_STREAM_4K);
+sysbus_init_mmio(sbd, >iomem_sfr);
+}
+
+static void cfu_sfr_reset_enter(Object *obj, ResetType type)
+{
+XlnxVersalCFUSFR *s = XLNX_VERSAL_CFU_SFR(obj);
+
+memset(s->wfifo, 0, WFIFO_SZ * sizeof(uint32_t));
+}
+
 static void cfu_fdro_init(Object *obj)
 {
 XlnxVersalCFUFDRO *s = XLNX_VERSAL_CFU_FDRO(obj);
@@ -401,6 +453,12 @@ static Property cfu_props[] = {
 DEFINE_PROP_END_OF_LIST(),
 };
 
+static Property cfu_sfr_props[] = {
+DEFINE_PROP_LINK("cfu", XlnxVersalCFUSFR, cfg.cfu,
+ TYPE_XLNX_VERSAL_CFU_APB, XlnxVersalCFUAPB *),
+DEFINE_PROP_END_OF_LIST(),
+};
+
 static const VMStateDescription vmstate_cfu_apb = {
 .name = TYPE_XLNX_VERSAL_CFU_APB,
 .version_id = 1,
@@ -423,6 +481,16 @@ static const VMStateDescription vmstate_cfu_fdro = {
 }
 };
 
+static const VMStateDescription vmstate_cfu_sfr = {
+.name = TYPE_XLNX_VERSAL_CFU_SFR,
+.version_id = 1,
+.minimum_version_id = 1,
+.fields = (VMStateField[]) {
+VMSTATE_UINT32_ARRAY(wfifo, XlnxVersalCFUSFR, 4),
+VMSTATE_END_OF_LIST(),
+}
+};
+
 static void cfu_apb_class_init(ObjectClass *klass, void *data)
 {
 DeviceClass *dc = DEVICE_CLASS(klass);
@@ -443,6 +511,16 @@ static void cfu_fdro_class_init(ObjectClass *klass, void 
*data)
 rc->phases.enter = cfu_fdro_reset_enter;
 }
 
+static void cfu_sfr_class_init(ObjectClass *klass, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(klass);
+ResettableClass *rc = RESETTABLE_CLASS(klass);
+
+device_class_set_props(dc, cfu_sfr_props);
+dc->vmsd = _cfu_sfr;
+rc->phases.enter = cfu_sfr_reset_enter;
+}
+
 static const TypeInfo cfu_apb_info = {
 .name  = TYPE_XLNX_VERSAL_CFU_APB,
 .parent= TYPE_SYS_BUS_DEVICE,
@@ -467,10 +545,19 @@ static const TypeInfo cfu_fdro_info = {
 }
 };
 
+static const TypeInfo cfu_sfr_info = {
+.name  = TYPE_XLNX_VERSAL_CFU_SFR,
+.parent= TYPE_SYS_BUS_DEVICE,
+.instance_size = sizeof(XlnxVersalCFUSFR),
+.class_init= cfu_sfr_class_init,
+.instance_init = cfu_sfr_init,
+};
+
 static void cfu_apb_register_types(void)
 {
 type_register_static(_apb_info);
 type_register_static(_fdro_info);
+type_register_static(_sfr_info);
 }
 
 type_init(cfu_apb_register_types)
diff --git a/include/hw/misc/xlnx-versal-cfu.h 
b/include/hw/misc/xlnx-versal-cfu.h
index 73e9a21af4..86fb841053 100644
--- a/include/hw/misc/xlnx-versal-cfu.h
+++ b/include/hw/misc/xlnx-versal-cfu.h
@@ -28,6 +28,9 @@ OBJECT_DECLARE_SIMPLE_TYPE(XlnxVersalCFUAPB, 
XLNX_VERSAL_CFU_A

[PATCH v2 1/8] hw/misc: Introduce the Xilinx CFI interface

2023-08-10 Thread Francisco Iglesias
Introduce the Xilinx Configuration Frame Interface (CFI) for transmitting
CFI data packets between the Xilinx Configuration Frame Unit models
(CFU_APB, CFU_FDRO and CFU_SFR), the Xilinx CFRAME controller (CFRAME_REG)
and the Xilinx CFRAME broadcast controller (CFRAME_BCAST_REG) models (when
emulating bitstream programming and readback).

Signed-off-by: Francisco Iglesias 
Reviewed-by: Sai Pavan Boddu 
Acked-by: Edgar E. Iglesias 
---
 MAINTAINERS   |  6 
 hw/misc/meson.build   |  1 +
 hw/misc/xlnx-cfi-if.c | 34 
 include/hw/misc/xlnx-cfi-if.h | 59 +++
 4 files changed, 100 insertions(+)
 create mode 100644 hw/misc/xlnx-cfi-if.c
 create mode 100644 include/hw/misc/xlnx-cfi-if.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 6111b6b4d9..e0cd365462 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1034,6 +1034,12 @@ S: Maintained
 F: hw/ssi/xlnx-versal-ospi.c
 F: include/hw/ssi/xlnx-versal-ospi.h
 
+Xilinx Versal CFI
+M: Francisco Iglesias 
+S: Maintained
+F: hw/misc/xlnx-cfi-if.c
+F: include/hw/misc/xlnx-cfi-if.h
+
 STM32F100
 M: Alexandre Iooss 
 L: qemu-...@nongnu.org
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
index 892f8b91c5..0c562f5e3e 100644
--- a/hw/misc/meson.build
+++ b/hw/misc/meson.build
@@ -97,6 +97,7 @@ specific_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: 
files('xlnx-versal-crl.c'))
 system_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files(
   'xlnx-versal-xramc.c',
   'xlnx-versal-pmc-iou-slcr.c',
+  'xlnx-cfi-if.c',
 ))
 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'))
diff --git a/hw/misc/xlnx-cfi-if.c b/hw/misc/xlnx-cfi-if.c
new file mode 100644
index 00..c45f05c4aa
--- /dev/null
+++ b/hw/misc/xlnx-cfi-if.c
@@ -0,0 +1,34 @@
+/*
+ * Xilinx CFI interface
+ *
+ * Copyright (C) 2023, Advanced Micro Devices, Inc.
+ *
+ * Written by Francisco Iglesias 
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#include "qemu/osdep.h"
+#include "hw/misc/xlnx-cfi-if.h"
+
+void xlnx_cfi_transfer_packet(XlnxCfiIf *cfi_if, XlnxCfiPacket *pkt)
+{
+XlnxCfiIfClass *xcic = XLNX_CFI_IF_GET_CLASS(cfi_if);
+
+if (xcic->cfi_transfer_packet) {
+xcic->cfi_transfer_packet(cfi_if, pkt);
+}
+}
+
+static const TypeInfo xlnx_cfi_if_info = {
+.name  = TYPE_XLNX_CFI_IF,
+.parent= TYPE_INTERFACE,
+.class_size = sizeof(XlnxCfiIfClass),
+};
+
+static void xlnx_cfi_if_register_types(void)
+{
+type_register_static(_cfi_if_info);
+}
+
+type_init(xlnx_cfi_if_register_types)
+
diff --git a/include/hw/misc/xlnx-cfi-if.h b/include/hw/misc/xlnx-cfi-if.h
new file mode 100644
index 00..f9bd12292d
--- /dev/null
+++ b/include/hw/misc/xlnx-cfi-if.h
@@ -0,0 +1,59 @@
+/*
+ * Xilinx CFI interface
+ *
+ * Copyright (C) 2023, Advanced Micro Devices, Inc.
+ *
+ * Written by Francisco Iglesias 
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#ifndef XLNX_CFI_IF_H
+#define XLNX_CFI_IF_H 1
+
+#include "qemu/help-texts.h"
+#include "hw/hw.h"
+#include "qom/object.h"
+
+#define TYPE_XLNX_CFI_IF "xlnx-cfi-if"
+typedef struct XlnxCfiIfClass XlnxCfiIfClass;
+DECLARE_CLASS_CHECKERS(XlnxCfiIfClass, XLNX_CFI_IF, TYPE_XLNX_CFI_IF)
+
+#define XLNX_CFI_IF(obj) \
+ INTERFACE_CHECK(XlnxCfiIf, (obj), TYPE_XLNX_CFI_IF)
+
+typedef enum {
+PACKET_TYPE_CFU = 0x52,
+PACKET_TYPE_CFRAME = 0xA1,
+} xlnx_cfi_packet_type;
+
+typedef enum {
+CFRAME_FAR = 1,
+CFRAME_SFR = 2,
+CFRAME_FDRI = 4,
+CFRAME_CMD = 6,
+} xlnx_cfi_reg_addr;
+
+typedef struct XlnxCfiPacket {
+uint8_t reg_addr;
+uint32_t data[4];
+} XlnxCfiPacket;
+
+typedef struct XlnxCfiIf {
+Object Parent;
+} XlnxCfiIf;
+
+typedef struct XlnxCfiIfClass {
+InterfaceClass parent;
+
+void (*cfi_transfer_packet)(XlnxCfiIf *cfi_if, XlnxCfiPacket *pkt);
+} XlnxCfiIfClass;
+
+/**
+ * Transfer a XlnxCfiPacket.
+ *
+ * @cfi_if: the object implementing this interface
+ * @XlnxCfiPacket: a pointer to the XlnxCfiPacket to transfer
+ */
+void xlnx_cfi_transfer_packet(XlnxCfiIf *cfi_if, XlnxCfiPacket *pkt);
+
+#endif /* XLNX_CFI_IF_H */
-- 
2.34.1




[PATCH v2 0/8] Xilinx Versal CFI support

2023-08-10 Thread Francisco Iglesias
Hi,

This series adds support for the Configuration Frame Unit (CFU) and the
Configuration Frame controllers (CFRAME) to the Xilinx Versal machine
([1], chapter 21) for emulaing bitstream loading and readback.

The series starts by introducing the Xilinx CFI interface that is
thereafter used by the Xilinx CFU components, the Xilinx CFRAME and Xilinx
CFRAME broadcast models for transfering CFI packets between each other.
Thereafter a model of the CFU_APB, CFU_FDRO and CFU_SFR are introduced and
also models of the CFRAME controller and CFRAME broadcast controller.

The series thereafter ends with connecting the models to Xilinx Versal
machine.

Best regards,
Francisco Iglesias

References:
[1] https://docs.xilinx.com/r/en-US/am011-versal-acap-trm/PSM-Local-Registers

Changelog:
v1->v2:
 [PATCH 2]
   * Use KiB when defining KEYHOLE_STREAM_4K/KEYHOLE_STREAM_256K
   * Updated to be able to share wfifo code 

 [PATCH 3]
   * Swap to use Fifo32 instead of GArray in the CFU_FDRO model
   * Add device reset to the CFU_FDRO model

 [PATCH 4]
   * Add device reset to the CFU_SFR model

 [PATCH 5]
   * Use KiB when defining KEYHOLE_STREAM_4K
   * Add comma after CFRAME_CMD_DLPARK
   * Remove backwards compatibility comment (and the 'cfu' alias propname for
 cfg.cfu_fdro)
   * Use Fifo32 inside the XlnxCFrame structure
   * Reworked cframes_reg_pre_save / cframes_reg_post_load

 [PATCH 6]
   * Add device reset to the CFrame broadcast reg model

 [PATCH 8]
   * Switch to use g_autofree instead of explicit g_free


Francisco Iglesias (8):
  hw/misc: Introduce the Xilinx CFI interface
  hw/misc: Introduce a model of Xilinx Versal's CFU_APB
  hw/misc/xlnx-versal-cfu: Introduce a model of Xilinx Versal CFU_FDRO
  hw/misc/xlnx-versal-cfu: Introduce a model of Xilinx Versal's CFU_SFR
  hw/misc: Introduce a model of Xilinx Versal's CFRAME_REG
  hw/misc: Introduce a model of Xilinx Versal's CFRAME_BCAST_REG
  hw/arm/xlnx-versal: Connect the CFU_APB, CFU_FDRO and CFU_SFR
  hw/arm/versal: Connect the CFRAME_REG and CFRAME_BCAST_REG

 MAINTAINERS  |  10 +
 hw/arm/xlnx-versal.c | 155 +++-
 hw/misc/meson.build  |   3 +
 hw/misc/xlnx-cfi-if.c|  34 +
 hw/misc/xlnx-versal-cframe-reg.c | 914 +++
 hw/misc/xlnx-versal-cfu.c| 563 ++
 include/hw/arm/xlnx-versal.h |  85 +++
 include/hw/misc/xlnx-cfi-if.h|  59 ++
 include/hw/misc/xlnx-versal-cframe-reg.h | 306 
 include/hw/misc/xlnx-versal-cfu.h| 258 +++
 10 files changed, 2386 insertions(+), 1 deletion(-)
 create mode 100644 hw/misc/xlnx-cfi-if.c
 create mode 100644 hw/misc/xlnx-versal-cframe-reg.c
 create mode 100644 hw/misc/xlnx-versal-cfu.c
 create mode 100644 include/hw/misc/xlnx-cfi-if.h
 create mode 100644 include/hw/misc/xlnx-versal-cframe-reg.h
 create mode 100644 include/hw/misc/xlnx-versal-cfu.h

-- 
2.34.1




Re: [PATCH v2] hw/arm/xlnx: Connect secondary CGEM IRQs

2023-07-10 Thread Francisco Iglesias


+PMM (I think this one might have fallen throught the cracks)

Best regards,
Francisco Iglesias

On [2023 Jun 18] Sun 00:50:47, Philippe Mathieu-Daudé wrote:
> On 16/6/23 16:38, Kinsey Moore wrote:
> > The Cadence GEM peripherals as configured for Zynq MPSoC and Versal
> > platforms have two priority queues with separate interrupt sources for
> > each. If the interrupt source for the second priority queue is not
> > connected, they work in polling mode only. This change connects the
> > second interrupt source for platforms where it is available. This patch
> > has been tested using the lwIP stack with a Xilinx-supplied driver from
> > their embeddedsw repository.
> > 
> > Signed-off-by: Kinsey Moore 
> > ---
> >   hw/arm/xlnx-versal.c | 12 +++-
> >   hw/arm/xlnx-zynqmp.c | 11 ++-
> >   include/hw/arm/xlnx-versal.h |  1 +
> >   include/hw/arm/xlnx-zynqmp.h |  1 +
> >   4 files changed, 23 insertions(+), 2 deletions(-)
> 
> Reviewed-by: Philippe Mathieu-Daudé 
> 
> 



[PATCH v1 0/8] Xilinx Versal CFI support

2023-07-10 Thread Francisco Iglesias
Hi,

This series adds support for the Configuration Frame Unit (CFU) and the
Configuration Frame controllers (CFRAME) to the Xilinx Versal machine
([1], chapter 21) for emulaing bitstream loading and readback.

The series starts by introducing the Xilinx CFI interface that is
thereafter used by the Xilinx CFU components, the Xilinx CFRAME and Xilinx
CFRAME broadcast models for transfering CFI packets between each other.
Thereafter a model of the CFU_APB, CFU_FDRO and CFU_SFR are introduced and
also models of the CFRAME controller and CFRAME broadcast controller.

The series thereafter ends with connecting the models to Xilinx Versal
machine.

Best regards,
Francisco Iglesias

References:
[1] https://docs.xilinx.com/r/en-US/am011-versal-acap-trm/PSM-Local-Registers


Francisco Iglesias (8):
  hw/misc: Introduce the Xilinx CFI interface
  hw/misc: Introduce a model of Xilinx Versal's CFU_APB
  hw/misc/xlnx-versal-cfu: Introduce a model of Xilinx Versal CFU_FDRO
  hw/misc/xlnx-versal-cfu: Introduce a model of Xilinx Versal's CFU_SFR
  hw/misc: Introduce a model of Xilinx Versal's CFRAME_REG
  hw/misc: Introduce a model of Xilinx Versal's CFRAME_BCAST_REG
  hw/arm/xlnx-versal: Connect the CFU_APB, CFU_FDRO and CFU_SFR
  hw/arm/versal: Connect the CFRAME_REG and CFRAME_BCAST_REG

 MAINTAINERS  |  10 +
 hw/arm/xlnx-versal.c | 158 +++-
 hw/misc/meson.build  |   3 +
 hw/misc/xlnx-cfi-if.c|  34 +
 hw/misc/xlnx-versal-cframe-reg.c | 887 +++
 hw/misc/xlnx-versal-cfu.c| 566 +++
 include/hw/arm/xlnx-versal.h |  85 +++
 include/hw/misc/xlnx-cfi-if.h|  59 ++
 include/hw/misc/xlnx-versal-cframe-reg.h | 305 
 include/hw/misc/xlnx-versal-cfu.h| 238 ++
 10 files changed, 2344 insertions(+), 1 deletion(-)
 create mode 100644 hw/misc/xlnx-cfi-if.c
 create mode 100644 hw/misc/xlnx-versal-cframe-reg.c
 create mode 100644 hw/misc/xlnx-versal-cfu.c
 create mode 100644 include/hw/misc/xlnx-cfi-if.h
 create mode 100644 include/hw/misc/xlnx-versal-cframe-reg.h
 create mode 100644 include/hw/misc/xlnx-versal-cfu.h

-- 
2.34.1




[PATCH v1 3/8] hw/misc/xlnx-versal-cfu: Introduce a model of Xilinx Versal CFU_FDRO

2023-07-10 Thread Francisco Iglesias
Introduce a model of Xilinx Versal's Configuration Frame Unit's data out
port (CFU_FDRO).

Signed-off-by: Francisco Iglesias 
---
 hw/misc/xlnx-versal-cfu.c | 105 ++
 include/hw/misc/xlnx-versal-cfu.h |  11 
 2 files changed, 116 insertions(+)

diff --git a/hw/misc/xlnx-versal-cfu.c b/hw/misc/xlnx-versal-cfu.c
index cbd17d2351..528090ef1b 100644
--- a/hw/misc/xlnx-versal-cfu.c
+++ b/hw/misc/xlnx-versal-cfu.c
@@ -257,6 +257,26 @@ static void cfu_stream_write(void *opaque, hwaddr addr, 
uint64_t value,
 }
 }
 
+static uint64_t cfu_fdro_read(void *opaque, hwaddr addr, unsigned size)
+{
+XlnxVersalCFUFDRO *s = XLNX_VERSAL_CFU_FDRO(opaque);
+uint64_t ret = 0;
+
+if (s->fdro_data->len) {
+ret = g_array_index(s->fdro_data, uint32_t, 0);
+g_array_remove_index(s->fdro_data, 0);
+}
+
+return ret;
+}
+
+static void cfu_fdro_write(void *opaque, hwaddr addr, uint64_t value,
+   unsigned size)
+{
+qemu_log_mask(LOG_GUEST_ERROR, "%s: Unsupported write from addr=%"
+  HWADDR_PRIx "\n", __func__, addr);
+}
+
 static const MemoryRegionOps cfu_stream_ops = {
 .read = cfu_stream_read,
 .write = cfu_stream_write,
@@ -267,6 +287,16 @@ static const MemoryRegionOps cfu_stream_ops = {
 },
 };
 
+static const MemoryRegionOps cfu_fdro_ops = {
+.read = cfu_fdro_read,
+.write = cfu_fdro_write,
+.endianness = DEVICE_LITTLE_ENDIAN,
+.valid = {
+.min_access_size = 4,
+.max_access_size = 4,
+},
+};
+
 static void cfu_apb_init(Object *obj)
 {
 XlnxVersalCFUAPB *s = XLNX_VERSAL_CFU_APB(obj);
@@ -298,6 +328,24 @@ static void cfu_apb_init(Object *obj)
 sysbus_init_irq(sbd, >irq_cfu_imr);
 }
 
+static void cfu_fdro_init(Object *obj)
+{
+XlnxVersalCFUFDRO *s = XLNX_VERSAL_CFU_FDRO(obj);
+SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+
+memory_region_init_io(>iomem_fdro, obj, _fdro_ops, s,
+  TYPE_XLNX_VERSAL_CFU_FDRO, KEYHOLE_STREAM_4K);
+sysbus_init_mmio(sbd, >iomem_fdro);
+s->fdro_data = g_array_new(FALSE, FALSE, sizeof(uint32_t));
+}
+
+static void cfu_fdro_cfi_transfer_packet(XlnxCfiIf *cfi_if, XlnxCfiPacket *pkt)
+{
+XlnxVersalCFUFDRO *s = XLNX_VERSAL_CFU_FDRO(cfi_if);
+
+g_array_append_vals(s->fdro_data, >data[0], 4);
+}
+
 static Property cfu_props[] = {
 DEFINE_PROP_LINK("cframe0", XlnxVersalCFUAPB, cfg.cframe[0],
  TYPE_XLNX_CFI_IF, XlnxCfiIf *),
@@ -344,6 +392,41 @@ static const VMStateDescription vmstate_cfu_apb = {
 }
 };
 
+static int cfdro_reg_pre_save(void *opaque)
+{
+XlnxVersalCFUFDRO *s = XLNX_VERSAL_CFU_FDRO(opaque);
+
+if (s->fdro_data->len) {
+s->ro_data = (uint32_t *) s->fdro_data->data;
+s->ro_dlen = s->fdro_data->len;
+}
+
+return 0;
+}
+
+static int cfdro_reg_post_load(void *opaque, int version_id)
+{
+XlnxVersalCFUFDRO *s = XLNX_VERSAL_CFU_FDRO(opaque);
+
+if (s->ro_dlen) {
+g_array_append_vals(s->fdro_data, s->ro_data, s->ro_dlen);
+}
+return 0;
+}
+
+static const VMStateDescription vmstate_cfu_fdro = {
+.name = TYPE_XLNX_VERSAL_CFU_FDRO,
+.version_id = 1,
+.minimum_version_id = 1,
+.pre_save = cfdro_reg_pre_save,
+.post_load = cfdro_reg_post_load,
+.fields = (VMStateField[]) {
+VMSTATE_VARRAY_UINT32_ALLOC(ro_data, XlnxVersalCFUFDRO, ro_dlen,
+0, vmstate_info_uint32, uint32_t),
+VMSTATE_END_OF_LIST(),
+}
+};
+
 static void cfu_apb_class_init(ObjectClass *klass, void *data)
 {
 DeviceClass *dc = DEVICE_CLASS(klass);
@@ -353,6 +436,15 @@ static void cfu_apb_class_init(ObjectClass *klass, void 
*data)
 device_class_set_props(dc, cfu_props);
 }
 
+static void cfu_fdro_class_init(ObjectClass *klass, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(klass);
+XlnxCfiIfClass *xcic = XLNX_CFI_IF_CLASS(klass);
+
+dc->vmsd = _cfu_fdro;
+xcic->cfi_transfer_packet = cfu_fdro_cfi_transfer_packet;
+}
+
 static const TypeInfo cfu_apb_info = {
 .name  = TYPE_XLNX_VERSAL_CFU_APB,
 .parent= TYPE_SYS_BUS_DEVICE,
@@ -365,9 +457,22 @@ static const TypeInfo cfu_apb_info = {
 }
 };
 
+static const TypeInfo cfu_fdro_info = {
+.name  = TYPE_XLNX_VERSAL_CFU_FDRO,
+.parent= TYPE_SYS_BUS_DEVICE,
+.instance_size = sizeof(XlnxVersalCFUFDRO),
+.class_init= cfu_fdro_class_init,
+.instance_init = cfu_fdro_init,
+.interfaces = (InterfaceInfo[]) {
+{ TYPE_XLNX_CFI_IF },
+{ }
+}
+};
+
 static void cfu_apb_register_types(void)
 {
 type_register_static(_apb_info);
+type_register_static(_fdro_info);
 }
 
 type_init(cfu_apb_register_types)
diff --git a/include/hw/misc/xlnx-versal-cfu.h 
b/include/hw/misc/xlnx-versal-cfu.h
index 4936d6e5f0..3603

[PATCH v1 7/8] hw/arm/xlnx-versal: Connect the CFU_APB, CFU_FDRO and CFU_SFR

2023-07-10 Thread Francisco Iglesias
Connect the Configuration Frame Unit (CFU_APB, CFU_FDRO and CFU_SFR) to
the Versal machine.

Signed-off-by: Francisco Iglesias 
---
 hw/arm/xlnx-versal.c | 42 
 include/hw/arm/xlnx-versal.h | 16 ++
 2 files changed, 58 insertions(+)

diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
index 60bf5fe657..3f4b4b1560 100644
--- a/hw/arm/xlnx-versal.c
+++ b/hw/arm/xlnx-versal.c
@@ -570,6 +570,47 @@ static void versal_create_ospi(Versal *s, qemu_irq *pic)
 qdev_connect_gpio_out(orgate, 0, pic[VERSAL_OSPI_IRQ]);
 }
 
+static void versal_create_cfu(Versal *s, qemu_irq *pic)
+{
+SysBusDevice *sbd;
+
+/* CFU FDRO */
+object_initialize_child(OBJECT(s), "cfu-fdro", >pmc.cfu_fdro,
+TYPE_XLNX_VERSAL_CFU_FDRO);
+sbd = SYS_BUS_DEVICE(>pmc.cfu_fdro);
+
+sysbus_realize(sbd, _fatal);
+memory_region_add_subregion(>mr_ps, MM_PMC_CFU_FDRO,
+sysbus_mmio_get_region(sbd, 0));
+
+/* CFU APB */
+object_initialize_child(OBJECT(s), "cfu-apb", >pmc.cfu_apb,
+TYPE_XLNX_VERSAL_CFU_APB);
+sbd = SYS_BUS_DEVICE(>pmc.cfu_apb);
+
+sysbus_realize(sbd, _fatal);
+memory_region_add_subregion(>mr_ps, MM_PMC_CFU_APB,
+sysbus_mmio_get_region(sbd, 0));
+memory_region_add_subregion(>mr_ps, MM_PMC_CFU_STREAM,
+sysbus_mmio_get_region(sbd, 1));
+memory_region_add_subregion(>mr_ps, MM_PMC_CFU_STREAM_2,
+sysbus_mmio_get_region(sbd, 2));
+sysbus_connect_irq(sbd, 0, pic[VERSAL_CFU_IRQ_0]);
+
+/* CFU SFR */
+object_initialize_child(OBJECT(s), "cfu-sfr", >pmc.cfu_sfr,
+TYPE_XLNX_VERSAL_CFU_SFR);
+
+sbd = SYS_BUS_DEVICE(>pmc.cfu_sfr);
+
+object_property_set_link(OBJECT(>pmc.cfu_sfr),
+"cfu", OBJECT(>pmc.cfu_apb), _abort);
+
+sysbus_realize(sbd, _fatal);
+memory_region_add_subregion(>mr_ps, MM_PMC_CFU_SFR,
+sysbus_mmio_get_region(sbd, 0));
+}
+
 static void versal_create_crl(Versal *s, qemu_irq *pic)
 {
 SysBusDevice *sbd;
@@ -763,6 +804,7 @@ static void versal_realize(DeviceState *dev, Error **errp)
 versal_create_pmc_iou_slcr(s, pic);
 versal_create_ospi(s, pic);
 versal_create_crl(s, pic);
+versal_create_cfu(s, pic);
 versal_map_ddr(s);
 versal_unimp(s);
 
diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
index 39ee31185c..29b9c60301 100644
--- a/include/hw/arm/xlnx-versal.h
+++ b/include/hw/arm/xlnx-versal.h
@@ -32,6 +32,7 @@
 #include "hw/misc/xlnx-versal-crl.h"
 #include "hw/misc/xlnx-versal-pmc-iou-slcr.h"
 #include "hw/net/xlnx-versal-canfd.h"
+#include "hw/misc/xlnx-versal-cfu.h"
 
 #define TYPE_XLNX_VERSAL "xlnx-versal"
 OBJECT_DECLARE_SIMPLE_TYPE(Versal, XLNX_VERSAL)
@@ -117,6 +118,9 @@ struct Versal {
 XlnxEFuse efuse;
 XlnxVersalEFuseCtrl efuse_ctrl;
 XlnxVersalEFuseCache efuse_cache;
+XlnxVersalCFUAPB cfu_apb;
+XlnxVersalCFUFDRO cfu_fdro;
+XlnxVersalCFUSFR cfu_sfr;
 
 OrIRQState apb_irq_orgate;
 } pmc;
@@ -147,6 +151,7 @@ struct Versal {
 #define VERSAL_GEM1_WAKE_IRQ_0 59
 #define VERSAL_ADMA_IRQ_0  60
 #define VERSAL_XRAM_IRQ_0  79
+#define VERSAL_CFU_IRQ_0   120
 #define VERSAL_PMC_APB_IRQ 121
 #define VERSAL_OSPI_IRQ124
 #define VERSAL_SD0_IRQ_0   126
@@ -240,6 +245,17 @@ struct Versal {
 #define MM_PMC_EFUSE_CACHE  0xf125
 #define MM_PMC_EFUSE_CACHE_SIZE 0x00C00
 
+#define MM_PMC_CFU_APB  0xf12b
+#define MM_PMC_CFU_APB_SIZE 0x1
+#define MM_PMC_CFU_STREAM   0xf12c
+#define MM_PMC_CFU_STREAM_SIZE  0x1000
+#define MM_PMC_CFU_SFR  0xf12c1000
+#define MM_PMC_CFU_SFR_SIZE 0x1000
+#define MM_PMC_CFU_FDRO 0xf12c2000
+#define MM_PMC_CFU_FDRO_SIZE0x1000
+#define MM_PMC_CFU_STREAM_2 0xf1f8
+#define MM_PMC_CFU_STREAM_2_SIZE0x4
+
 #define MM_PMC_CRP  0xf126U
 #define MM_PMC_CRP_SIZE 0x1
 #define MM_PMC_RTC  0xf12a
-- 
2.34.1




[PATCH v1 5/8] hw/misc: Introduce a model of Xilinx Versal's CFRAME_REG

2023-07-10 Thread Francisco Iglesias
Introduce a model of Xilinx Versal's Configuration Frame controller
(CFRAME_REG).

Signed-off-by: Francisco Iglesias 
---
 MAINTAINERS  |   2 +
 hw/misc/meson.build  |   1 +
 hw/misc/xlnx-versal-cframe-reg.c | 714 +++
 include/hw/misc/xlnx-versal-cframe-reg.h | 288 +
 4 files changed, 1005 insertions(+)
 create mode 100644 hw/misc/xlnx-versal-cframe-reg.c
 create mode 100644 include/hw/misc/xlnx-versal-cframe-reg.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 2bc7ab42ae..1fdd6927b7 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1043,6 +1043,8 @@ F: hw/misc/xlnx-cfi-if.c
 F: include/hw/misc/xlnx-cfi-if.h
 F: hw/misc/xlnx-versal-cfu.c
 F: include/hw/misc/xlnx-versal-cfu.h
+F: hw/misc/xlnx-versal-cframe-reg.c
+F: include/hw/misc/xlnx-versal-cframe-reg.h
 
 STM32F100
 M: Alexandre Iooss 
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
index c88051aa51..f1ef952004 100644
--- a/hw/misc/meson.build
+++ b/hw/misc/meson.build
@@ -98,6 +98,7 @@ system_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files(
   'xlnx-versal-pmc-iou-slcr.c',
   'xlnx-versal-cfu.c',
   'xlnx-cfi-if.c',
+  'xlnx-versal-cframe-reg.c',
 ))
 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'))
diff --git a/hw/misc/xlnx-versal-cframe-reg.c b/hw/misc/xlnx-versal-cframe-reg.c
new file mode 100644
index 00..7e3420e14d
--- /dev/null
+++ b/hw/misc/xlnx-versal-cframe-reg.c
@@ -0,0 +1,714 @@
+/*
+ * QEMU model of the Configuration Frame Control module
+ *
+ * Copyright (C) 2023, Advanced Micro Devices, Inc.
+ *
+ * Written by Francisco Iglesias 
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "hw/sysbus.h"
+#include "hw/register.h"
+#include "hw/registerfields.h"
+#include "qemu/bitops.h"
+#include "qemu/log.h"
+#include "qapi/error.h"
+#include "hw/qdev-properties.h"
+#include "migration/vmstate.h"
+#include "hw/irq.h"
+#include "hw/misc/xlnx-versal-cframe-reg.h"
+
+#ifndef XLNX_VERSAL_CFRAME_REG_ERR_DEBUG
+#define XLNX_VERSAL_CFRAME_REG_ERR_DEBUG 0
+#endif
+
+#define KEYHOLE_STREAM_4K 0x1000
+
+#define MAX_BLOCKTYPE 6
+#define MAX_BLOCKTYPE_FRAMES 0xF
+
+enum {
+CFRAME_CMD_WCFG = 1,
+CFRAME_CMD_ROWON = 2,
+CFRAME_CMD_ROWOFF = 3,
+CFRAME_CMD_RCFG = 4,
+CFRAME_CMD_DLPARK = 5
+};
+
+static void cfrm_imr_update_irq(XlnxVersalCFrameReg *s)
+{
+bool pending = s->regs[R_CFRM_ISR0] & ~s->regs[R_CFRM_IMR0];
+qemu_set_irq(s->irq_cfrm_imr, pending);
+}
+
+static void cfrm_isr_postw(RegisterInfo *reg, uint64_t val64)
+{
+XlnxVersalCFrameReg *s = XLNX_VERSAL_CFRAME_REG(reg->opaque);
+cfrm_imr_update_irq(s);
+}
+
+static uint64_t cfrm_ier_prew(RegisterInfo *reg, uint64_t val64)
+{
+XlnxVersalCFrameReg *s = XLNX_VERSAL_CFRAME_REG(reg->opaque);
+
+s->regs[R_CFRM_IMR0] &= ~s->regs[R_CFRM_IER0];
+s->regs[R_CFRM_IER0] = 0;
+cfrm_imr_update_irq(s);
+return 0;
+}
+
+static uint64_t cfrm_idr_prew(RegisterInfo *reg, uint64_t val64)
+{
+XlnxVersalCFrameReg *s = XLNX_VERSAL_CFRAME_REG(reg->opaque);
+
+s->regs[R_CFRM_IMR0] |= s->regs[R_CFRM_IDR0];
+s->regs[R_CFRM_IDR0] = 0;
+cfrm_imr_update_irq(s);
+return 0;
+}
+
+static uint64_t cfrm_itr_prew(RegisterInfo *reg, uint64_t val64)
+{
+XlnxVersalCFrameReg *s = XLNX_VERSAL_CFRAME_REG(reg->opaque);
+
+s->regs[R_CFRM_ISR0] |= s->regs[R_CFRM_ITR0];
+s->regs[R_CFRM_ITR0] = 0;
+cfrm_imr_update_irq(s);
+return 0;
+}
+
+static void cframe_incr_far(XlnxVersalCFrameReg *s)
+{
+uint32_t faddr = ARRAY_FIELD_EX32(s->regs, FAR0, FRAME_ADDR);
+uint32_t blktype = ARRAY_FIELD_EX32(s->regs, FAR0, BLOCKTYPE);
+
+assert(blktype <= MAX_BLOCKTYPE);
+
+faddr++;
+if (faddr > s->cfg.blktype_num_frames[blktype]) {
+/* Restart from 0 and increment block type */
+faddr = 0;
+blktype++;
+
+assert(blktype <= MAX_BLOCKTYPE);
+
+ARRAY_FIELD_DP32(s->regs, FAR0, BLOCKTYPE, blktype);
+}
+
+ARRAY_FIELD_DP32(s->regs, FAR0, FRAME_ADDR, faddr);
+}
+
+static XlnxCFrame *cframes_get_frame(XlnxVersalCFrameReg *s, uint32_t addr)
+{
+for (int i = 0; i < s->cframes->len; i++) {
+XlnxCFrame *f = _array_index(s->cframes, XlnxCFrame, i);
+
+if (f->addr == addr) {
+return f;
+}
+}
+return NULL;
+}
+
+static void cfrm_fdri_post_write(RegisterInfo *reg, uint64_t val)
+{
+XlnxVersalCFrameReg *s = XLNX_VERSAL_CFRAME_REG(reg->opaque);
+
+if (s->row_configured && s->rowon && s->wcfg) {
+XlnxCFrame *new_f = >new_f;
+
+new_f->data[new_f-&

[PATCH v1 1/8] hw/misc: Introduce the Xilinx CFI interface

2023-07-10 Thread Francisco Iglesias
Introduce the Xilinx Configuration Frame Interface (CFI) for transmitting
CFI data packets between the Xilinx Configuration Frame Unit models
(CFU_APB, CFU_FDRO and CFU_SFR), the Xilinx CFRAME controller (CFRAME_REG)
and the Xilinx CFRAME broadcast controller (CFRAME_BCAST_REG) models (when
emulating bitstream programming and readback).

Signed-off-by: Francisco Iglesias 
---
 MAINTAINERS   |  6 
 hw/misc/meson.build   |  1 +
 hw/misc/xlnx-cfi-if.c | 34 
 include/hw/misc/xlnx-cfi-if.h | 59 +++
 4 files changed, 100 insertions(+)
 create mode 100644 hw/misc/xlnx-cfi-if.c
 create mode 100644 include/hw/misc/xlnx-cfi-if.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 1817cfc62f..3ba115bb9b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1036,6 +1036,12 @@ S: Maintained
 F: hw/ssi/xlnx-versal-ospi.c
 F: include/hw/ssi/xlnx-versal-ospi.h
 
+Xilinx Versal CFI
+M: Francisco Iglesias 
+S: Maintained
+F: hw/misc/xlnx-cfi-if.c
+F: include/hw/misc/xlnx-cfi-if.h
+
 STM32F100
 M: Alexandre Iooss 
 L: qemu-...@nongnu.org
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
index 05877f61cc..9971b1e4db 100644
--- a/hw/misc/meson.build
+++ b/hw/misc/meson.build
@@ -96,6 +96,7 @@ specific_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: 
files('xlnx-versal-crl.c'))
 system_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files(
   'xlnx-versal-xramc.c',
   'xlnx-versal-pmc-iou-slcr.c',
+  'xlnx-cfi-if.c',
 ))
 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'))
diff --git a/hw/misc/xlnx-cfi-if.c b/hw/misc/xlnx-cfi-if.c
new file mode 100644
index 00..c45f05c4aa
--- /dev/null
+++ b/hw/misc/xlnx-cfi-if.c
@@ -0,0 +1,34 @@
+/*
+ * Xilinx CFI interface
+ *
+ * Copyright (C) 2023, Advanced Micro Devices, Inc.
+ *
+ * Written by Francisco Iglesias 
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#include "qemu/osdep.h"
+#include "hw/misc/xlnx-cfi-if.h"
+
+void xlnx_cfi_transfer_packet(XlnxCfiIf *cfi_if, XlnxCfiPacket *pkt)
+{
+XlnxCfiIfClass *xcic = XLNX_CFI_IF_GET_CLASS(cfi_if);
+
+if (xcic->cfi_transfer_packet) {
+xcic->cfi_transfer_packet(cfi_if, pkt);
+}
+}
+
+static const TypeInfo xlnx_cfi_if_info = {
+.name  = TYPE_XLNX_CFI_IF,
+.parent= TYPE_INTERFACE,
+.class_size = sizeof(XlnxCfiIfClass),
+};
+
+static void xlnx_cfi_if_register_types(void)
+{
+type_register_static(_cfi_if_info);
+}
+
+type_init(xlnx_cfi_if_register_types)
+
diff --git a/include/hw/misc/xlnx-cfi-if.h b/include/hw/misc/xlnx-cfi-if.h
new file mode 100644
index 00..f9bd12292d
--- /dev/null
+++ b/include/hw/misc/xlnx-cfi-if.h
@@ -0,0 +1,59 @@
+/*
+ * Xilinx CFI interface
+ *
+ * Copyright (C) 2023, Advanced Micro Devices, Inc.
+ *
+ * Written by Francisco Iglesias 
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#ifndef XLNX_CFI_IF_H
+#define XLNX_CFI_IF_H 1
+
+#include "qemu/help-texts.h"
+#include "hw/hw.h"
+#include "qom/object.h"
+
+#define TYPE_XLNX_CFI_IF "xlnx-cfi-if"
+typedef struct XlnxCfiIfClass XlnxCfiIfClass;
+DECLARE_CLASS_CHECKERS(XlnxCfiIfClass, XLNX_CFI_IF, TYPE_XLNX_CFI_IF)
+
+#define XLNX_CFI_IF(obj) \
+ INTERFACE_CHECK(XlnxCfiIf, (obj), TYPE_XLNX_CFI_IF)
+
+typedef enum {
+PACKET_TYPE_CFU = 0x52,
+PACKET_TYPE_CFRAME = 0xA1,
+} xlnx_cfi_packet_type;
+
+typedef enum {
+CFRAME_FAR = 1,
+CFRAME_SFR = 2,
+CFRAME_FDRI = 4,
+CFRAME_CMD = 6,
+} xlnx_cfi_reg_addr;
+
+typedef struct XlnxCfiPacket {
+uint8_t reg_addr;
+uint32_t data[4];
+} XlnxCfiPacket;
+
+typedef struct XlnxCfiIf {
+Object Parent;
+} XlnxCfiIf;
+
+typedef struct XlnxCfiIfClass {
+InterfaceClass parent;
+
+void (*cfi_transfer_packet)(XlnxCfiIf *cfi_if, XlnxCfiPacket *pkt);
+} XlnxCfiIfClass;
+
+/**
+ * Transfer a XlnxCfiPacket.
+ *
+ * @cfi_if: the object implementing this interface
+ * @XlnxCfiPacket: a pointer to the XlnxCfiPacket to transfer
+ */
+void xlnx_cfi_transfer_packet(XlnxCfiIf *cfi_if, XlnxCfiPacket *pkt);
+
+#endif /* XLNX_CFI_IF_H */
-- 
2.34.1




[PATCH v1 8/8] hw/arm/versal: Connect the CFRAME_REG and CFRAME_BCAST_REG

2023-07-10 Thread Francisco Iglesias
Connect the Configuration Frame controller (CFRAME_REG) and the
Configuration Frame broadcast controller (CFRAME_BCAST_REG) to the
Versal machine.

Signed-off-by: Francisco Iglesias 
---
 hw/arm/xlnx-versal.c | 116 ++-
 include/hw/arm/xlnx-versal.h |  69 +
 2 files changed, 184 insertions(+), 1 deletion(-)

diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
index 3f4b4b1560..9cd3c7218e 100644
--- a/hw/arm/xlnx-versal.c
+++ b/hw/arm/xlnx-versal.c
@@ -27,7 +27,7 @@
 #define XLNX_VERSAL_RCPU_TYPE ARM_CPU_TYPE_NAME("cortex-r5f")
 #define GEM_REVISION0x40070106
 
-#define VERSAL_NUM_PMC_APB_IRQS 3
+#define VERSAL_NUM_PMC_APB_IRQS 18
 #define NUM_OSPI_IRQ_LINES 3
 
 static void versal_create_apu_cpus(Versal *s)
@@ -341,6 +341,7 @@ static void versal_create_pmc_apb_irq_orgate(Versal *s, 
qemu_irq *pic)
  *  - RTC
  *  - BBRAM
  *  - PMC SLCR
+ *  - CFRAME regs (input 3 - 17 to the orgate)
  */
 object_initialize_child(OBJECT(s), "pmc-apb-irq-orgate",
 >pmc.apb_irq_orgate, TYPE_OR_IRQ);
@@ -573,6 +574,42 @@ static void versal_create_ospi(Versal *s, qemu_irq *pic)
 static void versal_create_cfu(Versal *s, qemu_irq *pic)
 {
 SysBusDevice *sbd;
+DeviceState *dev;
+int i;
+const struct {
+uint64_t reg_base;
+uint64_t fdri_base;
+} cframe_addr[] = {
+{ MM_PMC_CFRAME0_REG, MM_PMC_CFRAME0_FDRI },
+{ MM_PMC_CFRAME1_REG, MM_PMC_CFRAME1_FDRI },
+{ MM_PMC_CFRAME2_REG, MM_PMC_CFRAME2_FDRI },
+{ MM_PMC_CFRAME3_REG, MM_PMC_CFRAME3_FDRI },
+{ MM_PMC_CFRAME4_REG, MM_PMC_CFRAME4_FDRI },
+{ MM_PMC_CFRAME5_REG, MM_PMC_CFRAME5_FDRI },
+{ MM_PMC_CFRAME6_REG, MM_PMC_CFRAME6_FDRI },
+{ MM_PMC_CFRAME7_REG, MM_PMC_CFRAME7_FDRI },
+{ MM_PMC_CFRAME8_REG, MM_PMC_CFRAME8_FDRI },
+{ MM_PMC_CFRAME9_REG, MM_PMC_CFRAME9_FDRI },
+{ MM_PMC_CFRAME10_REG, MM_PMC_CFRAME10_FDRI },
+{ MM_PMC_CFRAME11_REG, MM_PMC_CFRAME11_FDRI },
+{ MM_PMC_CFRAME12_REG, MM_PMC_CFRAME12_FDRI },
+{ MM_PMC_CFRAME13_REG, MM_PMC_CFRAME13_FDRI },
+{ MM_PMC_CFRAME14_REG, MM_PMC_CFRAME14_FDRI },
+};
+const struct {
+uint32_t blktype0_frames;
+uint32_t blktype1_frames;
+uint32_t blktype2_frames;
+uint32_t blktype3_frames;
+uint32_t blktype4_frames;
+uint32_t blktype5_frames;
+uint32_t blktype6_frames;
+} cframe_cfg[] = {
+[0] = { 34111, 3528, 12800, 11, 5, 1, 1 },
+[1] = { 38498, 3841, 15361, 13, 7, 3, 1 },
+[2] = { 38498, 3841, 15361, 13, 7, 3, 1 },
+[3] = { 38498, 3841, 15361, 13, 7, 3, 1 },
+};
 
 /* CFU FDRO */
 object_initialize_child(OBJECT(s), "cfu-fdro", >pmc.cfu_fdro,
@@ -583,10 +620,87 @@ static void versal_create_cfu(Versal *s, qemu_irq *pic)
 memory_region_add_subregion(>mr_ps, MM_PMC_CFU_FDRO,
 sysbus_mmio_get_region(sbd, 0));
 
+/* CFRAME REG */
+for (i = 0; i < ARRAY_SIZE(s->pmc.cframe); i++) {
+char *name = g_strdup_printf("cframe%d", i);
+
+object_initialize_child(OBJECT(s), name, >pmc.cframe[i],
+TYPE_XLNX_VERSAL_CFRAME_REG);
+
+sbd = SYS_BUS_DEVICE(>pmc.cframe[i]);
+dev = DEVICE(>pmc.cframe[i]);
+
+if (i < ARRAY_SIZE(cframe_cfg)) {
+object_property_set_int(OBJECT(dev), "blktype0-frames",
+cframe_cfg[i].blktype0_frames,
+_abort);
+object_property_set_int(OBJECT(dev), "blktype1-frames",
+cframe_cfg[i].blktype1_frames,
+_abort);
+object_property_set_int(OBJECT(dev), "blktype2-frames",
+cframe_cfg[i].blktype2_frames,
+_abort);
+object_property_set_int(OBJECT(dev), "blktype3-frames",
+cframe_cfg[i].blktype3_frames,
+_abort);
+object_property_set_int(OBJECT(dev), "blktype4-frames",
+cframe_cfg[i].blktype4_frames,
+_abort);
+object_property_set_int(OBJECT(dev), "blktype5-frames",
+cframe_cfg[i].blktype5_frames,
+_abort);
+object_property_set_int(OBJECT(dev), "blktype6-frames",
+cframe_cfg[i].blktype6_frames,
+_abort);
+}
+object_property_set_link(OBJECT(dev), "cfu-fdro",
+ OBJECT(>

[PATCH v1 2/8] hw/misc: Introduce a model of Xilinx Versal's CFU_APB

2023-07-10 Thread Francisco Iglesias
Introduce a model of the software programming interface (CFU_APB) of
Xilinx Versal's Configuration Frame Unit.

Signed-off-by: Francisco Iglesias 
---
 MAINTAINERS   |   2 +
 hw/misc/meson.build   |   1 +
 hw/misc/xlnx-versal-cfu.c | 373 ++
 include/hw/misc/xlnx-versal-cfu.h | 212 +
 4 files changed, 588 insertions(+)
 create mode 100644 hw/misc/xlnx-versal-cfu.c
 create mode 100644 include/hw/misc/xlnx-versal-cfu.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 3ba115bb9b..2bc7ab42ae 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1041,6 +1041,8 @@ M: Francisco Iglesias 
 S: Maintained
 F: hw/misc/xlnx-cfi-if.c
 F: include/hw/misc/xlnx-cfi-if.h
+F: hw/misc/xlnx-versal-cfu.c
+F: include/hw/misc/xlnx-versal-cfu.h
 
 STM32F100
 M: Alexandre Iooss 
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
index 9971b1e4db..c88051aa51 100644
--- a/hw/misc/meson.build
+++ b/hw/misc/meson.build
@@ -96,6 +96,7 @@ specific_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: 
files('xlnx-versal-crl.c'))
 system_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files(
   'xlnx-versal-xramc.c',
   'xlnx-versal-pmc-iou-slcr.c',
+  'xlnx-versal-cfu.c',
   'xlnx-cfi-if.c',
 ))
 system_ss.add(when: 'CONFIG_STM32F2XX_SYSCFG', if_true: 
files('stm32f2xx_syscfg.c'))
diff --git a/hw/misc/xlnx-versal-cfu.c b/hw/misc/xlnx-versal-cfu.c
new file mode 100644
index 00..cbd17d2351
--- /dev/null
+++ b/hw/misc/xlnx-versal-cfu.c
@@ -0,0 +1,373 @@
+/*
+ * QEMU model of the CFU Configuration Unit.
+ *
+ * Copyright (C) 2023, Advanced Micro Devices, Inc.
+ *
+ * Written by Edgar E. Iglesias ,
+ *Sai Pavan Boddu ,
+ *Francisco Iglesias 
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "hw/sysbus.h"
+#include "hw/register.h"
+#include "hw/irq.h"
+#include "qemu/bitops.h"
+#include "qemu/log.h"
+#include "migration/vmstate.h"
+#include "hw/qdev-properties.h"
+#include "hw/qdev-properties-system.h"
+#include "hw/misc/xlnx-versal-cfu.h"
+
+#ifndef XLNX_VERSAL_CFU_APB_ERR_DEBUG
+#define XLNX_VERSAL_CFU_APB_ERR_DEBUG 0
+#endif
+
+#define KEYHOLE_STREAM_4K 0x1000
+#define KEYHOLE_STREAM_256K 0x4
+#define CFRAME_BROADCAST_ROW 0x1F
+
+static void cfu_imr_update_irq(XlnxVersalCFUAPB *s)
+{
+bool pending = s->regs[R_CFU_ISR] & ~s->regs[R_CFU_IMR];
+qemu_set_irq(s->irq_cfu_imr, pending);
+}
+
+static void cfu_isr_postw(RegisterInfo *reg, uint64_t val64)
+{
+XlnxVersalCFUAPB *s = XLNX_VERSAL_CFU_APB(reg->opaque);
+cfu_imr_update_irq(s);
+}
+
+static uint64_t cfu_ier_prew(RegisterInfo *reg, uint64_t val64)
+{
+XlnxVersalCFUAPB *s = XLNX_VERSAL_CFU_APB(reg->opaque);
+uint32_t val = val64;
+
+s->regs[R_CFU_IMR] &= ~val;
+cfu_imr_update_irq(s);
+return 0;
+}
+
+static uint64_t cfu_idr_prew(RegisterInfo *reg, uint64_t val64)
+{
+XlnxVersalCFUAPB *s = XLNX_VERSAL_CFU_APB(reg->opaque);
+uint32_t val = val64;
+
+s->regs[R_CFU_IMR] |= val;
+cfu_imr_update_irq(s);
+return 0;
+}
+
+static uint64_t cfu_itr_prew(RegisterInfo *reg, uint64_t val64)
+{
+XlnxVersalCFUAPB *s = XLNX_VERSAL_CFU_APB(reg->opaque);
+uint32_t val = val64;
+
+s->regs[R_CFU_ISR] |= val;
+cfu_imr_update_irq(s);
+return 0;
+}
+
+static void cfu_fgcr_postw(RegisterInfo *reg, uint64_t val64)
+{
+XlnxVersalCFUAPB *s = XLNX_VERSAL_CFU_APB(reg->opaque);
+uint32_t val = (uint32_t)val64;
+
+/* Do a scan. It always looks good. */
+if (FIELD_EX32(val, CFU_FGCR, SC_HBC_TRIGGER)) {
+ARRAY_FIELD_DP32(s->regs, CFU_STATUS, SCAN_CLEAR_PASS, 1);
+ARRAY_FIELD_DP32(s->regs, CFU_STATUS, SCAN_CLEAR_DONE, 1);
+}
+}
+
+static const RegisterAccessInfo cfu_apb_regs_info[] = {
+{   .name = "CFU_ISR",  .addr = A_CFU_ISR,
+.rsvd = 0xfc00,
+.w1c = 0x3ff,
+.post_write = cfu_isr_postw,
+},{ .name = "CFU_IMR",  .addr = A_CFU_IMR,
+.reset = 0x3ff,
+.rsvd = 0xfc00,
+.ro = 0x3ff,
+},{ .name = "CFU_IER",  .addr = A_CFU_IER,
+.rsvd = 0xfc00,
+.pre_write = cfu_ier_prew,
+},{ .name = "CFU_IDR",  .addr = A_CFU_IDR,
+.rsvd = 0xfc00,
+.pre_write = cfu_idr_prew,
+},{ .name = "CFU_ITR",  .addr = A_CFU_ITR,
+.rsvd = 0xfc00,
+.pre_write = cfu_itr_prew,
+},{ .name = "CFU_PROTECT",  .addr = A_CFU_PROTECT,
+.reset = 0x1,
+},{ .name = "CFU_FGCR",  .addr = A_CFU_FGCR,
+.rsvd = 0x8000,
+.post_write = cfu_fgcr_postw,
+},{ .name = "CFU_CTL",  .addr = A_CFU_CTL,
+.rsvd = 0x,
+},{ .name = "CFU_CRAM_RW",  .addr = A_CFU_CRAM_RW,
+.reset = 0x401f7d9,
+.rsvd = 

[PATCH v1 6/8] hw/misc: Introduce a model of Xilinx Versal's CFRAME_BCAST_REG

2023-07-10 Thread Francisco Iglesias
Introduce a model of Xilinx Versal's Configuration Frame broadcast
controller (CFRAME_BCAST_REG).

Signed-off-by: Francisco Iglesias 
---
 hw/misc/xlnx-versal-cframe-reg.c | 173 +++
 include/hw/misc/xlnx-versal-cframe-reg.h |  17 +++
 2 files changed, 190 insertions(+)

diff --git a/hw/misc/xlnx-versal-cframe-reg.c b/hw/misc/xlnx-versal-cframe-reg.c
index 7e3420e14d..4f90eaa240 100644
--- a/hw/misc/xlnx-versal-cframe-reg.c
+++ b/hw/misc/xlnx-versal-cframe-reg.c
@@ -571,6 +571,104 @@ static const MemoryRegionOps cframe_reg_fdri_ops = {
 },
 };
 
+static uint64_t cframes_bcast_reg_read(void *opaque, hwaddr addr, unsigned 
size)
+{
+qemu_log_mask(LOG_GUEST_ERROR, "%s: Unsupported read from addr=%"
+  HWADDR_PRIx "\n", __func__, addr);
+return 0;
+}
+
+static void cframes_bcast_reg_write(void *opaque, hwaddr addr, uint64_t value,
+  unsigned size)
+{
+XlnxVersalCFrameBcastReg *s = XLNX_VERSAL_CFRAME_BCAST_REG(opaque);
+unsigned int idx;
+
+/* 4 32bit words. */
+idx = (addr >> 2) & 3;
+
+s->wfifo[idx] = value;
+
+/* Writing to the top word triggers the transmit onto CFI. */
+if (idx == 3) {
+uint32_t reg_addr = extract32(addr, 4, 6);
+XlnxCfiPacket pkt = {
+.reg_addr = reg_addr,
+.data[0] = s->wfifo[0],
+.data[1] = s->wfifo[1],
+.data[2] = s->wfifo[2],
+.data[3] = s->wfifo[3]
+};
+
+for (int i = 0; i < ARRAY_SIZE(s->cfg.cframe); i++) {
+if (s->cfg.cframe[i]) {
+xlnx_cfi_transfer_packet(s->cfg.cframe[i], );
+}
+}
+
+memset(s->wfifo, 0, 4 * sizeof(uint32_t));
+}
+}
+
+static uint64_t cframes_bcast_fdri_read(void *opaque, hwaddr addr,
+unsigned size)
+{
+qemu_log_mask(LOG_GUEST_ERROR, "%s: Unsupported read from addr=%"
+  HWADDR_PRIx "\n", __func__, addr);
+return 0;
+}
+
+static void cframes_bcast_fdri_write(void *opaque, hwaddr addr, uint64_t value,
+  unsigned size)
+{
+XlnxVersalCFrameBcastReg *s = XLNX_VERSAL_CFRAME_BCAST_REG(opaque);
+unsigned int idx;
+
+/* 4 32bit words. */
+idx = (addr >> 2) & 3;
+
+s->wfifo[idx] = value;
+
+/* Writing to the top word triggers the transmit onto CFI. */
+if (idx == 3) {
+XlnxCfiPacket pkt = {
+.reg_addr = CFRAME_FDRI,
+.data[0] = s->wfifo[0],
+.data[1] = s->wfifo[1],
+.data[2] = s->wfifo[2],
+.data[3] = s->wfifo[3]
+};
+
+for (int i = 0; i < ARRAY_SIZE(s->cfg.cframe); i++) {
+if (s->cfg.cframe[i]) {
+xlnx_cfi_transfer_packet(s->cfg.cframe[i], );
+}
+}
+
+memset(s->wfifo, 0, 4 * sizeof(uint32_t));
+}
+}
+
+static const MemoryRegionOps cframes_bcast_reg_reg_ops = {
+.read = cframes_bcast_reg_read,
+.write = cframes_bcast_reg_write,
+.endianness = DEVICE_LITTLE_ENDIAN,
+.valid = {
+.min_access_size = 4,
+.max_access_size = 4,
+},
+};
+
+static const MemoryRegionOps cframes_bcast_reg_fdri_ops = {
+.read = cframes_bcast_fdri_read,
+.write = cframes_bcast_fdri_write,
+.endianness = DEVICE_LITTLE_ENDIAN,
+.valid = {
+.min_access_size = 4,
+.max_access_size = 4,
+},
+};
+
 static void cframe_reg_realize(DeviceState *dev, Error **errp)
 {
 XlnxVersalCFrameReg *s = XLNX_VERSAL_CFRAME_REG(dev);
@@ -680,6 +778,64 @@ static Property cframe_regs_props[] = {
 DEFINE_PROP_END_OF_LIST(),
 };
 
+static void cframe_bcast_reg_init(Object *obj)
+{
+XlnxVersalCFrameBcastReg *s = XLNX_VERSAL_CFRAME_BCAST_REG(obj);
+SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+
+memory_region_init_io(>iomem_reg, obj, _bcast_reg_reg_ops, s,
+  TYPE_XLNX_VERSAL_CFRAME_BCAST_REG, 
KEYHOLE_STREAM_4K);
+memory_region_init_io(>iomem_fdri, obj, _bcast_reg_fdri_ops, s,
+  TYPE_XLNX_VERSAL_CFRAME_BCAST_REG "-fdri",
+  KEYHOLE_STREAM_4K);
+sysbus_init_mmio(sbd, >iomem_reg);
+sysbus_init_mmio(sbd, >iomem_fdri);
+}
+
+static const VMStateDescription vmstate_cframe_bcast_reg = {
+.name = TYPE_XLNX_VERSAL_CFRAME_BCAST_REG,
+.version_id = 1,
+.minimum_version_id = 1,
+.fields = (VMStateField[]) {
+VMSTATE_UINT32_ARRAY(wfifo, XlnxVersalCFrameBcastReg, 4),
+VMSTATE_END_OF_LIST(),
+}
+};
+
+static Property cframe_bcast_regs_props[] = {
+DEFINE_PROP_LINK("cframe0", XlnxVersalCFrameBcastReg, cfg.cframe[0],
+ TYPE_XLNX_CFI_IF, XlnxCfiIf *),
+DEFINE_PROP_LINK("cframe1", XlnxVersalCFrameBcastReg, cfg.cframe[1],
+  

[PATCH v1 4/8] hw/misc/xlnx-versal-cfu: Introduce a model of Xilinx Versal's CFU_SFR

2023-07-10 Thread Francisco Iglesias
Introduce a model of Xilinx Versal's Configuration Frame Unit's Single
Frame Read port (CFU_SFR).

Signed-off-by: Francisco Iglesias 
---
 hw/misc/xlnx-versal-cfu.c | 88 +++
 include/hw/misc/xlnx-versal-cfu.h | 15 ++
 2 files changed, 103 insertions(+)

diff --git a/hw/misc/xlnx-versal-cfu.c b/hw/misc/xlnx-versal-cfu.c
index 528090ef1b..60aec02a58 100644
--- a/hw/misc/xlnx-versal-cfu.c
+++ b/hw/misc/xlnx-versal-cfu.c
@@ -257,6 +257,41 @@ static void cfu_stream_write(void *opaque, hwaddr addr, 
uint64_t value,
 }
 }
 
+static uint64_t cfu_sfr_read(void *opaque, hwaddr addr, unsigned size)
+{
+qemu_log_mask(LOG_GUEST_ERROR, "%s: Unsupported read from addr=%"
+  HWADDR_PRIx "\n", __func__, addr);
+return 0;
+}
+
+static void cfu_sfr_write(void *opaque, hwaddr addr, uint64_t value,
+  unsigned size)
+{
+XlnxVersalCFUSFR *s = XLNX_VERSAL_CFU_SFR(opaque);
+unsigned int idx;
+
+/* 4 32bit words. */
+idx = (addr >> 2) & 3;
+
+s->wfifo[idx] = value;
+
+/* Writing to the top word triggers the transmit onto CFI. */
+if (idx == 3) {
+uint8_t row_addr = extract32(s->wfifo[0], 23, 5);
+uint32_t frame_addr = extract32(s->wfifo[0], 0, 23);
+XlnxCfiPacket pkt = { .reg_addr = CFRAME_SFR,
+  .data[0] = frame_addr };
+
+if (s->cfg.cfu) {
+cfu_transfer_cfi_packet(s->cfg.cfu, row_addr, );
+}
+
+for (int i = 0; i < ARRAY_SIZE(s->wfifo); i++) {
+s->wfifo[i] = 0;
+}
+}
+}
+
 static uint64_t cfu_fdro_read(void *opaque, hwaddr addr, unsigned size)
 {
 XlnxVersalCFUFDRO *s = XLNX_VERSAL_CFU_FDRO(opaque);
@@ -287,6 +322,16 @@ static const MemoryRegionOps cfu_stream_ops = {
 },
 };
 
+static const MemoryRegionOps cfu_sfr_ops = {
+.read = cfu_sfr_read,
+.write = cfu_sfr_write,
+.endianness = DEVICE_LITTLE_ENDIAN,
+.valid = {
+.min_access_size = 4,
+.max_access_size = 4,
+},
+};
+
 static const MemoryRegionOps cfu_fdro_ops = {
 .read = cfu_fdro_read,
 .write = cfu_fdro_write,
@@ -328,6 +373,16 @@ static void cfu_apb_init(Object *obj)
 sysbus_init_irq(sbd, >irq_cfu_imr);
 }
 
+static void cfu_sfr_init(Object *obj)
+{
+XlnxVersalCFUSFR *s = XLNX_VERSAL_CFU_SFR(obj);
+SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+
+memory_region_init_io(>iomem_sfr, obj, _sfr_ops, s,
+  TYPE_XLNX_VERSAL_CFU_SFR, KEYHOLE_STREAM_4K);
+sysbus_init_mmio(sbd, >iomem_sfr);
+}
+
 static void cfu_fdro_init(Object *obj)
 {
 XlnxVersalCFUFDRO *s = XLNX_VERSAL_CFU_FDRO(obj);
@@ -380,6 +435,12 @@ static Property cfu_props[] = {
 DEFINE_PROP_END_OF_LIST(),
 };
 
+static Property cfu_sfr_props[] = {
+DEFINE_PROP_LINK("cfu", XlnxVersalCFUSFR, cfg.cfu,
+ TYPE_XLNX_VERSAL_CFU_APB, XlnxVersalCFUAPB *),
+DEFINE_PROP_END_OF_LIST(),
+};
+
 static const VMStateDescription vmstate_cfu_apb = {
 .name = TYPE_XLNX_VERSAL_CFU_APB,
 .version_id = 1,
@@ -427,6 +488,16 @@ static const VMStateDescription vmstate_cfu_fdro = {
 }
 };
 
+static const VMStateDescription vmstate_cfu_sfr = {
+.name = TYPE_XLNX_VERSAL_CFU_SFR,
+.version_id = 1,
+.minimum_version_id = 1,
+.fields = (VMStateField[]) {
+VMSTATE_UINT32_ARRAY(wfifo, XlnxVersalCFUSFR, 4),
+VMSTATE_END_OF_LIST(),
+}
+};
+
 static void cfu_apb_class_init(ObjectClass *klass, void *data)
 {
 DeviceClass *dc = DEVICE_CLASS(klass);
@@ -445,6 +516,14 @@ static void cfu_fdro_class_init(ObjectClass *klass, void 
*data)
 xcic->cfi_transfer_packet = cfu_fdro_cfi_transfer_packet;
 }
 
+static void cfu_sfr_class_init(ObjectClass *klass, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(klass);
+
+device_class_set_props(dc, cfu_sfr_props);
+dc->vmsd = _cfu_sfr;
+}
+
 static const TypeInfo cfu_apb_info = {
 .name  = TYPE_XLNX_VERSAL_CFU_APB,
 .parent= TYPE_SYS_BUS_DEVICE,
@@ -469,10 +548,19 @@ static const TypeInfo cfu_fdro_info = {
 }
 };
 
+static const TypeInfo cfu_sfr_info = {
+.name  = TYPE_XLNX_VERSAL_CFU_SFR,
+.parent= TYPE_SYS_BUS_DEVICE,
+.instance_size = sizeof(XlnxVersalCFUSFR),
+.class_init= cfu_sfr_class_init,
+.instance_init = cfu_sfr_init,
+};
+
 static void cfu_apb_register_types(void)
 {
 type_register_static(_apb_info);
 type_register_static(_fdro_info);
+type_register_static(_sfr_info);
 }
 
 type_init(cfu_apb_register_types)
diff --git a/include/hw/misc/xlnx-versal-cfu.h 
b/include/hw/misc/xlnx-versal-cfu.h
index 3603bb2862..add155a8c4 100644
--- a/include/hw/misc/xlnx-versal-cfu.h
+++ b/include/hw/misc/xlnx-versal-cfu.h
@@ -27,6 +27,9 @@ OBJECT_DECLARE_SIMPLE_TYPE(XlnxVersalCFUAPB, 
XLNX_VERSAL_CFU_APB)
 #define TYPE_XLNX_VERSA

Re: [PATCH v2] hw/arm/xlnx: Connect secondary CGEM IRQs

2023-06-16 Thread Francisco Iglesias
On [2023 Jun 16] Fri 09:38:03, Kinsey Moore wrote:
> The Cadence GEM peripherals as configured for Zynq MPSoC and Versal
> platforms have two priority queues with separate interrupt sources for
> each. If the interrupt source for the second priority queue is not
> connected, they work in polling mode only. This change connects the
> second interrupt source for platforms where it is available. This patch
> has been tested using the lwIP stack with a Xilinx-supplied driver from
> their embeddedsw repository.
> 
> Signed-off-by: Kinsey Moore 

Reviewed-by: Francisco Iglesias 

> ---
>  hw/arm/xlnx-versal.c | 12 +++-
>  hw/arm/xlnx-zynqmp.c | 11 ++-
>  include/hw/arm/xlnx-versal.h |  1 +
>  include/hw/arm/xlnx-zynqmp.h |  1 +
>  4 files changed, 23 insertions(+), 2 deletions(-)
> 
> diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
> index 60bf5fe657..cb79b855fd 100644
> --- a/hw/arm/xlnx-versal.c
> +++ b/hw/arm/xlnx-versal.c
> @@ -252,9 +252,13 @@ static void versal_create_gems(Versal *s, qemu_irq *pic)
>  NICInfo *nd = _table[i];
>  DeviceState *dev;
>  MemoryRegion *mr;
> +OrIRQState *or_irq;
>  
>  object_initialize_child(OBJECT(s), name, >lpd.iou.gem[i],
>  TYPE_CADENCE_GEM);
> +or_irq = >lpd.iou.gem_irq_orgate[i];
> +object_initialize_child(OBJECT(s), "gem-irq-orgate[*]",
> +or_irq, TYPE_OR_IRQ);
>  dev = DEVICE(>lpd.iou.gem[i]);
>  /* FIXME use qdev NIC properties instead of nd_table[] */
>  if (nd->used) {
> @@ -264,6 +268,11 @@ static void versal_create_gems(Versal *s, qemu_irq *pic)
>  object_property_set_int(OBJECT(dev), "phy-addr", 23, _abort);
>  object_property_set_int(OBJECT(dev), "num-priority-queues", 2,
>  _abort);
> +object_property_set_int(OBJECT(or_irq),
> +"num-lines", 2, _fatal);
> +qdev_realize(DEVICE(or_irq), NULL, _fatal);
> +qdev_connect_gpio_out(DEVICE(or_irq), 0, pic[irqs[i]]);
> +
>  object_property_set_link(OBJECT(dev), "dma", OBJECT(>mr_ps),
>   _abort);
>  sysbus_realize(SYS_BUS_DEVICE(dev), _fatal);
> @@ -271,7 +280,8 @@ static void versal_create_gems(Versal *s, qemu_irq *pic)
>  mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
>  memory_region_add_subregion(>mr_ps, addrs[i], mr);
>  
> -sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[irqs[i]]);
> +sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, 
> qdev_get_gpio_in(DEVICE(or_irq), 0));
> +sysbus_connect_irq(SYS_BUS_DEVICE(dev), 1, 
> qdev_get_gpio_in(DEVICE(or_irq), 1));
>  g_free(name);
>  }
>  }
> diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
> index 5905a33015..f7158e4fd3 100644
> --- a/hw/arm/xlnx-zynqmp.c
> +++ b/hw/arm/xlnx-zynqmp.c
> @@ -392,6 +392,8 @@ static void xlnx_zynqmp_init(Object *obj)
>  
>  for (i = 0; i < XLNX_ZYNQMP_NUM_GEMS; i++) {
>  object_initialize_child(obj, "gem[*]", >gem[i], TYPE_CADENCE_GEM);
> +object_initialize_child(obj, "gem-irq-orgate[*]",
> +>gem_irq_orgate[i], TYPE_OR_IRQ);
>  }
>  
>  for (i = 0; i < XLNX_ZYNQMP_NUM_UARTS; i++) {
> @@ -629,12 +631,19 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error 
> **errp)
>  _abort);
>  object_property_set_int(OBJECT(>gem[i]), "num-priority-queues", 2,
>  _abort);
> +object_property_set_int(OBJECT(>gem_irq_orgate[i]),
> +"num-lines", 2, _fatal);
> +qdev_realize(DEVICE(>gem_irq_orgate[i]), NULL, _fatal);
> +qdev_connect_gpio_out(DEVICE(>gem_irq_orgate[i]), 0, 
> gic_spi[gem_intr[i]]);
> +
>  if (!sysbus_realize(SYS_BUS_DEVICE(>gem[i]), errp)) {
>  return;
>  }
>  sysbus_mmio_map(SYS_BUS_DEVICE(>gem[i]), 0, gem_addr[i]);
>  sysbus_connect_irq(SYS_BUS_DEVICE(>gem[i]), 0,
> -   gic_spi[gem_intr[i]]);
> +   qdev_get_gpio_in(DEVICE(>gem_irq_orgate[i]), 
> 0));
> +sysbus_connect_irq(SYS_BUS_DEVICE(>gem[i]), 1,
> +   qdev_get_gpio_in(DEVICE(>gem_irq_orgate[i]), 
> 1));
>  }
>  
>  for (i = 0; i < XLNX_ZYNQMP_NUM_UARTS; i++) {
> diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
> in

Re: [PATCH] hw/arm/xlnx: Connect secondary CGEM IRQs

2023-06-16 Thread Francisco Iglesias
Hi Kinsey,

On [2023 Jun 15] Thu 08:48:47, Kinsey Moore wrote:
> The Cadence GEM peripherals as configured for Zynq MPSoC and Versal
> platforms have two priority queues with separate interrupt sources for
> each. If the interrupt source for the second priority queue is not
> connected, they work in polling mode only. This change connects the
> second interrupt source for platforms where it is available. This patch
> has been tested using the lwIP stack with a Xilinx-supplied driver from
> their embeddedsw repository.
> 
> Signed-off-by: Kinsey Moore 
> ---
>  hw/arm/xlnx-versal.c | 1 +
>  hw/arm/xlnx-zynqmp.c | 2 ++
>  2 files changed, 3 insertions(+)
> 
> diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
> index 60bf5fe657..a9e06b7fd1 100644
> --- a/hw/arm/xlnx-versal.c
> +++ b/hw/arm/xlnx-versal.c
> @@ -272,6 +272,7 @@ static void versal_create_gems(Versal *s, qemu_irq *pic)
>  memory_region_add_subregion(>mr_ps, addrs[i], mr);
>  
>  sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[irqs[i]]);
> +sysbus_connect_irq(SYS_BUS_DEVICE(dev), 1, pic[irqs[i]]);

This is correct (thanks!) but the lines need to be connected through a
qemu_or_irq (in both places), you can look into this commit: c74ccb5dd6 for an
example (and reason).

Best regards,
Francisco

>  g_free(name);
>  }
>  }
> diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
> index 5905a33015..b919b38e91 100644
> --- a/hw/arm/xlnx-zynqmp.c
> +++ b/hw/arm/xlnx-zynqmp.c
> @@ -635,6 +635,8 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error 
> **errp)
>  sysbus_mmio_map(SYS_BUS_DEVICE(>gem[i]), 0, gem_addr[i]);
>  sysbus_connect_irq(SYS_BUS_DEVICE(>gem[i]), 0,
> gic_spi[gem_intr[i]]);
> +sysbus_connect_irq(SYS_BUS_DEVICE(>gem[i]), 1,
> +   gic_spi[gem_intr[i]]);
>  }
>  
>  for (i = 0; i < XLNX_ZYNQMP_NUM_UARTS; i++) {
> -- 
> 2.30.2
> 
> 



Re: [PATCH] hw/arm/xlnx-zynqmp: fix unsigned error when checking the RPUs number

2023-05-24 Thread Francisco Iglesias
On [2023 May 24] Wed 16:37:14, Clément Chigot wrote:
> When passing --smp with a number lower than XLNX_ZYNQMP_NUM_APU_CPUS,
> the expression (ms->smp.cpus - XLNX_ZYNQMP_NUM_APU_CPUS) will result
> in a positive number as ms->smp.cpus is a unsigned int.
> This will raise the following error afterwards, as Qemu will try to
> instantiate some additional RPUs.
>   | $ qemu-system-aarch64 --smp 1 -M xlnx-zcu102
>   | **
>   | ERROR:../src/tcg/tcg.c:777:tcg_register_thread:
>   |   assertion failed: (n < tcg_max_ctxs)
> 
> Signed-off-by: Clément Chigot 

Reviewed-by: Francisco Iglesias 
Tested-by: Francisco Iglesias 

> ---
>  hw/arm/xlnx-zynqmp.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
> index 335cfc417d..5905a33015 100644
> --- a/hw/arm/xlnx-zynqmp.c
> +++ b/hw/arm/xlnx-zynqmp.c
> @@ -213,7 +213,7 @@ static void xlnx_zynqmp_create_rpu(MachineState *ms, 
> XlnxZynqMPState *s,
> const char *boot_cpu, Error **errp)
>  {
>  int i;
> -int num_rpus = MIN(ms->smp.cpus - XLNX_ZYNQMP_NUM_APU_CPUS,
> +int num_rpus = MIN((int)(ms->smp.cpus - XLNX_ZYNQMP_NUM_APU_CPUS),
> XLNX_ZYNQMP_NUM_RPU_CPUS);
>  
>  if (num_rpus <= 0) {
> -- 
> 2.25.1
> 
> 



Re: [QEMU][PATCH v5 2/4] hw/net/can: Introduce Xilinx Versal CANFD controller

2023-05-24 Thread Francisco Iglesias
 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.
> + */
> +
> +#ifndef HW_CANFD_XILINX_H
> +#define HW_CANFD_XILINX_H
> +
> +#include "hw/register.h"
> +#include "hw/ptimer.h"
> +#include "net/can_emu.h"
> +#include "hw/qdev-clock.h"
> +
> +#define TYPE_XILINX_CANFD "xlnx.versal-canfd"
> +
> +OBJECT_DECLARE_SIMPLE_TYPE(XlnxVersalCANFDState, XILINX_CANFD)
> +
> +#define NUM_REGS_PER_MSG_SPACE 18 /* 1 ID + 1 DLC + 16 Data(DW0 - DW15) 
> regs. */
> +#define MAX_NUM_RX 64
> +#define OFFSET_RX1_DW15(0x4144 / 4)
> +#define CANFD_TIMER_MAX0xUL
> +#define CANFD_DEFAULT_CLOCK(24 * 1000 * 1000)

s/24/25/

With above changes:

Reviewed-by: Francisco Iglesias 

> +
> +#define XLNX_VERSAL_CANFD_R_MAX (OFFSET_RX1_DW15 + \
> +((MAX_NUM_RX - 1) * NUM_REGS_PER_MSG_SPACE) + 1)
> +
> +typedef struct XlnxVersalCANFDState {
> +SysBusDeviceparent_obj;
> +MemoryRegioniomem;
> +
> +qemu_irqirq_canfd_int;
> +qemu_irqirq_addr_err;
> +
> +RegisterInforeg_info[XLNX_VERSAL_CANFD_R_MAX];
> +RegisterAccessInfo  *tx_regs;
> +RegisterAccessInfo  *rx0_regs;
> +RegisterAccessInfo  *rx1_regs;
> +RegisterAccessInfo  *af_regs;
> +RegisterAccessInfo  *txe_regs;
> +RegisterAccessInfo  *rx_mailbox_regs;
> +RegisterAccessInfo  *af_mask_regs_mailbox;
> +
> +uint32_tregs[XLNX_VERSAL_CANFD_R_MAX];
> +
> +ptimer_state*canfd_timer;
> +
> +CanBusClientState   bus_client;
> +CanBusState *canfdbus;
> +
> +struct {
> +uint8_t rx0_fifo;
> +uint8_t rx1_fifo;
> +uint8_t tx_fifo;
> +boolenable_rx_fifo1;
> +uint32_text_clk_freq;
> +   } cfg;
> +
> +} XlnxVersalCANFDState;
> +
> +typedef struct tx_ready_reg_info {
> +uint32_t can_id;
> +uint32_t reg_num;
> +} tx_ready_reg_info;
> +
> +#endif
> -- 
> 2.17.1
> 



Re: [QEMU][PATCH v5 3/4] xlnx-versal: Connect Xilinx VERSAL CANFD controllers

2023-05-22 Thread Francisco Iglesias
On [2023 May 19] Fri 13:36:57, Vikram Garhwal wrote:
> Connect CANFD0 and CANFD1 on the Versal-virt machine and update 
> xlnx-versal-virt
> document with CANFD command line examples.
> 
> Signed-off-by: Vikram Garhwal 
> Reviewed-by: Peter Maydell 

Reviewed-by: Francisco Iglesias 

> ---
>  docs/system/arm/xlnx-versal-virt.rst | 31 
>  hw/arm/xlnx-versal-virt.c| 53 
>  hw/arm/xlnx-versal.c | 37 +++
>  include/hw/arm/xlnx-versal.h | 12 +++
>  4 files changed, 133 insertions(+)
> 
> diff --git a/docs/system/arm/xlnx-versal-virt.rst 
> b/docs/system/arm/xlnx-versal-virt.rst
> index 92ad10d2da..d2d1b26692 100644
> --- a/docs/system/arm/xlnx-versal-virt.rst
> +++ b/docs/system/arm/xlnx-versal-virt.rst
> @@ -34,6 +34,7 @@ Implemented devices:
>  - DDR memory
>  - BBRAM (36 bytes of Battery-backed RAM)
>  - eFUSE (3072 bytes of one-time field-programmable bit array)
> +- 2 CANFDs
>  
>  QEMU does not yet model any other devices, including the PL and the AI 
> Engine.
>  
> @@ -224,3 +225,33 @@ To use a different index value, N, from default of 1, 
> add:
>  
>Better yet, do not use actual product data when running guest image
>on this Xilinx Versal Virt board.
> +
> +Using CANFDs for Versal Virt
> +""""""""""""""""""""""""""""
> +Versal CANFD controller is developed based on SocketCAN and QEMU CAN bus
> +implementation. Bus connection and socketCAN connection for each CAN module
> +can be set through command lines.
> +
> +To connect both CANFD0 and CANFD1 on the same bus:
> +
> +.. code-block:: bash
> +
> +-object can-bus,id=canbus -machine canbus0=canbus -machine canbus1=canbus
> +
> +To connect CANFD0 and CANFD1 to separate buses:
> +
> +.. code-block:: bash
> +
> +-object can-bus,id=canbus0 -object can-bus,id=canbus1 \
> +-machine canbus0=canbus0 -machine canbus1=canbus1
> +
> +The SocketCAN interface can connect to a Physical or a Virtual CAN 
> interfaces on
> +the host machine. Please check this document to learn about CAN interface on
> +Linux: docs/system/devices/can.rst
> +
> +To connect CANFD0 and CANFD1 to host machine's CAN interface can0:
> +
> +.. code-block:: bash
> +
> +-object can-bus,id=canbus -machine canbus0=canbus -machine canbus1=canbus
> +-object can-host-socketcan,id=canhost0,if=can0,canbus=canbus
> diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
> index 668a9d65a4..1ee2b8697f 100644
> --- a/hw/arm/xlnx-versal-virt.c
> +++ b/hw/arm/xlnx-versal-virt.c
> @@ -40,9 +40,11 @@ struct VersalVirt {
>  uint32_t clk_25Mhz;
>  uint32_t usb;
>  uint32_t dwc;
> +uint32_t canfd[2];
>  } phandle;
>  struct arm_boot_info binfo;
>  
> +CanBusState *canbus[XLNX_VERSAL_NR_CANFD];
>  struct {
>  bool secure;
>  } cfg;
> @@ -235,6 +237,38 @@ static void fdt_add_uart_nodes(VersalVirt *s)
>  }
>  }
>  
> +static void fdt_add_canfd_nodes(VersalVirt *s)
> +{
> +uint64_t addrs[] = { MM_CANFD1, MM_CANFD0 };
> +uint32_t size[] = { MM_CANFD1_SIZE, MM_CANFD0_SIZE };
> +unsigned int irqs[] = { VERSAL_CANFD1_IRQ_0, VERSAL_CANFD0_IRQ_0 };
> +const char clocknames[] = "can_clk\0s_axi_aclk";
> +int i;
> +
> +/* Create and connect CANFD0 and CANFD1 nodes to canbus0. */
> +for (i = 0; i < ARRAY_SIZE(addrs); i++) {
> +char *name = g_strdup_printf("/canfd@%" PRIx64, addrs[i]);
> +qemu_fdt_add_subnode(s->fdt, name);
> +
> +qemu_fdt_setprop_cell(s->fdt, name, "rx-fifo-depth", 0x40);
> +qemu_fdt_setprop_cell(s->fdt, name, "tx-mailbox-count", 0x20);
> +
> +qemu_fdt_setprop_cells(s->fdt, name, "clocks",
> +   s->phandle.clk_25Mhz, s->phandle.clk_25Mhz);
> +qemu_fdt_setprop(s->fdt, name, "clock-names",
> + clocknames, sizeof(clocknames));
> +qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
> +   GIC_FDT_IRQ_TYPE_SPI, irqs[i],
> +   GIC_FDT_IRQ_FLAGS_LEVEL_HI);
> +qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
> + 2, addrs[i], 2, size[i]);
> +qemu_fdt_setprop_string(s->fdt, name, "compatible",
> +"xlnx,canfd-2.0");
> +
> +   

Re: [PATCH 03/12] util/fifo8: Introduce fifo8_peek_buf()

2023-05-22 Thread Francisco Iglesias
On [2023 May 22] Mon 17:31:35, Philippe Mathieu-Daudé wrote:
> To be able to poke at FIFO content without popping it,
> introduce the fifo8_peek_buf() method by factoring
> common content from fifo8_pop_buf().
> 
> Signed-off-by: Philippe Mathieu-Daudé 
> ---
>  include/qemu/fifo8.h | 26 ++
>  util/fifo8.c | 22 ++
>  2 files changed, 44 insertions(+), 4 deletions(-)
> 
> diff --git a/include/qemu/fifo8.h b/include/qemu/fifo8.h
> index d0d02bc73d..7acf6d1347 100644
> --- a/include/qemu/fifo8.h
> +++ b/include/qemu/fifo8.h
> @@ -93,6 +93,32 @@ uint8_t fifo8_pop(Fifo8 *fifo);
>   */
>  const uint8_t *fifo8_pop_buf(Fifo8 *fifo, uint32_t max, uint32_t *numptr);
>  
> +/**
> + * fifo8_peek_buf:
> + * @fifo: FIFO to poke from
> + * @max: maximum number of bytes to pop
> + * @numptr: pointer filled with number of bytes returned (can be NULL)
> + *
> + * Pop a number of elements from the FIFO up to a maximum of max. The buffer

s/Pop/Peek into/

> + * containing the popped data is returned. This buffer points directly into

s/popped data/data peeked into/

If above sounds good:

Reviewed-by: Francisco Iglesias 


> + * the FIFO backing store and data is invalidated once any of the fifo8_* 
> APIs
> + * are called on the FIFO.

(Above sounds as if it happens automatically to me but I'm not english native,
a suggestion could be to put something as below "clients are responsible for
tracking this")

> + *
> + * The function may return fewer bytes than requested when the data wraps
> + * around in the ring buffer; in this case only a contiguous part of the data
> + * is returned.
> + *
> + * The number of valid bytes returned is populated in *numptr; will always
> + * return at least 1 byte. max must not be 0 or greater than the number of
> + * bytes in the FIFO.
> + *
> + * Clients are responsible for checking the availability of requested data
> + * using fifo8_num_used().
> + *
> + * Returns: A pointer to peekable data.
> + */
> +const uint8_t *fifo8_peek_buf(Fifo8 *fifo, uint32_t max, uint32_t *numptr);
> +
>  /**
>   * fifo8_reset:
>   * @fifo: FIFO to reset
> diff --git a/util/fifo8.c b/util/fifo8.c
> index 032e985440..e12477843e 100644
> --- a/util/fifo8.c
> +++ b/util/fifo8.c
> @@ -66,7 +66,8 @@ uint8_t fifo8_pop(Fifo8 *fifo)
>  return ret;
>  }
>  
> -const uint8_t *fifo8_pop_buf(Fifo8 *fifo, uint32_t max, uint32_t *numptr)
> +static const uint8_t *fifo8_peekpop_buf(Fifo8 *fifo, uint32_t max,
> +uint32_t *numptr, bool do_pop)
>  {
>  uint8_t *ret;
>  uint32_t num;
> @@ -74,15 +75,28 @@ const uint8_t *fifo8_pop_buf(Fifo8 *fifo, uint32_t max, 
> uint32_t *numptr)
>  assert(max > 0 && max <= fifo->num);
>  num = MIN(fifo->capacity - fifo->head, max);
>  ret = >data[fifo->head];
> -fifo->head += num;
> -fifo->head %= fifo->capacity;
> -fifo->num -= num;
> +
> +if (do_pop) {
> +fifo->head += num;
> +fifo->head %= fifo->capacity;
> +fifo->num -= num;
> +}
>  if (numptr) {
>  *numptr = num;
>  }
>  return ret;
>  }
>  
> +const uint8_t *fifo8_peek_buf(Fifo8 *fifo, uint32_t max, uint32_t *numptr)
> +{
> +return fifo8_peekpop_buf(fifo, max, numptr, false);
> +}
> +
> +const uint8_t *fifo8_pop_buf(Fifo8 *fifo, uint32_t max, uint32_t *numptr)
> +{
> +return fifo8_peekpop_buf(fifo, max, numptr, true);
> +}
> +
>  void fifo8_reset(Fifo8 *fifo)
>  {
>  fifo->num = 0;
> -- 
> 2.38.1
> 
> 



Re: [PATCH 02/12] util/fifo8: Allow fifo8_pop_buf() to not populate popped length

2023-05-22 Thread Francisco Iglesias
On [2023 May 22] Mon 17:31:34, Philippe Mathieu-Daudé wrote:
> There might be cases where we know the number of bytes we can
> pop from the FIFO, or we simply don't care how many bytes is
> returned. Allow fifo8_pop_buf() to take a NULL numptr.
> 
> Signed-off-by: Philippe Mathieu-Daudé 

Reviewed-by: Francisco Iglesias 


> ---
>  include/qemu/fifo8.h | 10 +-
>  util/fifo8.c | 12 
>  2 files changed, 13 insertions(+), 9 deletions(-)
> 
> diff --git a/include/qemu/fifo8.h b/include/qemu/fifo8.h
> index 16be02f361..d0d02bc73d 100644
> --- a/include/qemu/fifo8.h
> +++ b/include/qemu/fifo8.h
> @@ -71,7 +71,7 @@ uint8_t fifo8_pop(Fifo8 *fifo);
>   * fifo8_pop_buf:
>   * @fifo: FIFO to pop from
>   * @max: maximum number of bytes to pop
> - * @num: actual number of returned bytes
> + * @numptr: pointer filled with number of bytes returned (can be NULL)
>   *
>   * Pop a number of elements from the FIFO up to a maximum of max. The buffer
>   * containing the popped data is returned. This buffer points directly into
> @@ -82,16 +82,16 @@ uint8_t fifo8_pop(Fifo8 *fifo);
>   * around in the ring buffer; in this case only a contiguous part of the data
>   * is returned.
>   *
> - * The number of valid bytes returned is populated in *num; will always 
> return
> - * at least 1 byte. max must not be 0 or greater than the number of bytes in
> - * the FIFO.
> + * The number of valid bytes returned is populated in *numptr; will always
> + * return at least 1 byte. max must not be 0 or greater than the number of
> + * bytes in the FIFO.
>   *
>   * Clients are responsible for checking the availability of requested data
>   * using fifo8_num_used().
>   *
>   * Returns: A pointer to popped data.
>   */
> -const uint8_t *fifo8_pop_buf(Fifo8 *fifo, uint32_t max, uint32_t *num);
> +const uint8_t *fifo8_pop_buf(Fifo8 *fifo, uint32_t max, uint32_t *numptr);
>  
>  /**
>   * fifo8_reset:
> diff --git a/util/fifo8.c b/util/fifo8.c
> index d4d1c135e0..032e985440 100644
> --- a/util/fifo8.c
> +++ b/util/fifo8.c
> @@ -66,16 +66,20 @@ uint8_t fifo8_pop(Fifo8 *fifo)
>  return ret;
>  }
>  
> -const uint8_t *fifo8_pop_buf(Fifo8 *fifo, uint32_t max, uint32_t *num)
> +const uint8_t *fifo8_pop_buf(Fifo8 *fifo, uint32_t max, uint32_t *numptr)
>  {
>  uint8_t *ret;
> +uint32_t num;
>  
>  assert(max > 0 && max <= fifo->num);
> -*num = MIN(fifo->capacity - fifo->head, max);
> +num = MIN(fifo->capacity - fifo->head, max);
>  ret = >data[fifo->head];
> -fifo->head += *num;
> +fifo->head += num;
>  fifo->head %= fifo->capacity;
> -fifo->num -= *num;
> +fifo->num -= num;
> +if (numptr) {
> +*numptr = num;
> +}
>  return ret;
>  }
>  
> -- 
> 2.38.1
> 
> 



Re: [PATCH 01/12] util/fifo8: Fix typo in fifo8_push_all() description

2023-05-22 Thread Francisco Iglesias
On [2023 May 22] Mon 17:31:33, Philippe Mathieu-Daudé wrote:
> Signed-off-by: Philippe Mathieu-Daudé 

Reviewed-by: Francisco Iglesias 

> ---
>  include/qemu/fifo8.h | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/include/qemu/fifo8.h b/include/qemu/fifo8.h
> index 28bf2cee57..16be02f361 100644
> --- a/include/qemu/fifo8.h
> +++ b/include/qemu/fifo8.h
> @@ -46,7 +46,7 @@ void fifo8_push(Fifo8 *fifo, uint8_t data);
>   * fifo8_push_all:
>   * @fifo: FIFO to push to
>   * @data: data to push
> - * @size: number of bytes to push
> + * @num: number of bytes to push
>   *
>   * Push a byte array to the FIFO. Behaviour is undefined if the FIFO is full.
>   * Clients are responsible for checking the space left in the FIFO using
> -- 
> 2.38.1
> 
> 



Re: [PATCH] hw/net: Move xilinx_ethlite.c to the target-independent source set

2023-05-08 Thread Francisco Iglesias
On [2023 May 08] Mon 14:03:14, Thomas Huth wrote:
> Now that the tswap() functions are available for target-independent
> code, too, we can move xilinx_ethlite.c from specific_ss to softmmu_ss
> to avoid that we have to compile this file multiple times.
> 
> Signed-off-by: Thomas Huth 

Reviewed-by: Francisco Iglesias 

> ---
>  hw/net/xilinx_ethlite.c | 2 +-
>  hw/net/meson.build  | 2 +-
>  2 files changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/hw/net/xilinx_ethlite.c b/hw/net/xilinx_ethlite.c
> index 99c22819ea..89f4f3b254 100644
> --- a/hw/net/xilinx_ethlite.c
> +++ b/hw/net/xilinx_ethlite.c
> @@ -25,7 +25,7 @@
>  #include "qemu/osdep.h"
>  #include "qemu/module.h"
>  #include "qom/object.h"
> -#include "cpu.h" /* FIXME should not use tswap* */
> +#include "exec/tswap.h"
>  #include "hw/sysbus.h"
>  #include "hw/irq.h"
>  #include "hw/qdev-properties.h"
> diff --git a/hw/net/meson.build b/hw/net/meson.build
> index e2be0654a1..a7860c5efe 100644
> --- a/hw/net/meson.build
> +++ b/hw/net/meson.build
> @@ -43,7 +43,7 @@ softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: 
> files('npcm7xx_emc.c'))
>  softmmu_ss.add(when: 'CONFIG_ETRAXFS', if_true: files('etraxfs_eth.c'))
>  softmmu_ss.add(when: 'CONFIG_COLDFIRE', if_true: files('mcf_fec.c'))
>  specific_ss.add(when: 'CONFIG_PSERIES', if_true: files('spapr_llan.c'))
> -specific_ss.add(when: 'CONFIG_XILINX_ETHLITE', if_true: 
> files('xilinx_ethlite.c'))
> +softmmu_ss.add(when: 'CONFIG_XILINX_ETHLITE', if_true: 
> files('xilinx_ethlite.c'))
>  
>  softmmu_ss.add(when: 'CONFIG_VIRTIO_NET', if_true: files('net_rx_pkt.c'))
>  specific_ss.add(when: 'CONFIG_VIRTIO_NET', if_true: files('virtio-net.c'))
> -- 
> 2.31.1
> 
> 



Re: [PATCH 01/12] aspeed/hace: Initialize g_autofree pointer

2023-05-08 Thread Francisco Iglesias
On [2023 May 08] Mon 09:58:48, Cédric Le Goater wrote:
> As mentioned in docs/devel/style.rst "Automatic memory deallocation":
> 
> * Variables declared with g_auto* MUST always be initialized,
>   otherwise the cleanup function will use uninitialized stack memory
> 
> This avoids QEMU to coredump when running the "hash test" command
> under Zephyr.
> 
> Cc: Steven Lee 
> Cc: Joel Stanley 
> Fixes: c5475b3f9a ("hw: Model ASPEED's Hash and Crypto Engine")
> Reviewed-by: Alex Bennée 
> Reviewed-by: Thomas Huth 
> Message-Id: <20230421131547.2177449-1-...@kaod.org>
> Signed-off-by: Cédric Le Goater 

Reviewed-by: Francisco Iglesias 

> ---
>  hw/misc/aspeed_hace.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/hw/misc/aspeed_hace.c b/hw/misc/aspeed_hace.c
> index 12a761f1f5..b07506ec04 100644
> --- a/hw/misc/aspeed_hace.c
> +++ b/hw/misc/aspeed_hace.c
> @@ -189,7 +189,7 @@ static void do_hash_operation(AspeedHACEState *s, int 
> algo, bool sg_mode,
>bool acc_mode)
>  {
>  struct iovec iov[ASPEED_HACE_MAX_SG];
> -g_autofree uint8_t *digest_buf;
> +g_autofree uint8_t *digest_buf = NULL;
>  size_t digest_len = 0;
>  int niov = 0;
>  int i;
> -- 
> 2.40.0
> 
> 



Re: [PATCH 02/12] aspeed: Introduce a boot_rom region at the machine level

2023-05-08 Thread Francisco Iglesias
On [2023 May 08] Mon 09:58:49, Cédric Le Goater wrote:
> This should also avoid Coverity to report a memory leak warning when
> the QEMU process exits. See CID 1508061.
> 
> Signed-off-by: Cédric Le Goater 

Reviewed-by: Francisco Iglesias 

> ---
>  hw/arm/aspeed.c | 12 ++--
>  1 file changed, 6 insertions(+), 6 deletions(-)
> 
> diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
> index 0b29028fe1..b654513f35 100644
> --- a/hw/arm/aspeed.c
> +++ b/hw/arm/aspeed.c
> @@ -40,6 +40,7 @@ struct AspeedMachineState {
>  /* Public */
>  
>  AspeedSoCState soc;
> +MemoryRegion boot_rom;
>  bool mmio_exec;
>  char *fmc_model;
>  char *spi_model;
> @@ -275,15 +276,15 @@ static void write_boot_rom(BlockBackend *blk, hwaddr 
> addr, size_t rom_size,
>   * Create a ROM and copy the flash contents at the expected address
>   * (0x0). Boots faster than execute-in-place.
>   */
> -static void aspeed_install_boot_rom(AspeedSoCState *soc, BlockBackend *blk,
> +static void aspeed_install_boot_rom(AspeedMachineState *bmc, BlockBackend 
> *blk,
>  uint64_t rom_size)
>  {
> -MemoryRegion *boot_rom = g_new(MemoryRegion, 1);
> +AspeedSoCState *soc = >soc;
>  
> -memory_region_init_rom(boot_rom, NULL, "aspeed.boot_rom", rom_size,
> +memory_region_init_rom(>boot_rom, NULL, "aspeed.boot_rom", rom_size,
> _abort);
>  memory_region_add_subregion_overlap(>spi_boot_container, 0,
> -boot_rom, 1);
> +>boot_rom, 1);
>  write_boot_rom(blk, ASPEED_SOC_SPI_BOOT_ADDR, rom_size, _abort);
>  }
>  
> @@ -431,8 +432,7 @@ static void aspeed_machine_init(MachineState *machine)
>  
>  if (mtd0) {
>  uint64_t rom_size = memory_region_size(>soc.spi_boot);
> -aspeed_install_boot_rom(>soc, blk_by_legacy_dinfo(mtd0),
> -rom_size);
> +aspeed_install_boot_rom(bmc, blk_by_legacy_dinfo(mtd0), 
> rom_size);
>  }
>  }
>  
> -- 
> 2.40.0
> 
> 



Re: [QEMU][PATCH v4 2/4] hw/net/can: Introduce Xilinx Versal CANFD controller

2023-05-02 Thread Francisco Iglesias
Hi Vikram,

A few comments below and some suggestions!


On [2023 Apr 24] Mon 23:34:31, Vikram Garhwal wrote:
> The Xilinx Versal CANFD controller is developed based on SocketCAN, QEMU CAN 
> bus
> implementation. Bus connection and socketCAN connection for each CAN module
> can be set through command lines.
> 
> Signed-off-by: Vikram Garhwal 
> ---
>  hw/net/can/meson.build |1 +
>  hw/net/can/trace-events|7 +
>  hw/net/can/xlnx-versal-canfd.c | 2115 
>  include/hw/net/xlnx-versal-canfd.h |   87 ++
>  4 files changed, 2210 insertions(+)
>  create mode 100644 hw/net/can/xlnx-versal-canfd.c
>  create mode 100644 include/hw/net/xlnx-versal-canfd.h
> 
> diff --git a/hw/net/can/meson.build b/hw/net/can/meson.build
> index 8fabbd9ee6..8d85201cb0 100644
> --- a/hw/net/can/meson.build
> +++ b/hw/net/can/meson.build
> @@ -5,3 +5,4 @@ softmmu_ss.add(when: 'CONFIG_CAN_PCI', if_true: 
> files('can_mioe3680_pci.c'))
>  softmmu_ss.add(when: 'CONFIG_CAN_CTUCANFD', if_true: files('ctucan_core.c'))
>  softmmu_ss.add(when: 'CONFIG_CAN_CTUCANFD_PCI', if_true: 
> files('ctucan_pci.c'))
>  softmmu_ss.add(when: 'CONFIG_XLNX_ZYNQMP', if_true: 
> files('xlnx-zynqmp-can.c'))
> +softmmu_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: 
> files('xlnx-versal-canfd.c'))
> diff --git a/hw/net/can/trace-events b/hw/net/can/trace-events
> index 8346a98ab5..de64ac1b31 100644
> --- a/hw/net/can/trace-events
> +++ b/hw/net/can/trace-events
> @@ -7,3 +7,10 @@ xlnx_can_filter_mask_pre_write(uint8_t filter_num, uint32_t 
> value) "Filter%d MAS
>  xlnx_can_tx_data(uint32_t id, uint8_t dlc, uint8_t db0, uint8_t db1, uint8_t 
> db2, uint8_t db3, uint8_t db4, uint8_t db5, uint8_t db6, uint8_t db7) "Frame: 
> ID: 0x%08x DLC: 0x%02x DATA: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 
> 0x%02x"
>  xlnx_can_rx_data(uint32_t id, uint32_t dlc, uint8_t db0, uint8_t db1, 
> uint8_t db2, uint8_t db3, uint8_t db4, uint8_t db5, uint8_t db6, uint8_t db7) 
> "Frame: ID: 0x%08x DLC: 0x%02x DATA: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 
> 0x%02x 0x%02x 0x%02x"
>  xlnx_can_rx_discard(uint32_t status) "Controller is not enabled for bus 
> communication. Status Register: 0x%08x"
> +
> +# xlnx-versal-canfd.c
> +xlnx_canfd_update_irq(char *path, uint32_t isr, uint32_t ier, uint32_t irq) 
> "%s: ISR: 0x%08x IER: 0x%08x IRQ: 0x%08x"
> +xlnx_canfd_rx_fifo_filter_reject(char *path, uint32_t id, uint8_t dlc) "%s: 
> Frame: ID: 0x%08x DLC: 0x%02x"
> +xlnx_canfd_rx_data(char *path, uint32_t id, uint8_t dlc, uint8_t flags) "%s: 
> Frame: ID: 0x%08x DLC: 0x%02x CANFD Flag: 0x%02x"
> +xlnx_canfd_tx_data(char *path, uint32_t id, uint8_t dlc, uint8_t flgas) "%s: 
> Frame: ID: 0x%08x DLC: 0x%02x CANFD Flag: 0x%02x"
> +xlnx_canfd_reset(char *path, uint32_t val) "%s: Resetting controller with 
> value = 0x%08x"
> diff --git a/hw/net/can/xlnx-versal-canfd.c b/hw/net/can/xlnx-versal-canfd.c
> new file mode 100644
> index 00..fb6fa54698
> --- /dev/null
> +++ b/hw/net/can/xlnx-versal-canfd.c
> @@ -0,0 +1,2115 @@
> +/*
> + * QEMU model of the Xilinx Versal CANFD device.
> + *
> + * This implementation is based on the following datasheet:
> + * https://docs.xilinx.com/v/u/2.0-English/pg223-canfd
> + *
> + * Copyright (c) 2022 AMD Inc.
> + *
> + * Written-by: Vikram Garhwal 
> + *
> + * Based on QEMU CANFD Device emulation implemented by Jin Yang, Deniz Eren 
> and
> + * Pavel Pisa
> + *
> + * 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.
> + */
> +
> +#include "qemu/osdep.h"
> +#include "hw/sysbus.h"
> +#include "hw/irq.h"
> +#include "hw/register.h"
> +#include "qapi/error.h"
> +#include "qemu/bitops.h"
> +#include "qemu/log.h"
> +#include "qemu/cutils.h"
> +#include "qemu/event_notifier.h"
> +#include "hw/qdev-properties.h"
> +#include "qom/object_interfaces.h"
> +#include "migration/vmstate.h"
> +#include "hw/net/xlnx-versal-canfd.h"
> +#include "trace.h"
> 

Re: [PATCH] hw/nvram: Avoid unnecessary Xilinx eFuse backstore write

2023-04-27 Thread Francisco Iglesias
On [2023 Apr 26] Wed 14:16:07, Tong Ho wrote:
> Add a check in the bit-set operation to write the backstore
> only if the affected bit is 0 before.
> 
> With this in place, there will be no need for callers to
> do the checking in order to avoid unnecessary writes.
> 
> Signed-off-by: Tong Ho 

Reviewed-by: Francisco Iglesias 

> ---
>  hw/nvram/xlnx-efuse.c | 11 +--
>  1 file changed, 9 insertions(+), 2 deletions(-)
> 
> diff --git a/hw/nvram/xlnx-efuse.c b/hw/nvram/xlnx-efuse.c
> index fdfffaab99..655c40b8d1 100644
> --- a/hw/nvram/xlnx-efuse.c
> +++ b/hw/nvram/xlnx-efuse.c
> @@ -143,6 +143,8 @@ static bool efuse_ro_bits_find(XlnxEFuse *s, uint32_t k)
>  
>  bool xlnx_efuse_set_bit(XlnxEFuse *s, unsigned int bit)
>  {
> +uint32_t set, *row;
> +
>  if (efuse_ro_bits_find(s, bit)) {
>  g_autofree char *path = object_get_canonical_path(OBJECT(s));
>  
> @@ -152,8 +154,13 @@ bool xlnx_efuse_set_bit(XlnxEFuse *s, unsigned int bit)
>  return false;
>  }
>  
> -s->fuse32[bit / 32] |= 1 << (bit % 32);
> -efuse_bdrv_sync(s, bit);
> +/* Avoid back-end write unless there is a real update */
> +row = >fuse32[bit / 32];
> +set = 1 << (bit % 32);
> +if (!(set & *row)) {
> +*row |= set;
> +efuse_bdrv_sync(s, bit);
> +}
>  return true;
>  }
>  
> -- 
> 2.25.1
> 



Re: [QEMU][PATCH v4 3/4] xlnx-versal: Connect Xilinx VERSAL CANFD controllers

2023-04-25 Thread Francisco Iglesias
clocknames, sizeof(clocknames));


> +
> +qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
> +   GIC_FDT_IRQ_TYPE_SPI, irqs[i],
> +   GIC_FDT_IRQ_FLAGS_LEVEL_HI);
> +qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
> + 2, addrs[i], 2, size[i]);
> +qemu_fdt_setprop_string(s->fdt, name, "compatible",


> +"xlnx,versal-canfd");

And here we can swap above line with (kernel compatible):

"xlnx,canfd-2.0");

After changing above the linux kernel will find the devices:

...
[1.791998] CAN device driver interface
[1.732791] xilinx_can ff06.canfd can0: reg_base=0x(ptrval) 
irq=28 clock=2500, tx buffers: actual 32, using 1
[1.734668] xilinx_can ff07.canfd can1: reg_base=0x(ptrval) 
irq=29 clock=2500, tx buffers: actual 32, using 1
...

...
#  ip a
...
2: can0:  mtu 16 qdisc noop qlen 10
link/[280] 
3: can1:  mtu 16 qdisc noop qlen 10
link/[280] 
...

Looks good otherwise!

Best regards,
Francisco Iglesias


> +
> +g_free(name);
> +}
> +}
> +
>  static void fdt_add_fixed_link_nodes(VersalVirt *s, char *gemname,
>   uint32_t phandle)
>  {
> @@ -639,12 +668,17 @@ static void versal_virt_init(MachineState *machine)
>  TYPE_XLNX_VERSAL);
>  object_property_set_link(OBJECT(>soc), "ddr", OBJECT(machine->ram),
>   _abort);
> +object_property_set_link(OBJECT(>soc), "canbus0", 
> OBJECT(s->canbus[0]),
> + _abort);
> +object_property_set_link(OBJECT(>soc), "canbus1", 
> OBJECT(s->canbus[1]),
> + _abort);
>  sysbus_realize(SYS_BUS_DEVICE(>soc), _fatal);
>  
>  fdt_create(s);
>  create_virtio_regions(s);
>  fdt_add_gem_nodes(s);
>  fdt_add_uart_nodes(s);
> +fdt_add_canfd_nodes(s);
>  fdt_add_gic_nodes(s);
>  fdt_add_timer_nodes(s);
>  fdt_add_zdma_nodes(s);
> @@ -712,6 +746,20 @@ static void versal_virt_init(MachineState *machine)
>  
>  static void versal_virt_machine_instance_init(Object *obj)
>  {
> +VersalVirt *s = XLNX_VERSAL_VIRT_MACHINE(obj);
> +
> +/*
> + * User can set canbus0 and canbus1 properties to can-bus object and 
> connect
> + * to socketcan(optional) interface via command line.
> + */
> +object_property_add_link(obj, "canbus0", TYPE_CAN_BUS,
> + (Object **)>canbus[0],
> + object_property_allow_set_link,
> + 0);
> +object_property_add_link(obj, "canbus1", TYPE_CAN_BUS,
> + (Object **)>canbus[1],
> + object_property_allow_set_link,
> + 0);
>  }
>  
>  static void versal_virt_machine_class_init(ObjectClass *oc, void *data)
> diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
> index 69b1b99e93..1594dd6c5c 100644
> --- a/hw/arm/xlnx-versal.c
> +++ b/hw/arm/xlnx-versal.c
> @@ -184,6 +184,38 @@ static void versal_create_uarts(Versal *s, qemu_irq *pic)
>  }
>  }
>  
> +static void versal_create_canfds(Versal *s, qemu_irq *pic)
> +{
> +int i;
> +uint32_t irqs[] = { VERSAL_CANFD0_IRQ_0, VERSAL_CANFD1_IRQ_0};
> +uint64_t addrs[] = { MM_CANFD0, MM_CANFD1 };
> +
> +for (i = 0; i < ARRAY_SIZE(s->lpd.iou.canfd); i++) {
> +char *name = g_strdup_printf("canfd%d", i);
> +SysBusDevice *sbd;
> +MemoryRegion *mr;
> +
> +object_initialize_child(OBJECT(s), name, >lpd.iou.canfd[i],
> +TYPE_XILINX_CANFD);
> +sbd = SYS_BUS_DEVICE(>lpd.iou.canfd[i]);
> +
> +object_property_set_int(OBJECT(>lpd.iou.canfd[i]), "ext_clk_freq",
> +XLNX_VERSAL_CANFD_REF_CLK , _abort);
> +
> +object_property_set_link(OBJECT(>lpd.iou.canfd[i]), "canfdbus",
> + OBJECT(s->lpd.iou.canbus[i]),
> + _abort);
> +
> +sysbus_realize(sbd, _fatal);
> +
> +mr = sysbus_mmio_get_region(sbd, 0);
> +memory_region_add_subregion(>mr_ps, addrs[i], mr);
> +
> +sysbus_connect_irq(sbd, 0, pic[irqs[i]]);
> +g_free(name);
> +}
> +}
> +
>  static void versal_create_usbs(Versal *s, qemu_irq *pic)
>  {
>  DeviceState *dev;
> @@ -718,6 +75

Re: [QEMU][PATCH v4 1/4] MAINTAINERS: Include canfd tests under Xilinx CAN

2023-04-25 Thread Francisco Iglesias
On [2023 Apr 24] Mon 23:34:30, Vikram Garhwal wrote:
> Signed-off-by: Vikram Garhwal 
> Reviewed-by: Peter Maydell 

Reviewed-by: Francisco Iglesias 

> ---
>  MAINTAINERS | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 24154f5721..c3dbacb615 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -1809,7 +1809,7 @@ M: Francisco Iglesias 
>  S: Maintained
>  F: hw/net/can/xlnx-*
>  F: include/hw/net/xlnx-*
> -F: tests/qtest/xlnx-can-test*
> +F: tests/qtest/xlnx-can*-test*
>  
>  EDU
>  M: Jiri Slaby 
> -- 
> 2.17.1
> 



Re: [PATCH v2 10/10] contrib/gitdm: add group map for AMD

2023-03-13 Thread Francisco Iglesias




On 2023-03-10 19:03, Alex Bennée wrote:

AMD recently acquired Xilinx and contributors have been transitioning
their emails across.
 > Signed-off-by: Alex Bennée 


Reviewed-by: Francisco Iglesias 


Cc: Vikram Garhwal 
Cc: Francisco Iglesias 
Cc: Stefano Stabellini 
Cc: Sai Pavan Boddu 
Cc: Tong Ho 
---
  contrib/gitdm/domain-map| 1 -
  contrib/gitdm/group-map-amd | 8 
  gitdm.config| 1 +
  3 files changed, 9 insertions(+), 1 deletion(-)
  create mode 100644 contrib/gitdm/group-map-amd

diff --git a/contrib/gitdm/domain-map b/contrib/gitdm/domain-map
index ee0804b6ed..79fd65b077 100644
--- a/contrib/gitdm/domain-map
+++ b/contrib/gitdm/domain-map
@@ -50,6 +50,5 @@ virtuozzo.com   Virtuozzo
  vrull.euVRULL
  wdc.com Western Digital
  windriver.com   Wind River
-xilinx.com  Xilinx
  yadro.com   YADRO
  yandex-team.ru  Yandex
diff --git a/contrib/gitdm/group-map-amd b/contrib/gitdm/group-map-amd
new file mode 100644
index 00..bda4239a8a
--- /dev/null
+++ b/contrib/gitdm/group-map-amd
@@ -0,0 +1,8 @@
+# AMD acquired Xilinx and contributors have been slowly updating emails
+
+edgar.igles...@xilinx.com
+fnu.vik...@xilinx.com
+francisco.igles...@xilinx.com
+sai.pavan.bo...@xilinx.com
+stefano.stabell...@xilinx.com
+tong...@xilinx.com
diff --git a/gitdm.config b/gitdm.config
index 6908ddbd19..c9d961dd23 100644
--- a/gitdm.config
+++ b/gitdm.config
@@ -32,6 +32,7 @@ EmailMap contrib/gitdm/domain-map
  #
  
  GroupMap contrib/gitdm/group-map-alibaba Alibaba

+GroupMap contrib/gitdm/group-map-amd AMD
  GroupMap contrib/gitdm/group-map-cadence Cadence Design Systems
  GroupMap contrib/gitdm/group-map-codeweavers CodeWeavers
  GroupMap contrib/gitdm/group-map-facebook Facebook




Re: [PATCH] hw/arm: Add missing ZynqMP ZCU102 -> USB_DWC3 Kconfig dependency

2023-02-16 Thread Francisco Iglesias




On 2023-02-16 10:23, Philippe Mathieu-Daudé wrote:

Since commit acc0b8b05a when running the ZynqMP ZCU102 board with
a QEMU configured using --without-default-devices, we get:

   $ qemu-system-aarch64 -M xlnx-zcu102
   qemu-system-aarch64: missing object type 'usb_dwc3'
   Abort trap: 6

Fix by adding the missing Kconfig dependency.

Fixes: acc0b8b05a ("hw/arm/xlnx-zynqmp: Connect ZynqMP's USB controllers")
Signed-off-by: Philippe Mathieu-Daudé 


Reviewed-by: Francisco Iglesias 


---
  hw/arm/Kconfig | 1 +
  1 file changed, 1 insertion(+)

diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 2d157de9b8..b5aed4aff5 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -389,6 +389,7 @@ config XLNX_ZYNQMP_ARM
  select XLNX_CSU_DMA
  select XLNX_ZYNQMP
  select XLNX_ZDMA
+select USB_DWC3
  
  config XLNX_VERSAL

  bool




Re: [PATCH v2] m25p80: Improve error when the backend file size does not match the device

2022-11-16 Thread Francisco Iglesias
On [2022 Nov 15] Tue 16:10:00, Cédric Le Goater wrote:
> Currently, when a block backend is attached to a m25p80 device and the
> associated file size does not match the flash model, QEMU complains
> with the error message "failed to read the initial flash content".
> This is confusing for the user.
> 
> Use blk_check_size_and_read_all() instead of blk_pread() to improve
> the reported error.
> 
> Signed-off-by: Cédric Le Goater 

Reviewed-by: Francisco Iglesias 

> ---
>  hw/block/m25p80.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c
> index 02adc87527..68a757abf3 100644
> --- a/hw/block/m25p80.c
> +++ b/hw/block/m25p80.c
> @@ -24,6 +24,7 @@
>  #include "qemu/osdep.h"
>  #include "qemu/units.h"
>  #include "sysemu/block-backend.h"
> +#include "hw/block/block.h"
>  #include "hw/qdev-properties.h"
>  #include "hw/qdev-properties-system.h"
>  #include "hw/ssi/ssi.h"
> @@ -1614,8 +1615,7 @@ static void m25p80_realize(SSIPeripheral *ss, Error 
> **errp)
>  trace_m25p80_binding(s);
>  s->storage = blk_blockalign(s->blk, s->size);
>  
> -if (blk_pread(s->blk, 0, s->size, s->storage, 0) < 0) {
> -error_setg(errp, "failed to read the initial flash content");
> +if (!blk_check_size_and_read_all(s->blk, s->storage, s->size, errp)) 
> {
>  return;
>  }
>  } else {
> -- 
> 2.38.1
> 



Re: [QEMU][PATCH v2 3/5] xlnx-zynqmp: Connect Xilinx VERSAL CANFD controllers

2022-11-09 Thread Francisco Iglesias
Hi Vikram,

In the git summary s/zynqmp/versal/.

On [2022 Oct 21] Fri 22:47:44, Vikram Garhwal wrote:
> Connect CANFD0 and CANFD1 on the Versal-virt machine and update 
> xlnx-versal-virt
> document with CANFD command line examples.
> 
> Signed-off-by: Vikram Garhwal 
> ---
>  docs/system/arm/xlnx-versal-virt.rst | 31 ++
>  hw/arm/xlnx-versal-virt.c| 48 
>  hw/arm/xlnx-versal.c | 37 +
>  include/hw/arm/xlnx-versal.h | 12 +++
>  4 files changed, 128 insertions(+)
> 
> diff --git a/docs/system/arm/xlnx-versal-virt.rst 
> b/docs/system/arm/xlnx-versal-virt.rst
> index 92ad10d2da..372e4249f0 100644
> --- a/docs/system/arm/xlnx-versal-virt.rst
> +++ b/docs/system/arm/xlnx-versal-virt.rst
> @@ -34,6 +34,7 @@ Implemented devices:
>  - DDR memory
>  - BBRAM (36 bytes of Battery-backed RAM)
>  - eFUSE (3072 bytes of one-time field-programmable bit array)
> +- 2 CANFDs
>  
>  QEMU does not yet model any other devices, including the PL and the AI 
> Engine.
>  
> @@ -224,3 +225,33 @@ To use a different index value, N, from default of 1, 
> add:
>  
>Better yet, do not use actual product data when running guest image
>on this Xilinx Versal Virt board.
> +
> +Using CANFDs for Versal Virt
> +
> +Versal CANFD controller is developed based on SocketCAN and QEMU CAN bus
> +implementation. Bus connection and socketCAN connection for each CAN module
> +can be set through command lines.
> +
> +To connect both CANFD0 and CANFD1 on the same bus:
> +
> +.. code-block:: bash
> +
> +-object can-bus,id=canbus -machine canbus0=canbus -machine canbus1=canbus
> +
> +To connect CANFD0 and CANFD1 to separate buses:
> +
> +.. code-block:: bash
> +
> +-object can-bus,id=canbus0 -object can-bus,id=canbus1 \
> +-machine canbus0=canbus0 -machine canbus1=canbus1
> +
> +SocketCAN interface can connect to a Physical or a Virtual CAN interfaces on
> +host machine.

I'm not native english but this sounds better to me:

"The SocketCAN interface can connect to a Physical or a Virtual CAN interface on
the host machine."

> Please check this document to learn about CAN interface on Linux:
> +docs/system/devices/can.rst
> +
> +To connect CANFD0 and CANFD1 to host machine's CAN interface can0:
> +
> +.. code-block:: bash
> +
> +-object can-bus,id=canbus -machine canbus0=canbus -machine canbus1=canbus
> +-object can-host-socketcan,id=canhost0,if=can0,canbus=canbus
> diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
> index 37fc9b919c..963ace861e 100644
> --- a/hw/arm/xlnx-versal-virt.c
> +++ b/hw/arm/xlnx-versal-virt.c
> @@ -40,9 +40,11 @@ struct VersalVirt {
>  uint32_t clk_25Mhz;
>  uint32_t usb;
>  uint32_t dwc;
> +uint32_t canfd[2];
>  } phandle;
>  struct arm_boot_info binfo;
>  
> +CanBusState *canbus[XLNX_VERSAL_NR_CANFD];
>  struct {
>  bool secure;
>  } cfg;
> @@ -235,6 +237,33 @@ static void fdt_add_uart_nodes(VersalVirt *s)
>  }
>  }
>  
> +static void fdt_add_canfd_nodes(VersalVirt *s)
> +{
> +uint64_t addrs[] = { MM_CANFD0, MM_CANFD1 };
> +uint32_t size[] = { MM_CANFD0_SIZE, MM_CANFD1_SIZE };
> +unsigned int irqs[] = { VERSAL_CANFD0_IRQ_0, VERSAL_CANFD1_IRQ_0 };
> +int i;
> +
> +/* Create and connect CANFD0 and CANFD1 nodes to canbus0. */
> +for (i = 0; i < ARRAY_SIZE(addrs); i++) {
> +char *name = g_strdup_printf("/canfd@%" PRIx64, addrs[i]);
> +qemu_fdt_add_subnode(s->fdt, name);
> +qemu_fdt_setprop_cell(s->fdt, name, "rx-fifo0", 0x40);
> +qemu_fdt_setprop_cell(s->fdt, name, "enable-rx-fifo1", 0x1);
> +qemu_fdt_setprop_cell(s->fdt, name, "rx-fifo1", 0x40);
> +
> +qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
> +   GIC_FDT_IRQ_TYPE_SPI, irqs[i],
> +   GIC_FDT_IRQ_FLAGS_LEVEL_HI);
> +qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
> + 2, addrs[i], 2, size[i]);
> +qemu_fdt_setprop_string(s->fdt, name, "compatible",
> +"xlnx,versal-canfd");

For the nodes we need to go with something similar to this:
https://github.com/Xilinx/linux-xlnx/blob/master/arch/arm64/boot/dts/xilinx/versal.dtsi#L153

> +
> +g_free(name);
> +}
> +}
> +
>  static void fdt_add_fixed_link_nodes(VersalVirt *s, char *gemname,
>   uint32_t phandle)
>  {
> @@ -639,12 +668,17 @@ static void versal_virt_init(MachineState *machine)
>  TYPE_XLNX_VERSAL);
>  object_property_set_link(OBJECT(>soc), "ddr", OBJECT(machine->ram),
>   _abort);
> +object_property_set_link(OBJECT(>soc), "canbus0", 
> OBJECT(s->canbus[0]),
> + _abort);
> +object_property_set_link(OBJECT(>soc), "canbus1", 
> 

Re: [QEMU][PATCH v2 4/5] tests/qtest: Introduce tests for Xilinx VERSAL CANFD controller

2022-11-08 Thread Francisco Iglesias
On [2022 Oct 21] Fri 22:47:45, Vikram Garhwal wrote:
> The QTests perform three tests on the Xilinx VERSAL CANFD controller:
> Tests the CANFD controllers in loopback.
> Tests the CANFD controllers in normal mode with CAN frame.
> Tests the CANFD controllers in normal mode with CANFD frame.
> 
> Signed-off-by: Vikram Garhwal 
> Acked-by: Thomas Huth 

Reviewed-by: Francisco Iglesias 

> ---
>  tests/qtest/meson.build   |   1 +
>  tests/qtest/xlnx-canfd-test.c | 422 ++
>  2 files changed, 423 insertions(+)
>  create mode 100644 tests/qtest/xlnx-canfd-test.c
> 
> diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
> index c07a5b1a5f..9486ebee24 100644
> --- a/tests/qtest/meson.build
> +++ b/tests/qtest/meson.build
> @@ -213,6 +213,7 @@ qtests_aarch64 = \
>(config_all_devices.has_key('CONFIG_TPM_TIS_SYSBUS') ? 
> ['tpm-tis-device-test'] : []) +\
>(config_all_devices.has_key('CONFIG_TPM_TIS_SYSBUS') ? 
> ['tpm-tis-device-swtpm-test'] : []) +  \
>(config_all_devices.has_key('CONFIG_XLNX_ZYNQMP_ARM') ? ['xlnx-can-test', 
> 'fuzz-xlnx-dp-test'] : []) + \
> +  (config_all_devices.has_key('CONFIG_XLNX_VERSAL') ? ['xlnx-canfd-test'] : 
> []) + \
>['arm-cpu-features',
> 'numa-test',
> 'boot-serial-test',
> diff --git a/tests/qtest/xlnx-canfd-test.c b/tests/qtest/xlnx-canfd-test.c
> new file mode 100644
> index 00..d0e3e43b78
> --- /dev/null
> +++ b/tests/qtest/xlnx-canfd-test.c
> @@ -0,0 +1,422 @@
> +/* SPDX-License-Identifier: MIT
> + *
> + * QTests for the Xilinx Versal CANFD controller.
> + *
> + * Copyright (c) 2022 AMD Inc.
> + *
> + * Written-by: Vikram Garhwal
> + *
> + * 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.
> + */
> +
> +#include "qemu/osdep.h"
> +#include "libqtest.h"
> +
> +/* Base address. */
> +#define CANFD0_BASE_ADDR0xFF06
> +#define CANFD1_BASE_ADDR0xFF07
> +
> +/* Register addresses. */
> +#define R_SRR_OFFSET0x00
> +#define R_MSR_OFFSET0x04
> +#define R_FILTER_CONTROL_REGISTER   0xe0
> +#define R_SR_OFFSET 0x18
> +#define R_ISR_OFFSET0x1C
> +#define R_IER_OFFSET0x20
> +#define R_ICR_OFFSET0x24
> +#define R_TX_READY_REQ_REGISTER 0x90
> +#define RX_FIFO_STATUS_REGISTER 0xE8
> +#define R_TXID_OFFSET   0x100
> +#define R_TXDLC_OFFSET  0x104
> +#define R_TXDATA1_OFFSET0x108
> +#define R_TXDATA2_OFFSET0x10C
> +#define R_AFMR_REGISTER00xa00
> +#define R_AFIR_REGISTER00xa04
> +#define R_RX0_ID_OFFSET 0x2100
> +#define R_RX0_DLC_OFFSET0x2104
> +#define R_RX0_DATA1_OFFSET  0x2108
> +#define R_RX0_DATA2_OFFSET  0x210C
> +
> +/* CANFD modes. */
> +#define SRR_CONFIG_MODE 0x00
> +#define MSR_NORMAL_MODE 0x00
> +#define MSR_LOOPBACK_MODE   (1 << 1)
> +#define ENABLE_CANFD(1 << 1)
> +
> +/* CANFD status. */
> +#define STATUS_CONFIG_MODE  (1 << 0)
> +#define STATUS_NORMAL_MODE  (1 << 3)
> +#define STATUS_LOOPBACK_MODE(1 << 1)
> +#define ISR_TXOK(1 << 1)
> +#define ISR_RXOK(1 << 4)
> +
> +#define ENABLE_ALL_FILTERS  0x
> +#define ENABLE_ALL_INTERRUPTS

Re: [QEMU][PATCH v2 5/5] MAINTAINERS: Include canfd tests under Xilinx CAN

2022-11-08 Thread Francisco Iglesias
On [2022 Oct 21] Fri 22:47:46, Vikram Garhwal wrote:
> Signed-off-by: Vikram Garhwal 
> Reviewed-by: Peter Maydell 

Reviewed-by: Francisco Iglesias 

> ---
>  MAINTAINERS | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 538af2885c..a642026361 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -1756,7 +1756,7 @@ M: Francisco Iglesias 
>  S: Maintained
>  F: hw/net/can/xlnx-*
>  F: include/hw/net/xlnx-*
> -F: tests/qtest/xlnx-can-test*
> +F: tests/qtest/xlnx-can*-test*
>  
>  EDU
>  M: Jiri Slaby 
> -- 
> 2.17.1
> 
> 



Re: [PATCH v4 03/10] m25p80: Add erase size for mx25l25635e

2022-10-14 Thread Francisco Iglesias
On [2022 Oct 13] Thu 18:12:34, Cédric Le Goater wrote:
> Signed-off-by: Cédric Le Goater 

Reviewed-by: Francisco Iglesias 

> ---
>  hw/block/m25p80.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c
> index 13e7b28fd2b0..637c25d76e37 100644
> --- a/hw/block/m25p80.c
> +++ b/hw/block/m25p80.c
> @@ -232,7 +232,8 @@ static const FlashPartInfo known_devices[] = {
>  { INFO("mx25l6405d",  0xc22017,  0,  64 << 10, 128, 0) },
>  { INFO("mx25l12805d", 0xc22018,  0,  64 << 10, 256, 0) },
>  { INFO("mx25l12855e", 0xc22618,  0,  64 << 10, 256, 0) },
> -{ INFO6("mx25l25635e", 0xc22019, 0xc22019,  64 << 10, 512, 0) },
> +{ INFO6("mx25l25635e", 0xc22019, 0xc22019,  64 << 10, 512,
> +ER_4K | ER_32K) },
>  { INFO("mx25l25655e", 0xc22619,  0,  64 << 10, 512, 0) },
>  { INFO("mx66l51235f", 0xc2201a,  0,  64 << 10, 1024, ER_4K | ER_32K) 
> },
>  { INFO("mx66u51235f", 0xc2253a,  0,  64 << 10, 1024, ER_4K | ER_32K) 
> },
> -- 
> 2.37.3
> 



Re: [PATCH v3 4/8] m25p80: Add the mx25l25635f SFPD table

2022-10-10 Thread Francisco Iglesias
Hi  Cedric,

On [2022 Oct 10] Mon 11:58:40, Michael Walle wrote:
> Am 2022-10-10 08:23, schrieb Cédric Le Goater:
> > On 10/7/22 16:44, Francisco Iglesias wrote:
> 
> > > > --- a/hw/block/m25p80.c
> > > > +++ b/hw/block/m25p80.c
> > > > @@ -234,6 +234,8 @@ static const FlashPartInfo known_devices[] = {
> > > >   { INFO("mx25l12855e", 0xc22618,  0,  64 << 10, 256, 0) },
> > > >   { INFO6("mx25l25635e", 0xc22019, 0xc22019,  64 << 10,
> > > > 512, 0),
> > > > .sfdp_read = m25p80_sfdp_mx25l25635e },
> > > > +{ INFO6("mx25l25635f", 0xc22019, 0xc22019,  64 << 10,
> > > > 512, 0),

I think I missed the (ER_4K | ER_32K) flags above (in case we go for a v4 we 
can add it in). 

> > > 
> > > I think I'm not seeing the extended id part in the datasheet I've
> > > found so
> > > might be that you can switch to just INFO and _ext_id 0 above
> > 
> > This was added by commit 6bbe036f32dc ("m25p80: Return the JEDEC ID
> > twice for
> > mx25l25635e") to fix a real breakage on HW.
> 
> From my experience, the ID has a particular length, at least three bytes
> and if you read past that length for some (all?) devices the id bytes just
> get repeated. I.e. the counter in the device will just wrap to offset 0
> again. If you want to emulate the hardware correctly, you would have to
> take that into consideration.

If we decide to go with Michael's proposal above you can use '0' on the
'extended_id' and enable 's->data_read_loop = true' when reading the ID.

Best regards,
Francisco

> But I don't think it's worth it, OTOH there seems to be some broken
> software which rely on that (undefined?) behavior.
> 
> -michael




Re: [PATCH] m25p80: Add the w25q01jvq SFPD table

2022-10-07 Thread Francisco Iglesias
On [2022 Oct 06] Thu 17:44:24, Patrick Williams wrote:
> Generated from hardware using the following command and then padding
> with 0xff to fill out a power-of-2:
> hexdump -v -e '8/1 "0x%02x, " "\n"' sfdp`
> 
> Signed-off-by: Patrick Williams 
> ---
>  hw/block/m25p80.c  |  3 ++-
>  hw/block/m25p80_sfdp.c | 36 
>  hw/block/m25p80_sfdp.h |  2 ++
>  3 files changed, 40 insertions(+), 1 deletion(-)
> 
> diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c
> index 8ba9d732a3..86343160ef 100644
> --- a/hw/block/m25p80.c
> +++ b/hw/block/m25p80.c
> @@ -349,7 +349,8 @@ static const FlashPartInfo known_devices[] = {
>.sfdp_read = m25p80_sfdp_w25q256 },
>  { INFO("w25q512jv",   0xef4020,  0,  64 << 10, 1024, ER_4K),
>.sfdp_read = m25p80_sfdp_w25q512jv },
> -{ INFO("w25q01jvq",   0xef4021,  0,  64 << 10, 2048, ER_4K) },
> +{ INFO("w25q01jvq",   0xef4021,  0,  64 << 10, 2048, ER_4K),
> +  .sfdp_read = m25p80_sfdp_w25q01jvq },
>  };
>  
>  typedef enum {
> diff --git a/hw/block/m25p80_sfdp.c b/hw/block/m25p80_sfdp.c
> index dad3d7e64f..77615fa29e 100644
> --- a/hw/block/m25p80_sfdp.c
> +++ b/hw/block/m25p80_sfdp.c
> @@ -294,3 +294,39 @@ static const uint8_t sfdp_w25q512jv[] = {
>  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
>  };
>  define_sfdp_read(w25q512jv);
> +
> +static const uint8_t sfdp_w25q01jvq[] = {
> +0x53, 0x46, 0x44, 0x50, 0x06, 0x01, 0x01, 0xff,
> +0x00, 0x06, 0x01, 0x10, 0x80, 0x00, 0x00, 0xff,
> +0x84, 0x00, 0x01, 0x02, 0xd0, 0x00, 0x00, 0xff,
> +0x03, 0x00, 0x01, 0x02, 0xf0, 0x00, 0x00, 0xff,
> +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +0xe5, 0x20, 0xfb, 0xff, 0xff, 0xff, 0xff, 0x3f,
> +0x44, 0xeb, 0x08, 0x6b, 0x08, 0x3b, 0x42, 0xbb,
> +0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
> +0xff, 0xff, 0x40, 0xeb, 0x0c, 0x20, 0x0f, 0x52,
> +0x10, 0xd8, 0x00, 0x00, 0x36, 0x02, 0xa6, 0x00,
> +0x82, 0xea, 0x14, 0xe2, 0xe9, 0x63, 0x76, 0x33,
> +0x7a, 0x75, 0x7a, 0x75, 0xf7, 0xa2, 0xd5, 0x5c,
> +0x19, 0xf7, 0x4d, 0xff, 0xe9, 0x70, 0xf9, 0xa5,
> +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +0xff, 0x0a, 0xf0, 0xff, 0x21, 0xff, 0xdc, 0xff,
> +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +};
> +define_sfdp_read(w25q01jvq);
> diff --git a/hw/block/m25p80_sfdp.h b/hw/block/m25p80_sfdp.h
> index 62f140a2fc..8fb1cd3f8a 100644
> --- a/hw/block/m25p80_sfdp.h
> +++ b/hw/block/m25p80_sfdp.h
> @@ -24,4 +24,6 @@ extern uint8_t m25p80_sfdp_mx66l1g45g(uint32_t addr);
>  extern uint8_t m25p80_sfdp_w25q256(uint32_t addr);
>  extern uint8_t m25p80_sfdp_w25q512jv(uint32_t addr);
>  
> +extern uint8_t m25p80_sfdp_w25q01jvq(uint32_t addr);
(optional -extern)

Reviewed-by: Francisco Iglesias 

> +
>  #endif
> -- 
> 2.35.1
> 



  1   2   3   4   5   6   >