root/kernel/riscv.h

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. r_mhartid
  2. r_mstatus
  3. w_mstatus
  4. w_mepc
  5. r_sstatus
  6. w_sstatus
  7. s_sstatus
  8. c_sstatus
  9. rc_sstatus
  10. r_sip
  11. w_sip
  12. r_sie
  13. w_sie
  14. r_mie
  15. w_mie
  16. w_sepc
  17. r_sepc
  18. r_medeleg
  19. w_medeleg
  20. r_mideleg
  21. w_mideleg
  22. w_stvec
  23. r_stvec
  24. r_stimecmp
  25. w_stimecmp
  26. r_menvcfg
  27. w_menvcfg
  28. w_pmpcfg0
  29. w_pmpaddr0
  30. w_satp
  31. r_satp
  32. r_scause
  33. r_stval
  34. w_mcounteren
  35. r_mcounteren
  36. r_time
  37. intr_on
  38. intr_off
  39. intr_get
  40. r_sp
  41. r_tp
  42. w_tp
  43. r_ra
  44. sfence_vma
  45. io_fence
  46. icache_fence

   1 #ifndef __ASSEMBLER__
   2 
   3 // which hart (core) is this?
   4 static inline uint64
   5 r_mhartid()
   6 {
   7   uint64 x;
   8   asm volatile("csrr %0, mhartid" : "=r"(x));
   9   return x;
  10 }
  11 
  12 // Machine Status Register, mstatus
  13 
  14 #define MSTATUS_MPP_MASK (3L << 11) // previous mode.
  15 #define MSTATUS_MPP_M    (3L << 11)
  16 #define MSTATUS_MPP_S    (1L << 11)
  17 #define MSTATUS_MPP_U    (0L << 11)
  18 
  19 static inline uint64
  20 r_mstatus()
  21 {
  22   uint64 x;
  23   asm volatile("csrr %0, mstatus" : "=r"(x));
  24   return x;
  25 }
  26 
  27 static inline void
  28 w_mstatus(uint64 x)
  29 {
  30   asm volatile("csrw mstatus, %0" : : "r"(x));
  31 }
  32 
  33 // machine exception program counter, holds the
  34 // instruction address to which a return from
  35 // exception will go.
  36 static inline void
  37 w_mepc(uint64 x)
  38 {
  39   asm volatile("csrw mepc, %0" : : "r"(x));
  40 }
  41 
  42 // Supervisor Status Register, sstatus
  43 
  44 #define SSTATUS_SPP  (1L << 8) // Previous mode, 1=Supervisor, 0=User
  45 #define SSTATUS_SPIE (1L << 5) // Supervisor Previous Interrupt Enable
  46 #define SSTATUS_UPIE (1L << 4) // User Previous Interrupt Enable
  47 #define SSTATUS_SIE  (1L << 1) // Supervisor Interrupt Enable
  48 #define SSTATUS_UIE  (1L << 0) // User Interrupt Enable
  49 
  50 static inline uint64
  51 r_sstatus()
  52 {
  53   uint64 x;
  54   asm volatile("csrr %0, sstatus" : "=r"(x));
  55   return x;
  56 }
  57 
  58 static inline void
  59 w_sstatus(uint64 x)
  60 {
  61   asm volatile("csrw sstatus, %0" : : "r"(x));
  62 }
  63 
  64 static inline void
  65 s_sstatus(uint64 x)
  66 {
  67   __asm__ __volatile__("csrs sstatus, %0" ::"rK"(x) : "memory");
  68 }
  69 
  70 static inline void
  71 c_sstatus(uint64 x)
  72 {
  73   __asm__ __volatile__("csrc sstatus, %0" ::"rK"(x) : "memory");
  74 }
  75 
  76 static inline uint64
  77 rc_sstatus(uint64 x)
  78 {
  79   __asm__ __volatile__("csrrc %0, sstatus, %1" : "=r"(x) : "rK"(x) : "memory");
  80   return x;
  81 }
  82 
  83 // Supervisor Interrupt Pending
  84 static inline uint64
  85 r_sip()
  86 {
  87   uint64 x;
  88   asm volatile("csrr %0, sip" : "=r"(x));
  89   return x;
  90 }
  91 
  92 static inline void
  93 w_sip(uint64 x)
  94 {
  95   asm volatile("csrw sip, %0" : : "r"(x));
  96 }
  97 
  98 // Supervisor Interrupt Enable
  99 #define SIE_SEIE (1L << 9) // external
 100 #define SIE_STIE (1L << 5) // timer
 101 static inline uint64
 102 r_sie()
 103 {
 104   uint64 x;
 105   asm volatile("csrr %0, sie" : "=r"(x));
 106   return x;
 107 }
 108 
 109 static inline void
 110 w_sie(uint64 x)
 111 {
 112   asm volatile("csrw sie, %0" : : "r"(x));
 113 }
 114 
 115 // Machine-mode Interrupt Enable
 116 #define MIE_STIE (1L << 5) // supervisor timer
 117 static inline uint64
 118 r_mie()
 119 {
 120   uint64 x;
 121   asm volatile("csrr %0, mie" : "=r"(x));
 122   return x;
 123 }
 124 
 125 static inline void
 126 w_mie(uint64 x)
 127 {
 128   asm volatile("csrw mie, %0" : : "r"(x));
 129 }
 130 
 131 // supervisor exception program counter, holds the
 132 // instruction address to which a return from
 133 // exception will go.
 134 static inline void
 135 w_sepc(uint64 x)
 136 {
 137   asm volatile("csrw sepc, %0" : : "r"(x));
 138 }
 139 
 140 static inline uint64
 141 r_sepc()
 142 {
 143   uint64 x;
 144   asm volatile("csrr %0, sepc" : "=r"(x));
 145   return x;
 146 }
 147 
 148 // Machine Exception Delegation
 149 static inline uint64
 150 r_medeleg()
 151 {
 152   uint64 x;
 153   asm volatile("csrr %0, medeleg" : "=r"(x));
 154   return x;
 155 }
 156 
 157 static inline void
 158 w_medeleg(uint64 x)
 159 {
 160   asm volatile("csrw medeleg, %0" : : "r"(x));
 161 }
 162 
 163 // Machine Interrupt Delegation
 164 static inline uint64
 165 r_mideleg()
 166 {
 167   uint64 x;
 168   asm volatile("csrr %0, mideleg" : "=r"(x));
 169   return x;
 170 }
 171 
 172 static inline void
 173 w_mideleg(uint64 x)
 174 {
 175   asm volatile("csrw mideleg, %0" : : "r"(x));
 176 }
 177 
 178 // Supervisor Trap-Vector Base Address
 179 // low two bits are mode.
 180 static inline void
 181 w_stvec(uint64 x)
 182 {
 183   asm volatile("csrw stvec, %0" : : "r"(x));
 184 }
 185 
 186 static inline uint64
 187 r_stvec()
 188 {
 189   uint64 x;
 190   asm volatile("csrr %0, stvec" : "=r"(x));
 191   return x;
 192 }
 193 
 194 // Supervisor Timer Comparison Register
 195 static inline uint64
 196 r_stimecmp()
 197 {
 198   uint64 x;
 199   // asm volatile("csrr %0, stimecmp" : "=r" (x) );
 200   asm volatile("csrr %0, 0x14d" : "=r"(x));
 201   return x;
 202 }
 203 
 204 static inline void
 205 w_stimecmp(uint64 x)
 206 {
 207   // asm volatile("csrw stimecmp, %0" : : "r" (x));
 208   asm volatile("csrw 0x14d, %0" : : "r"(x));
 209 }
 210 
 211 // Machine Environment Configuration Register
 212 
 213 #define MENVCFG_STCE (1L << 63)
 214 #define MENVCFG_ADUE (1L << 61)
 215 
 216 static inline uint64
 217 r_menvcfg()
 218 {
 219   uint64 x;
 220   // asm volatile("csrr %0, menvcfg" : "=r" (x) );
 221   asm volatile("csrr %0, 0x30a" : "=r"(x));
 222   return x;
 223 }
 224 
 225 static inline void
 226 w_menvcfg(uint64 x)
 227 {
 228   // asm volatile("csrw menvcfg, %0" : : "r" (x));
 229   asm volatile("csrw 0x30a, %0" : : "r"(x));
 230 }
 231 
 232 // Physical Memory Protection
 233 static inline void
 234 w_pmpcfg0(uint64 x)
 235 {
 236   asm volatile("csrw pmpcfg0, %0" : : "r"(x));
 237 }
 238 
 239 static inline void
 240 w_pmpaddr0(uint64 x)
 241 {
 242   asm volatile("csrw pmpaddr0, %0" : : "r"(x));
 243 }
 244 
 245 // use riscv's sv39 page table scheme.
 246 #define SATP_SV39 (8L << 60)
 247 
 248 #define MAKE_SATP(pagetable) (SATP_SV39 | (((uint64)pagetable) >> 12))
 249 
 250 // supervisor address translation and protection;
 251 // holds the address of the page table.
 252 static inline void
 253 w_satp(uint64 x)
 254 {
 255   asm volatile("csrw satp, %0" : : "r"(x));
 256 }
 257 
 258 static inline uint64
 259 r_satp()
 260 {
 261   uint64 x;
 262   asm volatile("csrr %0, satp" : "=r"(x));
 263   return x;
 264 }
 265 
 266 // Supervisor Trap Cause
 267 static inline uint64
 268 r_scause()
 269 {
 270   uint64 x;
 271   asm volatile("csrr %0, scause" : "=r"(x));
 272   return x;
 273 }
 274 
 275 // Supervisor Trap Value
 276 static inline uint64
 277 r_stval()
 278 {
 279   uint64 x;
 280   asm volatile("csrr %0, stval" : "=r"(x));
 281   return x;
 282 }
 283 
 284 // Machine-mode Counter-Enable
 285 static inline void
 286 w_mcounteren(uint64 x)
 287 {
 288   asm volatile("csrw mcounteren, %0" : : "r"(x));
 289 }
 290 
 291 static inline uint64
 292 r_mcounteren()
 293 {
 294   uint64 x;
 295   asm volatile("csrr %0, mcounteren" : "=r"(x));
 296   return x;
 297 }
 298 
 299 // machine-mode cycle counter
 300 static inline uint64
 301 r_time()
 302 {
 303   uint64 x;
 304   asm volatile("csrr %0, time" : "=r"(x));
 305   return x;
 306 }
 307 
 308 // enable device interrupts
 309 static inline void
 310 intr_on()
 311 {
 312   s_sstatus(SSTATUS_SIE);
 313 }
 314 
 315 // disable device interrupts
 316 static inline void
 317 intr_off()
 318 {
 319   c_sstatus(SSTATUS_SIE);
 320 }
 321 
 322 // are device interrupts enabled?
 323 static inline int
 324 intr_get()
 325 {
 326   uint64 x = r_sstatus();
 327   return (x & SSTATUS_SIE) != 0;
 328 }
 329 
 330 static inline uint64
 331 r_sp()
 332 {
 333   uint64 x;
 334   asm volatile("mv %0, sp" : "=r"(x));
 335   return x;
 336 }
 337 
 338 // read and write tp, the thread pointer, which xv6 uses to hold
 339 // this core's hartid (core number), the index into cpus[].
 340 static inline uint64
 341 r_tp()
 342 {
 343   uint64 x;
 344   asm volatile("mv %0, tp" : "=r"(x));
 345   return x;
 346 }
 347 
 348 static inline void
 349 w_tp(uint64 x)
 350 {
 351   asm volatile("mv tp, %0" : : "r"(x));
 352 }
 353 
 354 static inline uint64
 355 r_ra()
 356 {
 357   uint64 x;
 358   asm volatile("mv %0, ra" : "=r"(x));
 359   return x;
 360 }
 361 
 362 // flush the TLB.
 363 static inline void
 364 sfence_vma()
 365 {
 366   // the zero, zero means flush all TLB entries.
 367   asm volatile("sfence.vma zero, zero" ::: "memory");
 368 }
 369 
 370 // fence for memory-mapped IO
 371 static inline void
 372 io_fence()
 373 {
 374   asm volatile("fence iorw, iorw" ::: "memory");
 375 }
 376 
 377 // fence for icache
 378 static inline void
 379 icache_fence()
 380 {
 381   asm volatile("fence.i" ::: "memory");
 382 }
 383 
 384 typedef uint64 pte_t;
 385 typedef uint64 *pagetable_t; // 512 PTEs
 386 
 387 #endif // __ASSEMBLER__
 388 
 389 #define PGSIZE  4096 // bytes per page
 390 #define PGSHIFT 12   // bits of offset within a page
 391 
 392 #define PGROUNDUP(sz)  (((sz) + PGSIZE - 1) & ~(PGSIZE - 1))
 393 #define PGROUNDDOWN(a) (((a)) & ~(PGSIZE - 1))
 394 
 395 #define PTE_V (1L << 0) // valid
 396 #define PTE_R (1L << 1)
 397 #define PTE_W (1L << 2)
 398 #define PTE_X (1L << 3)
 399 #define PTE_U (1L << 4) // user can access
 400 
 401 // shift a physical address to the right place for a PTE.
 402 #define PA2PTE(pa) ((((uint64)pa) >> 12) << 10)
 403 
 404 #define PTE2PA(pte) (((pte) >> 10) << 12)
 405 
 406 #define PTE_FLAGS(pte) ((pte) & 0x3FF)
 407 
 408 // extract the three 9-bit page table indices from a virtual address.
 409 #define PXMASK         0x1FF // 9 bits
 410 #define PXSHIFT(level) (PGSHIFT + (9 * (level)))
 411 #define PX(level, va)  ((((uint64)(va)) >> PXSHIFT(level)) & PXMASK)
 412 
 413 // one beyond the highest possible virtual address.
 414 // MAXVA is actually one bit less than the max allowed by
 415 // Sv39, to avoid having to sign-extend virtual addresses
 416 // that have the high bit set.
 417 #define MAXVA (1L << (9 + 9 + 9 + 12 - 1))

/* [<][>][^][v][top][bottom][index][help] */