1 /* 2 * Copyright 2021, Haiku, Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 */ 5 #ifndef _SYSTEM_ARCH_RISCV64_DEFS_H 6 #define _SYSTEM_ARCH_RISCV64_DEFS_H 7 8 9 #include <SupportDefs.h> 10 11 12 enum { 13 modeU = 0, 14 modeS = 1, 15 modeM = 3, 16 }; 17 18 // fs, xs 19 enum { 20 extStatusOff = 0, 21 extStatusInitial = 1, 22 extStatusClean = 2, 23 extStatusDirty = 3, 24 }; 25 26 struct MstatusReg { 27 union { 28 struct { 29 uint64 ie: 4; // interrupt enable 30 uint64 pie: 4; // previous interrupt enable 31 uint64 spp: 1; // previous mode (supervisor) 32 uint64 unused1: 2; 33 uint64 mpp: 2; // previous mode (machine) 34 uint64 fs: 2; // FPU status 35 uint64 xs: 2; // extensions status 36 uint64 mprv: 1; // modify privelege 37 uint64 sum: 1; // permit supervisor user memory access 38 uint64 mxr: 1; // make executable readable 39 uint64 tvm: 1; // trap virtual memory 40 uint64 tw: 1; // timeout wait (trap WFI) 41 uint64 tsr: 1; // trap SRET 42 uint64 unused2: 9; 43 uint64 uxl: 2; // U-mode XLEN 44 uint64 sxl: 2; // S-mode XLEN 45 uint64 unused3: 27; 46 uint64 sd: 1; // status dirty 47 }; 48 uint64 val; 49 }; 50 51 MstatusReg() {} 52 MstatusReg(uint64 val): val(val) {} 53 }; 54 55 struct SstatusReg { 56 union { 57 struct { 58 uint64 ie: 2; // interrupt enable 59 uint64 unused1: 2; 60 uint64 pie: 2; // previous interrupt enable 61 uint64 unused2: 2; 62 uint64 spp: 1; // previous mode (supervisor) 63 uint64 unused3: 4; 64 uint64 fs: 2; // FPU status 65 uint64 xs: 2; // extensions status 66 uint64 unused4: 1; 67 uint64 sum: 1; // permit supervisor user memory access 68 uint64 mxr: 1; // make executable readable 69 uint64 unused5: 12; 70 uint64 uxl: 2; // U-mode XLEN 71 uint64 unused6: 29; 72 uint64 sd: 1; // status dirty 73 }; 74 uint64 val; 75 }; 76 77 SstatusReg() {} 78 SstatusReg(uint64 val): val(val) {} 79 }; 80 81 enum { 82 softInt = 0, 83 uSoftInt = softInt + modeU, 84 sSoftInt = softInt + modeS, 85 mSoftInt = softInt + modeM, 86 timerInt = 4, 87 uTimerInt = timerInt + modeU, 88 sTimerInt = timerInt + modeS, 89 mTimerInt = timerInt + modeM, 90 externInt = 8, 91 uExternInt = externInt + modeU, 92 sExternInt = externInt + modeS, 93 mExternInt = externInt + modeM, 94 }; 95 96 enum { 97 causeInterrupt = 1ULL << 63, // rest bits are interrupt number 98 causeExecMisalign = 0, 99 causeExecAccessFault = 1, 100 causeIllegalInst = 2, 101 causeBreakpoint = 3, 102 causeLoadMisalign = 4, 103 causeLoadAccessFault = 5, 104 causeStoreMisalign = 6, 105 causeStoreAccessFault = 7, 106 causeECall = 8, 107 causeUEcall = causeECall + modeU, 108 causeSEcall = causeECall + modeS, 109 causeMEcall = causeECall + modeM, 110 causeExecPageFault = 12, 111 causeLoadPageFault = 13, 112 causeStorePageFault = 15, 113 }; 114 115 enum { 116 pageSize = 4096, 117 pageBits = 12, 118 pteCount = 512, 119 pteIdxBits = 9, 120 }; 121 122 enum { 123 pteValid = 0, 124 pteRead = 1, 125 pteWrite = 2, 126 pteExec = 3, 127 pteUser = 4, 128 pteGlobal = 5, 129 pteAccessed = 6, 130 pteDirty = 7, 131 }; 132 133 struct Pte { 134 union { 135 struct { 136 uint64 flags: 8; 137 uint64 rsw: 2; 138 uint64 ppn: 44; 139 uint64 reserved: 10; 140 }; 141 uint64 val; 142 }; 143 144 Pte() {} 145 Pte(uint64 val): val(val) {} 146 }; 147 148 enum { 149 satpModeBare = 0, 150 satpModeSv39 = 8, 151 satpModeSv48 = 9, 152 satpModeSv57 = 10, 153 satpModeSv64 = 11, 154 }; 155 156 struct SatpReg { 157 union { 158 struct { 159 uint64 ppn: 44; 160 uint64 asid: 16; 161 uint64 mode: 4; 162 }; 163 uint64 val; 164 }; 165 166 SatpReg() {} 167 SatpReg(uint64 val): val(val) {} 168 }; 169 170 static B_ALWAYS_INLINE uint64 PhysAdrPte(uint64 physAdr, uint32 level) 171 { 172 return (physAdr >> (pageBits + pteIdxBits*level)) % (1 << pteIdxBits); 173 } 174 175 static B_ALWAYS_INLINE uint64 PhysAdrOfs(uint64 physAdr) 176 { 177 return physAdr % pageSize; 178 } 179 180 // CPU core ID 181 static B_ALWAYS_INLINE uint64 Mhartid() { 182 uint64 x; asm volatile("csrr %0, mhartid" : "=r" (x)); return x;} 183 184 // status register 185 static B_ALWAYS_INLINE uint64 Mstatus() { 186 uint64 x; asm volatile("csrr %0, mstatus" : "=r" (x)); return x;} 187 static B_ALWAYS_INLINE void SetMstatus(uint64 x) { 188 asm volatile("csrw mstatus, %0" : : "r" (x));} 189 static B_ALWAYS_INLINE uint64 Sstatus() { 190 uint64 x; asm volatile("csrr %0, sstatus" : "=r" (x)); return x;} 191 static B_ALWAYS_INLINE void SetSstatus(uint64 x) { 192 asm volatile("csrw sstatus, %0" : : "r" (x));} 193 194 // exception program counter 195 static B_ALWAYS_INLINE uint64 Mepc() { 196 uint64 x; asm volatile("csrr %0, mepc" : "=r" (x)); return x;} 197 static B_ALWAYS_INLINE void SetMepc(uint64 x) { 198 asm volatile("csrw mepc, %0" : : "r" (x));} 199 static B_ALWAYS_INLINE uint64 Sepc() { 200 uint64 x; asm volatile("csrr %0, sepc" : "=r" (x)); return x;} 201 static B_ALWAYS_INLINE void SetSepc(uint64 x) { 202 asm volatile("csrw sepc, %0" : : "r" (x));} 203 204 // interrupt pending 205 static B_ALWAYS_INLINE uint64 Mip() { 206 uint64 x; asm volatile("csrr %0, mip" : "=r" (x)); return x;} 207 static B_ALWAYS_INLINE void SetMip(uint64 x) { 208 asm volatile("csrw mip, %0" : : "r" (x));} 209 static B_ALWAYS_INLINE uint64 Sip() { 210 uint64 x; asm volatile("csrr %0, sip" : "=r" (x)); return x;} 211 static B_ALWAYS_INLINE void SetSip(uint64 x) { 212 asm volatile("csrw sip, %0" : : "r" (x));} 213 214 // interrupt enable 215 static B_ALWAYS_INLINE uint64 Sie() { 216 uint64 x; asm volatile("csrr %0, sie" : "=r" (x)); return x;} 217 static B_ALWAYS_INLINE void SetSie(uint64 x) { 218 asm volatile("csrw sie, %0" : : "r" (x));} 219 static B_ALWAYS_INLINE uint64 Mie() { 220 uint64 x; asm volatile("csrr %0, mie" : "=r" (x)); return x;} 221 static B_ALWAYS_INLINE void SetMie(uint64 x) { 222 asm volatile("csrw mie, %0" : : "r" (x));} 223 224 // exception delegation 225 static B_ALWAYS_INLINE uint64 Medeleg() { 226 uint64 x; asm volatile("csrr %0, medeleg" : "=r" (x)); return x;} 227 static B_ALWAYS_INLINE void SetMedeleg(uint64 x) { 228 asm volatile("csrw medeleg, %0" : : "r" (x));} 229 // interrupt delegation 230 static B_ALWAYS_INLINE uint64 Mideleg() { 231 uint64 x; asm volatile("csrr %0, mideleg" : "=r" (x)); return x;} 232 static B_ALWAYS_INLINE void SetMideleg(uint64 x) { 233 asm volatile("csrw mideleg, %0" : : "r" (x));} 234 235 // trap vector, 2 low bits: mode 236 static B_ALWAYS_INLINE uint64 Mtvec() { 237 uint64 x; asm volatile("csrr %0, mtvec" : "=r" (x)); return x;} 238 static B_ALWAYS_INLINE void SetMtvec(uint64 x) { 239 asm volatile("csrw mtvec, %0" : : "r" (x));} 240 static B_ALWAYS_INLINE uint64 Stvec() { 241 uint64 x; asm volatile("csrr %0, stvec" : "=r" (x)); return x;} 242 static B_ALWAYS_INLINE void SetStvec(uint64 x) { 243 asm volatile("csrw stvec, %0" : : "r" (x));} 244 245 // address translation and protection (pointer to page table and flags) 246 static B_ALWAYS_INLINE uint64 Satp() { 247 uint64 x; asm volatile("csrr %0, satp" : "=r" (x)); return x;} 248 static B_ALWAYS_INLINE void SetSatp(uint64 x) { 249 asm volatile("csrw satp, %0" : : "r" (x));} 250 251 // scratch register 252 static B_ALWAYS_INLINE uint64 Mscratch() { 253 uint64 x; asm volatile("csrr %0, mscratch" : "=r" (x)); return x;} 254 static B_ALWAYS_INLINE void SetMscratch(uint64 x) { 255 asm volatile("csrw mscratch, %0" : : "r" (x));} 256 static B_ALWAYS_INLINE uint64 Sscratch() { 257 uint64 x; asm volatile("csrr %0, sscratch" : "=r" (x)); return x;} 258 static B_ALWAYS_INLINE void SetSscratch(uint64 x) { 259 asm volatile("csrw sscratch, %0" : : "r" (x));} 260 261 // trap cause 262 static B_ALWAYS_INLINE uint64 Mcause() { 263 uint64 x; asm volatile("csrr %0, mcause" : "=r" (x)); return x;} 264 static B_ALWAYS_INLINE void SetMcause(uint64 x) { 265 asm volatile("csrw mcause, %0" : : "r" (x));} 266 static B_ALWAYS_INLINE uint64 Scause() { 267 uint64 x; asm volatile("csrr %0, scause" : "=r" (x)); return x;} 268 static B_ALWAYS_INLINE void SetScause(uint64 x) { 269 asm volatile("csrw scause, %0" : : "r" (x));} 270 271 // trap value 272 static B_ALWAYS_INLINE uint64 Mtval() { 273 uint64 x; asm volatile("csrr %0, mtval" : "=r" (x)); return x;} 274 static B_ALWAYS_INLINE void SetMtval(uint64 x) { 275 asm volatile("csrw mtval, %0" : : "r" (x));} 276 static B_ALWAYS_INLINE uint64 Stval() { 277 uint64 x; asm volatile("csrr %0, stval" : "=r" (x)); return x;} 278 static B_ALWAYS_INLINE void SetStval(uint64 x) { 279 asm volatile("csrw stval, %0" : : "r" (x));} 280 281 // machine-mode counter enable 282 static B_ALWAYS_INLINE uint64 Mcounteren() { 283 uint64 x; asm volatile("csrr %0, mcounteren" : "=r" (x)); return x;} 284 static B_ALWAYS_INLINE void SetMcounteren(uint64 x) { 285 asm volatile("csrw mcounteren, %0" : : "r" (x));} 286 287 // machine-mode cycle counter 288 static B_ALWAYS_INLINE uint64 Mcycle() { 289 uint64 x; asm volatile("csrr %0, mcycle" : "=r" (x)); return x;} 290 // monotonic timer 291 static B_ALWAYS_INLINE uint64 CpuTime() { 292 uint64 x; asm volatile("csrr %0, time" : "=r" (x)); return x;} 293 294 // flush the TLB 295 static B_ALWAYS_INLINE void FlushTlbAll() { 296 asm volatile("sfence.vma" : : : "memory");} 297 static B_ALWAYS_INLINE void FlushTlbPage(uint64 x) { 298 asm volatile("sfence.vma %0" : : "r" (x) : "memory");} 299 300 static B_ALWAYS_INLINE uint64 Sp() { 301 uint64 x; asm volatile("mv %0, sp" : "=r" (x)); return x;} 302 static B_ALWAYS_INLINE void SetSp(uint64 x) { 303 asm volatile("mv sp, %0" : : "r" (x));} 304 static B_ALWAYS_INLINE uint64 Fp() { 305 uint64 x; asm volatile("mv %0, fp" : "=r" (x)); return x;} 306 static B_ALWAYS_INLINE void SetFp(uint64 x) { 307 asm volatile("mv fp, %0" : : "r" (x));} 308 static B_ALWAYS_INLINE uint64 Tp() { 309 uint64 x; asm volatile("mv %0, tp" : "=r" (x)); return x;} 310 static B_ALWAYS_INLINE void SetTp(uint64 x) { 311 asm volatile("mv tp, %0" : : "r" (x));} 312 static B_ALWAYS_INLINE uint64 Ra() { 313 uint64 x; asm volatile("mv %0, ra" : "=r" (x)); return x;} 314 static B_ALWAYS_INLINE void SetRa(uint64 x) { 315 asm volatile("mv ra, %0" : : "r" (x));} 316 317 static B_ALWAYS_INLINE void Ecall() {asm volatile("ecall");} 318 319 // Wait for interrupts, reduce CPU load when inactive. 320 static B_ALWAYS_INLINE void Wfi() {asm volatile("wfi");} 321 322 static B_ALWAYS_INLINE void Mret() {asm volatile("mret");} 323 static B_ALWAYS_INLINE void Sret() {asm volatile("sret");} 324 325 326 #define SPINLOCK_PAUSE() do {} while (false) 327 328 329 #endif /* _SYSTEM_ARCH_RISCV64_DEFS_H */ 330 331