Things now compile and link.
[akaros.git] / kern / arch / x86 / arch.h
1 #ifndef ROS_INC_ARCH_H
2 #define ROS_INC_ARCH_H
3
4 #include <ros/arch/arch.h>
5 #include <ros/common.h>
6 #include <arch/x86.h>
7 #include <arch/apic.h>
8
9 /* Arch Constants */
10 #define ARCH_CL_SIZE                             64
11
12 static inline void breakpoint(void) __attribute__((always_inline));
13 static inline void invlpg(void *addr) __attribute__((always_inline));  
14 static inline void tlbflush(void) __attribute__((always_inline));
15 static inline void icache_flush_page(void *va, void *kva)
16               __attribute__((always_inline));
17 static inline uint64_t read_tsc(void) __attribute__((always_inline));
18 static inline uint64_t read_tscp(void) __attribute__((always_inline));
19 static inline uint64_t read_tsc_serialized(void) __attribute__((always_inline));
20 static inline void enable_irq(void) __attribute__((always_inline));
21 static inline void disable_irq(void) __attribute__((always_inline));
22 static inline void enable_irqsave(int8_t *state) __attribute__((always_inline));
23 static inline void disable_irqsave(int8_t *state)
24               __attribute__((always_inline));
25 static inline void cpu_relax(void) __attribute__((always_inline));
26 static inline void cpu_halt(void) __attribute__((always_inline));
27 static inline void clflush(uintptr_t* addr) __attribute__((always_inline));
28 static inline int irq_is_enabled(void) __attribute__((always_inline));
29 static inline int get_hw_coreid(uint32_t coreid) __attribute__((always_inline));
30 static inline int hw_core_id(void) __attribute__((always_inline));
31 static inline int get_os_coreid(int hw_coreid) __attribute__((always_inline));
32 static inline int core_id(void) __attribute__((always_inline));
33 static inline int node_id(void) __attribute__((always_inline));
34 static inline int core_id_early(void) __attribute__((always_inline));
35 static inline void cache_flush(void) __attribute__((always_inline));
36 static inline void reboot(void)
37               __attribute__((always_inline)) __attribute__((noreturn));
38
39 /* in trap.c */
40 void send_ipi(uint32_t os_coreid, uint8_t vector);
41 /* in cpuinfo.c */
42 void print_cpuinfo(void);
43 void show_mapping(uintptr_t start, size_t size);
44
45 /* declared in smp.c */
46 extern int hw_coreid_lookup[MAX_NUM_CPUS];
47 extern int os_coreid_lookup[MAX_NUM_CPUS];
48
49 static inline void breakpoint(void)
50 {
51         asm volatile("int3");
52 }
53
54 static inline void invlpg(void *addr)
55
56         asm volatile("invlpg (%0)" : : "r" (addr) : "memory");
57 }  
58
59 static inline void tlbflush(void)
60 {
61         unsigned long cr3;
62         asm volatile("mov %%cr3,%0" : "=r" (cr3));
63         asm volatile("mov %0,%%cr3" : : "r" (cr3));
64 }
65
66 static inline void icache_flush_page(void *va, void *kva)
67 {
68         // x86 handles self-modifying code (mostly) without SW support
69 }
70
71 static inline uint64_t read_tsc(void)
72 {
73         uint32_t edx, eax;
74         asm volatile("rdtsc" : "=d"(edx), "=a"(eax));
75         return (uint64_t)edx << 32 | eax;
76 }
77
78 /* non-core-id reporting style (it is in ecx) */
79 static inline uint64_t read_tscp(void)
80 {
81         uint32_t edx, eax;
82         asm volatile("rdtscp" : "=d"(edx), "=a"(eax) : : X86_REG_CX);
83         return (uint64_t)edx << 32 | eax;
84 }
85
86 /* Check out k/a/x86/rdtsc_test.c for more info */
87 static inline uint64_t read_tsc_serialized(void)
88 {
89         asm volatile("lfence" ::: "memory");    /* mfence on amd? */
90         return read_tsc();
91 }
92
93 static inline void enable_irq(void)
94 {
95         asm volatile("sti");
96 }
97
98 static inline void disable_irq(void)
99 {
100         asm volatile("cli");
101 }
102
103 static inline void enable_irqsave(int8_t *state)
104 {
105         // *state tracks the number of nested enables and disables
106         // initial value of state: 0 = first run / no favorite
107         // > 0 means more enabled calls have been made
108         // < 0 means more disabled calls have been made
109         // Mostly doing this so we can call disable_irqsave first if we want
110
111         // one side or another "gets a point" if interrupts were already the
112         // way it wanted to go.  o/w, state stays at 0.  if the state was not 0
113         // then, enabling/disabling isn't even an option.  just increment/decrement
114
115         // if enabling is winning or tied, make sure it's enabled
116         if ((*state == 0) && !irq_is_enabled())
117                 enable_irq();
118         else
119                 (*state)++;
120 }
121
122 static inline void disable_irqsave(int8_t *state)
123 {
124         if ((*state == 0) && irq_is_enabled())
125                 disable_irq();
126         else 
127                 (*state)--;
128 }
129
130 static inline void cpu_relax(void)
131 {
132         __cpu_relax();
133 }
134
135 /* This doesn't atomically enable interrupts and then halt, like we want, so
136  * x86 needs to use a custom helper in the irq handler in trap.c. */
137 static inline void cpu_halt(void)
138 {
139         asm volatile("sti; hlt" : : : "memory");
140 }
141
142 static inline void clflush(uintptr_t* addr)
143 {
144         asm volatile("clflush %0" : : "m"(*addr));
145 }
146
147 static inline int irq_is_enabled(void)
148 {
149         return read_flags() & FL_IF;
150 }
151
152 /* os_coreid -> hw_coreid */
153 static inline int get_hw_coreid(uint32_t coreid)
154 {
155         return hw_coreid_lookup[coreid];
156 }
157
158 static inline int hw_core_id(void)
159 {
160         return lapic_get_id();
161 }
162
163 /* hw_coreid -> os_coreid */
164 static inline int get_os_coreid(int hw_coreid)
165 {
166         return os_coreid_lookup[hw_coreid];
167 }
168
169 static inline int node_id(void)
170 {
171         return 0;
172 }
173
174 #ifdef CONFIG_FAST_COREID
175 static inline int core_id(void)
176 {
177         int ret;
178         asm volatile ("rdtscp" : "=c"(ret) : : "eax", "edx");
179         return ret;
180 }
181 #else
182 /* core_id() returns the OS core number, not to be confused with the
183  * hardware-specific core identifier (such as the lapic id) returned by
184  * hw_core_id() */
185 static inline int core_id(void)
186 {
187         return get_os_coreid(hw_core_id());
188 }
189 #endif /* CONFIG_FAST_COREID */
190
191 static inline int core_id_early(void)
192 {
193         if (!core_id_ready)
194                 return 0;
195         return core_id();
196 }
197
198 static inline void cache_flush(void)
199 {
200         wbinvd();
201 }
202
203 static inline void reboot(void)
204 {
205         outb(0x92, 0x3);
206         asm volatile ("mov $0, %"X86_REG_SP"; int $0");
207         while (1);
208 }
209
210 #endif /* !ROS_INC_ARCH_H */