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. r_sip
  8. w_sip
  9. r_sie
  10. w_sie
  11. r_mie
  12. w_mie
  13. w_sepc
  14. r_sepc
  15. r_medeleg
  16. w_medeleg
  17. r_mideleg
  18. w_mideleg
  19. w_stvec
  20. r_stvec
  21. r_stimecmp
  22. w_stimecmp
  23. r_menvcfg
  24. w_menvcfg
  25. w_pmpcfg0
  26. w_pmpaddr0
  27. w_satp
  28. r_satp
  29. r_scause
  30. r_stval
  31. w_mcounteren
  32. r_mcounteren
  33. r_time
  34. intr_on
  35. intr_off
  36. intr_get
  37. r_sp
  38. r_tp
  39. w_tp
  40. r_ra
  41. sfence_vma

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

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