qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/7] Register API leaks fixes
@ 2025-09-17 11:44 Luc Michel
  2025-09-17 11:44 ` [PATCH 1/7] hw/core/register: remove the REGISTER device type Luc Michel
                   ` (8 more replies)
  0 siblings, 9 replies; 23+ messages in thread
From: Luc Michel @ 2025-09-17 11:44 UTC (permalink / raw)
  To: qemu-devel, qemu-arm
  Cc: Luc Michel, Peter Maydell, Francisco Iglesias, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Vikram Garhwal

Based-on: 20250912100059.103997-1-luc.michel@amd.com ([PATCH v5 00/47] AMD Versal Gen 2 support)

Hello,

This series addresses the memory leaks caused by the register API. The
first patches fix the API itself while the last ones take care of the
CANFD model.

The leaks in the register API were caused by:
   - the REGISTER device being initialized without being realized nor
     finalized. Those devices were not parented to anything and were
     not using the qdev API. So in the end I chose to drop the REGISTER
     object completely (patch 1).
   - Register API users not calling `register_finalize_block' on the
     RegisterInfoArray returned by `register_init_block'. Instead of
     fixing all the users, I chose to simplify the API by removing the
     need for this call. I turned the RegisterInfoArray struct into a QOM
     object and parented it to the device in `register_init_block'. This
     way it has its own finalize function that gets called when the
     parent device is finalized. This implies a small API change: the
     `register_finalize_block' function is removed (patch 2, 3, 4).

The CANFD model needed special care. It was rolling out its own version
of `register_init_block', including the discrepancies leading to the
memory leaks. This is because the register map of this device is
composed of main registers (from 0x0 to 0xec), followed by several banks
of multiple registers (Tx banks, filter banks, Txe banks, ...). The
register API is not suited for this kind of layout and the resulting
code to handle that is convoluted. However a simple decoding logic is
easily written for this, those registers having basically no side effect
upon access.

Patch 6 introduces this decoding logic for the banked registers, patch 7
removes the register API bits for those, keeping the one for the base
registers.

Note: this series is based on my Versal 2 series. It modifies the CRL
device during the register API refactoring. It can easily be rebased on
master if needed.

Thanks

Luc


Luc Michel (7):
  hw/core/register: remove the REGISTER device type
  hw/core/register: add the REGISTER_ARRAY type
  hw/core/register: remove the calls to `register_finalize_block'
  hw/core/register: remove the `register_finalize_block' function
  hw/net/can/xlnx-versal-canfd: remove unused include directives
  hw/net/can/xlnx-versal-canfd: refactor the banked registers logic
  hw/net/can/xlnx-versal-canfd: remove register API usage for banked
    regs

 include/hw/misc/xlnx-versal-crl.h      |   1 -
 include/hw/misc/xlnx-versal-xramc.h    |   1 -
 include/hw/misc/xlnx-zynqmp-apu-ctrl.h |   1 -
 include/hw/misc/xlnx-zynqmp-crf.h      |   1 -
 include/hw/net/xlnx-versal-canfd.h     |   8 -
 include/hw/nvram/xlnx-bbram.h          |   1 -
 include/hw/register.h                  |  25 +-
 hw/core/register.c                     |  36 +-
 hw/misc/xlnx-versal-crl.c              |  38 +--
 hw/misc/xlnx-versal-trng.c             |   1 -
 hw/misc/xlnx-versal-xramc.c            |  12 +-
 hw/misc/xlnx-zynqmp-apu-ctrl.c         |  12 +-
 hw/misc/xlnx-zynqmp-crf.c              |  12 +-
 hw/net/can/xlnx-versal-canfd.c         | 434 +++++++++----------------
 hw/nvram/xlnx-bbram.c                  |  13 +-
 hw/nvram/xlnx-versal-efuse-ctrl.c      |   1 -
 hw/nvram/xlnx-zynqmp-efuse.c           |   8 -
 17 files changed, 196 insertions(+), 409 deletions(-)

-- 
2.50.1



^ permalink raw reply	[flat|nested] 23+ messages in thread

* [PATCH 1/7] hw/core/register: remove the REGISTER device type
  2025-09-17 11:44 [PATCH 0/7] Register API leaks fixes Luc Michel
@ 2025-09-17 11:44 ` Luc Michel
  2025-09-19  8:49   ` Francisco Iglesias
  2025-09-28 23:32   ` Alistair Francis
  2025-09-17 11:44 ` [PATCH 2/7] hw/core/register: add the REGISTER_ARRAY type Luc Michel
                   ` (7 subsequent siblings)
  8 siblings, 2 replies; 23+ messages in thread
From: Luc Michel @ 2025-09-17 11:44 UTC (permalink / raw)
  To: qemu-devel, qemu-arm
  Cc: Luc Michel, Peter Maydell, Francisco Iglesias, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis

The REGISTER class (RegisterInfo struct) is currently a QOM type
inheriting from DEVICE. This class has no real purpose:
   - the qdev API is not used,
   - according to the comment preceding it, the object_initialize call
     is here to zero-initialize the struct. However all the effective
     struct attributes are then initialized explicitly.
   - the object is never parented.

This commits drops the REGISTER QOM type completely, leaving the
RegisterInfo struct as a bare C struct.

The register_register_types function is left empty here because it is
reused in the next commit.

Signed-off-by: Luc Michel <luc.michel@amd.com>
---
 include/hw/register.h |  7 -------
 hw/core/register.c    | 18 ------------------
 2 files changed, 25 deletions(-)

diff --git a/include/hw/register.h b/include/hw/register.h
index a913c52aee5..4d13ea183c7 100644
--- a/include/hw/register.h
+++ b/include/hw/register.h
@@ -73,25 +73,18 @@ struct RegisterAccessInfo {
  *
  * @opaque: Opaque data for the register
  */
 
 struct RegisterInfo {
-    /* <private> */
-    DeviceState parent_obj;
-
-    /* <public> */
     void *data;
     int data_size;
 
     const RegisterAccessInfo *access;
 
     void *opaque;
 };
 
-#define TYPE_REGISTER "qemu-register"
-DECLARE_INSTANCE_CHECKER(RegisterInfo, REGISTER,
-                         TYPE_REGISTER)
 
 /**
  * This structure is used to group all of the individual registers which are
  * modeled using the RegisterInfo structure.
  *
diff --git a/hw/core/register.c b/hw/core/register.c
index 8f63d9f227c..57dde29710c 100644
--- a/hw/core/register.c
+++ b/hw/core/register.c
@@ -256,13 +256,10 @@ static RegisterInfoArray *register_init_block(DeviceState *owner,
 
     for (i = 0; i < num; i++) {
         int index = rae[i].addr / data_size;
         RegisterInfo *r = &ri[index];
 
-        /* Init the register, this will zero it. */
-        object_initialize((void *)r, sizeof(*r), TYPE_REGISTER);
-
         /* Set the properties of the register */
         r->data = data + data_size * index;
         r->data_size = data_size;
         r->access = &rae[i];
         r->opaque = owner;
@@ -317,26 +314,11 @@ void register_finalize_block(RegisterInfoArray *r_array)
     object_unparent(OBJECT(&r_array->mem));
     g_free(r_array->r);
     g_free(r_array);
 }
 
-static void register_class_init(ObjectClass *oc, const void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(oc);
-
-    /* Reason: needs to be wired up to work */
-    dc->user_creatable = false;
-}
-
-static const TypeInfo register_info = {
-    .name  = TYPE_REGISTER,
-    .parent = TYPE_DEVICE,
-    .class_init = register_class_init,
-    .instance_size = sizeof(RegisterInfo),
-};
 
 static void register_register_types(void)
 {
-    type_register_static(&register_info);
 }
 
 type_init(register_register_types)
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 2/7] hw/core/register: add the REGISTER_ARRAY type
  2025-09-17 11:44 [PATCH 0/7] Register API leaks fixes Luc Michel
  2025-09-17 11:44 ` [PATCH 1/7] hw/core/register: remove the REGISTER device type Luc Michel
@ 2025-09-17 11:44 ` Luc Michel
  2025-09-19  8:50   ` Francisco Iglesias
  2025-09-28 23:34   ` Alistair Francis
  2025-09-17 11:44 ` [PATCH 3/7] hw/core/register: remove the calls to `register_finalize_block' Luc Michel
                   ` (6 subsequent siblings)
  8 siblings, 2 replies; 23+ messages in thread
From: Luc Michel @ 2025-09-17 11:44 UTC (permalink / raw)
  To: qemu-devel, qemu-arm
  Cc: Luc Michel, Peter Maydell, Francisco Iglesias, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis

Introduce the REGISTER_ARRAY QOM type. This type reuses the existing
RegisterInfoArray struct. When `register_init_block' is called, it creates
a REGISTER_ARRAY object and parents it to the calling device. This way
it gets finalized when the device is.

The finalize function of the REGISTER_ARRAY type performs the necessary
cleaning that used to be done by `register_finalize_block'. The latter
is left empty and will be removed when all the register API users have
been refactored.

Signed-off-by: Luc Michel <luc.michel@amd.com>
---
 include/hw/register.h |  4 ++++
 hw/core/register.c    | 24 +++++++++++++++++++++---
 2 files changed, 25 insertions(+), 3 deletions(-)

diff --git a/include/hw/register.h b/include/hw/register.h
index 4d13ea183c7..65c82600e06 100644
--- a/include/hw/register.h
+++ b/include/hw/register.h
@@ -81,10 +81,12 @@ struct RegisterInfo {
     const RegisterAccessInfo *access;
 
     void *opaque;
 };
 
+#define TYPE_REGISTER_ARRAY "qemu-register-array"
+OBJECT_DECLARE_SIMPLE_TYPE(RegisterInfoArray, REGISTER_ARRAY)
 
 /**
  * This structure is used to group all of the individual registers which are
  * modeled using the RegisterInfo structure.
  *
@@ -94,10 +96,12 @@ struct RegisterInfo {
  *
  * @mem: optional Memory region for the register
  */
 
 struct RegisterInfoArray {
+    Object parent_obj;
+
     MemoryRegion mem;
 
     int num_elements;
     RegisterInfo **r;
 
diff --git a/hw/core/register.c b/hw/core/register.c
index 57dde29710c..4d1cce02a55 100644
--- a/hw/core/register.c
+++ b/hw/core/register.c
@@ -243,14 +243,20 @@ static RegisterInfoArray *register_init_block(DeviceState *owner,
                                               bool debug_enabled,
                                               uint64_t memory_size,
                                               size_t data_size_bits)
 {
     const char *device_prefix = object_get_typename(OBJECT(owner));
-    RegisterInfoArray *r_array = g_new0(RegisterInfoArray, 1);
+    Object *obj;
+    RegisterInfoArray *r_array;
     int data_size = data_size_bits >> 3;
     int i;
 
+    obj = object_new(TYPE_REGISTER_ARRAY);
+    object_property_add_child(OBJECT(owner), "reg-array[*]", obj);
+    object_unref(obj);
+
+    r_array = REGISTER_ARRAY(obj);
     r_array->r = g_new0(RegisterInfo *, num);
     r_array->num_elements = num;
     r_array->debug = debug_enabled;
     r_array->prefix = device_prefix;
 
@@ -307,18 +313,30 @@ RegisterInfoArray *register_init_block64(DeviceState *owner,
 {
     return register_init_block(owner, rae, num, ri, (void *)
                                data, ops, debug_enabled, memory_size, 64);
 }
 
-void register_finalize_block(RegisterInfoArray *r_array)
+static void register_array_finalize(Object *obj)
 {
+    RegisterInfoArray *r_array = REGISTER_ARRAY(obj);
+
     object_unparent(OBJECT(&r_array->mem));
     g_free(r_array->r);
-    g_free(r_array);
 }
 
+void register_finalize_block(RegisterInfoArray *r_array)
+{
+}
+
+static const TypeInfo register_array_info = {
+    .name  = TYPE_REGISTER_ARRAY,
+    .parent = TYPE_OBJECT,
+    .instance_size = sizeof(RegisterInfoArray),
+    .instance_finalize = register_array_finalize,
+};
 
 static void register_register_types(void)
 {
+    type_register_static(&register_array_info);
 }
 
 type_init(register_register_types)
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 3/7] hw/core/register: remove the calls to `register_finalize_block'
  2025-09-17 11:44 [PATCH 0/7] Register API leaks fixes Luc Michel
  2025-09-17 11:44 ` [PATCH 1/7] hw/core/register: remove the REGISTER device type Luc Michel
  2025-09-17 11:44 ` [PATCH 2/7] hw/core/register: add the REGISTER_ARRAY type Luc Michel
@ 2025-09-17 11:44 ` Luc Michel
  2025-09-19  8:51   ` Francisco Iglesias
  2025-09-28 23:35   ` Alistair Francis
  2025-09-17 11:44 ` [PATCH 4/7] hw/core/register: remove the `register_finalize_block' function Luc Michel
                   ` (5 subsequent siblings)
  8 siblings, 2 replies; 23+ messages in thread
From: Luc Michel @ 2025-09-17 11:44 UTC (permalink / raw)
  To: qemu-devel, qemu-arm
  Cc: Luc Michel, Peter Maydell, Francisco Iglesias, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis

This function is now a no-op. The register array is parented to the
device and get finalized when the device is.

