]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/riscv_cpu.c
Update RISCC-V-RV32-SiFive_HiFive1_FreedomStudio project to latest tools and metal...
[freertos] / FreeRTOS / Demo / RISC-V_RV32_SiFive_HiFive1_FreedomStudio / freedom-metal / src / drivers / riscv_cpu.c
1 /* Copyright 2018 SiFive, Inc */
2 /* SPDX-License-Identifier: Apache-2.0 */
3
4 #include <stdint.h>
5 #include <metal/io.h>
6 #include <metal/shutdown.h>
7 #include <metal/machine.h>
8
9 extern void __metal_vector_table();
10 unsigned long long __metal_driver_cpu_mtime_get(struct metal_cpu *cpu);
11 int __metal_driver_cpu_mtimecmp_set(struct metal_cpu *cpu, unsigned long long time);
12
13 struct metal_cpu *__metal_driver_cpu_get(int hartid)
14 {
15     if (hartid < __METAL_DT_MAX_HARTS) {
16         return &(__metal_cpu_table[hartid]->cpu);
17     }
18     return (struct metal_cpu *)NULL;
19 }
20
21 uintptr_t __metal_myhart_id (void)
22 {
23     uintptr_t myhart;
24     __asm__ volatile ("csrr %0, mhartid" : "=r"(myhart));
25     return myhart;
26 }
27
28 void __metal_zero_memory (unsigned char *base, unsigned int size)
29 {
30     volatile unsigned char *ptr;
31     for (ptr = base; ptr < (base + size); ptr++){
32         *ptr = 0;
33     }
34 }
35
36 void __metal_interrupt_global_enable (void) {
37     uintptr_t m;
38     __asm__ volatile ("csrrs %0, mstatus, %1" : "=r"(m) : "r"(METAL_MIE_INTERRUPT));
39 }
40
41 void __metal_interrupt_global_disable (void) {
42     uintptr_t m;
43     __asm__ volatile ("csrrc %0, mstatus, %1" : "=r"(m) : "r"(METAL_MIE_INTERRUPT));
44 }
45
46 void __metal_interrupt_software_enable (void) {
47     uintptr_t m;
48     __asm__ volatile ("csrrs %0, mie, %1" : "=r"(m) : "r"(METAL_LOCAL_INTERRUPT_SW));
49 }
50
51 void __metal_interrupt_software_disable (void) {
52     uintptr_t m;
53     __asm__ volatile ("csrrc %0, mie, %1" : "=r"(m) : "r"(METAL_LOCAL_INTERRUPT_SW));
54 }
55
56 void __metal_interrupt_timer_enable (void) {
57     uintptr_t m;
58     __asm__ volatile ("csrrs %0, mie, %1" : "=r"(m) : "r"(METAL_LOCAL_INTERRUPT_TMR));
59 }
60
61 void __metal_interrupt_timer_disable (void) {
62     uintptr_t m;
63     __asm__ volatile ("csrrc %0, mie, %1" : "=r"(m) : "r"(METAL_LOCAL_INTERRUPT_TMR));
64 }
65
66 void __metal_interrupt_external_enable (void) {
67     uintptr_t m;
68     __asm__ volatile ("csrrs %0, mie, %1" : "=r"(m) : "r"(METAL_LOCAL_INTERRUPT_EXT));
69 }
70
71 void __metal_interrupt_external_disable (void) {
72     unsigned long m;
73     __asm__ volatile ("csrrc %0, mie, %1" : "=r"(m) : "r"(METAL_LOCAL_INTERRUPT_EXT));
74 }
75
76 void __metal_interrupt_local_enable (int id) {
77     uintptr_t b = 1 << id;
78     uintptr_t m;
79     __asm__ volatile ("csrrs %0, mie, %1" : "=r"(m) : "r"(b));
80 }
81
82 void __metal_interrupt_local_disable (int id) {
83     uintptr_t b = 1 << id;
84     uintptr_t m;
85     __asm__ volatile ("csrrc %0, mie, %1" : "=r"(m) : "r"(b));
86 }
87
88 void __metal_default_exception_handler (struct metal_cpu *cpu, int ecode) {
89     metal_shutdown(100);
90 }
91
92 void __metal_default_interrupt_handler (int id, void *priv) {
93     metal_shutdown(200);
94 }
95
96 /* The metal_interrupt_vector_handler() function can be redefined. */
97 void __attribute__((weak, interrupt)) metal_interrupt_vector_handler (void) {
98     metal_shutdown(300);
99 }
100
101 /* The metal_software_interrupt_vector_handler() function can be redefined. */
102 void __attribute__((weak, interrupt)) metal_software_interrupt_vector_handler (void) {
103     void *priv;
104     struct __metal_driver_riscv_cpu_intc *intc;
105     struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
106
107     if ( cpu ) {
108         intc = (struct __metal_driver_riscv_cpu_intc *)
109           __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
110         priv = intc->metal_int_table[METAL_INTERRUPT_ID_SW].exint_data;
111         intc->metal_int_table[METAL_INTERRUPT_ID_SW].handler(METAL_INTERRUPT_ID_SW, priv);
112     }
113 }
114
115 void __metal_default_sw_handler (int id, void *priv) {
116     uintptr_t mcause;
117     struct __metal_driver_riscv_cpu_intc *intc;
118     struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
119
120     __asm__ volatile ("csrr %0, mcause" : "=r"(mcause));
121     if ( cpu ) {
122         intc = (struct __metal_driver_riscv_cpu_intc *)
123           __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
124         intc->metal_exception_table[mcause & METAL_MCAUSE_CAUSE]((struct metal_cpu *)cpu, id);
125     }
126 }
127
128 /* The metal_timer_interrupt_vector_handler() function can be redefined. */
129 void __attribute__((weak, interrupt)) metal_timer_interrupt_vector_handler (void) {
130     void *priv;
131     struct __metal_driver_riscv_cpu_intc *intc;
132     struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
133
134     if ( cpu ) {
135         intc = (struct __metal_driver_riscv_cpu_intc *)
136           __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
137         priv = intc->metal_int_table[METAL_INTERRUPT_ID_TMR].exint_data;
138         intc->metal_int_table[METAL_INTERRUPT_ID_TMR].handler(METAL_INTERRUPT_ID_TMR, priv);
139     }
140 }
141
142 void __metal_default_timer_handler (int id, void *priv) {
143     struct metal_cpu *cpu = __metal_driver_cpu_get(__metal_myhart_id());
144     unsigned long long time = __metal_driver_cpu_mtime_get(cpu);
145
146     /* Set a 10 cycle timer */
147     __metal_driver_cpu_mtimecmp_set(cpu, time + 10);
148 }
149
150 /* The metal_external_interrupt_vector_handler() function can be redefined. */
151 void __attribute__((weak, interrupt)) metal_external_interrupt_vector_handler (void) {
152     void *priv;
153     struct __metal_driver_riscv_cpu_intc *intc;
154     struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
155
156     if ( cpu ) {
157         intc = (struct __metal_driver_riscv_cpu_intc *)
158           __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
159         priv = intc->metal_int_table[METAL_INTERRUPT_ID_EXT].exint_data;
160         intc->metal_int_table[METAL_INTERRUPT_ID_EXT].handler(METAL_INTERRUPT_ID_EXT, priv);
161     }
162 }
163
164 void __metal_exception_handler(void) __attribute__((interrupt, aligned(128)));
165 void __metal_exception_handler (void) {
166     int id;
167     void *priv;
168     uintptr_t mcause, mepc, mtval, mtvec;
169     struct __metal_driver_riscv_cpu_intc *intc;
170     struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
171
172     __asm__ volatile ("csrr %0, mcause" : "=r"(mcause));
173     __asm__ volatile ("csrr %0, mepc" : "=r"(mepc));
174     __asm__ volatile ("csrr %0, mtval" : "=r"(mtval));
175     __asm__ volatile ("csrr %0, mtvec" : "=r"(mtvec));
176
177     if ( cpu ) {
178         intc = (struct __metal_driver_riscv_cpu_intc *)
179           __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
180         id = mcause & METAL_MCAUSE_CAUSE;
181         if (mcause & METAL_MCAUSE_INTR) {
182             if ((id < METAL_INTERRUPT_ID_CSW) ||
183                ((mtvec & METAL_MTVEC_MASK) == METAL_MTVEC_DIRECT)) {
184                 priv = intc->metal_int_table[id].exint_data;
185                 intc->metal_int_table[id].handler(id, priv);
186                 return;
187             }
188             if ((mtvec & METAL_MTVEC_MASK) == METAL_MTVEC_CLIC) {
189                 uintptr_t mtvt;
190                 metal_interrupt_handler_t mtvt_handler;
191
192                 __asm__ volatile ("csrr %0, 0x307" : "=r"(mtvt));
193                 priv = intc->metal_int_table[METAL_INTERRUPT_ID_SW].sub_int;
194                 mtvt_handler = (metal_interrupt_handler_t)*(uintptr_t *)mtvt;
195                 mtvt_handler(id, priv);
196                 return;
197             }
198         } else {
199             intc->metal_exception_table[id]((struct metal_cpu *)cpu, id);
200         }
201     }
202 }
203
204 /* The metal_lc0_interrupt_vector_handler() function can be redefined. */
205 void __attribute__((weak, interrupt)) metal_lc0_interrupt_vector_handler (void) {
206     void *priv;
207     struct __metal_driver_riscv_cpu_intc *intc;
208     struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
209
210     if ( cpu ) {
211         intc = (struct __metal_driver_riscv_cpu_intc *)
212           __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
213         priv = intc->metal_int_table[METAL_INTERRUPT_ID_LC0].exint_data;
214         intc->metal_int_table[METAL_INTERRUPT_ID_LC0].handler(METAL_INTERRUPT_ID_LC0, priv);
215     }
216 }
217
218 /* The metal_lc1_interrupt_vector_handler() function can be redefined. */
219 void __attribute__((weak, interrupt)) metal_lc1_interrupt_vector_handler (void) {
220     void *priv;
221     struct __metal_driver_riscv_cpu_intc *intc;
222     struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
223
224     if ( cpu ) {
225         intc = (struct __metal_driver_riscv_cpu_intc *)
226           __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
227         priv = intc->metal_int_table[METAL_INTERRUPT_ID_LC1].exint_data;
228         intc->metal_int_table[METAL_INTERRUPT_ID_LC1].handler(METAL_INTERRUPT_ID_LC1, priv);
229     }
230 }
231
232 /* The metal_lc2_interrupt_vector_handler() function can be redefined. */
233 void __attribute__((weak, interrupt)) metal_lc2_interrupt_vector_handler (void) {
234     void *priv;
235     struct __metal_driver_riscv_cpu_intc *intc;
236     struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
237
238     if ( cpu ) {
239         intc = (struct __metal_driver_riscv_cpu_intc *)
240           __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
241         priv = intc->metal_int_table[METAL_INTERRUPT_ID_LC2].exint_data;
242         intc->metal_int_table[METAL_INTERRUPT_ID_LC2].handler(METAL_INTERRUPT_ID_LC2, priv);
243     }
244 }
245
246 /* The metal_lc3_interrupt_vector_handler() function can be redefined. */
247 void __attribute__((weak, interrupt)) metal_lc3_interrupt_vector_handler (void) {
248     void *priv;
249     struct __metal_driver_riscv_cpu_intc *intc;
250     struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
251
252     if ( cpu ) {
253         intc = (struct __metal_driver_riscv_cpu_intc *)
254           __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
255         priv = intc->metal_int_table[METAL_INTERRUPT_ID_LC3].exint_data;
256         intc->metal_int_table[METAL_INTERRUPT_ID_LC3].handler(METAL_INTERRUPT_ID_LC3, priv);
257     }
258 }
259
260 /* The metal_lc4_interrupt_vector_handler() function can be redefined. */
261 void __attribute__((weak, interrupt)) metal_lc4_interrupt_vector_handler (void) {
262     void *priv;
263     struct __metal_driver_riscv_cpu_intc *intc;
264     struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
265
266     if ( cpu ) {
267         intc = (struct __metal_driver_riscv_cpu_intc *)
268           __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
269         priv = intc->metal_int_table[METAL_INTERRUPT_ID_LC4].exint_data;
270         intc->metal_int_table[METAL_INTERRUPT_ID_LC4].handler(METAL_INTERRUPT_ID_LC4, priv);
271     }
272 }
273
274 /* The metal_lc5_interrupt_vector_handler() function can be redefined. */
275 void __attribute__((weak, interrupt)) metal_lc5_interrupt_vector_handler (void) {
276     void *priv;
277     struct __metal_driver_riscv_cpu_intc *intc;
278     struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
279
280     if ( cpu ) {
281         intc = (struct __metal_driver_riscv_cpu_intc *)
282           __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
283         priv = intc->metal_int_table[METAL_INTERRUPT_ID_LC5].exint_data;
284         intc->metal_int_table[METAL_INTERRUPT_ID_LC5].handler(METAL_INTERRUPT_ID_LC5, priv);
285     }
286 }
287
288 /* The metal_lc6_interrupt_vector_handler() function can be redefined. */
289 void __attribute__((weak, interrupt)) metal_lc6_interrupt_vector_handler (void) {
290     void *priv;
291     struct __metal_driver_riscv_cpu_intc *intc;
292     struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
293
294     if ( cpu ) {
295         intc = (struct __metal_driver_riscv_cpu_intc *)
296           __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
297         priv = intc->metal_int_table[METAL_INTERRUPT_ID_LC6].exint_data;
298         intc->metal_int_table[METAL_INTERRUPT_ID_LC6].handler(METAL_INTERRUPT_ID_LC6, priv);
299     }
300 }
301
302 /* The metal_lc7_interrupt_vector_handler() function can be redefined. */
303 void __attribute__((weak, interrupt)) metal_lc7_interrupt_vector_handler (void) {
304     void *priv;
305     struct __metal_driver_riscv_cpu_intc *intc;
306     struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
307
308     if ( cpu ) {
309         intc = (struct __metal_driver_riscv_cpu_intc *)
310           __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
311         priv = intc->metal_int_table[METAL_INTERRUPT_ID_LC7].exint_data;
312         intc->metal_int_table[METAL_INTERRUPT_ID_LC7].handler(METAL_INTERRUPT_ID_LC7, priv);
313     }
314 }
315
316 /* The metal_lc8_interrupt_vector_handler() function can be redefined. */
317 void __attribute__((weak, interrupt)) metal_lc8_interrupt_vector_handler (void) {
318     void *priv;
319     struct __metal_driver_riscv_cpu_intc *intc;
320     struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
321
322     if ( cpu ) {
323         intc = (struct __metal_driver_riscv_cpu_intc *)
324           __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
325         priv = intc->metal_int_table[METAL_INTERRUPT_ID_LC8].exint_data;
326         intc->metal_int_table[METAL_INTERRUPT_ID_LC8].handler(METAL_INTERRUPT_ID_LC8, priv);
327     }
328 }
329
330 /* The metal_lc9_interrupt_vector_handler() function can be redefined. */
331 void __attribute__((weak, interrupt)) metal_lc9_interrupt_vector_handler (void) {
332     void *priv;
333     struct __metal_driver_riscv_cpu_intc *intc;
334     struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
335
336     if ( cpu ) {
337         intc = (struct __metal_driver_riscv_cpu_intc *)
338           __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
339         priv = intc->metal_int_table[METAL_INTERRUPT_ID_LC9].exint_data;
340         intc->metal_int_table[METAL_INTERRUPT_ID_LC9].handler(METAL_INTERRUPT_ID_LC9, priv);
341     }
342 }
343
344 /* The metal_lc10_interrupt_vector_handler() function can be redefined. */
345 void __attribute__((weak, interrupt)) metal_lc10_interrupt_vector_handler (void) {
346     void *priv;
347     struct __metal_driver_riscv_cpu_intc *intc;
348     struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
349
350     if ( cpu ) {
351         intc = (struct __metal_driver_riscv_cpu_intc *)
352           __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
353         priv = intc->metal_int_table[METAL_INTERRUPT_ID_LC10].exint_data;
354         intc->metal_int_table[METAL_INTERRUPT_ID_LC10].handler(METAL_INTERRUPT_ID_LC10, priv);
355     }
356 }
357
358 /* The metal_lc11_interrupt_vector_handler() function can be redefined. */
359 void __attribute__((weak, interrupt)) metal_lc11_interrupt_vector_handler (void) {
360     void *priv;
361     struct __metal_driver_riscv_cpu_intc *intc;
362     struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
363
364     if ( cpu ) {
365         intc = (struct __metal_driver_riscv_cpu_intc *)
366           __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
367         priv = intc->metal_int_table[METAL_INTERRUPT_ID_LC11].exint_data;
368         intc->metal_int_table[METAL_INTERRUPT_ID_LC11].handler(METAL_INTERRUPT_ID_LC11, priv);
369     }
370 }
371
372 /* The metal_lc12_interrupt_vector_handler() function can be redefined. */
373 void __attribute__((weak, interrupt)) metal_lc12_interrupt_vector_handler (void) {
374     void *priv;
375     struct __metal_driver_riscv_cpu_intc *intc;
376     struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
377
378     if ( cpu ) {
379         intc = (struct __metal_driver_riscv_cpu_intc *)
380           __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
381         priv = intc->metal_int_table[METAL_INTERRUPT_ID_LC12].exint_data;
382         intc->metal_int_table[METAL_INTERRUPT_ID_LC12].handler(METAL_INTERRUPT_ID_LC12, priv);
383     }
384 }
385
386 /* The metal_lc13_interrupt_vector_handler() function can be redefined. */
387 void __attribute__((weak, interrupt)) metal_lc13_interrupt_vector_handler (void) {
388     void *priv;
389     struct __metal_driver_riscv_cpu_intc *intc;
390     struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
391
392     if ( cpu ) {
393         intc = (struct __metal_driver_riscv_cpu_intc *)
394           __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
395         priv = intc->metal_int_table[METAL_INTERRUPT_ID_LC13].exint_data;
396         intc->metal_int_table[METAL_INTERRUPT_ID_LC13].handler(METAL_INTERRUPT_ID_LC13, priv);
397     }
398 }
399
400 /* The metal_lc14_interrupt_vector_handler() function can be redefined. */
401 void __attribute__((weak, interrupt)) metal_lc14_interrupt_vector_handler (void) {
402     void *priv;
403     struct __metal_driver_riscv_cpu_intc *intc;
404     struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
405
406     if ( cpu ) {
407         intc = (struct __metal_driver_riscv_cpu_intc *)
408           __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
409         priv = intc->metal_int_table[METAL_INTERRUPT_ID_LC14].exint_data;
410         intc->metal_int_table[METAL_INTERRUPT_ID_LC14].handler(METAL_INTERRUPT_ID_LC14, priv);
411     }
412 }
413
414 /* The metal_lc15_interrupt_vector_handler() function can be redefined. */
415 void __attribute__((weak, interrupt)) metal_lc15_interrupt_vector_handler (void) {
416     void *priv;
417     struct __metal_driver_riscv_cpu_intc *intc;
418     struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
419
420     if ( cpu ) {
421         intc = (struct __metal_driver_riscv_cpu_intc *)
422           __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
423         priv = intc->metal_int_table[METAL_INTERRUPT_ID_LC15].exint_data;
424         intc->metal_int_table[METAL_INTERRUPT_ID_LC15].handler(METAL_INTERRUPT_ID_LC15, priv);
425     }
426 }
427
428 metal_vector_mode __metal_controller_interrupt_vector_mode (void)
429 {
430     uintptr_t val;
431
432     asm volatile ("csrr %0, mtvec" : "=r"(val));
433     val &= METAL_MTVEC_MASK;
434
435     switch (val) {
436     case METAL_MTVEC_CLIC:
437         return METAL_SELECTIVE_VECTOR_MODE;
438     case METAL_MTVEC_CLIC_VECTORED:
439         return METAL_HARDWARE_VECTOR_MODE;
440     case METAL_MTVEC_VECTORED:
441         return METAL_VECTOR_MODE;
442     }
443     return METAL_DIRECT_MODE;
444 }
445
446 void __metal_controller_interrupt_vector (metal_vector_mode mode, void *vec_table)
447 {  
448     uintptr_t trap_entry, val;
449
450     __asm__ volatile ("csrr %0, mtvec" : "=r"(val));
451     val &= ~(METAL_MTVEC_CLIC_VECTORED | METAL_MTVEC_CLIC_RESERVED);
452     trap_entry = (uintptr_t)vec_table;
453
454     switch (mode) {
455     case METAL_SELECTIVE_NONVECTOR_MODE:
456     case METAL_SELECTIVE_VECTOR_MODE:
457         __asm__ volatile ("csrw 0x307, %0" :: "r"(trap_entry));
458         __asm__ volatile ("csrw mtvec, %0" :: "r"(val | METAL_MTVEC_CLIC));
459         break;
460     case METAL_HARDWARE_VECTOR_MODE:
461         __asm__ volatile ("csrw 0x307, %0" :: "r"(trap_entry));
462         __asm__ volatile ("csrw mtvec, %0" :: "r"(val | METAL_MTVEC_CLIC_VECTORED));
463         break;
464     case METAL_VECTOR_MODE:
465         __asm__ volatile ("csrw mtvec, %0" :: "r"(trap_entry | METAL_MTVEC_VECTORED));
466         break;
467     case METAL_DIRECT_MODE:
468         __asm__ volatile ("csrw mtvec, %0" :: "r"(trap_entry & ~METAL_MTVEC_CLIC_VECTORED));
469         break;
470     }
471 }
472
473 int __metal_valid_interrupt_id (int id)
474 {
475     switch (id) {
476     case METAL_INTERRUPT_ID_SW:
477     case METAL_INTERRUPT_ID_TMR:
478     case METAL_INTERRUPT_ID_EXT:
479     case METAL_INTERRUPT_ID_LC0:
480     case METAL_INTERRUPT_ID_LC1:
481     case METAL_INTERRUPT_ID_LC2:
482     case METAL_INTERRUPT_ID_LC3:
483     case METAL_INTERRUPT_ID_LC4:
484     case METAL_INTERRUPT_ID_LC5:
485     case METAL_INTERRUPT_ID_LC6:
486     case METAL_INTERRUPT_ID_LC7:
487     case METAL_INTERRUPT_ID_LC8:
488     case METAL_INTERRUPT_ID_LC9:
489     case METAL_INTERRUPT_ID_LC10:
490     case METAL_INTERRUPT_ID_LC11:
491     case METAL_INTERRUPT_ID_LC12:
492     case METAL_INTERRUPT_ID_LC13:
493     case METAL_INTERRUPT_ID_LC14:
494     case METAL_INTERRUPT_ID_LC15:
495         return 1;
496     default:
497         break;
498     }
499
500     return 0;
501 }
502
503  
504 int __metal_local_interrupt_enable (struct metal_interrupt *controller,
505                                   metal_interrupt_id_e id, int enable)
506 {
507     int rc = 0;
508   
509     if ( !controller) {
510         return -1;
511     }
512
513     switch (id) {
514     case METAL_INTERRUPT_ID_BASE:
515         if (enable) {
516             __metal_interrupt_global_enable();
517         } else {
518             __metal_interrupt_global_disable();
519         }
520         break;
521     case METAL_INTERRUPT_ID_SW:
522         if (enable) {
523             __metal_interrupt_software_enable();
524         } else {
525             __metal_interrupt_software_disable();
526         }
527         break;
528     case METAL_INTERRUPT_ID_TMR:
529         if (enable) {
530             __metal_interrupt_timer_enable();
531         } else {
532             __metal_interrupt_timer_disable();
533         }
534         break;
535     case METAL_INTERRUPT_ID_EXT:
536         if (enable) {
537             __metal_interrupt_external_enable();
538         } else {
539             __metal_interrupt_external_disable();
540         }
541         break;
542     case METAL_INTERRUPT_ID_LC0:
543     case METAL_INTERRUPT_ID_LC1:
544     case METAL_INTERRUPT_ID_LC2:
545     case METAL_INTERRUPT_ID_LC3:
546     case METAL_INTERRUPT_ID_LC4:
547     case METAL_INTERRUPT_ID_LC5:
548     case METAL_INTERRUPT_ID_LC6:
549     case METAL_INTERRUPT_ID_LC7:
550     case METAL_INTERRUPT_ID_LC8:
551     case METAL_INTERRUPT_ID_LC9:
552     case METAL_INTERRUPT_ID_LC10:
553     case METAL_INTERRUPT_ID_LC11:
554     case METAL_INTERRUPT_ID_LC12:
555     case METAL_INTERRUPT_ID_LC13:
556     case METAL_INTERRUPT_ID_LC14:
557     case METAL_INTERRUPT_ID_LC15:
558         if (enable) {
559             __metal_interrupt_local_enable(id);
560         } else {
561             __metal_interrupt_local_disable(id);
562         }
563         break;
564     default:
565         rc = -1;
566     }
567     return rc;
568 }
569
570 int __metal_exception_register (struct metal_interrupt *controller,
571                               int ecode, metal_exception_handler_t isr)
572 {
573     struct __metal_driver_riscv_cpu_intc *intc = (void *)(controller);
574
575     if ((ecode < METAL_MAX_EXCEPTION_CODE) && isr) {
576         intc->metal_exception_table[ecode] = isr;
577         return 0;
578     }
579     return -1;
580 }
581
582 void __metal_driver_riscv_cpu_controller_interrupt_init (struct metal_interrupt *controller)
583 {
584     struct __metal_driver_riscv_cpu_intc *intc = (void *)(controller);
585     uintptr_t val;
586
587     if ( !intc->init_done ) {
588         /* Disable and clear all interrupt sources */
589         __asm__ volatile ("csrc mie, %0" :: "r"(-1));
590         __asm__ volatile ("csrc mip, %0" :: "r"(-1));
591
592         /* Read the misa CSR to determine if the delegation registers exist */
593         uintptr_t misa;
594         __asm__ volatile ("csrr %0, misa" : "=r" (misa));
595
596         /* The delegation CSRs exist if user mode interrupts (N extension) or
597          * supervisor mode (S extension) are supported */
598         if((misa & METAL_ISA_N_EXTENSIONS) || (misa & METAL_ISA_S_EXTENSIONS)) {
599             /* Disable interrupt and exception delegation */
600             __asm__ volatile ("csrc mideleg, %0" :: "r"(-1));
601             __asm__ volatile ("csrc medeleg, %0" :: "r"(-1));
602         }
603
604         /* The satp CSR exists if supervisor mode (S extension) is supported */
605         if(misa & METAL_ISA_S_EXTENSIONS) {
606             /* Clear the entire CSR to make sure that satp.MODE = 0 */
607             __asm__ volatile ("csrc satp, %0" :: "r"(-1));
608         }
609
610         /* Default to use direct interrupt, setup sw cb table*/
611         for (int i = 0; i < METAL_MAX_MI; i++) {
612             intc->metal_int_table[i].handler = NULL;
613             intc->metal_int_table[i].sub_int = NULL;
614             intc->metal_int_table[i].exint_data = NULL;
615         }
616         for (int i = 0; i < METAL_MAX_ME; i++) {
617             intc->metal_exception_table[i] = __metal_default_exception_handler;
618         }
619         __metal_controller_interrupt_vector(METAL_DIRECT_MODE, (void *)(uintptr_t)&__metal_exception_handler);
620         __asm__ volatile ("csrr %0, misa" : "=r"(val));
621         if (val & (METAL_ISA_D_EXTENSIONS | METAL_ISA_F_EXTENSIONS | METAL_ISA_Q_EXTENSIONS)) {
622             /* Floating point architecture, so turn on FP register saving*/
623             __asm__ volatile ("csrr %0, mstatus" : "=r"(val));
624             __asm__ volatile ("csrw mstatus, %0" :: "r"(val | METAL_MSTATUS_FS_INIT));
625         }
626         intc->init_done = 1;
627     }
628 }
629
630 int __metal_driver_riscv_cpu_controller_interrupt_register(struct metal_interrupt *controller,
631                                                          int id, metal_interrupt_handler_t isr,
632                                                          void *priv)
633 {
634     int rc = 0;
635     struct __metal_driver_riscv_cpu_intc *intc = (void *)(controller);
636  
637     if ( !__metal_valid_interrupt_id(id) ) {
638         return -11;
639     }
640
641     if (isr) {
642         intc->metal_int_table[id].handler = isr;
643         intc->metal_int_table[id].exint_data = priv;
644     } else {
645         switch (id) {
646         case METAL_INTERRUPT_ID_SW:
647             intc->metal_int_table[id].handler = __metal_default_sw_handler;
648             intc->metal_int_table[id].sub_int = priv;
649           break;
650         case METAL_INTERRUPT_ID_TMR:
651             intc->metal_int_table[id].handler = __metal_default_timer_handler;
652             intc->metal_int_table[id].sub_int = priv;
653           break;
654         case METAL_INTERRUPT_ID_EXT:
655         case METAL_INTERRUPT_ID_LC0:
656         case METAL_INTERRUPT_ID_LC1:
657         case METAL_INTERRUPT_ID_LC2:
658         case METAL_INTERRUPT_ID_LC3:
659         case METAL_INTERRUPT_ID_LC4:
660         case METAL_INTERRUPT_ID_LC5:
661         case METAL_INTERRUPT_ID_LC6:
662         case METAL_INTERRUPT_ID_LC7:
663         case METAL_INTERRUPT_ID_LC8:
664         case METAL_INTERRUPT_ID_LC9:
665         case METAL_INTERRUPT_ID_LC10:
666         case METAL_INTERRUPT_ID_LC11:
667         case METAL_INTERRUPT_ID_LC12:
668         case METAL_INTERRUPT_ID_LC13:
669         case METAL_INTERRUPT_ID_LC14:
670         case METAL_INTERRUPT_ID_LC15:
671             intc->metal_int_table[id].handler = __metal_default_interrupt_handler;
672             intc->metal_int_table[id].sub_int = priv;
673           break;
674         default:
675           rc = -12;
676         }
677     }
678     return rc;
679 }
680
681 int __metal_driver_riscv_cpu_controller_interrupt_enable (struct metal_interrupt *controller,
682                                                         int id)
683 {
684     return __metal_local_interrupt_enable(controller, id, METAL_ENABLE);
685 }
686
687 int __metal_driver_riscv_cpu_controller_interrupt_disable (struct metal_interrupt *controller,
688                                                          int id)
689 {   
690     return __metal_local_interrupt_enable(controller, id, METAL_DISABLE);
691 }
692
693 int __metal_driver_riscv_cpu_controller_interrupt_enable_vector(struct metal_interrupt *controller,
694                                                              int id, metal_vector_mode mode)
695 {
696     struct __metal_driver_riscv_cpu_intc *intc = (void *)(controller);
697
698     if (id == METAL_INTERRUPT_ID_BASE) {
699         if (mode == METAL_DIRECT_MODE) {
700             __metal_controller_interrupt_vector(mode, (void *)(uintptr_t)&__metal_exception_handler);
701             return 0;
702         }   
703         if (mode == METAL_VECTOR_MODE) {
704             __metal_controller_interrupt_vector(mode, (void *)&intc->metal_mtvec_table);
705             return 0;
706         }
707     }
708     return -1;
709 }
710
711 int __metal_driver_riscv_cpu_controller_interrupt_disable_vector(struct metal_interrupt *controller,
712                                                               int id)
713 {
714     if (id == METAL_INTERRUPT_ID_BASE) {
715         __metal_controller_interrupt_vector(METAL_DIRECT_MODE, (void *)(uintptr_t)&__metal_exception_handler);
716         return 0;
717     }
718     return -1;
719 }
720
721 metal_vector_mode __metal_driver_riscv_cpu_controller_get_vector_mode (struct metal_interrupt *controller)
722 {   
723     return __metal_controller_interrupt_vector_mode();
724 }
725
726 int __metal_driver_riscv_cpu_controller_set_vector_mode (struct metal_interrupt *controller,
727                                                          metal_vector_mode mode)
728 {   
729     struct __metal_driver_riscv_cpu_intc *intc = (void *)(controller);
730     ( void ) intc;
731
732     if (mode == METAL_DIRECT_MODE) {
733         __metal_controller_interrupt_vector(mode, (void *)(uintptr_t)&__metal_exception_handler);
734             return 0;
735     }
736     if (mode == METAL_VECTOR_MODE) {
737         __metal_controller_interrupt_vector(mode, (void *)__metal_vector_table);
738         return 0;
739     }
740     return -1;
741 }
742
743 int __metal_driver_riscv_cpu_controller_command_request (struct metal_interrupt *controller,
744                                                        int cmd, void *data)
745 {
746     /* NOP for now, unless local interrupt lines the like of clic, clint, plic */
747     return 0;
748 }
749
750 /* CPU driver !!! */
751
752 unsigned long long __metal_driver_cpu_mcycle_get(struct metal_cpu *cpu)
753 {
754     unsigned long long val = 0;
755
756 #if __riscv_xlen == 32
757     unsigned long hi, hi1, lo;
758
759     __asm__ volatile ("csrr %0, mcycleh" : "=r"(hi));
760     __asm__ volatile ("csrr %0, mcycle" : "=r"(lo));
761     __asm__ volatile ("csrr %0, mcycleh" : "=r"(hi1));
762     if (hi == hi1) {
763         val = ((unsigned long long)hi << 32) | lo;
764     }
765 #else
766     __asm__ volatile ("csrr %0, mcycle" : "=r"(val));
767 #endif
768
769     return val;
770 }
771
772 unsigned long long __metal_driver_cpu_timebase_get(struct metal_cpu *cpu)
773 {
774   int timebase;
775     if (!cpu) {
776         return 0;
777     }
778
779     timebase = __metal_driver_cpu_timebase((struct metal_cpu *)cpu);
780     return timebase;
781 }
782
783 unsigned long long  __metal_driver_cpu_mtime_get (struct metal_cpu *cpu)
784 {
785     unsigned long long time = 0;
786     struct metal_interrupt *tmr_intc;
787     struct __metal_driver_riscv_cpu_intc *intc =
788         (struct __metal_driver_riscv_cpu_intc *)__metal_driver_cpu_interrupt_controller(cpu);
789
790     if (intc) {
791         tmr_intc = intc->metal_int_table[METAL_INTERRUPT_ID_TMR].sub_int;
792         if (tmr_intc) {
793             tmr_intc->vtable->command_request(tmr_intc,
794                                               METAL_TIMER_MTIME_GET, &time);
795         }
796     }
797     return time;
798 }
799
800 int __metal_driver_cpu_mtimecmp_set (struct metal_cpu *cpu, unsigned long long time)
801 {
802     int rc = -1;
803     struct metal_interrupt *tmr_intc;
804     struct __metal_driver_riscv_cpu_intc *intc =
805         (struct __metal_driver_riscv_cpu_intc *)__metal_driver_cpu_interrupt_controller(cpu);
806
807     if (intc) {
808         tmr_intc = intc->metal_int_table[METAL_INTERRUPT_ID_TMR].sub_int;
809         if (tmr_intc) {
810             rc = tmr_intc->vtable->mtimecmp_set(tmr_intc,
811                                                 __metal_driver_cpu_hartid(cpu),
812                                                 time);
813         }
814     }
815     return rc;
816 }
817
818 struct metal_interrupt *
819 __metal_driver_cpu_timer_controller_interrupt(struct metal_cpu *cpu)
820 {
821 #ifdef __METAL_DT_RISCV_CLINT0_HANDLE
822     return __METAL_DT_RISCV_CLINT0_HANDLE;
823 #else
824 #ifdef __METAL_DT_SIFIVE_CLIC0_HANDLE
825     return __METAL_DT_SIFIVE_CLIC0_HANDLE;
826 #else
827 #pragma message("There is no interrupt controller for Timer interrupt")
828     return NULL;
829 #endif
830 #endif
831 }
832
833 int __metal_driver_cpu_get_timer_interrupt_id(struct metal_cpu *cpu)
834 {
835     return METAL_INTERRUPT_ID_TMR;
836 }
837
838 struct metal_interrupt *
839 __metal_driver_cpu_sw_controller_interrupt(struct metal_cpu *cpu)
840 {
841 #ifdef __METAL_DT_RISCV_CLINT0_HANDLE
842     return __METAL_DT_RISCV_CLINT0_HANDLE;
843 #else
844 #ifdef __METAL_DT_SIFIVE_CLIC0_HANDLE
845     return __METAL_DT_SIFIVE_CLIC0_HANDLE;
846 #else
847 #pragma message("There is no interrupt controller for Software interrupt")
848     return NULL;
849 #endif
850 #endif
851 }
852
853 int __metal_driver_cpu_get_sw_interrupt_id(struct metal_cpu *cpu)
854 {
855     return METAL_INTERRUPT_ID_SW;
856 }
857
858 int __metal_driver_cpu_set_sw_ipi (struct metal_cpu *cpu, int hartid)
859 {
860     int rc = -1;
861     struct metal_interrupt *sw_intc;
862     struct __metal_driver_riscv_cpu_intc *intc = 
863         (struct __metal_driver_riscv_cpu_intc *)__metal_driver_cpu_interrupt_controller(cpu);
864
865     if (intc) {
866         sw_intc = intc->metal_int_table[METAL_INTERRUPT_ID_SW].sub_int;
867         if (sw_intc) {
868             rc = sw_intc->vtable->command_request(sw_intc,
869                                                   METAL_SOFTWARE_IPI_SET, &hartid);
870         }
871     }
872     return rc;
873 }
874
875 int __metal_driver_cpu_clear_sw_ipi (struct metal_cpu *cpu, int hartid)
876 {
877     int rc = -1;
878     struct metal_interrupt *sw_intc;
879     struct __metal_driver_riscv_cpu_intc *intc =
880         (struct __metal_driver_riscv_cpu_intc *)__metal_driver_cpu_interrupt_controller(cpu);
881
882     if (intc) {
883         sw_intc = intc->metal_int_table[METAL_INTERRUPT_ID_SW].sub_int;
884         if (sw_intc) {
885             rc = sw_intc->vtable->command_request(sw_intc,
886                                                   METAL_SOFTWARE_IPI_CLEAR, &hartid);
887         }
888     }
889     return rc;
890 }
891
892 int __metal_driver_cpu_get_msip (struct metal_cpu *cpu, int hartid)
893 {
894     int rc = 0;
895     struct metal_interrupt *sw_intc;
896     struct __metal_driver_riscv_cpu_intc *intc =
897         (struct __metal_driver_riscv_cpu_intc *)__metal_driver_cpu_interrupt_controller(cpu);
898
899     if (intc) {
900         sw_intc = intc->metal_int_table[METAL_INTERRUPT_ID_SW].sub_int;
901         if (sw_intc) {
902             rc = sw_intc->vtable->command_request(sw_intc,
903                                                   METAL_SOFTWARE_MSIP_GET, &hartid);
904         }
905     }
906     return rc;
907 }
908
909 struct metal_interrupt *
910 __metal_driver_cpu_controller_interrupt(struct metal_cpu *cpu)
911 {
912     return __metal_driver_cpu_interrupt_controller(cpu);
913 }
914
915 int __metal_driver_cpu_enable_interrupt(struct metal_cpu *cpu, void *priv)
916 {
917     if ( __metal_driver_cpu_interrupt_controller(cpu) ) {
918         /* Only support machine mode for now */
919         __metal_interrupt_global_enable();
920         return 0;
921     }
922     return -1;
923 }
924
925 int __metal_driver_cpu_disable_interrupt(struct metal_cpu *cpu, void *priv)
926 {
927     if ( __metal_driver_cpu_interrupt_controller(cpu) ) {
928         /* Only support machine mode for now */
929         __metal_interrupt_global_disable();
930         return 0;
931     }
932     return -1;
933 }
934
935 int __metal_driver_cpu_exception_register(struct metal_cpu *cpu, int ecode,
936                                         metal_exception_handler_t isr)
937 {
938     struct __metal_driver_riscv_cpu_intc *intc =
939         (struct __metal_driver_riscv_cpu_intc *)__metal_driver_cpu_interrupt_controller(cpu);
940
941     if (intc) {
942         return __metal_exception_register((struct metal_interrupt *)intc, ecode, isr);
943     }
944     return -1;
945 }
946
947 int  __metal_driver_cpu_get_instruction_length(struct metal_cpu *cpu, uintptr_t epc)
948 {
949     /**
950      * Per ISA compressed instruction has last two bits of opcode set.
951      * The encoding '00' '01' '10' are used for compressed instruction.
952      * Only enconding '11' isn't regarded as compressed instruction (>16b).
953      */
954     return ((*(unsigned short*)epc & METAL_INSN_LENGTH_MASK)
955             == METAL_INSN_NOT_COMPRESSED) ? 4 : 2;
956 }
957
958 uintptr_t  __metal_driver_cpu_get_exception_pc(struct metal_cpu *cpu)
959 {
960     uintptr_t mepc;
961     __asm__ volatile ("csrr %0, mepc" : "=r"(mepc));
962     return mepc;
963 }
964
965 int  __metal_driver_cpu_set_exception_pc(struct metal_cpu *cpu, uintptr_t mepc)
966 {
967     __asm__ volatile ("csrw mepc, %0" :: "r"(mepc));
968     return 0;
969 }
970
971 __METAL_DEFINE_VTABLE(__metal_driver_vtable_riscv_cpu_intc) = {
972     .controller_vtable.interrupt_init     = __metal_driver_riscv_cpu_controller_interrupt_init,
973     .controller_vtable.interrupt_register = __metal_driver_riscv_cpu_controller_interrupt_register,
974     .controller_vtable.interrupt_enable   = __metal_driver_riscv_cpu_controller_interrupt_enable,
975     .controller_vtable.interrupt_disable  = __metal_driver_riscv_cpu_controller_interrupt_disable,
976     .controller_vtable.interrupt_get_vector_mode = __metal_driver_riscv_cpu_controller_get_vector_mode,
977     .controller_vtable.interrupt_set_vector_mode = __metal_driver_riscv_cpu_controller_set_vector_mode,
978     .controller_vtable.command_request    = __metal_driver_riscv_cpu_controller_command_request,
979 };
980
981 __METAL_DEFINE_VTABLE(__metal_driver_vtable_cpu) = {
982     .cpu_vtable.mcycle_get     = __metal_driver_cpu_mcycle_get,
983     .cpu_vtable.timebase_get  = __metal_driver_cpu_timebase_get,
984     .cpu_vtable.mtime_get = __metal_driver_cpu_mtime_get,
985     .cpu_vtable.mtimecmp_set = __metal_driver_cpu_mtimecmp_set,
986     .cpu_vtable.tmr_controller_interrupt = __metal_driver_cpu_timer_controller_interrupt,
987     .cpu_vtable.get_tmr_interrupt_id = __metal_driver_cpu_get_timer_interrupt_id,
988     .cpu_vtable.sw_controller_interrupt = __metal_driver_cpu_sw_controller_interrupt,
989     .cpu_vtable.get_sw_interrupt_id = __metal_driver_cpu_get_sw_interrupt_id,
990     .cpu_vtable.set_sw_ipi = __metal_driver_cpu_set_sw_ipi,
991     .cpu_vtable.clear_sw_ipi = __metal_driver_cpu_clear_sw_ipi,
992     .cpu_vtable.get_msip = __metal_driver_cpu_get_msip,
993     .cpu_vtable.controller_interrupt = __metal_driver_cpu_controller_interrupt,
994     .cpu_vtable.exception_register = __metal_driver_cpu_exception_register,
995     .cpu_vtable.get_ilen = __metal_driver_cpu_get_instruction_length,
996     .cpu_vtable.get_epc = __metal_driver_cpu_get_exception_pc,
997     .cpu_vtable.set_epc = __metal_driver_cpu_set_exception_pc,
998 };
999