From c169e2c287c16d6cdef6f073d12fa02cbd80086c Mon Sep 17 00:00:00 2001 From: Stefano Stabellini Date: Mon, 20 Sep 2021 18:33:45 -0700 Subject: [PATCH] xen/arm: introduce PHYSDEV_sgi_send Introduce a simple hypercall to inject an SGI interrupt into a target domain/vcpu. Please note that the implementation doesn't come with any rate limiting. Signed-off-by: Stefano Stabellini --- xen/arch/arm/physdev.c | 34 ++++++++++++++++++++++++++++++--- xen/arch/arm/traps.c | 2 +- xen/include/asm-arm/hypercall.h | 3 ++- xen/include/public/physdev.h | 19 ++++++++++++++++++ 4 files changed, 53 insertions(+), 5 deletions(-) diff --git a/xen/arch/arm/physdev.c b/xen/arch/arm/physdev.c index e91355fe22..2ee29939d2 100644 --- a/xen/arch/arm/physdev.c +++ b/xen/arch/arm/physdev.c @@ -11,10 +11,38 @@ #include -int do_physdev_op(int cmd, XEN_GUEST_HANDLE_PARAM(void) arg) +int do_physdev_op(int cmd, uint8_t sgi, uint16_t domid, uint32_t vcpuid) { - gdprintk(XENLOG_DEBUG, "PHYSDEVOP cmd=%d: not implemented\n", cmd); - return -ENOSYS; + int rc = 0; + struct domain *d; + + if ( cmd != PHYSDEV_sgi_send ) + { + gdprintk(XENLOG_DEBUG, "PHYSDEVOP cmd=%d: not implemented\n", cmd); + return -ENOSYS; + } + + if ( sgi >= 16 ) + { + gdprintk(XENLOG_DEBUG, "PHYSDEVOP_sgi_send invalid sgi=%u\n", sgi); + return -EINVAL; + } + + + d = rcu_lock_domain_by_any_id(domid); + if ( d == NULL ) + return -ESRCH; + if ( vcpuid >= d->max_vcpus ) + { + rc = -EINVAL; + goto out; + } + + vgic_inject_irq(d, d->vcpu[vcpuid], sgi, true); + +out: + rcu_unlock_domain(d); + return rc; } /* diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c index 219ab3c3fb..374ed490a2 100644 --- a/xen/arch/arm/traps.c +++ b/xen/arch/arm/traps.c @@ -1377,7 +1377,7 @@ static arm_hypercall_t arm_hypercall_table[] = { HYPERCALL(xsm_op, 1), HYPERCALL(event_channel_op, 2), HYPERCALL_DEPRECATED(event_channel_op_compat, 1), - HYPERCALL(physdev_op, 2), + HYPERCALL(physdev_op, 4), HYPERCALL_DEPRECATED(physdev_op_compat, 1), HYPERCALL(sysctl, 2), HYPERCALL(hvm_op, 2), diff --git a/xen/include/asm-arm/hypercall.h b/xen/include/asm-arm/hypercall.h index a0c5a31a2f..4299548907 100644 --- a/xen/include/asm-arm/hypercall.h +++ b/xen/include/asm-arm/hypercall.h @@ -2,7 +2,8 @@ #define __ASM_ARM_HYPERCALL_H__ #include /* for arch_do_domctl */ -int do_physdev_op(int cmd, XEN_GUEST_HANDLE_PARAM(void) arg); + +int do_physdev_op(int cmd, uint8_t sgi, uint16_t domid, uint32_t vcpuid); long do_arm_vcpu_op(int cmd, unsigned int vcpuid, XEN_GUEST_HANDLE_PARAM(void) arg); diff --git a/xen/include/public/physdev.h b/xen/include/public/physdev.h index d271766ad0..64458fe7a1 100644 --- a/xen/include/public/physdev.h +++ b/xen/include/public/physdev.h @@ -340,6 +340,25 @@ struct physdev_dbgp_op { typedef struct physdev_dbgp_op physdev_dbgp_op_t; DEFINE_XEN_GUEST_HANDLE(physdev_dbgp_op_t); +/* + * ARM only hypercall to send an SGI to another VM + * + * int physdev_op(int cmd, uint8_t sgi, uint16_t domid, uint32_t vcpuid) + * + * sgi: SGI number of the interrupt to inject + * domid: target domid + * vcpuid: target vcpusid + * + * example: + * mov x0, #30 // PHYSDEV_sgi_send command + * mov x1, #5 // SGI number 5, can chose any in the range 0-15 + * mov x2, #1 // destination domain id (e.g. 0 for dom0, 1 for first domU) + * mov x3, #0 // destination vcpu id (not physical cpu), typically 0 + * mov x16, #33 // hypercall physdev_op number 33 + * hvc 0xEA1 // hypercall command + */ +#define PHYSDEV_sgi_send 30 + /* * Notify that some PIRQ-bound event channels have been unmasked. * ** This command is obsolete since interface version 0x00030202 and is ** -- 2.17.1