The internal i8259 implementation has workaround logic for storing interrupt statistics since these are currently recorded at the PIC level (i.e. for all 16 interrupt lines) whilst being stored in the master i8259 device which only has 8 physical interrupt lines.
Move the get_statistics() implementation from the individual i8259 device to the containing PIC device in preparation for removing this hack. Note that this has a visible change to the "info pic" HMP monitor output since the named device displayed by "info irq" is now the PIC and not the individual i8259: Before (TCG): (qemu) info irq IRQ statistics for ioapic: 0: 68 4: 1 IRQ statistics for isa-i8259: 0: 68 4: 1 After (TCG): (qemu) info irq IRQ statistics for ioapic: 0: 47 4: 1 IRQ statistics for isa-i8259-pic: 0: 47 4: 1 Before (KVM): (qemu) info irq IRQ statistics for kvm-ioapic: 4: 1 IRQ statistics for kvm-i8259: 4: 1 After (KVM): (qemu) info irq IRQ statistics for kvm-ioapic: 1: 3 4: 1 IRQ statistics for kvm-i8259-pic: 1: 3 4: 1 Signed-off-by: Mark Cave-Ayland <[email protected]> Reviewed-by: Peter Maydell <[email protected]> --- include/hw/intc/i8259.h | 6 ++++++ include/hw/isa/i8259_internal.h | 1 - hw/i386/kvm/i8259.c | 7 +++++++ hw/intc/i8259.c | 7 +++++++ hw/intc/i8259_common.c | 27 ++++++++++++++++++--------- 5 files changed, 38 insertions(+), 10 deletions(-) diff --git a/include/hw/intc/i8259.h b/include/hw/intc/i8259.h index 87ccd55a4d..d51a7fde32 100644 --- a/include/hw/intc/i8259.h +++ b/include/hw/intc/i8259.h @@ -1,6 +1,8 @@ #ifndef HW_I8259_H #define HW_I8259_H +#include "hw/intc/intc.h" + /* i8259.c */ typedef struct I8259State I8259State; @@ -18,5 +20,9 @@ qemu_irq *i8259_init(ISABus *bus, qemu_irq parent_irq_in); qemu_irq *kvm_i8259_init(ISABus *bus); int pic_get_output(I8259State *s); int pic_read_irq(I8259State *s); +bool i8259_pic_get_statistics(InterruptStatsProvider *obj, + uint64_t **irq_counts, + unsigned int *nb_irqs); +void i8259_pic_print_info(InterruptStatsProvider *obj, GString *buf); #endif diff --git a/include/hw/isa/i8259_internal.h b/include/hw/isa/i8259_internal.h index dd255fac24..2807409eff 100644 --- a/include/hw/isa/i8259_internal.h +++ b/include/hw/isa/i8259_internal.h @@ -26,7 +26,6 @@ #define QEMU_I8259_INTERNAL_H #include "hw/isa/isa.h" -#include "hw/intc/intc.h" #include "hw/intc/i8259.h" #include "qom/object.h" diff --git a/hw/i386/kvm/i8259.c b/hw/i386/kvm/i8259.c index c51738dd44..b56e4fced4 100644 --- a/hw/i386/kvm/i8259.c +++ b/hw/i386/kvm/i8259.c @@ -223,9 +223,12 @@ static const Property kvm_i8259_pic_properties[] = { static void kvm_i8259_pic_class_init(ObjectClass *klass, const void *data) { DeviceClass *dc = DEVICE_CLASS(klass); + InterruptStatsProviderClass *ic = INTERRUPT_STATS_PROVIDER_CLASS(klass); dc->realize = kvm_i8259_pic_realize; device_class_set_props(dc, kvm_i8259_pic_properties); + ic->get_statistics = i8259_pic_get_statistics; + ic->print_info = i8259_pic_print_info; /* * Reason: must be wired to the ISA bus via the "bus" property */ @@ -246,6 +249,10 @@ static const TypeInfo kvm_i8259_type_infos[] = { .class_init = kvm_i8259_pic_class_init, .instance_init = kvm_i8259_pic_init, .instance_size = sizeof(KVMI8259PICState), + .interfaces = (const InterfaceInfo[]) { + { TYPE_INTERRUPT_STATS_PROVIDER }, + { } + }, }, }; diff --git a/hw/intc/i8259.c b/hw/intc/i8259.c index 5f90edbe60..842507f9f8 100644 --- a/hw/intc/i8259.c +++ b/hw/intc/i8259.c @@ -535,9 +535,12 @@ static const Property i8259_pic_properties[] = { static void i8259_pic_class_init(ObjectClass *klass, const void *data) { DeviceClass *dc = DEVICE_CLASS(klass); + InterruptStatsProviderClass *ic = INTERRUPT_STATS_PROVIDER_CLASS(klass); dc->realize = i8259_pic_realize; device_class_set_props(dc, i8259_pic_properties); + ic->get_statistics = i8259_pic_get_statistics; + ic->print_info = i8259_pic_print_info; /* * Reason: must be wired to the ISA bus via the "bus" property */ @@ -558,6 +561,10 @@ static const TypeInfo i8259_type_infos[] = { .class_init = i8259_pic_class_init, .instance_init = i8259_pic_init, .instance_size = sizeof(I8259PICState), + .interfaces = (const InterfaceInfo[]) { + { TYPE_INTERRUPT_STATS_PROVIDER }, + { } + }, }, }; diff --git a/hw/intc/i8259_common.c b/hw/intc/i8259_common.c index 5fa38fbc5f..684290fb2d 100644 --- a/hw/intc/i8259_common.c +++ b/hw/intc/i8259_common.c @@ -99,19 +99,28 @@ void i8259_stat_update_irq(int irq, int level) } } +bool i8259_pic_get_statistics(InterruptStatsProvider *obj, + uint64_t **irq_counts, + unsigned int *nb_irqs) +{ + *irq_counts = irq_count; + *nb_irqs = ARRAY_SIZE(irq_count); + + return true; +} + +void i8259_pic_print_info(InterruptStatsProvider *obj, GString *buf) +{ + /* No information for i8259-based PICs */ + return; +} + static bool i8259_common_get_statistics(InterruptStatsProvider *obj, uint64_t **irq_counts, unsigned int *nb_irqs) { - I8259CommonState *cs = I8259_COMMON(obj); - - if (cs->master) { - *irq_counts = irq_count; - *nb_irqs = ARRAY_SIZE(irq_count); - } else { - *irq_counts = NULL; - *nb_irqs = 0; - } + /* No statistics for individual i8259s */ + *nb_irqs = 0; return true; } -- 2.43.0
