|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [RFC PATCH 4/6] xen/riscv: Add sbi.c, sbi.h
Signed-off-by: Xie Xun <xiexun162534@xxxxxxxxx>
---
xen/arch/riscv/Makefile | 1 +
xen/arch/riscv/include/asm/sbi.h | 275 ++++++++++++++++++
xen/arch/riscv/sbi.c | 483 +++++++++++++++++++++++++++++++
3 files changed, 759 insertions(+)
create mode 100644 xen/arch/riscv/include/asm/sbi.h
create mode 100644 xen/arch/riscv/sbi.c
diff --git a/xen/arch/riscv/Makefile b/xen/arch/riscv/Makefile
index 3a57556631..c61349818f 100644
--- a/xen/arch/riscv/Makefile
+++ b/xen/arch/riscv/Makefile
@@ -8,6 +8,7 @@ obj-y += irq.o
obj-y += p2m.o
obj-y += mm.o
obj-y += percpu.o
+obj-y += sbi.o
obj-y += setup.o
obj-y += shutdown.o
obj-y += smp.o
diff --git a/xen/arch/riscv/include/asm/sbi.h b/xen/arch/riscv/include/asm/sbi.h
new file mode 100644
index 0000000000..eb727f1a5e
--- /dev/null
+++ b/xen/arch/riscv/include/asm/sbi.h
@@ -0,0 +1,275 @@
+/**
+ * Copyright (c) 2021 Vates SAS.
+ *
+ * Taken from xvisor, modified by Bobby Eshleman (bobby.eshleman@xxxxxxxxx).
+ *
+ * Taken/modified from Xvisor project with the following copyright:
+ *
+ * Copyright (c) 2019 Western Digital Corporation or its affiliates.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __CPU_SBI_H__
+#define __CPU_SBI_H__
+
+#include <xen/types.h>
+
+/* SBI Extension IDs */
+#define SBI_EXT_0_1_SET_TIMER 0x0
+#define SBI_EXT_0_1_CONSOLE_PUTCHAR 0x1
+#define SBI_EXT_0_1_CONSOLE_GETCHAR 0x2
+#define SBI_EXT_0_1_CLEAR_IPI 0x3
+#define SBI_EXT_0_1_SEND_IPI 0x4
+#define SBI_EXT_0_1_REMOTE_FENCE_I 0x5
+#define SBI_EXT_0_1_REMOTE_SFENCE_VMA 0x6
+#define SBI_EXT_0_1_REMOTE_SFENCE_VMA_ASID 0x7
+#define SBI_EXT_0_1_SHUTDOWN 0x8
+#define SBI_EXT_BASE 0x10
+#define SBI_EXT_TIME 0x54494D45
+#define SBI_EXT_IPI 0x735049
+#define SBI_EXT_RFENCE 0x52464E43
+
+/* SBI function IDs for BASE extension */
+#define SBI_EXT_BASE_GET_SPEC_VERSION 0x0
+#define SBI_EXT_BASE_GET_IMP_ID 0x1
+#define SBI_EXT_BASE_GET_IMP_VERSION 0x2
+#define SBI_EXT_BASE_PROBE_EXT 0x3
+#define SBI_EXT_BASE_GET_MVENDORID 0x4
+#define SBI_EXT_BASE_GET_MARCHID 0x5
+#define SBI_EXT_BASE_GET_MIMPID 0x6
+
+#define SBI_SPEC_VERSION_MAJOR_SHIFT 24
+#define SBI_SPEC_VERSION_MAJOR_MASK 0x7f
+#define SBI_SPEC_VERSION_MINOR_MASK 0xffffff
+
+/* SBI function IDs for TIME extension */
+#define SBI_EXT_TIME_SET_TIMER 0x0
+
+/* SBI function IDs for IPI extension */
+#define SBI_EXT_IPI_SEND_IPI 0x0
+
+/* SBI function IDs for RFENCE extension */
+#define SBI_EXT_RFENCE_REMOTE_FENCE_I 0x0
+#define SBI_EXT_RFENCE_REMOTE_SFENCE_VMA 0x1
+#define SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID 0x2
+#define SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA 0x3
+#define SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA_VMID 0x4
+#define SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA 0x5
+#define SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA_ASID 0x6
+
+#define SBI_EXT_VENDOR_START 0x09000000
+#define SBI_EXT_VENDOR_END 0x09FFFFFF
+
+/* SBI return error codes */
+#define SBI_SUCCESS 0
+#define SBI_ERR_FAILURE -1
+#define SBI_ERR_NOT_SUPPORTED -2
+#define SBI_ERR_INVALID_PARAM -3
+#define SBI_ERR_DENIED -4
+#define SBI_ERR_INVALID_ADDRESS -5
+
+#define SBI_SPEC_VERSION_DEFAULT 0x1
+
+struct cpumask;
+
+struct sbiret {
+ long error;
+ long value;
+};
+
+struct sbiret sbi_ecall(int ext, int fid, unsigned long arg0,
+ unsigned long arg1, unsigned long arg2,
+ unsigned long arg3, unsigned long arg4,
+ unsigned long arg5);
+
+/**
+ * Convert SBI spec error code into Xvisor error code
+ *
+ * @return errno error code
+ */
+int sbi_err_map_xvisor_errno(int err);
+
+/**
+ * Convert logical CPU mask to hardware HART mask
+ *
+ * @param cmask input logical CPU mask
+ * @param hmask output hardware HART mask
+ */
+void sbi_cpumask_to_hartmask(const struct cpumask *cmask,
+ struct cpumask *hmask);
+
+/**
+ * Writes given character to the console device.
+ *
+ * @param ch The data to be written to the console.
+ */
+void sbi_console_putchar(int ch);
+
+/**
+ * Reads a character from console device.
+ *
+ * @return the character read from console
+ */
+int sbi_console_getchar(void);
+
+/**
+ * Remove all the harts from executing supervisor code.
+ */
+void sbi_shutdown(void);
+
+/**
+ * Clear any pending IPIs for the calling HART.
+ */
+void sbi_clear_ipi(void);
+
+/**
+ * Send IPIs to a set of target HARTs.
+ *
+ * @param hart_mask mask representing set of target HARTs
+ */
+void sbi_send_ipi(const unsigned long *hart_mask);
+
+/**
+ * Program the timer for next timer event.
+ *
+ * @param stime_value Timer value after which next timer event should fire.
+ */
+void sbi_set_timer(u64 stime_value);
+
+/**
+ * Send FENCE_I to a set of target HARTs.
+ *
+ * @param hart_mask mask representing set of target HARTs
+ */
+void sbi_remote_fence_i(const unsigned long *hart_mask);
+
+/**
+ * Send SFENCE_VMA to a set of target HARTs.
+ *
+ * @param hart_mask mask representing set of target HARTs
+ * @param start virtual address start
+ * @param size virtual address size
+ */
+void sbi_remote_sfence_vma(const unsigned long *hart_mask,
+ unsigned long start,
+ unsigned long size);
+
+/**
+ * Send SFENCE_VMA_ASID to a set of target HARTs.
+ *
+ * @param hart_mask mask representing set of target HARTs
+ * @param start virtual address start
+ * @param size virtual address size
+ * @param asid address space ID
+ */
+void sbi_remote_sfence_vma_asid(const unsigned long *hart_mask,
+ unsigned long start,
+ unsigned long size,
+ unsigned long asid);
+
+/**
+ * Send HFENCE_GVMA to a set of target HARTs.
+ *
+ * @param hart_mask mask representing set of target HARTs
+ * @param start guest physical address start
+ * @param size guest physical address size
+ */
+void sbi_remote_hfence_gvma(const unsigned long *hart_mask,
+ unsigned long start,
+ unsigned long size);
+
+/**
+ * Send HFENCE_GVMA_VMID to a set of target HARTs.
+ *
+ * @param hart_mask mask representing set of target HARTs
+ * @param start guest physical address start
+ * @param size guest physical address size
+ * @param vmid virtual machine ID
+ */
+void sbi_remote_hfence_gvma_vmid(const unsigned long *hart_mask,
+ unsigned long start,
+ unsigned long size,
+ unsigned long vmid);
+
+/**
+ * Send HFENCE_VVMA to a set of target HARTs.
+ *
+ * @param hart_mask mask representing set of target HARTs
+ * @param start virtual address start
+ * @param size virtual address size
+ */
+void sbi_remote_hfence_vvma(const unsigned long *hart_mask,
+ unsigned long start,
+ unsigned long size);
+
+/**
+ * Send HFENCE_VVMA_ASID to a set of target HARTs.
+ *
+ * @param hart_mask mask representing set of target HARTs
+ * @param start virtual address start
+ * @param size virtual address size
+ * @param asid address space ID
+ */
+void sbi_remote_hfence_vvma_asid(const unsigned long *hart_mask,
+ unsigned long start,
+ unsigned long size,
+ unsigned long asid);
+
+/**
+ * Check given SBI extension is supported or not.
+ *
+ * @param ext extension ID
+ * @return >= 0 for supported AND -EOPNOTSUPP for not-supported
+ */
+int sbi_probe_extension(long ext);
+
+/**
+ * Check underlying SBI implementation is v0.1 only
+ *
+ * @return 1 for SBI v0.1 AND 0 for higer version
+ */
+int sbi_spec_is_0_1(void);
+
+/**
+ * Check underlying SBI implementation has v0.2 RFENCE
+ *
+ * @return 1 for supported AND 0 for not-supported
+ */
+int sbi_has_0_2_rfence(void);
+
+/**
+ * Get SBI spec major version
+ *
+ * @return major version number
+ */
+unsigned long sbi_major_version(void);
+
+/**
+ * Get SBI spec minor version
+ *
+ * @return minor version number
+ */
+unsigned long sbi_minor_version(void);
+
+/**
+ * Initialize SBI library
+ *
+ * @return 0 on success, otherwise negative errno on failure
+ */
+int sbi_init(void);
+
+#endif // __CPU_SBI_H__
diff --git a/xen/arch/riscv/sbi.c b/xen/arch/riscv/sbi.c
new file mode 100644
index 0000000000..be5f337a88
--- /dev/null
+++ b/xen/arch/riscv/sbi.c
@@ -0,0 +1,483 @@
+/**
+ * Taken and modified from the xvisor project with the copyright Copyright (c)
+ * 2019 Western Digital Corporation or its affiliates and author Anup Patel
+ * (anup.patel@xxxxxxx).
+ *
+ * Modified by Bobby Eshleman (bobby.eshleman@xxxxxxxxx).
+ *
+ * Copyright (c) 2019 Western Digital Corporation or its affiliates.
+ * Copyright (c) 2021 Vates SAS.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <xen/errno.h>
+#include <xen/init.h>
+#include <xen/smp.h>
+
+#include <asm/system.h>
+#include <asm/sbi.h>
+
+static unsigned long sbi_spec_version = SBI_SPEC_VERSION_DEFAULT;
+
+struct sbiret sbi_ecall(int ext, int fid, unsigned long arg0,
+ unsigned long arg1, unsigned long arg2,
+ unsigned long arg3, unsigned long arg4,
+ unsigned long arg5)
+{
+ struct sbiret ret;
+
+ register unsigned long a0 asm ("a0") = (unsigned long)(arg0);
+ register unsigned long a1 asm ("a1") = (unsigned long)(arg1);
+ register unsigned long a2 asm ("a2") = (unsigned long)(arg2);
+ register unsigned long a3 asm ("a3") = (unsigned long)(arg3);
+ register unsigned long a4 asm ("a4") = (unsigned long)(arg4);
+ register unsigned long a5 asm ("a5") = (unsigned long)(arg5);
+ register unsigned long a6 asm ("a6") = (unsigned long)(fid);
+ register unsigned long a7 asm ("a7") = (unsigned long)(ext);
+ asm volatile ("ecall"
+ : "+r" (a0), "+r" (a1)
+ : "r" (a2), "r" (a3), "r" (a4), "r" (a5), "r" (a6), "r"
(a7)
+ : "memory");
+ ret.error = a0;
+ ret.value = a1;
+
+ return ret;
+}
+
+int sbi_err_map_xen_errno(int err)
+{
+ switch (err) {
+ case SBI_SUCCESS:
+ return 0;
+ case SBI_ERR_DENIED:
+ return -EACCES;
+ case SBI_ERR_INVALID_PARAM:
+ return -EINVAL;
+ case SBI_ERR_INVALID_ADDRESS:
+ return -EFAULT;
+ case SBI_ERR_NOT_SUPPORTED:
+ case SBI_ERR_FAILURE:
+ default:
+ return -EOPNOTSUPP;
+ };
+}
+
+void sbi_cpumask_to_hartmask(const struct cpumask *cmask,
+ struct cpumask *hmask)
+{
+ u32 cpu;
+ unsigned long hart;
+
+ if (!cmask || !hmask)
+ return;
+
+ cpumask_clear(hmask);
+ for_each_cpu(cpu, cmask) {
+ if (CONFIG_NR_CPUS <= cpu) {
+ printk(XENLOG_ERR "SBI: invalid hart=%lu for cpu=%d\n",
+ hart, cpu);
+ continue;
+ }
+ hart = pcpu_info[cpu].processor_id;
+ cpumask_set_cpu(hart, hmask);
+ }
+}
+
+void sbi_console_putchar(int ch)
+{
+ sbi_ecall(SBI_EXT_0_1_CONSOLE_PUTCHAR, 0, ch, 0, 0, 0, 0, 0);
+}
+
+int sbi_console_getchar(void)
+{
+ struct sbiret ret;
+
+ ret = sbi_ecall(SBI_EXT_0_1_CONSOLE_GETCHAR, 0, 0, 0, 0, 0, 0, 0);
+
+ return ret.error;
+}
+
+void sbi_shutdown(void)
+{
+ sbi_ecall(SBI_EXT_0_1_SHUTDOWN, 0, 0, 0, 0, 0, 0, 0);
+}
+
+void sbi_clear_ipi(void)
+{
+ sbi_ecall(SBI_EXT_0_1_CLEAR_IPI, 0, 0, 0, 0, 0, 0, 0);
+}
+
+static int __sbi_send_ipi_v01(const unsigned long *hart_mask)
+{
+ sbi_ecall(SBI_EXT_0_1_SEND_IPI, 0,
+ (unsigned long)hart_mask, 0, 0, 0, 0, 0);
+ return 0;
+}
+
+static void __sbi_set_timer_v01(u64 stime_value)
+{
+#ifdef CONFIG_RISCV_64
+ sbi_ecall(SBI_EXT_0_1_SET_TIMER, 0, stime_value, 0, 0, 0, 0, 0);
+#else
+ sbi_ecall(SBI_EXT_0_1_SET_TIMER, 0, stime_value,
+ stime_value >> 32, 0, 0, 0, 0);
+#endif
+}
+
+static int __sbi_rfence_v01(unsigned long fid,
+ const unsigned long *hart_mask,
+ unsigned long start, unsigned long size,
+ unsigned long arg4, unsigned long arg5)
+{
+ int result = 0;
+
+ switch (fid) {
+ case SBI_EXT_RFENCE_REMOTE_FENCE_I:
+ sbi_ecall(SBI_EXT_0_1_REMOTE_FENCE_I, 0,
+ (unsigned long)hart_mask, 0, 0, 0, 0, 0);
+ break;
+ case SBI_EXT_RFENCE_REMOTE_SFENCE_VMA:
+ sbi_ecall(SBI_EXT_0_1_REMOTE_SFENCE_VMA, 0,
+ (unsigned long)hart_mask, start, size,
+ 0, 0, 0);
+ break;
+ case SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID:
+ sbi_ecall(SBI_EXT_0_1_REMOTE_SFENCE_VMA_ASID, 0,
+ (unsigned long)hart_mask, start, size,
+ arg4, 0, 0);
+ break;
+ default:
+ printk("%s: unknown function ID [%lu]\n", __func__, fid);
+ result = -EINVAL;
+ break;
+ };
+
+ return result;
+}
+
+static void __sbi_set_timer_v02(u64 stime_value)
+{
+#ifdef CONFIG_RISCV_64
+ sbi_ecall(SBI_EXT_TIME, SBI_EXT_TIME_SET_TIMER, stime_value, 0,
+ 0, 0, 0, 0);
+#else
+ sbi_ecall(SBI_EXT_TIME, SBI_EXT_TIME_SET_TIMER, stime_value,
+ stime_value >> 32, 0, 0, 0, 0);
+#endif
+}
+
+static int __sbi_send_ipi_v02(const unsigned long *hart_mask)
+{
+ struct cpumask tmask;
+ unsigned long hart, hmask, hbase;
+ struct sbiret ret = {0};
+ int result;
+
+ if (!hart_mask) {
+ sbi_cpumask_to_hartmask(&cpu_online_map, &tmask);
+ hart_mask = cpumask_bits(&tmask);
+ }
+
+ hmask = hbase = 0;
+ for_each_set_bit(hart, hart_mask, CONFIG_NR_CPUS) {
+ if (hmask && ((hbase + BITS_PER_LONG) <= hart)) {
+ ret = sbi_ecall(SBI_EXT_IPI, SBI_EXT_IPI_SEND_IPI,
+ hmask, hbase, 0, 0, 0, 0);
+ if (ret.error) {
+ result = sbi_err_map_xen_errno(ret.error);
+ printk("%s: hmask=0x%lx hbase=%lu failed "
+ "(error %d)\n", __func__, hmask,
+ hbase, result);
+ return result;
+ }
+ hmask = hbase = 0;
+ }
+ if (!hmask) {
+ hbase = hart;
+ }
+ hmask |= 1UL << (hart - hbase);
+ }
+ if (hmask) {
+ ret = sbi_ecall(SBI_EXT_IPI, SBI_EXT_IPI_SEND_IPI,
+ hmask, hbase, 0, 0, 0, 0);
+ if (ret.error) {
+ result = sbi_err_map_xen_errno(ret.error);
+ printk("%s: hmask=0x%lx hbase=%lu failed "
+ "(error %d)\n", __func__, hmask,
+ hbase, result);
+ return result;
+ }
+ }
+
+ return 0;
+}
+
+static int __sbi_rfence_v02_real(unsigned long fid,
+ unsigned long hmask, unsigned long hbase,
+ unsigned long start, unsigned long size,
+ unsigned long arg4)
+{
+ struct sbiret ret = {0};
+ int result = 0;
+
+ switch (fid) {
+ case SBI_EXT_RFENCE_REMOTE_FENCE_I:
+ ret = sbi_ecall(SBI_EXT_RFENCE, fid, hmask, hbase,
+ 0, 0, 0, 0);
+ break;
+ case SBI_EXT_RFENCE_REMOTE_SFENCE_VMA:
+ ret = sbi_ecall(SBI_EXT_RFENCE, fid, hmask, hbase,
+ start, size, 0, 0);
+ break;
+ case SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID:
+ ret = sbi_ecall(SBI_EXT_RFENCE, fid, hmask, hbase,
+ start, size, arg4, 0);
+ break;
+ case SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA:
+ ret = sbi_ecall(SBI_EXT_RFENCE, fid, hmask, hbase,
+ start, size, 0, 0);
+ break;
+ case SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA_VMID:
+ ret = sbi_ecall(SBI_EXT_RFENCE, fid, hmask, hbase,
+ start, size, arg4, 0);
+ break;
+ case SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA:
+ ret = sbi_ecall(SBI_EXT_RFENCE, fid, hmask, hbase,
+ start, size, 0, 0);
+ break;
+ case SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA_ASID:
+ ret = sbi_ecall(SBI_EXT_RFENCE, fid, hmask, hbase,
+ start, size, arg4, 0);
+ break;
+ default:
+ printk("%s: unknown function ID [%lu]\n",
+ __func__, fid);
+ result = -EINVAL;
+ break;
+ };
+
+ if (ret.error) {
+ result = sbi_err_map_xen_errno(ret.error);
+ printk("%s: hbase=%lu hmask=0x%lx failed (error %d)\n",
+ __func__, hbase, hmask, result);
+ }
+
+ return result;
+}
+
+static int __sbi_rfence_v02(unsigned long fid,
+ const unsigned long *hart_mask,
+ unsigned long start, unsigned long size,
+ unsigned long arg4, unsigned long arg5)
+{
+ struct cpumask tmask;
+ unsigned long hart, hmask, hbase;
+ int result;
+
+ if (!hart_mask) {
+ sbi_cpumask_to_hartmask(&cpu_online_map, &tmask);
+ hart_mask = cpumask_bits(&tmask);
+ }
+
+ hmask = hbase = 0;
+ for_each_set_bit(hart, hart_mask, CONFIG_NR_CPUS) {
+ if (hmask && ((hbase + BITS_PER_LONG) <= hart)) {
+ result = __sbi_rfence_v02_real(fid, hmask, hbase,
+ start, size, arg4);
+ if (result)
+ return result;
+ hmask = hbase = 0;
+ }
+ if (!hmask) {
+ hbase = hart;
+ }
+ hmask |= 1UL << (hart - hbase);
+ }
+ if (hmask) {
+ result = __sbi_rfence_v02_real(fid, hmask, hbase,
+ start, size, arg4);
+ if (result)
+ return result;
+ }
+
+ return 0;
+}
+
+static void (*__sbi_set_timer)(u64 stime) = __sbi_set_timer_v01;
+static int (*__sbi_send_ipi)(const unsigned long *hart_mask) =
+ __sbi_send_ipi_v01;
+static int (*__sbi_rfence)(unsigned long fid,
+ const unsigned long *hart_mask,
+ unsigned long start, unsigned long size,
+ unsigned long arg4, unsigned long arg5) = __sbi_rfence_v01;
+
+void sbi_send_ipi(const unsigned long *hart_mask)
+{
+ __sbi_send_ipi(hart_mask);
+}
+
+void sbi_set_timer(u64 stime_value)
+{
+ __sbi_set_timer(stime_value);
+}
+
+void sbi_remote_fence_i(const unsigned long *hart_mask)
+{
+ __sbi_rfence(SBI_EXT_RFENCE_REMOTE_FENCE_I,
+ hart_mask, 0, 0, 0, 0);
+}
+
+void sbi_remote_sfence_vma(const unsigned long *hart_mask,
+ unsigned long start,
+ unsigned long size)
+{
+ __sbi_rfence(SBI_EXT_RFENCE_REMOTE_SFENCE_VMA,
+ hart_mask, start, size, 0, 0);
+}
+
+void sbi_remote_sfence_vma_asid(const unsigned long *hart_mask,
+ unsigned long start,
+ unsigned long size,
+ unsigned long asid)
+{
+ __sbi_rfence(SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID,
+ hart_mask, start, size, asid, 0);
+}
+
+void sbi_remote_hfence_gvma(const unsigned long *hart_mask,
+ unsigned long start,
+ unsigned long size)
+{
+ __sbi_rfence(SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA,
+ hart_mask, start, size, 0, 0);
+}
+
+void sbi_remote_hfence_gvma_vmid(const unsigned long *hart_mask,
+ unsigned long start,
+ unsigned long size,
+ unsigned long vmid)
+{
+ __sbi_rfence(SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA_VMID,
+ hart_mask, start, size, vmid, 0);
+}
+
+void sbi_remote_hfence_vvma(const unsigned long *hart_mask,
+ unsigned long start,
+ unsigned long size)
+{
+ __sbi_rfence(SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA,
+ hart_mask, start, size, 0, 0);
+}
+
+void sbi_remote_hfence_vvma_asid(const unsigned long *hart_mask,
+ unsigned long start,
+ unsigned long size,
+ unsigned long asid)
+{
+ __sbi_rfence(SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA_ASID,
+ hart_mask, start, size, asid, 0);
+}
+
+static long sbi_ext_base_func(long fid)
+{
+ struct sbiret ret;
+
+ ret = sbi_ecall(SBI_EXT_BASE, fid, 0, 0, 0, 0, 0, 0);
+ if (!ret.error)
+ return ret.value;
+ else
+ return ret.error;
+}
+
+#define sbi_get_spec_version() \
+ sbi_ext_base_func(SBI_EXT_BASE_GET_SPEC_VERSION)
+
+#define sbi_get_firmware_id() \
+ sbi_ext_base_func(SBI_EXT_BASE_GET_IMP_ID)
+
+#define sbi_get_firmware_version() \
+ sbi_ext_base_func(SBI_EXT_BASE_GET_IMP_VERSION)
+
+int sbi_probe_extension(long extid)
+{
+ struct sbiret ret;
+
+ ret = sbi_ecall(SBI_EXT_BASE, SBI_EXT_BASE_PROBE_EXT, extid,
+ 0, 0, 0, 0, 0);
+ if (!ret.error && ret.value)
+ return ret.value;
+
+ return -EOPNOTSUPP;
+}
+
+int sbi_spec_is_0_1(void)
+{
+ return (sbi_spec_version == SBI_SPEC_VERSION_DEFAULT) ? 1 : 0;
+}
+
+int sbi_has_0_2_rfence(void)
+{
+ return (__sbi_rfence == __sbi_rfence_v01) ? 0 : 1;
+}
+
+unsigned long sbi_major_version(void)
+{
+ return (sbi_spec_version >> SBI_SPEC_VERSION_MAJOR_SHIFT) &
+ SBI_SPEC_VERSION_MAJOR_MASK;
+}
+
+unsigned long sbi_minor_version(void)
+{
+ return sbi_spec_version & SBI_SPEC_VERSION_MINOR_MASK;
+}
+
+int __init sbi_init(void)
+{
+ int ret;
+
+ ret = sbi_get_spec_version();
+ if (ret > 0)
+ sbi_spec_version = ret;
+
+ printk("SBI specification v%lu.%lu detected\n",
+ sbi_major_version(), sbi_minor_version());
+
+ if (!sbi_spec_is_0_1()) {
+ printk("SBI implementation ID=0x%lx Version=0x%lx\n",
+ sbi_get_firmware_id(), sbi_get_firmware_version());
+ if (sbi_probe_extension(SBI_EXT_TIME) > 0) {
+ __sbi_set_timer = __sbi_set_timer_v02;
+ printk("SBI v0.2 TIME extension detected\n");
+ }
+ if (sbi_probe_extension(SBI_EXT_IPI) > 0) {
+ __sbi_send_ipi = __sbi_send_ipi_v02;
+ printk("SBI v0.2 IPI extension detected\n");
+ }
+ if (sbi_probe_extension(SBI_EXT_RFENCE) > 0) {
+ __sbi_rfence = __sbi_rfence_v02;
+ printk("SBI v0.2 RFENCE extension detected\n");
+ }
+ }
+
+ if (!sbi_has_0_2_rfence()) {
+ printk("WARNING: SBI v0.2 RFENCE not available !\n");
+ }
+
+ return 0;
+}
+
+__initcall(sbi_init);
--
2.30.2
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |