#include <metal/shutdown.h>
#include <metal/machine.h>
+extern void __metal_vector_table();
unsigned long long __metal_driver_cpu_mtime_get(struct metal_cpu *cpu);
int __metal_driver_cpu_mtimecmp_set(struct metal_cpu *cpu, unsigned long long time);
uintptr_t __metal_myhart_id (void)
{
uintptr_t myhart;
- asm volatile ("csrr %0, mhartid" : "=r"(myhart));
+ __asm__ volatile ("csrr %0, mhartid" : "=r"(myhart));
return myhart;
}
void __metal_interrupt_global_enable (void) {
uintptr_t m;
- asm volatile ("csrrs %0, mstatus, %1" : "=r"(m) : "r"(METAL_MIE_INTERRUPT));
+ __asm__ volatile ("csrrs %0, mstatus, %1" : "=r"(m) : "r"(METAL_MIE_INTERRUPT));
}
void __metal_interrupt_global_disable (void) {
uintptr_t m;
- asm volatile ("csrrc %0, mstatus, %1" : "=r"(m) : "r"(METAL_MIE_INTERRUPT));
+ __asm__ volatile ("csrrc %0, mstatus, %1" : "=r"(m) : "r"(METAL_MIE_INTERRUPT));
}
void __metal_interrupt_software_enable (void) {
uintptr_t m;
- asm volatile ("csrrs %0, mie, %1" : "=r"(m) : "r"(METAL_LOCAL_INTERRUPT_SW));
+ __asm__ volatile ("csrrs %0, mie, %1" : "=r"(m) : "r"(METAL_LOCAL_INTERRUPT_SW));
}
void __metal_interrupt_software_disable (void) {
uintptr_t m;
- asm volatile ("csrrc %0, mie, %1" : "=r"(m) : "r"(METAL_LOCAL_INTERRUPT_SW));
+ __asm__ volatile ("csrrc %0, mie, %1" : "=r"(m) : "r"(METAL_LOCAL_INTERRUPT_SW));
}
void __metal_interrupt_timer_enable (void) {
uintptr_t m;
- asm volatile ("csrrs %0, mie, %1" : "=r"(m) : "r"(METAL_LOCAL_INTERRUPT_TMR));
+ __asm__ volatile ("csrrs %0, mie, %1" : "=r"(m) : "r"(METAL_LOCAL_INTERRUPT_TMR));
}
void __metal_interrupt_timer_disable (void) {
uintptr_t m;
- asm volatile ("csrrc %0, mie, %1" : "=r"(m) : "r"(METAL_LOCAL_INTERRUPT_TMR));
+ __asm__ volatile ("csrrc %0, mie, %1" : "=r"(m) : "r"(METAL_LOCAL_INTERRUPT_TMR));
}
void __metal_interrupt_external_enable (void) {
uintptr_t m;
- asm volatile ("csrrs %0, mie, %1" : "=r"(m) : "r"(METAL_LOCAL_INTERRUPT_EXT));
+ __asm__ volatile ("csrrs %0, mie, %1" : "=r"(m) : "r"(METAL_LOCAL_INTERRUPT_EXT));
}
void __metal_interrupt_external_disable (void) {
unsigned long m;
- asm volatile ("csrrc %0, mie, %1" : "=r"(m) : "r"(METAL_LOCAL_INTERRUPT_EXT));
+ __asm__ volatile ("csrrc %0, mie, %1" : "=r"(m) : "r"(METAL_LOCAL_INTERRUPT_EXT));
}
void __metal_interrupt_local_enable (int id) {
uintptr_t b = 1 << id;
uintptr_t m;
- asm volatile ("csrrs %0, mie, %1" : "=r"(m) : "r"(b));
+ __asm__ volatile ("csrrs %0, mie, %1" : "=r"(m) : "r"(b));
}
void __metal_interrupt_local_disable (int id) {
uintptr_t b = 1 << id;
uintptr_t m;
- asm volatile ("csrrc %0, mie, %1" : "=r"(m) : "r"(b));
+ __asm__ volatile ("csrrc %0, mie, %1" : "=r"(m) : "r"(b));
}
void __metal_default_exception_handler (struct metal_cpu *cpu, int ecode) {
metal_shutdown(200);
}
+/* The metal_interrupt_vector_handler() function can be redefined. */
+void __attribute__((weak, interrupt)) metal_interrupt_vector_handler (void) {
+ metal_shutdown(300);
+}
+
+/* The metal_software_interrupt_vector_handler() function can be redefined. */
+void __attribute__((weak, interrupt)) metal_software_interrupt_vector_handler (void) {
+ void *priv;
+ struct __metal_driver_riscv_cpu_intc *intc;
+ struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
+
+ if ( cpu ) {
+ intc = (struct __metal_driver_riscv_cpu_intc *)
+ __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
+ priv = intc->metal_int_table[METAL_INTERRUPT_ID_SW].exint_data;
+ intc->metal_int_table[METAL_INTERRUPT_ID_SW].handler(METAL_INTERRUPT_ID_SW, priv);
+ }
+}
+
void __metal_default_sw_handler (int id, void *priv) {
uintptr_t mcause;
struct __metal_driver_riscv_cpu_intc *intc;
struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
- asm volatile ("csrr %0, mcause" : "=r"(mcause));
+ __asm__ volatile ("csrr %0, mcause" : "=r"(mcause));
if ( cpu ) {
intc = (struct __metal_driver_riscv_cpu_intc *)
__metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
}
}
+/* The metal_timer_interrupt_vector_handler() function can be redefined. */
+void __attribute__((weak, interrupt)) metal_timer_interrupt_vector_handler (void) {
+ void *priv;
+ struct __metal_driver_riscv_cpu_intc *intc;
+ struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
+
+ if ( cpu ) {
+ intc = (struct __metal_driver_riscv_cpu_intc *)
+ __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
+ priv = intc->metal_int_table[METAL_INTERRUPT_ID_TMR].exint_data;
+ intc->metal_int_table[METAL_INTERRUPT_ID_TMR].handler(METAL_INTERRUPT_ID_TMR, priv);
+ }
+}
+
void __metal_default_timer_handler (int id, void *priv) {
struct metal_cpu *cpu = __metal_driver_cpu_get(__metal_myhart_id());
unsigned long long time = __metal_driver_cpu_mtime_get(cpu);
__metal_driver_cpu_mtimecmp_set(cpu, time + 10);
}
+/* The metal_external_interrupt_vector_handler() function can be redefined. */
+void __attribute__((weak, interrupt)) metal_external_interrupt_vector_handler (void) {
+ void *priv;
+ struct __metal_driver_riscv_cpu_intc *intc;
+ struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
+
+ if ( cpu ) {
+ intc = (struct __metal_driver_riscv_cpu_intc *)
+ __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
+ priv = intc->metal_int_table[METAL_INTERRUPT_ID_EXT].exint_data;
+ intc->metal_int_table[METAL_INTERRUPT_ID_EXT].handler(METAL_INTERRUPT_ID_EXT, priv);
+ }
+}
+
void __metal_exception_handler(void) __attribute__((interrupt, aligned(128)));
void __metal_exception_handler (void) {
int id;
struct __metal_driver_riscv_cpu_intc *intc;
struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
- asm volatile ("csrr %0, mcause" : "=r"(mcause));
- asm volatile ("csrr %0, mepc" : "=r"(mepc));
- asm volatile ("csrr %0, mtval" : "=r"(mtval));
- asm volatile ("csrr %0, mtvec" : "=r"(mtvec));
+ __asm__ volatile ("csrr %0, mcause" : "=r"(mcause));
+ __asm__ volatile ("csrr %0, mepc" : "=r"(mepc));
+ __asm__ volatile ("csrr %0, mtval" : "=r"(mtval));
+ __asm__ volatile ("csrr %0, mtvec" : "=r"(mtvec));
if ( cpu ) {
intc = (struct __metal_driver_riscv_cpu_intc *)
__metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
id = mcause & METAL_MCAUSE_CAUSE;
if (mcause & METAL_MCAUSE_INTR) {
- if ((id < METAL_INTERRUPT_ID_LC0) ||
+ if ((id < METAL_INTERRUPT_ID_CSW) ||
((mtvec & METAL_MTVEC_MASK) == METAL_MTVEC_DIRECT)) {
priv = intc->metal_int_table[id].exint_data;
intc->metal_int_table[id].handler(id, priv);
uintptr_t mtvt;
metal_interrupt_handler_t mtvt_handler;
- asm volatile ("csrr %0, mtvt" : "=r"(mtvt));
+ __asm__ volatile ("csrr %0, 0x307" : "=r"(mtvt));
priv = intc->metal_int_table[METAL_INTERRUPT_ID_SW].sub_int;
- mtvt_handler = (metal_interrupt_handler_t)mtvt;
+ mtvt_handler = (metal_interrupt_handler_t)*(uintptr_t *)mtvt;
mtvt_handler(id, priv);
return;
}
}
}
+/* The metal_lc0_interrupt_vector_handler() function can be redefined. */
+void __attribute__((weak, interrupt)) metal_lc0_interrupt_vector_handler (void) {
+ void *priv;
+ struct __metal_driver_riscv_cpu_intc *intc;
+ struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
+
+ if ( cpu ) {
+ intc = (struct __metal_driver_riscv_cpu_intc *)
+ __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
+ priv = intc->metal_int_table[METAL_INTERRUPT_ID_LC0].exint_data;
+ intc->metal_int_table[METAL_INTERRUPT_ID_LC0].handler(METAL_INTERRUPT_ID_LC0, priv);
+ }
+}
+
+/* The metal_lc1_interrupt_vector_handler() function can be redefined. */
+void __attribute__((weak, interrupt)) metal_lc1_interrupt_vector_handler (void) {
+ void *priv;
+ struct __metal_driver_riscv_cpu_intc *intc;
+ struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
+
+ if ( cpu ) {
+ intc = (struct __metal_driver_riscv_cpu_intc *)
+ __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
+ priv = intc->metal_int_table[METAL_INTERRUPT_ID_LC1].exint_data;
+ intc->metal_int_table[METAL_INTERRUPT_ID_LC1].handler(METAL_INTERRUPT_ID_LC1, priv);
+ }
+}
+
+/* The metal_lc2_interrupt_vector_handler() function can be redefined. */
+void __attribute__((weak, interrupt)) metal_lc2_interrupt_vector_handler (void) {
+ void *priv;
+ struct __metal_driver_riscv_cpu_intc *intc;
+ struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
+
+ if ( cpu ) {
+ intc = (struct __metal_driver_riscv_cpu_intc *)
+ __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
+ priv = intc->metal_int_table[METAL_INTERRUPT_ID_LC2].exint_data;
+ intc->metal_int_table[METAL_INTERRUPT_ID_LC2].handler(METAL_INTERRUPT_ID_LC2, priv);
+ }
+}
+
+/* The metal_lc3_interrupt_vector_handler() function can be redefined. */
+void __attribute__((weak, interrupt)) metal_lc3_interrupt_vector_handler (void) {
+ void *priv;
+ struct __metal_driver_riscv_cpu_intc *intc;
+ struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
+
+ if ( cpu ) {
+ intc = (struct __metal_driver_riscv_cpu_intc *)
+ __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
+ priv = intc->metal_int_table[METAL_INTERRUPT_ID_LC3].exint_data;
+ intc->metal_int_table[METAL_INTERRUPT_ID_LC3].handler(METAL_INTERRUPT_ID_LC3, priv);
+ }
+}
+
+/* The metal_lc4_interrupt_vector_handler() function can be redefined. */
+void __attribute__((weak, interrupt)) metal_lc4_interrupt_vector_handler (void) {
+ void *priv;
+ struct __metal_driver_riscv_cpu_intc *intc;
+ struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
+
+ if ( cpu ) {
+ intc = (struct __metal_driver_riscv_cpu_intc *)
+ __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
+ priv = intc->metal_int_table[METAL_INTERRUPT_ID_LC4].exint_data;
+ intc->metal_int_table[METAL_INTERRUPT_ID_LC4].handler(METAL_INTERRUPT_ID_LC4, priv);
+ }
+}
+
+/* The metal_lc5_interrupt_vector_handler() function can be redefined. */
+void __attribute__((weak, interrupt)) metal_lc5_interrupt_vector_handler (void) {
+ void *priv;
+ struct __metal_driver_riscv_cpu_intc *intc;
+ struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
+
+ if ( cpu ) {
+ intc = (struct __metal_driver_riscv_cpu_intc *)
+ __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
+ priv = intc->metal_int_table[METAL_INTERRUPT_ID_LC5].exint_data;
+ intc->metal_int_table[METAL_INTERRUPT_ID_LC5].handler(METAL_INTERRUPT_ID_LC5, priv);
+ }
+}
+
+/* The metal_lc6_interrupt_vector_handler() function can be redefined. */
+void __attribute__((weak, interrupt)) metal_lc6_interrupt_vector_handler (void) {
+ void *priv;
+ struct __metal_driver_riscv_cpu_intc *intc;
+ struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
+
+ if ( cpu ) {
+ intc = (struct __metal_driver_riscv_cpu_intc *)
+ __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
+ priv = intc->metal_int_table[METAL_INTERRUPT_ID_LC6].exint_data;
+ intc->metal_int_table[METAL_INTERRUPT_ID_LC6].handler(METAL_INTERRUPT_ID_LC6, priv);
+ }
+}
+
+/* The metal_lc7_interrupt_vector_handler() function can be redefined. */
+void __attribute__((weak, interrupt)) metal_lc7_interrupt_vector_handler (void) {
+ void *priv;
+ struct __metal_driver_riscv_cpu_intc *intc;
+ struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
+
+ if ( cpu ) {
+ intc = (struct __metal_driver_riscv_cpu_intc *)
+ __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
+ priv = intc->metal_int_table[METAL_INTERRUPT_ID_LC7].exint_data;
+ intc->metal_int_table[METAL_INTERRUPT_ID_LC7].handler(METAL_INTERRUPT_ID_LC7, priv);
+ }
+}
+
+/* The metal_lc8_interrupt_vector_handler() function can be redefined. */
+void __attribute__((weak, interrupt)) metal_lc8_interrupt_vector_handler (void) {
+ void *priv;
+ struct __metal_driver_riscv_cpu_intc *intc;
+ struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
+
+ if ( cpu ) {
+ intc = (struct __metal_driver_riscv_cpu_intc *)
+ __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
+ priv = intc->metal_int_table[METAL_INTERRUPT_ID_LC8].exint_data;
+ intc->metal_int_table[METAL_INTERRUPT_ID_LC8].handler(METAL_INTERRUPT_ID_LC8, priv);
+ }
+}
+
+/* The metal_lc9_interrupt_vector_handler() function can be redefined. */
+void __attribute__((weak, interrupt)) metal_lc9_interrupt_vector_handler (void) {
+ void *priv;
+ struct __metal_driver_riscv_cpu_intc *intc;
+ struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
+
+ if ( cpu ) {
+ intc = (struct __metal_driver_riscv_cpu_intc *)
+ __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
+ priv = intc->metal_int_table[METAL_INTERRUPT_ID_LC9].exint_data;
+ intc->metal_int_table[METAL_INTERRUPT_ID_LC9].handler(METAL_INTERRUPT_ID_LC9, priv);
+ }
+}
+
+/* The metal_lc10_interrupt_vector_handler() function can be redefined. */
+void __attribute__((weak, interrupt)) metal_lc10_interrupt_vector_handler (void) {
+ void *priv;
+ struct __metal_driver_riscv_cpu_intc *intc;
+ struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
+
+ if ( cpu ) {
+ intc = (struct __metal_driver_riscv_cpu_intc *)
+ __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
+ priv = intc->metal_int_table[METAL_INTERRUPT_ID_LC10].exint_data;
+ intc->metal_int_table[METAL_INTERRUPT_ID_LC10].handler(METAL_INTERRUPT_ID_LC10, priv);
+ }
+}
+
+/* The metal_lc11_interrupt_vector_handler() function can be redefined. */
+void __attribute__((weak, interrupt)) metal_lc11_interrupt_vector_handler (void) {
+ void *priv;
+ struct __metal_driver_riscv_cpu_intc *intc;
+ struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
+
+ if ( cpu ) {
+ intc = (struct __metal_driver_riscv_cpu_intc *)
+ __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
+ priv = intc->metal_int_table[METAL_INTERRUPT_ID_LC11].exint_data;
+ intc->metal_int_table[METAL_INTERRUPT_ID_LC11].handler(METAL_INTERRUPT_ID_LC11, priv);
+ }
+}
+
+/* The metal_lc12_interrupt_vector_handler() function can be redefined. */
+void __attribute__((weak, interrupt)) metal_lc12_interrupt_vector_handler (void) {
+ void *priv;
+ struct __metal_driver_riscv_cpu_intc *intc;
+ struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
+
+ if ( cpu ) {
+ intc = (struct __metal_driver_riscv_cpu_intc *)
+ __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
+ priv = intc->metal_int_table[METAL_INTERRUPT_ID_LC12].exint_data;
+ intc->metal_int_table[METAL_INTERRUPT_ID_LC12].handler(METAL_INTERRUPT_ID_LC12, priv);
+ }
+}
+
+/* The metal_lc13_interrupt_vector_handler() function can be redefined. */
+void __attribute__((weak, interrupt)) metal_lc13_interrupt_vector_handler (void) {
+ void *priv;
+ struct __metal_driver_riscv_cpu_intc *intc;
+ struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
+
+ if ( cpu ) {
+ intc = (struct __metal_driver_riscv_cpu_intc *)
+ __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
+ priv = intc->metal_int_table[METAL_INTERRUPT_ID_LC13].exint_data;
+ intc->metal_int_table[METAL_INTERRUPT_ID_LC13].handler(METAL_INTERRUPT_ID_LC13, priv);
+ }
+}
+
+/* The metal_lc14_interrupt_vector_handler() function can be redefined. */
+void __attribute__((weak, interrupt)) metal_lc14_interrupt_vector_handler (void) {
+ void *priv;
+ struct __metal_driver_riscv_cpu_intc *intc;
+ struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
+
+ if ( cpu ) {
+ intc = (struct __metal_driver_riscv_cpu_intc *)
+ __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
+ priv = intc->metal_int_table[METAL_INTERRUPT_ID_LC14].exint_data;
+ intc->metal_int_table[METAL_INTERRUPT_ID_LC14].handler(METAL_INTERRUPT_ID_LC14, priv);
+ }
+}
+
+/* The metal_lc15_interrupt_vector_handler() function can be redefined. */
+void __attribute__((weak, interrupt)) metal_lc15_interrupt_vector_handler (void) {
+ void *priv;
+ struct __metal_driver_riscv_cpu_intc *intc;
+ struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
+
+ if ( cpu ) {
+ intc = (struct __metal_driver_riscv_cpu_intc *)
+ __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
+ priv = intc->metal_int_table[METAL_INTERRUPT_ID_LC15].exint_data;
+ intc->metal_int_table[METAL_INTERRUPT_ID_LC15].handler(METAL_INTERRUPT_ID_LC15, priv);
+ }
+}
+
+metal_vector_mode __metal_controller_interrupt_vector_mode (void)
+{
+ uintptr_t val;
+
+ asm volatile ("csrr %0, mtvec" : "=r"(val));
+ val &= METAL_MTVEC_MASK;
+
+ switch (val) {
+ case METAL_MTVEC_CLIC:
+ return METAL_SELECTIVE_VECTOR_MODE;
+ case METAL_MTVEC_CLIC_VECTORED:
+ return METAL_HARDWARE_VECTOR_MODE;
+ case METAL_MTVEC_VECTORED:
+ return METAL_VECTOR_MODE;
+ }
+ return METAL_DIRECT_MODE;
+}
+
void __metal_controller_interrupt_vector (metal_vector_mode mode, void *vec_table)
{
uintptr_t trap_entry, val;
- asm volatile ("csrr %0, mtvec" : "=r"(val));
+ __asm__ volatile ("csrr %0, mtvec" : "=r"(val));
val &= ~(METAL_MTVEC_CLIC_VECTORED | METAL_MTVEC_CLIC_RESERVED);
trap_entry = (uintptr_t)vec_table;
switch (mode) {
+ case METAL_SELECTIVE_NONVECTOR_MODE:
case METAL_SELECTIVE_VECTOR_MODE:
- asm volatile ("csrw mtvt, %0" :: "r"(trap_entry | METAL_MTVEC_CLIC));
- asm volatile ("csrw mtvec, %0" :: "r"(val | METAL_MTVEC_CLIC));
+ __asm__ volatile ("csrw 0x307, %0" :: "r"(trap_entry));
+ __asm__ volatile ("csrw mtvec, %0" :: "r"(val | METAL_MTVEC_CLIC));
break;
case METAL_HARDWARE_VECTOR_MODE:
- asm volatile ("csrw mtvt, %0" :: "r"(trap_entry | METAL_MTVEC_CLIC_VECTORED));
- asm volatile ("csrw mtvec, %0" :: "r"(val | METAL_MTVEC_CLIC_VECTORED));
+ __asm__ volatile ("csrw 0x307, %0" :: "r"(trap_entry));
+ __asm__ volatile ("csrw mtvec, %0" :: "r"(val | METAL_MTVEC_CLIC_VECTORED));
break;
case METAL_VECTOR_MODE:
- asm volatile ("csrw mtvec, %0" :: "r"(trap_entry | METAL_MTVEC_VECTORED));
+ __asm__ volatile ("csrw mtvec, %0" :: "r"(trap_entry | METAL_MTVEC_VECTORED));
break;
case METAL_DIRECT_MODE:
- asm volatile ("csrw mtvec, %0" :: "r"(trap_entry & ~METAL_MTVEC_CLIC_VECTORED));
+ __asm__ volatile ("csrw mtvec, %0" :: "r"(trap_entry & ~METAL_MTVEC_CLIC_VECTORED));
break;
}
}
__metal_interrupt_local_disable(id);
}
break;
- defaut:
+ default:
rc = -1;
}
return rc;
if ( !intc->init_done ) {
/* Disable and clear all interrupt sources */
- asm volatile ("csrc mie, %0" :: "r"(-1));
- asm volatile ("csrc mip, %0" :: "r"(-1));
+ __asm__ volatile ("csrc mie, %0" :: "r"(-1));
+ __asm__ volatile ("csrc mip, %0" :: "r"(-1));
/* Read the misa CSR to determine if the delegation registers exist */
uintptr_t misa;
- asm volatile ("csrr %0, misa" : "=r" (misa));
+ __asm__ volatile ("csrr %0, misa" : "=r" (misa));
/* The delegation CSRs exist if user mode interrupts (N extension) or
* supervisor mode (S extension) are supported */
if((misa & METAL_ISA_N_EXTENSIONS) || (misa & METAL_ISA_S_EXTENSIONS)) {
/* Disable interrupt and exception delegation */
- asm volatile ("csrc mideleg, %0" :: "r"(-1));
- asm volatile ("csrc medeleg, %0" :: "r"(-1));
+ __asm__ volatile ("csrc mideleg, %0" :: "r"(-1));
+ __asm__ volatile ("csrc medeleg, %0" :: "r"(-1));
}
/* The satp CSR exists if supervisor mode (S extension) is supported */
if(misa & METAL_ISA_S_EXTENSIONS) {
/* Clear the entire CSR to make sure that satp.MODE = 0 */
- asm volatile ("csrc satp, %0" :: "r"(-1));
+ __asm__ volatile ("csrc satp, %0" :: "r"(-1));
}
/* Default to use direct interrupt, setup sw cb table*/
for (int i = 0; i < METAL_MAX_ME; i++) {
intc->metal_exception_table[i] = __metal_default_exception_handler;
}
- __metal_controller_interrupt_vector(METAL_DIRECT_MODE, &__metal_exception_handler);
- asm volatile ("csrr %0, misa" : "=r"(val));
+ __metal_controller_interrupt_vector(METAL_DIRECT_MODE, (void *)(uintptr_t)&__metal_exception_handler);
+ __asm__ volatile ("csrr %0, misa" : "=r"(val));
if (val & (METAL_ISA_D_EXTENSIONS | METAL_ISA_F_EXTENSIONS | METAL_ISA_Q_EXTENSIONS)) {
/* Floating point architecture, so turn on FP register saving*/
- asm volatile ("csrr %0, mstatus" : "=r"(val));
- asm volatile ("csrw mstatus, %0" :: "r"(val | METAL_MSTATUS_FS_INIT));
+ __asm__ volatile ("csrr %0, mstatus" : "=r"(val));
+ __asm__ volatile ("csrw mstatus, %0" :: "r"(val | METAL_MSTATUS_FS_INIT));
}
intc->init_done = 1;
}
intc->metal_int_table[id].handler = __metal_default_interrupt_handler;
intc->metal_int_table[id].sub_int = priv;
break;
- defaut:
+ default:
rc = -12;
}
}
if (id == METAL_INTERRUPT_ID_BASE) {
if (mode == METAL_DIRECT_MODE) {
- __metal_controller_interrupt_vector(mode, &__metal_exception_handler);
+ __metal_controller_interrupt_vector(mode, (void *)(uintptr_t)&__metal_exception_handler);
return 0;
}
if (mode == METAL_VECTOR_MODE) {
- __metal_controller_interrupt_vector(mode, &intc->metal_mtvec_table);
+ __metal_controller_interrupt_vector(mode, (void *)&intc->metal_mtvec_table);
return 0;
}
}
int __metal_driver_riscv_cpu_controller_interrupt_disable_vector(struct metal_interrupt *controller,
int id)
{
+ if (id == METAL_INTERRUPT_ID_BASE) {
+ __metal_controller_interrupt_vector(METAL_DIRECT_MODE, (void *)(uintptr_t)&__metal_exception_handler);
+ return 0;
+ }
+ return -1;
+}
+
+metal_vector_mode __metal_driver_riscv_cpu_controller_get_vector_mode (struct metal_interrupt *controller)
+{
+ return __metal_controller_interrupt_vector_mode();
+}
+
+int __metal_driver_riscv_cpu_controller_set_vector_mode (struct metal_interrupt *controller,
+ metal_vector_mode mode)
+{
struct __metal_driver_riscv_cpu_intc *intc = (void *)(controller);
+ ( void ) intc;
- if (id == METAL_INTERRUPT_ID_BASE) {
- __metal_controller_interrupt_vector(METAL_DIRECT_MODE, &__metal_exception_handler);
+ if (mode == METAL_DIRECT_MODE) {
+ __metal_controller_interrupt_vector(mode, (void *)(uintptr_t)&__metal_exception_handler);
+ return 0;
+ }
+ if (mode == METAL_VECTOR_MODE) {
+ __metal_controller_interrupt_vector(mode, (void *)__metal_vector_table);
return 0;
}
return -1;
return 0;
}
-extern inline int __metal_controller_interrupt_is_selective_vectored(void);
-
/* CPU driver !!! */
-unsigned long long __metal_driver_cpu_timer_get(struct metal_cpu *cpu)
+unsigned long long __metal_driver_cpu_mcycle_get(struct metal_cpu *cpu)
{
unsigned long long val = 0;
#if __riscv_xlen == 32
unsigned long hi, hi1, lo;
- asm volatile ("csrr %0, mcycleh" : "=r"(hi));
- asm volatile ("csrr %0, mcycle" : "=r"(lo));
- asm volatile ("csrr %0, mcycleh" : "=r"(hi1));
+ __asm__ volatile ("csrr %0, mcycleh" : "=r"(hi));
+ __asm__ volatile ("csrr %0, mcycle" : "=r"(lo));
+ __asm__ volatile ("csrr %0, mcycleh" : "=r"(hi1));
if (hi == hi1) {
val = ((unsigned long long)hi << 32) | lo;
}
#else
- asm volatile ("csrr %0, mcycle" : "=r"(val));
+ __asm__ volatile ("csrr %0, mcycle" : "=r"(val));
#endif
return val;
struct metal_interrupt *tmr_intc;
struct __metal_driver_riscv_cpu_intc *intc =
(struct __metal_driver_riscv_cpu_intc *)__metal_driver_cpu_interrupt_controller(cpu);
- struct __metal_driver_cpu *_cpu = (void *)cpu;
if (intc) {
tmr_intc = intc->metal_int_table[METAL_INTERRUPT_ID_TMR].sub_int;
struct metal_interrupt *tmr_intc;
struct __metal_driver_riscv_cpu_intc *intc =
(struct __metal_driver_riscv_cpu_intc *)__metal_driver_cpu_interrupt_controller(cpu);
- struct __metal_driver_cpu *_cpu = (void *)cpu;
if (intc) {
tmr_intc = intc->metal_int_table[METAL_INTERRUPT_ID_TMR].sub_int;
#ifdef __METAL_DT_SIFIVE_CLIC0_HANDLE
return __METAL_DT_SIFIVE_CLIC0_HANDLE;
#else
-#warning "There is no interrupt controller for Timer interrupt"
+#pragma message("There is no interrupt controller for Timer interrupt")
return NULL;
#endif
#endif
#ifdef __METAL_DT_SIFIVE_CLIC0_HANDLE
return __METAL_DT_SIFIVE_CLIC0_HANDLE;
#else
-#warning "There is no interrupt controller for Software interrupt"
+#pragma message("There is no interrupt controller for Software interrupt")
return NULL;
#endif
#endif
struct metal_interrupt *sw_intc;
struct __metal_driver_riscv_cpu_intc *intc =
(struct __metal_driver_riscv_cpu_intc *)__metal_driver_cpu_interrupt_controller(cpu);
- struct __metal_driver_cpu *_cpu = (void *)cpu;
if (intc) {
sw_intc = intc->metal_int_table[METAL_INTERRUPT_ID_SW].sub_int;
struct metal_interrupt *sw_intc;
struct __metal_driver_riscv_cpu_intc *intc =
(struct __metal_driver_riscv_cpu_intc *)__metal_driver_cpu_interrupt_controller(cpu);
- struct __metal_driver_cpu *_cpu = (void *)cpu;
if (intc) {
sw_intc = intc->metal_int_table[METAL_INTERRUPT_ID_SW].sub_int;
struct metal_interrupt *sw_intc;
struct __metal_driver_riscv_cpu_intc *intc =
(struct __metal_driver_riscv_cpu_intc *)__metal_driver_cpu_interrupt_controller(cpu);
- struct __metal_driver_cpu *_cpu = (void *)cpu;
if (intc) {
sw_intc = intc->metal_int_table[METAL_INTERRUPT_ID_SW].sub_int;
int __metal_driver_cpu_get_instruction_length(struct metal_cpu *cpu, uintptr_t epc)
{
- /* Per ISA compressed instruction has last two bits of opcode set */
- return (*(unsigned short*)epc & 3) ? 4 : 2;
+ /**
+ * Per ISA compressed instruction has last two bits of opcode set.
+ * The encoding '00' '01' '10' are used for compressed instruction.
+ * Only enconding '11' isn't regarded as compressed instruction (>16b).
+ */
+ return ((*(unsigned short*)epc & METAL_INSN_LENGTH_MASK)
+ == METAL_INSN_NOT_COMPRESSED) ? 4 : 2;
}
uintptr_t __metal_driver_cpu_get_exception_pc(struct metal_cpu *cpu)
{
uintptr_t mepc;
- asm volatile ("csrr %0, mepc" : "=r"(mepc));
+ __asm__ volatile ("csrr %0, mepc" : "=r"(mepc));
return mepc;
}
int __metal_driver_cpu_set_exception_pc(struct metal_cpu *cpu, uintptr_t mepc)
{
- asm volatile ("csrw mepc, %0" :: "r"(mepc));
+ __asm__ volatile ("csrw mepc, %0" :: "r"(mepc));
return 0;
}
__METAL_DEFINE_VTABLE(__metal_driver_vtable_riscv_cpu_intc) = {
- .controller_vtable.interrupt_init = __metal_driver_riscv_cpu_controller_interrupt_init,
+ .controller_vtable.interrupt_init = __metal_driver_riscv_cpu_controller_interrupt_init,
.controller_vtable.interrupt_register = __metal_driver_riscv_cpu_controller_interrupt_register,
.controller_vtable.interrupt_enable = __metal_driver_riscv_cpu_controller_interrupt_enable,
.controller_vtable.interrupt_disable = __metal_driver_riscv_cpu_controller_interrupt_disable,
- .controller_vtable.interrupt_vector_enable = __metal_driver_riscv_cpu_controller_interrupt_enable_vector,
- .controller_vtable.interrupt_vector_disable = __metal_driver_riscv_cpu_controller_interrupt_disable_vector,
+ .controller_vtable.interrupt_get_vector_mode = __metal_driver_riscv_cpu_controller_get_vector_mode,
+ .controller_vtable.interrupt_set_vector_mode = __metal_driver_riscv_cpu_controller_set_vector_mode,
.controller_vtable.command_request = __metal_driver_riscv_cpu_controller_command_request,
};
__METAL_DEFINE_VTABLE(__metal_driver_vtable_cpu) = {
- .cpu_vtable.timer_get = __metal_driver_cpu_timer_get,
+ .cpu_vtable.mcycle_get = __metal_driver_cpu_mcycle_get,
.cpu_vtable.timebase_get = __metal_driver_cpu_timebase_get,
.cpu_vtable.mtime_get = __metal_driver_cpu_mtime_get,
.cpu_vtable.mtimecmp_set = __metal_driver_cpu_mtimecmp_set,