On RISC-V, there's no possibility to parameterise IPIs resp. enrich them
with some userdata. Great. We need to do it in software...

We differentiate between two IPI types in software: IPI_CAUSE_MGMT, and
IPI_CAUSE_GUEST.

When a guest sends an IPI to a HART within the cell, the HV will trap,
and we forward the IPI call to the SBI. Before, we set the cause to
IPI_CAUSE_GUEST.

Follow the same logic for management IPIs accordingly.

Signed-off-by: Ralf Ramsauer <ralf.ramsa...@oth-regensburg.de>
---
 hypervisor/arch/riscv/control.c | 33 +++++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)

diff --git a/hypervisor/arch/riscv/control.c b/hypervisor/arch/riscv/control.c
index b848994b..7d4c31be 100644
--- a/hypervisor/arch/riscv/control.c
+++ b/hypervisor/arch/riscv/control.c
@@ -11,6 +11,8 @@
  */
 
 #include <jailhouse/control.h>
+#include <jailhouse/printk.h>
+#include <asm/sbi.h>
 
 int arch_cell_create(struct cell *cell)
 {
@@ -68,4 +70,35 @@ void arch_park_cpu(unsigned int cpu_id)
 
 void arch_send_event(struct public_per_cpu *target_data)
 {
+       struct sbiret result;
+
+       /*
+        * For sending an event to a remote HART, we need two conditions to be
+        * set:
+        *   1. We have to grab the CPU's control lock. Having the control lock
+        *      ensures that the CPU is currently not processing any other IPI.
+        *      If the CPU is processing an IPI, then we have to busy wait for
+        *      completion.
+        *   2. target_data->ipi_cause must be NONE at the moment of grabbing
+        *      the lock. This ensures that no other CPU enqueued an IPI
+        *      before.
+        */
+retry:
+       spin_lock(&target_data->control_lock);
+       if (target_data->ipi_cause != IPI_CAUSE_NONE) {
+               spin_unlock(&target_data->control_lock);
+               goto retry;
+       }
+
+       target_data->ipi_cause = IPI_CAUSE_MGMT;
+       memory_barrier();
+       spin_unlock(&target_data->control_lock);
+
+       result = sbi_send_ipi(1UL << (target_data->phys_id % BITS_PER_LONG),
+                             target_data->phys_id / BITS_PER_LONG);
+       if (result.error != SBI_SUCCESS) {
+               printk("IPI send to HART %lu failed: %ld\n",
+                      target_data->phys_id, result.error);
+               panic_stop();
+       }
 }
-- 
2.40.1

-- 
You received this message because you are subscribed to the Google Groups 
"Jailhouse" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to jailhouse-dev+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/jailhouse-dev/20230519204033.643200-42-ralf.ramsauer%40oth-regensburg.de.

Reply via email to