1 /* Copyright 2018 SiFive, Inc */
2 /* SPDX-License-Identifier: Apache-2.0 */
6 #include <metal/shutdown.h>
7 #include <metal/machine.h>
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);
13 struct metal_cpu *__metal_driver_cpu_get(int hartid)
15 if (hartid < __METAL_DT_MAX_HARTS) {
16 return &(__metal_cpu_table[hartid]->cpu);
18 return (struct metal_cpu *)NULL;
21 uintptr_t __metal_myhart_id (void)
24 __asm__ volatile ("csrr %0, mhartid" : "=r"(myhart));
28 void __metal_zero_memory (unsigned char *base, unsigned int size)
30 volatile unsigned char *ptr;
31 for (ptr = base; ptr < (base + size); ptr++){
36 void __metal_interrupt_global_enable (void) {
38 __asm__ volatile ("csrrs %0, mstatus, %1" : "=r"(m) : "r"(METAL_MIE_INTERRUPT));
41 void __metal_interrupt_global_disable (void) {
43 __asm__ volatile ("csrrc %0, mstatus, %1" : "=r"(m) : "r"(METAL_MIE_INTERRUPT));
46 void __metal_interrupt_software_enable (void) {
48 __asm__ volatile ("csrrs %0, mie, %1" : "=r"(m) : "r"(METAL_LOCAL_INTERRUPT_SW));
51 void __metal_interrupt_software_disable (void) {
53 __asm__ volatile ("csrrc %0, mie, %1" : "=r"(m) : "r"(METAL_LOCAL_INTERRUPT_SW));
56 void __metal_interrupt_timer_enable (void) {
58 __asm__ volatile ("csrrs %0, mie, %1" : "=r"(m) : "r"(METAL_LOCAL_INTERRUPT_TMR));
61 void __metal_interrupt_timer_disable (void) {
63 __asm__ volatile ("csrrc %0, mie, %1" : "=r"(m) : "r"(METAL_LOCAL_INTERRUPT_TMR));
66 void __metal_interrupt_external_enable (void) {
68 __asm__ volatile ("csrrs %0, mie, %1" : "=r"(m) : "r"(METAL_LOCAL_INTERRUPT_EXT));
71 void __metal_interrupt_external_disable (void) {
73 __asm__ volatile ("csrrc %0, mie, %1" : "=r"(m) : "r"(METAL_LOCAL_INTERRUPT_EXT));
76 void __metal_interrupt_local_enable (int id) {
77 uintptr_t b = 1 << id;
79 __asm__ volatile ("csrrs %0, mie, %1" : "=r"(m) : "r"(b));
82 void __metal_interrupt_local_disable (int id) {
83 uintptr_t b = 1 << id;
85 __asm__ volatile ("csrrc %0, mie, %1" : "=r"(m) : "r"(b));
88 void __metal_default_exception_handler (struct metal_cpu *cpu, int ecode) {
92 void __metal_default_interrupt_handler (int id, void *priv) {
96 /* The metal_interrupt_vector_handler() function can be redefined. */
97 void __attribute__((weak, interrupt)) metal_interrupt_vector_handler (void) {
101 /* The metal_software_interrupt_vector_handler() function can be redefined. */
102 void __attribute__((weak, interrupt)) metal_software_interrupt_vector_handler (void) {
104 struct __metal_driver_riscv_cpu_intc *intc;
105 struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
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);
115 void __metal_default_sw_handler (int id, void *priv) {
117 struct __metal_driver_riscv_cpu_intc *intc;
118 struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
120 __asm__ volatile ("csrr %0, mcause" : "=r"(mcause));
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);
128 /* The metal_timer_interrupt_vector_handler() function can be redefined. */
129 void __attribute__((weak, interrupt)) metal_timer_interrupt_vector_handler (void) {
131 struct __metal_driver_riscv_cpu_intc *intc;
132 struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
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);
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);
146 /* Set a 10 cycle timer */
147 __metal_driver_cpu_mtimecmp_set(cpu, time + 10);
150 /* The metal_external_interrupt_vector_handler() function can be redefined. */
151 void __attribute__((weak, interrupt)) metal_external_interrupt_vector_handler (void) {
153 struct __metal_driver_riscv_cpu_intc *intc;
154 struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
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);
164 void __metal_exception_handler(void) __attribute__((interrupt, aligned(128)));
165 void __metal_exception_handler (void) {
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()];
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));
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);
188 if ((mtvec & METAL_MTVEC_MASK) == METAL_MTVEC_CLIC) {
190 metal_interrupt_handler_t mtvt_handler;
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);
199 intc->metal_exception_table[id]((struct metal_cpu *)cpu, id);
204 /* The metal_lc0_interrupt_vector_handler() function can be redefined. */
205 void __attribute__((weak, interrupt)) metal_lc0_interrupt_vector_handler (void) {
207 struct __metal_driver_riscv_cpu_intc *intc;
208 struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
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);
218 /* The metal_lc1_interrupt_vector_handler() function can be redefined. */
219 void __attribute__((weak, interrupt)) metal_lc1_interrupt_vector_handler (void) {
221 struct __metal_driver_riscv_cpu_intc *intc;
222 struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
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);
232 /* The metal_lc2_interrupt_vector_handler() function can be redefined. */
233 void __attribute__((weak, interrupt)) metal_lc2_interrupt_vector_handler (void) {
235 struct __metal_driver_riscv_cpu_intc *intc;
236 struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
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);
246 /* The metal_lc3_interrupt_vector_handler() function can be redefined. */
247 void __attribute__((weak, interrupt)) metal_lc3_interrupt_vector_handler (void) {
249 struct __metal_driver_riscv_cpu_intc *intc;
250 struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
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);
260 /* The metal_lc4_interrupt_vector_handler() function can be redefined. */
261 void __attribute__((weak, interrupt)) metal_lc4_interrupt_vector_handler (void) {
263 struct __metal_driver_riscv_cpu_intc *intc;
264 struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
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);
274 /* The metal_lc5_interrupt_vector_handler() function can be redefined. */
275 void __attribute__((weak, interrupt)) metal_lc5_interrupt_vector_handler (void) {
277 struct __metal_driver_riscv_cpu_intc *intc;
278 struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
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);
288 /* The metal_lc6_interrupt_vector_handler() function can be redefined. */
289 void __attribute__((weak, interrupt)) metal_lc6_interrupt_vector_handler (void) {
291 struct __metal_driver_riscv_cpu_intc *intc;
292 struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
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);
302 /* The metal_lc7_interrupt_vector_handler() function can be redefined. */
303 void __attribute__((weak, interrupt)) metal_lc7_interrupt_vector_handler (void) {
305 struct __metal_driver_riscv_cpu_intc *intc;
306 struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
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);
316 /* The metal_lc8_interrupt_vector_handler() function can be redefined. */
317 void __attribute__((weak, interrupt)) metal_lc8_interrupt_vector_handler (void) {
319 struct __metal_driver_riscv_cpu_intc *intc;
320 struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
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);
330 /* The metal_lc9_interrupt_vector_handler() function can be redefined. */
331 void __attribute__((weak, interrupt)) metal_lc9_interrupt_vector_handler (void) {
333 struct __metal_driver_riscv_cpu_intc *intc;
334 struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
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);
344 /* The metal_lc10_interrupt_vector_handler() function can be redefined. */
345 void __attribute__((weak, interrupt)) metal_lc10_interrupt_vector_handler (void) {
347 struct __metal_driver_riscv_cpu_intc *intc;
348 struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
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);
358 /* The metal_lc11_interrupt_vector_handler() function can be redefined. */
359 void __attribute__((weak, interrupt)) metal_lc11_interrupt_vector_handler (void) {
361 struct __metal_driver_riscv_cpu_intc *intc;
362 struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
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);
372 /* The metal_lc12_interrupt_vector_handler() function can be redefined. */
373 void __attribute__((weak, interrupt)) metal_lc12_interrupt_vector_handler (void) {
375 struct __metal_driver_riscv_cpu_intc *intc;
376 struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
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);
386 /* The metal_lc13_interrupt_vector_handler() function can be redefined. */
387 void __attribute__((weak, interrupt)) metal_lc13_interrupt_vector_handler (void) {
389 struct __metal_driver_riscv_cpu_intc *intc;
390 struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
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);
400 /* The metal_lc14_interrupt_vector_handler() function can be redefined. */
401 void __attribute__((weak, interrupt)) metal_lc14_interrupt_vector_handler (void) {
403 struct __metal_driver_riscv_cpu_intc *intc;
404 struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
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);
414 /* The metal_lc15_interrupt_vector_handler() function can be redefined. */
415 void __attribute__((weak, interrupt)) metal_lc15_interrupt_vector_handler (void) {
417 struct __metal_driver_riscv_cpu_intc *intc;
418 struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
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);
428 metal_vector_mode __metal_controller_interrupt_vector_mode (void)
432 asm volatile ("csrr %0, mtvec" : "=r"(val));
433 val &= METAL_MTVEC_MASK;
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;
443 return METAL_DIRECT_MODE;
446 void __metal_controller_interrupt_vector (metal_vector_mode mode, void *vec_table)
448 uintptr_t trap_entry, val;
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;
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));
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));
464 case METAL_VECTOR_MODE:
465 __asm__ volatile ("csrw mtvec, %0" :: "r"(trap_entry | METAL_MTVEC_VECTORED));
467 case METAL_DIRECT_MODE:
468 __asm__ volatile ("csrw mtvec, %0" :: "r"(trap_entry & ~METAL_MTVEC_CLIC_VECTORED));
473 int __metal_valid_interrupt_id (int 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:
504 int __metal_local_interrupt_enable (struct metal_interrupt *controller,
505 metal_interrupt_id_e id, int enable)
514 case METAL_INTERRUPT_ID_BASE:
516 __metal_interrupt_global_enable();
518 __metal_interrupt_global_disable();
521 case METAL_INTERRUPT_ID_SW:
523 __metal_interrupt_software_enable();
525 __metal_interrupt_software_disable();
528 case METAL_INTERRUPT_ID_TMR:
530 __metal_interrupt_timer_enable();
532 __metal_interrupt_timer_disable();
535 case METAL_INTERRUPT_ID_EXT:
537 __metal_interrupt_external_enable();
539 __metal_interrupt_external_disable();
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:
559 __metal_interrupt_local_enable(id);
561 __metal_interrupt_local_disable(id);
570 int __metal_exception_register (struct metal_interrupt *controller,
571 int ecode, metal_exception_handler_t isr)
573 struct __metal_driver_riscv_cpu_intc *intc = (void *)(controller);
575 if ((ecode < METAL_MAX_EXCEPTION_CODE) && isr) {
576 intc->metal_exception_table[ecode] = isr;
582 void __metal_driver_riscv_cpu_controller_interrupt_init (struct metal_interrupt *controller)
584 struct __metal_driver_riscv_cpu_intc *intc = (void *)(controller);
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));
592 /* Read the misa CSR to determine if the delegation registers exist */
594 __asm__ volatile ("csrr %0, misa" : "=r" (misa));
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));
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));
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;
616 for (int i = 0; i < METAL_MAX_ME; i++) {
617 intc->metal_exception_table[i] = __metal_default_exception_handler;
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));
630 int __metal_driver_riscv_cpu_controller_interrupt_register(struct metal_interrupt *controller,
631 int id, metal_interrupt_handler_t isr,
635 struct __metal_driver_riscv_cpu_intc *intc = (void *)(controller);
637 if ( !__metal_valid_interrupt_id(id) ) {
642 intc->metal_int_table[id].handler = isr;
643 intc->metal_int_table[id].exint_data = priv;
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;
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;
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;
681 int __metal_driver_riscv_cpu_controller_interrupt_enable (struct metal_interrupt *controller,
684 return __metal_local_interrupt_enable(controller, id, METAL_ENABLE);
687 int __metal_driver_riscv_cpu_controller_interrupt_disable (struct metal_interrupt *controller,
690 return __metal_local_interrupt_enable(controller, id, METAL_DISABLE);
693 int __metal_driver_riscv_cpu_controller_interrupt_enable_vector(struct metal_interrupt *controller,
694 int id, metal_vector_mode mode)
696 struct __metal_driver_riscv_cpu_intc *intc = (void *)(controller);
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);
703 if (mode == METAL_VECTOR_MODE) {
704 __metal_controller_interrupt_vector(mode, (void *)&intc->metal_mtvec_table);
711 int __metal_driver_riscv_cpu_controller_interrupt_disable_vector(struct metal_interrupt *controller,
714 if (id == METAL_INTERRUPT_ID_BASE) {
715 __metal_controller_interrupt_vector(METAL_DIRECT_MODE, (void *)(uintptr_t)&__metal_exception_handler);
721 metal_vector_mode __metal_driver_riscv_cpu_controller_get_vector_mode (struct metal_interrupt *controller)
723 return __metal_controller_interrupt_vector_mode();
726 int __metal_driver_riscv_cpu_controller_set_vector_mode (struct metal_interrupt *controller,
727 metal_vector_mode mode)
729 struct __metal_driver_riscv_cpu_intc *intc = (void *)(controller);
732 if (mode == METAL_DIRECT_MODE) {
733 __metal_controller_interrupt_vector(mode, (void *)(uintptr_t)&__metal_exception_handler);
736 if (mode == METAL_VECTOR_MODE) {
737 __metal_controller_interrupt_vector(mode, (void *)__metal_vector_table);
743 int __metal_driver_riscv_cpu_controller_command_request (struct metal_interrupt *controller,
746 /* NOP for now, unless local interrupt lines the like of clic, clint, plic */
752 unsigned long long __metal_driver_cpu_mcycle_get(struct metal_cpu *cpu)
754 unsigned long long val = 0;
756 #if __riscv_xlen == 32
757 unsigned long hi, hi1, lo;
759 __asm__ volatile ("csrr %0, mcycleh" : "=r"(hi));
760 __asm__ volatile ("csrr %0, mcycle" : "=r"(lo));
761 __asm__ volatile ("csrr %0, mcycleh" : "=r"(hi1));
763 val = ((unsigned long long)hi << 32) | lo;
766 __asm__ volatile ("csrr %0, mcycle" : "=r"(val));
772 unsigned long long __metal_driver_cpu_timebase_get(struct metal_cpu *cpu)
779 timebase = __metal_driver_cpu_timebase((struct metal_cpu *)cpu);
783 unsigned long long __metal_driver_cpu_mtime_get (struct metal_cpu *cpu)
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);
791 tmr_intc = intc->metal_int_table[METAL_INTERRUPT_ID_TMR].sub_int;
793 tmr_intc->vtable->command_request(tmr_intc,
794 METAL_TIMER_MTIME_GET, &time);
800 int __metal_driver_cpu_mtimecmp_set (struct metal_cpu *cpu, unsigned long long time)
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);
808 tmr_intc = intc->metal_int_table[METAL_INTERRUPT_ID_TMR].sub_int;
810 rc = tmr_intc->vtable->mtimecmp_set(tmr_intc,
811 __metal_driver_cpu_hartid(cpu),
818 struct metal_interrupt *
819 __metal_driver_cpu_timer_controller_interrupt(struct metal_cpu *cpu)
821 #ifdef __METAL_DT_RISCV_CLINT0_HANDLE
822 return __METAL_DT_RISCV_CLINT0_HANDLE;
824 #ifdef __METAL_DT_SIFIVE_CLIC0_HANDLE
825 return __METAL_DT_SIFIVE_CLIC0_HANDLE;
827 #pragma message("There is no interrupt controller for Timer interrupt")
833 int __metal_driver_cpu_get_timer_interrupt_id(struct metal_cpu *cpu)
835 return METAL_INTERRUPT_ID_TMR;
838 struct metal_interrupt *
839 __metal_driver_cpu_sw_controller_interrupt(struct metal_cpu *cpu)
841 #ifdef __METAL_DT_RISCV_CLINT0_HANDLE
842 return __METAL_DT_RISCV_CLINT0_HANDLE;
844 #ifdef __METAL_DT_SIFIVE_CLIC0_HANDLE
845 return __METAL_DT_SIFIVE_CLIC0_HANDLE;
847 #pragma message("There is no interrupt controller for Software interrupt")
853 int __metal_driver_cpu_get_sw_interrupt_id(struct metal_cpu *cpu)
855 return METAL_INTERRUPT_ID_SW;
858 int __metal_driver_cpu_set_sw_ipi (struct metal_cpu *cpu, int hartid)
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);
866 sw_intc = intc->metal_int_table[METAL_INTERRUPT_ID_SW].sub_int;
868 rc = sw_intc->vtable->command_request(sw_intc,
869 METAL_SOFTWARE_IPI_SET, &hartid);
875 int __metal_driver_cpu_clear_sw_ipi (struct metal_cpu *cpu, int hartid)
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);
883 sw_intc = intc->metal_int_table[METAL_INTERRUPT_ID_SW].sub_int;
885 rc = sw_intc->vtable->command_request(sw_intc,
886 METAL_SOFTWARE_IPI_CLEAR, &hartid);
892 int __metal_driver_cpu_get_msip (struct metal_cpu *cpu, int hartid)
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);
900 sw_intc = intc->metal_int_table[METAL_INTERRUPT_ID_SW].sub_int;
902 rc = sw_intc->vtable->command_request(sw_intc,
903 METAL_SOFTWARE_MSIP_GET, &hartid);
909 struct metal_interrupt *
910 __metal_driver_cpu_controller_interrupt(struct metal_cpu *cpu)
912 return __metal_driver_cpu_interrupt_controller(cpu);
915 int __metal_driver_cpu_enable_interrupt(struct metal_cpu *cpu, void *priv)
917 if ( __metal_driver_cpu_interrupt_controller(cpu) ) {
918 /* Only support machine mode for now */
919 __metal_interrupt_global_enable();
925 int __metal_driver_cpu_disable_interrupt(struct metal_cpu *cpu, void *priv)
927 if ( __metal_driver_cpu_interrupt_controller(cpu) ) {
928 /* Only support machine mode for now */
929 __metal_interrupt_global_disable();
935 int __metal_driver_cpu_exception_register(struct metal_cpu *cpu, int ecode,
936 metal_exception_handler_t isr)
938 struct __metal_driver_riscv_cpu_intc *intc =
939 (struct __metal_driver_riscv_cpu_intc *)__metal_driver_cpu_interrupt_controller(cpu);
942 return __metal_exception_register((struct metal_interrupt *)intc, ecode, isr);
947 int __metal_driver_cpu_get_instruction_length(struct metal_cpu *cpu, uintptr_t epc)
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).
954 return ((*(unsigned short*)epc & METAL_INSN_LENGTH_MASK)
955 == METAL_INSN_NOT_COMPRESSED) ? 4 : 2;
958 uintptr_t __metal_driver_cpu_get_exception_pc(struct metal_cpu *cpu)
961 __asm__ volatile ("csrr %0, mepc" : "=r"(mepc));
965 int __metal_driver_cpu_set_exception_pc(struct metal_cpu *cpu, uintptr_t mepc)
967 __asm__ volatile ("csrw mepc, %0" :: "r"(mepc));
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,
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,