Drop all the calls to `register_finalize_block'. Drop the
RegisterInfoArray reference when it is not used elsewhere in the device.

Signed-off-by: Luc Michel <luc.michel@amd.com>
---
 include/hw/misc/xlnx-versal-crl.h      |  1 -
 include/hw/misc/xlnx-versal-xramc.h    |  1 -
 include/hw/misc/xlnx-zynqmp-apu-ctrl.h |  1 -
 include/hw/misc/xlnx-zynqmp-crf.h      |  1 -
 include/hw/nvram/xlnx-bbram.h          |  1 -
 hw/misc/xlnx-versal-crl.c              | 38 +++++++++++---------------
 hw/misc/xlnx-versal-trng.c             |  1 -
 hw/misc/xlnx-versal-xramc.c            | 12 ++------
 hw/misc/xlnx-zynqmp-apu-ctrl.c         | 12 ++------
 hw/misc/xlnx-zynqmp-crf.c              | 12 ++------
 hw/nvram/xlnx-bbram.c                  | 13 ++-------
 hw/nvram/xlnx-versal-efuse-ctrl.c      |  1 -
 hw/nvram/xlnx-zynqmp-efuse.c           |  8 ------
 13 files changed, 28 insertions(+), 74 deletions(-)

diff --git a/include/hw/misc/xlnx-versal-crl.h b/include/hw/misc/xlnx-versal-crl.h
index f6b8694ebea..49ed500acde 100644
--- a/include/hw/misc/xlnx-versal-crl.h
+++ b/include/hw/misc/xlnx-versal-crl.h
@@ -531,11 +531,10 @@ REG32(VERSAL2_RST_OCM, 0x3d8)
 #define VERSAL2_CRL_R_MAX (R_VERSAL2_RST_OCM + 1)
 
 struct XlnxVersalCRLBase {
     SysBusDevice parent_obj;
 
-    RegisterInfoArray *reg_array;
     uint32_t *regs;
 };
 
 struct XlnxVersalCRLBaseClass {
     SysBusDeviceClass parent_class;
diff --git a/include/hw/misc/xlnx-versal-xramc.h b/include/hw/misc/xlnx-versal-xramc.h
index d3d1862676f..35e4e8b91dd 100644
--- a/include/hw/misc/xlnx-versal-xramc.h
+++ b/include/hw/misc/xlnx-versal-xramc.h
@@ -88,10 +88,9 @@ typedef struct XlnxXramCtrl {
     struct {
         uint64_t size;
         unsigned int encoded_size;
     } cfg;
 
-    RegisterInfoArray *reg_array;
     uint32_t regs[XRAM_CTRL_R_MAX];
     RegisterInfo regs_info[XRAM_CTRL_R_MAX];
 } XlnxXramCtrl;
 #endif
diff --git a/include/hw/misc/xlnx-zynqmp-apu-ctrl.h b/include/hw/misc/xlnx-zynqmp-apu-ctrl.h
index c3bf3c1583b..fbfe34aa7e5 100644
--- a/include/hw/misc/xlnx-zynqmp-apu-ctrl.h
+++ b/include/hw/misc/xlnx-zynqmp-apu-ctrl.h
@@ -83,11 +83,10 @@ struct XlnxZynqMPAPUCtrl {
     qemu_irq irq_imr;
 
     uint8_t cpu_pwrdwn_req;
     uint8_t cpu_in_wfi;
 
-    RegisterInfoArray *reg_array;
     uint32_t regs[APU_R_MAX];
     RegisterInfo regs_info[APU_R_MAX];
 };
 
 #endif
diff --git a/include/hw/misc/xlnx-zynqmp-crf.h b/include/hw/misc/xlnx-zynqmp-crf.h
index 02ef0bdeeee..c746ae10397 100644
--- a/include/hw/misc/xlnx-zynqmp-crf.h
+++ b/include/hw/misc/xlnx-zynqmp-crf.h
@@ -201,11 +201,10 @@ REG32(RST_DDR_SS, 0x108)
 struct XlnxZynqMPCRF {
     SysBusDevice parent_obj;
     MemoryRegion iomem;
     qemu_irq irq_ir;
 
-    RegisterInfoArray *reg_array;
     uint32_t regs[CRF_R_MAX];
     RegisterInfo regs_info[CRF_R_MAX];
 };
 
 #endif
diff --git a/include/hw/nvram/xlnx-bbram.h b/include/hw/nvram/xlnx-bbram.h
index 58acbe9f51b..af90900bfc6 100644
--- a/include/hw/nvram/xlnx-bbram.h
+++ b/include/hw/nvram/xlnx-bbram.h
@@ -45,11 +45,10 @@ struct XlnxBBRam {
 
     uint32_t crc_zpads;
     bool bbram8_wo;
     bool blk_ro;
 
-    RegisterInfoArray *reg_array;
     uint32_t regs[RMAX_XLNX_BBRAM];
     RegisterInfo regs_info[RMAX_XLNX_BBRAM];
 };
 
 #endif
diff --git a/hw/misc/xlnx-versal-crl.c b/hw/misc/xlnx-versal-crl.c
index 10e6af002ba..5987f32c716 100644
--- a/hw/misc/xlnx-versal-crl.c
+++ b/hw/misc/xlnx-versal-crl.c
@@ -632,21 +632,21 @@ static const MemoryRegionOps crl_ops = {
 static void versal_crl_init(Object *obj)
 {
     XlnxVersalCRL *s = XLNX_VERSAL_CRL(obj);
     XlnxVersalCRLBase *xvcb = XLNX_VERSAL_CRL_BASE(obj);
     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+    RegisterInfoArray *reg_array;
     int i;
 
-    xvcb->reg_array =
-        register_init_block32(DEVICE(obj), crl_regs_info,
-                              ARRAY_SIZE(crl_regs_info),
-                              s->regs_info, s->regs,
-                              &crl_ops,
-                              XLNX_VERSAL_CRL_ERR_DEBUG,
-                              CRL_R_MAX * 4);
+    reg_array = register_init_block32(DEVICE(obj), crl_regs_info,
+                                      ARRAY_SIZE(crl_regs_info),
+                                      s->regs_info, s->regs,
+                                      &crl_ops,
+                                      XLNX_VERSAL_CRL_ERR_DEBUG,
+                                      CRL_R_MAX * 4);
     xvcb->regs = s->regs;
-    sysbus_init_mmio(sbd, &xvcb->reg_array->mem);
+    sysbus_init_mmio(sbd, &reg_array->mem);
     sysbus_init_irq(sbd, &s->irq);
 
     for (i = 0; i < ARRAY_SIZE(s->cfg.rpu); ++i) {
         object_property_add_link(obj, "rpu[*]", TYPE_ARM_CPU,
                                  (Object **)&s->cfg.rpu[i],
@@ -686,21 +686,22 @@ static void versal_crl_init(Object *obj)
 static void versal2_crl_init(Object *obj)
 {
     XlnxVersal2CRL *s = XLNX_VERSAL2_CRL(obj);
     XlnxVersalCRLBase *xvcb = XLNX_VERSAL_CRL_BASE(obj);
     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+    RegisterInfoArray *reg_array;
     size_t i;
 
-    xvcb->reg_array = register_init_block32(DEVICE(obj), versal2_crl_regs_info,
-                                            ARRAY_SIZE(versal2_crl_regs_info),
-                                            s->regs_info, s->regs,
-                                            &crl_ops,
-                                            XLNX_VERSAL_CRL_ERR_DEBUG,
-                                            VERSAL2_CRL_R_MAX * 4);
+    reg_array = register_init_block32(DEVICE(obj), versal2_crl_regs_info,
+                                      ARRAY_SIZE(versal2_crl_regs_info),
+                                      s->regs_info, s->regs,
+                                      &crl_ops,
+                                      XLNX_VERSAL_CRL_ERR_DEBUG,
+                                      VERSAL2_CRL_R_MAX * 4);
     xvcb->regs = s->regs;
 
-    sysbus_init_mmio(sbd, &xvcb->reg_array->mem);
+    sysbus_init_mmio(sbd, &reg_array->mem);
 
     for (i = 0; i < ARRAY_SIZE(s->cfg.rpu); ++i) {
         object_property_add_link(obj, "rpu[*]", TYPE_ARM_CPU,
                                  (Object **)&s->cfg.rpu[i],
                                  qdev_prop_allow_set_link_before_realize,
@@ -748,16 +749,10 @@ static void versal2_crl_init(Object *obj)
                                  qdev_prop_allow_set_link_before_realize,
                                  OBJ_PROP_LINK_STRONG);
     }
 }
 
-static void crl_finalize(Object *obj)
-{
-    XlnxVersalCRLBase *s = XLNX_VERSAL_CRL_BASE(obj);
-    register_finalize_block(s->reg_array);
-}
-
 static const VMStateDescription vmstate_versal_crl = {
     .name = TYPE_XLNX_VERSAL_CRL,
     .version_id = 1,
     .minimum_version_id = 1,
     .fields = (const VMStateField[]) {
@@ -802,11 +797,10 @@ static void versal2_crl_class_init(ObjectClass *klass, const void *data)
 static const TypeInfo crl_base_info = {
     .name          = TYPE_XLNX_VERSAL_CRL_BASE,
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(XlnxVersalCRLBase),
     .class_size    = sizeof(XlnxVersalCRLBaseClass),
-    .instance_finalize = crl_finalize,
     .abstract      = true,
 };
 
 static const TypeInfo versal_crl_info = {
     .name          = TYPE_XLNX_VERSAL_CRL,
diff --git a/hw/misc/xlnx-versal-trng.c b/hw/misc/xlnx-versal-trng.c
index f34dd3ef352..2b573a45bdb 100644
--- a/hw/misc/xlnx-versal-trng.c
+++ b/hw/misc/xlnx-versal-trng.c
@@ -625,11 +625,10 @@ static void trng_init(Object *obj)
 
 static void trng_finalize(Object *obj)
 {
     XlnxVersalTRng *s = XLNX_VERSAL_TRNG(obj);
 
-    register_finalize_block(s->reg_array);
     g_rand_free(s->prng);
     s->prng = NULL;
 }
 
 static void trng_reset_hold(Object *obj, ResetType type)
diff --git a/hw/misc/xlnx-versal-xramc.c b/hw/misc/xlnx-versal-xramc.c
index 07370b80c0d..d90f3e87c74 100644
--- a/hw/misc/xlnx-versal-xramc.c
+++ b/hw/misc/xlnx-versal-xramc.c
@@ -188,28 +188,23 @@ static void xram_ctrl_realize(DeviceState *dev, Error **errp)
 
 static void xram_ctrl_init(Object *obj)
 {
     XlnxXramCtrl *s = XLNX_XRAM_CTRL(obj);
     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+    RegisterInfoArray *reg_array;
 
-    s->reg_array =
+    reg_array =
         register_init_block32(DEVICE(obj), xram_ctrl_regs_info,
                               ARRAY_SIZE(xram_ctrl_regs_info),
                               s->regs_info, s->regs,
                               &xram_ctrl_ops,
                               XLNX_XRAM_CTRL_ERR_DEBUG,
                               XRAM_CTRL_R_MAX * 4);
-    sysbus_init_mmio(sbd, &s->reg_array->mem);
+    sysbus_init_mmio(sbd, &reg_array->mem);
     sysbus_init_irq(sbd, &s->irq);
 }
 
-static void xram_ctrl_finalize(Object *obj)
-{
-    XlnxXramCtrl *s = XLNX_XRAM_CTRL(obj);
-    register_finalize_block(s->reg_array);
-}
-
 static const VMStateDescription vmstate_xram_ctrl = {
     .name = TYPE_XLNX_XRAM_CTRL,
     .version_id = 1,
     .minimum_version_id = 1,
     .fields = (const VMStateField[]) {
@@ -239,11 +234,10 @@ static const TypeInfo xram_ctrl_info = {
     .name              = TYPE_XLNX_XRAM_CTRL,
     .parent            = TYPE_SYS_BUS_DEVICE,
     .instance_size     = sizeof(XlnxXramCtrl),
     .class_init        = xram_ctrl_class_init,
     .instance_init     = xram_ctrl_init,
-    .instance_finalize = xram_ctrl_finalize,
 };
 
 static void xram_ctrl_register_types(void)
 {
     type_register_static(&xram_ctrl_info);
diff --git a/hw/misc/xlnx-zynqmp-apu-ctrl.c b/hw/misc/xlnx-zynqmp-apu-ctrl.c
index e85da32d99c..08777496d56 100644
--- a/hw/misc/xlnx-zynqmp-apu-ctrl.c
+++ b/hw/misc/xlnx-zynqmp-apu-ctrl.c
@@ -177,20 +177,21 @@ static void zynqmp_apu_handle_wfi(void *opaque, int irq, int level)
 }
 
 static void zynqmp_apu_init(Object *obj)
 {
     XlnxZynqMPAPUCtrl *s = XLNX_ZYNQMP_APU_CTRL(obj);
+    RegisterInfoArray *reg_array;
     int i;
 
-    s->reg_array =
+    reg_array =
         register_init_block32(DEVICE(obj), zynqmp_apu_regs_info,
                               ARRAY_SIZE(zynqmp_apu_regs_info),
                               s->regs_info, s->regs,
                               &zynqmp_apu_ops,
                               XILINX_ZYNQMP_APU_ERR_DEBUG,
                               APU_R_MAX * 4);
-    sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->reg_array->mem);
+    sysbus_init_mmio(SYS_BUS_DEVICE(obj), &reg_array->mem);
     sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq_imr);
 
     for (i = 0; i < APU_MAX_CPU; ++i) {
         g_autofree gchar *prop_name = g_strdup_printf("cpu%d", i);
         object_property_add_link(obj, prop_name, TYPE_ARM_CPU,
@@ -206,16 +207,10 @@ static void zynqmp_apu_init(Object *obj)
                              "CPU_POWER_STATUS", 4);
     /* wfi_in is used as input from CPUs as wfi request. */
     qdev_init_gpio_in_named(DEVICE(obj), zynqmp_apu_handle_wfi, "wfi_in", 4);
 }
 
-static void zynqmp_apu_finalize(Object *obj)
-{
-    XlnxZynqMPAPUCtrl *s = XLNX_ZYNQMP_APU_CTRL(obj);
-    register_finalize_block(s->reg_array);
-}
-
 static const VMStateDescription vmstate_zynqmp_apu = {
     .name = TYPE_XLNX_ZYNQMP_APU_CTRL,
     .version_id = 1,
     .minimum_version_id = 1,
     .fields = (const VMStateField[]) {
@@ -239,11 +234,10 @@ static const TypeInfo zynqmp_apu_info = {
     .name              = TYPE_XLNX_ZYNQMP_APU_CTRL,
     .parent            = TYPE_SYS_BUS_DEVICE,
     .instance_size     = sizeof(XlnxZynqMPAPUCtrl),
     .class_init        = zynqmp_apu_class_init,
     .instance_init     = zynqmp_apu_init,
-    .instance_finalize = zynqmp_apu_finalize,
 };
 
 static void zynqmp_apu_register_types(void)
 {
     type_register_static(&zynqmp_apu_info);
diff --git a/hw/misc/xlnx-zynqmp-crf.c b/hw/misc/xlnx-zynqmp-crf.c
index cccca0e814e..d9c1bd50e4f 100644
--- a/hw/misc/xlnx-zynqmp-crf.c
+++ b/hw/misc/xlnx-zynqmp-crf.c
@@ -209,28 +209,23 @@ static const MemoryRegionOps crf_ops = {
 
 static void crf_init(Object *obj)
 {
     XlnxZynqMPCRF *s = XLNX_ZYNQMP_CRF(obj);
     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+    RegisterInfoArray *reg_array;
 
-    s->reg_array =
+    reg_array =
         register_init_block32(DEVICE(obj), crf_regs_info,
                               ARRAY_SIZE(crf_regs_info),
                               s->regs_info, s->regs,
                               &crf_ops,
                               XLNX_ZYNQMP_CRF_ERR_DEBUG,
                               CRF_R_MAX * 4);
-    sysbus_init_mmio(sbd, &s->reg_array->mem);
+    sysbus_init_mmio(sbd, &reg_array->mem);
     sysbus_init_irq(sbd, &s->irq_ir);
 }
 
-static void crf_finalize(Object *obj)
-{
-    XlnxZynqMPCRF *s = XLNX_ZYNQMP_CRF(obj);
-    register_finalize_block(s->reg_array);
-}
-
 static const VMStateDescription vmstate_crf = {
     .name = TYPE_XLNX_ZYNQMP_CRF,
     .version_id = 1,
     .minimum_version_id = 1,
     .fields = (const VMStateField[]) {
@@ -253,11 +248,10 @@ static const TypeInfo crf_info = {
     .name              = TYPE_XLNX_ZYNQMP_CRF,
     .parent            = TYPE_SYS_BUS_DEVICE,
     .instance_size     = sizeof(XlnxZynqMPCRF),
     .class_init        = crf_class_init,
     .instance_init     = crf_init,
-    .instance_finalize = crf_finalize,
 };
 
 static void crf_register_types(void)
 {
     type_register_static(&crf_info);
diff --git a/hw/nvram/xlnx-bbram.c b/hw/nvram/xlnx-bbram.c
index 5702bb3f310..22aefbc240d 100644
--- a/hw/nvram/xlnx-bbram.c
+++ b/hw/nvram/xlnx-bbram.c
@@ -454,30 +454,24 @@ static void bbram_ctrl_realize(DeviceState *dev, Error **errp)
 
 static void bbram_ctrl_init(Object *obj)
 {
     XlnxBBRam *s = XLNX_BBRAM(obj);
     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+    RegisterInfoArray *reg_array;
 
-    s->reg_array =
+    reg_array =
         register_init_block32(DEVICE(obj), bbram_ctrl_regs_info,
                               ARRAY_SIZE(bbram_ctrl_regs_info),
                               s->regs_info, s->regs,
                               &bbram_ctrl_ops,
                               XLNX_BBRAM_ERR_DEBUG,
                               R_MAX * 4);
 
-    sysbus_init_mmio(sbd, &s->reg_array->mem);
+    sysbus_init_mmio(sbd, &reg_array->mem);
     sysbus_init_irq(sbd, &s->irq_bbram);
 }
 
-static void bbram_ctrl_finalize(Object *obj)
-{
-    XlnxBBRam *s = XLNX_BBRAM(obj);
-
-    register_finalize_block(s->reg_array);
-}
-
 static void bbram_prop_set_drive(Object *obj, Visitor *v, const char *name,
                                  void *opaque, Error **errp)
 {
     DeviceState *dev = DEVICE(obj);
 
@@ -540,11 +534,10 @@ static const TypeInfo bbram_ctrl_info = {
     .name          = TYPE_XLNX_BBRAM,
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(XlnxBBRam),
     .class_init    = bbram_ctrl_class_init,
     .instance_init = bbram_ctrl_init,
-    .instance_finalize = bbram_ctrl_finalize,
 };
 
 static void bbram_ctrl_register_types(void)
 {
     type_register_static(&bbram_ctrl_info);
diff --git a/hw/nvram/xlnx-versal-efuse-ctrl.c b/hw/nvram/xlnx-versal-efuse-ctrl.c
index 90962198008..6f17f32a0c3 100644
--- a/hw/nvram/xlnx-versal-efuse-ctrl.c
+++ b/hw/nvram/xlnx-versal-efuse-ctrl.c
@@ -726,11 +726,10 @@ static void efuse_ctrl_init(Object *obj)
 
 static void efuse_ctrl_finalize(Object *obj)
 {
     XlnxVersalEFuseCtrl *s = XLNX_VERSAL_EFUSE_CTRL(obj);
 
-    register_finalize_block(s->reg_array);
     g_free(s->extra_pg0_lock_spec);
 }
 
 static const VMStateDescription vmstate_efuse_ctrl = {
     .name = TYPE_XLNX_VERSAL_EFUSE_CTRL,
diff --git a/hw/nvram/xlnx-zynqmp-efuse.c b/hw/nvram/xlnx-zynqmp-efuse.c
index 5a218c32e84..ce35bb0cc1f 100644
--- a/hw/nvram/xlnx-zynqmp-efuse.c
+++ b/hw/nvram/xlnx-zynqmp-efuse.c
@@ -814,17 +814,10 @@ static void zynqmp_efuse_init(Object *obj)
 
     sysbus_init_mmio(sbd, &s->reg_array->mem);
     sysbus_init_irq(sbd, &s->irq);
 }
 
-static void zynqmp_efuse_finalize(Object *obj)
-{
-    XlnxZynqMPEFuse *s = XLNX_ZYNQMP_EFUSE(obj);
-
-    register_finalize_block(s->reg_array);
-}
-
 static const VMStateDescription vmstate_efuse = {
     .name = TYPE_XLNX_ZYNQMP_EFUSE,
     .version_id = 1,
     .minimum_version_id = 1,
     .fields = (const VMStateField[]) {
@@ -855,11 +848,10 @@ static const TypeInfo efuse_info = {
     .name          = TYPE_XLNX_ZYNQMP_EFUSE,
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(XlnxZynqMPEFuse),
     .class_init    = zynqmp_efuse_class_init,
     .instance_init = zynqmp_efuse_init,
-    .instance_finalize = zynqmp_efuse_finalize,
 };
 
 static void efuse_register_types(void)
 {
     type_register_static(&efuse_info);
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 4/7] hw/core/register: remove the `register_finalize_block' function
  2025-09-17 11:44 [PATCH 0/7] Register API leaks fixes Luc Michel
                   ` (2 preceding siblings ...)
  2025-09-17 11:44 ` [PATCH 3/7] hw/core/register: remove the calls to `register_finalize_block' Luc Michel
@ 2025-09-17 11:44 ` Luc Michel
  2025-09-19  8:52   ` Francisco Iglesias
  2025-09-28 23:35   ` Alistair Francis
  2025-09-17 11:44 ` [PATCH 5/7] hw/net/can/xlnx-versal-canfd: remove unused include directives Luc Michel
                   ` (4 subsequent siblings)
  8 siblings, 2 replies; 23+ messages in thread
From: Luc Michel @ 2025-09-17 11:44 UTC (permalink / raw)
  To: qemu-devel, qemu-arm
  Cc: Luc Michel, Peter Maydell, Francisco Iglesias, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis

This function is now unused. Drop it.

Signed-off-by: Luc Michel <luc.michel@amd.com>
---
 include/hw/register.h | 14 --------------
 hw/core/register.c    |  4 ----
 2 files changed, 18 deletions(-)

diff --git a/include/hw/register.h b/include/hw/register.h
index 65c82600e06..7b0f4c8b7a6 100644
--- a/include/hw/register.h
+++ b/include/hw/register.h
@@ -207,20 +207,6 @@ RegisterInfoArray *register_init_block64(DeviceState *owner,
                                          uint64_t *data,
                                          const MemoryRegionOps *ops,
                                          bool debug_enabled,
                                          uint64_t memory_size);
 
-/**
- * This function should be called to cleanup the registers that were initialized
- * when calling register_init_block32(). This function should only be called
- * from the device's instance_finalize function.
- *
- * Any memory operations that the device performed that require cleanup (such
- * as creating subregions) need to be called before calling this function.
- *
- * @r_array: A structure containing all of the registers, as returned by
- *           register_init_block32()
- */
-
-void register_finalize_block(RegisterInfoArray *r_array);
-
 #endif
diff --git a/hw/core/register.c b/hw/core/register.c
index 4d1cce02a55..6cfcfcd2b14 100644
--- a/hw/core/register.c
+++ b/hw/core/register.c
@@ -321,14 +321,10 @@ static void register_array_finalize(Object *obj)
 
     object_unparent(OBJECT(&r_array->mem));
     g_free(r_array->r);
 }
 
-void register_finalize_block(RegisterInfoArray *r_array)
-{
-}
-
 static const TypeInfo register_array_info = {
     .name  = TYPE_REGISTER_ARRAY,
     .parent = TYPE_OBJECT,
     .instance_size = sizeof(RegisterInfoArray),
     .instance_finalize = register_array_finalize,
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 5/7] hw/net/can/xlnx-versal-canfd: remove unused include directives
  2025-09-17 11:44 [PATCH 0/7] Register API leaks fixes Luc Michel
                   ` (3 preceding siblings ...)
  2025-09-17 11:44 ` [PATCH 4/7] hw/core/register: remove the `register_finalize_block' function Luc Michel
@ 2025-09-17 11:44 ` Luc Michel
  2025-09-19  8:47   ` Francisco Iglesias
  2025-09-28 23:36   ` Alistair Francis
  2025-09-17 11:44 ` [PATCH 6/7] hw/net/can/xlnx-versal-canfd: refactor the banked registers logic Luc Michel
                   ` (3 subsequent siblings)
  8 siblings, 2 replies; 23+ messages in thread
From: Luc Michel @ 2025-09-17 11:44 UTC (permalink / raw)
  To: qemu-devel, qemu-arm
  Cc: Luc Michel, Peter Maydell, Francisco Iglesias, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis

Drop unecessary include directives in xlnx-versal-canfd.c.

Signed-off-by: Luc Michel <luc.michel@amd.com>
---
 hw/net/can/xlnx-versal-canfd.c | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/hw/net/can/xlnx-versal-canfd.c b/hw/net/can/xlnx-versal-canfd.c
index 3eb111949f8..343348660b5 100644
--- a/hw/net/can/xlnx-versal-canfd.c
+++ b/hw/net/can/xlnx-versal-canfd.c
@@ -33,16 +33,12 @@
 #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"
 
 REG32(SOFTWARE_RESET_REGISTER, 0x0)
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 6/7] hw/net/can/xlnx-versal-canfd: refactor the banked registers logic
  2025-09-17 11:44 [PATCH 0/7] Register API leaks fixes Luc Michel
                   ` (4 preceding siblings ...)
  2025-09-17 11:44 ` [PATCH 5/7] hw/net/can/xlnx-versal-canfd: remove unused include directives Luc Michel
@ 2025-09-17 11:44 ` Luc Michel
  2025-09-19  8:48   ` Francisco Iglesias
  2025-09-17 11:44 ` [PATCH 7/7] hw/net/can/xlnx-versal-canfd: remove register API usage for banked regs Luc Michel
                   ` (2 subsequent siblings)
  8 siblings, 1 reply; 23+ messages in thread
From: Luc Michel @ 2025-09-17 11:44 UTC (permalink / raw)
  To: qemu-devel, qemu-arm
  Cc: Luc Michel, Peter Maydell, Francisco Iglesias, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis

The CANFD device has several groups of registers:
  - the main control registers from 0x0 to 0xec
  - several banks of multiple registers. The number of banks is either
    hardcoded, or configurable using QOM properties:
      - Tx registers
      - Filter registers
      - Tx events registers
      - Rx0 registers
      - Rx1 registers

As of now, all the registers are handled using the register API. The
banked register logic results in a convoluted code to correctly allocate
the register descriptors for the register API. This code bypasses the
standard register API creation function (register_init_block). The
resulting code leaks memory when the device is finalized.

This commit introduces decoding logic for the banked registers. Those
registers are quite simple in practice. Accessing them triggers no
side-effect (only the filter registers need a check to catch guest
invalid behaviour). Starting from the Tx events registers, they are all
read-only.

The main device memory region is changed to an I/O one, calling the
new decoding logic when accessed. The register API memory region still
overlaps all of it so for now the introduced code has no effect. The
next commit will remove the register API usage for banked registers.

Signed-off-by: Luc Michel <luc.michel@amd.com>
---
 hw/net/can/xlnx-versal-canfd.c | 155 ++++++++++++++++++++++++++++++++-
 1 file changed, 153 insertions(+), 2 deletions(-)

diff --git a/hw/net/can/xlnx-versal-canfd.c b/hw/net/can/xlnx-versal-canfd.c
index 343348660b5..81615bc52a6 100644
--- a/hw/net/can/xlnx-versal-canfd.c
+++ b/hw/net/can/xlnx-versal-canfd.c
@@ -1408,10 +1408,27 @@ static uint64_t canfd_srr_pre_write(RegisterInfo *reg, uint64_t val64)
     }
 
     return s->regs[R_SOFTWARE_RESET_REGISTER];
 }
 
