|  | #pragma once | 
|  |  | 
|  | #include <ros/arch/arch.h> | 
|  | #include <arch/mmu.h> | 
|  | #include <ros/common.h> | 
|  | #include <arch/membar.h> | 
|  | #include <arch/riscv.h> | 
|  | #include <arch/time.h> | 
|  |  | 
|  | /* Arch Constants */ | 
|  | #define ARCH_CL_SIZE 64 | 
|  |  | 
|  | void print_cpuinfo(void); | 
|  | void show_mapping(pgdir_t pgdir, uintptr_t start, size_t size); | 
|  | void backtrace(void); | 
|  |  | 
|  | static __inline void breakpoint(void) | 
|  | { | 
|  | asm volatile ("break"); | 
|  | } | 
|  |  | 
|  | static __inline void tlbflush(void) | 
|  | { | 
|  | lcr3(rcr3()); | 
|  | } | 
|  |  | 
|  | static __inline void invlpg(void *addr) | 
|  | { | 
|  | tlbflush(); | 
|  | } | 
|  |  | 
|  | static __inline void icache_flush_page(void* va, void* kva) | 
|  | { | 
|  | asm volatile ("fence.i"); | 
|  | } | 
|  |  | 
|  | static __inline uint64_t read_tsc(void) | 
|  | { | 
|  | unsigned long t; | 
|  | asm volatile ("rdtime %0" : "=r"(t)); | 
|  | return t; | 
|  | } | 
|  |  | 
|  | /* Continuing the poor tradition of x86 opcode functions... */ | 
|  | static __inline uint64_t read_tscp(void) | 
|  | { | 
|  | return read_tsc(); | 
|  | } | 
|  |  | 
|  | static __inline uint64_t read_tsc_serialized(void) | 
|  | { | 
|  | mb(); | 
|  | return read_tsc(); | 
|  | } | 
|  |  | 
|  | static __inline uintptr_t enable_fp(void) | 
|  | { | 
|  | return setpcr(PCR_SR, SR_EF); | 
|  | } | 
|  |  | 
|  | static __inline uintptr_t enable_irq(void) | 
|  | { | 
|  | return setpcr(PCR_SR, SR_ET); | 
|  | } | 
|  |  | 
|  | static __inline uintptr_t disable_irq(void) | 
|  | { | 
|  | return clearpcr(PCR_SR, SR_ET); | 
|  | } | 
|  |  | 
|  | static __inline void restore_irq(uintptr_t val) | 
|  | { | 
|  | mtpcr(PCR_SR, val); | 
|  | } | 
|  |  | 
|  | static __inline int irq_is_enabled(void) | 
|  | { | 
|  | return mfpcr(PCR_SR) & SR_ET; | 
|  | } | 
|  |  | 
|  | static __inline void enable_irqsave(int8_t* state) | 
|  | { | 
|  | // *state tracks the number of nested enables and disables | 
|  | // initial value of state: 0 = first run / no favorite | 
|  | // > 0 means more enabled calls have been made | 
|  | // < 0 means more disabled calls have been made | 
|  | // Mostly doing this so we can call disable_irqsave first if we want | 
|  |  | 
|  | // one side or another "gets a point" if interrupts were already the way | 
|  | // it wanted to go.  o/w, state stays at 0.  if the state was not 0 | 
|  | // then, enabling/disabling isn't even an option.  just | 
|  | // increment/decrement | 
|  |  | 
|  | // if enabling is winning or tied, make sure it's enabled | 
|  | if ((*state == 0) && !irq_is_enabled()) | 
|  | enable_irq(); | 
|  | else | 
|  | (*state)++; | 
|  | } | 
|  |  | 
|  | static __inline void disable_irqsave(int8_t* state) | 
|  | { | 
|  | if ((*state == 0) && irq_is_enabled()) | 
|  | disable_irq(); | 
|  | else | 
|  | (*state)--; | 
|  | } | 
|  |  | 
|  | static __inline void cpu_relax(void) | 
|  | { | 
|  | // compute and use 0/0, which stalls Rocket for dozens of cycles | 
|  | long scratch; | 
|  | asm volatile ("div %0, zero, zero; move %0, %0" : "=r"(scratch)); | 
|  | } | 
|  |  | 
|  | static __inline void clflush(uintptr_t* addr) | 
|  | { | 
|  | } | 
|  |  | 
|  | /* os_coreid -> hw_coreid */ | 
|  | static __inline int get_hw_coreid(int coreid) | 
|  | { | 
|  | return coreid; | 
|  | } | 
|  |  | 
|  | static __inline int hw_core_id(void) | 
|  | { | 
|  | return mfpcr(PCR_COREID); | 
|  | } | 
|  |  | 
|  | /* hw_coreid -> os_coreid */ | 
|  | static __inline int get_os_coreid(int hw_coreid) | 
|  | { | 
|  | return hw_coreid; | 
|  | } | 
|  |  | 
|  | /* core_id() returns the OS core number, not to be confused with the | 
|  | * hardware-specific core identifier (such as the lapic id) returned by | 
|  | * hw_core_id() */ | 
|  | static __inline int core_id(void) | 
|  | { | 
|  | return get_os_coreid(hw_core_id()); | 
|  | } | 
|  |  | 
|  | static __inline int core_id_early(void) | 
|  | { | 
|  | return core_id(); | 
|  | } | 
|  |  | 
|  | static __inline void cache_flush(void) | 
|  | { | 
|  | } | 
|  |  | 
|  | static __inline void reboot(void) | 
|  | { | 
|  | extern void cputchar(int ch); | 
|  | cputchar(0); | 
|  | } | 
|  |  | 
|  | extern void cpu_halt(void); | 
|  |  | 
|  | struct preempt_data; | 
|  | static inline void cpu_halt_notif_pending(struct preempt_data *vcpd) | 
|  | { | 
|  | cpu_halt(); | 
|  | } | 
|  |  | 
|  | static inline void prefetch(void *addr) | 
|  | { | 
|  | } | 
|  |  | 
|  | static inline void prefetchw(void *addr) | 
|  | { | 
|  | } | 
|  |  | 
|  | /* Resets a stack pointer to sp, then calls f(arg) */ | 
|  | static inline void __attribute__((noreturn)) | 
|  | __reset_stack_pointer(void *arg, uintptr_t sp, void (*f)(void *)) | 
|  | { | 
|  | #error "implement me" | 
|  | } |