From 1d5b128cbeeab638f772e88674f22e36b1b024e5 Mon Sep 17 00:00:00 2001 From: David Kiarie Date: Tue, 4 Oct 2016 07:03:28 +0300 Subject: hw/iommu: Fix problems reported by Coverity scan Signed-off-by: David Kiarie Message-Id: <1475553808-13285-2-git-send-email-davidkiarie4@gmail.com> Signed-off-by: Paolo Bonzini --- hw/i386/amd_iommu.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) (limited to 'hw') diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c index 023de526f6..47b79d9112 100644 --- a/hw/i386/amd_iommu.c +++ b/hw/i386/amd_iommu.c @@ -143,10 +143,10 @@ static void amdvi_assign_andq(AMDVIState *s, hwaddr addr, uint64_t val) static void amdvi_generate_msi_interrupt(AMDVIState *s) { - MSIMessage msg; - MemTxAttrs attrs; - - attrs.requester_id = pci_requester_id(&s->pci.dev); + MSIMessage msg = {}; + MemTxAttrs attrs = { + .requester_id = pci_requester_id(&s->pci.dev) + }; if (msi_enabled(&s->pci.dev)) { msg = msi_get_message(&s->pci.dev, 0); @@ -185,7 +185,7 @@ static void amdvi_setevent_bits(uint64_t *buffer, uint64_t value, int start, int length) { int index = start / 64, bitpos = start % 64; - uint64_t mask = ((1 << length) - 1) << bitpos; + uint64_t mask = MAKE_64BIT_MASK(start, length); buffer[index] &= ~mask; buffer[index] |= (value << bitpos) & mask; } @@ -333,8 +333,8 @@ static void amdvi_update_iotlb(AMDVIState *s, uint16_t devid, uint64_t gpa, IOMMUTLBEntry to_cache, uint16_t domid) { - AMDVIIOTLBEntry *entry = g_malloc(sizeof(*entry)); - uint64_t *key = g_malloc(sizeof(key)); + AMDVIIOTLBEntry *entry = g_new(AMDVIIOTLBEntry, 1); + uint64_t *key = g_new(uint64_t, 1); uint64_t gfn = gpa >> AMDVI_PAGE_SHIFT_4K; /* don't cache erroneous translations */ @@ -1135,6 +1135,7 @@ static void amdvi_reset(DeviceState *dev) static void amdvi_realize(DeviceState *dev, Error **err) { + int ret = 0; AMDVIState *s = AMD_IOMMU_DEVICE(dev); X86IOMMUState *x86_iommu = X86_IOMMU_DEVICE(dev); PCIBus *bus = PC_MACHINE(qdev_get_machine())->bus; @@ -1147,8 +1148,11 @@ static void amdvi_realize(DeviceState *dev, Error **err) object_property_set_bool(OBJECT(&s->pci), true, "realized", err); s->capab_offset = pci_add_capability(&s->pci.dev, AMDVI_CAPAB_ID_SEC, 0, AMDVI_CAPAB_SIZE); - pci_add_capability(&s->pci.dev, PCI_CAP_ID_MSI, 0, AMDVI_CAPAB_REG_SIZE); - pci_add_capability(&s->pci.dev, PCI_CAP_ID_HT, 0, AMDVI_CAPAB_REG_SIZE); + assert(s->capab_offset > 0); + ret = pci_add_capability(&s->pci.dev, PCI_CAP_ID_MSI, 0, AMDVI_CAPAB_REG_SIZE); + assert(ret > 0); + ret = pci_add_capability(&s->pci.dev, PCI_CAP_ID_HT, 0, AMDVI_CAPAB_REG_SIZE); + assert(ret > 0); /* set up MMIO */ memory_region_init_io(&s->mmio, OBJECT(s), &mmio_mem_ops, s, "amdvi-mmio", -- cgit v1.2.3-55-g7522 From 3cf294eebc98da6e2ff7976fcdf6a9b41984840e Mon Sep 17 00:00:00 2001 From: Junlian Bell Date: Mon, 26 Sep 2016 20:41:01 +0800 Subject: MC146818 RTC: coordinate guest clock base to destination host after migration qemu tracks guest time based on vector [base_rtc, last_update], in which last_update stands for a monotonic tick which is actually uptime of the host. according to rtc implementation codes of recent releases and upstream, after migration, the time base vector [base_rtc, last_update] isn't updated to coordinate with the destionation host, ie. qemu doesnt update last_update to uptime of the destination host. what problem have we got because of this bug? after migration, guest time may jump back to several days ago, that will make some critical business applications, such as lotus notes, malfunction. this patch is trying to fix the problem. first, when vmsave in progress, we rtc_update_time to refresh time stamp in cmos array, then during vmrestore, we rtc_set_time to update qemu base_rtc and last_update variable according to time stamp in cmos array. Signed-off-by: Junlian Bell Message-Id: <20160926124101.2364-1-zhongjun@sangfor.com.cn> Signed-off-by: Paolo Bonzini --- hw/timer/mc146818rtc.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'hw') diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c index ea625f25ce..da209d02f0 100644 --- a/hw/timer/mc146818rtc.c +++ b/hw/timer/mc146818rtc.c @@ -717,11 +717,18 @@ static void rtc_set_date_from_host(ISADevice *dev) rtc_set_cmos(s, &tm); } +static void rtc_pre_save(void *opaque) +{ + RTCState *s = opaque; + + rtc_update_time(s); +} + static int rtc_post_load(void *opaque, int version_id) { RTCState *s = opaque; - if (version_id <= 2) { + if (version_id <= 2 || rtc_clock == QEMU_CLOCK_REALTIME) { rtc_set_time(s); s->offset = 0; check_update_timer(s); @@ -764,6 +771,7 @@ static const VMStateDescription vmstate_rtc = { .name = "mc146818rtc", .version_id = 3, .minimum_version_id = 1, + .pre_save = rtc_pre_save, .post_load = rtc_post_load, .fields = (VMStateField[]) { VMSTATE_BUFFER(cmos_data, RTCState), -- cgit v1.2.3-55-g7522 From eabb5782f70b4a10975b24ccd7129929a05ac932 Mon Sep 17 00:00:00 2001 From: Peter Xu Date: Wed, 28 Sep 2016 21:03:39 +0800 Subject: hw/misc/edu: support MSI interrupt So now edu device can support both line or msi interrupt, depending on how user configures it. Signed-off-by: Peter Xu Message-Id: <1475067819-21413-1-git-send-email-peterx@redhat.com> Signed-off-by: Paolo Bonzini --- docs/specs/edu.txt | 7 ++++++- hw/misc/edu.c | 18 ++++++++++++++++-- 2 files changed, 22 insertions(+), 3 deletions(-) (limited to 'hw') diff --git a/docs/specs/edu.txt b/docs/specs/edu.txt index 7f8146780b..0876310809 100644 --- a/docs/specs/edu.txt +++ b/docs/specs/edu.txt @@ -52,7 +52,7 @@ size == 8 for the rest. 0x20 (RW) : status register, bitwise OR 0x01 -- computing factorial (RO) - 0x80 -- raise interrupt 0x01 after finishing factorial computation + 0x80 -- raise interrupt after finishing factorial computation 0x24 (RO) : interrupt status register It contains values which raised the interrupt (see interrupt raise @@ -87,6 +87,11 @@ An IRQ is generated when written to the interrupt raise register. The value appears in interrupt status register when the interrupt is raised and has to be written to the interrupt acknowledge register to lower it. +The device supports both INTx and MSI interrupt. By default, INTx is +used. Even if the driver disabled INTx and only uses MSI, it still +needs to update the acknowledge register at the end of the IRQ handler +routine. + DMA controller -------------- One has to specify, source, destination, size, and start the transfer. One diff --git a/hw/misc/edu.c b/hw/misc/edu.c index 888ba49a0e..401039c100 100644 --- a/hw/misc/edu.c +++ b/hw/misc/edu.c @@ -24,6 +24,7 @@ #include "qemu/osdep.h" #include "hw/pci/pci.h" +#include "hw/pci/msi.h" #include "qemu/timer.h" #include "qemu/main-loop.h" /* iothread mutex */ #include "qapi/visitor.h" @@ -69,11 +70,20 @@ typedef struct { uint64_t dma_mask; } EduState; +static bool edu_msi_enabled(EduState *edu) +{ + return msi_enabled(&edu->pdev); +} + static void edu_raise_irq(EduState *edu, uint32_t val) { edu->irq_status |= val; if (edu->irq_status) { - pci_set_irq(&edu->pdev, 1); + if (edu_msi_enabled(edu)) { + msi_notify(&edu->pdev, 0); + } else { + pci_set_irq(&edu->pdev, 1); + } } } @@ -81,7 +91,7 @@ static void edu_lower_irq(EduState *edu, uint32_t val) { edu->irq_status &= ~val; - if (!edu->irq_status) { + if (!edu->irq_status && !edu_msi_enabled(edu)) { pci_set_irq(&edu->pdev, 0); } } @@ -342,6 +352,10 @@ static void pci_edu_realize(PCIDevice *pdev, Error **errp) pci_config_set_interrupt_pin(pci_conf, 1); + if (msi_init(pdev, 0, 1, true, false, errp)) { + return; + } + memory_region_init_io(&edu->mmio, OBJECT(edu), &edu_mmio_ops, edu, "edu-mmio", 1 << 20); pci_register_bar(pdev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &edu->mmio); -- cgit v1.2.3-55-g7522 From 120e512b7f753f2e2978b47344f329c2595284de Mon Sep 17 00:00:00 2001 From: Hervé Poussineau Date: Mon, 26 Sep 2016 22:23:23 +0200 Subject: intc: add an interface to gather statistics/informations on interrupt controllers This interface will be used by HMP commands 'info irq' and 'info pic'. Signed-off-by: Hervé Poussineau Message-Id: <1474921408-24710-2-git-send-email-hpoussin@reactos.org> Signed-off-by: Paolo Bonzini --- hw/intc/Makefile.objs | 1 + hw/intc/intc.c | 41 +++++++++++++++++++++++++++++++++++++++++ include/hw/intc/intc.h | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 75 insertions(+) create mode 100644 hw/intc/intc.c create mode 100644 include/hw/intc/intc.h (limited to 'hw') diff --git a/hw/intc/Makefile.objs b/hw/intc/Makefile.objs index 05ec21b21e..f24c837118 100644 --- a/hw/intc/Makefile.objs +++ b/hw/intc/Makefile.objs @@ -17,6 +17,7 @@ common-obj-$(CONFIG_ARM_GIC) += arm_gicv3.o common-obj-$(CONFIG_ARM_GIC) += arm_gicv3_dist.o common-obj-$(CONFIG_ARM_GIC) += arm_gicv3_redist.o common-obj-$(CONFIG_OPENPIC) += openpic.o +common-obj-y += intc.o obj-$(CONFIG_APIC) += apic.o apic_common.o obj-$(CONFIG_ARM_GIC_KVM) += arm_gic_kvm.o diff --git a/hw/intc/intc.c b/hw/intc/intc.c new file mode 100644 index 0000000000..2e1e29e753 --- /dev/null +++ b/hw/intc/intc.c @@ -0,0 +1,41 @@ +/* + * QEMU Generic Interrupt Controller + * + * Copyright (c) 2016 Hervé Poussineau + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "qemu/osdep.h" +#include "hw/intc/intc.h" +#include "qemu/module.h" + +static const TypeInfo intctrl_info = { + .name = TYPE_INTERRUPT_STATS_PROVIDER, + .parent = TYPE_INTERFACE, + .class_size = sizeof(InterruptStatsProviderClass), +}; + +static void intc_register_types(void) +{ + type_register_static(&intctrl_info); +} + +type_init(intc_register_types) + diff --git a/include/hw/intc/intc.h b/include/hw/intc/intc.h new file mode 100644 index 0000000000..27d9828943 --- /dev/null +++ b/include/hw/intc/intc.h @@ -0,0 +1,33 @@ +#ifndef INTC_H +#define INTC_H + +#include "qom/object.h" + +#define TYPE_INTERRUPT_STATS_PROVIDER "intctrl" + +#define INTERRUPT_STATS_PROVIDER_CLASS(klass) \ + OBJECT_CLASS_CHECK(InterruptStatsProviderClass, (klass), \ + TYPE_INTERRUPT_STATS_PROVIDER) +#define INTERRUPT_STATS_PROVIDER_GET_CLASS(obj) \ + OBJECT_GET_CLASS(InterruptStatsProviderClass, (obj), \ + TYPE_INTERRUPT_STATS_PROVIDER) +#define INTERRUPT_STATS_PROVIDER(obj) \ + INTERFACE_CHECK(InterruptStatsProvider, (obj), \ + TYPE_INTERRUPT_STATS_PROVIDER) + +typedef struct InterruptStatsProvider { + Object parent; +} InterruptStatsProvider; + +typedef struct InterruptStatsProviderClass { + InterfaceClass parent; + + /* The returned pointer and statistics must remain valid until + * the BQL is next dropped. + */ + bool (*get_statistics)(InterruptStatsProvider *obj, uint64_t **irq_counts, + unsigned int *nb_irqs); + void (*print_info)(InterruptStatsProvider *obj, Monitor *mon); +} InterruptStatsProviderClass; + +#endif -- cgit v1.2.3-55-g7522 From 4f2e39e10360380862ae388424c129ce56ec8ae9 Mon Sep 17 00:00:00 2001 From: Hervé Poussineau Date: Mon, 26 Sep 2016 22:23:24 +0200 Subject: intc/i8259: implement InterruptStatsProvider interface Signed-off-by: Hervé Poussineau Message-Id: <1474921408-24710-3-git-send-email-hpoussin@reactos.org> Signed-off-by: Paolo Bonzini --- hw/intc/i8259.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) (limited to 'hw') diff --git a/hw/intc/i8259.c b/hw/intc/i8259.c index c2607a5868..75c8d22518 100644 --- a/hw/intc/i8259.c +++ b/hw/intc/i8259.c @@ -29,6 +29,7 @@ #include "qemu/timer.h" #include "qemu/log.h" #include "hw/isa/i8259_internal.h" +#include "hw/intc/intc.h" /* debug PIC */ //#define DEBUG_PIC @@ -251,6 +252,35 @@ static void pic_reset(DeviceState *dev) pic_init_reset(s); } +static bool pic_get_statistics(InterruptStatsProvider *obj, + uint64_t **irq_counts, unsigned int *nb_irqs) +{ + PICCommonState *s = PIC_COMMON(obj); + + if (s->master) { +#ifdef DEBUG_IRQ_COUNT + *irq_counts = irq_count; + *nb_irqs = ARRAY_SIZE(irq_count); +#else + return false; +#endif + } else { + *irq_counts = NULL; + *nb_irqs = 0; + } + return true; +} + +static void pic_print_info(InterruptStatsProvider *obj, Monitor *mon) +{ + PICCommonState *s = PIC_COMMON(obj); + monitor_printf(mon, "pic%d: irr=%02x imr=%02x isr=%02x hprio=%d " + "irq_base=%02x rr_sel=%d elcr=%02x fnm=%d\n", + s->master ? 0 : 1, s->irr, s->imr, s->isr, s->priority_add, + s->irq_base, s->read_reg_select, s->elcr, + s->special_fully_nested_mode); +} + static void pic_ioport_write(void *opaque, hwaddr addr64, uint64_t val64, unsigned size) { @@ -503,10 +533,13 @@ static void i8259_class_init(ObjectClass *klass, void *data) { PICClass *k = PIC_CLASS(klass); DeviceClass *dc = DEVICE_CLASS(klass); + InterruptStatsProviderClass *ic = INTERRUPT_STATS_PROVIDER_CLASS(klass); k->parent_realize = dc->realize; dc->realize = pic_realize; dc->reset = pic_reset; + ic->get_statistics = pic_get_statistics; + ic->print_info = pic_print_info; } static const TypeInfo i8259_info = { @@ -515,6 +548,10 @@ static const TypeInfo i8259_info = { .parent = TYPE_PIC_COMMON, .class_init = i8259_class_init, .class_size = sizeof(PICClass), + .interfaces = (InterfaceInfo[]) { + { TYPE_INTERRUPT_STATS_PROVIDER }, + { } + }, }; static void pic_register_types(void) -- cgit v1.2.3-55-g7522 From 148fbe950454a7faf9ffae1763a3a185fcc7233e Mon Sep 17 00:00:00 2001 From: Hervé Poussineau Date: Mon, 26 Sep 2016 22:23:25 +0200 Subject: intc/slavio_intctl: implement InterruptStatsProvider interface Acked-by: Artyom Tarasenko Signed-off-by: Hervé Poussineau Message-Id: <1474921408-24710-4-git-send-email-hpoussin@reactos.org> Signed-off-by: Paolo Bonzini --- hw/intc/slavio_intctl.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) (limited to 'hw') diff --git a/hw/intc/slavio_intctl.c b/hw/intc/slavio_intctl.c index e82e893628..a9acb647cc 100644 --- a/hw/intc/slavio_intctl.c +++ b/hw/intc/slavio_intctl.c @@ -26,6 +26,7 @@ #include "hw/sparc/sun4m.h" #include "monitor/monitor.h" #include "hw/sysbus.h" +#include "hw/intc/intc.h" #include "trace.h" //#define DEBUG_IRQ_COUNT @@ -418,6 +419,31 @@ static void slavio_intctl_reset(DeviceState *d) slavio_check_interrupts(s, 0); } +#ifdef DEBUG_IRQ_COUNT +static bool slavio_intctl_get_statistics(InterruptStatsProvider *obj, + uint64_t **irq_counts, + unsigned int *nb_irqs) +{ + SLAVIO_INTCTLState *s = SLAVIO_INTCTL(obj); + *irq_counts = s->irq_count; + *nb_irqs = ARRAY_SIZE(s->irq_count); + return true; +} +#endif + +static void slavio_intctl_print_info(InterruptStatsProvider *obj, Monitor *mon) +{ + SLAVIO_INTCTLState *s = SLAVIO_INTCTL(obj); + int i; + + for (i = 0; i < MAX_CPUS; i++) { + monitor_printf(mon, "per-cpu %d: pending 0x%08x\n", i, + s->slaves[i].intreg_pending); + } + monitor_printf(mon, "master: pending 0x%08x, disabled 0x%08x\n", + s->intregm_pending, s->intregm_disabled); +} + static void slavio_intctl_init(Object *obj) { DeviceState *dev = DEVICE(obj); @@ -449,9 +475,14 @@ static void slavio_intctl_init(Object *obj) static void slavio_intctl_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); + InterruptStatsProviderClass *ic = INTERRUPT_STATS_PROVIDER_CLASS(klass); dc->reset = slavio_intctl_reset; dc->vmsd = &vmstate_intctl; +#ifdef DEBUG_IRQ_COUNT + ic->get_statistics = slavio_intctl_get_statistics; +#endif + ic->print_info = slavio_intctl_print_info; } static const TypeInfo slavio_intctl_info = { @@ -460,6 +491,10 @@ static const TypeInfo slavio_intctl_info = { .instance_size = sizeof(SLAVIO_INTCTLState), .instance_init = slavio_intctl_init, .class_init = slavio_intctl_class_init, + .interfaces = (InterfaceInfo[]) { + { TYPE_INTERRUPT_STATS_PROVIDER }, + { } + }, }; static void slavio_intctl_register_types(void) -- cgit v1.2.3-55-g7522 From 7c468ec54cf1b077022f870e211c41966bf58a2f Mon Sep 17 00:00:00 2001 From: Hervé Poussineau Date: Mon, 26 Sep 2016 22:23:26 +0200 Subject: intc/lm32_pic: implement InterruptStatsProvider interface We have to change the vmstate version due to changes in statistics counters. Signed-off-by: Hervé Poussineau Message-Id: <1474921408-24710-5-git-send-email-hpoussin@reactos.org> Signed-off-by: Paolo Bonzini --- hw/intc/lm32_pic.c | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) (limited to 'hw') diff --git a/hw/intc/lm32_pic.c b/hw/intc/lm32_pic.c index 3dad01c5ba..c045b99e32 100644 --- a/hw/intc/lm32_pic.c +++ b/hw/intc/lm32_pic.c @@ -25,6 +25,7 @@ #include "hw/sysbus.h" #include "trace.h" #include "hw/lm32/lm32_pic.h" +#include "hw/intc/intc.h" #define TYPE_LM32_PIC "lm32-pic" #define LM32_PIC(obj) OBJECT_CHECK(LM32PicState, (obj), TYPE_LM32_PIC) @@ -38,7 +39,7 @@ struct LM32PicState { uint32_t irq_state; /* statistics */ - uint32_t stats_irq_count[32]; + uint64_t stats_irq_count[32]; }; typedef struct LM32PicState LM32PicState; @@ -152,6 +153,22 @@ static void pic_reset(DeviceState *d) } } +static bool lm32_get_statistics(InterruptStatsProvider *obj, + uint64_t **irq_counts, unsigned int *nb_irqs) +{ + LM32PicState *s = LM32_PIC(obj); + *irq_counts = s->stats_irq_count; + *nb_irqs = ARRAY_SIZE(s->stats_irq_count); + return true; +} + +static void lm32_print_info(InterruptStatsProvider *obj, Monitor *mon) +{ + LM32PicState *s = LM32_PIC(obj); + monitor_printf(mon, "lm32-pic: im=%08x ip=%08x irq_state=%08x\n", + s->im, s->ip, s->irq_state); +} + static void lm32_pic_init(Object *obj) { DeviceState *dev = DEVICE(obj); @@ -166,13 +183,13 @@ static void lm32_pic_init(Object *obj) static const VMStateDescription vmstate_lm32_pic = { .name = "lm32-pic", - .version_id = 1, - .minimum_version_id = 1, + .version_id = 2, + .minimum_version_id = 2, .fields = (VMStateField[]) { VMSTATE_UINT32(im, LM32PicState), VMSTATE_UINT32(ip, LM32PicState), VMSTATE_UINT32(irq_state, LM32PicState), - VMSTATE_UINT32_ARRAY(stats_irq_count, LM32PicState, 32), + VMSTATE_UINT64_ARRAY(stats_irq_count, LM32PicState, 32), VMSTATE_END_OF_LIST() } }; @@ -180,9 +197,12 @@ static const VMStateDescription vmstate_lm32_pic = { static void lm32_pic_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); + InterruptStatsProviderClass *ic = INTERRUPT_STATS_PROVIDER_CLASS(klass); dc->reset = pic_reset; dc->vmsd = &vmstate_lm32_pic; + ic->get_statistics = lm32_get_statistics; + ic->print_info = lm32_print_info; } static const TypeInfo lm32_pic_info = { @@ -191,6 +211,10 @@ static const TypeInfo lm32_pic_info = { .instance_size = sizeof(LM32PicState), .instance_init = lm32_pic_init, .class_init = lm32_pic_class_init, + .interfaces = (InterfaceInfo[]) { + { TYPE_INTERRUPT_STATS_PROVIDER }, + { } + }, }; static void lm32_pic_register_types(void) -- cgit v1.2.3-55-g7522 From 61b97833b38122e22c7af08685277681c6b79653 Mon Sep 17 00:00:00 2001 From: Hervé Poussineau Date: Mon, 26 Sep 2016 22:23:27 +0200 Subject: intc: make HMP 'info irq' and 'info pic' commands use InterruptStatsProvider interface Signed-off-by: Hervé Poussineau Message-Id: <1474921408-24710-6-git-send-email-hpoussin@reactos.org> Signed-off-by: Paolo Bonzini --- hmp-commands-info.hx | 12 --------- hmp.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++ hmp.h | 2 ++ hw/intc/i8259.c | 36 ------------------------- hw/intc/lm32_pic.c | 31 ---------------------- hw/intc/slavio_intctl.c | 32 ----------------------- hw/sparc/sun4m.c | 15 +---------- include/hw/i386/pc.h | 2 -- include/hw/lm32/lm32_pic.h | 3 --- include/hw/sparc/sun4m.h | 8 ------ monitor.c | 6 ----- 11 files changed, 68 insertions(+), 144 deletions(-) (limited to 'hw') diff --git a/hmp-commands-info.hx b/hmp-commands-info.hx index 19729e55ae..6a7c476065 100644 --- a/hmp-commands-info.hx +++ b/hmp-commands-info.hx @@ -179,13 +179,7 @@ ETEXI .args_type = "", .params = "", .help = "show the interrupts statistics (if available)", -#ifdef TARGET_SPARC - .cmd = sun4m_hmp_info_irq, -#elif defined(TARGET_LM32) - .cmd = lm32_hmp_info_irq, -#else .cmd = hmp_info_irq, -#endif }, STEXI @@ -199,13 +193,7 @@ ETEXI .args_type = "", .params = "", .help = "show i8259 (PIC) state", -#ifdef TARGET_SPARC - .cmd = sun4m_hmp_info_pic, -#elif defined(TARGET_LM32) - .cmd = lm32_hmp_info_pic, -#else .cmd = hmp_info_pic, -#endif }, #endif diff --git a/hmp.c b/hmp.c index 336e7bf076..a79e7f94b7 100644 --- a/hmp.c +++ b/hmp.c @@ -36,6 +36,7 @@ #include "qemu-io.h" #include "qemu/cutils.h" #include "qemu/error-report.h" +#include "hw/intc/intc.h" #ifdef CONFIG_SPICE #include @@ -787,6 +788,70 @@ static void hmp_info_pci_device(Monitor *mon, const PciDeviceInfo *dev) } } +static int hmp_info_irq_foreach(Object *obj, void *opaque) +{ + InterruptStatsProvider *intc; + InterruptStatsProviderClass *k; + Monitor *mon = opaque; + + if (object_dynamic_cast(obj, TYPE_INTERRUPT_STATS_PROVIDER)) { + intc = INTERRUPT_STATS_PROVIDER(obj); + k = INTERRUPT_STATS_PROVIDER_GET_CLASS(obj); + uint64_t *irq_counts; + unsigned int nb_irqs, i; + if (k->get_statistics && + k->get_statistics(intc, &irq_counts, &nb_irqs)) { + if (nb_irqs > 0) { + monitor_printf(mon, "IRQ statistics for %s:\n", + object_get_typename(obj)); + for (i = 0; i < nb_irqs; i++) { + if (irq_counts[i] > 0) { + monitor_printf(mon, "%2d: %" PRId64 "\n", i, + irq_counts[i]); + } + } + } + } else { + monitor_printf(mon, "IRQ statistics not available for %s.\n", + object_get_typename(obj)); + } + } + + return 0; +} + +void hmp_info_irq(Monitor *mon, const QDict *qdict) +{ + object_child_foreach_recursive(object_get_root(), + hmp_info_irq_foreach, mon); +} + +static int hmp_info_pic_foreach(Object *obj, void *opaque) +{ + InterruptStatsProvider *intc; + InterruptStatsProviderClass *k; + Monitor *mon = opaque; + + if (object_dynamic_cast(obj, TYPE_INTERRUPT_STATS_PROVIDER)) { + intc = INTERRUPT_STATS_PROVIDER(obj); + k = INTERRUPT_STATS_PROVIDER_GET_CLASS(obj); + if (k->print_info) { + k->print_info(intc, mon); + } else { + monitor_printf(mon, "Interrupt controller information not available for %s.\n", + object_get_typename(obj)); + } + } + + return 0; +} + +void hmp_info_pic(Monitor *mon, const QDict *qdict) +{ + object_child_foreach_recursive(object_get_root(), + hmp_info_pic_foreach, mon); +} + void hmp_info_pci(Monitor *mon, const QDict *qdict) { PciInfoList *info_list, *info; diff --git a/hmp.h b/hmp.h index 0876ec03a1..184769c13f 100644 --- a/hmp.h +++ b/hmp.h @@ -36,6 +36,8 @@ void hmp_info_blockstats(Monitor *mon, const QDict *qdict); void hmp_info_vnc(Monitor *mon, const QDict *qdict); void hmp_info_spice(Monitor *mon, const QDict *qdict); void hmp_info_balloon(Monitor *mon, const QDict *qdict); +void hmp_info_irq(Monitor *mon, const QDict *qdict); +void hmp_info_pic(Monitor *mon, const QDict *qdict); void hmp_info_pci(Monitor *mon, const QDict *qdict); void hmp_info_block_jobs(Monitor *mon, const QDict *qdict); void hmp_info_tpm(Monitor *mon, const QDict *qdict); diff --git a/hw/intc/i8259.c b/hw/intc/i8259.c index 75c8d22518..fe9ecd6bd4 100644 --- a/hw/intc/i8259.c +++ b/hw/intc/i8259.c @@ -461,42 +461,6 @@ static void pic_realize(DeviceState *dev, Error **errp) pc->parent_realize(dev, errp); } -void hmp_info_pic(Monitor *mon, const QDict *qdict) -{ - int i; - PICCommonState *s; - - if (!isa_pic) { - return; - } - for (i = 0; i < 2; i++) { - s = i == 0 ? PIC_COMMON(isa_pic) : slave_pic; - monitor_printf(mon, "pic%d: irr=%02x imr=%02x isr=%02x hprio=%d " - "irq_base=%02x rr_sel=%d elcr=%02x fnm=%d\n", - i, s->irr, s->imr, s->isr, s->priority_add, - s->irq_base, s->read_reg_select, s->elcr, - s->special_fully_nested_mode); - } -} - -void hmp_info_irq(Monitor *mon, const QDict *qdict) -{ -#ifndef DEBUG_IRQ_COUNT - monitor_printf(mon, "irq statistic code not compiled.\n"); -#else - int i; - int64_t count; - - monitor_printf(mon, "IRQ statistics:\n"); - for (i = 0; i < 16; i++) { - count = irq_count[i]; - if (count > 0) { - monitor_printf(mon, "%2d: %" PRId64 "\n", i, count); - } - } -#endif -} - qemu_irq *i8259_init(ISABus *bus, qemu_irq parent_irq) { qemu_irq *irq_set; diff --git a/hw/intc/lm32_pic.c b/hw/intc/lm32_pic.c index c045b99e32..09e15115fb 100644 --- a/hw/intc/lm32_pic.c +++ b/hw/intc/lm32_pic.c @@ -43,35 +43,6 @@ struct LM32PicState { }; typedef struct LM32PicState LM32PicState; -static LM32PicState *pic; -void lm32_hmp_info_pic(Monitor *mon, const QDict *qdict) -{ - if (pic == NULL) { - return; - } - - monitor_printf(mon, "lm32-pic: im=%08x ip=%08x irq_state=%08x\n", - pic->im, pic->ip, pic->irq_state); -} - -void lm32_hmp_info_irq(Monitor *mon, const QDict *qdict) -{ - int i; - uint32_t count; - - if (pic == NULL) { - return; - } - - monitor_printf(mon, "IRQ statistics:\n"); - for (i = 0; i < 32; i++) { - count = pic->stats_irq_count[i]; - if (count > 0) { - monitor_printf(mon, "%2d: %u\n", i, count); - } - } -} - static void update_irq(LM32PicState *s) { s->ip |= s->irq_state; @@ -177,8 +148,6 @@ static void lm32_pic_init(Object *obj) qdev_init_gpio_in(dev, irq_handler, 32); sysbus_init_irq(sbd, &s->parent_irq); - - pic = s; } static const VMStateDescription vmstate_lm32_pic = { diff --git a/hw/intc/slavio_intctl.c b/hw/intc/slavio_intctl.c index a9acb647cc..84e0bee4a9 100644 --- a/hw/intc/slavio_intctl.c +++ b/hw/intc/slavio_intctl.c @@ -211,38 +211,6 @@ static const MemoryRegionOps slavio_intctlm_mem_ops = { }, }; -void slavio_pic_info(Monitor *mon, DeviceState *dev) -{ - SLAVIO_INTCTLState *s = SLAVIO_INTCTL(dev); - int i; - - for (i = 0; i < MAX_CPUS; i++) { - monitor_printf(mon, "per-cpu %d: pending 0x%08x\n", i, - s->slaves[i].intreg_pending); - } - monitor_printf(mon, "master: pending 0x%08x, disabled 0x%08x\n", - s->intregm_pending, s->intregm_disabled); -} - -void slavio_irq_info(Monitor *mon, DeviceState *dev) -{ -#ifndef DEBUG_IRQ_COUNT - monitor_printf(mon, "irq statistic code not compiled.\n"); -#else - SLAVIO_INTCTLState *s = SLAVIO_INTCTL(dev); - int i; - int64_t count; - - s = SLAVIO_INTCTL(dev); - monitor_printf(mon, "IRQ statistics:\n"); - for (i = 0; i < 32; i++) { - count = s->irq_count[i]; - if (count > 0) - monitor_printf(mon, "%2d: %" PRId64 "\n", i, count); - } -#endif -} - static const uint32_t intbit_to_level[] = { 2, 3, 5, 7, 9, 11, 13, 2, 3, 5, 7, 9, 11, 13, 12, 12, 6, 13, 4, 10, 8, 9, 11, 0, 0, 0, 0, 15, 15, 15, 15, 0, diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c index 478fda8209..b3915e4fd6 100644 --- a/hw/sparc/sun4m.c +++ b/hw/sparc/sun4m.c @@ -159,20 +159,6 @@ static void nvram_init(Nvram *nvram, uint8_t *macaddr, } } -static DeviceState *slavio_intctl; - -void sun4m_hmp_info_pic(Monitor *mon, const QDict *qdict) -{ - if (slavio_intctl) - slavio_pic_info(mon, slavio_intctl); -} - -void sun4m_hmp_info_irq(Monitor *mon, const QDict *qdict) -{ - if (slavio_intctl) - slavio_irq_info(mon, slavio_intctl); -} - void cpu_check_irqs(CPUSPARCState *env) { CPUState *cs; @@ -873,6 +859,7 @@ static void dummy_fdc_tc(void *opaque, int irq, int level) static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, MachineState *machine) { + DeviceState *slavio_intctl; const char *cpu_model = machine->cpu_model; unsigned int i; void *iommu, *espdma, *ledma, *nvram; diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h index 47bdf10cfd..142b57f753 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -181,8 +181,6 @@ qemu_irq *i8259_init(ISABus *bus, qemu_irq parent_irq); qemu_irq *kvm_i8259_init(ISABus *bus); int pic_read_irq(DeviceState *d); int pic_get_output(DeviceState *d); -void hmp_info_pic(Monitor *mon, const QDict *qdict); -void hmp_info_irq(Monitor *mon, const QDict *qdict); /* ioapic.c */ diff --git a/include/hw/lm32/lm32_pic.h b/include/hw/lm32/lm32_pic.h index 189fa386f7..e6479b8f63 100644 --- a/include/hw/lm32/lm32_pic.h +++ b/include/hw/lm32/lm32_pic.h @@ -8,7 +8,4 @@ uint32_t lm32_pic_get_im(DeviceState *d); void lm32_pic_set_ip(DeviceState *d, uint32_t ip); void lm32_pic_set_im(DeviceState *d, uint32_t im); -void lm32_hmp_info_pic(Monitor *mon, const QDict *qdict); -void lm32_hmp_info_irq(Monitor *mon, const QDict *qdict); - #endif /* QEMU_HW_LM32_PIC_H */ diff --git a/include/hw/sparc/sun4m.h b/include/hw/sparc/sun4m.h index 9c17425a43..580d87b252 100644 --- a/include/hw/sparc/sun4m.h +++ b/include/hw/sparc/sun4m.h @@ -24,14 +24,6 @@ static inline void sparc_iommu_memory_write(void *opaque, sparc_iommu_memory_rw(opaque, addr, buf, len, 1); } -/* slavio_intctl.c */ -void slavio_pic_info(Monitor *mon, DeviceState *dev); -void slavio_irq_info(Monitor *mon, DeviceState *dev); - -/* sun4m.c */ -void sun4m_hmp_info_pic(Monitor *mon, const QDict *qdict); -void sun4m_hmp_info_irq(Monitor *mon, const QDict *qdict); - /* sparc32_dma.c */ #include "hw/sparc/sparc32_dma.h" diff --git a/monitor.c b/monitor.c index 83c4edfce0..d26c3bcfcf 100644 --- a/monitor.c +++ b/monitor.c @@ -81,12 +81,6 @@ #include "qemu/cutils.h" #include "qapi/qmp/dispatch.h" -/* for hmp_info_irq/pic */ -#if defined(TARGET_SPARC) -#include "hw/sparc/sun4m.h" -#endif -#include "hw/lm32/lm32_pic.h" - #if defined(TARGET_S390X) #include "hw/s390x/storage-keys.h" #endif -- cgit v1.2.3-55-g7522 From 25a8535943b456954eeb82eb7d1f53d2b4f168e6 Mon Sep 17 00:00:00 2001 From: Hervé Poussineau Date: Sun, 2 Oct 2016 21:44:27 +0200 Subject: i8259: give ISA device when registering ISA ioports Signed-off-by: Hervé Poussineau Message-Id: <1475437467-22781-1-git-send-email-hpoussin@reactos.org> Signed-off-by: Paolo Bonzini --- hw/intc/i8259_common.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'hw') diff --git a/hw/intc/i8259_common.c b/hw/intc/i8259_common.c index 3a850b0c66..d9a5e8b217 100644 --- a/hw/intc/i8259_common.c +++ b/hw/intc/i8259_common.c @@ -70,10 +70,11 @@ static int pic_dispatch_post_load(void *opaque, int version_id) static void pic_common_realize(DeviceState *dev, Error **errp) { PICCommonState *s = PIC_COMMON(dev); + ISADevice *isa = ISA_DEVICE(dev); - isa_register_ioport(NULL, &s->base_io, s->iobase); + isa_register_ioport(isa, &s->base_io, s->iobase); if (s->elcr_addr != -1) { - isa_register_ioport(NULL, &s->elcr_io, s->elcr_addr); + isa_register_ioport(isa, &s->elcr_io, s->elcr_addr); } qdev_set_legacy_instance_id(dev, s->iobase, 1); -- cgit v1.2.3-55-g7522