sbi.c (a1ff5a7d78a036d6c2178ee5acd6ba4946243800) sbi.c (1ff95eb2bebda50c4c5406caaf201e0fcb24cc8f)
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * SBI initialilization and all extension implementation.
4 *
5 * Copyright (c) 2020 Western Digital Corporation or its affiliates.
6 */
7
8#include <linux/bits.h>
9#include <linux/init.h>
10#include <linux/mm.h>
11#include <linux/pm.h>
12#include <linux/reboot.h>
13#include <asm/sbi.h>
14#include <asm/smp.h>
15#include <asm/tlbflush.h>
16
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * SBI initialilization and all extension implementation.
4 *
5 * Copyright (c) 2020 Western Digital Corporation or its affiliates.
6 */
7
8#include <linux/bits.h>
9#include <linux/init.h>
10#include <linux/mm.h>
11#include <linux/pm.h>
12#include <linux/reboot.h>
13#include <asm/sbi.h>
14#include <asm/smp.h>
15#include <asm/tlbflush.h>
16
17#define CREATE_TRACE_POINTS
18#include <asm/trace.h>
19
20/* default SBI version is 0.1 */
21unsigned long sbi_spec_version __ro_after_init = SBI_SPEC_VERSION_DEFAULT;
22EXPORT_SYMBOL(sbi_spec_version);
23
24static void (*__sbi_set_timer)(uint64_t stime) __ro_after_init;
25static void (*__sbi_send_ipi)(unsigned int cpu) __ro_after_init;
26static int (*__sbi_rfence)(int fid, const struct cpumask *cpu_mask,
27 unsigned long start, unsigned long size,
28 unsigned long arg4, unsigned long arg5) __ro_after_init;
29
17/* default SBI version is 0.1 */
18unsigned long sbi_spec_version __ro_after_init = SBI_SPEC_VERSION_DEFAULT;
19EXPORT_SYMBOL(sbi_spec_version);
20
21static void (*__sbi_set_timer)(uint64_t stime) __ro_after_init;
22static void (*__sbi_send_ipi)(unsigned int cpu) __ro_after_init;
23static int (*__sbi_rfence)(int fid, const struct cpumask *cpu_mask,
24 unsigned long start, unsigned long size,
25 unsigned long arg4, unsigned long arg5) __ro_after_init;
26
30struct sbiret __sbi_ecall(unsigned long arg0, unsigned long arg1,
31 unsigned long arg2, unsigned long arg3,
32 unsigned long arg4, unsigned long arg5,
33 int fid, int ext)
34{
35 struct sbiret ret;
36
37 trace_sbi_call(ext, fid);
38
39 register uintptr_t a0 asm ("a0") = (uintptr_t)(arg0);
40 register uintptr_t a1 asm ("a1") = (uintptr_t)(arg1);
41 register uintptr_t a2 asm ("a2") = (uintptr_t)(arg2);
42 register uintptr_t a3 asm ("a3") = (uintptr_t)(arg3);
43 register uintptr_t a4 asm ("a4") = (uintptr_t)(arg4);
44 register uintptr_t a5 asm ("a5") = (uintptr_t)(arg5);
45 register uintptr_t a6 asm ("a6") = (uintptr_t)(fid);
46 register uintptr_t a7 asm ("a7") = (uintptr_t)(ext);
47 asm volatile ("ecall"
48 : "+r" (a0), "+r" (a1)
49 : "r" (a2), "r" (a3), "r" (a4), "r" (a5), "r" (a6), "r" (a7)
50 : "memory");
51 ret.error = a0;
52 ret.value = a1;
53
54 trace_sbi_return(ext, ret.error, ret.value);
55
56 return ret;
57}
58EXPORT_SYMBOL(__sbi_ecall);
59
60int sbi_err_map_linux_errno(int err)
61{
62 switch (err) {
63 case SBI_SUCCESS:
64 return 0;
65 case SBI_ERR_DENIED:
66 return -EPERM;
67 case SBI_ERR_INVALID_PARAM:
68 return -EINVAL;
69 case SBI_ERR_INVALID_ADDRESS:
70 return -EFAULT;
71 case SBI_ERR_NOT_SUPPORTED:
72 case SBI_ERR_FAILURE:
73 default:
74 return -ENOTSUPP;
75 };
76}
77EXPORT_SYMBOL(sbi_err_map_linux_errno);
78
79#ifdef CONFIG_RISCV_SBI_V01
80static unsigned long __sbi_v01_cpumask_to_hartmask(const struct cpumask *cpu_mask)
81{
82 unsigned long cpuid, hartid;
83 unsigned long hmask = 0;
84
85 /*
86 * There is no maximum hartid concept in RISC-V and NR_CPUS must not be

--- 443 unchanged lines hidden (view full) ---

530 0, 0, 0, 0, 0);
531 if (!ret.error)
532 return ret.value;
533
534 return 0;
535}
536EXPORT_SYMBOL(sbi_probe_extension);
537
27#ifdef CONFIG_RISCV_SBI_V01
28static unsigned long __sbi_v01_cpumask_to_hartmask(const struct cpumask *cpu_mask)
29{
30 unsigned long cpuid, hartid;
31 unsigned long hmask = 0;
32
33 /*
34 * There is no maximum hartid concept in RISC-V and NR_CPUS must not be

--- 443 unchanged lines hidden (view full) ---

478 0, 0, 0, 0, 0);
479 if (!ret.error)
480 return ret.value;
481
482 return 0;
483}
484EXPORT_SYMBOL(sbi_probe_extension);
485
538static long __sbi_base_ecall(int fid)
539{
540 struct sbiret ret;
541
542 ret = sbi_ecall(SBI_EXT_BASE, fid, 0, 0, 0, 0, 0, 0);
543 if (!ret.error)
544 return ret.value;
545 else
546 return sbi_err_map_linux_errno(ret.error);
547}
548
549static inline long sbi_get_spec_version(void)
550{
551 return __sbi_base_ecall(SBI_EXT_BASE_GET_SPEC_VERSION);
552}
553
554static inline long sbi_get_firmware_id(void)
555{
556 return __sbi_base_ecall(SBI_EXT_BASE_GET_IMP_ID);

--- 137 unchanged lines hidden ---
486static inline long sbi_get_spec_version(void)
487{
488 return __sbi_base_ecall(SBI_EXT_BASE_GET_SPEC_VERSION);
489}
490
491static inline long sbi_get_firmware_id(void)
492{
493 return __sbi_base_ecall(SBI_EXT_BASE_GET_IMP_ID);

--- 137 unchanged lines hidden ---