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