On 2026/06/17 0:55, Daniel P. Berrangé wrote:
Prepare for the move to dynamically allocated IRQ objects by
introducing qemu_irq_new / qemu_irq_new_child / qemu_irq_new_array
functions which call through to object_new instead of object_initialize.
Signed-off-by: Daniel P. Berrangé <[email protected]>
---
hw/core/irq.c | 35 ++++++++++++++++++++
include/hw/core/irq.h | 75 ++++++++++++++++++++++++++++++++++++++++---
2 files changed, 106 insertions(+), 4 deletions(-)
diff --git a/hw/core/irq.c b/hw/core/irq.c
index 106805e241..e943c87b81 100644
--- a/hw/core/irq.c
+++ b/hw/core/irq.c
@@ -49,6 +49,13 @@ void qemu_init_irq(IRQState *irq, qemu_irq_handler handler,
void *opaque,
init_irq_fields(irq, handler, opaque, n);
}
+IRQState *qemu_irq_new(qemu_irq_handler handler, void *opaque, int n)
+{
+ IRQState *irq = IRQ(object_new(TYPE_IRQ));
+ init_irq_fields(irq, handler, opaque, n);
+ return irq;
+}
+
void qemu_init_irq_child(Object *parent, const char *propname,
IRQState *irq, qemu_irq_handler handler,
void *opaque, int n)
@@ -57,14 +64,42 @@ void qemu_init_irq_child(Object *parent, const char
*propname,
init_irq_fields(irq, handler, opaque, n);
}
+IRQState *qemu_irq_new_child(Object *parent, const char *propname,
+ qemu_irq_handler handler,
+ void *opaque, int n,
+ Error **errp)
+{
+ IRQState *irq = IRQ(object_new_with_props(TYPE_IRQ, parent, propname,
+ errp, NULL));
object_new_with_props() rejects a property name including [*].
hw/char/serial-pci-multi.c passes "irq[*]" to qemu_init_irq_child() so
this prevents simply replacing it.
Regards,
Akihiko Odaki
+ if (!irq) {
+ return NULL;
+ }
+ init_irq_fields(irq, handler, opaque, n);
+ return irq;
+}
+
+
void qemu_init_irqs(IRQState irq[], size_t count,
qemu_irq_handler handler, void *opaque)
{
for (size_t i = 0; i < count; i++) {
+ QEMU_DEPRECATIONS_OFF;
qemu_init_irq(&irq[i], handler, opaque, i);
+ QEMU_DEPRECATIONS_ON;
}
}
+IRQState **qemu_irq_new_array(size_t count,
+ qemu_irq_handler handler, void *opaque)
+{
+ IRQState **irqs = g_new0(IRQState *, count);
+ for (size_t i = 0; i < count; i++) {
+ irqs[i] = qemu_irq_new(handler, opaque, i);
+ }
+ return irqs;
+}
+
+
qemu_irq *qemu_extend_irqs(qemu_irq *old, int n_old, qemu_irq_handler handler,
void *opaque, int n)
{
diff --git a/include/hw/core/irq.h b/include/hw/core/irq.h
index 291fdd67df..af9bf6fb12 100644
--- a/include/hw/core/irq.h
+++ b/include/hw/core/irq.h
@@ -34,7 +34,12 @@ static inline void qemu_irq_pulse(qemu_irq irq)
qemu_set_irq(irq, 0);
}
-/*
+/**
+ * qemu_init_irq: Initialize IRQ
+ * @handler: handler function for incoming interrupts
+ * @opaque: opaque data to pass to @handler
+ * @n: interrupt number to pass to @handler
+ *
* Init a single IRQ. The irq is assigned with a handler, an opaque data
* and the interrupt number. The caller must free this with qemu_free_irq().
* If you are using this inside a device's init or realize method, then
@@ -42,7 +47,21 @@ static inline void qemu_irq_pulse(qemu_irq irq)
* to manually clean up the IRQ.
*/
void qemu_init_irq(IRQState *irq, qemu_irq_handler handler, void *opaque,
- int n);
+ int n)
+ QEMU_DEPRECATED;
+/**
+ * qemu_new_irq: Allocate IRQ
+ * @handler: handler function for incoming interrupts
+ * @opaque: opaque data to pass to @handler
+ * @n: interrupt number to pass to @handler
+ *
+ * The returned IRQ will have a single reference, which is held by the
+ * caller and must be released to free the returned IRQ object when
+ * no longer required.
+ *
+ * Returns: the newly allocated IRQ
+ */
+IRQState *qemu_irq_new(qemu_irq_handler handler, void *opaque, int n);
/**
* qemu_init_irq_child: Initialize IRQ and make it a QOM child
@@ -56,10 +75,38 @@ void qemu_init_irq(IRQState *irq, qemu_irq_handler handler,
void *opaque,
* Init a single IRQ and make the IRQ object a child of @parent with
* the child-property name @propname. The IRQ object will thus be
* automatically freed when @parent is destroyed.
+ *
+ * Use of this function is now deprecated. All IRQs must be
+ * allocated using the qemu_irq_new() family of functions and not
+ * statically embedded in a larger struct.
*/
void qemu_init_irq_child(Object *parent, const char *propname,
IRQState *irq, qemu_irq_handler handler,
- void *opaque, int n);
+ void *opaque, int n)
+ QEMU_DEPRECATED;
+
+/**
+ * qemu_init_irq_child: Allocate IRQ and make it a QOM child
+ * @parent: QOM object which owns this IRQ
+ * @propname: child property name
+ * @handler: handler function for incoming interrupts
+ * @opaque: opaque data to pass to @handler
+ * @n: interrupt number to pass to @handler
+ *
+ * Allocate a single IRQ and make the IRQ object a child of @parent with
+ * the child-property name @propname.
+ *
+ * The returned IRQ will have a single reference, which is held by the
+ * @owner object in the QOM composition tree. Thus in the absence of
+ * any further references being acquired, the IRQ will be freed when
+ * @owner is freed
+ *
+ * Returns: the newly allocated IRQ
+ */
+IRQState *qemu_irq_new_child(Object *parent, const char *propname,
+ qemu_irq_handler handler,
+ void *opaque, int n,
+ Error **errp);
/**
@@ -69,9 +116,29 @@ void qemu_init_irq_child(Object *parent, const char
*propname,
* @count: number of IRQs to initialize
* @handler: handler to assign to each IRQ
* @opaque: opaque data to pass to @handler
+ *
+ * Use of this function is now deprecated. All IRQs must be
+ * allocated using the qemu_irq_new() family of functions and not
+ * statically embedded in a larger struct.
*/
void qemu_init_irqs(IRQState irq[], size_t count,
- qemu_irq_handler handler, void *opaque);
+ qemu_irq_handler handler, void *opaque)
+ QEMU_DEPRECATED;
+/**
+ * qemu_irq_new_array: Allocate an array of IRQs.
+ * @count: number of IRQs to initialize
+ * @handler: handler to assign to each IRQ
+ * @opaque: opaque data to pass to @handler
+ *
+ * The returned IRQs will have a single reference, which is held by the
+ * caller and must be released to free the returned IRQs object when
+ * no longer required. The return array memory must also be freed by
+ * the caller.
+ *
+ * Returns: an array of IRQ objects
+ */
+IRQState **qemu_irq_new_array(size_t count,
+ qemu_irq_handler handler, void *opaque);
/* Returns an array of N IRQs. Each IRQ is assigned the argument handler and
* opaque data.