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