Message ID | 20210629133823.9908-1-arkaisp2021@gmail.com |
---|---|
State | New |
Headers | show |
Series | trace: add hardware interrupt calls tracing | expand |
Ping? https://patchwork.kernel.org/project/qemu-devel/patch/20210625073844.1229-3-mark.cave-ayland@ilande.co.uk/ вт, 29 июн. 2021 г. в 16:38, Arkadiy <arkaisp2021@gmail.com>: > From: NDNF <arkaisp2021@gmail.com> > > Adds hardware interrupt call tracing. This is necessary to debugging Qemu > and > virtual devices. It was decided to use function names. This allow us > tracing > IRQ without global code changes. > There was an attempt to use device names, but appeared the problem: > it wasn't always possible to find out the name of the calling device or > the receiver. For example GSI is not a device in Qemu. > Hence, there will be a gap in the interrupt chain. > > Signed-off-by: NDNF <arkaisp2021@gmail.com> > --- > hw/core/irq.c | 28 ++++++++++++++++------ > hw/core/qdev.c | 20 ++++++++++------ > hw/core/trace-events | 3 +++ > include/hw/irq.h | 54 ++++++++++++++++++++++++++++-------------- > include/hw/qdev-core.h | 32 ++++++++++++++++++------- > 5 files changed, 97 insertions(+), 40 deletions(-) > > diff --git a/hw/core/irq.c b/hw/core/irq.c > index 8a9cbdd556..ee32b58cec 100644 > --- a/hw/core/irq.c > +++ b/hw/core/irq.c > @@ -26,6 +26,9 @@ > #include "hw/irq.h" > #include "qom/object.h" > > + > +#include "trace.h" > + > DECLARE_INSTANCE_CHECKER(struct IRQState, IRQ, > TYPE_IRQ) > > @@ -35,18 +38,24 @@ struct IRQState { > qemu_irq_handler handler; > void *opaque; > int n; > + const char *targetFunc; > }; > > -void qemu_set_irq(qemu_irq irq, int level) > +void qemu_set_irq_with_trace(qemu_irq irq, int level, const char > *callFunc) > { > if (!irq) > return; > > + const char *targetFunc = irq->targetFunc; > + trace_irq_tracker(callFunc, targetFunc, irq->n, level); > irq->handler(irq->opaque, irq->n, level); > } > > -qemu_irq *qemu_extend_irqs(qemu_irq *old, int n_old, qemu_irq_handler > handler, > - void *opaque, int n) > +/*Tracking irq function*/ > + > +qemu_irq *qemu_extend_irqs_with_trace(qemu_irq *old, int n_old, > + qemu_irq_handler handler, void > *opaque, > + int n, const char *targetFunc) > { > qemu_irq *s; > int i; > @@ -56,17 +65,19 @@ qemu_irq *qemu_extend_irqs(qemu_irq *old, int n_old, > qemu_irq_handler handler, > } > s = old ? g_renew(qemu_irq, old, n + n_old) : g_new(qemu_irq, n); > for (i = n_old; i < n + n_old; i++) { > - s[i] = qemu_allocate_irq(handler, opaque, i); > + s[i] = qemu_allocate_irq_with_trace(handler, opaque, i, > targetFunc); > } > return s; > } > > -qemu_irq *qemu_allocate_irqs(qemu_irq_handler handler, void *opaque, int > n) > +qemu_irq *qemu_allocate_irqs_with_trace(qemu_irq_handler handler, void > *opaque, > + int n, const char *targetFunc) > { > - return qemu_extend_irqs(NULL, 0, handler, opaque, n); > + return qemu_extend_irqs_with_trace(NULL, 0, handler, opaque, n, > targetFunc); > } > > -qemu_irq qemu_allocate_irq(qemu_irq_handler handler, void *opaque, int n) > +qemu_irq qemu_allocate_irq_with_trace(qemu_irq_handler handler, void > *opaque, > + int n, const char *targetFunc) > { > struct IRQState *irq; > > @@ -74,10 +85,13 @@ qemu_irq qemu_allocate_irq(qemu_irq_handler handler, > void *opaque, int n) > irq->handler = handler; > irq->opaque = opaque; > irq->n = n; > + irq->targetFunc = targetFunc; > > return irq; > } > > +/*Tracking irq function*/ > + > void qemu_free_irqs(qemu_irq *s, int n) > { > int i; > diff --git a/hw/core/qdev.c b/hw/core/qdev.c > index cefc5eaa0a..e621de506d 100644 > --- a/hw/core/qdev.c > +++ b/hw/core/qdev.c > @@ -450,17 +450,20 @@ static NamedGPIOList > *qdev_get_named_gpio_list(DeviceState *dev, > return ngl; > } > > -void qdev_init_gpio_in_named_with_opaque(DeviceState *dev, > +/*Tracking irq function*/ > + > +void qdev_init_gpio_in_named_with_opaque_with_trace(DeviceState *dev, > qemu_irq_handler handler, > - void *opaque, > - const char *name, int n) > + void *opaque, const char *name, > + int n, const char *target) > { > int i; > NamedGPIOList *gpio_list = qdev_get_named_gpio_list(dev, name); > > assert(gpio_list->num_out == 0 || !name); > - gpio_list->in = qemu_extend_irqs(gpio_list->in, gpio_list->num_in, > handler, > - opaque, n); > + gpio_list->in = qemu_extend_irqs_with_trace(gpio_list->in, > + gpio_list->num_in, > handler, > + opaque, n, target); > > if (!name) { > name = "unnamed-gpio-in"; > @@ -476,11 +479,14 @@ void qdev_init_gpio_in_named_with_opaque(DeviceState > *dev, > gpio_list->num_in += n; > } > > -void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n) > +void qdev_init_gpio_in_with_trace(DeviceState *dev, qemu_irq_handler > handler, > + int n, const char *target) > { > - qdev_init_gpio_in_named(dev, handler, NULL, n); > + qdev_init_gpio_in_named_with_trace(dev, handler, NULL, n, target); > } > > +/*Tracking irq function*/ > + > void qdev_init_gpio_out_named(DeviceState *dev, qemu_irq *pins, > const char *name, int n) > { > diff --git a/hw/core/trace-events b/hw/core/trace-events > index 360ddeb2c8..a2a09d597f 100644 > --- a/hw/core/trace-events > +++ b/hw/core/trace-events > @@ -34,3 +34,6 @@ clock_disconnect(const char *clk) "'%s'" > clock_set(const char *clk, uint64_t old, uint64_t new) "'%s', > %"PRIu64"Hz->%"PRIu64"Hz" > clock_propagate(const char *clk) "'%s'" > clock_update(const char *clk, const char *src, uint64_t hz, int cb) > "'%s', src='%s', val=%"PRIu64"Hz cb=%d" > + > +# irq.c > +irq_tracker(const char *call_function, const char *target_function, int > number, int level) ": callFunction = %s, targetFunction = %s, n = %i, level > = %i" > diff --git a/include/hw/irq.h b/include/hw/irq.h > index dc7abf199e..dfcdff14a1 100644 > --- a/include/hw/irq.h > +++ b/include/hw/irq.h > @@ -5,40 +5,58 @@ > > #define TYPE_IRQ "irq" > > -void qemu_set_irq(qemu_irq irq, int level); > +/*Tracking irq define*/ > > -static inline void qemu_irq_raise(qemu_irq irq) > -{ > - qemu_set_irq(irq, 1); > -} > +#define qemu_set_irq(irq, level) \ > + qemu_set_irq_with_trace(irq, level, __func__) > > -static inline void qemu_irq_lower(qemu_irq irq) > -{ > - qemu_set_irq(irq, 0); > -} > +#define qemu_irq_raise(irq) \ > + qemu_set_irq(irq, 1) > > -static inline void qemu_irq_pulse(qemu_irq irq) > -{ > - qemu_set_irq(irq, 1); > +#define qemu_irq_lower(irq) \ > qemu_set_irq(irq, 0); > -} > + > +#define qemu_irq_pulse(irq) \ > + do { \ > + qemu_set_irq(irq, 1); \ > + qemu_set_irq(irq, 0); \ > + } while (0) > + > +#define qemu_allocate_irqs(handler, opaque, n) \ > + qemu_allocate_irqs_with_trace(handler, opaque, n, #handler) > + > +#define qemu_allocate_irq(handler, opaque, n) \ > + qemu_allocate_irq_with_trace(handler, opaque, n, #handler) > + > +#define qemu_extend_irqs(old, n_old, handler, opaque, n) \ > + qemu_extend_irqs_with_trace(old, n_old, handler, opaque, n, __func__) > + > +/*Tracking irq define*/ > + > +/*Tracking irq function*/ > + > +void qemu_set_irq_with_trace(qemu_irq irq, int level, const char > *callFunc); > > /* Returns an array of N IRQs. Each IRQ is assigned the argument handler > and > * opaque data. > */ > -qemu_irq *qemu_allocate_irqs(qemu_irq_handler handler, void *opaque, int > n); > +qemu_irq *qemu_allocate_irqs_with_trace(qemu_irq_handler handler, void > *opaque, > + int n, const char *targetFunc); > > /* > * Allocates a single IRQ. The irq is assigned with a handler, an opaque > * data and the interrupt number. > */ > -qemu_irq qemu_allocate_irq(qemu_irq_handler handler, void *opaque, int n); > - > +qemu_irq qemu_allocate_irq_with_trace(qemu_irq_handler handler, void > *opaque, > + int n, const char *targetFunc); > /* Extends an Array of IRQs. Old IRQs have their handlers and opaque data > * preserved. New IRQs are assigned the argument handler and opaque data. > */ > -qemu_irq *qemu_extend_irqs(qemu_irq *old, int n_old, qemu_irq_handler > handler, > - void *opaque, int n); > +qemu_irq *qemu_extend_irqs_with_trace(qemu_irq *old, int n_old, > + qemu_irq_handler handler, void > *opaque, > + int n, const char *targetFunc); > + > +/*Tracking irq function*/ > > void qemu_free_irqs(qemu_irq *s, int n); > void qemu_free_irq(qemu_irq irq); > diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h > index bafc311bfa..f6f4642ac3 100644 > --- a/include/hw/qdev-core.h > +++ b/include/hw/qdev-core.h > @@ -557,6 +557,20 @@ BusState *qdev_get_child_bus(DeviceState *dev, const > char *name); > > /*** Device API. ***/ > > +/*Tracking irq define*/ > + > +#define qdev_init_gpio_in(dev, handler, n) \ > + qdev_init_gpio_in_with_trace(dev, handler, n, #handler) > + > +#define qdev_init_gpio_in_named_with_opaque(dev, handler, opaque, name, > n) \ > + qdev_init_gpio_in_named_with_opaque_with_trace(dev, handler, opaque, > name, \ > + n, #handler) > + > +#define qdev_init_gpio_in_named(dev, handler, name, n) \ > + qdev_init_gpio_in_named_with_trace(dev, handler, name, n, #handler) > + > +/*Tracking irq define*/ > + > /** > * qdev_init_gpio_in: create an array of anonymous input GPIO lines > * @dev: Device to create input GPIOs for > @@ -574,7 +588,8 @@ BusState *qdev_get_child_bus(DeviceState *dev, const > char *name); > * See qdev_get_gpio_in() for how code that uses such a device can get > * hold of an input GPIO line to manipulate it. > */ > -void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n); > +void qdev_init_gpio_in_with_trace(DeviceState *dev, qemu_irq_handler > handler, > + int n, const char *target); > /** > * qdev_init_gpio_out: create an array of anonymous output GPIO lines > * @dev: Device to create output GPIOs for > @@ -622,11 +637,10 @@ void qdev_init_gpio_out_named(DeviceState *dev, > qemu_irq *pins, > * @name: Name of the GPIO input (must be unique for this device) > * @n: Number of GPIO lines in this input set > */ > -void qdev_init_gpio_in_named_with_opaque(DeviceState *dev, > +void qdev_init_gpio_in_named_with_opaque_with_trace(DeviceState *dev, > qemu_irq_handler handler, > - void *opaque, > - const char *name, int n); > - > + void *opaque, const char *name, > + int n, const char *target); > /** > * qdev_init_gpio_in_named: create an array of input GPIO lines > * for the specified device > @@ -634,11 +648,13 @@ void qdev_init_gpio_in_named_with_opaque(DeviceState > *dev, > * Like qdev_init_gpio_in_named_with_opaque(), but the opaque pointer > * passed to the handler is @dev (which is the most commonly desired > behaviour). > */ > -static inline void qdev_init_gpio_in_named(DeviceState *dev, > +static inline void qdev_init_gpio_in_named_with_trace(DeviceState *dev, > qemu_irq_handler handler, > - const char *name, int n) > + const char *name, int n, > + const char *target) > { > - qdev_init_gpio_in_named_with_opaque(dev, handler, dev, name, n); > + qdev_init_gpio_in_named_with_opaque_with_trace(dev, handler, dev, > + name, n, target); > } > > /** > -- > 2.17.1 > >
diff --git a/hw/core/irq.c b/hw/core/irq.c index 8a9cbdd556..ee32b58cec 100644 --- a/hw/core/irq.c +++ b/hw/core/irq.c @@ -26,6 +26,9 @@ #include "hw/irq.h" #include "qom/object.h" + +#include "trace.h" + DECLARE_INSTANCE_CHECKER(struct IRQState, IRQ, TYPE_IRQ) @@ -35,18 +38,24 @@ struct IRQState { qemu_irq_handler handler; void *opaque; int n; + const char *targetFunc; }; -void qemu_set_irq(qemu_irq irq, int level) +void qemu_set_irq_with_trace(qemu_irq irq, int level, const char *callFunc) { if (!irq) return; + const char *targetFunc = irq->targetFunc; + trace_irq_tracker(callFunc, targetFunc, irq->n, level); irq->handler(irq->opaque, irq->n, level); } -qemu_irq *qemu_extend_irqs(qemu_irq *old, int n_old, qemu_irq_handler handler, - void *opaque, int n) +/*Tracking irq function*/ + +qemu_irq *qemu_extend_irqs_with_trace(qemu_irq *old, int n_old, + qemu_irq_handler handler, void *opaque, + int n, const char *targetFunc) { qemu_irq *s; int i; @@ -56,17 +65,19 @@ qemu_irq *qemu_extend_irqs(qemu_irq *old, int n_old, qemu_irq_handler handler, } s = old ? g_renew(qemu_irq, old, n + n_old) : g_new(qemu_irq, n); for (i = n_old; i < n + n_old; i++) { - s[i] = qemu_allocate_irq(handler, opaque, i); + s[i] = qemu_allocate_irq_with_trace(handler, opaque, i, targetFunc); } return s; } -qemu_irq *qemu_allocate_irqs(qemu_irq_handler handler, void *opaque, int n) +qemu_irq *qemu_allocate_irqs_with_trace(qemu_irq_handler handler, void *opaque, + int n, const char *targetFunc) { - return qemu_extend_irqs(NULL, 0, handler, opaque, n); + return qemu_extend_irqs_with_trace(NULL, 0, handler, opaque, n, targetFunc); } -qemu_irq qemu_allocate_irq(qemu_irq_handler handler, void *opaque, int n) +qemu_irq qemu_allocate_irq_with_trace(qemu_irq_handler handler, void *opaque, + int n, const char *targetFunc) { struct IRQState *irq; @@ -74,10 +85,13 @@ qemu_irq qemu_allocate_irq(qemu_irq_handler handler, void *opaque, int n) irq->handler = handler; irq->opaque = opaque; irq->n = n; + irq->targetFunc = targetFunc; return irq; } +/*Tracking irq function*/ + void qemu_free_irqs(qemu_irq *s, int n) { int i; diff --git a/hw/core/qdev.c b/hw/core/qdev.c index cefc5eaa0a..e621de506d 100644 --- a/hw/core/qdev.c +++ b/hw/core/qdev.c @@ -450,17 +450,20 @@ static NamedGPIOList *qdev_get_named_gpio_list(DeviceState *dev, return ngl; } -void qdev_init_gpio_in_named_with_opaque(DeviceState *dev, +/*Tracking irq function*/ + +void qdev_init_gpio_in_named_with_opaque_with_trace(DeviceState *dev, qemu_irq_handler handler, - void *opaque, - const char *name, int n) + void *opaque, const char *name, + int n, const char *target) { int i; NamedGPIOList *gpio_list = qdev_get_named_gpio_list(dev, name); assert(gpio_list->num_out == 0 || !name); - gpio_list->in = qemu_extend_irqs(gpio_list->in, gpio_list->num_in, handler, - opaque, n); + gpio_list->in = qemu_extend_irqs_with_trace(gpio_list->in, + gpio_list->num_in, handler, + opaque, n, target); if (!name) { name = "unnamed-gpio-in"; @@ -476,11 +479,14 @@ void qdev_init_gpio_in_named_with_opaque(DeviceState *dev, gpio_list->num_in += n; } -void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n) +void qdev_init_gpio_in_with_trace(DeviceState *dev, qemu_irq_handler handler, + int n, const char *target) { - qdev_init_gpio_in_named(dev, handler, NULL, n); + qdev_init_gpio_in_named_with_trace(dev, handler, NULL, n, target); } +/*Tracking irq function*/ + void qdev_init_gpio_out_named(DeviceState *dev, qemu_irq *pins, const char *name, int n) { diff --git a/hw/core/trace-events b/hw/core/trace-events index 360ddeb2c8..a2a09d597f 100644 --- a/hw/core/trace-events +++ b/hw/core/trace-events @@ -34,3 +34,6 @@ clock_disconnect(const char *clk) "'%s'" clock_set(const char *clk, uint64_t old, uint64_t new) "'%s', %"PRIu64"Hz->%"PRIu64"Hz" clock_propagate(const char *clk) "'%s'" clock_update(const char *clk, const char *src, uint64_t hz, int cb) "'%s', src='%s', val=%"PRIu64"Hz cb=%d" + +# irq.c +irq_tracker(const char *call_function, const char *target_function, int number, int level) ": callFunction = %s, targetFunction = %s, n = %i, level = %i" diff --git a/include/hw/irq.h b/include/hw/irq.h index dc7abf199e..dfcdff14a1 100644 --- a/include/hw/irq.h +++ b/include/hw/irq.h @@ -5,40 +5,58 @@ #define TYPE_IRQ "irq" -void qemu_set_irq(qemu_irq irq, int level); +/*Tracking irq define*/ -static inline void qemu_irq_raise(qemu_irq irq) -{ - qemu_set_irq(irq, 1); -} +#define qemu_set_irq(irq, level) \ + qemu_set_irq_with_trace(irq, level, __func__) -static inline void qemu_irq_lower(qemu_irq irq) -{ - qemu_set_irq(irq, 0); -} +#define qemu_irq_raise(irq) \ + qemu_set_irq(irq, 1) -static inline void qemu_irq_pulse(qemu_irq irq) -{ - qemu_set_irq(irq, 1); +#define qemu_irq_lower(irq) \ qemu_set_irq(irq, 0); -} + +#define qemu_irq_pulse(irq) \ + do { \ + qemu_set_irq(irq, 1); \ + qemu_set_irq(irq, 0); \ + } while (0) + +#define qemu_allocate_irqs(handler, opaque, n) \ + qemu_allocate_irqs_with_trace(handler, opaque, n, #handler) + +#define qemu_allocate_irq(handler, opaque, n) \ + qemu_allocate_irq_with_trace(handler, opaque, n, #handler) + +#define qemu_extend_irqs(old, n_old, handler, opaque, n) \ + qemu_extend_irqs_with_trace(old, n_old, handler, opaque, n, __func__) + +/*Tracking irq define*/ + +/*Tracking irq function*/ + +void qemu_set_irq_with_trace(qemu_irq irq, int level, const char *callFunc); /* Returns an array of N IRQs. Each IRQ is assigned the argument handler and * opaque data. */ -qemu_irq *qemu_allocate_irqs(qemu_irq_handler handler, void *opaque, int n); +qemu_irq *qemu_allocate_irqs_with_trace(qemu_irq_handler handler, void *opaque, + int n, const char *targetFunc); /* * Allocates a single IRQ. The irq is assigned with a handler, an opaque * data and the interrupt number. */ -qemu_irq qemu_allocate_irq(qemu_irq_handler handler, void *opaque, int n); - +qemu_irq qemu_allocate_irq_with_trace(qemu_irq_handler handler, void *opaque, + int n, const char *targetFunc); /* Extends an Array of IRQs. Old IRQs have their handlers and opaque data * preserved. New IRQs are assigned the argument handler and opaque data. */ -qemu_irq *qemu_extend_irqs(qemu_irq *old, int n_old, qemu_irq_handler handler, - void *opaque, int n); +qemu_irq *qemu_extend_irqs_with_trace(qemu_irq *old, int n_old, + qemu_irq_handler handler, void *opaque, + int n, const char *targetFunc); + +/*Tracking irq function*/ void qemu_free_irqs(qemu_irq *s, int n); void qemu_free_irq(qemu_irq irq); diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h index bafc311bfa..f6f4642ac3 100644 --- a/include/hw/qdev-core.h +++ b/include/hw/qdev-core.h @@ -557,6 +557,20 @@ BusState *qdev_get_child_bus(DeviceState *dev, const char *name); /*** Device API. ***/ +/*Tracking irq define*/ + +#define qdev_init_gpio_in(dev, handler, n) \ + qdev_init_gpio_in_with_trace(dev, handler, n, #handler) + +#define qdev_init_gpio_in_named_with_opaque(dev, handler, opaque, name, n) \ + qdev_init_gpio_in_named_with_opaque_with_trace(dev, handler, opaque, name, \ + n, #handler) + +#define qdev_init_gpio_in_named(dev, handler, name, n) \ + qdev_init_gpio_in_named_with_trace(dev, handler, name, n, #handler) + +/*Tracking irq define*/ + /** * qdev_init_gpio_in: create an array of anonymous input GPIO lines * @dev: Device to create input GPIOs for @@ -574,7 +588,8 @@ BusState *qdev_get_child_bus(DeviceState *dev, const char *name); * See qdev_get_gpio_in() for how code that uses such a device can get * hold of an input GPIO line to manipulate it. */ -void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n); +void qdev_init_gpio_in_with_trace(DeviceState *dev, qemu_irq_handler handler, + int n, const char *target); /** * qdev_init_gpio_out: create an array of anonymous output GPIO lines * @dev: Device to create output GPIOs for @@ -622,11 +637,10 @@ void qdev_init_gpio_out_named(DeviceState *dev, qemu_irq *pins, * @name: Name of the GPIO input (must be unique for this device) * @n: Number of GPIO lines in this input set */ -void qdev_init_gpio_in_named_with_opaque(DeviceState *dev, +void qdev_init_gpio_in_named_with_opaque_with_trace(DeviceState *dev, qemu_irq_handler handler, - void *opaque, - const char *name, int n); - + void *opaque, const char *name, + int n, const char *target); /** * qdev_init_gpio_in_named: create an array of input GPIO lines * for the specified device @@ -634,11 +648,13 @@ void qdev_init_gpio_in_named_with_opaque(DeviceState *dev, * Like qdev_init_gpio_in_named_with_opaque(), but the opaque pointer * passed to the handler is @dev (which is the most commonly desired behaviour). */ -static inline void qdev_init_gpio_in_named(DeviceState *dev, +static inline void qdev_init_gpio_in_named_with_trace(DeviceState *dev, qemu_irq_handler handler, - const char *name, int n) + const char *name, int n, + const char *target) { - qdev_init_gpio_in_named_with_opaque(dev, handler, dev, name, n); + qdev_init_gpio_in_named_with_opaque_with_trace(dev, handler, dev, + name, n, target); } /**