From 3d0db3e74d818ba43c62cdfb3220e551f4f5ae37 Mon Sep 17 00:00:00 2001 From: Greg Kurz Date: Thu, 25 Feb 2016 12:08:00 +0100 Subject: [PATCH 1/8] spapr_rng: disable hotpluggability It is currently possible to hotplug a spapr_rng device but QEMU crashes when we try to hot unplug: ERROR:hw/core/qdev.c:295:qdev_unplug: assertion failed: (hotplug_ctrl) Aborted This happens because spapr_rng isn't plugged to any bus and sPAPR does not provide hotplug support for it: qdev_get_hotplug_handler() hence return NULL and we hit the assertion. And anyway, it doesn't make much sense to unplug this device since hcalls cannot be unregistered. Even the idea of hotplugging a RNG device instead of declaring it on the QEMU command line looks weird. This patch simply disables hotpluggability for the spapr-rng class. Signed-off-by: Greg Kurz Reviewed-by: Thomas Huth Signed-off-by: David Gibson --- hw/ppc/spapr_rng.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/ppc/spapr_rng.c b/hw/ppc/spapr_rng.c index 8484fcf54774..a39d472b66fd 100644 --- a/hw/ppc/spapr_rng.c +++ b/hw/ppc/spapr_rng.c @@ -170,6 +170,7 @@ static void spapr_rng_class_init(ObjectClass *oc, void *data) dc->realize = spapr_rng_realize; set_bit(DEVICE_CATEGORY_MISC, dc->categories); dc->props = spapr_rng_properties; + dc->hotpluggable = false; } static const TypeInfo spapr_rng_info = { From d4a63ac8b19eb208465f27fde63f3cff7018fdfd Mon Sep 17 00:00:00 2001 From: Greg Kurz Date: Thu, 25 Feb 2016 19:02:12 +0100 Subject: [PATCH 2/8] spapr_pci: kill useless variable in rtas_ibm_change_msi() The num local variable is initialized to zero and has no writer. Signed-off-by: Greg Kurz Signed-off-by: David Gibson --- hw/ppc/spapr_pci.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c index cca9257fecc5..19dd6dbeb943 100644 --- a/hw/ppc/spapr_pci.c +++ b/hw/ppc/spapr_pci.c @@ -275,7 +275,7 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPRMachineState *spapr, unsigned int req_num = rtas_ld(args, 4); /* 0 == remove all */ unsigned int seq_num = rtas_ld(args, 5); unsigned int ret_intr_type; - unsigned int irq, max_irqs = 0, num = 0; + unsigned int irq, max_irqs = 0; sPAPRPHBState *phb = NULL; PCIDevice *pdev = NULL; spapr_pci_msi *msi; @@ -316,10 +316,10 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPRMachineState *spapr, xics_free(spapr->icp, msi->first_irq, msi->num); if (msi_present(pdev)) { - spapr_msi_setmsg(pdev, 0, false, 0, num); + spapr_msi_setmsg(pdev, 0, false, 0, 0); } if (msix_present(pdev)) { - spapr_msi_setmsg(pdev, 0, true, 0, num); + spapr_msi_setmsg(pdev, 0, true, 0, 0); } g_hash_table_remove(phb->msi, &config_addr); From ce266b75febdeee5b91ab630a7158ddff3e002fb Mon Sep 17 00:00:00 2001 From: Greg Kurz Date: Thu, 25 Feb 2016 19:02:18 +0100 Subject: [PATCH 3/8] spapr_pci: fix irq leak in RTAS ibm,change-msi This RTAS call is used to request new interrupts or to free all interrupts. If the driver has already allocated interrupts and asks again for a non-null number of irqs, then the rtas_ibm_change_msi() function will silently leak the previous interrupts. It happens because xics_free() is only called when the driver releases all interrupts (!req_num case). Note that the previously allocated spapr_pci_msi is not leaked because the GHashTable is created with destroy functions and g_hash_table_insert() hence frees the old value. This patch makes sure any previously allocated MSIs are released when a new allocation succeeds. Signed-off-by: Greg Kurz Signed-off-by: David Gibson --- hw/ppc/spapr_pci.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c index 19dd6dbeb943..9b2b546b541c 100644 --- a/hw/ppc/spapr_pci.c +++ b/hw/ppc/spapr_pci.c @@ -305,9 +305,10 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPRMachineState *spapr, return; } + msi = (spapr_pci_msi *) g_hash_table_lookup(phb->msi, &config_addr); + /* Releasing MSIs */ if (!req_num) { - msi = (spapr_pci_msi *) g_hash_table_lookup(phb->msi, &config_addr); if (!msi) { trace_spapr_pci_msi("Releasing wrong config", config_addr); rtas_st(rets, 0, RTAS_OUT_HW_ERROR); @@ -360,6 +361,12 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPRMachineState *spapr, return; } + /* Release previous MSIs */ + if (msi) { + xics_free(spapr->icp, msi->first_irq, msi->num); + g_hash_table_remove(phb->msi, &config_addr); + } + /* Setup MSI/MSIX vectors in the device (via cfgspace or MSIX BAR) */ spapr_msi_setmsg(pdev, SPAPR_PCI_MSI_WINDOW, ret_intr_type == RTAS_TYPE_MSIX, irq, req_num); From cba0e7796be18f61f43e60bff6bff986851e359a Mon Sep 17 00:00:00 2001 From: Greg Kurz Date: Tue, 23 Feb 2016 17:47:59 +0100 Subject: [PATCH 4/8] spapr: disable vmdesc submission for old machines Since QEMU 2.3, we have a vmdesc section in the migration stream. This section is not mandatory but when migrating a pseries-2.2 machine from QEMU 2.2, you get a warning at the destination: qemu-system-ppc64: Expected vmdescription section, but got 0 The warning goes away if we decide to skip vmdesc as well for older pseries, like it is already done for pc's. This can only be observed with -cpu POWER7 because POWER8 cannot migrate from QEMU 2.2 to 2.3 (insns_flags2 mismatch). Signed-off-by: Greg Kurz Signed-off-by: David Gibson --- hw/ppc/spapr.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index c119f5582429..3b4a557c0a91 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -2452,6 +2452,7 @@ DEFINE_SPAPR_MACHINE(2_3, "2.3", false); static void spapr_machine_2_2_instance_options(MachineState *machine) { spapr_machine_2_3_instance_options(machine); + machine->suppress_vmdesc = true; } static void spapr_machine_2_2_class_options(MachineClass *mc) From 2d7d06d847b78fc1487a1b8908a823089c6a53b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Poussineau?= Date: Thu, 25 Feb 2016 13:02:11 +0100 Subject: [PATCH 5/8] dbdma: warn when using unassigned channel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With this, it's easier to know if a guest uses an invalid and/or unimplemented DMA channel. Signed-off-by: Hervé Poussineau Reviewed-by: Thomas Huth Acked-by: Mark Cave-Ayland Signed-off-by: David Gibson --- hw/misc/macio/mac_dbdma.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/hw/misc/macio/mac_dbdma.c b/hw/misc/macio/mac_dbdma.c index d81dea7b0d43..6051f17dbd94 100644 --- a/hw/misc/macio/mac_dbdma.c +++ b/hw/misc/macio/mac_dbdma.c @@ -557,11 +557,13 @@ void DBDMA_register_channel(void *dbdma, int nchan, qemu_irq irq, DBDMA_DPRINTF("DBDMA_register_channel 0x%x\n", nchan); + assert(rw); + assert(flush); + ch->irq = irq; ch->rw = rw; ch->flush = flush; ch->io.opaque = opaque; - ch->io.channel = ch; } static void @@ -775,6 +777,20 @@ static void dbdma_reset(void *opaque) memset(s->channels[i].regs, 0, DBDMA_SIZE); } +static void dbdma_unassigned_rw(DBDMA_io *io) +{ + DBDMA_channel *ch = io->channel; + qemu_log_mask(LOG_GUEST_ERROR, "%s: use of unassigned channel %d\n", + __func__, ch->channel); +} + +static void dbdma_unassigned_flush(DBDMA_io *io) +{ + DBDMA_channel *ch = io->channel; + qemu_log_mask(LOG_GUEST_ERROR, "%s: use of unassigned channel %d\n", + __func__, ch->channel); +} + void* DBDMA_init (MemoryRegion **dbdma_mem) { DBDMAState *s; @@ -784,8 +800,13 @@ void* DBDMA_init (MemoryRegion **dbdma_mem) for (i = 0; i < DBDMA_CHANNELS; i++) { DBDMA_io *io = &s->channels[i].io; + DBDMA_channel *ch = &s->channels[i]; qemu_iovec_init(&io->iov, 1); - s->channels[i].channel = i; + + ch->rw = dbdma_unassigned_rw; + ch->flush = dbdma_unassigned_flush; + ch->channel = i; + ch->io.channel = ch; } memory_region_init_io(&s->mem, NULL, &dbdma_ops, s, "dbdma", 0x1000); From 09b5e30da5b19f44768a5429f603caaede216757 Mon Sep 17 00:00:00 2001 From: Greg Kurz Date: Thu, 18 Feb 2016 12:32:18 +0100 Subject: [PATCH 6/8] spapr: skip configuration section during migration of older machines Since QEMU 2.4, we have a configuration section in the migration stream. This must be skipped for older machines, like it is already done for x86. This patch fixes the migration of pseries-2.3 from/to QEMU 2.3, but it breaks migration of the same machine from/to QEMU 2.4/2.4.1/2.5. We do that anyway because QEMU 2.3 is likely to be more widely deployed than newer QEMU versions. Fixes: 61964c23e5ddd5a33f15699e45ce126f879e3e33 Signed-off-by: Greg Kurz Reviewed-by: Laurent Vivier Reviewed-by: Juan Quintela Signed-off-by: David Gibson --- hw/ppc/spapr.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 3b4a557c0a91..e9d4abf06a6b 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -2427,6 +2427,7 @@ static void spapr_machine_2_3_instance_options(MachineState *machine) spapr_machine_2_4_instance_options(machine); savevm_skip_section_footers(); global_state_set_optional(); + savevm_skip_configuration(); } static void spapr_machine_2_3_class_options(MachineClass *mc) From 902c053d834e3b802ec736f170edf226d4a841ff Mon Sep 17 00:00:00 2001 From: Greg Kurz Date: Thu, 18 Feb 2016 12:32:25 +0100 Subject: [PATCH 7/8] migration: allow machine to enforce configuration section migration Migration of pseries-2.3 doesn't have configuration section. Unfortunately, QEMU 2.4/2.4.1/2.5 are buggy and always stream and expect the configuration section, and break migration both ways. This patch introduces a property which allows to enforce a configuration section for machines who don't have one. It can be set at startup: -machine enforce-config-section=on or later from the QEMU monitor: qom-set /machine enforce-config-section on It is up to the tooling to set or unset this property according to the version of the QEMU at the other end of the pipe. Signed-off-by: Greg Kurz Reviewed-by: Laurent Vivier Reviewed-by: Juan Quintela Signed-off-by: David Gibson --- hw/core/machine.c | 21 +++++++++++++++++++++ include/hw/boards.h | 1 + migration/savevm.c | 10 ++++++++-- qemu-options.hx | 3 ++- 4 files changed, 32 insertions(+), 3 deletions(-) diff --git a/hw/core/machine.c b/hw/core/machine.c index 6d1a0d8eebc4..a8c4680b0c47 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -312,6 +312,21 @@ static bool machine_get_suppress_vmdesc(Object *obj, Error **errp) return ms->suppress_vmdesc; } +static void machine_set_enforce_config_section(Object *obj, bool value, + Error **errp) +{ + MachineState *ms = MACHINE(obj); + + ms->enforce_config_section = value; +} + +static bool machine_get_enforce_config_section(Object *obj, Error **errp) +{ + MachineState *ms = MACHINE(obj); + + return ms->enforce_config_section; +} + static int error_on_sysbus_device(SysBusDevice *sbdev, void *opaque) { error_report("Option '-device %s' cannot be handled by this machine", @@ -467,6 +482,12 @@ static void machine_initfn(Object *obj) object_property_set_description(obj, "suppress-vmdesc", "Set on to disable self-describing migration", NULL); + object_property_add_bool(obj, "enforce-config-section", + machine_get_enforce_config_section, + machine_set_enforce_config_section, NULL); + object_property_set_description(obj, "enforce-config-section", + "Set on to enforce configuration section migration", + NULL); /* Register notifier when init is done for sysbus sanity checks */ ms->sysbus_notifier.notify = machine_init_notify; diff --git a/include/hw/boards.h b/include/hw/boards.h index de3b3bdafdfe..b5d7eae3f303 100644 --- a/include/hw/boards.h +++ b/include/hw/boards.h @@ -127,6 +127,7 @@ struct MachineState { char *firmware; bool iommu; bool suppress_vmdesc; + bool enforce_config_section; ram_addr_t ram_size; ram_addr_t maxram_size; diff --git a/migration/savevm.c b/migration/savevm.c index b45915612fac..96e7db5967d0 100644 --- a/migration/savevm.c +++ b/migration/savevm.c @@ -878,13 +878,19 @@ bool qemu_savevm_state_blocked(Error **errp) return false; } +static bool enforce_config_section(void) +{ + MachineState *machine = MACHINE(qdev_get_machine()); + return machine->enforce_config_section; +} + void qemu_savevm_state_header(QEMUFile *f) { trace_savevm_state_header(); qemu_put_be32(f, QEMU_VM_FILE_MAGIC); qemu_put_be32(f, QEMU_VM_FILE_VERSION); - if (!savevm_state.skip_configuration) { + if (!savevm_state.skip_configuration || enforce_config_section()) { qemu_put_byte(f, QEMU_VM_CONFIGURATION); vmstate_save_state(f, &vmstate_configuration, &savevm_state, 0); } @@ -1883,7 +1889,7 @@ int qemu_loadvm_state(QEMUFile *f) return -ENOTSUP; } - if (!savevm_state.skip_configuration) { + if (!savevm_state.skip_configuration || enforce_config_section()) { if (qemu_get_byte(f) != QEMU_VM_CONFIGURATION) { error_report("Configuration section missing"); return -EINVAL; diff --git a/qemu-options.hx b/qemu-options.hx index 599db9474cad..144e6a9b764a 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -43,7 +43,8 @@ DEF("machine", HAS_ARG, QEMU_OPTION_machine, \ " aes-key-wrap=on|off controls support for AES key wrapping (default=on)\n" " dea-key-wrap=on|off controls support for DEA key wrapping (default=on)\n" " suppress-vmdesc=on|off disables self-describing migration (default=off)\n" - " nvdimm=on|off controls NVDIMM support (default=off)\n", + " nvdimm=on|off controls NVDIMM support (default=off)\n" + " enforce-config-section=on|off enforce configuration section migration (default=off)\n", QEMU_ARCH_ALL) STEXI @item -machine [type=]@var{name}[,prop=@var{value}[,...]] From a005b3ef50439b5bc6b2eb0b5bda8e8c7c2368bf Mon Sep 17 00:00:00 2001 From: Greg Kurz Date: Fri, 26 Feb 2016 10:44:07 +0100 Subject: [PATCH 8/8] xics: report errors with the QEMU Error API Using the return value to report errors is error prone: - xics_alloc() returns -1 on error but spapr_vio_busdev_realize() errors on 0 - xics_alloc_block() returns the unclear value of ics->offset - 1 on error but both rtas_ibm_change_msi() and spapr_phb_realize() error on 0 This patch adds an errp argument to xics_alloc() and xics_alloc_block() to report errors. The return value of these functions is a valid IRQ number if errp is NULL. It is undefined otherwise. The corresponding error traces get promotted to error messages. Note that the "can't allocate IRQ" error message in spapr_vio_busdev_realize() also moves to xics_alloc(). Similar error message consolidation isn't really applicable to xics_alloc_block() because callers have extra context (device config address, MSI or MSIX). This fixes the issues mentioned above. Based on previous work from Brian W. Hart. Signed-off-by: Greg Kurz Signed-off-by: David Gibson --- hw/intc/xics.c | 13 +++++++++---- hw/ppc/spapr_events.c | 3 ++- hw/ppc/spapr_pci.c | 16 ++++++++++------ hw/ppc/spapr_vio.c | 7 ++++--- include/hw/ppc/xics.h | 5 +++-- trace-events | 2 -- 6 files changed, 28 insertions(+), 18 deletions(-) diff --git a/hw/intc/xics.c b/hw/intc/xics.c index e66ae328819a..213a3709254c 100644 --- a/hw/intc/xics.c +++ b/hw/intc/xics.c @@ -712,7 +712,7 @@ static int ics_find_free_block(ICSState *ics, int num, int alignnum) return -1; } -int xics_alloc(XICSState *icp, int src, int irq_hint, bool lsi) +int xics_alloc(XICSState *icp, int src, int irq_hint, bool lsi, Error **errp) { ICSState *ics = &icp->ics[src]; int irq; @@ -720,14 +720,14 @@ int xics_alloc(XICSState *icp, int src, int irq_hint, bool lsi) if (irq_hint) { assert(src == xics_find_source(icp, irq_hint)); if (!ICS_IRQ_FREE(ics, irq_hint - ics->offset)) { - trace_xics_alloc_failed_hint(src, irq_hint); + error_setg(errp, "can't allocate IRQ %d: already in use", irq_hint); return -1; } irq = irq_hint; } else { irq = ics_find_free_block(ics, 1, 1); if (irq < 0) { - trace_xics_alloc_failed_no_left(src); + error_setg(errp, "can't allocate IRQ: no IRQ left"); return -1; } irq += ics->offset; @@ -743,7 +743,8 @@ int xics_alloc(XICSState *icp, int src, int irq_hint, bool lsi) * Allocate block of consecutive IRQs, and return the number of the first IRQ in the block. * If align==true, aligns the first IRQ number to num. */ -int xics_alloc_block(XICSState *icp, int src, int num, bool lsi, bool align) +int xics_alloc_block(XICSState *icp, int src, int num, bool lsi, bool align, + Error **errp) { int i, first = -1; ICSState *ics = &icp->ics[src]; @@ -763,6 +764,10 @@ int xics_alloc_block(XICSState *icp, int src, int num, bool lsi, bool align) } else { first = ics_find_free_block(ics, num, 1); } + if (first < 0) { + error_setg(errp, "can't find a free %d-IRQ block", num); + return -1; + } if (first >= 0) { for (i = first; i < first + num; ++i) { diff --git a/hw/ppc/spapr_events.c b/hw/ppc/spapr_events.c index f5eac4b5441c..39f4682f957f 100644 --- a/hw/ppc/spapr_events.c +++ b/hw/ppc/spapr_events.c @@ -588,7 +588,8 @@ static void event_scan(PowerPCCPU *cpu, sPAPRMachineState *spapr, void spapr_events_init(sPAPRMachineState *spapr) { QTAILQ_INIT(&spapr->pending_events); - spapr->check_exception_irq = xics_alloc(spapr->icp, 0, 0, false); + spapr->check_exception_irq = xics_alloc(spapr->icp, 0, 0, false, + &error_fatal); spapr->epow_notifier.notify = spapr_powerdown_req; qemu_register_powerdown_notifier(&spapr->epow_notifier); spapr_rtas_register(RTAS_CHECK_EXCEPTION, "check-exception", diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c index 9b2b546b541c..e8edad3ab7c3 100644 --- a/hw/ppc/spapr_pci.c +++ b/hw/ppc/spapr_pci.c @@ -280,6 +280,7 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPRMachineState *spapr, PCIDevice *pdev = NULL; spapr_pci_msi *msi; int *config_addr_key; + Error *err = NULL; switch (func) { case RTAS_CHANGE_MSI_FN: @@ -354,9 +355,10 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPRMachineState *spapr, /* Allocate MSIs */ irq = xics_alloc_block(spapr->icp, 0, req_num, false, - ret_intr_type == RTAS_TYPE_MSI); - if (!irq) { - error_report("Cannot allocate MSIs for device %x", config_addr); + ret_intr_type == RTAS_TYPE_MSI, &err); + if (err) { + error_reportf_err(err, "Can't allocate MSIs for device %x: ", + config_addr); rtas_st(rets, 0, RTAS_OUT_HW_ERROR); return; } @@ -1367,10 +1369,12 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp) /* Initialize the LSI table */ for (i = 0; i < PCI_NUM_PINS; i++) { uint32_t irq; + Error *local_err = NULL; - irq = xics_alloc_block(spapr->icp, 0, 1, true, false); - if (!irq) { - error_setg(errp, "spapr_allocate_lsi failed"); + irq = xics_alloc_block(spapr->icp, 0, 1, true, false, &local_err); + if (local_err) { + error_propagate(errp, local_err); + error_prepend(errp, "can't allocate LSIs: "); return; } diff --git a/hw/ppc/spapr_vio.c b/hw/ppc/spapr_vio.c index ac6666a90be7..0f61a550cb2e 100644 --- a/hw/ppc/spapr_vio.c +++ b/hw/ppc/spapr_vio.c @@ -431,6 +431,7 @@ static void spapr_vio_busdev_realize(DeviceState *qdev, Error **errp) VIOsPAPRDevice *dev = (VIOsPAPRDevice *)qdev; VIOsPAPRDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev); char *id; + Error *local_err = NULL; if (dev->reg != -1) { /* @@ -463,9 +464,9 @@ static void spapr_vio_busdev_realize(DeviceState *qdev, Error **errp) dev->qdev.id = id; } - dev->irq = xics_alloc(spapr->icp, 0, dev->irq, false); - if (!dev->irq) { - error_setg(errp, "can't allocate IRQ"); + dev->irq = xics_alloc(spapr->icp, 0, dev->irq, false, &local_err); + if (local_err) { + error_propagate(errp, local_err); return; } diff --git a/include/hw/ppc/xics.h b/include/hw/ppc/xics.h index 355a96623c70..f60b06ae829e 100644 --- a/include/hw/ppc/xics.h +++ b/include/hw/ppc/xics.h @@ -161,8 +161,9 @@ struct ICSIRQState { qemu_irq xics_get_qirq(XICSState *icp, int irq); void xics_set_irq_type(XICSState *icp, int irq, bool lsi); -int xics_alloc(XICSState *icp, int src, int irq_hint, bool lsi); -int xics_alloc_block(XICSState *icp, int src, int num, bool lsi, bool align); +int xics_alloc(XICSState *icp, int src, int irq_hint, bool lsi, Error **errp); +int xics_alloc_block(XICSState *icp, int src, int num, bool lsi, bool align, + Error **errp); void xics_free(XICSState *icp, int irq, int num); void xics_cpu_setup(XICSState *icp, PowerPCCPU *cpu); diff --git a/trace-events b/trace-events index 61a133f6eea9..075ec271007d 100644 --- a/trace-events +++ b/trace-events @@ -1409,8 +1409,6 @@ xics_ics_write_xive(int nr, int srcno, int server, uint8_t priority) "ics_write_ xics_ics_reject(int nr, int srcno) "reject irq %#x [src %d]" xics_ics_eoi(int nr) "ics_eoi: irq %#x" xics_alloc(int src, int irq) "source#%d, irq %d" -xics_alloc_failed_hint(int src, int irq) "source#%d, irq %d is already in use" -xics_alloc_failed_no_left(int src) "source#%d, no irq left" xics_alloc_block(int src, int first, int num, bool lsi, int align) "source#%d, first irq %d, %d irqs, lsi=%d, alignnum %d" xics_ics_free(int src, int irq, int num) "Source#%d, first irq %d, %d irqs" xics_ics_free_warn(int src, int irq) "Source#%d, irq %d is already free"