From c169e2c287c16d6cdef6f073d12fa02cbd80086c Mon Sep 17 00:00:00 2001
From: Stefano Stabellini <stefano.stabellini@xilinx.com>
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 <stefano.stabellini@xilinx.com>
---
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(-)
@@ -11,10 +11,38 @@
#include <asm/hypercall.h>
-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;
}
/*
@@ -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),
@@ -2,7 +2,8 @@
#define __ASM_ARM_HYPERCALL_H__
#include <public/domctl.h> /* 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);
@@ -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