1 /*
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2020 Western Digital Corporation or its affiliates.
5  *
6  * Authors:
7  *   Anup Patel <anup.patel@wdc.com>
8  *   Atish Patra <atish.patra@wdc.com>
9  */
10 
11 #include <sbi/sbi_ecall.h>
12 #include <sbi/sbi_ecall_interface.h>
13 #include <sbi/sbi_error.h>
14 #include <sbi/sbi_hart.h>
15 #include <sbi/sbi_ipi.h>
16 #include <sbi/sbi_timer.h>
17 #include <sbi/sbi_tlb.h>
18 #include <sbi/riscv_asm.h>
19 
sbi_ecall_time_handler(struct sbi_scratch * scratch,unsigned long extid,unsigned long funcid,unsigned long * args,unsigned long * out_val,struct sbi_trap_info * out_trap)20 static int sbi_ecall_time_handler(struct sbi_scratch *scratch,
21 				  unsigned long extid, unsigned long funcid,
22 				  unsigned long *args, unsigned long *out_val,
23 				  struct sbi_trap_info *out_trap)
24 {
25 	int ret = 0;
26 
27 	if (funcid == SBI_EXT_TIME_SET_TIMER) {
28 #if __riscv_xlen == 32
29 		sbi_timer_event_start(scratch,
30 				      (((u64)args[1] << 32) | (u64)args[0]));
31 #else
32 		sbi_timer_event_start(scratch, (u64)args[0]);
33 #endif
34 	} else
35 		ret = SBI_ENOTSUPP;
36 
37 	return ret;
38 }
39 
40 struct sbi_ecall_extension ecall_time = {
41 	.extid_start = SBI_EXT_TIME,
42 	.extid_end = SBI_EXT_TIME,
43 	.handle = sbi_ecall_time_handler,
44 };
45 
sbi_ecall_rfence_handler(struct sbi_scratch * scratch,unsigned long extid,unsigned long funcid,unsigned long * args,unsigned long * out_val,struct sbi_trap_info * out_trap)46 static int sbi_ecall_rfence_handler(struct sbi_scratch *scratch,
47 				    unsigned long extid, unsigned long funcid,
48 				    unsigned long *args, unsigned long *out_val,
49 				    struct sbi_trap_info *out_trap)
50 {
51 	int ret = 0;
52 	struct sbi_tlb_info tlb_info;
53 	u32 source_hart = sbi_current_hartid();
54 
55 	if (funcid >= SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA &&
56 	    funcid <= SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA_ASID)
57 		if (!misa_extension('H'))
58 			return SBI_ENOTSUPP;
59 
60 	switch (funcid) {
61 	case SBI_EXT_RFENCE_REMOTE_FENCE_I:
62 		tlb_info.start  = 0;
63 		tlb_info.size  = 0;
64 		tlb_info.type  = SBI_ITLB_FLUSH;
65 		tlb_info.shart_mask = 1UL << source_hart;
66 		ret = sbi_tlb_request(scratch, args[0], args[1], &tlb_info);
67 		break;
68 	case SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA:
69 		tlb_info.start = (unsigned long)args[2];
70 		tlb_info.size  = (unsigned long)args[3];
71 		tlb_info.type  = SBI_TLB_FLUSH_GVMA;
72 		tlb_info.shart_mask = 1UL << source_hart;
73 		ret = sbi_tlb_request(scratch, args[0], args[1], &tlb_info);
74 		break;
75 	case SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA_VMID:
76 		tlb_info.start = (unsigned long)args[2];
77 		tlb_info.size  = (unsigned long)args[3];
78 		tlb_info.asid  = (unsigned long)args[4];
79 		tlb_info.type  = SBI_TLB_FLUSH_GVMA_VMID;
80 		tlb_info.shart_mask = 1UL << source_hart;
81 		ret = sbi_tlb_request(scratch, args[0], args[1], &tlb_info);
82 		break;
83 	case SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA:
84 		tlb_info.start = (unsigned long)args[2];
85 		tlb_info.size  = (unsigned long)args[3];
86 		tlb_info.type  = SBI_TLB_FLUSH_VVMA;
87 		tlb_info.shart_mask = 1UL << source_hart;
88 		ret = sbi_tlb_request(scratch, args[0], args[1], &tlb_info);
89 		break;
90 	case SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA_ASID:
91 		tlb_info.start = (unsigned long)args[2];
92 		tlb_info.size  = (unsigned long)args[3];
93 		tlb_info.asid  = (unsigned long)args[4];
94 		tlb_info.type  = SBI_TLB_FLUSH_VVMA_ASID;
95 		tlb_info.shart_mask = 1UL << source_hart;
96 		ret = sbi_tlb_request(scratch, args[0], args[1], &tlb_info);
97 		break;
98 	case SBI_EXT_RFENCE_REMOTE_SFENCE_VMA:
99 		tlb_info.start = (unsigned long)args[2];
100 		tlb_info.size  = (unsigned long)args[3];
101 		tlb_info.type  = SBI_TLB_FLUSH_VMA;
102 		tlb_info.shart_mask = 1UL << source_hart;
103 		ret = sbi_tlb_request(scratch, args[0], args[1], &tlb_info);
104 		break;
105 	case SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID:
106 		tlb_info.start = (unsigned long)args[2];
107 		tlb_info.size  = (unsigned long)args[3];
108 		tlb_info.asid  = (unsigned long)args[4];
109 		tlb_info.type  = SBI_TLB_FLUSH_VMA_ASID;
110 		tlb_info.shart_mask = 1UL << source_hart;
111 		ret = sbi_tlb_request(scratch, args[0], args[1], &tlb_info);
112 		break;
113 
114 	default:
115 		ret = SBI_ENOTSUPP;
116 	};
117 
118 	return ret;
119 }
120 
121 struct sbi_ecall_extension ecall_rfence = {
122 	.extid_start = SBI_EXT_RFENCE,
123 	.extid_end = SBI_EXT_RFENCE,
124 	.handle = sbi_ecall_rfence_handler,
125 };
126 
sbi_ecall_ipi_handler(struct sbi_scratch * scratch,unsigned long extid,unsigned long funcid,unsigned long * args,unsigned long * out_val,struct sbi_trap_info * out_trap)127 static int sbi_ecall_ipi_handler(struct sbi_scratch *scratch,
128 				 unsigned long extid, unsigned long funcid,
129 				 unsigned long *args, unsigned long *out_val,
130 				 struct sbi_trap_info *out_trap)
131 {
132 	int ret = 0;
133 
134 	if (funcid == SBI_EXT_IPI_SEND_IPI)
135 		ret = sbi_ipi_send_smode(scratch, args[0], args[1]);
136 	else
137 		ret = SBI_ENOTSUPP;
138 
139 	return ret;
140 }
141 
142 struct sbi_ecall_extension ecall_ipi = {
143 	.extid_start = SBI_EXT_IPI,
144 	.extid_end = SBI_EXT_IPI,
145 	.handle = sbi_ecall_ipi_handler,
146 };
147