kernel/riscv.h

380 lines
1#ifndef __ASSEMBLER__23// which hart (core) is this?4static inline uint645r_mhartid()6{7  uint64 x;8  asm volatile("csrr %0, mhartid" : "=r" (x) );9  return x;10}1112// Machine Status Register, mstatus1314#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)1819static inline uint6420r_mstatus()21{22  uint64 x;23  asm volatile("csrr %0, mstatus" : "=r" (x) );24  return x;25}2627static inline void 28w_mstatus(uint64 x)29{30  asm volatile("csrw mstatus, %0" : : "r" (x));31}3233// machine exception program counter, holds the34// instruction address to which a return from35// exception will go.36static inline void 37w_mepc(uint64 x)38{39  asm volatile("csrw mepc, %0" : : "r" (x));40}4142// Supervisor Status Register, sstatus4344#define SSTATUS_SPP (1L << 8)  // Previous mode, 1=Supervisor, 0=User45#define SSTATUS_SPIE (1L << 5) // Supervisor Previous Interrupt Enable46#define SSTATUS_UPIE (1L << 4) // User Previous Interrupt Enable47#define SSTATUS_SIE (1L << 1)  // Supervisor Interrupt Enable48#define SSTATUS_UIE (1L << 0)  // User Interrupt Enable4950static inline uint6451r_sstatus()52{53  uint64 x;54  asm volatile("csrr %0, sstatus" : "=r" (x) );55  return x;56}5758static inline void 59w_sstatus(uint64 x)60{61  asm volatile("csrw sstatus, %0" : : "r" (x));62}6364// Supervisor Interrupt Pending65static inline uint6466r_sip()67{68  uint64 x;69  asm volatile("csrr %0, sip" : "=r" (x) );70  return x;71}7273static inline void 74w_sip(uint64 x)75{76  asm volatile("csrw sip, %0" : : "r" (x));77}7879// Supervisor Interrupt Enable80#define SIE_SEIE (1L << 9) // external81#define SIE_STIE (1L << 5) // timer82static inline uint6483r_sie()84{85  uint64 x;86  asm volatile("csrr %0, sie" : "=r" (x) );87  return x;88}8990static inline void 91w_sie(uint64 x)92{93  asm volatile("csrw sie, %0" : : "r" (x));94}9596// Machine-mode Interrupt Enable97#define MIE_STIE (1L << 5)  // supervisor timer98static inline uint6499r_mie()100{101  uint64 x;102  asm volatile("csrr %0, mie" : "=r" (x) );103  return x;104}105106static inline void 107w_mie(uint64 x)108{109  asm volatile("csrw mie, %0" : : "r" (x));110}111112// supervisor exception program counter, holds the113// instruction address to which a return from114// exception will go.115static inline void 116w_sepc(uint64 x)117{118  asm volatile("csrw sepc, %0" : : "r" (x));119}120121static inline uint64122r_sepc()123{124  uint64 x;125  asm volatile("csrr %0, sepc" : "=r" (x) );126  return x;127}128129// Machine Exception Delegation130static inline uint64131r_medeleg()132{133  uint64 x;134  asm volatile("csrr %0, medeleg" : "=r" (x) );135  return x;136}137138static inline void 139w_medeleg(uint64 x)140{141  asm volatile("csrw medeleg, %0" : : "r" (x));142}143144// Machine Interrupt Delegation145static inline uint64146r_mideleg()147{148  uint64 x;149  asm volatile("csrr %0, mideleg" : "=r" (x) );150  return x;151}152153static inline void 154w_mideleg(uint64 x)155{156  asm volatile("csrw mideleg, %0" : : "r" (x));157}158159// Supervisor Trap-Vector Base Address160// low two bits are mode.161static inline void 162w_stvec(uint64 x)163{164  asm volatile("csrw stvec, %0" : : "r" (x));165}166167static inline uint64168r_stvec()169{170  uint64 x;171  asm volatile("csrr %0, stvec" : "=r" (x) );172  return x;173}174175// Supervisor Timer Comparison Register176static inline uint64177r_stimecmp()178{179  uint64 x;180  // asm volatile("csrr %0, stimecmp" : "=r" (x) );181  asm volatile("csrr %0, 0x14d" : "=r" (x) );182  return x;183}184185static inline void 186w_stimecmp(uint64 x)187{188  // asm volatile("csrw stimecmp, %0" : : "r" (x));189  asm volatile("csrw 0x14d, %0" : : "r" (x));190}191192// Machine Environment Configuration Register193static inline uint64194r_menvcfg()195{196  uint64 x;197  // asm volatile("csrr %0, menvcfg" : "=r" (x) );198  asm volatile("csrr %0, 0x30a" : "=r" (x) );199  return x;200}201202static inline void 203w_menvcfg(uint64 x)204{205  // asm volatile("csrw menvcfg, %0" : : "r" (x));206  asm volatile("csrw 0x30a, %0" : : "r" (x));207}208209// Physical Memory Protection210static inline void211w_pmpcfg0(uint64 x)212{213  asm volatile("csrw pmpcfg0, %0" : : "r" (x));214}215216static inline void217w_pmpaddr0(uint64 x)218{219  asm volatile("csrw pmpaddr0, %0" : : "r" (x));220}221222// use riscv's sv39 page table scheme.223#define SATP_SV39 (8L << 60)224225#define MAKE_SATP(pagetable) (SATP_SV39 | (((uint64)pagetable) >> 12))226227// supervisor address translation and protection;228// holds the address of the page table.229static inline void 230w_satp(uint64 x)231{232  asm volatile("csrw satp, %0" : : "r" (x));233}234235static inline uint64236r_satp()237{238  uint64 x;239  asm volatile("csrr %0, satp" : "=r" (x) );240  return x;241}242243// Supervisor Trap Cause244static inline uint64245r_scause()246{247  uint64 x;248  asm volatile("csrr %0, scause" : "=r" (x) );249  return x;250}251252// Supervisor Trap Value253static inline uint64254r_stval()255{256  uint64 x;257  asm volatile("csrr %0, stval" : "=r" (x) );258  return x;259}260261// Machine-mode Counter-Enable262static inline void 263w_mcounteren(uint64 x)264{265  asm volatile("csrw mcounteren, %0" : : "r" (x));266}267268static inline uint64269r_mcounteren()270{271  uint64 x;272  asm volatile("csrr %0, mcounteren" : "=r" (x) );273  return x;274}275276// machine-mode cycle counter277static inline uint64278r_time()279{280  uint64 x;281  asm volatile("csrr %0, time" : "=r" (x) );282  return x;283}284285// enable device interrupts286static inline void287intr_on()288{289  w_sstatus(r_sstatus() | SSTATUS_SIE);290}291292// disable device interrupts293static inline void294intr_off()295{296  w_sstatus(r_sstatus() & ~SSTATUS_SIE);297}298299// are device interrupts enabled?300static inline int301intr_get()302{303  uint64 x = r_sstatus();304  return (x & SSTATUS_SIE) != 0;305}306307static inline uint64308r_sp()309{310  uint64 x;311  asm volatile("mv %0, sp" : "=r" (x) );312  return x;313}314315// read and write tp, the thread pointer, which xv6 uses to hold316// this core's hartid (core number), the index into cpus[].317static inline uint64318r_tp()319{320  uint64 x;321  asm volatile("mv %0, tp" : "=r" (x) );322  return x;323}324325static inline void 326w_tp(uint64 x)327{328  asm volatile("mv tp, %0" : : "r" (x));329}330331static inline uint64332r_ra()333{334  uint64 x;335  asm volatile("mv %0, ra" : "=r" (x) );336  return x;337}338339// flush the TLB.340static inline void341sfence_vma()342{343  // the zero, zero means flush all TLB entries.344  asm volatile("sfence.vma zero, zero");345}346347typedef uint64 pte_t;348typedef uint64 *pagetable_t; // 512 PTEs349350#endif // __ASSEMBLER__351352#define PGSIZE 4096 // bytes per page353#define PGSHIFT 12  // bits of offset within a page354355#define PGROUNDUP(sz)  (((sz)+PGSIZE-1) & ~(PGSIZE-1))356#define PGROUNDDOWN(a) (((a)) & ~(PGSIZE-1))357358#define PTE_V (1L << 0) // valid359#define PTE_R (1L << 1)360#define PTE_W (1L << 2)361#define PTE_X (1L << 3)362#define PTE_U (1L << 4) // user can access363364// shift a physical address to the right place for a PTE.365#define PA2PTE(pa) ((((uint64)pa) >> 12) << 10)366367#define PTE2PA(pte) (((pte) >> 10) << 12)368369#define PTE_FLAGS(pte) ((pte) & 0x3FF)370371// extract the three 9-bit page table indices from a virtual address.372#define PXMASK          0x1FF // 9 bits373#define PXSHIFT(level)  (PGSHIFT+(9*(level)))374#define PX(level, va) ((((uint64) (va)) >> PXSHIFT(level)) & PXMASK)375376// one beyond the highest possible virtual address.377// MAXVA is actually one bit less than the max allowed by378// Sv39, to avoid having to sign-extend virtual addresses379// that have the high bit set.380#define MAXVA (1L << (9 + 9 + 9 + 12 - 1))381