1 /* Copyright 2018 SiFive, Inc */
2 /* SPDX-License-Identifier: Apache-2.0 */
4 #ifndef METAL__DRIVERS__RISCV_CPU_H
5 #define METAL__DRIVERS__RISCV_CPU_H
9 #include <metal/compiler.h>
11 #define METAL_MAX_CORES 8
12 #define METAL_MAX_MI 32 /* Per ISA MCause interrupts 32+ are Reserved */
13 #define METAL_MAX_ME 12 /* Per ISA Exception codes 12+ are Reserved */
14 #define METAL_DEFAULT_RTC_FREQ 32768
16 #define METAL_DISABLE 0
17 #define METAL_ENABLE 1
19 #define METAL_ISA_A_EXTENSIONS 0x0001
20 #define METAL_ISA_C_EXTENSIONS 0x0004
21 #define METAL_ISA_D_EXTENSIONS 0x0008
22 #define METAL_ISA_E_EXTENSIONS 0x0010
23 #define METAL_ISA_F_EXTENSIONS 0x0020
24 #define METAL_ISA_G_EXTENSIONS 0x0040
25 #define METAL_ISA_I_EXTENSIONS 0x0100
26 #define METAL_ISA_M_EXTENSIONS 0x1000
27 #define METAL_ISA_N_EXTENSIONS 0x2000
28 #define METAL_ISA_Q_EXTENSIONS 0x10000
29 #define METAL_ISA_S_EXTENSIONS 0x40000
30 #define METAL_ISA_U_EXTENSIONS 0x100000
31 #define METAL_ISA_V_EXTENSIONS 0x200000
32 #define METAL_ISA_XL32_EXTENSIONS 0x40000000UL
33 #define METAL_ISA_XL64_EXTENSIONS 0x8000000000000000UL
34 #define METAL_ISA_XL128_EXTENSIONS 0xC000000000000000UL
36 #define METAL_MTVEC_DIRECT 0x00
37 #define METAL_MTVEC_VECTORED 0x01
38 #define METAL_MTVEC_CLIC 0x02
39 #define METAL_MTVEC_CLIC_VECTORED 0x03
40 #define METAL_MTVEC_CLIC_RESERVED 0x3C
41 #define METAL_MTVEC_MASK 0x3F
42 #if __riscv_xlen == 32
43 #define METAL_MCAUSE_INTR 0x80000000UL
44 #define METAL_MCAUSE_CAUSE 0x000003FFUL
46 #define METAL_MCAUSE_INTR 0x8000000000000000UL
47 #define METAL_MCAUSE_CAUSE 0x00000000000003FFUL
49 #define METAL_MCAUSE_MINHV 0x40000000UL
50 #define METAL_MCAUSE_MPP 0x30000000UL
51 #define METAL_MCAUSE_MPIE 0x08000000UL
52 #define METAL_MCAUSE_MPIL 0x00FF0000UL
53 #define METAL_MSTATUS_MIE 0x00000008UL
54 #define METAL_MSTATUS_MPIE 0x00000080UL
55 #define METAL_MSTATUS_MPP 0x00001800UL
56 #define METAL_MSTATUS_FS_INIT 0x00002000UL
57 #define METAL_MSTATUS_FS_CLEAN 0x00004000UL
58 #define METAL_MSTATUS_FS_DIRTY 0x00006000UL
59 #define METAL_MSTATUS_MPRV 0x00020000UL
60 #define METAL_MSTATUS_MXR 0x00080000UL
61 #define METAL_MINTSTATUS_MIL 0xFF000000UL
62 #define METAL_MINTSTATUS_SIL 0x0000FF00UL
63 #define METAL_MINTSTATUS_UIL 0x000000FFUL
65 #define METAL_LOCAL_INTR(X) (16 + X)
66 #define METAL_MCAUSE_EVAL(cause) (cause & METAL_MCAUSE_INTR)
67 #define METAL_INTERRUPT(cause) (METAL_MCAUSE_EVAL(cause) ? 1 : 0)
68 #define METAL_EXCEPTION(cause) (METAL_MCAUSE_EVAL(cause) ? 0 : 1)
69 #define METAL_SW_INTR_EXCEPTION (METAL_MCAUSE_INTR + 3)
70 #define METAL_TMR_INTR_EXCEPTION (METAL_MCAUSE_INTR + 7)
71 #define METAL_EXT_INTR_EXCEPTION (METAL_MCAUSE_INTR + 11)
72 #define METAL_LOCAL_INTR_EXCEPTION(X) (METAL_MCAUSE_INTR + METAL_LOCAL_INTR(X))
73 #define METAL_LOCAL_INTR_RESERVE0 1
74 #define METAL_LOCAL_INTR_RESERVE1 2
75 #define METAL_LOCAL_INTR_RESERVE2 4
76 #define METAL_LOCAL_INTERRUPT_SW 8 /* Bit3 0x008 */
77 #define METAL_LOCAL_INTR_RESERVE4 16
78 #define METAL_LOCAL_INTR_RESERVE5 32
79 #define METAL_LOCAL_INTR_RESERVE6 64
80 #define METAL_LOCAL_INTERRUPT_TMR 128 /* Bit7 0x080 */
81 #define METAL_LOCAL_INTR_RESERVE8 256
82 #define METAL_LOCAL_INTR_RESERVE9 512
83 #define METAL_LOCAL_INTR_RESERVE10 1024
84 #define METAL_LOCAL_INTERRUPT_EXT 2048 /* Bit11 0x800 */
85 /* Bit12 to Bit15 are Reserved */
86 #define METAL_LOCAL_INTERRUPT(X) (0x10000 << X) /* Bit16+ Start of Custom Local Interrupt */
87 #define METAL_MIE_INTERRUPT METAL_MSTATUS_MIE
90 METAL_MACHINE_PRIVILEGE_MODE,
91 METAL_SUPERVISOR_PRIVILEGE_MODE,
92 METAL_USER_PRIVILEGE_MODE,
93 } metal_privilege_mode_e;
96 METAL_INTERRUPT_ID_BASE,
97 METAL_INTERRUPT_ID_SW = (METAL_INTERRUPT_ID_BASE + 3),
98 METAL_INTERRUPT_ID_TMR = (METAL_INTERRUPT_ID_BASE + 7),
99 METAL_INTERRUPT_ID_EXT = (METAL_INTERRUPT_ID_BASE + 11),
100 METAL_INTERRUPT_ID_LC0 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(0)),
101 METAL_INTERRUPT_ID_LC1 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(1)),
102 METAL_INTERRUPT_ID_LC2 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(2)),
103 METAL_INTERRUPT_ID_LC3 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(3)),
104 METAL_INTERRUPT_ID_LC4 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(4)),
105 METAL_INTERRUPT_ID_LC5 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(5)),
106 METAL_INTERRUPT_ID_LC6 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(6)),
107 METAL_INTERRUPT_ID_LC7 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(7)),
108 METAL_INTERRUPT_ID_LC8 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(8)),
109 METAL_INTERRUPT_ID_LC9 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(9)),
110 METAL_INTERRUPT_ID_LC10 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(10)),
111 METAL_INTERRUPT_ID_LC11 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(11)),
112 METAL_INTERRUPT_ID_LC12 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(12)),
113 METAL_INTERRUPT_ID_LC13 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(13)),
114 METAL_INTERRUPT_ID_LC14 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(14)),
115 METAL_INTERRUPT_ID_LC15 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(15)),
116 METAL_INTERRUPT_ID_LCMX,
117 METAL_INTERRUPT_ID_GL0 = METAL_INTERRUPT_ID_LCMX,
118 METAL_INTERRUPT_ID_GLMX = (METAL_MCAUSE_CAUSE + 1),
119 } metal_interrupt_id_e;
122 METAL_IAM_EXCEPTION_CODE, /* Instruction address misaligned */
123 METAL_IAF_EXCEPTION_CODE, /* Instruction access faultd */
124 METAL_II_EXCEPTION_CODE, /* Illegal instruction */
125 METAL_BREAK_EXCEPTION_CODE, /* Breakpoint */
126 METAL_LAM_EXCEPTION_CODE, /* Load address misaligned */
127 METAL_LAF_EXCEPTION_CODE, /* Load access fault */
128 METAL_SAMOAM_EXCEPTION_CODE, /* Store/AMO address misaligned */
129 METAL_SAMOAF_EXCEPTION_CODE, /* Store/AMO access fault */
130 METAL_ECALL_U_EXCEPTION_CODE, /* Environment call from U-mode */
131 METAL_R9_EXCEPTION_CODE, /* Reserved */
132 METAL_R10_EXCEPTION_CODE, /* Reserved */
133 METAL_ECALL_M_EXCEPTION_CODE, /* Environment call from M-mode */
134 METAL_MAX_EXCEPTION_CODE,
135 } metal_exception_code_e;
138 METAL_TIMER_MTIME_GET = 1,
139 METAL_SOFTWARE_IPI_CLEAR,
140 METAL_SOFTWARE_IPI_SET,
141 METAL_SOFTWARE_MSIP_GET,
142 METAL_MAX_INTERRUPT_GET,
143 METAL_INDEX_INTERRUPT_GET,
144 } metal_interrup_cmd_e;
146 typedef struct __metal_interrupt_data {
148 metal_interrupt_handler_t handler;
151 } __metal_interrupt_data;
153 /* CPU interrupt controller */
155 uintptr_t __metal_myhart_id(void);
157 struct __metal_driver_interrupt_controller_vtable {
158 void (*interrupt_init)(struct metal_interrupt *controller);
159 int (*interrupt_register)(struct metal_interrupt *controller,
160 int id, metal_interrupt_handler_t isr, void *priv_data);
161 int (*interrupt_enable)(struct metal_interrupt *controller, int id);
162 int (*interrupt_disable)(struct metal_interrupt *controller, int id);
163 int (*command_request)(struct metal_interrupt *intr, int cmd, void *data);
166 struct __metal_driver_vtable_riscv_cpu_intc {
167 struct metal_interrupt_vtable controller_vtable;
171 void __metal_interrupt_global_enable(void);
172 void __metal_interrupt_global_disable(void);
173 void __metal_controller_interrupt_vector(metal_vector_mode mode, void *vec_table);
174 inline int __metal_controller_interrupt_is_selective_vectored (void)
178 asm volatile ("csrr %0, mtvec" : "=r"(val));
179 return ((val & METAL_MTVEC_CLIC_VECTORED) == METAL_MTVEC_CLIC);
182 __METAL_DECLARE_VTABLE(__metal_driver_vtable_riscv_cpu_intc)
184 struct __metal_driver_riscv_cpu_intc {
185 struct metal_interrupt controller;
187 uintptr_t metal_mtvec_table[METAL_MAX_MI];
188 __metal_interrupt_data metal_int_table[METAL_MAX_MI];
189 metal_exception_handler_t metal_exception_table[METAL_MAX_ME];
193 struct __metal_driver_vtable_cpu {
194 struct metal_cpu_vtable cpu_vtable;
197 __METAL_DECLARE_VTABLE(__metal_driver_vtable_cpu)
199 struct __metal_driver_cpu {
200 struct metal_cpu cpu;