C Microkernel Realtime eXecutive
Realtime Operating System for Cortex-M based microcontrollers
 
Loading...
Searching...
No Matches
exception_frame.h
1#pragma once
2
27/*
28 * Byte offsets — usable from both C and assembly.
29 *
30 * Caller-saved registers (offsets 0-60):
31 */
32#define EF_RA 0
33#define EF_T0 4
34#define EF_T1 8
35#define EF_T2 12
36#define EF_A0 16
37#define EF_A1 20
38#define EF_A2 24
39#define EF_A3 28
40#define EF_A4 32
41#define EF_A5 36
42#define EF_A6 40
43#define EF_A7 44
44#define EF_T3 48
45#define EF_T4 52
46#define EF_T5 56
47#define EF_T6 60
48
49/* Callee-saved registers (offsets 64-108): */
50#define EF_S0 64
51#define EF_S1 68
52#define EF_S2 72
53#define EF_S3 76
54#define EF_S4 80
55#define EF_S5 84
56#define EF_S6 88
57#define EF_S7 92
58#define EF_S8 96
59#define EF_S9 100
60#define EF_S10 104
61#define EF_S11 108
62
63/* CSRs (offsets 112-116): */
64#define EF_MEPC 112
65#define EF_MSTATUS 116
66
68#define EXCEPTION_FRAME_SIZE 128
69
70/* Stringification helpers for use inside inline asm macros. */
71#define _RISCV_EFS(x) #x
72#define RISCV_EFS(x) _RISCV_EFS(x)
73
80#define SAVE_CONTEXT() \
81asm volatile( \
82 "addi sp, sp, -" RISCV_EFS(EXCEPTION_FRAME_SIZE) "\n\t" \
83 "sw ra, " RISCV_EFS(EF_RA) "(sp)\n\t" \
84 "sw t0, " RISCV_EFS(EF_T0) "(sp)\n\t" \
85 "sw t1, " RISCV_EFS(EF_T1) "(sp)\n\t" \
86 "sw t2, " RISCV_EFS(EF_T2) "(sp)\n\t" \
87 "sw a0, " RISCV_EFS(EF_A0) "(sp)\n\t" \
88 "sw a1, " RISCV_EFS(EF_A1) "(sp)\n\t" \
89 "sw a2, " RISCV_EFS(EF_A2) "(sp)\n\t" \
90 "sw a3, " RISCV_EFS(EF_A3) "(sp)\n\t" \
91 "sw a4, " RISCV_EFS(EF_A4) "(sp)\n\t" \
92 "sw a5, " RISCV_EFS(EF_A5) "(sp)\n\t" \
93 "sw a6, " RISCV_EFS(EF_A6) "(sp)\n\t" \
94 "sw a7, " RISCV_EFS(EF_A7) "(sp)\n\t" \
95 "sw t3, " RISCV_EFS(EF_T3) "(sp)\n\t" \
96 "sw t4, " RISCV_EFS(EF_T4) "(sp)\n\t" \
97 "sw t5, " RISCV_EFS(EF_T5) "(sp)\n\t" \
98 "sw t6, " RISCV_EFS(EF_T6) "(sp)\n\t" \
99 "sw s0, " RISCV_EFS(EF_S0) "(sp)\n\t" \
100 "sw s1, " RISCV_EFS(EF_S1) "(sp)\n\t" \
101 "sw s2, " RISCV_EFS(EF_S2) "(sp)\n\t" \
102 "sw s3, " RISCV_EFS(EF_S3) "(sp)\n\t" \
103 "sw s4, " RISCV_EFS(EF_S4) "(sp)\n\t" \
104 "sw s5, " RISCV_EFS(EF_S5) "(sp)\n\t" \
105 "sw s6, " RISCV_EFS(EF_S6) "(sp)\n\t" \
106 "sw s7, " RISCV_EFS(EF_S7) "(sp)\n\t" \
107 "sw s8, " RISCV_EFS(EF_S8) "(sp)\n\t" \
108 "sw s9, " RISCV_EFS(EF_S9) "(sp)\n\t" \
109 "sw s10, " RISCV_EFS(EF_S10) "(sp)\n\t" \
110 "sw s11, " RISCV_EFS(EF_S11) "(sp)\n\t" \
111 "csrr t0, mepc\n\t" \
112 "csrr t1, mstatus\n\t" \
113 "sw t0, " RISCV_EFS(EF_MEPC) "(sp)\n\t" \
114 "sw t1, " RISCV_EFS(EF_MSTATUS) "(sp)\n\t" \
115 : : : "memory" \
116)
117
124#define LOAD_CONTEXT() \
125asm volatile( \
126 "lw t0, " RISCV_EFS(EF_MEPC) "(sp)\n\t" \
127 "lw t1, " RISCV_EFS(EF_MSTATUS) "(sp)\n\t" \
128 "csrw mepc, t0\n\t" \
129 "csrw mstatus, t1\n\t" \
130 "lw s0, " RISCV_EFS(EF_S0) "(sp)\n\t" \
131 "lw s1, " RISCV_EFS(EF_S1) "(sp)\n\t" \
132 "lw s2, " RISCV_EFS(EF_S2) "(sp)\n\t" \
133 "lw s3, " RISCV_EFS(EF_S3) "(sp)\n\t" \
134 "lw s4, " RISCV_EFS(EF_S4) "(sp)\n\t" \
135 "lw s5, " RISCV_EFS(EF_S5) "(sp)\n\t" \
136 "lw s6, " RISCV_EFS(EF_S6) "(sp)\n\t" \
137 "lw s7, " RISCV_EFS(EF_S7) "(sp)\n\t" \
138 "lw s8, " RISCV_EFS(EF_S8) "(sp)\n\t" \
139 "lw s9, " RISCV_EFS(EF_S9) "(sp)\n\t" \
140 "lw s10, " RISCV_EFS(EF_S10) "(sp)\n\t" \
141 "lw s11, " RISCV_EFS(EF_S11) "(sp)\n\t" \
142 "lw ra, " RISCV_EFS(EF_RA) "(sp)\n\t" \
143 "lw t0, " RISCV_EFS(EF_T0) "(sp)\n\t" \
144 "lw t1, " RISCV_EFS(EF_T1) "(sp)\n\t" \
145 "lw t2, " RISCV_EFS(EF_T2) "(sp)\n\t" \
146 "lw a0, " RISCV_EFS(EF_A0) "(sp)\n\t" \
147 "lw a1, " RISCV_EFS(EF_A1) "(sp)\n\t" \
148 "lw a2, " RISCV_EFS(EF_A2) "(sp)\n\t" \
149 "lw a3, " RISCV_EFS(EF_A3) "(sp)\n\t" \
150 "lw a4, " RISCV_EFS(EF_A4) "(sp)\n\t" \
151 "lw a5, " RISCV_EFS(EF_A5) "(sp)\n\t" \
152 "lw a6, " RISCV_EFS(EF_A6) "(sp)\n\t" \
153 "lw a7, " RISCV_EFS(EF_A7) "(sp)\n\t" \
154 "lw t3, " RISCV_EFS(EF_T3) "(sp)\n\t" \
155 "lw t4, " RISCV_EFS(EF_T4) "(sp)\n\t" \
156 "lw t5, " RISCV_EFS(EF_T5) "(sp)\n\t" \
157 "lw t6, " RISCV_EFS(EF_T6) "(sp)\n\t" \
158 "addi sp, sp, " RISCV_EFS(EXCEPTION_FRAME_SIZE) "\n\t" \
159 : : : "memory" \
160)
161
162#ifndef __ASSEMBLER__
163
164#include <stdint.h>
165
176typedef struct {
177 /* Caller-saved registers */
178 uint32_t ra;
179 uint32_t t0;
180 uint32_t t1;
181 uint32_t t2;
182 uint32_t a0;
183 uint32_t a1;
184 uint32_t a2;
185 uint32_t a3;
186 uint32_t a4;
187 uint32_t a5;
188 uint32_t a6;
189 uint32_t a7;
190 uint32_t t3;
191 uint32_t t4;
192 uint32_t t5;
193 uint32_t t6;
194 /* Callee-saved registers */
195 uint32_t s0;
196 uint32_t s1;
197 uint32_t s2;
198 uint32_t s3;
199 uint32_t s4;
200 uint32_t s5;
201 uint32_t s6;
202 uint32_t s7;
203 uint32_t s8;
204 uint32_t s9;
205 uint32_t s10;
206 uint32_t s11;
207 /* CSRs */
208 uint32_t mepc;
209 uint32_t mstatus;
210 /* Padding for 16-byte alignment */
211 uint32_t _pad[2];
213
214_Static_assert(sizeof(ExceptionFrame) == EXCEPTION_FRAME_SIZE,
215 "ExceptionFrame size must match EXCEPTION_FRAME_SIZE");
216
218#define EXCEPTION_FRAME_WORDS (sizeof(ExceptionFrame) / sizeof(uint32_t))
219
227#define CMRX_RISCV_INITIAL_MSTATUS ((1u << 7) | (3u << 11))
228
233static inline uint32_t riscv_exception_get_arg(const ExceptionFrame *frame,
234 unsigned argno)
235{
236 switch (argno) {
237 case 0: return frame->a0;
238 case 1: return frame->a1;
239 case 2: return frame->a2;
240 case 3: return frame->a3;
241 default: return 0;
242 }
243}
244
246static inline uint8_t riscv_exception_get_syscall_id(const ExceptionFrame *frame)
247{
248 return (uint8_t)frame->a7;
249}
250
253 int32_t retval)
254{
255 frame->a0 = (uint32_t)retval;
256}
257
258#endif /* __ASSEMBLER__ */
259
static uint8_t riscv_exception_get_syscall_id(const ExceptionFrame *frame)
Retrieve the syscall ID from the exception frame (a7 per RISC-V ecall ABI).
Definition exception_frame.h:246
static uint32_t riscv_exception_get_arg(const ExceptionFrame *frame, unsigned argno)
Retrieve a syscall argument from the exception frame.
Definition exception_frame.h:233
static void riscv_exception_set_retval(ExceptionFrame *frame, int32_t retval)
Write the syscall return value into the exception frame (a0).
Definition exception_frame.h:252
#define EXCEPTION_FRAME_SIZE
Total frame size in bytes.
Definition exception_frame.h:68
Full RISC-V trap context frame.
Definition exception_frame.h:176
uint32_t t2
Definition exception_frame.h:181
uint32_t a1
Definition exception_frame.h:183
uint32_t s9
Definition exception_frame.h:204
uint32_t s2
Definition exception_frame.h:197
uint32_t s5
Definition exception_frame.h:200
uint32_t s0
Definition exception_frame.h:195
uint32_t s6
Definition exception_frame.h:201
uint32_t mepc
Definition exception_frame.h:208
uint32_t s11
Definition exception_frame.h:206
uint32_t t4
Definition exception_frame.h:191
uint32_t a6
Definition exception_frame.h:188
uint32_t a4
Definition exception_frame.h:186
uint32_t t6
Definition exception_frame.h:193
uint32_t s1
Definition exception_frame.h:196
uint32_t t1
Definition exception_frame.h:180
uint32_t a2
Definition exception_frame.h:184
uint32_t t3
Definition exception_frame.h:190
uint32_t a0
Definition exception_frame.h:182
uint32_t a7
Definition exception_frame.h:189
uint32_t t0
Definition exception_frame.h:179
uint32_t a3
Definition exception_frame.h:185
uint32_t s4
Definition exception_frame.h:199
uint32_t s8
Definition exception_frame.h:203
uint32_t s10
Definition exception_frame.h:205
uint32_t ra
Definition exception_frame.h:178
uint32_t mstatus
Definition exception_frame.h:209
uint32_t t5
Definition exception_frame.h:192
uint32_t a5
Definition exception_frame.h:187
uint32_t s3
Definition exception_frame.h:198
uint32_t s7
Definition exception_frame.h:202