summaryrefslogtreecommitdiff
path: root/lib/sbi_ipi.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sbi_ipi.c')
-rw-r--r--lib/sbi_ipi.c82
1 files changed, 82 insertions, 0 deletions
diff --git a/lib/sbi_ipi.c b/lib/sbi_ipi.c
new file mode 100644
index 0000000..f3e68de
--- /dev/null
+++ b/lib/sbi_ipi.c
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2018 Western Digital Corporation or its affiliates.
+ *
+ * Authors:
+ * Anup Patel <anup.patel@wdc.com>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <sbi/riscv_asm.h>
+#include <sbi/riscv_barrier.h>
+#include <sbi/sbi_hart.h>
+#include <sbi/sbi_ipi.h>
+#include <sbi/sbi_platform.h>
+#include <sbi/sbi_timer.h>
+#include <sbi/sbi_unpriv.h>
+
+int sbi_ipi_send_many(struct sbi_scratch *scratch,
+ u32 hartid, ulong *pmask, u32 event)
+{
+ ulong i, m;
+ struct sbi_scratch *oth;
+ ulong mask = sbi_hart_available_mask();
+ struct sbi_platform *plat = sbi_platform_ptr(scratch);
+
+ if (pmask)
+ mask &= load_ulong(pmask, csr_read(mepc));
+
+ /* send IPIs to everyone */
+ for (i = 0, m = mask; m; i++, m >>= 1) {
+ if ((m & 1) && (i != hartid)) {
+ oth = sbi_hart_id_to_scratch(scratch, i);
+ oth->ipi_type = event;
+ mb();
+ sbi_platform_ipi_inject(plat, i, hartid);
+ if (event != SBI_IPI_EVENT_SOFT)
+ sbi_platform_ipi_sync(plat, i, hartid);
+ }
+ }
+
+ return 0;
+}
+
+void sbi_ipi_clear_smode(struct sbi_scratch *scratch, u32 hartid)
+{
+ csr_clear(mip, MIP_SSIP);
+}
+
+void sbi_ipi_process(struct sbi_scratch *scratch, u32 hartid)
+{
+ struct sbi_platform *plat = sbi_platform_ptr(scratch);
+
+ sbi_platform_ipi_clear(plat, hartid);
+ switch (scratch->ipi_type) {
+ case SBI_IPI_EVENT_SOFT:
+ csr_set(mip, MIP_SSIP);
+ break;
+ case SBI_IPI_EVENT_FENCE_I:
+ __asm__ __volatile("fence.i");
+ break;
+ case SBI_IPI_EVENT_SFENCE_VMA:
+ __asm__ __volatile("sfence.vma");
+ break;
+ case SBI_IPI_EVENT_HALT:
+ sbi_hart_hang();
+ break;
+ };
+ scratch->ipi_type = 0;
+}
+
+int sbi_ipi_warm_init(struct sbi_scratch *scratch, u32 hartid)
+{
+ /* Enable software interrupts */
+ csr_set(mie, MIP_MSIP);
+
+ return sbi_platform_warm_ipi_init(sbi_platform_ptr(scratch), hartid);
+}
+
+int sbi_ipi_cold_init(struct sbi_scratch *scratch)
+{
+ return sbi_platform_cold_ipi_init(sbi_platform_ptr(scratch));
+}