Add an external interface to trigger an SDEI event bound to an interrupt by providing GIC interrupt ID.
Signed-off-by: Heyi Guo <guoh...@huawei.com> Cc: Peter Maydell <peter.mayd...@linaro.org> Cc: Dave Martin <dave.mar...@arm.com> Cc: Marc Zyngier <marc.zyng...@arm.com> Cc: Mark Rutland <mark.rutl...@arm.com> Cc: James Morse <james.mo...@arm.com> --- target/arm/sdei.c | 37 +++++++++++++++++++++++++++++++++++++ target/arm/sdei.h | 7 +++++++ 2 files changed, 44 insertions(+) diff --git a/target/arm/sdei.c b/target/arm/sdei.c index 6af4a9044b..713ac97775 100644 --- a/target/arm/sdei.c +++ b/target/arm/sdei.c @@ -476,6 +476,28 @@ static int64_t sdei_version(QemuSDEState *s, CPUState *cs, struct kvm_run *run) (0ULL << SDEI_VERSION_MINOR_SHIFT); } +static bool inject_event(QemuSDEState *s, CPUState *cs, int32_t event, int irq) +{ + QemuSDE *sde; + + if (event < 0) { + return false; + } + sde = get_sde_no_check(s, event, cs); + if (sde->event_id == SDEI_INVALID_EVENT_ID) { + put_sde(sde, cs); + return false; + } + if (irq > 0 && sde->prop->interrupt != irq) { + /* Someone unbinds the interrupt! */ + put_sde(sde, cs); + return false; + } + sde->pending = true; + dispatch_single(s, sde, cs); + return true; +} + static int64_t unregister_single_sde(QemuSDEState *s, int32_t event, CPUState *cs, bool force) { @@ -1104,6 +1126,21 @@ void sdei_handle_request(CPUState *cs, struct kvm_run *run) } } +bool trigger_sdei_by_irq(int cpu, int irq) +{ + QemuSDEState *s = sde_state; + + if (!s || irq >= ARRAY_SIZE(s->irq_map)) { + return false; + } + + if (s->irq_map[irq] == SDEI_INVALID_EVENT_ID) { + return false; + } + + return inject_event(s, qemu_get_cpu(cpu), s->irq_map[irq], irq); +} + static void sde_array_init(QemuSDE **array, int count) { int i; diff --git a/target/arm/sdei.h b/target/arm/sdei.h index 828f70bbf1..5ecc32d667 100644 --- a/target/arm/sdei.h +++ b/target/arm/sdei.h @@ -31,4 +31,11 @@ void sdei_handle_request(CPUState *cs, struct kvm_run *run); +/* + * Trigger an SDEI event bound to an interrupt. + * Return true if event has been triggered successfully. + * Return false if event has not been triggered for some reason. + */ +bool trigger_sdei_by_irq(int cpu, int irq); + #endif -- 2.19.1