diff options
Diffstat (limited to 'hw/intc')
| -rw-r--r-- | hw/intc/Kconfig | 3 | ||||
| -rw-r--r-- | hw/intc/armv7m_nvic.c | 261 | ||||
| -rw-r--r-- | hw/intc/bcm2836_control.c | 101 | ||||
| -rw-r--r-- | hw/intc/trace-events | 35 | ||||
| -rw-r--r-- | hw/intc/xics_spapr.c | 9 |
5 files changed, 388 insertions, 21 deletions
diff --git a/hw/intc/Kconfig b/hw/intc/Kconfig index de10a6bcbf..5347f8412c 100644 --- a/hw/intc/Kconfig +++ b/hw/intc/Kconfig @@ -12,12 +12,15 @@ config IOAPIC config ARM_GIC bool + select MSI_NONBROKEN config OPENPIC bool + select MSI_NONBROKEN config APIC bool + select MSI_NONBROKEN config ARM_GIC_KVM bool diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c index ab822f4251..fff6e694e6 100644 --- a/hw/intc/armv7m_nvic.c +++ b/hw/intc/armv7m_nvic.c @@ -655,6 +655,102 @@ void armv7m_nvic_set_pending_derived(void *opaque, int irq, bool secure) do_armv7m_nvic_set_pending(opaque, irq, secure, true); } +void armv7m_nvic_set_pending_lazyfp(void *opaque, int irq, bool secure) +{ + /* + * Pend an exception during lazy FP stacking. This differs + * from the usual exception pending because the logic for + * whether we should escalate depends on the saved context + * in the FPCCR register, not on the current state of the CPU/NVIC. + */ + NVICState *s = (NVICState *)opaque; + bool banked = exc_is_banked(irq); + VecInfo *vec; + bool targets_secure; + bool escalate = false; + /* + * We will only look at bits in fpccr if this is a banked exception + * (in which case 'secure' tells us whether it is the S or NS version). + * All the bits for the non-banked exceptions are in fpccr_s. + */ + uint32_t fpccr_s = s->cpu->env.v7m.fpccr[M_REG_S]; + uint32_t fpccr = s->cpu->env.v7m.fpccr[secure]; + + assert(irq > ARMV7M_EXCP_RESET && irq < s->num_irq); + assert(!secure || banked); + + vec = (banked && secure) ? &s->sec_vectors[irq] : &s->vectors[irq]; + + targets_secure = banked ? secure : exc_targets_secure(s, irq); + + switch (irq) { + case ARMV7M_EXCP_DEBUG: + if (!(fpccr_s & R_V7M_FPCCR_MONRDY_MASK)) { + /* Ignore DebugMonitor exception */ + return; + } + break; + case ARMV7M_EXCP_MEM: + escalate = !(fpccr & R_V7M_FPCCR_MMRDY_MASK); + break; + case ARMV7M_EXCP_USAGE: + escalate = !(fpccr & R_V7M_FPCCR_UFRDY_MASK); + break; + case ARMV7M_EXCP_BUS: + escalate = !(fpccr_s & R_V7M_FPCCR_BFRDY_MASK); + break; + case ARMV7M_EXCP_SECURE: + escalate = !(fpccr_s & R_V7M_FPCCR_SFRDY_MASK); + break; + default: + g_assert_not_reached(); + } + + if (escalate) { + /* + * Escalate to HardFault: faults that initially targeted Secure + * continue to do so, even if HF normally targets NonSecure. + */ + irq = ARMV7M_EXCP_HARD; + if (arm_feature(&s->cpu->env, ARM_FEATURE_M_SECURITY) && + (targets_secure || + !(s->cpu->env.v7m.aircr & R_V7M_AIRCR_BFHFNMINS_MASK))) { + vec = &s->sec_vectors[irq]; + } else { + vec = &s->vectors[irq]; + } + } + + if (!vec->enabled || + nvic_exec_prio(s) <= exc_group_prio(s, vec->prio, secure)) { + if (!(fpccr_s & R_V7M_FPCCR_HFRDY_MASK)) { + /* + * We want to escalate to HardFault but the context the + * FP state belongs to prevents the exception pre-empting. + */ + cpu_abort(&s->cpu->parent_obj, + "Lockup: can't escalate to HardFault during " + "lazy FP register stacking\n"); + } + } + + if (escalate) { + s->cpu->env.v7m.hfsr |= R_V7M_HFSR_FORCED_MASK; + } + if (!vec->pending) { + vec->pending = 1; + /* + * We do not call nvic_irq_update(), because we know our caller + * is going to handle causing us to take the exception by + * raising EXCP_LAZYFP, so raising the IRQ line would be + * pointless extra work. We just need to recompute the + * priorities so that armv7m_nvic_can_take_pending_exception() + * returns the right answer. + */ + nvic_recompute_state(s); + } +} + /* Make pending IRQ active. */ void armv7m_nvic_acknowledge_irq(void *opaque) { @@ -746,6 +842,40 @@ int armv7m_nvic_complete_irq(void *opaque, int irq, bool secure) return ret; } +bool armv7m_nvic_get_ready_status(void *opaque, int irq, bool secure) +{ + /* + * Return whether an exception is "ready", i.e. it is enabled and is + * configured at a priority which would allow it to interrupt the + * current execution priority. + * + * irq and secure have the same semantics as for armv7m_nvic_set_pending(): + * for non-banked exceptions secure is always false; for banked exceptions + * it indicates which of the exceptions is required. + */ + NVICState *s = (NVICState *)opaque; + bool banked = exc_is_banked(irq); + VecInfo *vec; + int running = nvic_exec_prio(s); + + assert(irq > ARMV7M_EXCP_RESET && irq < s->num_irq); + assert(!secure || banked); + + /* + * HardFault is an odd special case: we always check against -1, + * even if we're secure and HardFault has priority -3; we never + * need to check for enabled state. + */ + if (irq == ARMV7M_EXCP_HARD) { + return running > -1; + } + + vec = (banked && secure) ? &s->sec_vectors[irq] : &s->vectors[irq]; + + return vec->enabled && + exc_group_prio(s, vec->prio, secure) < running; +} + /* callback when external interrupt line is changed */ static void set_irq_level(void *opaque, int n, int level) { @@ -1077,6 +1207,16 @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs) } case 0xd84: /* CSSELR */ return cpu->env.v7m.csselr[attrs.secure]; + case 0xd88: /* CPACR */ + if (!arm_feature(&cpu->env, ARM_FEATURE_VFP)) { + return 0; + } + return cpu->env.v7m.cpacr[attrs.secure]; + case 0xd8c: /* NSACR */ + if (!attrs.secure || !arm_feature(&cpu->env, ARM_FEATURE_VFP)) { + return 0; + } + return cpu->env.v7m.nsacr; /* TODO: Implement debug registers. */ case 0xd90: /* MPU_TYPE */ /* Unified MPU; if the MPU is not present this value is zero */ @@ -1222,6 +1362,49 @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs) return 0; } return cpu->env.v7m.sfar; + case 0xf34: /* FPCCR */ + if (!arm_feature(&cpu->env, ARM_FEATURE_VFP)) { + return 0; + } + if (attrs.secure) { + return cpu->env.v7m.fpccr[M_REG_S]; + } else { + /* + * NS can read LSPEN, CLRONRET and MONRDY. It can read + * BFRDY and HFRDY if AIRCR.BFHFNMINS != 0; + * other non-banked bits RAZ. + * TODO: MONRDY should RAZ/WI if DEMCR.SDME is set. + */ + uint32_t value = cpu->env.v7m.fpccr[M_REG_S]; + uint32_t mask = R_V7M_FPCCR_LSPEN_MASK | + R_V7M_FPCCR_CLRONRET_MASK | + R_V7M_FPCCR_MONRDY_MASK; + + if (s->cpu->env.v7m.aircr & R_V7M_AIRCR_BFHFNMINS_MASK) { + mask |= R_V7M_FPCCR_BFRDY_MASK | R_V7M_FPCCR_HFRDY_MASK; + } + + value &= mask; + + value |= cpu->env.v7m.fpccr[M_REG_NS]; + return value; + } + case 0xf38: /* FPCAR */ + if (!arm_feature(&cpu->env, ARM_FEATURE_VFP)) { + return 0; + } + return cpu->env.v7m.fpcar[attrs.secure]; + case 0xf3c: /* FPDSCR */ + if (!arm_feature(&cpu->env, ARM_FEATURE_VFP)) { + return 0; + } + return cpu->env.v7m.fpdscr[attrs.secure]; + case 0xf40: /* MVFR0 */ + return cpu->isar.mvfr0; + case 0xf44: /* MVFR1 */ + return cpu->isar.mvfr1; + case 0xf48: /* MVFR2 */ + return cpu->isar.mvfr2; default: bad_offset: qemu_log_mask(LOG_GUEST_ERROR, "NVIC: Bad read offset 0x%x\n", offset); @@ -1469,6 +1652,18 @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value, cpu->env.v7m.csselr[attrs.secure] = value & R_V7M_CSSELR_INDEX_MASK; } break; + case 0xd88: /* CPACR */ + if (arm_feature(&cpu->env, ARM_FEATURE_VFP)) { + /* We implement only the Floating Point extension's CP10/CP11 */ + cpu->env.v7m.cpacr[attrs.secure] = value & (0xf << 20); + } + break; + case 0xd8c: /* NSACR */ + if (attrs.secure && arm_feature(&cpu->env, ARM_FEATURE_VFP)) { + /* We implement only the Floating Point extension's CP10/CP11 */ + cpu->env.v7m.nsacr = value & (3 << 10); + } + break; case 0xd90: /* MPU_TYPE */ return; /* RO */ case 0xd94: /* MPU_CTRL */ @@ -1697,6 +1892,72 @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value, } break; } + case 0xf34: /* FPCCR */ + if (arm_feature(&cpu->env, ARM_FEATURE_VFP)) { + /* Not all bits here are banked. */ + uint32_t fpccr_s; + + if (!arm_feature(&cpu->env, ARM_FEATURE_V8)) { + /* Don't allow setting of bits not present in v7M */ + value &= (R_V7M_FPCCR_LSPACT_MASK | + R_V7M_FPCCR_USER_MASK | + R_V7M_FPCCR_THREAD_MASK | + R_V7M_FPCCR_HFRDY_MASK | + R_V7M_FPCCR_MMRDY_MASK | + R_V7M_FPCCR_BFRDY_MASK | + R_V7M_FPCCR_MONRDY_MASK | + R_V7M_FPCCR_LSPEN_MASK | + R_V7M_FPCCR_ASPEN_MASK); + } + value &= ~R_V7M_FPCCR_RES0_MASK; + + if (!attrs.secure) { + /* Some non-banked bits are configurably writable by NS */ + fpccr_s = cpu->env.v7m.fpccr[M_REG_S]; + if (!(fpccr_s & R_V7M_FPCCR_LSPENS_MASK)) { + uint32_t lspen = FIELD_EX32(value, V7M_FPCCR, LSPEN); + fpccr_s = FIELD_DP32(fpccr_s, V7M_FPCCR, LSPEN, lspen); + } + if (!(fpccr_s & R_V7M_FPCCR_CLRONRETS_MASK)) { + uint32_t cor = FIELD_EX32(value, V7M_FPCCR, CLRONRET); + fpccr_s = FIELD_DP32(fpccr_s, V7M_FPCCR, CLRONRET, cor); + } + if ((s->cpu->env.v7m.aircr & R_V7M_AIRCR_BFHFNMINS_MASK)) { + uint32_t hfrdy = FIELD_EX32(value, V7M_FPCCR, HFRDY); + uint32_t bfrdy = FIELD_EX32(value, V7M_FPCCR, BFRDY); + fpccr_s = FIELD_DP32(fpccr_s, V7M_FPCCR, HFRDY, hfrdy); + fpccr_s = FIELD_DP32(fpccr_s, V7M_FPCCR, BFRDY, bfrdy); + } + /* TODO MONRDY should RAZ/WI if DEMCR.SDME is set */ + { + uint32_t monrdy = FIELD_EX32(value, V7M_FPCCR, MONRDY); + fpccr_s = FIELD_DP32(fpccr_s, V7M_FPCCR, MONRDY, monrdy); + } + + /* + * All other non-banked bits are RAZ/WI from NS; write + * just the banked bits to fpccr[M_REG_NS]. + */ + value &= R_V7M_FPCCR_BANKED_MASK; + cpu->env.v7m.fpccr[M_REG_NS] = value; + } else { + fpccr_s = value; + } + cpu->env.v7m.fpccr[M_REG_S] = fpccr_s; + } + break; + case 0xf38: /* FPCAR */ + if (arm_feature(&cpu->env, ARM_FEATURE_VFP)) { + value &= ~7; + cpu->env.v7m.fpcar[attrs.secure] = value; + } + break; + case 0xf3c: /* FPDSCR */ + if (arm_feature(&cpu->env, ARM_FEATURE_VFP)) { + value &= 0x07c00000; + cpu->env.v7m.fpdscr[attrs.secure] = value; + } + break; case 0xf50: /* ICIALLU */ case 0xf58: /* ICIMVAU */ case 0xf5c: /* DCIMVAC */ diff --git a/hw/intc/bcm2836_control.c b/hw/intc/bcm2836_control.c index cfa5bc7365..421469f2ef 100644 --- a/hw/intc/bcm2836_control.c +++ b/hw/intc/bcm2836_control.c @@ -7,7 +7,9 @@ * This code is licensed under the GNU GPLv2 and later. * * At present, only implements interrupt routing, and mailboxes (i.e., - * not local timer, PMU interrupt, or AXI counters). + * not PMU interrupt, or AXI counters). + * + * ARM Local Timer IRQ Copyright (c) 2019. Zoltán Baldaszti * * Ref: * https://www.raspberrypi.org/documentation/hardware/raspberrypi/bcm2836/QA7_rev3.4.pdf @@ -18,6 +20,9 @@ #include "qemu/log.h" #define REG_GPU_ROUTE 0x0c +#define REG_LOCALTIMERROUTING 0x24 +#define REG_LOCALTIMERCONTROL 0x34 +#define REG_LOCALTIMERACK 0x38 #define REG_TIMERCONTROL 0x40 #define REG_MBOXCONTROL 0x50 #define REG_IRQSRC 0x60 @@ -43,6 +48,13 @@ #define IRQ_TIMER 11 #define IRQ_MAX IRQ_TIMER +#define LOCALTIMER_FREQ 38400000 +#define LOCALTIMER_INTFLAG (1 << 31) +#define LOCALTIMER_RELOAD (1 << 30) +#define LOCALTIMER_INTENABLE (1 << 29) +#define LOCALTIMER_ENABLE (1 << 28) +#define LOCALTIMER_VALUE(x) ((x) & 0xfffffff) + static void deliver_local(BCM2836ControlState *s, uint8_t core, uint8_t irq, uint32_t controlreg, uint8_t controlidx) { @@ -78,6 +90,20 @@ static void bcm2836_control_update(BCM2836ControlState *s) s->fiqsrc[s->route_gpu_fiq] |= (uint32_t)1 << IRQ_GPU; } + /* + * handle the control module 'local timer' interrupt for one of the + * cores' IRQ/FIQ; this is distinct from the per-CPU timer + * interrupts handled below. + */ + if ((s->local_timer_control & LOCALTIMER_INTENABLE) && + (s->local_timer_control & LOCALTIMER_INTFLAG)) { + if (s->route_localtimer & 4) { + s->fiqsrc[(s->route_localtimer & 3)] |= (uint32_t)1 << IRQ_TIMER; + } else { + s->irqsrc[(s->route_localtimer & 3)] |= (uint32_t)1 << IRQ_TIMER; + } + } + for (i = 0; i < BCM2836_NCORES; i++) { /* handle local timer interrupts for this core */ if (s->timerirqs[i]) { @@ -162,6 +188,54 @@ static void bcm2836_control_set_gpu_fiq(void *opaque, int irq, int level) bcm2836_control_update(s); } +static void bcm2836_control_local_timer_set_next(void *opaque) +{ + BCM2836ControlState *s = opaque; + uint64_t next_event; + + assert(LOCALTIMER_VALUE(s->local_timer_control) > 0); + + next_event = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + + muldiv64(LOCALTIMER_VALUE(s->local_timer_control), + NANOSECONDS_PER_SECOND, LOCALTIMER_FREQ); + timer_mod(&s->timer, next_event); +} + +static void bcm2836_control_local_timer_tick(void *opaque) +{ + BCM2836ControlState *s = opaque; + + bcm2836_control_local_timer_set_next(s); + + s->local_timer_control |= LOCALTIMER_INTFLAG; + bcm2836_control_update(s); +} + +static void bcm2836_control_local_timer_control(void *opaque, uint32_t val) +{ + BCM2836ControlState *s = opaque; + + s->local_timer_control = val; + if (val & LOCALTIMER_ENABLE) { + bcm2836_control_local_timer_set_next(s); + } else { + timer_del(&s->timer); + } +} + +static void bcm2836_control_local_timer_ack(void *opaque, uint32_t val) +{ + BCM2836ControlState *s = opaque; + + if (val & LOCALTIMER_INTFLAG) { + s->local_timer_control &= ~LOCALTIMER_INTFLAG; + } + if ((val & LOCALTIMER_RELOAD) && + (s->local_timer_control & LOCALTIMER_ENABLE)) { + bcm2836_control_local_timer_set_next(s); + } +} + static uint64_t bcm2836_control_read(void *opaque, hwaddr offset, unsigned size) { BCM2836ControlState *s = opaque; @@ -170,6 +244,12 @@ static uint64_t bcm2836_control_read(void *opaque, hwaddr offset, unsigned size) assert(s->route_gpu_fiq < BCM2836_NCORES && s->route_gpu_irq < BCM2836_NCORES); return ((uint32_t)s->route_gpu_fiq << 2) | s->route_gpu_irq; + } else if (offset == REG_LOCALTIMERROUTING) { + return s->route_localtimer; + } else if (offset == REG_LOCALTIMERCONTROL) { + return s->local_timer_control; + } else if (offset == REG_LOCALTIMERACK) { + return 0; } else if (offset >= REG_TIMERCONTROL && offset < REG_MBOXCONTROL) { return s->timercontrol[(offset - REG_TIMERCONTROL) >> 2]; } else if (offset >= REG_MBOXCONTROL && offset < REG_IRQSRC) { @@ -195,6 +275,12 @@ static void bcm2836_control_write(void *opaque, hwaddr offset, if (offset == REG_GPU_ROUTE) { s->route_gpu_irq = val & 0x3; s->route_gpu_fiq = (val >> 2) & 0x3; + } else if (offset == REG_LOCALTIMERROUTING) { + s->route_localtimer = val & 7; + } else if (offset == REG_LOCALTIMERCONTROL) { + bcm2836_control_local_timer_control(s, val); + } else if (offset == REG_LOCALTIMERACK) { + bcm2836_control_local_timer_ack(s, val); } else if (offset >= REG_TIMERCONTROL && offset < REG_MBOXCONTROL) { s->timercontrol[(offset - REG_TIMERCONTROL) >> 2] = val & 0xff; } else if (offset >= REG_MBOXCONTROL && offset < REG_IRQSRC) { @@ -227,6 +313,10 @@ static void bcm2836_control_reset(DeviceState *d) s->route_gpu_irq = s->route_gpu_fiq = 0; + timer_del(&s->timer); + s->route_localtimer = 0; + s->local_timer_control = 0; + for (i = 0; i < BCM2836_NCORES; i++) { s->timercontrol[i] = 0; s->mailboxcontrol[i] = 0; @@ -263,11 +353,15 @@ static void bcm2836_control_init(Object *obj) /* outputs to CPU cores */ qdev_init_gpio_out_named(dev, s->irq, "irq", BCM2836_NCORES); qdev_init_gpio_out_named(dev, s->fiq, "fiq", BCM2836_NCORES); + + /* create a qemu virtual timer */ + timer_init_ns(&s->timer, QEMU_CLOCK_VIRTUAL, + bcm2836_control_local_timer_tick, s); } static const VMStateDescription vmstate_bcm2836_control = { .name = TYPE_BCM2836_CONTROL, - .version_id = 1, + .version_id = 2, .minimum_version_id = 1, .fields = (VMStateField[]) { VMSTATE_UINT32_ARRAY(mailboxes, BCM2836ControlState, @@ -277,6 +371,9 @@ static const VMStateDescription vmstate_bcm2836_control = { VMSTATE_UINT32_ARRAY(timercontrol, BCM2836ControlState, BCM2836_NCORES), VMSTATE_UINT32_ARRAY(mailboxcontrol, BCM2836ControlState, BCM2836_NCORES), + VMSTATE_TIMER_V(timer, BCM2836ControlState, 2), + VMSTATE_UINT32_V(local_timer_control, BCM2836ControlState, 2), + VMSTATE_UINT8_V(route_localtimer, BCM2836ControlState, 2), VMSTATE_END_OF_LIST() } }; diff --git a/hw/intc/trace-events b/hw/intc/trace-events index 7769869a13..a28bdce925 100644 --- a/hw/intc/trace-events +++ b/hw/intc/trace-events @@ -1,13 +1,13 @@ # See docs/devel/tracing.txt for syntax documentation. -# hw/intc/i8259.c +# i8259.c pic_update_irq(bool master, uint8_t imr, uint8_t irr, uint8_t padd) "master %d imr %"PRIu8" irr %"PRIu8" padd %"PRIu8 pic_set_irq(bool master, int irq, int level) "master %d irq %d level %d" pic_interrupt(int irq, int intno) "irq %d intno %d" pic_ioport_write(bool master, uint64_t addr, uint64_t val) "master %d addr 0x%"PRIx64" val 0x%"PRIx64 pic_ioport_read(bool master, uint64_t addr, int val) "master %d addr 0x%"PRIx64" val 0x%x" -# hw/intc/apic_common.c +# apic_common.c cpu_set_apic_base(uint64_t val) "0x%016"PRIx64 cpu_get_apic_base(uint64_t val) "0x%016"PRIx64 # coalescing @@ -15,13 +15,13 @@ apic_report_irq_delivered(int apic_irq_delivered) "coalescing %d" apic_reset_irq_delivered(int apic_irq_delivered) "old coalescing %d" apic_get_irq_delivered(int apic_irq_delivered) "returning coalescing %d" -# hw/intc/apic.c +# apic.c apic_local_deliver(int vector, uint32_t lvt) "vector %d delivery mode %d" apic_deliver_irq(uint8_t dest, uint8_t dest_mode, uint8_t delivery_mode, uint8_t vector_num, uint8_t trigger_mode) "dest %d dest_mode %d delivery_mode %d vector %d trigger_mode %d" apic_mem_readl(uint64_t addr, uint32_t val) "0x%"PRIx64" = 0x%08x" apic_mem_writel(uint64_t addr, uint32_t val) "0x%"PRIx64" = 0x%08x" -# hw/intc/ioapic.c +# ioapic.c ioapic_set_remote_irr(int n) "set remote irr for pin %d" ioapic_clear_remote_irr(int n, int vector) "clear remote irr for pin %d vector %d" ioapic_eoi_broadcast(int vector) "EOI broadcast for vector %d" @@ -29,7 +29,7 @@ ioapic_mem_read(uint8_t addr, uint8_t regsel, uint8_t size, uint32_t val) "ioapi ioapic_mem_write(uint8_t addr, uint8_t regsel, uint8_t size, uint32_t val) "ioapic mem write addr 0x%"PRIx8" regsel: 0x%"PRIx8" size 0x%"PRIx8" val 0x%"PRIx32 ioapic_set_irq(int vector, int level) "vector: %d level: %d" -# hw/intc/slavio_intctl.c +# slavio_intctl.c slavio_intctl_mem_readl(uint32_t cpu, uint64_t addr, uint32_t ret) "read cpu %d reg 0x%"PRIx64" = 0x%x" slavio_intctl_mem_writel(uint32_t cpu, uint64_t addr, uint32_t val) "write cpu %d reg 0x%"PRIx64" = 0x%x" slavio_intctl_mem_writel_clear(uint32_t cpu, uint32_t val, uint32_t intreg_pending) "Cleared cpu %d irq mask 0x%x, curmask 0x%x" @@ -43,14 +43,14 @@ slavio_check_interrupts(uint32_t pending, uint32_t intregm_disabled) "pending 0x slavio_set_irq(uint32_t target_cpu, int irq, uint32_t pil, int level) "Set cpu %d irq %d -> pil %d level %d" slavio_set_timer_irq_cpu(int cpu, int level) "Set cpu %d local timer level %d" -# hw/intc/grlib_irqmp.c +# grlib_irqmp.c grlib_irqmp_check_irqs(uint32_t pend, uint32_t force, uint32_t mask, uint32_t lvl1, uint32_t lvl2) "pend:0x%04x force:0x%04x mask:0x%04x lvl1:0x%04x lvl0:0x%04x" grlib_irqmp_ack(int intno) "interrupt:%d" grlib_irqmp_set_irq(int irq) "Raise CPU IRQ %d" grlib_irqmp_readl_unknown(uint64_t addr) "addr 0x%"PRIx64 grlib_irqmp_writel_unknown(uint64_t addr, uint32_t value) "addr 0x%"PRIx64" value 0x%x" -# hw/intc/lm32_pic.c +# lm32_pic.c lm32_pic_raise_irq(void) "Raise CPU interrupt" lm32_pic_lower_irq(void) "Lower CPU interrupt" lm32_pic_interrupt(int irq, int level) "Set IRQ%d %d" @@ -59,7 +59,7 @@ lm32_pic_set_ip(uint32_t ip) "ip 0x%08x" lm32_pic_get_im(uint32_t im) "im 0x%08x" lm32_pic_get_ip(uint32_t ip) "ip 0x%08x" -# hw/intc/xics.c +# xics.c xics_icp_check_ipi(int server, uint8_t mfrr) "CPU %d can take IPI mfrr=0x%x" xics_icp_accept(uint32_t old_xirr, uint32_t new_xirr) "icp_accept: XIRR 0x%"PRIx32"->0x%"PRIx32 xics_icp_eoi(int server, uint32_t xirr, uint32_t new_xirr) "icp_eoi: server %d given XIRR 0x%"PRIx32" new XIRR 0x%"PRIx32 @@ -72,23 +72,23 @@ xics_ics_simple_write_xive(int nr, int srcno, int server, uint8_t priority) "ics xics_ics_simple_reject(int nr, int srcno) "reject irq 0x%x [src %d]" xics_ics_simple_eoi(int nr) "ics_eoi: irq 0x%x" -# hw/intc/s390_flic_kvm.c +# s390_flic_kvm.c flic_create_device(int err) "flic: create device failed %d" flic_no_device_api(int err) "flic: no Device Contral API support %d" flic_reset_failed(int err) "flic: reset failed %d" -# hw/intc/s390_flic.c +# s390_flic.c qemu_s390_airq_suppressed(uint8_t type, uint8_t isc) "flic: adapter I/O interrupt suppressed (type 0x%x isc 0x%x)" qemu_s390_suppress_airq(uint8_t isc, const char *from, const char *to) "flic: for isc 0x%x, suppress airq by modifying ais mode from %s to %s" -# hw/intc/aspeed_vic.c +# aspeed_vic.c aspeed_vic_set_irq(int irq, int level) "Enabling IRQ %d: %d" aspeed_vic_update_fiq(int flags) "Raising FIQ: %d" aspeed_vic_update_irq(int flags) "Raising IRQ: %d" aspeed_vic_read(uint64_t offset, unsigned size, uint32_t value) "From 0x%" PRIx64 " of size %u: 0x%" PRIx32 aspeed_vic_write(uint64_t offset, unsigned size, uint32_t data) "To 0x%" PRIx64 " of size %u: 0x%" PRIx32 -# hw/intc/arm_gic.c +# arm_gic.c gic_enable_irq(int irq) "irq %d enabled" gic_disable_irq(int irq) "irq %d disabled" gic_set_irq(int irq, int level, int cpumask, int target) "irq %d level %d cpumask 0x%x target 0x%x" @@ -104,7 +104,7 @@ gic_dist_write(int addr, unsigned int size, uint32_t val) "dist write at 0x%08x gic_lr_entry(int cpu, int entry, uint32_t val) "cpu %d: new lr entry %d: 0x%08" PRIx32 gic_update_maintenance_irq(int cpu, int val) "cpu %d: maintenance = %d" -# hw/intc/arm_gicv3_cpuif.c +# arm_gicv3_cpuif.c gicv3_icc_pmr_read(uint32_t cpu, uint64_t val) "GICv3 ICC_PMR read cpu 0x%x value 0x%" PRIx64 gicv3_icc_pmr_write(uint32_t cpu, uint64_t val) "GICv3 ICC_PMR write cpu 0x%x value 0x%" PRIx64 gicv3_icc_bpr_read(int grp, uint32_t cpu, uint64_t val) "GICv3 ICC_BPR%d read cpu 0x%x value 0x%" PRIx64 @@ -163,14 +163,14 @@ gicv3_icv_eoir_write(int grp, uint32_t cpu, uint64_t val) "GICv3 ICV_EOIR%d writ gicv3_cpuif_virt_update(uint32_t cpuid, int idx) "GICv3 CPU i/f 0x%x virt HPPI update LR index %d" gicv3_cpuif_virt_set_irqs(uint32_t cpuid, int fiqlevel, int irqlevel, int maintlevel) "GICv3 CPU i/f 0x%x virt HPPI update: setting FIQ %d IRQ %d maintenance-irq %d" -# hw/intc/arm_gicv3_dist.c +# arm_gicv3_dist.c gicv3_dist_read(uint64_t offset, uint64_t data, unsigned size, bool secure) "GICv3 distributor read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u secure %d" gicv3_dist_badread(uint64_t offset, unsigned size, bool secure) "GICv3 distributor read: offset 0x%" PRIx64 " size %u secure %d: error" gicv3_dist_write(uint64_t offset, uint64_t data, unsigned size, bool secure) "GICv3 distributor write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u secure %d" gicv3_dist_badwrite(uint64_t offset, uint64_t data, unsigned size, bool secure) "GICv3 distributor write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u secure %d: error" gicv3_dist_set_irq(int irq, int level) "GICv3 distributor interrupt %d level changed to %d" -# hw/intc/arm_gicv3_redist.c +# arm_gicv3_redist.c gicv3_redist_read(uint32_t cpu, uint64_t offset, uint64_t data, unsigned size, bool secure) "GICv3 redistributor 0x%x read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u secure %d" gicv3_redist_badread(uint32_t cpu, uint64_t offset, unsigned size, bool secure) "GICv3 redistributor 0x%x read: offset 0x%" PRIx64 " size %u secure %d: error" gicv3_redist_write(uint32_t cpu, uint64_t offset, uint64_t data, unsigned size, bool secure) "GICv3 redistributor 0x%x write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u secure %d" @@ -178,7 +178,7 @@ gicv3_redist_badwrite(uint32_t cpu, uint64_t offset, uint64_t data, unsigned siz gicv3_redist_set_irq(uint32_t cpu, int irq, int level) "GICv3 redistributor 0x%x interrupt %d level changed to %d" gicv3_redist_send_sgi(uint32_t cpu, int irq) "GICv3 redistributor 0x%x pending SGI %d" -# hw/intc/armv7m_nvic.c +# armv7m_nvic.c nvic_recompute_state(int vectpending, int vectpending_prio, int exception_prio) "NVIC state recomputed: vectpending %d vectpending_prio %d exception_prio %d" nvic_recompute_state_secure(int vectpending, bool vectpending_is_s_banked, int vectpending_prio, int exception_prio) "NVIC state recomputed: vectpending %d is_s_banked %d vectpending_prio %d exception_prio %d" nvic_set_prio(int irq, bool secure, uint8_t prio) "NVIC set irq %d secure-bank %d priority %d" @@ -187,7 +187,6 @@ nvic_escalate_prio(int irq, int irqprio, int runprio) "NVIC escalating irq %d to nvic_escalate_disabled(int irq) "NVIC escalating irq %d to HardFault: disabled" nvic_set_pending(int irq, bool secure, bool targets_secure, bool derived, int en, int prio) "NVIC set pending irq %d secure-bank %d targets_secure %d derived %d (enabled: %d priority %d)" nvic_clear_pending(int irq, bool secure, int en, int prio) "NVIC clear pending irq %d secure-bank %d (enabled: %d priority %d)" -nvic_set_pending_level(int irq) "NVIC set pending: irq %d higher prio than vectpending: setting irq line to 1" nvic_acknowledge_irq(int irq, int prio) "NVIC acknowledge IRQ: %d now active (prio %d)" nvic_get_pending_irq_info(int irq, bool secure) "NVIC next IRQ %d: targets_secure: %d" nvic_complete_irq(int irq, bool secure) "NVIC complete IRQ %d (secure %d)" @@ -196,7 +195,7 @@ nvic_set_nmi_level(int level) "NVIC external NMI level set to %d" nvic_sysreg_read(uint64_t addr, uint32_t value, unsigned size) "NVIC sysreg read addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u" nvic_sysreg_write(uint64_t addr, uint32_t value, unsigned size) "NVIC sysreg write addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u" -# hw/intc/heathrow_pic.c +# heathrow_pic.c heathrow_write(uint64_t addr, unsigned int n, uint64_t value) "0x%"PRIx64" %u: 0x%"PRIx64 heathrow_read(uint64_t addr, unsigned int n, uint64_t value) "0x%"PRIx64" %u: 0x%"PRIx64 heathrow_set_irq(int num, int level) "set_irq: num=0x%02x level=%d" diff --git a/hw/intc/xics_spapr.c b/hw/intc/xics_spapr.c index 607e1c167b..9d2b8adef7 100644 --- a/hw/intc/xics_spapr.c +++ b/hw/intc/xics_spapr.c @@ -95,8 +95,15 @@ static target_ulong h_eoi(PowerPCCPU *cpu, SpaprMachineState *spapr, static target_ulong h_ipoll(PowerPCCPU *cpu, SpaprMachineState *spapr, target_ulong opcode, target_ulong *args) { + ICPState *icp = xics_icp_get(XICS_FABRIC(spapr), args[0]); uint32_t mfrr; - uint32_t xirr = icp_ipoll(spapr_cpu_state(cpu)->icp, &mfrr); + uint32_t xirr; + + if (!icp) { + return H_PARAMETER; + } + + xirr = icp_ipoll(icp, &mfrr); args[0] = xirr; args[1] = mfrr; |