MSI-X: Minor changes
[akaros.git] / kern / arch / riscv / arch.h
1 #ifndef ROS_INC_ARCH_H
2 #define ROS_INC_ARCH_H
3
4 #include <ros/arch/arch.h>
5 #include <arch/mmu.h>
6 #include <ros/common.h>
7 #include <ros/arch/membar.h>
8 #include <arch/riscv.h>
9 #include <arch/time.h>
10
11 /* Arch Constants */
12 #define ARCH_CL_SIZE 64
13
14 void print_cpuinfo(void);
15 void show_mapping(uintptr_t start, size_t size);
16 void backtrace(void);
17
18 static __inline void breakpoint(void)
19 {
20         asm volatile ("break");
21 }
22
23 static __inline void tlbflush(void)
24 {
25         lcr3(rcr3());
26 }
27
28 static __inline void invlpg(void *addr)
29
30         tlbflush();
31 }
32
33 static __inline void icache_flush_page(void* va, void* kva)
34 {
35         asm volatile ("fence.i");
36 }
37
38 static __inline uint64_t read_tsc(void)
39 {
40         unsigned long t;
41         asm volatile ("rdtime %0" : "=r"(t));
42         return t;
43 }
44
45 /* Continuing the poor tradition of x86 opcode functions... */
46 static __inline uint64_t read_tscp(void)
47 {
48         return read_tsc();
49 }
50
51 static __inline uint64_t read_tsc_serialized(void)
52 {
53         mb();
54         return read_tsc();
55 }
56
57 static __inline uintptr_t enable_fp(void)
58 {
59         return setpcr(PCR_SR, SR_EF);
60 }
61
62 static __inline uintptr_t enable_irq(void)
63 {
64         return setpcr(PCR_SR, SR_ET);
65 }
66
67 static __inline uintptr_t disable_irq(void)
68 {
69         return clearpcr(PCR_SR, SR_ET);
70 }
71
72 static __inline void restore_irq(uintptr_t val)
73 {
74         mtpcr(PCR_SR, val);
75 }
76
77 static __inline int irq_is_enabled(void)
78 {
79         return mfpcr(PCR_SR) & SR_ET;
80 }
81
82 static __inline void enable_irqsave(int8_t* state)
83 {
84         // *state tracks the number of nested enables and disables
85         // initial value of state: 0 = first run / no favorite
86         // > 0 means more enabled calls have been made
87         // < 0 means more disabled calls have been made
88         // Mostly doing this so we can call disable_irqsave first if we want
89
90         // one side or another "gets a point" if interrupts were already the
91         // way it wanted to go.  o/w, state stays at 0.  if the state was not 0
92         // then, enabling/disabling isn't even an option.  just increment/decrement
93
94         // if enabling is winning or tied, make sure it's enabled
95         if ((*state == 0) && !irq_is_enabled())
96                 enable_irq();
97         else
98                 (*state)++;
99 }
100
101 static __inline void disable_irqsave(int8_t* state)
102 {
103         if ((*state == 0) && irq_is_enabled())
104                 disable_irq();
105         else 
106                 (*state)--;
107 }
108
109 static __inline void cpu_relax(void)
110 {
111         // compute and use 0/0, which stalls Rocket for dozens of cycles
112         long scratch;
113         asm volatile ("div %0, zero, zero; move %0, %0" : "=r"(scratch));
114 }
115
116 static __inline void clflush(uintptr_t* addr)
117 {
118 }
119
120 /* os_coreid -> hw_coreid */
121 static __inline int get_hw_coreid(int coreid)
122 {
123         return coreid;
124 }
125
126 static __inline int hw_core_id(void)
127 {
128         return mfpcr(PCR_COREID);
129 }
130
131 /* hw_coreid -> os_coreid */
132 static __inline int get_os_coreid(int hw_coreid)
133 {
134         return hw_coreid;
135 }
136
137 /* core_id() returns the OS core number, not to be confused with the
138  * hardware-specific core identifier (such as the lapic id) returned by
139  * hw_core_id() */
140 static __inline int core_id(void)
141 {
142         return get_os_coreid(hw_core_id());
143 }
144
145 static __inline int core_id_early(void)
146 {
147         return core_id();
148 }
149
150 static __inline void cache_flush(void)
151 {
152 }
153
154 static __inline void reboot(void)
155 {
156         extern void cputchar(int ch);
157         cputchar(0);
158 }
159
160 extern void cpu_halt(void);
161
162 #endif /* !ROS_INC_ARCH_H */