+static void filter_reg_write(XlnxVersalCANFDState *s, hwaddr addr,
+                             size_t bank_idx, uint32_t val)
+{
+    size_t reg_idx = addr / sizeof(uint32_t);
+
+    if (!(s->regs[R_ACCEPTANCE_FILTER_CONTROL_REGISTER] &
+        (1 << bank_idx))) {
+        s->regs[reg_idx] = val;
+    } else {
+        g_autofree char *path = object_get_canonical_path(OBJECT(s));
+
+        qemu_log_mask(LOG_GUEST_ERROR, "%s: Acceptance filter register 0x%"
+                      HWADDR_PRIx " changed while filter %zu enabled\n",
+                      path, addr, bank_idx + 1);
+    }
+}
+
 static uint64_t filter_mask(RegisterInfo *reg, uint64_t val64)
 {
     XlnxVersalCANFDState *s = XILINX_CANFD(reg->opaque);
     uint32_t reg_idx = (reg->access->addr) / 4;
     uint32_t val = val64;
@@ -1761,11 +1778,145 @@ static const RegisterAccessInfo canfd_regs_info[] = {
 static void xlnx_versal_canfd_ptimer_cb(void *opaque)
 {
     /* No action required on the timer rollover. */
 }
 
+static bool canfd_decode_reg_bank(XlnxVersalCANFDState *s, hwaddr addr,
+                                  hwaddr first_reg, hwaddr last_reg,
+                                  size_t num_banks, size_t *idx, size_t *offset)
+{
+    hwaddr base = addr - first_reg;
+    hwaddr span = last_reg - first_reg + sizeof(uint32_t);
+
+    *idx = base / span;
+
+    if (*idx >= num_banks) {
+        return false;
+    }
+
+    *offset = base % span;
+    *offset += first_reg;
+
+    return true;
+}
+
+/*
+ * Decode the given addr into a (idx, offset) pair:
+ *   - idx is the bank index of the register at addr,
+ *   - offset is the register offset relative to bank 0
+ *
+ * @return true is the decoding succeded, false otherwise
+ */
+static bool canfd_decode_addr(XlnxVersalCANFDState *s, hwaddr addr,
+                              size_t *idx, size_t *offset)
+{
+    if (addr <= A_RX_FIFO_WATERMARK_REGISTER) {
+        /* from 0x0 to 0xec. Handled by the register API */
+        g_assert_not_reached();
+    } else if (addr < A_TB_ID_REGISTER) {
+        /* no register in this gap */
+        return false;
+    } else if (addr < A_AFMR_REGISTER) {
+        /* TX registers */
+        return canfd_decode_reg_bank(s, addr,
+                                     A_TB_ID_REGISTER, A_TB_DW15_REGISTER,
+                                     s->cfg.tx_fifo, idx, offset);
+    } else if (addr < A_TXE_FIFO_TB_ID_REGISTER) {
+        /* Filter registers */
+        return canfd_decode_reg_bank(s, addr,
+                                     A_AFMR_REGISTER, A_AFIR_REGISTER,
+                                     32, idx, offset);
+    } else if (addr < A_RB_ID_REGISTER) {
+        /* TX event registers */
+        return canfd_decode_reg_bank(s, addr,
+                                     A_TXE_FIFO_TB_ID_REGISTER,
+                                     A_TXE_FIFO_TB_DLC_REGISTER,
+                                     32, idx, offset);
+    } else if (addr < A_RB_ID_REGISTER_1) {
+        /* RX0 registers */
+        return canfd_decode_reg_bank(s, addr,
+                                     A_RB_ID_REGISTER,
+                                     A_RB_DW15_REGISTER,
+                                     s->cfg.rx0_fifo, idx, offset);
+    } else if (addr <= A_RB_DW15_REGISTER_1) {
+        /* RX1 registers */
+        return canfd_decode_reg_bank(s, addr,
+                                     A_RB_ID_REGISTER_1,
+                                     A_RB_DW15_REGISTER_1,
+                                     s->cfg.rx1_fifo, idx, offset);
+    }
+
+    /* decode error */
+    return false;
+}
+
+static uint64_t canfd_read(void *opaque, hwaddr addr, unsigned size)
+{
+    XlnxVersalCANFDState *s = XILINX_CANFD(opaque);
+    size_t bank_idx;
+    hwaddr reg_offset;
+    uint64_t ret;
+
+    if (!canfd_decode_addr(s, addr, &bank_idx, &reg_offset)) {
+        qemu_log_mask(LOG_GUEST_ERROR, TYPE_XILINX_CANFD
+                      ": read to unknown register at address 0x%"
+                      HWADDR_PRIx "\n", addr);
+        return 0;
+    }
+
+    switch (reg_offset) {
+    default:
+        ret = s->regs[addr / sizeof(uint32_t)];
+    }
+
+    return ret;
+}
+
+static void canfd_write(void *opaque, hwaddr addr, uint64_t value,
+                        unsigned size)
+{
+    XlnxVersalCANFDState *s = XILINX_CANFD(opaque);
+    size_t bank_idx;
+    hwaddr reg_offset;
+
+    if (!canfd_decode_addr(s, addr, &bank_idx, &reg_offset)) {
+        qemu_log_mask(LOG_GUEST_ERROR, TYPE_XILINX_CANFD
+                      ": write to unknown register at address 0x%"
+                      HWADDR_PRIx "\n", addr);
+        return;
+    }
+
+    if (addr >= A_TXE_FIFO_TB_ID_REGISTER) {
+        /* All registers from TX event regs to the end are read-only */
+        qemu_log_mask(LOG_GUEST_ERROR, TYPE_XILINX_CANFD
+                      ": write to read-only register at 0x%" HWADDR_PRIx "\n",
+                      addr);
+        return;
+    }
+
+    switch (reg_offset) {
+    case A_AFMR_REGISTER:
+    case A_AFIR_REGISTER:
+        filter_reg_write(s, addr, bank_idx, value);
+        break;
+
+    default:
+        s->regs[addr / sizeof(uint32_t)] = value;
+    }
+}
+
 static const MemoryRegionOps canfd_ops = {
+    .read = canfd_read,
+    .write = canfd_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+};
+
+static const MemoryRegionOps canfd_regs_ops = {
     .read = register_read_memory,
     .write = register_write_memory,
     .endianness = DEVICE_LITTLE_ENDIAN,
     .valid = {
         .min_access_size = 4,
@@ -2018,12 +2169,12 @@ static void canfd_realize(DeviceState *dev, Error **errp)
 
 static void canfd_init(Object *obj)
 {
     XlnxVersalCANFDState *s = XILINX_CANFD(obj);
 
-    memory_region_init(&s->iomem, obj, TYPE_XILINX_CANFD,
-                       XLNX_VERSAL_CANFD_R_MAX * 4);
+    memory_region_init_io(&s->iomem, obj, &canfd_ops, s, TYPE_XILINX_CANFD,
+                          XLNX_VERSAL_CANFD_R_MAX * 4);
 }
 
 static const VMStateDescription vmstate_canfd = {
     .name = TYPE_XILINX_CANFD,
     .version_id = 1,
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 7/7] hw/net/can/xlnx-versal-canfd: remove register API usage for banked regs
  2025-09-17 11:44 [PATCH 0/7] Register API leaks fixes Luc Michel
                   ` (5 preceding siblings ...)
  2025-09-17 11:44 ` [PATCH 6/7] hw/net/can/xlnx-versal-canfd: refactor the banked registers logic Luc Michel
@ 2025-09-17 11:44 ` Luc Michel
  2025-09-19  8:48   ` Francisco Iglesias
  2025-09-18  6:21 ` [PATCH 0/7] Register API leaks fixes Edgar E. Iglesias
  2025-09-29 10:19 ` Philippe Mathieu-Daudé
  8 siblings, 1 reply; 23+ messages in thread
From: Luc Michel @ 2025-09-17 11:44 UTC (permalink / raw)
  To: qemu-devel, qemu-arm
  Cc: Luc Michel, Peter Maydell, Francisco Iglesias, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis

Now that we have a simple decoding logic for all the banked registers,
remove the register API usage for them. This restricts the register API
usage to only the base registers (from 0x0 to 0xec).

This also removes all the custom code that was creating register
descriptors for the register API and was leading to memory leaks when
the device was finalized.

Signed-off-by: Luc Michel <luc.michel@amd.com>
---
 include/hw/net/xlnx-versal-canfd.h |   8 -
 hw/net/can/xlnx-versal-canfd.c     | 295 +----------------------------
 2 files changed, 5 insertions(+), 298 deletions(-)

diff --git a/include/hw/net/xlnx-versal-canfd.h b/include/hw/net/xlnx-versal-canfd.h
index ad3104dd13f..396f90d6dc1 100644
--- a/include/hw/net/xlnx-versal-canfd.h
+++ b/include/hw/net/xlnx-versal-canfd.h
@@ -52,18 +52,10 @@ typedef struct XlnxVersalCANFDState {
 
     qemu_irq                irq_canfd_int;
     qemu_irq                irq_addr_err;
 
     RegisterInfo            reg_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_t                regs[XLNX_VERSAL_CANFD_R_MAX];
 
     ptimer_state            *canfd_timer;
 
     CanBusClientState       bus_client;
diff --git a/hw/net/can/xlnx-versal-canfd.c b/hw/net/can/xlnx-versal-canfd.c
index 81615bc52a6..49f1b174b70 100644
--- a/hw/net/can/xlnx-versal-canfd.c
+++ b/hw/net/can/xlnx-versal-canfd.c
@@ -1425,50 +1425,10 @@ static void filter_reg_write(XlnxVersalCANFDState *s, hwaddr addr,
                       HWADDR_PRIx " changed while filter %zu enabled\n",
                       path, addr, bank_idx + 1);
     }
 }
 
-static uint64_t filter_mask(RegisterInfo *reg, uint64_t val64)
-{
-    XlnxVersalCANFDState *s = XILINX_CANFD(reg->opaque);
-    uint32_t reg_idx = (reg->access->addr) / 4;
-    uint32_t val = val64;
-    uint32_t filter_offset = (reg_idx - R_AFMR_REGISTER) / 2;
-
-    if (!(s->regs[R_ACCEPTANCE_FILTER_CONTROL_REGISTER] &
-        (1 << filter_offset))) {
-        s->regs[reg_idx] = val;
-    } else {
-        g_autofree char *path = object_get_canonical_path(OBJECT(s));
-
-        qemu_log_mask(LOG_GUEST_ERROR, "%s: Acceptance filter %d not enabled\n",
-                      path, filter_offset + 1);
-    }
-
-    return s->regs[reg_idx];
-}
-
-static uint64_t filter_id(RegisterInfo *reg, uint64_t val64)
-{
-    XlnxVersalCANFDState *s = XILINX_CANFD(reg->opaque);
-    hwaddr reg_idx = (reg->access->addr) / 4;
-    uint32_t val = val64;
-    uint32_t filter_offset = (reg_idx - R_AFIR_REGISTER) / 2;
-
-    if (!(s->regs[R_ACCEPTANCE_FILTER_CONTROL_REGISTER] &
-        (1 << filter_offset))) {
-        s->regs[reg_idx] = val;
-    } else {
-        g_autofree char *path = object_get_canonical_path(OBJECT(s));
-
-        qemu_log_mask(LOG_GUEST_ERROR, "%s: Acceptance filter %d not enabled\n",
-                      path, filter_offset + 1);
-    }
-
-    return s->regs[reg_idx];
-}
-
 static uint64_t canfd_tx_fifo_status_prew(RegisterInfo *reg, uint64_t val64)
 {
     XlnxVersalCANFDState *s = XILINX_CANFD(reg->opaque);
     uint32_t val = val64;
     uint8_t read_ind = 0;
@@ -1590,129 +1550,10 @@ static uint64_t canfd_write_check_prew(RegisterInfo *reg, uint64_t val64)
         return val;
     }
     return 0;
 }
 
-static const RegisterAccessInfo canfd_tx_regs[] = {
-    {   .name = "TB_ID_REGISTER",  .addr = A_TB_ID_REGISTER,
-    },{ .name = "TB0_DLC_REGISTER",  .addr = A_TB0_DLC_REGISTER,
-    },{ .name = "TB_DW0_REGISTER",  .addr = A_TB_DW0_REGISTER,
-    },{ .name = "TB_DW1_REGISTER",  .addr = A_TB_DW1_REGISTER,
-    },{ .name = "TB_DW2_REGISTER",  .addr = A_TB_DW2_REGISTER,
-    },{ .name = "TB_DW3_REGISTER",  .addr = A_TB_DW3_REGISTER,
-    },{ .name = "TB_DW4_REGISTER",  .addr = A_TB_DW4_REGISTER,
-    },{ .name = "TB_DW5_REGISTER",  .addr = A_TB_DW5_REGISTER,
-    },{ .name = "TB_DW6_REGISTER",  .addr = A_TB_DW6_REGISTER,
-    },{ .name = "TB_DW7_REGISTER",  .addr = A_TB_DW7_REGISTER,
-    },{ .name = "TB_DW8_REGISTER",  .addr = A_TB_DW8_REGISTER,
-    },{ .name = "TB_DW9_REGISTER",  .addr = A_TB_DW9_REGISTER,
-    },{ .name = "TB_DW10_REGISTER",  .addr = A_TB_DW10_REGISTER,
-    },{ .name = "TB_DW11_REGISTER",  .addr = A_TB_DW11_REGISTER,
-    },{ .name = "TB_DW12_REGISTER",  .addr = A_TB_DW12_REGISTER,
-    },{ .name = "TB_DW13_REGISTER",  .addr = A_TB_DW13_REGISTER,
-    },{ .name = "TB_DW14_REGISTER",  .addr = A_TB_DW14_REGISTER,
-    },{ .name = "TB_DW15_REGISTER",  .addr = A_TB_DW15_REGISTER,
-    }
-};
-
-static const RegisterAccessInfo canfd_rx0_regs[] = {
-    {   .name = "RB_ID_REGISTER",  .addr = A_RB_ID_REGISTER,
-        .ro = 0xffffffff,
-    },{ .name = "RB_DLC_REGISTER",  .addr = A_RB_DLC_REGISTER,
-        .ro = 0xfe1fffff,
-    },{ .name = "RB_DW0_REGISTER",  .addr = A_RB_DW0_REGISTER,
-        .ro = 0xffffffff,
-    },{ .name = "RB_DW1_REGISTER",  .addr = A_RB_DW1_REGISTER,
-        .ro = 0xffffffff,
-    },{ .name = "RB_DW2_REGISTER",  .addr = A_RB_DW2_REGISTER,
-        .ro = 0xffffffff,
-    },{ .name = "RB_DW3_REGISTER",  .addr = A_RB_DW3_REGISTER,
-        .ro = 0xffffffff,
-    },{ .name = "RB_DW4_REGISTER",  .addr = A_RB_DW4_REGISTER,
-        .ro = 0xffffffff,
-    },{ .name = "RB_DW5_REGISTER",  .addr = A_RB_DW5_REGISTER,
-        .ro = 0xffffffff,
-    },{ .name = "RB_DW6_REGISTER",  .addr = A_RB_DW6_REGISTER,
-        .ro = 0xffffffff,
-    },{ .name = "RB_DW7_REGISTER",  .addr = A_RB_DW7_REGISTER,
-        .ro = 0xffffffff,
-    },{ .name = "RB_DW8_REGISTER",  .addr = A_RB_DW8_REGISTER,
-        .ro = 0xffffffff,
-    },{ .name = "RB_DW9_REGISTER",  .addr = A_RB_DW9_REGISTER,
-        .ro = 0xffffffff,
-    },{ .name = "RB_DW10_REGISTER",  .addr = A_RB_DW10_REGISTER,
-        .ro = 0xffffffff,
-    },{ .name = "RB_DW11_REGISTER",  .addr = A_RB_DW11_REGISTER,
-        .ro = 0xffffffff,
-    },{ .name = "RB_DW12_REGISTER",  .addr = A_RB_DW12_REGISTER,
-        .ro = 0xffffffff,
-    },{ .name = "RB_DW13_REGISTER",  .addr = A_RB_DW13_REGISTER,
-        .ro = 0xffffffff,
-    },{ .name = "RB_DW14_REGISTER",  .addr = A_RB_DW14_REGISTER,
-        .ro = 0xffffffff,
-    },{ .name = "RB_DW15_REGISTER",  .addr = A_RB_DW15_REGISTER,
-        .ro = 0xffffffff,
-    }
-};
-
-static const RegisterAccessInfo canfd_rx1_regs[] = {
-    {   .name = "RB_ID_REGISTER_1",  .addr = A_RB_ID_REGISTER_1,
-        .ro = 0xffffffff,
-    },{ .name = "RB_DLC_REGISTER_1",  .addr = A_RB_DLC_REGISTER_1,
-        .ro = 0xfe1fffff,
-    },{ .name = "RB0_DW0_REGISTER_1",  .addr = A_RB0_DW0_REGISTER_1,
-        .ro = 0xffffffff,
-    },{ .name = "RB_DW1_REGISTER_1",  .addr = A_RB_DW1_REGISTER_1,
-        .ro = 0xffffffff,
-    },{ .name = "RB_DW2_REGISTER_1",  .addr = A_RB_DW2_REGISTER_1,
-        .ro = 0xffffffff,
-    },{ .name = "RB_DW3_REGISTER_1",  .addr = A_RB_DW3_REGISTER_1,
-        .ro = 0xffffffff,
-    },{ .name = "RB_DW4_REGISTER_1",  .addr = A_RB_DW4_REGISTER_1,
-        .ro = 0xffffffff,
-    },{ .name = "RB_DW5_REGISTER_1",  .addr = A_RB_DW5_REGISTER_1,
-        .ro = 0xffffffff,
-    },{ .name = "RB_DW6_REGISTER_1",  .addr = A_RB_DW6_REGISTER_1,
-        .ro = 0xffffffff,
-    },{ .name = "RB_DW7_REGISTER_1",  .addr = A_RB_DW7_REGISTER_1,
-        .ro = 0xffffffff,
-    },{ .name = "RB_DW8_REGISTER_1",  .addr = A_RB_DW8_REGISTER_1,
-        .ro = 0xffffffff,
-    },{ .name = "RB_DW9_REGISTER_1",  .addr = A_RB_DW9_REGISTER_1,
-        .ro = 0xffffffff,
-    },{ .name = "RB_DW10_REGISTER_1",  .addr = A_RB_DW10_REGISTER_1,
-        .ro = 0xffffffff,
-    },{ .name = "RB_DW11_REGISTER_1",  .addr = A_RB_DW11_REGISTER_1,
-        .ro = 0xffffffff,
-    },{ .name = "RB_DW12_REGISTER_1",  .addr = A_RB_DW12_REGISTER_1,
-        .ro = 0xffffffff,
-    },{ .name = "RB_DW13_REGISTER_1",  .addr = A_RB_DW13_REGISTER_1,
-        .ro = 0xffffffff,
-    },{ .name = "RB_DW14_REGISTER_1",  .addr = A_RB_DW14_REGISTER_1,
-        .ro = 0xffffffff,
-    },{ .name = "RB_DW15_REGISTER_1",  .addr = A_RB_DW15_REGISTER_1,
-        .ro = 0xffffffff,
-    }
-};
-
-/* Acceptance filter registers. */
-static const RegisterAccessInfo canfd_af_regs[] = {
-    {   .name = "AFMR_REGISTER",  .addr = A_AFMR_REGISTER,
-        .pre_write = filter_mask,
-    },{ .name = "AFIR_REGISTER",  .addr = A_AFIR_REGISTER,
-        .pre_write = filter_id,
-    }
-};
-
-static const RegisterAccessInfo canfd_txe_regs[] = {
-    {   .name = "TXE_FIFO_TB_ID_REGISTER",  .addr = A_TXE_FIFO_TB_ID_REGISTER,
-        .ro = 0xffffffff,
-    },{ .name = "TXE_FIFO_TB_DLC_REGISTER",  .addr = A_TXE_FIFO_TB_DLC_REGISTER,
-        .ro = 0xffffffff,
-    }
-};
-
 static const RegisterAccessInfo canfd_regs_info[] = {
     {   .name = "SOFTWARE_RESET_REGISTER",  .addr = A_SOFTWARE_RESET_REGISTER,
         .pre_write = canfd_srr_pre_write,
     },{ .name = "MODE_SELECT_REGISTER",  .addr = A_MODE_SELECT_REGISTER,
         .pre_write = canfd_msr_pre_write,
@@ -2001,146 +1842,20 @@ static int xlnx_canfd_connect_to_bus(XlnxVersalCANFDState *s,
     s->bus_client.info = &canfd_xilinx_bus_client_info;
 
     return can_bus_insert_client(bus, &s->bus_client);
 }
 
-#define NUM_REG_PER_AF      ARRAY_SIZE(canfd_af_regs)
-#define NUM_AF              32
-#define NUM_REG_PER_TXE     ARRAY_SIZE(canfd_txe_regs)
-#define NUM_TXE             32
-
-static int canfd_populate_regarray(XlnxVersalCANFDState *s,
-                                  RegisterInfoArray *r_array, int pos,
-                                  const RegisterAccessInfo *rae,
-                                  int num_rae)
-{
-    int i;
-
-    for (i = 0; i < num_rae; i++) {
-        int index = rae[i].addr / 4;
-        RegisterInfo *r = &s->reg_info[index];
-
-        object_initialize(r, sizeof(*r), TYPE_REGISTER);
-
-        *r = (RegisterInfo) {
-            .data = &s->regs[index],
-            .data_size = sizeof(uint32_t),
-            .access = &rae[i],
-            .opaque = OBJECT(s),
-        };
-
-        r_array->r[i + pos] = r;
-    }
-    return i + pos;
-}
-
-static void canfd_create_rai(RegisterAccessInfo *rai_array,
-                                const RegisterAccessInfo *canfd_regs,
-                                int template_rai_array_sz,
-                                int num_template_to_copy)
-{
-    int i;
-    int reg_num;
-
-    for (reg_num = 0; reg_num < num_template_to_copy; reg_num++) {
-        int pos = reg_num * template_rai_array_sz;
-
-        memcpy(rai_array + pos, canfd_regs,
-               template_rai_array_sz * sizeof(RegisterAccessInfo));
-
-        for (i = 0; i < template_rai_array_sz; i++) {
-            const char *name = canfd_regs[i].name;
-            uint64_t addr = canfd_regs[i].addr;
-            rai_array[i + pos].name = g_strdup_printf("%s%d", name, reg_num);
-            rai_array[i + pos].addr = addr + pos * 4;
-        }
-    }
-}
-
-static RegisterInfoArray *canfd_create_regarray(XlnxVersalCANFDState *s)
-{
-    const char *device_prefix = object_get_typename(OBJECT(s));
-    uint64_t memory_size = XLNX_VERSAL_CANFD_R_MAX * 4;
-    int num_regs;
-    int pos = 0;
-    RegisterInfoArray *r_array;
-
-    num_regs = ARRAY_SIZE(canfd_regs_info) +
-                s->cfg.tx_fifo * NUM_REGS_PER_MSG_SPACE +
-                s->cfg.rx0_fifo * NUM_REGS_PER_MSG_SPACE +
-                NUM_AF * NUM_REG_PER_AF +
-                NUM_TXE * NUM_REG_PER_TXE;
-
-    s->tx_regs = g_new0(RegisterAccessInfo,
-                        s->cfg.tx_fifo * ARRAY_SIZE(canfd_tx_regs));
-
-    canfd_create_rai(s->tx_regs, canfd_tx_regs,
-                     ARRAY_SIZE(canfd_tx_regs), s->cfg.tx_fifo);
-
-    s->rx0_regs = g_new0(RegisterAccessInfo,
-                         s->cfg.rx0_fifo * ARRAY_SIZE(canfd_rx0_regs));
-
-    canfd_create_rai(s->rx0_regs, canfd_rx0_regs,
-                     ARRAY_SIZE(canfd_rx0_regs), s->cfg.rx0_fifo);
-
-    s->af_regs = g_new0(RegisterAccessInfo,
-                        NUM_AF * ARRAY_SIZE(canfd_af_regs));
-
-    canfd_create_rai(s->af_regs, canfd_af_regs,
-                     ARRAY_SIZE(canfd_af_regs), NUM_AF);
-
-    s->txe_regs = g_new0(RegisterAccessInfo,
-                         NUM_TXE * ARRAY_SIZE(canfd_txe_regs));
-
-    canfd_create_rai(s->txe_regs, canfd_txe_regs,
-                     ARRAY_SIZE(canfd_txe_regs), NUM_TXE);
-
-    if (s->cfg.enable_rx_fifo1) {
-        num_regs += s->cfg.rx1_fifo * NUM_REGS_PER_MSG_SPACE;
-
-        s->rx1_regs = g_new0(RegisterAccessInfo,
-                             s->cfg.rx1_fifo * ARRAY_SIZE(canfd_rx1_regs));
-
-        canfd_create_rai(s->rx1_regs, canfd_rx1_regs,
-                         ARRAY_SIZE(canfd_rx1_regs), s->cfg.rx1_fifo);
-    }
-
-    r_array = g_new0(RegisterInfoArray, 1);
-    r_array->r = g_new0(RegisterInfo * , num_regs);
-    r_array->num_elements = num_regs;
-    r_array->prefix = device_prefix;
-
-    pos = canfd_populate_regarray(s, r_array, pos,
-                                  canfd_regs_info,
-                                  ARRAY_SIZE(canfd_regs_info));
-    pos = canfd_populate_regarray(s, r_array, pos,
-                                  s->tx_regs, s->cfg.tx_fifo *
-                                  NUM_REGS_PER_MSG_SPACE);
-    pos = canfd_populate_regarray(s, r_array, pos,
-                                  s->rx0_regs, s->cfg.rx0_fifo *
-                                  NUM_REGS_PER_MSG_SPACE);
-    if (s->cfg.enable_rx_fifo1) {
-        pos = canfd_populate_regarray(s, r_array, pos,
-                                      s->rx1_regs, s->cfg.rx1_fifo *
-                                      NUM_REGS_PER_MSG_SPACE);
-    }
-    pos = canfd_populate_regarray(s, r_array, pos,
-                                  s->af_regs, NUM_AF * NUM_REG_PER_AF);
-    pos = canfd_populate_regarray(s, r_array, pos,
-                                  s->txe_regs, NUM_TXE * NUM_REG_PER_TXE);
-
-    memory_region_init_io(&r_array->mem, OBJECT(s), &canfd_ops, r_array,
-                          device_prefix, memory_size);
-    return r_array;
-}
-
 static void canfd_realize(DeviceState *dev, Error **errp)
 {
     XlnxVersalCANFDState *s = XILINX_CANFD(dev);
     RegisterInfoArray *reg_array;
 
-    reg_array = canfd_create_regarray(s);
+    reg_array = register_init_block32(dev, canfd_regs_info,
+                                      ARRAY_SIZE(canfd_regs_info), s->reg_info,
+                                      s->regs, &canfd_regs_ops, false,
+                                      A_RX_FIFO_WATERMARK_REGISTER
+                                          + sizeof(uint32_t));
     memory_region_add_subregion(&s->iomem, 0x00, &reg_array->mem);
     sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);
     sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq_canfd_int);
 
     if (s->canfdbus) {
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 23+ messages in thread

* Re: [PATCH 0/7] Register API leaks fixes
  2025-09-17 11:44 [PATCH 0/7] Register API leaks fixes Luc Michel
                   ` (6 preceding siblings ...)
  2025-09-17 11:44 ` [PATCH 7/7] hw/net/can/xlnx-versal-canfd: remove register API usage for banked regs Luc Michel
@ 2025-09-18  6:21 ` Edgar E. Iglesias
  2025-09-29 10:19 ` Philippe Mathieu-Daudé
  8 siblings, 0 replies; 23+ messages in thread
From: Edgar E. Iglesias @ 2025-09-18  6:21 UTC (permalink / raw)
  To: Luc Michel
  Cc: qemu-devel, qemu-arm, Peter Maydell, Francisco Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis, Vikram Garhwal

On Wed, Sep 17, 2025 at 01:44:41PM +0200, Luc Michel wrote:
> Based-on: 20250912100059.103997-1-luc.michel@amd.com ([PATCH v5 00/47] AMD Versal Gen 2 support)
> 
> Hello,
> 
> This series addresses the memory leaks caused by the register API. The
> first patches fix the API itself while the last ones take care of the
> CANFD model.
> 
> The leaks in the register API were caused by:
>    - the REGISTER device being initialized without being realized nor
>      finalized. Those devices were not parented to anything and were
>      not using the qdev API. So in the end I chose to drop the REGISTER
>      object completely (patch 1).
>    - Register API users not calling `register_finalize_block' on the
>      RegisterInfoArray returned by `register_init_block'. Instead of
>      fixing all the users, I chose to simplify the API by removing the
>      need for this call. I turned the RegisterInfoArray struct into a QOM
>      object and parented it to the device in `register_init_block'. This
>      way it has its own finalize function that gets called when the
>      parent device is finalized. This implies a small API change: the
>      `register_finalize_block' function is removed (patch 2, 3, 4).
> 
> The CANFD model needed special care. It was rolling out its own version
> of `register_init_block', including the discrepancies leading to the
> memory leaks. This is because the register map of this device is
> composed of main registers (from 0x0 to 0xec), followed by several banks
> of multiple registers (Tx banks, filter banks, Txe banks, ...). The
> register API is not suited for this kind of layout and the resulting
> code to handle that is convoluted. However a simple decoding logic is
> easily written for this, those registers having basically no side effect
> upon access.
> 
> Patch 6 introduces this decoding logic for the banked registers, patch 7
> removes the register API bits for those, keeping the one for the base
> registers.
> 
> Note: this series is based on my Versal 2 series. It modifies the CRL
> device during the register API refactoring. It can easily be rebased on
> master if needed.
> 
> Thanks
> 
> Luc


Hi Luc,

Entire series looks good to me!
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@amd.com>



> 
> 
> Luc Michel (7):
>   hw/core/register: remove the REGISTER device type
>   hw/core/register: add the REGISTER_ARRAY type
>   hw/core/register: remove the calls to `register_finalize_block'
>   hw/core/register: remove the `register_finalize_block' function
>   hw/net/can/xlnx-versal-canfd: remove unused include directives
>   hw/net/can/xlnx-versal-canfd: refactor the banked registers logic
>   hw/net/can/xlnx-versal-canfd: remove register API usage for banked
>     regs
> 
>  include/hw/misc/xlnx-versal-crl.h      |   1 -
>  include/hw/misc/xlnx-versal-xramc.h    |   1 -
>  include/hw/misc/xlnx-zynqmp-apu-ctrl.h |   1 -
>  include/hw/misc/xlnx-zynqmp-crf.h      |   1 -
>  include/hw/net/xlnx-versal-canfd.h     |   8 -
>  include/hw/nvram/xlnx-bbram.h          |   1 -
>  include/hw/register.h                  |  25 +-
>  hw/core/register.c                     |  36 +-
>  hw/misc/xlnx-versal-crl.c              |  38 +--
>  hw/misc/xlnx-versal-trng.c             |   1 -
>  hw/misc/xlnx-versal-xramc.c            |  12 +-
>  hw/misc/xlnx-zynqmp-apu-ctrl.c         |  12 +-
>  hw/misc/xlnx-zynqmp-crf.c              |  12 +-
>  hw/net/can/xlnx-versal-canfd.c         | 434 +++++++++----------------
>  hw/nvram/xlnx-bbram.c                  |  13 +-
>  hw/nvram/xlnx-versal-efuse-ctrl.c      |   1 -
>  hw/nvram/xlnx-zynqmp-efuse.c           |   8 -
>  17 files changed, 196 insertions(+), 409 deletions(-)
> 
> -- 
> 2.50.1
> 


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 5/7] hw/net/can/xlnx-versal-canfd: remove unused include directives
  2025-09-17 11:44 ` [PATCH 5/7] hw/net/can/xlnx-versal-canfd: remove unused include directives Luc Michel
@ 2025-09-19  8:47   ` Francisco Iglesias
  2025-09-28 23:36   ` Alistair Francis
  1 sibling, 0 replies; 23+ messages in thread
From: Francisco Iglesias @ 2025-09-19  8:47 UTC (permalink / raw)
  To: Luc Michel
  Cc: qemu-devel, qemu-arm, Peter Maydell, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis

On Wed, Sep 17, 2025 at 01:44:46PM +0200, Luc Michel wrote:
> Drop unecessary include directives in xlnx-versal-canfd.c.
> 
> Signed-off-by: Luc Michel <luc.michel@amd.com>

    Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>

> ---
>  hw/net/can/xlnx-versal-canfd.c | 4 ----
>  1 file changed, 4 deletions(-)
> 
> diff --git a/hw/net/can/xlnx-versal-canfd.c b/hw/net/can/xlnx-versal-canfd.c
> index 3eb111949f8..343348660b5 100644
> --- a/hw/net/can/xlnx-versal-canfd.c
> +++ b/hw/net/can/xlnx-versal-canfd.c
> @@ -33,16 +33,12 @@
>  #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"
>  
>  REG32(SOFTWARE_RESET_REGISTER, 0x0)
> -- 
> 2.50.1
> 


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 6/7] hw/net/can/xlnx-versal-canfd: refactor the banked registers logic
  2025-09-17 11:44 ` [PATCH 6/7] hw/net/can/xlnx-versal-canfd: refactor the banked registers logic Luc Michel
@ 2025-09-19  8:48   ` Francisco Iglesias
  0 siblings, 0 replies; 23+ messages in thread
From: Francisco Iglesias @ 2025-09-19  8:48 UTC (permalink / raw)
  To: Luc Michel
  Cc: qemu-devel, qemu-arm, Peter Maydell, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis

On Wed, Sep 17, 2025 at 01:44:47PM +0200, Luc Michel wrote:
> The CANFD device has several groups of registers:
>   - the main control registers from 0x0 to 0xec
>   - several banks of multiple registers. The number of banks is either
>     hardcoded, or configurable using QOM properties:
>       - Tx registers
>       - Filter registers
>       - Tx events registers
>       - Rx0 registers
>       - Rx1 registers
> 
> As of now, all the registers are handled using the register API. The
> banked register logic results in a convoluted code to correctly allocate
> the register descriptors for the register API. This code bypasses the
> standard register API creation function (register_init_block). The
> resulting code leaks memory when the device is finalized.
> 
> This commit introduces decoding logic for the banked registers. Those
> registers are quite simple in practice. Accessing them triggers no
> side-effect (only the filter registers need a check to catch guest
> invalid behaviour). Starting from the Tx events registers, they are all
> read-only.
> 
> The main device memory region is changed to an I/O one, calling the
> new decoding logic when accessed. The register API memory region still
> overlaps all of it so for now the introduced code has no effect. The
> next commit will remove the register API usage for banked registers.
> 
> Signed-off-by: Luc Michel <luc.michel@amd.com>

Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>


> ---
>  hw/net/can/xlnx-versal-canfd.c | 155 ++++++++++++++++++++++++++++++++-
>  1 file changed, 153 insertions(+), 2 deletions(-)
> 
> diff --git a/hw/net/can/xlnx-versal-canfd.c b/hw/net/can/xlnx-versal-canfd.c
> index 343348660b5..81615bc52a6 100644
> --- a/hw/net/can/xlnx-versal-canfd.c
> +++ b/hw/net/can/xlnx-versal-canfd.c
> @@ -1408,10 +1408,27 @@ static uint64_t canfd_srr_pre_write(RegisterInfo *reg, uint64_t val64)
>      }
>  
>      return s->regs[R_SOFTWARE_RESET_REGISTER];
>  }
>  
> +static void filter_reg_write(XlnxVersalCANFDState *s, hwaddr addr,
> +                             size_t bank_idx, uint32_t val)
> +{
> +    size_t reg_idx = addr / sizeof(uint32_t);
> +
> +    if (!(s->regs[R_ACCEPTANCE_FILTER_CONTROL_REGISTER] &
> +        (1 << bank_idx))) {
> +        s->regs[reg_idx] = val;
> +    } else {
> +        g_autofree char *path = object_get_canonical_path(OBJECT(s));
> +
> +        qemu_log_mask(LOG_GUEST_ERROR, "%s: Acceptance filter register 0x%"
> +                      HWADDR_PRIx " changed while filter %zu enabled\n",
> +                      path, addr, bank_idx + 1);
> +    }
> +}
> +
>  static uint64_t filter_mask(RegisterInfo *reg, uint64_t val64)
>  {
>      XlnxVersalCANFDState *s = XILINX_CANFD(reg->opaque);
>      uint32_t reg_idx = (reg->access->addr) / 4;
>      uint32_t val = val64;
> @@ -1761,11 +1778,145 @@ static const RegisterAccessInfo canfd_regs_info[] = {
>  static void xlnx_versal_canfd_ptimer_cb(void *opaque)
>  {
>      /* No action required on the timer rollover. */
>  }
>  
> +static bool canfd_decode_reg_bank(XlnxVersalCANFDState *s, hwaddr addr,
> +                                  hwaddr first_reg, hwaddr last_reg,
> +                                  size_t num_banks, size_t *idx, size_t *offset)
> +{
> +    hwaddr base = addr - first_reg;
> +    hwaddr span = last_reg - first_reg + sizeof(uint32_t);
> +
> +    *idx = base / span;
> +
> +    if (*idx >= num_banks) {
> +        return false;
> +    }
> +
> +    *offset = base % span;
> +    *offset += first_reg;
> +
> +    return true;
> +}
> +
> +/*
> + * Decode the given addr into a (idx, offset) pair:
> + *   - idx is the bank index of the register at addr,
> + *   - offset is the register offset relative to bank 0
> + *
> + * @return true is the decoding succeded, false otherwise
> + */
> +static bool canfd_decode_addr(XlnxVersalCANFDState *s, hwaddr addr,
> +                              size_t *idx, size_t *offset)
> +{
> +    if (addr <= A_RX_FIFO_WATERMARK_REGISTER) {
> +        /* from 0x0 to 0xec. Handled by the register API */
> +        g_assert_not_reached();
> +    } else if (addr < A_TB_ID_REGISTER) {
> +        /* no register in this gap */
> +        return false;
> +    } else if (addr < A_AFMR_REGISTER) {
> +        /* TX registers */
> +        return canfd_decode_reg_bank(s, addr,
> +                                     A_TB_ID_REGISTER, A_TB_DW15_REGISTER,
> +                                     s->cfg.tx_fifo, idx, offset);
> +    } else if (addr < A_TXE_FIFO_TB_ID_REGISTER) {
> +        /* Filter registers */
> +        return canfd_decode_reg_bank(s, addr,
> +                                     A_AFMR_REGISTER, A_AFIR_REGISTER,
> +                                     32, idx, offset);
> +    } else if (addr < A_RB_ID_REGISTER) {
> +        /* TX event registers */
> +        return canfd_decode_reg_bank(s, addr,
> +                                     A_TXE_FIFO_TB_ID_REGISTER,
> +                                     A_TXE_FIFO_TB_DLC_REGISTER,
> +                                     32, idx, offset);
> +    } else if (addr < A_RB_ID_REGISTER_1) {
> +        /* RX0 registers */
> +        return canfd_decode_reg_bank(s, addr,
> +                                     A_RB_ID_REGISTER,
> +                                     A_RB_DW15_REGISTER,
> +                                     s->cfg.rx0_fifo, idx, offset);
> +    } else if (addr <= A_RB_DW15_REGISTER_1) {
> +        /* RX1 registers */
> +        return canfd_decode_reg_bank(s, addr,
> +                                     A_RB_ID_REGISTER_1,
> +                                     A_RB_DW15_REGISTER_1,
> +                                     s->cfg.rx1_fifo, idx, offset);
> +    }
> +
> +    /* decode error */
> +    return false;
> +}
> +
> +static uint64_t canfd_read(void *opaque, hwaddr addr, unsigned size)
> +{
> +    XlnxVersalCANFDState *s = XILINX_CANFD(opaque);
> +    size_t bank_idx;
> +    hwaddr reg_offset;
> +    uint64_t ret;
> +
> +    if (!canfd_decode_addr(s, addr, &bank_idx, &reg_offset)) {
> +        qemu_log_mask(LOG_GUEST_ERROR, TYPE_XILINX_CANFD
> +                      ": read to unknown register at address 0x%"
> +                      HWADDR_PRIx "\n", addr);
> +        return 0;
> +    }
> +
> +    switch (reg_offset) {
> +    default:
> +        ret = s->regs[addr / sizeof(uint32_t)];
> +    }
> +
> +    return ret;
> +}
> +
> +static void canfd_write(void *opaque, hwaddr addr, uint64_t value,
> +                        unsigned size)
> +{
> +    XlnxVersalCANFDState *s = XILINX_CANFD(opaque);
> +    size_t bank_idx;
> +    hwaddr reg_offset;
> +
> +    if (!canfd_decode_addr(s, addr, &bank_idx, &reg_offset)) {
> +        qemu_log_mask(LOG_GUEST_ERROR, TYPE_XILINX_CANFD
> +                      ": write to unknown register at address 0x%"
> +                      HWADDR_PRIx "\n", addr);
> +        return;
> +    }
> +
> +    if (addr >= A_TXE_FIFO_TB_ID_REGISTER) {
> +        /* All registers from TX event regs to the end are read-only */
> +        qemu_log_mask(LOG_GUEST_ERROR, TYPE_XILINX_CANFD
> +                      ": write to read-only register at 0x%" HWADDR_PRIx "\n",
> +                      addr);
> +        return;
> +    }
> +
> +    switch (reg_offset) {
> +    case A_AFMR_REGISTER:
> +    case A_AFIR_REGISTER:
> +        filter_reg_write(s, addr, bank_idx, value);
> +        break;
> +
> +    default:
> +        s->regs[addr / sizeof(uint32_t)] = value;
> +    }
> +}
> +
>  static const MemoryRegionOps canfd_ops = {
> +    .read = canfd_read,
> +    .write = canfd_write,
> +    .endianness = DEVICE_LITTLE_ENDIAN,
> +    .valid = {
> +        .min_access_size = 4,
> +        .max_access_size = 4,
> +    },
> +};
> +
> +static const MemoryRegionOps canfd_regs_ops = {
>      .read = register_read_memory,
>      .write = register_write_memory,
>      .endianness = DEVICE_LITTLE_ENDIAN,
>      .valid = {
>          .min_access_size = 4,
> @@ -2018,12 +2169,12 @@ static void canfd_realize(DeviceState *dev, Error **errp)
>  
>  static void canfd_init(Object *obj)
>  {
>      XlnxVersalCANFDState *s = XILINX_CANFD(obj);
>  
> -    memory_region_init(&s->iomem, obj, TYPE_XILINX_CANFD,
> -                       XLNX_VERSAL_CANFD_R_MAX * 4);
> +    memory_region_init_io(&s->iomem, obj, &canfd_ops, s, TYPE_XILINX_CANFD,
> +                          XLNX_VERSAL_CANFD_R_MAX * 4);
>  }
>  
>  static const VMStateDescription vmstate_canfd = {
>      .name = TYPE_XILINX_CANFD,
>      .version_id = 1,
> -- 
> 2.50.1
> 


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 7/7] hw/net/can/xlnx-versal-canfd: remove register API usage for banked regs
  2025-09-17 11:44 ` [PATCH 7/7] hw/net/can/xlnx-versal-canfd: remove register API usage for banked regs Luc Michel
@ 2025-09-19  8:48   ` Francisco Iglesias
  0 siblings, 0 replies; 23+ messages in thread
From: Francisco Iglesias @ 2025-09-19  8:48 UTC (permalink / raw)
  To: Luc Michel
  Cc: qemu-devel, qemu-arm, Peter Maydell, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis

On Wed, Sep 17, 2025 at 01:44:48PM +0200, Luc Michel wrote:
> Now that we have a simple decoding logic for all the banked registers,
> remove the register API usage for them. This restricts the register API
> usage to only the base registers (from 0x0 to 0xec).
> 
> This also removes all the custom code that was creating register
> descriptors for the register API and was leading to memory leaks when
> the device was finalized.
> 
> Signed-off-by: Luc Michel <luc.michel@amd.com>

Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>

> ---
>  include/hw/net/xlnx-versal-canfd.h |   8 -
>  hw/net/can/xlnx-versal-canfd.c     | 295 +----------------------------
>  2 files changed, 5 insertions(+), 298 deletions(-)
> 
> diff --git a/include/hw/net/xlnx-versal-canfd.h b/include/hw/net/xlnx-versal-canfd.h
> index ad3104dd13f..396f90d6dc1 100644
> --- a/include/hw/net/xlnx-versal-canfd.h
> +++ b/include/hw/net/xlnx-versal-canfd.h
> @@ -52,18 +52,10 @@ typedef struct XlnxVersalCANFDState {
>  
>      qemu_irq                irq_canfd_int;
>      qemu_irq                irq_addr_err;
>  
>      RegisterInfo            reg_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_t                regs[XLNX_VERSAL_CANFD_R_MAX];
>  
>      ptimer_state            *canfd_timer;
>  
>      CanBusClientState       bus_client;
> diff --git a/hw/net/can/xlnx-versal-canfd.c b/hw/net/can/xlnx-versal-canfd.c
> index 81615bc52a6..49f1b174b70 100644
> --- a/hw/net/can/xlnx-versal-canfd.c
> +++ b/hw/net/can/xlnx-versal-canfd.c
> @@ -1425,50 +1425,10 @@ static void filter_reg_write(XlnxVersalCANFDState *s, hwaddr addr,
>                        HWADDR_PRIx " changed while filter %zu enabled\n",
>                        path, addr, bank_idx + 1);
>      }
>  }
>  
> -static uint64_t filter_mask(RegisterInfo *reg, uint64_t val64)
> -{
> -    XlnxVersalCANFDState *s = XILINX_CANFD(reg->opaque);
> -    uint32_t reg_idx = (reg->access->addr) / 4;
> -    uint32_t val = val64;
> -    uint32_t filter_offset = (reg_idx - R_AFMR_REGISTER) / 2;
> -
> -    if (!(s->regs[R_ACCEPTANCE_FILTER_CONTROL_REGISTER] &
> -        (1 << filter_offset))) {
> -        s->regs[reg_idx] = val;
> -    } else {
> -        g_autofree char *path = object_get_canonical_path(OBJECT(s));
> -
> -        qemu_log_mask(LOG_GUEST_ERROR, "%s: Acceptance filter %d not enabled\n",
> -                      path, filter_offset + 1);
> -    }
> -
> -    return s->regs[reg_idx];
> -}
> -
> -static uint64_t filter_id(RegisterInfo *reg, uint64_t val64)
> -{
> -    XlnxVersalCANFDState *s = XILINX_CANFD(reg->opaque);
> -    hwaddr reg_idx = (reg->access->addr) / 4;
> -    uint32_t val = val64;
> -    uint32_t filter_offset = (reg_idx - R_AFIR_REGISTER) / 2;
> -
> -    if (!(s->regs[R_ACCEPTANCE_FILTER_CONTROL_REGISTER] &
> -        (1 << filter_offset))) {
> -        s->regs[reg_idx] = val;
> -    } else {
> -        g_autofree char *path = object_get_canonical_path(OBJECT(s));
> -
> -        qemu_log_mask(LOG_GUEST_ERROR, "%s: Acceptance filter %d not enabled\n",
> -                      path, filter_offset + 1);
> -    }
> -
> -    return s->regs[reg_idx];
> -}
> -
>  static uint64_t canfd_tx_fifo_status_prew(RegisterInfo *reg, uint64_t val64)
>  {
>      XlnxVersalCANFDState *s = XILINX_CANFD(reg->opaque);
>      uint32_t val = val64;
>      uint8_t read_ind = 0;
> @@ -1590,129 +1550,10 @@ static uint64_t canfd_write_check_prew(RegisterInfo *reg, uint64_t val64)
>          return val;
>      }
>      return 0;
>  }
>  
> -static const RegisterAccessInfo canfd_tx_regs[] = {
> -    {   .name = "TB_ID_REGISTER",  .addr = A_TB_ID_REGISTER,
> -    },{ .name = "TB0_DLC_REGISTER",  .addr = A_TB0_DLC_REGISTER,
> -    },{ .name = "TB_DW0_REGISTER",  .addr = A_TB_DW0_REGISTER,
> -    },{ .name = "TB_DW1_REGISTER",  .addr = A_TB_DW1_REGISTER,
> -    },{ .name = "TB_DW2_REGISTER",  .addr = A_TB_DW2_REGISTER,
> -    },{ .name = "TB_DW3_REGISTER",  .addr = A_TB_DW3_REGISTER,
> -    },{ .name = "TB_DW4_REGISTER",  .addr = A_TB_DW4_REGISTER,
> -    },{ .name = "TB_DW5_REGISTER",  .addr = A_TB_DW5_REGISTER,
> -    },{ .name = "TB_DW6_REGISTER",  .addr = A_TB_DW6_REGISTER,
> -    },{ .name = "TB_DW7_REGISTER",  .addr = A_TB_DW7_REGISTER,
> -    },{ .name = "TB_DW8_REGISTER",  .addr = A_TB_DW8_REGISTER,
> -    },{ .name = "TB_DW9_REGISTER",  .addr = A_TB_DW9_REGISTER,
> -    },{ .name = "TB_DW10_REGISTER",  .addr = A_TB_DW10_REGISTER,
> -    },{ .name = "TB_DW11_REGISTER",  .addr = A_TB_DW11_REGISTER,
> -    },{ .name = "TB_DW12_REGISTER",  .addr = A_TB_DW12_REGISTER,
> -    },{ .name = "TB_DW13_REGISTER",  .addr = A_TB_DW13_REGISTER,
> -    },{ .name = "TB_DW14_REGISTER",  .addr = A_TB_DW14_REGISTER,
> -    },{ .name = "TB_DW15_REGISTER",  .addr = A_TB_DW15_REGISTER,
> -    }
> -};
> -
> -static const RegisterAccessInfo canfd_rx0_regs[] = {
> -    {   .name = "RB_ID_REGISTER",  .addr = A_RB_ID_REGISTER,
> -        .ro = 0xffffffff,
> -    },{ .name = "RB_DLC_REGISTER",  .addr = A_RB_DLC_REGISTER,
> -        .ro = 0xfe1fffff,
> -    },{ .name = "RB_DW0_REGISTER",  .addr = A_RB_DW0_REGISTER,
> -        .ro = 0xffffffff,
> -    },{ .name = "RB_DW1_REGISTER",  .addr = A_RB_DW1_REGISTER,
> -        .ro = 0xffffffff,
> -    },{ .name = "RB_DW2_REGISTER",  .addr = A_RB_DW2_REGISTER,
> -        .ro = 0xffffffff,
> -    },{ .name = "RB_DW3_REGISTER",  .addr = A_RB_DW3_REGISTER,
> -        .ro = 0xffffffff,
> -    },{ .name = "RB_DW4_REGISTER",  .addr = A_RB_DW4_REGISTER,
> -        .ro = 0xffffffff,
> -    },{ .name = "RB_DW5_REGISTER",  .addr = A_RB_DW5_REGISTER,
> -        .ro = 0xffffffff,
> -    },{ .name = "RB_DW6_REGISTER",  .addr = A_RB_DW6_REGISTER,
> -        .ro = 0xffffffff,
> -    },{ .name = "RB_DW7_REGISTER",  .addr = A_RB_DW7_REGISTER,
> -        .ro = 0xffffffff,
> -    },{ .name = "RB_DW8_REGISTER",  .addr = A_RB_DW8_REGISTER,
> -        .ro = 0xffffffff,
> -    },{ .name = "RB_DW9_REGISTER",  .addr = A_RB_DW9_REGISTER,
> -        .ro = 0xffffffff,
> -    },{ .name = "RB_DW10_REGISTER",  .addr = A_RB_DW10_REGISTER,
> -        .ro = 0xffffffff,
> -    },{ .name = "RB_DW11_REGISTER",  .addr = A_RB_DW11_REGISTER,
> -        .ro = 0xffffffff,
> -    },{ .name = "RB_DW12_REGISTER",  .addr = A_RB_DW12_REGISTER,
> -        .ro = 0xffffffff,
> -    },{ .name = "RB_DW13_REGISTER",  .addr = A_RB_DW13_REGISTER,
> -        .ro = 0xffffffff,
> -    },{ .name = "RB_DW14_REGISTER",  .addr = A_RB_DW14_REGISTER,
> -        .ro = 0xffffffff,
> -    },{ .name = "RB_DW15_REGISTER",  .addr = A_RB_DW15_REGISTER,
> -        .ro = 0xffffffff,
> -    }
> -};
> -
> -static const RegisterAccessInfo canfd_rx1_regs[] = {
> -    {   .name = "RB_ID_REGISTER_1",  .addr = A_RB_ID_REGISTER_1,
> -        .ro = 0xffffffff,
> -    },{ .name = "RB_DLC_REGISTER_1",  .addr = A_RB_DLC_REGISTER_1,
> -        .ro = 0xfe1fffff,
> -    },{ .name = "RB0_DW0_REGISTER_1",  .addr = A_RB0_DW0_REGISTER_1,
> -        .ro = 0xffffffff,
> -    },{ .name = "RB_DW1_REGISTER_1",  .addr = A_RB_DW1_REGISTER_1,
> -        .ro = 0xffffffff,
> -    },{ .name = "RB_DW2_REGISTER_1",  .addr = A_RB_DW2_REGISTER_1,
> -        .ro = 0xffffffff,
> -    },{ .name = "RB_DW3_REGISTER_1",  .addr = A_RB_DW3_REGISTER_1,
> -        .ro = 0xffffffff,
> -    },{ .name = "RB_DW4_REGISTER_1",  .addr = A_RB_DW4_REGISTER_1,
> -        .ro = 0xffffffff,
> -    },{ .name = "RB_DW5_REGISTER_1",  .addr = A_RB_DW5_REGISTER_1,
> -        .ro = 0xffffffff,
> -    },{ .name = "RB_DW6_REGISTER_1",  .addr = A_RB_DW6_REGISTER_1,
> -        .ro = 0xffffffff,
> -    },{ .name = "RB_DW7_REGISTER_1",  .addr = A_RB_DW7_REGISTER_1,
> -        .ro = 0xffffffff,
> -    },{ .name = "RB_DW8_REGISTER_1",  .addr = A_RB_DW8_REGISTER_1,
> -        .ro = 0xffffffff,
> -    },{ .name = "RB_DW9_REGISTER_1",  .addr = A_RB_DW9_REGISTER_1,
> -        .ro = 0xffffffff,
> -    },{ .name = "RB_DW10_REGISTER_1",  .addr = A_RB_DW10_REGISTER_1,
> -        .ro = 0xffffffff,
> -    },{ .name = "RB_DW11_REGISTER_1",  .addr = A_RB_DW11_REGISTER_1,
> -        .ro = 0xffffffff,
> -    },{ .name = "RB_DW12_REGISTER_1",  .addr = A_RB_DW12_REGISTER_1,
> -        .ro = 0xffffffff,
> -    },{ .name = "RB_DW13_REGISTER_1",  .addr = A_RB_DW13_REGISTER_1,
> -        .ro = 0xffffffff,
> -    },{ .name = "RB_DW14_REGISTER_1",  .addr = A_RB_DW14_REGISTER_1,
> -        .ro = 0xffffffff,
> -    },{ .name = "RB_DW15_REGISTER_1",  .addr = A_RB_DW15_REGISTER_1,
> -        .ro = 0xffffffff,
> -    }
> -};
> -
> -/* Acceptance filter registers. */
> -static const RegisterAccessInfo canfd_af_regs[] = {
> -    {   .name = "AFMR_REGISTER",  .addr = A_AFMR_REGISTER,
> -        .pre_write = filter_mask,
> -    },{ .name = "AFIR_REGISTER",  .addr = A_AFIR_REGISTER,
> -        .pre_write = filter_id,
> -    }
> -};
> -
> -static const RegisterAccessInfo canfd_txe_regs[] = {
> -    {   .name = "TXE_FIFO_TB_ID_REGISTER",  .addr = A_TXE_FIFO_TB_ID_REGISTER,
> -        .ro = 0xffffffff,
> -    },{ .name = "TXE_FIFO_TB_DLC_REGISTER",  .addr = A_TXE_FIFO_TB_DLC_REGISTER,
> -        .ro = 0xffffffff,
> -    }
> -};
> -
>  static const RegisterAccessInfo canfd_regs_info[] = {
>      {   .name = "SOFTWARE_RESET_REGISTER",  .addr = A_SOFTWARE_RESET_REGISTER,
>          .pre_write = canfd_srr_pre_write,
>      },{ .name = "MODE_SELECT_REGISTER",  .addr = A_MODE_SELECT_REGISTER,
>          .pre_write = canfd_msr_pre_write,
> @@ -2001,146 +1842,20 @@ static int xlnx_canfd_connect_to_bus(XlnxVersalCANFDState *s,
>      s->bus_client.info = &canfd_xilinx_bus_client_info;
>  
>      return can_bus_insert_client(bus, &s->bus_client);
>  }
>  
> -#define NUM_REG_PER_AF      ARRAY_SIZE(canfd_af_regs)
> -#define NUM_AF              32
> -#define NUM_REG_PER_TXE     ARRAY_SIZE(canfd_txe_regs)
> -#define NUM_TXE             32
> -
> -static int canfd_populate_regarray(XlnxVersalCANFDState *s,
> -                                  RegisterInfoArray *r_array, int pos,
> -                                  const RegisterAccessInfo *rae,
> -                                  int num_rae)
> -{
> -    int i;
> -
> -    for (i = 0; i < num_rae; i++) {
> -        int index = rae[i].addr / 4;
> -        RegisterInfo *r = &s->reg_info[index];
> -
> -        object_initialize(r, sizeof(*r), TYPE_REGISTER);
> -
> -        *r = (RegisterInfo) {
> -            .data = &s->regs[index],
> -            .data_size = sizeof(uint32_t),
> -            .access = &rae[i],
> -            .opaque = OBJECT(s),
> -        };
> -
> -        r_array->r[i + pos] = r;
> -    }
> -    return i + pos;
> -}
> -
> -static void canfd_create_rai(RegisterAccessInfo *rai_array,
> -                                const RegisterAccessInfo *canfd_regs,
> -                                int template_rai_array_sz,
> -                                int num_template_to_copy)
> -{
> -    int i;
> -    int reg_num;
> -
> -    for (reg_num = 0; reg_num < num_template_to_copy; reg_num++) {
> -        int pos = reg_num * template_rai_array_sz;
> -
> -        memcpy(rai_array + pos, canfd_regs,
> -               template_rai_array_sz * sizeof(RegisterAccessInfo));
> -
> -        for (i = 0; i < template_rai_array_sz; i++) {
> -            const char *name = canfd_regs[i].name;
> -            uint64_t addr = canfd_regs[i].addr;
> -            rai_array[i + pos].name = g_strdup_printf("%s%d", name, reg_num);
> -            rai_array[i + pos].addr = addr + pos * 4;
> -        }
> -    }
> -}
> -
> -static RegisterInfoArray *canfd_create_regarray(XlnxVersalCANFDState *s)
> -{
> -    const char *device_prefix = object_get_typename(OBJECT(s));
> -    uint64_t memory_size = XLNX_VERSAL_CANFD_R_MAX * 4;
> -    int num_regs;
> -    int pos = 0;
> -    RegisterInfoArray *r_array;
> -
> -    num_regs = ARRAY_SIZE(canfd_regs_info) +
> -                s->cfg.tx_fifo * NUM_REGS_PER_MSG_SPACE +
> -                s->cfg.rx0_fifo * NUM_REGS_PER_MSG_SPACE +
> -                NUM_AF * NUM_REG_PER_AF +
> -                NUM_TXE * NUM_REG_PER_TXE;
> -
> -    s->tx_regs = g_new0(RegisterAccessInfo,
> -                        s->cfg.tx_fifo * ARRAY_SIZE(canfd_tx_regs));
> -
> -    canfd_create_rai(s->tx_regs, canfd_tx_regs,
> -                     ARRAY_SIZE(canfd_tx_regs), s->cfg.tx_fifo);
> -
> -    s->rx0_regs = g_new0(RegisterAccessInfo,
> -                         s->cfg.rx0_fifo * ARRAY_SIZE(canfd_rx0_regs));
> -
> -    canfd_create_rai(s->rx0_regs, canfd_rx0_regs,
> -                     ARRAY_SIZE(canfd_rx0_regs), s->cfg.rx0_fifo);
> -
> -    s->af_regs = g_new0(RegisterAccessInfo,
> -                        NUM_AF * ARRAY_SIZE(canfd_af_regs));
> -
> -    canfd_create_rai(s->af_regs, canfd_af_regs,
> -                     ARRAY_SIZE(canfd_af_regs), NUM_AF);
> -
> -    s->txe_regs = g_new0(RegisterAccessInfo,
> -                         NUM_TXE * ARRAY_SIZE(canfd_txe_regs));
> -
> -    canfd_create_rai(s->txe_regs, canfd_txe_regs,
> -                     ARRAY_SIZE(canfd_txe_regs), NUM_TXE);
> -
> -    if (s->cfg.enable_rx_fifo1) {
> -        num_regs += s->cfg.rx1_fifo * NUM_REGS_PER_MSG_SPACE;
> -
> -        s->rx1_regs = g_new0(RegisterAccessInfo,
> -                             s->cfg.rx1_fifo * ARRAY_SIZE(canfd_rx1_regs));
> -
> -        canfd_create_rai(s->rx1_regs, canfd_rx1_regs,
> -                         ARRAY_SIZE(canfd_rx1_regs), s->cfg.rx1_fifo);
> -    }
> -
> -    r_array = g_new0(RegisterInfoArray, 1);
> -    r_array->r = g_new0(RegisterInfo * , num_regs);
> -    r_array->num_elements = num_regs;
> -    r_array->prefix = device_prefix;
> -
> -    pos = canfd_populate_regarray(s, r_array, pos,
> -                                  canfd_regs_info,
> -                                  ARRAY_SIZE(canfd_regs_info));
> -    pos = canfd_populate_regarray(s, r_array, pos,
> -                                  s->tx_regs, s->cfg.tx_fifo *
> -                                  NUM_REGS_PER_MSG_SPACE);
> -    pos = canfd_populate_regarray(s, r_array, pos,
> -                                  s->rx0_regs, s->cfg.rx0_fifo *
> -                                  NUM_REGS_PER_MSG_SPACE);
> -    if (s->cfg.enable_rx_fifo1) {
> -        pos = canfd_populate_regarray(s, r_array, pos,
> -                                      s->rx1_regs, s->cfg.rx1_fifo *
> -                                      NUM_REGS_PER_MSG_SPACE);
> -    }
> -    pos = canfd_populate_regarray(s, r_array, pos,
> -                                  s->af_regs, NUM_AF * NUM_REG_PER_AF);
> -    pos = canfd_populate_regarray(s, r_array, pos,
> -                                  s->txe_regs, NUM_TXE * NUM_REG_PER_TXE);
> -
> -    memory_region_init_io(&r_array->mem, OBJECT(s), &canfd_ops, r_array,
> -                          device_prefix, memory_size);
> -    return r_array;
> -}
> -
>  static void canfd_realize(DeviceState *dev, Error **errp)
>  {
>      XlnxVersalCANFDState *s = XILINX_CANFD(dev);
>      RegisterInfoArray *reg_array;
>  
> -    reg_array = canfd_create_regarray(s);
> +    reg_array = register_init_block32(dev, canfd_regs_info,
> +                                      ARRAY_SIZE(canfd_regs_info), s->reg_info,
> +                                      s->regs, &canfd_regs_ops, false,
> +                                      A_RX_FIFO_WATERMARK_REGISTER
> +                                          + sizeof(uint32_t));
>      memory_region_add_subregion(&s->iomem, 0x00, &reg_array->mem);
>      sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);
>      sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq_canfd_int);
>  
>      if (s->canfdbus) {
> -- 
> 2.50.1
> 


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 1/7] hw/core/register: remove the REGISTER device type
  2025-09-17 11:44 ` [PATCH 1/7] hw/core/register: remove the REGISTER device type Luc Michel
@ 2025-09-19  8:49   ` Francisco Iglesias
  2025-09-28 23:32   ` Alistair Francis
  1 sibling, 0 replies; 23+ messages in thread
From: Francisco Iglesias @ 2025-09-19  8:49 UTC (permalink / raw)
  To: Luc Michel
  Cc: qemu-devel, qemu-arm, Peter Maydell, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis

On Wed, Sep 17, 2025 at 01:44:42PM +0200, Luc Michel wrote:
> The REGISTER class (RegisterInfo struct) is currently a QOM type
> inheriting from DEVICE. This class has no real purpose:
>    - the qdev API is not used,
>    - according to the comment preceding it, the object_initialize call
>      is here to zero-initialize the struct. However all the effective
>      struct attributes are then initialized explicitly.
>    - the object is never parented.
> 
> This commits drops the REGISTER QOM type completely, leaving the
> RegisterInfo struct as a bare C struct.
> 
> The register_register_types function is left empty here because it is
> reused in the next commit.
> 
> Signed-off-by: Luc Michel <luc.michel@amd.com>

Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>


> ---
>  include/hw/register.h |  7 -------
>  hw/core/register.c    | 18 ------------------
>  2 files changed, 25 deletions(-)
> 
> diff --git a/include/hw/register.h b/include/hw/register.h
> index a913c52aee5..4d13ea183c7 100644
> --- a/include/hw/register.h
> +++ b/include/hw/register.h
> @@ -73,25 +73,18 @@ struct RegisterAccessInfo {
>   *
>   * @opaque: Opaque data for the register
>   */
>  
>  struct RegisterInfo {
> -    /* <private> */
> -    DeviceState parent_obj;
> -
> -    /* <public> */
>      void *data;
>      int data_size;
>  
>      const RegisterAccessInfo *access;
>  
>      void *opaque;
>  };
>  
> -#define TYPE_REGISTER "qemu-register"
> -DECLARE_INSTANCE_CHECKER(RegisterInfo, REGISTER,
> -                         TYPE_REGISTER)
>  
>  /**
>   * This structure is used to group all of the individual registers which are
>   * modeled using the RegisterInfo structure.
>   *
> diff --git a/hw/core/register.c b/hw/core/register.c
> index 8f63d9f227c..57dde29710c 100644
> --- a/hw/core/register.c
> +++ b/hw/core/register.c
> @@ -256,13 +256,10 @@ static RegisterInfoArray *register_init_block(DeviceState *owner,
>  
>      for (i = 0; i < num; i++) {
>          int index = rae[i].addr / data_size;
>          RegisterInfo *r = &ri[index];
>  
> -        /* Init the register, this will zero it. */
> -        object_initialize((void *)r, sizeof(*r), TYPE_REGISTER);
> -
>          /* Set the properties of the register */
>          r->data = data + data_size * index;
>          r->data_size = data_size;
>          r->access = &rae[i];
>          r->opaque = owner;
> @@ -317,26 +314,11 @@ void register_finalize_block(RegisterInfoArray *r_array)
>      object_unparent(OBJECT(&r_array->mem));
>      g_free(r_array->r);
>      g_free(r_array);
>  }
>  
> -static void register_class_init(ObjectClass *oc, const void *data)
> -{
> -    DeviceClass *dc = DEVICE_CLASS(oc);
> -
> -    /* Reason: needs to be wired up to work */
> -    dc->user_creatable = false;
> -}
> -
> -static const TypeInfo register_info = {
> -    .name  = TYPE_REGISTER,
> -    .parent = TYPE_DEVICE,
> -    .class_init = register_class_init,
> -    .instance_size = sizeof(RegisterInfo),
> -};
>  
>  static void register_register_types(void)
>  {
> -    type_register_static(&register_info);
>  }
>  
>  type_init(register_register_types)
> -- 
> 2.50.1
> 


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 2/7] hw/core/register: add the REGISTER_ARRAY type
  2025-09-17 11:44 ` [PATCH 2/7] hw/core/register: add the REGISTER_ARRAY type Luc Michel
@ 2025-09-19  8:50   ` Francisco Iglesias
  2025-09-28 23:34   ` Alistair Francis
  1 sibling, 0 replies; 23+ messages in thread
From: Francisco Iglesias @ 2025-09-19  8:50 UTC (permalink / raw)
  To: Luc Michel
  Cc: qemu-devel, qemu-arm, Peter Maydell, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis

On Wed, Sep 17, 2025 at 01:44:43PM +0200, Luc Michel wrote:
> Introduce the REGISTER_ARRAY QOM type. This type reuses the existing
> RegisterInfoArray struct. When `register_init_block' is called, it creates
> a REGISTER_ARRAY object and parents it to the calling device. This way
> it gets finalized when the device is.
> 
> The finalize function of the REGISTER_ARRAY type performs the necessary
> cleaning that used to be done by `register_finalize_block'. The latter
> is left empty and will be removed when all the register API users have
> been refactored.
> 
> Signed-off-by: Luc Michel <luc.michel@amd.com>

Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>


> ---
>  include/hw/register.h |  4 ++++
>  hw/core/register.c    | 24 +++++++++++++++++++++---
>  2 files changed, 25 insertions(+), 3 deletions(-)
> 
> diff --git a/include/hw/register.h b/include/hw/register.h
> index 4d13ea183c7..65c82600e06 100644
> --- a/include/hw/register.h
> +++ b/include/hw/register.h
> @@ -81,10 +81,12 @@ struct RegisterInfo {
>      const RegisterAccessInfo *access;
>  
>      void *opaque;
>  };
>  
> +#define TYPE_REGISTER_ARRAY "qemu-register-array"
> +OBJECT_DECLARE_SIMPLE_TYPE(RegisterInfoArray, REGISTER_ARRAY)
>  
>  /**
>   * This structure is used to group all of the individual registers which are
>   * modeled using the RegisterInfo structure.
>   *
> @@ -94,10 +96,12 @@ struct RegisterInfo {
>   *
>   * @mem: optional Memory region for the register
>   */
>  
>  struct RegisterInfoArray {
> +    Object parent_obj;
> +
>      MemoryRegion mem;
>  
>      int num_elements;
>      RegisterInfo **r;
>  
> diff --git a/hw/core/register.c b/hw/core/register.c
> index 57dde29710c..4d1cce02a55 100644
> --- a/hw/core/register.c
> +++ b/hw/core/register.c
> @@ -243,14 +243,20 @@ static RegisterInfoArray *register_init_block(DeviceState *owner,
>                                                bool debug_enabled,
>                                                uint64_t memory_size,
>                                                size_t data_size_bits)
>  {
>      const char *device_prefix = object_get_typename(OBJECT(owner));
> -    RegisterInfoArray *r_array = g_new0(RegisterInfoArray, 1);
> +    Object *obj;
> +    RegisterInfoArray *r_array;
>      int data_size = data_size_bits >> 3;
>      int i;
>  
> +    obj = object_new(TYPE_REGISTER_ARRAY);
> +    object_property_add_child(OBJECT(owner), "reg-array[*]", obj);
> +    object_unref(obj);
> +
> +    r_array = REGISTER_ARRAY(obj);
>      r_array->r = g_new0(RegisterInfo *, num);
>      r_array->num_elements = num;
>      r_array->debug = debug_enabled;
>      r_array->prefix = device_prefix;
>  
> @@ -307,18 +313,30 @@ RegisterInfoArray *register_init_block64(DeviceState *owner,
>  {
>      return register_init_block(owner, rae, num, ri, (void *)
>                                 data, ops, debug_enabled, memory_size, 64);
>  }
>  
> -void register_finalize_block(RegisterInfoArray *r_array)
> +static void register_array_finalize(Object *obj)
>  {
> +    RegisterInfoArray *r_array = REGISTER_ARRAY(obj);
> +
>      object_unparent(OBJECT(&r_array->mem));
>      g_free(r_array->r);
> -    g_free(r_array);
>  }
>  
> +void register_finalize_block(RegisterInfoArray *r_array)
> +{
> +}
> +
> +static const TypeInfo register_array_info = {
> +    .name  = TYPE_REGISTER_ARRAY,
> +    .parent = TYPE_OBJECT,
> +    .instance_size = sizeof(RegisterInfoArray),
> +    .instance_finalize = register_array_finalize,
> +};
>  
>  static void register_register_types(void)
>  {
> +    type_register_static(&register_array_info);
>  }
>  
>  type_init(register_register_types)
> -- 
> 2.50.1
> 


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 3/7] hw/core/register: remove the calls to `register_finalize_block'
  2025-09-17 11:44 ` [PATCH 3/7] hw/core/register: remove the calls to `register_finalize_block' Luc Michel
@ 2025-09-19  8:51   ` Francisco Iglesias
  2025-09-28 23:35   ` Alistair Francis
  1 sibling, 0 replies; 23+ messages in thread
From: Francisco Iglesias @ 2025-09-19  8:51 UTC (permalink / raw)
  To: Luc Michel
  Cc: qemu-devel, qemu-arm, Peter Maydell, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis

On Wed, Sep 17, 2025 at 01:44:44PM +0200, Luc Michel wrote:
> This function is now a no-op. The register array is parented to the
> device and get finalized when the device is.
> 
> Drop all the calls to `register_finalize_block'. Drop the
> RegisterInfoArray reference when it is not used elsewhere in the device.
> 
> Signed-off-by: Luc Michel <luc.michel@amd.com>

Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>


> ---
>  include/hw/misc/xlnx-versal-crl.h      |  1 -
>  include/hw/misc/xlnx-versal-xramc.h    |  1 -
>  include/hw/misc/xlnx-zynqmp-apu-ctrl.h |  1 -
>  include/hw/misc/xlnx-zynqmp-crf.h      |  1 -
>  include/hw/nvram/xlnx-bbram.h          |  1 -
>  hw/misc/xlnx-versal-crl.c              | 38 +++++++++++---------------
>  hw/misc/xlnx-versal-trng.c             |  1 -
>  hw/misc/xlnx-versal-xramc.c            | 12 ++------
>  hw/misc/xlnx-zynqmp-apu-ctrl.c         | 12 ++------
>  hw/misc/xlnx-zynqmp-crf.c              | 12 ++------
>  hw/nvram/xlnx-bbram.c                  | 13 ++-------
>  hw/nvram/xlnx-versal-efuse-ctrl.c      |  1 -
>  hw/nvram/xlnx-zynqmp-efuse.c           |  8 ------
>  13 files changed, 28 insertions(+), 74 deletions(-)
> 
> diff --git a/include/hw/misc/xlnx-versal-crl.h b/include/hw/misc/xlnx-versal-crl.h
> index f6b8694ebea..49ed500acde 100644
> --- a/include/hw/misc/xlnx-versal-crl.h
> +++ b/include/hw/misc/xlnx-versal-crl.h
> @@ -531,11 +531,10 @@ REG32(VERSAL2_RST_OCM, 0x3d8)
>  #define VERSAL2_CRL_R_MAX (R_VERSAL2_RST_OCM + 1)
>  
>  struct XlnxVersalCRLBase {
>      SysBusDevice parent_obj;
>  
> -    RegisterInfoArray *reg_array;
>      uint32_t *regs;
>  };
>  
>  struct XlnxVersalCRLBaseClass {
>      SysBusDeviceClass parent_class;
> diff --git a/include/hw/misc/xlnx-versal-xramc.h b/include/hw/misc/xlnx-versal-xramc.h
> index d3d1862676f..35e4e8b91dd 100644
> --- a/include/hw/misc/xlnx-versal-xramc.h
> +++ b/include/hw/misc/xlnx-versal-xramc.h
> @@ -88,10 +88,9 @@ typedef struct XlnxXramCtrl {
>      struct {
>          uint64_t size;
>          unsigned int encoded_size;
>      } cfg;
>  
> -    RegisterInfoArray *reg_array;
>      uint32_t regs[XRAM_CTRL_R_MAX];
>      RegisterInfo regs_info[XRAM_CTRL_R_MAX];
>  } XlnxXramCtrl;
>  #endif
> diff --git a/include/hw/misc/xlnx-zynqmp-apu-ctrl.h b/include/hw/misc/xlnx-zynqmp-apu-ctrl.h
> index c3bf3c1583b..fbfe34aa7e5 100644
> --- a/include/hw/misc/xlnx-zynqmp-apu-ctrl.h
> +++ b/include/hw/misc/xlnx-zynqmp-apu-ctrl.h
> @@ -83,11 +83,10 @@ struct XlnxZynqMPAPUCtrl {
>      qemu_irq irq_imr;
>  
>      uint8_t cpu_pwrdwn_req;
>      uint8_t cpu_in_wfi;
>  
> -    RegisterInfoArray *reg_array;
>      uint32_t regs[APU_R_MAX];
>      RegisterInfo regs_info[APU_R_MAX];
>  };
>  
>  #endif
> diff --git a/include/hw/misc/xlnx-zynqmp-crf.h b/include/hw/misc/xlnx-zynqmp-crf.h
> index 02ef0bdeeee..c746ae10397 100644
> --- a/include/hw/misc/xlnx-zynqmp-crf.h
> +++ b/include/hw/misc/xlnx-zynqmp-crf.h
> @@ -201,11 +201,10 @@ REG32(RST_DDR_SS, 0x108)
>  struct XlnxZynqMPCRF {
>      SysBusDevice parent_obj;
>      MemoryRegion iomem;
>      qemu_irq irq_ir;
>  
> -    RegisterInfoArray *reg_array;
>      uint32_t regs[CRF_R_MAX];
>      RegisterInfo regs_info[CRF_R_MAX];
>  };
>  
>  #endif
> diff --git a/include/hw/nvram/xlnx-bbram.h b/include/hw/nvram/xlnx-bbram.h
> index 58acbe9f51b..af90900bfc6 100644
> --- a/include/hw/nvram/xlnx-bbram.h
> +++ b/include/hw/nvram/xlnx-bbram.h
> @@ -45,11 +45,10 @@ struct XlnxBBRam {
>  
>      uint32_t crc_zpads;
>      bool bbram8_wo;
>      bool blk_ro;
>  
> -    RegisterInfoArray *reg_array;
>      uint32_t regs[RMAX_XLNX_BBRAM];
>      RegisterInfo regs_info[RMAX_XLNX_BBRAM];
>  };
>  
>  #endif
> diff --git a/hw/misc/xlnx-versal-crl.c b/hw/misc/xlnx-versal-crl.c
> index 10e6af002ba..5987f32c716 100644
> --- a/hw/misc/xlnx-versal-crl.c
> +++ b/hw/misc/xlnx-versal-crl.c
> @@ -632,21 +632,21 @@ static const MemoryRegionOps crl_ops = {
>  static void versal_crl_init(Object *obj)
>  {
>      XlnxVersalCRL *s = XLNX_VERSAL_CRL(obj);
>      XlnxVersalCRLBase *xvcb = XLNX_VERSAL_CRL_BASE(obj);
>      SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
> +    RegisterInfoArray *reg_array;
>      int i;
>  
> -    xvcb->reg_array =
> -        register_init_block32(DEVICE(obj), crl_regs_info,
> -                              ARRAY_SIZE(crl_regs_info),
> -                              s->regs_info, s->regs,
> -                              &crl_ops,
> -                              XLNX_VERSAL_CRL_ERR_DEBUG,
> -                              CRL_R_MAX * 4);
> +    reg_array = register_init_block32(DEVICE(obj), crl_regs_info,
> +                                      ARRAY_SIZE(crl_regs_info),
> +                                      s->regs_info, s->regs,
> +                                      &crl_ops,
> +                                      XLNX_VERSAL_CRL_ERR_DEBUG,
> +                                      CRL_R_MAX * 4);
>      xvcb->regs = s->regs;
> -    sysbus_init_mmio(sbd, &xvcb->reg_array->mem);
> +    sysbus_init_mmio(sbd, &reg_array->mem);
>      sysbus_init_irq(sbd, &s->irq);
>  
>      for (i = 0; i < ARRAY_SIZE(s->cfg.rpu); ++i) {
>          object_property_add_link(obj, "rpu[*]", TYPE_ARM_CPU,
>                                   (Object **)&s->cfg.rpu[i],
> @@ -686,21 +686,22 @@ static void versal_crl_init(Object *obj)
>  static void versal2_crl_init(Object *obj)
>  {
>      XlnxVersal2CRL *s = XLNX_VERSAL2_CRL(obj);
>      XlnxVersalCRLBase *xvcb = XLNX_VERSAL_CRL_BASE(obj);
>      SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
> +    RegisterInfoArray *reg_array;
>      size_t i;
>  
> -    xvcb->reg_array = register_init_block32(DEVICE(obj), versal2_crl_regs_info,
> -                                            ARRAY_SIZE(versal2_crl_regs_info),
> -                                            s->regs_info, s->regs,
> -                                            &crl_ops,
> -                                            XLNX_VERSAL_CRL_ERR_DEBUG,
> -                                            VERSAL2_CRL_R_MAX * 4);
> +    reg_array = register_init_block32(DEVICE(obj), versal2_crl_regs_info,
> +                                      ARRAY_SIZE(versal2_crl_regs_info),
> +                                      s->regs_info, s->regs,
> +                                      &crl_ops,
> +                                      XLNX_VERSAL_CRL_ERR_DEBUG,
> +                                      VERSAL2_CRL_R_MAX * 4);
>      xvcb->regs = s->regs;
>  
> -    sysbus_init_mmio(sbd, &xvcb->reg_array->mem);
> +    sysbus_init_mmio(sbd, &reg_array->mem);
>  
>      for (i = 0; i < ARRAY_SIZE(s->cfg.rpu); ++i) {
>          object_property_add_link(obj, "rpu[*]", TYPE_ARM_CPU,
>                                   (Object **)&s->cfg.rpu[i],
>                                   qdev_prop_allow_set_link_before_realize,
> @@ -748,16 +749,10 @@ static void versal2_crl_init(Object *obj)
>                                   qdev_prop_allow_set_link_before_realize,
>                                   OBJ_PROP_LINK_STRONG);
>      }
>  }
>  
> -static void crl_finalize(Object *obj)
> -{
> -    XlnxVersalCRLBase *s = XLNX_VERSAL_CRL_BASE(obj);
> -    register_finalize_block(s->reg_array);
> -}
> -
>  static const VMStateDescription vmstate_versal_crl = {
>      .name = TYPE_XLNX_VERSAL_CRL,
>      .version_id = 1,
>      .minimum_version_id = 1,
>      .fields = (const VMStateField[]) {
> @@ -802,11 +797,10 @@ static void versal2_crl_class_init(ObjectClass *klass, const void *data)
>  static const TypeInfo crl_base_info = {
>      .name          = TYPE_XLNX_VERSAL_CRL_BASE,
>      .parent        = TYPE_SYS_BUS_DEVICE,
>      .instance_size = sizeof(XlnxVersalCRLBase),
>      .class_size    = sizeof(XlnxVersalCRLBaseClass),
> -    .instance_finalize = crl_finalize,
>      .abstract      = true,
>  };
>  
>  static const TypeInfo versal_crl_info = {
>      .name          = TYPE_XLNX_VERSAL_CRL,
> diff --git a/hw/misc/xlnx-versal-trng.c b/hw/misc/xlnx-versal-trng.c
> index f34dd3ef352..2b573a45bdb 100644
> --- a/hw/misc/xlnx-versal-trng.c
> +++ b/hw/misc/xlnx-versal-trng.c
> @@ -625,11 +625,10 @@ static void trng_init(Object *obj)
>  
>  static void trng_finalize(Object *obj)
>  {
>      XlnxVersalTRng *s = XLNX_VERSAL_TRNG(obj);
>  
> -    register_finalize_block(s->reg_array);
>      g_rand_free(s->prng);
>      s->prng = NULL;
>  }
>  
>  static void trng_reset_hold(Object *obj, ResetType type)
> diff --git a/hw/misc/xlnx-versal-xramc.c b/hw/misc/xlnx-versal-xramc.c
> index 07370b80c0d..d90f3e87c74 100644
> --- a/hw/misc/xlnx-versal-xramc.c
> +++ b/hw/misc/xlnx-versal-xramc.c
> @@ -188,28 +188,23 @@ static void xram_ctrl_realize(DeviceState *dev, Error **errp)
>  
>  static void xram_ctrl_init(Object *obj)
>  {
>      XlnxXramCtrl *s = XLNX_XRAM_CTRL(obj);
>      SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
> +    RegisterInfoArray *reg_array;
>  
> -    s->reg_array =
> +    reg_array =
>          register_init_block32(DEVICE(obj), xram_ctrl_regs_info,
>                                ARRAY_SIZE(xram_ctrl_regs_info),
>                                s->regs_info, s->regs,
>                                &xram_ctrl_ops,
>                                XLNX_XRAM_CTRL_ERR_DEBUG,
>                                XRAM_CTRL_R_MAX * 4);
> -    sysbus_init_mmio(sbd, &s->reg_array->mem);
> +    sysbus_init_mmio(sbd, &reg_array->mem);
>      sysbus_init_irq(sbd, &s->irq);
>  }
>  
> -static void xram_ctrl_finalize(Object *obj)
> -{
> -    XlnxXramCtrl *s = XLNX_XRAM_CTRL(obj);
> -    register_finalize_block(s->reg_array);
> -}
> -
>  static const VMStateDescription vmstate_xram_ctrl = {
>      .name = TYPE_XLNX_XRAM_CTRL,
>      .version_id = 1,
>      .minimum_version_id = 1,
>      .fields = (const VMStateField[]) {
> @@ -239,11 +234,10 @@ static const TypeInfo xram_ctrl_info = {
>      .name              = TYPE_XLNX_XRAM_CTRL,
>      .parent            = TYPE_SYS_BUS_DEVICE,
>      .instance_size     = sizeof(XlnxXramCtrl),
>      .class_init        = xram_ctrl_class_init,
>      .instance_init     = xram_ctrl_init,
> -    .instance_finalize = xram_ctrl_finalize,
>  };
>  
>  static void xram_ctrl_register_types(void)
>  {
>      type_register_static(&xram_ctrl_info);
> diff --git a/hw/misc/xlnx-zynqmp-apu-ctrl.c b/hw/misc/xlnx-zynqmp-apu-ctrl.c
> index e85da32d99c..08777496d56 100644
> --- a/hw/misc/xlnx-zynqmp-apu-ctrl.c
> +++ b/hw/misc/xlnx-zynqmp-apu-ctrl.c
> @@ -177,20 +177,21 @@ static void zynqmp_apu_handle_wfi(void *opaque, int irq, int level)
>  }
>  
>  static void zynqmp_apu_init(Object *obj)
>  {
>      XlnxZynqMPAPUCtrl *s = XLNX_ZYNQMP_APU_CTRL(obj);
> +    RegisterInfoArray *reg_array;
>      int i;
>  
> -    s->reg_array =
> +    reg_array =
>          register_init_block32(DEVICE(obj), zynqmp_apu_regs_info,
>                                ARRAY_SIZE(zynqmp_apu_regs_info),
>                                s->regs_info, s->regs,
>                                &zynqmp_apu_ops,
>                                XILINX_ZYNQMP_APU_ERR_DEBUG,
>                                APU_R_MAX * 4);
> -    sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->reg_array->mem);
> +    sysbus_init_mmio(SYS_BUS_DEVICE(obj), &reg_array->mem);
>      sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq_imr);
>  
>      for (i = 0; i < APU_MAX_CPU; ++i) {
>          g_autofree gchar *prop_name = g_strdup_printf("cpu%d", i);
>          object_property_add_link(obj, prop_name, TYPE_ARM_CPU,
> @@ -206,16 +207,10 @@ static void zynqmp_apu_init(Object *obj)
>                               "CPU_POWER_STATUS", 4);
>      /* wfi_in is used as input from CPUs as wfi request. */
>      qdev_init_gpio_in_named(DEVICE(obj), zynqmp_apu_handle_wfi, "wfi_in", 4);
>  }
>  
> -static void zynqmp_apu_finalize(Object *obj)
> -{
> -    XlnxZynqMPAPUCtrl *s = XLNX_ZYNQMP_APU_CTRL(obj);
> -    register_finalize_block(s->reg_array);
> -}
> -
>  static const VMStateDescription vmstate_zynqmp_apu = {
>      .name = TYPE_XLNX_ZYNQMP_APU_CTRL,
>      .version_id = 1,
>      .minimum_version_id = 1,
>      .fields = (const VMStateField[]) {
> @@ -239,11 +234,10 @@ static const TypeInfo zynqmp_apu_info = {
>      .name              = TYPE_XLNX_ZYNQMP_APU_CTRL,
>      .parent            = TYPE_SYS_BUS_DEVICE,
>      .instance_size     = sizeof(XlnxZynqMPAPUCtrl),
>      .class_init        = zynqmp_apu_class_init,
>      .instance_init     = zynqmp_apu_init,
> -    .instance_finalize = zynqmp_apu_finalize,
>  };
>  
>  static void zynqmp_apu_register_types(void)
>  {
>      type_register_static(&zynqmp_apu_info);
> diff --git a/hw/misc/xlnx-zynqmp-crf.c b/hw/misc/xlnx-zynqmp-crf.c
> index cccca0e814e..d9c1bd50e4f 100644
> --- a/hw/misc/xlnx-zynqmp-crf.c
> +++ b/hw/misc/xlnx-zynqmp-crf.c
> @@ -209,28 +209,23 @@ static const MemoryRegionOps crf_ops = {
>  
>  static void crf_init(Object *obj)
>  {
>      XlnxZynqMPCRF *s = XLNX_ZYNQMP_CRF(obj);
>      SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
> +    RegisterInfoArray *reg_array;
>  
> -    s->reg_array =
> +    reg_array =
>          register_init_block32(DEVICE(obj), crf_regs_info,
>                                ARRAY_SIZE(crf_regs_info),
>                                s->regs_info, s->regs,
>                                &crf_ops,
>                                XLNX_ZYNQMP_CRF_ERR_DEBUG,
>                                CRF_R_MAX * 4);
> -    sysbus_init_mmio(sbd, &s->reg_array->mem);
> +    sysbus_init_mmio(sbd, &reg_array->mem);
>      sysbus_init_irq(sbd, &s->irq_ir);
>  }
>  
> -static void crf_finalize(Object *obj)
> -{
> -    XlnxZynqMPCRF *s = XLNX_ZYNQMP_CRF(obj);
> -    register_finalize_block(s->reg_array);
> -}
> -
>  static const VMStateDescription vmstate_crf = {
>      .name = TYPE_XLNX_ZYNQMP_CRF,
>      .version_id = 1,
>      .minimum_version_id = 1,
>      .fields = (const VMStateField[]) {
> @@ -253,11 +248,10 @@ static const TypeInfo crf_info = {
>      .name              = TYPE_XLNX_ZYNQMP_CRF,
>      .parent            = TYPE_SYS_BUS_DEVICE,
>      .instance_size     = sizeof(XlnxZynqMPCRF),
>      .class_init        = crf_class_init,
>      .instance_init     = crf_init,
> -    .instance_finalize = crf_finalize,
>  };
>  
>  static void crf_register_types(void)
>  {
>      type_register_static(&crf_info);
> diff --git a/hw/nvram/xlnx-bbram.c b/hw/nvram/xlnx-bbram.c
> index 5702bb3f310..22aefbc240d 100644
> --- a/hw/nvram/xlnx-bbram.c
> +++ b/hw/nvram/xlnx-bbram.c
> @@ -454,30 +454,24 @@ static void bbram_ctrl_realize(DeviceState *dev, Error **errp)
>  
>  static void bbram_ctrl_init(Object *obj)
>  {
>      XlnxBBRam *s = XLNX_BBRAM(obj);
>      SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
> +    RegisterInfoArray *reg_array;
>  
> -    s->reg_array =
> +    reg_array =
>          register_init_block32(DEVICE(obj), bbram_ctrl_regs_info,
>                                ARRAY_SIZE(bbram_ctrl_regs_info),
>                                s->regs_info, s->regs,
>                                &bbram_ctrl_ops,
>                                XLNX_BBRAM_ERR_DEBUG,
>                                R_MAX * 4);
>  
> -    sysbus_init_mmio(sbd, &s->reg_array->mem);
> +    sysbus_init_mmio(sbd, &reg_array->mem);
>      sysbus_init_irq(sbd, &s->irq_bbram);
>  }
>  
> -static void bbram_ctrl_finalize(Object *obj)
> -{
> -    XlnxBBRam *s = XLNX_BBRAM(obj);
> -
> -    register_finalize_block(s->reg_array);
> -}
> -
>  static void bbram_prop_set_drive(Object *obj, Visitor *v, const char *name,
>                                   void *opaque, Error **errp)
>  {
>      DeviceState *dev = DEVICE(obj);
>  
> @@ -540,11 +534,10 @@ static const TypeInfo bbram_ctrl_info = {
>      .name          = TYPE_XLNX_BBRAM,
>      .parent        = TYPE_SYS_BUS_DEVICE,
>      .instance_size = sizeof(XlnxBBRam),
>      .class_init    = bbram_ctrl_class_init,
>      .instance_init = bbram_ctrl_init,
> -    .instance_finalize = bbram_ctrl_finalize,
>  };
>  
>  static void bbram_ctrl_register_types(void)
>  {
>      type_register_static(&bbram_ctrl_info);
> diff --git a/hw/nvram/xlnx-versal-efuse-ctrl.c b/hw/nvram/xlnx-versal-efuse-ctrl.c
> index 90962198008..6f17f32a0c3 100644
> --- a/hw/nvram/xlnx-versal-efuse-ctrl.c
> +++ b/hw/nvram/xlnx-versal-efuse-ctrl.c
> @@ -726,11 +726,10 @@ static void efuse_ctrl_init(Object *obj)
>  
>  static void efuse_ctrl_finalize(Object *obj)
>  {
>      XlnxVersalEFuseCtrl *s = XLNX_VERSAL_EFUSE_CTRL(obj);
>  
> -    register_finalize_block(s->reg_array);
>      g_free(s->extra_pg0_lock_spec);
>  }
>  
>  static const VMStateDescription vmstate_efuse_ctrl = {
>      .name = TYPE_XLNX_VERSAL_EFUSE_CTRL,
> diff --git a/hw/nvram/xlnx-zynqmp-efuse.c b/hw/nvram/xlnx-zynqmp-efuse.c
> index 5a218c32e84..ce35bb0cc1f 100644
> --- a/hw/nvram/xlnx-zynqmp-efuse.c
> +++ b/hw/nvram/xlnx-zynqmp-efuse.c
> @@ -814,17 +814,10 @@ static void zynqmp_efuse_init(Object *obj)
>  
>      sysbus_init_mmio(sbd, &s->reg_array->mem);
>      sysbus_init_irq(sbd, &s->irq);
>  }
>  
> -static void zynqmp_efuse_finalize(Object *obj)
> -{
> -    XlnxZynqMPEFuse *s = XLNX_ZYNQMP_EFUSE(obj);
> -
> -    register_finalize_block(s->reg_array);
> -}
> -
>  static const VMStateDescription vmstate_efuse = {
>      .name = TYPE_XLNX_ZYNQMP_EFUSE,
>      .version_id = 1,
>      .minimum_version_id = 1,
>      .fields = (const VMStateField[]) {
> @@ -855,11 +848,10 @@ static const TypeInfo efuse_info = {
>      .name          = TYPE_XLNX_ZYNQMP_EFUSE,
>      .parent        = TYPE_SYS_BUS_DEVICE,
>      .instance_size = sizeof(XlnxZynqMPEFuse),
>      .class_init    = zynqmp_efuse_class_init,
>      .instance_init = zynqmp_efuse_init,
> -    .instance_finalize = zynqmp_efuse_finalize,
>  };
>  
>  static void efuse_register_types(void)
>  {
>      type_register_static(&efuse_info);
> -- 
> 2.50.1
> 


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 4/7] hw/core/register: remove the `register_finalize_block' function
  2025-09-17 11:44 ` [PATCH 4/7] hw/core/register: remove the `register_finalize_block' function Luc Michel
@ 2025-09-19  8:52   ` Francisco Iglesias
  2025-09-28 23:35   ` Alistair Francis
  1 sibling, 0 replies; 23+ messages in thread
From: Francisco Iglesias @ 2025-09-19  8:52 UTC (permalink / raw)
  To: Luc Michel
  Cc: qemu-devel, qemu-arm, Peter Maydell, Edgar E . Iglesias,
	Philippe Mathieu-Daudé, Alistair Francis

On Wed, Sep 17, 2025 at 01:44:45PM +0200, Luc Michel wrote:
> This function is now unused. Drop it.
> 
> Signed-off-by: Luc Michel <luc.michel@amd.com>

Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>

> ---
>  include/hw/register.h | 14 --------------
>  hw/core/register.c    |  4 ----
>  2 files changed, 18 deletions(-)
> 
> diff --git a/include/hw/register.h b/include/hw/register.h
> index 65c82600e06..7b0f4c8b7a6 100644
> --- a/include/hw/register.h
> +++ b/include/hw/register.h
> @@ -207,20 +207,6 @@ RegisterInfoArray *register_init_block64(DeviceState *owner,
>                                           uint64_t *data,
>                                           const MemoryRegionOps *ops,
>                                           bool debug_enabled,
>                                           uint64_t memory_size);
>  
> -/**
> - * This function should be called to cleanup the registers that were initialized
> - * when calling register_init_block32(). This function should only be called
> - * from the device's instance_finalize function.
> - *
> - * Any memory operations that the device performed that require cleanup (such
> - * as creating subregions) need to be called before calling this function.
> - *
> - * @r_array: A structure containing all of the registers, as returned by
> - *           register_init_block32()
> - */
> -
> -void register_finalize_block(RegisterInfoArray *r_array);
> -
>  #endif
> diff --git a/hw/core/register.c b/hw/core/register.c
> index 4d1cce02a55..6cfcfcd2b14 100644
> --- a/hw/core/register.c
> +++ b/hw/core/register.c
> @@ -321,14 +321,10 @@ static void register_array_finalize(Object *obj)
>  
>      object_unparent(OBJECT(&r_array->mem));
>      g_free(r_array->r);
>  }
>  
> -void register_finalize_block(RegisterInfoArray *r_array)
> -{
> -}
> -
>  static const TypeInfo register_array_info = {
>      .name  = TYPE_REGISTER_ARRAY,
>      .parent = TYPE_OBJECT,
>      .instance_size = sizeof(RegisterInfoArray),
>      .instance_finalize = register_array_finalize,
> -- 
> 2.50.1
> 


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 1/7] hw/core/register: remove the REGISTER device type
  2025-09-17 11:44 ` [PATCH 1/7] hw/core/register: remove the REGISTER device type Luc Michel
  2025-09-19  8:49   ` Francisco Iglesias
@ 2025-09-28 23:32   ` Alistair Francis
  1 sibling, 0 replies; 23+ messages in thread
From: Alistair Francis @ 2025-09-28 23:32 UTC (permalink / raw)
  To: Luc Michel
  Cc: qemu-devel, qemu-arm, Peter Maydell, Francisco Iglesias,
	Edgar E . Iglesias, Philippe Mathieu-Daudé, Alistair Francis

On Wed, Sep 17, 2025 at 9:51 PM Luc Michel <luc.michel@amd.com> wrote:
>
> The REGISTER class (RegisterInfo struct) is currently a QOM type
> inheriting from DEVICE. This class has no real purpose:
>    - the qdev API is not used,
>    - according to the comment preceding it, the object_initialize call
>      is here to zero-initialize the struct. However all the effective
>      struct attributes are then initialized explicitly.
>    - the object is never parented.
>
> This commits drops the REGISTER QOM type completely, leaving the
> RegisterInfo struct as a bare C struct.
>
> The register_register_types function is left empty here because it is
> reused in the next commit.
>
> Signed-off-by: Luc Michel <luc.michel@amd.com>

Reviewed-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  include/hw/register.h |  7 -------
>  hw/core/register.c    | 18 ------------------
>  2 files changed, 25 deletions(-)
>
> diff --git a/include/hw/register.h b/include/hw/register.h
> index a913c52aee5..4d13ea183c7 100644
> --- a/include/hw/register.h
> +++ b/include/hw/register.h
> @@ -73,25 +73,18 @@ struct RegisterAccessInfo {
>   *
>   * @opaque: Opaque data for the register
>   */
>
>  struct RegisterInfo {
> -    /* <private> */
> -    DeviceState parent_obj;
> -
> -    /* <public> */
>      void *data;
>      int data_size;
>
>      const RegisterAccessInfo *access;
>
>      void *opaque;
>  };
>
> -#define TYPE_REGISTER "qemu-register"
> -DECLARE_INSTANCE_CHECKER(RegisterInfo, REGISTER,
> -                         TYPE_REGISTER)
>
>  /**
>   * This structure is used to group all of the individual registers which are
>   * modeled using the RegisterInfo structure.
>   *
> diff --git a/hw/core/register.c b/hw/core/register.c
> index 8f63d9f227c..57dde29710c 100644
> --- a/hw/core/register.c
> +++ b/hw/core/register.c
> @@ -256,13 +256,10 @@ static RegisterInfoArray *register_init_block(DeviceState *owner,
>
>      for (i = 0; i < num; i++) {
>          int index = rae[i].addr / data_size;
>          RegisterInfo *r = &ri[index];
>
> -        /* Init the register, this will zero it. */
> -        object_initialize((void *)r, sizeof(*r), TYPE_REGISTER);
> -
>          /* Set the properties of the register */
>          r->data = data + data_size * index;
>          r->data_size = data_size;
>          r->access = &rae[i];
>          r->opaque = owner;
> @@ -317,26 +314,11 @@ void register_finalize_block(RegisterInfoArray *r_array)
>      object_unparent(OBJECT(&r_array->mem));
>      g_free(r_array->r);
>      g_free(r_array);
>  }
>
> -static void register_class_init(ObjectClass *oc, const void *data)
> -{
> -    DeviceClass *dc = DEVICE_CLASS(oc);
> -
> -    /* Reason: needs to be wired up to work */
> -    dc->user_creatable = false;
> -}
> -
> -static const TypeInfo register_info = {
> -    .name  = TYPE_REGISTER,
> -    .parent = TYPE_DEVICE,
> -    .class_init = register_class_init,
> -    .instance_size = sizeof(RegisterInfo),
> -};
>
>  static void register_register_types(void)
>  {
> -    type_register_static(&register_info);
>  }
>
>  type_init(register_register_types)
> --
> 2.50.1
>
>


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 2/7] hw/core/register: add the REGISTER_ARRAY type
  2025-09-17 11:44 ` [PATCH 2/7] hw/core/register: add the REGISTER_ARRAY type Luc Michel
  2025-09-19  8:50   ` Francisco Iglesias
@ 2025-09-28 23:34   ` Alistair Francis
  1 sibling, 0 replies; 23+ messages in thread
From: Alistair Francis @ 2025-09-28 23:34 UTC (permalink / raw)
  To: Luc Michel
  Cc: qemu-devel, qemu-arm, Peter Maydell, Francisco Iglesias,
	Edgar E . Iglesias, Philippe Mathieu-Daudé, Alistair Francis

On Wed, Sep 17, 2025 at 9:51 PM Luc Michel <luc.michel@amd.com> wrote:
>
> Introduce the REGISTER_ARRAY QOM type. This type reuses the existing
> RegisterInfoArray struct. When `register_init_block' is called, it creates
> a REGISTER_ARRAY object and parents it to the calling device. This way
> it gets finalized when the device is.
>
> The finalize function of the REGISTER_ARRAY type performs the necessary
> cleaning that used to be done by `register_finalize_block'. The latter
> is left empty and will be removed when all the register API users have
> been refactored.
>
> Signed-off-by: Luc Michel <luc.michel@amd.com>

Reviewed-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  include/hw/register.h |  4 ++++
>  hw/core/register.c    | 24 +++++++++++++++++++++---
>  2 files changed, 25 insertions(+), 3 deletions(-)
>
> diff --git a/include/hw/register.h b/include/hw/register.h
> index 4d13ea183c7..65c82600e06 100644
> --- a/include/hw/register.h
> +++ b/include/hw/register.h
> @@ -81,10 +81,12 @@ struct RegisterInfo {
>      const RegisterAccessInfo *access;
>
>      void *opaque;
>  };
>
> +#define TYPE_REGISTER_ARRAY "qemu-register-array"
> +OBJECT_DECLARE_SIMPLE_TYPE(RegisterInfoArray, REGISTER_ARRAY)
>
>  /**
>   * This structure is used to group all of the individual registers which are
>   * modeled using the RegisterInfo structure.
>   *
> @@ -94,10 +96,12 @@ struct RegisterInfo {
>   *
>   * @mem: optional Memory region for the register
>   */
>
>  struct RegisterInfoArray {
> +    Object parent_obj;
> +
>      MemoryRegion mem;
>
>      int num_elements;
>      RegisterInfo **r;
>
> diff --git a/hw/core/register.c b/hw/core/register.c
> index 57dde29710c..4d1cce02a55 100644
> --- a/hw/core/register.c
> +++ b/hw/core/register.c
> @@ -243,14 +243,20 @@ static RegisterInfoArray *register_init_block(DeviceState *owner,
>                                                bool debug_enabled,
>                                                uint64_t memory_size,
>                                                size_t data_size_bits)
>  {
>      const char *device_prefix = object_get_typename(OBJECT(owner));
> -    RegisterInfoArray *r_array = g_new0(RegisterInfoArray, 1);
> +    Object *obj;
> +    RegisterInfoArray *r_array;
>      int data_size = data_size_bits >> 3;
>      int i;
>
> +    obj = object_new(TYPE_REGISTER_ARRAY);
> +    object_property_add_child(OBJECT(owner), "reg-array[*]", obj);
> +    object_unref(obj);
> +
> +    r_array = REGISTER_ARRAY(obj);
>      r_array->r = g_new0(RegisterInfo *, num);
>      r_array->num_elements = num;
>      r_array->debug = debug_enabled;
>      r_array->prefix = device_prefix;
>
> @@ -307,18 +313,30 @@ RegisterInfoArray *register_init_block64(DeviceState *owner,
>  {
>      return register_init_block(owner, rae, num, ri, (void *)
>                                 data, ops, debug_enabled, memory_size, 64);
>  }
>
> -void register_finalize_block(RegisterInfoArray *r_array)
> +static void register_array_finalize(Object *obj)
>  {
> +    RegisterInfoArray *r_array = REGISTER_ARRAY(obj);
> +
>      object_unparent(OBJECT(&r_array->mem));
>      g_free(r_array->r);
> -    g_free(r_array);
>  }
>
> +void register_finalize_block(RegisterInfoArray *r_array)
> +{
> +}
> +
> +static const TypeInfo register_array_info = {
> +    .name  = TYPE_REGISTER_ARRAY,
> +    .parent = TYPE_OBJECT,
> +    .instance_size = sizeof(RegisterInfoArray),
> +    .instance_finalize = register_array_finalize,
> +};
>
>  static void register_register_types(void)
>  {
> +    type_register_static(&register_array_info);
>  }
>
>  type_init(register_register_types)
> --
> 2.50.1
>
>


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 3/7] hw/core/register: remove the calls to `register_finalize_block'
  2025-09-17 11:44 ` [PATCH 3/7] hw/core/register: remove the calls to `register_finalize_block' Luc Michel
  2025-09-19  8:51   ` Francisco Iglesias
@ 2025-09-28 23:35   ` Alistair Francis
  1 sibling, 0 replies; 23+ messages in thread
From: Alistair Francis @ 2025-09-28 23:35 UTC (permalink / raw)
  To: Luc Michel
  Cc: qemu-devel, qemu-arm, Peter Maydell, Francisco Iglesias,
	Edgar E . Iglesias, Philippe Mathieu-Daudé, Alistair Francis

On Wed, Sep 17, 2025 at 9:49 PM Luc Michel <luc.michel@amd.com> wrote:
>
> This function is now a no-op. The register array is parented to the
> device and get finalized when the device is.
>
> Drop all the calls to `register_finalize_block'. Drop the
> RegisterInfoArray reference when it is not used elsewhere in the device.
>
> Signed-off-by: Luc Michel <luc.michel@amd.com>

Reviewed-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  include/hw/misc/xlnx-versal-crl.h      |  1 -
>  include/hw/misc/xlnx-versal-xramc.h    |  1 -
>  include/hw/misc/xlnx-zynqmp-apu-ctrl.h |  1 -
>  include/hw/misc/xlnx-zynqmp-crf.h      |  1 -
>  include/hw/nvram/xlnx-bbram.h          |  1 -
>  hw/misc/xlnx-versal-crl.c              | 38 +++++++++++---------------
>  hw/misc/xlnx-versal-trng.c             |  1 -
>  hw/misc/xlnx-versal-xramc.c            | 12 ++------
>  hw/misc/xlnx-zynqmp-apu-ctrl.c         | 12 ++------
>  hw/misc/xlnx-zynqmp-crf.c              | 12 ++------
>  hw/nvram/xlnx-bbram.c                  | 13 ++-------
>  hw/nvram/xlnx-versal-efuse-ctrl.c      |  1 -
>  hw/nvram/xlnx-zynqmp-efuse.c           |  8 ------
>  13 files changed, 28 insertions(+), 74 deletions(-)
>
> diff --git a/include/hw/misc/xlnx-versal-crl.h b/include/hw/misc/xlnx-versal-crl.h
> index f6b8694ebea..49ed500acde 100644
> --- a/include/hw/misc/xlnx-versal-crl.h
> +++ b/include/hw/misc/xlnx-versal-crl.h
> @@ -531,11 +531,10 @@ REG32(VERSAL2_RST_OCM, 0x3d8)
>  #define VERSAL2_CRL_R_MAX (R_VERSAL2_RST_OCM + 1)
>
>  struct XlnxVersalCRLBase {
>      SysBusDevice parent_obj;
>
> -    RegisterInfoArray *reg_array;
>      uint32_t *regs;
>  };
>
>  struct XlnxVersalCRLBaseClass {
>      SysBusDeviceClass parent_class;
> diff --git a/include/hw/misc/xlnx-versal-xramc.h b/include/hw/misc/xlnx-versal-xramc.h
> index d3d1862676f..35e4e8b91dd 100644
> --- a/include/hw/misc/xlnx-versal-xramc.h
> +++ b/include/hw/misc/xlnx-versal-xramc.h
> @@ -88,10 +88,9 @@ typedef struct XlnxXramCtrl {
>      struct {
>          uint64_t size;
>          unsigned int encoded_size;
>      } cfg;
>
> -    RegisterInfoArray *reg_array;
>      uint32_t regs[XRAM_CTRL_R_MAX];
>      RegisterInfo regs_info[XRAM_CTRL_R_MAX];
>  } XlnxXramCtrl;
>  #endif
> diff --git a/include/hw/misc/xlnx-zynqmp-apu-ctrl.h b/include/hw/misc/xlnx-zynqmp-apu-ctrl.h
> index c3bf3c1583b..fbfe34aa7e5 100644
> --- a/include/hw/misc/xlnx-zynqmp-apu-ctrl.h
> +++ b/include/hw/misc/xlnx-zynqmp-apu-ctrl.h
> @@ -83,11 +83,10 @@ struct XlnxZynqMPAPUCtrl {
>      qemu_irq irq_imr;
>
>      uint8_t cpu_pwrdwn_req;
>      uint8_t cpu_in_wfi;
>
> -    RegisterInfoArray *reg_array;
>      uint32_t regs[APU_R_MAX];
>      RegisterInfo regs_info[APU_R_MAX];
>  };
>
>  #endif
> diff --git a/include/hw/misc/xlnx-zynqmp-crf.h b/include/hw/misc/xlnx-zynqmp-crf.h
> index 02ef0bdeeee..c746ae10397 100644
> --- a/include/hw/misc/xlnx-zynqmp-crf.h
> +++ b/include/hw/misc/xlnx-zynqmp-crf.h
> @@ -201,11 +201,10 @@ REG32(RST_DDR_SS, 0x108)
>  struct XlnxZynqMPCRF {
>      SysBusDevice parent_obj;
>      MemoryRegion iomem;
>      qemu_irq irq_ir;
>
> -    RegisterInfoArray *reg_array;
>      uint32_t regs[CRF_R_MAX];
>      RegisterInfo regs_info[CRF_R_MAX];
>  };
>
>  #endif
> diff --git a/include/hw/nvram/xlnx-bbram.h b/include/hw/nvram/xlnx-bbram.h
> index 58acbe9f51b..af90900bfc6 100644
> --- a/include/hw/nvram/xlnx-bbram.h
> +++ b/include/hw/nvram/xlnx-bbram.h
> @@ -45,11 +45,10 @@ struct XlnxBBRam {
>
>      uint32_t crc_zpads;
>      bool bbram8_wo;
>      bool blk_ro;
>
> -    RegisterInfoArray *reg_array;
>      uint32_t regs[RMAX_XLNX_BBRAM];
>      RegisterInfo regs_info[RMAX_XLNX_BBRAM];
>  };
>
>  #endif
> diff --git a/hw/misc/xlnx-versal-crl.c b/hw/misc/xlnx-versal-crl.c
> index 10e6af002ba..5987f32c716 100644
> --- a/hw/misc/xlnx-versal-crl.c
> +++ b/hw/misc/xlnx-versal-crl.c
> @@ -632,21 +632,21 @@ static const MemoryRegionOps crl_ops = {
>  static void versal_crl_init(Object *obj)
>  {
>      XlnxVersalCRL *s = XLNX_VERSAL_CRL(obj);
>      XlnxVersalCRLBase *xvcb = XLNX_VERSAL_CRL_BASE(obj);
>      SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
> +    RegisterInfoArray *reg_array;
>      int i;
>
> -    xvcb->reg_array =
> -        register_init_block32(DEVICE(obj), crl_regs_info,
> -                              ARRAY_SIZE(crl_regs_info),
> -                              s->regs_info, s->regs,
> -                              &crl_ops,
> -                              XLNX_VERSAL_CRL_ERR_DEBUG,
> -                              CRL_R_MAX * 4);
> +    reg_array = register_init_block32(DEVICE(obj), crl_regs_info,
> +                                      ARRAY_SIZE(crl_regs_info),
> +                                      s->regs_info, s->regs,
> +                                      &crl_ops,
> +                                      XLNX_VERSAL_CRL_ERR_DEBUG,
> +                                      CRL_R_MAX * 4);
>      xvcb->regs = s->regs;
> -    sysbus_init_mmio(sbd, &xvcb->reg_array->mem);
> +    sysbus_init_mmio(sbd, &reg_array->mem);
>      sysbus_init_irq(sbd, &s->irq);
>
>      for (i = 0; i < ARRAY_SIZE(s->cfg.rpu); ++i) {
>          object_property_add_link(obj, "rpu[*]", TYPE_ARM_CPU,
>                                   (Object **)&s->cfg.rpu[i],
> @@ -686,21 +686,22 @@ static void versal_crl_init(Object *obj)
>  static void versal2_crl_init(Object *obj)
>  {
>      XlnxVersal2CRL *s = XLNX_VERSAL2_CRL(obj);
>      XlnxVersalCRLBase *xvcb = XLNX_VERSAL_CRL_BASE(obj);
>      SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
> +    RegisterInfoArray *reg_array;
>      size_t i;
>
> -    xvcb->reg_array = register_init_block32(DEVICE(obj), versal2_crl_regs_info,
> -                                            ARRAY_SIZE(versal2_crl_regs_info),
> -                                            s->regs_info, s->regs,
> -                                            &crl_ops,
> -                                            XLNX_VERSAL_CRL_ERR_DEBUG,
> -                                            VERSAL2_CRL_R_MAX * 4);
> +    reg_array = register_init_block32(DEVICE(obj), versal2_crl_regs_info,
> +                                      ARRAY_SIZE(versal2_crl_regs_info),
> +                                      s->regs_info, s->regs,
> +                                      &crl_ops,
> +                                      XLNX_VERSAL_CRL_ERR_DEBUG,
> +                                      VERSAL2_CRL_R_MAX * 4);
>      xvcb->regs = s->regs;
>
> -    sysbus_init_mmio(sbd, &xvcb->reg_array->mem);
> +    sysbus_init_mmio(sbd, &reg_array->mem);
>
>      for (i = 0; i < ARRAY_SIZE(s->cfg.rpu); ++i) {
>          object_property_add_link(obj, "rpu[*]", TYPE_ARM_CPU,
>                                   (Object **)&s->cfg.rpu[i],
>                                   qdev_prop_allow_set_link_before_realize,
> @@ -748,16 +749,10 @@ static void versal2_crl_init(Object *obj)
>                                   qdev_prop_allow_set_link_before_realize,
>                                   OBJ_PROP_LINK_STRONG);
>      }
>  }
>
> -static void crl_finalize(Object *obj)
> -{
> -    XlnxVersalCRLBase *s = XLNX_VERSAL_CRL_BASE(obj);
> -    register_finalize_block(s->reg_array);
> -}
> -
>  static const VMStateDescription vmstate_versal_crl = {
>      .name = TYPE_XLNX_VERSAL_CRL,
>      .version_id = 1,
>      .minimum_version_id = 1,
>      .fields = (const VMStateField[]) {
> @@ -802,11 +797,10 @@ static void versal2_crl_class_init(ObjectClass *klass, const void *data)
>  static const TypeInfo crl_base_info = {
>      .name          = TYPE_XLNX_VERSAL_CRL_BASE,
>      .parent        = TYPE_SYS_BUS_DEVICE,
>      .instance_size = sizeof(XlnxVersalCRLBase),
>      .class_size    = sizeof(XlnxVersalCRLBaseClass),
> -    .instance_finalize = crl_finalize,
>      .abstract      = true,
>  };
>
>  static const TypeInfo versal_crl_info = {
>      .name          = TYPE_XLNX_VERSAL_CRL,
> diff --git a/hw/misc/xlnx-versal-trng.c b/hw/misc/xlnx-versal-trng.c
> index f34dd3ef352..2b573a45bdb 100644
> --- a/hw/misc/xlnx-versal-trng.c
> +++ b/hw/misc/xlnx-versal-trng.c
> @@ -625,11 +625,10 @@ static void trng_init(Object *obj)
>
>  static void trng_finalize(Object *obj)
>  {
>      XlnxVersalTRng *s = XLNX_VERSAL_TRNG(obj);
>
> -    register_finalize_block(s->reg_array);
>      g_rand_free(s->prng);
>      s->prng = NULL;
>  }
>
>  static void trng_reset_hold(Object *obj, ResetType type)
> diff --git a/hw/misc/xlnx-versal-xramc.c b/hw/misc/xlnx-versal-xramc.c
> index 07370b80c0d..d90f3e87c74 100644
> --- a/hw/misc/xlnx-versal-xramc.c
> +++ b/hw/misc/xlnx-versal-xramc.c
> @@ -188,28 +188,23 @@ static void xram_ctrl_realize(DeviceState *dev, Error **errp)
>
>  static void xram_ctrl_init(Object *obj)
>  {
>      XlnxXramCtrl *s = XLNX_XRAM_CTRL(obj);
>      SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
> +    RegisterInfoArray *reg_array;
>
> -    s->reg_array =
> +    reg_array =
>          register_init_block32(DEVICE(obj), xram_ctrl_regs_info,
>                                ARRAY_SIZE(xram_ctrl_regs_info),
>                                s->regs_info, s->regs,
>                                &xram_ctrl_ops,
>                                XLNX_XRAM_CTRL_ERR_DEBUG,
>                                XRAM_CTRL_R_MAX * 4);
> -    sysbus_init_mmio(sbd, &s->reg_array->mem);
> +    sysbus_init_mmio(sbd, &reg_array->mem);
>      sysbus_init_irq(sbd, &s->irq);
>  }
>
> -static void xram_ctrl_finalize(Object *obj)
> -{
> -    XlnxXramCtrl *s = XLNX_XRAM_CTRL(obj);
> -    register_finalize_block(s->reg_array);
> -}
> -
>  static const VMStateDescription vmstate_xram_ctrl = {
>      .name = TYPE_XLNX_XRAM_CTRL,
>      .version_id = 1,
>      .minimum_version_id = 1,
>      .fields = (const VMStateField[]) {
> @@ -239,11 +234,10 @@ static const TypeInfo xram_ctrl_info = {
>      .name              = TYPE_XLNX_XRAM_CTRL,
>      .parent            = TYPE_SYS_BUS_DEVICE,
>      .instance_size     = sizeof(XlnxXramCtrl),
>      .class_init        = xram_ctrl_class_init,
>      .instance_init     = xram_ctrl_init,
> -    .instance_finalize = xram_ctrl_finalize,
>  };
>
>  static void xram_ctrl_register_types(void)
>  {
>      type_register_static(&xram_ctrl_info);
> diff --git a/hw/misc/xlnx-zynqmp-apu-ctrl.c b/hw/misc/xlnx-zynqmp-apu-ctrl.c
> index e85da32d99c..08777496d56 100644
> --- a/hw/misc/xlnx-zynqmp-apu-ctrl.c
> +++ b/hw/misc/xlnx-zynqmp-apu-ctrl.c
> @@ -177,20 +177,21 @@ static void zynqmp_apu_handle_wfi(void *opaque, int irq, int level)
>  }
>
>  static void zynqmp_apu_init(Object *obj)
>  {
>      XlnxZynqMPAPUCtrl *s = XLNX_ZYNQMP_APU_CTRL(obj);
> +    RegisterInfoArray *reg_array;
>      int i;
>
> -    s->reg_array =
> +    reg_array =
>          register_init_block32(DEVICE(obj), zynqmp_apu_regs_info,
>                                ARRAY_SIZE(zynqmp_apu_regs_info),
>                                s->regs_info, s->regs,
>                                &zynqmp_apu_ops,
>                                XILINX_ZYNQMP_APU_ERR_DEBUG,
>                                APU_R_MAX * 4);
> -    sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->reg_array->mem);
> +    sysbus_init_mmio(SYS_BUS_DEVICE(obj), &reg_array->mem);
>      sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq_imr);
>
>      for (i = 0; i < APU_MAX_CPU; ++i) {
>          g_autofree gchar *prop_name = g_strdup_printf("cpu%d", i);
>          object_property_add_link(obj, prop_name, TYPE_ARM_CPU,
> @@ -206,16 +207,10 @@ static void zynqmp_apu_init(Object *obj)
>                               "CPU_POWER_STATUS", 4);
>      /* wfi_in is used as input from CPUs as wfi request. */
>      qdev_init_gpio_in_named(DEVICE(obj), zynqmp_apu_handle_wfi, "wfi_in", 4);
>  }
>
> -static void zynqmp_apu_finalize(Object *obj)
> -{
> -    XlnxZynqMPAPUCtrl *s = XLNX_ZYNQMP_APU_CTRL(obj);
> -    register_finalize_block(s->reg_array);
> -}
> -
>  static const VMStateDescription vmstate_zynqmp_apu = {
>      .name = TYPE_XLNX_ZYNQMP_APU_CTRL,
>      .version_id = 1,
>      .minimum_version_id = 1,
>      .fields = (const VMStateField[]) {
> @@ -239,11 +234,10 @@ static const TypeInfo zynqmp_apu_info = {
>      .name              = TYPE_XLNX_ZYNQMP_APU_CTRL,
>      .parent            = TYPE_SYS_BUS_DEVICE,
>      .instance_size     = sizeof(XlnxZynqMPAPUCtrl),
>      .class_init        = zynqmp_apu_class_init,
>      .instance_init     = zynqmp_apu_init,
> -    .instance_finalize = zynqmp_apu_finalize,
>  };
>
>  static void zynqmp_apu_register_types(void)
>  {
>      type_register_static(&zynqmp_apu_info);
> diff --git a/hw/misc/xlnx-zynqmp-crf.c b/hw/misc/xlnx-zynqmp-crf.c
> index cccca0e814e..d9c1bd50e4f 100644
> --- a/hw/misc/xlnx-zynqmp-crf.c
> +++ b/hw/misc/xlnx-zynqmp-crf.c
> @@ -209,28 +209,23 @@ static const MemoryRegionOps crf_ops = {
>
>  static void crf_init(Object *obj)
>  {
>      XlnxZynqMPCRF *s = XLNX_ZYNQMP_CRF(obj);
>      SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
> +    RegisterInfoArray *reg_array;
>
> -    s->reg_array =
> +    reg_array =
>          register_init_block32(DEVICE(obj), crf_regs_info,
>                                ARRAY_SIZE(crf_regs_info),
>                                s->regs_info, s->regs,
>                                &crf_ops,
>                                XLNX_ZYNQMP_CRF_ERR_DEBUG,
>                                CRF_R_MAX * 4);
> -    sysbus_init_mmio(sbd, &s->reg_array->mem);
> +    sysbus_init_mmio(sbd, &reg_array->mem);
>      sysbus_init_irq(sbd, &s->irq_ir);
>  }
>
> -static void crf_finalize(Object *obj)
> -{
> -    XlnxZynqMPCRF *s = XLNX_ZYNQMP_CRF(obj);
> -    register_finalize_block(s->reg_array);
> -}
> -
>  static const VMStateDescription vmstate_crf = {
>      .name = TYPE_XLNX_ZYNQMP_CRF,
>      .version_id = 1,
>      .minimum_version_id = 1,
>      .fields = (const VMStateField[]) {
> @@ -253,11 +248,10 @@ static const TypeInfo crf_info = {
>      .name              = TYPE_XLNX_ZYNQMP_CRF,
>      .parent            = TYPE_SYS_BUS_DEVICE,
>      .instance_size     = sizeof(XlnxZynqMPCRF),
>      .class_init        = crf_class_init,
>      .instance_init     = crf_init,
> -    .instance_finalize = crf_finalize,
>  };
>
>  static void crf_register_types(void)
>  {
>      type_register_static(&crf_info);
> diff --git a/hw/nvram/xlnx-bbram.c b/hw/nvram/xlnx-bbram.c
> index 5702bb3f310..22aefbc240d 100644
> --- a/hw/nvram/xlnx-bbram.c
> +++ b/hw/nvram/xlnx-bbram.c
> @@ -454,30 +454,24 @@ static void bbram_ctrl_realize(DeviceState *dev, Error **errp)
>
>  static void bbram_ctrl_init(Object *obj)
>  {
>      XlnxBBRam *s = XLNX_BBRAM(obj);
>      SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
> +    RegisterInfoArray *reg_array;
>
> -    s->reg_array =
> +    reg_array =
>          register_init_block32(DEVICE(obj), bbram_ctrl_regs_info,
>                                ARRAY_SIZE(bbram_ctrl_regs_info),
>                                s->regs_info, s->regs,
>                                &bbram_ctrl_ops,
>                                XLNX_BBRAM_ERR_DEBUG,
>                                R_MAX * 4);
>
> -    sysbus_init_mmio(sbd, &s->reg_array->mem);
> +    sysbus_init_mmio(sbd, &reg_array->mem);
>      sysbus_init_irq(sbd, &s->irq_bbram);
>  }
>
> -static void bbram_ctrl_finalize(Object *obj)
> -{
> -    XlnxBBRam *s = XLNX_BBRAM(obj);
> -
> -    register_finalize_block(s->reg_array);
> -}
> -
>  static void bbram_prop_set_drive(Object *obj, Visitor *v, const char *name,
>                                   void *opaque, Error **errp)
>  {
>      DeviceState *dev = DEVICE(obj);
>
> @@ -540,11 +534,10 @@ static const TypeInfo bbram_ctrl_info = {
>      .name          = TYPE_XLNX_BBRAM,
>      .parent        = TYPE_SYS_BUS_DEVICE,
>      .instance_size = sizeof(XlnxBBRam),
>      .class_init    = bbram_ctrl_class_init,
>      .instance_init = bbram_ctrl_init,
> -    .instance_finalize = bbram_ctrl_finalize,
>  };
>
>  static void bbram_ctrl_register_types(void)
>  {
>      type_register_static(&bbram_ctrl_info);
> diff --git a/hw/nvram/xlnx-versal-efuse-ctrl.c b/hw/nvram/xlnx-versal-efuse-ctrl.c
> index 90962198008..6f17f32a0c3 100644
> --- a/hw/nvram/xlnx-versal-efuse-ctrl.c
> +++ b/hw/nvram/xlnx-versal-efuse-ctrl.c
> @@ -726,11 +726,10 @@ static void efuse_ctrl_init(Object *obj)
>
>  static void efuse_ctrl_finalize(Object *obj)
>  {
>      XlnxVersalEFuseCtrl *s = XLNX_VERSAL_EFUSE_CTRL(obj);
>
> -    register_finalize_block(s->reg_array);
>      g_free(s->extra_pg0_lock_spec);
>  }
>
>  static const VMStateDescription vmstate_efuse_ctrl = {
>      .name = TYPE_XLNX_VERSAL_EFUSE_CTRL,
> diff --git a/hw/nvram/xlnx-zynqmp-efuse.c b/hw/nvram/xlnx-zynqmp-efuse.c
> index 5a218c32e84..ce35bb0cc1f 100644
> --- a/hw/nvram/xlnx-zynqmp-efuse.c
> +++ b/hw/nvram/xlnx-zynqmp-efuse.c
> @@ -814,17 +814,10 @@ static void zynqmp_efuse_init(Object *obj)
>
>      sysbus_init_mmio(sbd, &s->reg_array->mem);
>      sysbus_init_irq(sbd, &s->irq);
>  }
>
> -static void zynqmp_efuse_finalize(Object *obj)
> -{
> -    XlnxZynqMPEFuse *s = XLNX_ZYNQMP_EFUSE(obj);
> -
> -    register_finalize_block(s->reg_array);
> -}
> -
>  static const VMStateDescription vmstate_efuse = {
>      .name = TYPE_XLNX_ZYNQMP_EFUSE,
>      .version_id = 1,
>      .minimum_version_id = 1,
>      .fields = (const VMStateField[]) {
> @@ -855,11 +848,10 @@ static const TypeInfo efuse_info = {
>      .name          = TYPE_XLNX_ZYNQMP_EFUSE,
>      .parent        = TYPE_SYS_BUS_DEVICE,
>      .instance_size = sizeof(XlnxZynqMPEFuse),
>      .class_init    = zynqmp_efuse_class_init,
>      .instance_init = zynqmp_efuse_init,
> -    .instance_finalize = zynqmp_efuse_finalize,
>  };
>
>  static void efuse_register_types(void)
>  {
>      type_register_static(&efuse_info);
> --
> 2.50.1
>
>


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 4/7] hw/core/register: remove the `register_finalize_block' function
  2025-09-17 11:44 ` [PATCH 4/7] hw/core/register: remove the `register_finalize_block' function Luc Michel
  2025-09-19  8:52   ` Francisco Iglesias
@ 2025-09-28 23:35   ` Alistair Francis
  1 sibling, 0 replies; 23+ messages in thread
From: Alistair Francis @ 2025-09-28 23:35 UTC (permalink / raw)
  To: Luc Michel
  Cc: qemu-devel, qemu-arm, Peter Maydell, Francisco Iglesias,
	Edgar E . Iglesias, Philippe Mathieu-Daudé, Alistair Francis

On Wed, Sep 17, 2025 at 9:50 PM Luc Michel <luc.michel@amd.com> wrote:
>
> This function is now unused. Drop it.
>
> Signed-off-by: Luc Michel <luc.michel@amd.com>

Reviewed-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  include/hw/register.h | 14 --------------
>  hw/core/register.c    |  4 ----
>  2 files changed, 18 deletions(-)
>
> diff --git a/include/hw/register.h b/include/hw/register.h
> index 65c82600e06..7b0f4c8b7a6 100644
> --- a/include/hw/register.h
> +++ b/include/hw/register.h
> @@ -207,20 +207,6 @@ RegisterInfoArray *register_init_block64(DeviceState *owner,
>                                           uint64_t *data,
>                                           const MemoryRegionOps *ops,
>                                           bool debug_enabled,
>                                           uint64_t memory_size);
>
> -/**
> - * This function should be called to cleanup the registers that were initialized
> - * when calling register_init_block32(). This function should only be called
> - * from the device's instance_finalize function.
> - *
> - * Any memory operations that the device performed that require cleanup (such
> - * as creating subregions) need to be called before calling this function.
> - *
> - * @r_array: A structure containing all of the registers, as returned by
> - *           register_init_block32()
> - */
> -
> -void register_finalize_block(RegisterInfoArray *r_array);
> -
>  #endif
> diff --git a/hw/core/register.c b/hw/core/register.c
> index 4d1cce02a55..6cfcfcd2b14 100644
> --- a/hw/core/register.c
> +++ b/hw/core/register.c
> @@ -321,14 +321,10 @@ static void register_array_finalize(Object *obj)
>
>      object_unparent(OBJECT(&r_array->mem));
>      g_free(r_array->r);
>  }
>
> -void register_finalize_block(RegisterInfoArray *r_array)
> -{
> -}
> -
>  static const TypeInfo register_array_info = {
>      .name  = TYPE_REGISTER_ARRAY,
>      .parent = TYPE_OBJECT,
>      .instance_size = sizeof(RegisterInfoArray),
>      .instance_finalize = register_array_finalize,
> --
> 2.50.1
>
>


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 5/7] hw/net/can/xlnx-versal-canfd: remove unused include directives
  2025-09-17 11:44 ` [PATCH 5/7] hw/net/can/xlnx-versal-canfd: remove unused include directives Luc Michel
  2025-09-19  8:47   ` Francisco Iglesias
@ 2025-09-28 23:36   ` Alistair Francis
  1 sibling, 0 replies; 23+ messages in thread
From: Alistair Francis @ 2025-09-28 23:36 UTC (permalink / raw)
  To: Luc Michel
  Cc: qemu-devel, qemu-arm, Peter Maydell, Francisco Iglesias,
	Edgar E . Iglesias, Philippe Mathieu-Daudé, Alistair Francis

On Wed, Sep 17, 2025 at 9:49 PM Luc Michel <luc.michel@amd.com> wrote:
>
> Drop unecessary include directives in xlnx-versal-canfd.c.

unnecessary

>
> Signed-off-by: Luc Michel <luc.michel@amd.com>

Reviewed-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  hw/net/can/xlnx-versal-canfd.c | 4 ----
>  1 file changed, 4 deletions(-)
>
> diff --git a/hw/net/can/xlnx-versal-canfd.c b/hw/net/can/xlnx-versal-canfd.c
> index 3eb111949f8..343348660b5 100644
> --- a/hw/net/can/xlnx-versal-canfd.c
> +++ b/hw/net/can/xlnx-versal-canfd.c
> @@ -33,16 +33,12 @@
>  #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"
>
>  REG32(SOFTWARE_RESET_REGISTER, 0x0)
> --
> 2.50.1
>
>


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 0/7] Register API leaks fixes
  2025-09-17 11:44 [PATCH 0/7] Register API leaks fixes Luc Michel
                   ` (7 preceding siblings ...)
  2025-09-18  6:21 ` [PATCH 0/7] Register API leaks fixes Edgar E. Iglesias
@ 2025-09-29 10:19 ` Philippe Mathieu-Daudé
  2025-10-01 21:07   ` Luc Michel
  8 siblings, 1 reply; 23+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-09-29 10:19 UTC (permalink / raw)
  To: Luc Michel, qemu-devel, qemu-arm
  Cc: Peter Maydell, Francisco Iglesias, Edgar E . Iglesias,
	Alistair Francis, Vikram Garhwal

Hi Luc,

On 17/9/25 13:44, Luc Michel wrote:
> Based-on: 20250912100059.103997-1-luc.michel@amd.com ([PATCH v5 00/47] AMD Versal Gen 2 support)


> Note: this series is based on my Versal 2 series. It modifies the CRL
> device during the register API refactoring. It can easily be rebased on
> master if needed.

Couldn't apply locally:

$ b4 shazam -t 20250912100059.103997-1-luc.michel@amd.com
[...]
$ b4 shazam -t 20250917114450.175892-1-luc.michel@amd.com
Applying: hw/core/register: remove the REGISTER device type
Patch failed at 0001 hw/core/register: remove the REGISTER device type
error: patch failed: hw/core/register.c:317
error: hw/core/register.c: patch does not apply

If it isn't too much work, I'd appreciate a v2 based on master
so I can include in my next hw-misc pull request.

Thanks,

Phil.


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 0/7] Register API leaks fixes
  2025-09-29 10:19 ` Philippe Mathieu-Daudé
@ 2025-10-01 21:07   ` Luc Michel
  0 siblings, 0 replies; 23+ messages in thread
From: Luc Michel @ 2025-10-01 21:07 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé
  Cc: qemu-devel, qemu-arm, Peter Maydell, Francisco Iglesias,
	Edgar E . Iglesias, Alistair Francis, Vikram Garhwal

Hi,

On 12:19 Mon 29 Sep     , Philippe Mathieu-Daudé wrote:
> Hi Luc,
> 
> On 17/9/25 13:44, Luc Michel wrote:
> > Based-on: 20250912100059.103997-1-luc.michel@amd.com ([PATCH v5 00/47] AMD Versal Gen 2 support)
> 
> 
> > Note: this series is based on my Versal 2 series. It modifies the CRL
> > device during the register API refactoring. It can easily be rebased on
> > master if needed.
> 
> Couldn't apply locally:
> 
> $ b4 shazam -t 20250912100059.103997-1-luc.michel@amd.com
> [...]
> $ b4 shazam -t 20250917114450.175892-1-luc.michel@amd.com
> Applying: hw/core/register: remove the REGISTER device type
> Patch failed at 0001 hw/core/register: remove the REGISTER device type
> error: patch failed: hw/core/register.c:317
> error: hw/core/register.c: patch does not apply
> 
> If it isn't too much work, I'd appreciate a v2 based on master
> so I can include in my next hw-misc pull request.

I messed up patch 2, this is why it does not apply cleanly.

I'll send a v2 to fix this. As discuted off-list with Phil, it will be
still based on the Versal 2 series. This is to avoid a new rebase of the
Versal 2 series as it is fully reviewed and can probably be merged as-is.

Thanks

Luc


^ permalink raw reply	[flat|nested] 23+ messages in thread

end of thread, other threads:[~2025-10-01 21:09 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-09-17 11:44 [PATCH 0/7] Register API leaks fixes Luc Michel
2025-09-17 11:44 ` [PATCH 1/7] hw/core/register: remove the REGISTER device type Luc Michel
2025-09-19  8:49   ` Francisco Iglesias
2025-09-28 23:32   ` Alistair Francis
2025-09-17 11:44 ` [PATCH 2/7] hw/core/register: add the REGISTER_ARRAY type Luc Michel
2025-09-19  8:50   ` Francisco Iglesias
2025-09-28 23:34   ` Alistair Francis
2025-09-17 11:44 ` [PATCH 3/7] hw/core/register: remove the calls to `register_finalize_block' Luc Michel
2025-09-19  8:51   ` Francisco Iglesias
2025-09-28 23:35   ` Alistair Francis
2025-09-17 11:44 ` [PATCH 4/7] hw/core/register: remove the `register_finalize_block' function Luc Michel
2025-09-19  8:52   ` Francisco Iglesias
2025-09-28 23:35   ` Alistair Francis
2025-09-17 11:44 ` [PATCH 5/7] hw/net/can/xlnx-versal-canfd: remove unused include directives Luc Michel
2025-09-19  8:47   ` Francisco Iglesias
2025-09-28 23:36   ` Alistair Francis
2025-09-17 11:44 ` [PATCH 6/7] hw/net/can/xlnx-versal-canfd: refactor the banked registers logic Luc Michel
2025-09-19  8:48   ` Francisco Iglesias
2025-09-17 11:44 ` [PATCH 7/7] hw/net/can/xlnx-versal-canfd: remove register API usage for banked regs Luc Michel
2025-09-19  8:48   ` Francisco Iglesias
2025-09-18  6:21 ` [PATCH 0/7] Register API leaks fixes Edgar E. Iglesias
2025-09-29 10:19 ` Philippe Mathieu-Daudé
2025-10-01 21:07   ` Luc Michel

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).