Added more SharC annotations
[akaros.git] / kern / arch / i386 / x86.h
1 #ifndef ROS_INC_X86_H
2 #define ROS_INC_X86_H
3
4 #include <ros/common.h>
5 #include <arch/mmu.h>
6
7 /* Model Specific Registers */
8 #define IA32_APIC_BASE                          0x1b
9 #define IA32_FEATURE_CONTROL            0x3a
10 #define IA32_MTRR_DEF_TYPE                      0x2ff
11 #define IA32_MTRR_PHYSBASE0                     0x200
12 #define IA32_MTRR_PHYSMASK0                     0x201
13 #define IA32_MTRR_PHYSBASE1                     0x202
14 #define IA32_MTRR_PHYSMASK1                     0x203
15 #define IA32_MTRR_PHYSBASE2                     0x204
16 #define IA32_MTRR_PHYSMASK2                     0x205
17 #define IA32_MTRR_PHYSBASE3                     0x206
18 #define IA32_MTRR_PHYSMASK3                     0x207
19 #define IA32_MTRR_PHYSBASE4                     0x208
20 #define IA32_MTRR_PHYSMASK4                     0x209
21 #define IA32_MTRR_PHYSBASE5                     0x20a
22 #define IA32_MTRR_PHYSMASK5                     0x20b
23 #define IA32_MTRR_PHYSBASE6                     0x20c
24 #define IA32_MTRR_PHYSMASK6                     0x20d
25 #define IA32_MTRR_PHYSBASE7                     0x20e
26 #define IA32_MTRR_PHYSMASK7                     0x20f
27
28 #define MSR_APIC_ENABLE                         0x00000800
29 #define MSR_APIC_BASE_ADDRESS           0x0000000FFFFFF000
30
31 /* CPUID */
32 #define CPUID_PSE_SUPPORT                       0x00000008
33
34 /* Arch Constants */
35 #define MAX_NUM_CPUS                            255
36
37 static __inline uint8_t inb(int port) __attribute__((always_inline));
38 static __inline void insb(int port, void *addr, int cnt) __attribute__((always_inline));
39 static __inline uint16_t inw(int port) __attribute__((always_inline));
40 static __inline void insw(int port, void *addr, int cnt) __attribute__((always_inline));
41 static __inline uint32_t inl(int port) __attribute__((always_inline));
42 static __inline void insl(int port, void *addr, int cnt) __attribute__((always_inline));
43 static __inline void outb(int port, uint8_t data) __attribute__((always_inline));
44 static __inline void outsb(int port, const void *addr, int cnt) __attribute__((always_inline));
45 static __inline void outw(int port, uint16_t data) __attribute__((always_inline));
46 static __inline void outsw(int port, const void *addr, int cnt) __attribute__((always_inline));
47 static __inline void outsl(int port, const void *addr, int cnt) __attribute__((always_inline));
48 static __inline void outl(int port, uint32_t data) __attribute__((always_inline));
49 static __inline void lidt(void *p) __attribute__((always_inline));
50 static __inline void lldt(uint16_t sel) __attribute__((always_inline));
51 static __inline void ltr(uint16_t sel) __attribute__((always_inline));
52 static __inline void lcr0(uint32_t val) __attribute__((always_inline));
53 static __inline uint32_t rcr0(void) __attribute__((always_inline));
54 static __inline uint32_t rcr2(void) __attribute__((always_inline));
55 static __inline void lcr3(uint32_t val) __attribute__((always_inline));
56 static __inline uint32_t rcr3(void) __attribute__((always_inline));
57 static __inline void lcr4(uint32_t val) __attribute__((always_inline));
58 static __inline uint32_t rcr4(void) __attribute__((always_inline));
59 static __inline uint32_t read_eflags(void) __attribute__((always_inline));
60 static __inline void write_eflags(uint32_t eflags) __attribute__((always_inline));
61 static __inline uint32_t read_ebp(void) __attribute__((always_inline));
62 static __inline uint32_t read_esp(void) __attribute__((always_inline));
63 static __inline void cpuid(uint32_t info, uint32_t *eaxp, uint32_t *ebxp, uint32_t *ecxp, uint32_t *edxp);
64 static __inline uint64_t read_msr(uint32_t reg) __attribute__((always_inline));
65 static __inline void write_msr(uint32_t reg, uint64_t val) __attribute__((always_inline));
66 static __inline uint32_t read_mmreg32(uint32_t reg) __attribute__((always_inline));
67 static __inline void write_mmreg32(uint32_t reg, uint32_t val) __attribute__((always_inline));
68 static __inline void wbinvd(void) __attribute__((always_inline));
69 static __inline void __cpu_relax(void) __attribute__((always_inline));
70
71 static __inline uint8_t
72 inb(int port)
73 {
74         uint8_t data;
75         __asm __volatile("inb %w1,%0" : "=a" (data) : "d" (port));
76         return data;
77 }
78
79 static __inline void
80 insb(int port, void *addr, int cnt)
81 {
82         __asm __volatile("cld\n\trepne\n\tinsb"                 :
83                          "=D" (addr), "=c" (cnt)                :
84                          "d" (port), "0" (addr), "1" (cnt)      :
85                          "memory", "cc");
86 }
87
88 static __inline uint16_t
89 inw(int port)
90 {
91         uint16_t data;
92         __asm __volatile("inw %w1,%0" : "=a" (data) : "d" (port));
93         return data;
94 }
95
96 static __inline void
97 insw(int port, void *addr, int cnt)
98 {
99         __asm __volatile("cld\n\trepne\n\tinsw"                 :
100                          "=D" (addr), "=c" (cnt)                :
101                          "d" (port), "0" (addr), "1" (cnt)      :
102                          "memory", "cc");
103 }
104
105 static __inline uint32_t
106 inl(int port)
107 {
108         uint32_t data;
109         __asm __volatile("inl %w1,%0" : "=a" (data) : "d" (port));
110         return data;
111 }
112
113 static __inline void
114 insl(int port, void *addr, int cnt)
115 {
116         __asm __volatile("cld\n\trepne\n\tinsl"                 :
117                          "=D" (addr), "=c" (cnt)                :
118                          "d" (port), "0" (addr), "1" (cnt)      :
119                          "memory", "cc");
120 }
121
122 static __inline void
123 outb(int port, uint8_t data)
124 {
125         __asm __volatile("outb %0,%w1" : : "a" (data), "d" (port));
126 }
127
128 static __inline void
129 outsb(int port, const void *addr, int cnt)
130 {
131         __asm __volatile("cld\n\trepne\n\toutsb"                :
132                          "=S" (addr), "=c" (cnt)                :
133                          "d" (port), "0" (addr), "1" (cnt)      :
134                          "cc");
135 }
136
137 static __inline void
138 outw(int port, uint16_t data)
139 {
140         __asm __volatile("outw %0,%w1" : : "a" (data), "d" (port));
141 }
142
143 static __inline void
144 outsw(int port, const void *addr, int cnt)
145 {
146         __asm __volatile("cld\n\trepne\n\toutsw"                :
147                          "=S" (addr), "=c" (cnt)                :
148                          "d" (port), "0" (addr), "1" (cnt)      :
149                          "cc");
150 }
151
152 static __inline void
153 outsl(int port, const void *addr, int cnt)
154 {
155         __asm __volatile("cld\n\trepne\n\toutsl"                :
156                          "=S" (addr), "=c" (cnt)                :
157                          "d" (port), "0" (addr), "1" (cnt)      :
158                          "cc");
159 }
160
161 static __inline void
162 outl(int port, uint32_t data)
163 {
164         __asm __volatile("outl %0,%w1" : : "a" (data), "d" (port));
165 }
166
167 static __inline void
168 lidt(void *p)
169 {
170         __asm __volatile("lidt (%0)" : : "r" (p));
171 }
172
173 static __inline void
174 lldt(uint16_t sel)
175 {
176         __asm __volatile("lldt %0" : : "r" (sel));
177 }
178
179 static __inline void
180 ltr(uint16_t sel)
181 {
182         __asm __volatile("ltr %0" : : "r" (sel));
183 }
184
185 static __inline void
186 lcr0(uint32_t val)
187 {
188         __asm __volatile("movl %0,%%cr0" : : "r" (val));
189 }
190
191 static __inline uint32_t
192 rcr0(void)
193 {
194         uint32_t val;
195         __asm __volatile("movl %%cr0,%0" : "=r" (val));
196         return val;
197 }
198
199 static __inline uint32_t
200 rcr2(void)
201 {
202         uint32_t val;
203         __asm __volatile("movl %%cr2,%0" : "=r" (val));
204         return val;
205 }
206
207 static __inline void
208 lcr3(uint32_t val)
209 {
210         __asm __volatile("movl %0,%%cr3" : : "r" (val));
211 }
212
213 static __inline uint32_t
214 rcr3(void)
215 {
216         uint32_t val;
217         __asm __volatile("movl %%cr3,%0" : "=r" (val));
218         return val;
219 }
220
221 static __inline void
222 lcr4(uint32_t val)
223 {
224         __asm __volatile("movl %0,%%cr4" : : "r" (val));
225 }
226
227 static __inline uint32_t
228 rcr4(void)
229 {
230         uint32_t cr4;
231         __asm __volatile("movl %%cr4,%0" : "=r" (cr4));
232         return cr4;
233 }
234
235 static __inline uint32_t
236 read_eflags(void)
237 {
238         uint32_t eflags;
239         __asm __volatile("pushfl; popl %0" : "=r" (eflags));
240         return eflags;
241 }
242
243 static __inline void
244 write_eflags(uint32_t eflags)
245 {
246         __asm __volatile("pushl %0; popfl" : : "r" (eflags));
247 }
248
249 static __inline uint32_t
250 read_ebp(void)
251 {
252         uint32_t ebp;
253         __asm __volatile("movl %%ebp,%0" : "=r" (ebp));
254         return ebp;
255 }
256
257 static __inline uint32_t
258 read_esp(void)
259 {
260         uint32_t esp;
261         __asm __volatile("movl %%esp,%0" : "=r" (esp));
262         return esp;
263 }
264
265 static __inline void
266 cpuid(uint32_t info, uint32_t *eaxp, uint32_t *ebxp, uint32_t *ecxp, uint32_t *edxp)
267 {
268         uint32_t eax, ebx, ecx, edx;
269         asm volatile("cpuid" 
270                 : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx)
271                 : "a" (info));
272         if (eaxp)
273                 *eaxp = eax;
274         if (ebxp)
275                 *ebxp = ebx;
276         if (ecxp)
277                 *ecxp = ecx;
278         if (edxp)
279                 *edxp = edx;
280 }
281
282 // Might need to mfence rdmsr.  supposedly wrmsr serializes, but not for x2APIC
283 static __inline uint64_t
284 read_msr(uint32_t reg)
285 {
286         uint32_t edx, eax;
287         asm volatile("rdmsr; mfence" : "=d"(edx), "=a"(eax) : "c"(reg));
288         return (uint64_t)edx << 32 | eax;
289 }
290
291 static __inline void
292 write_msr(uint32_t reg, uint64_t val)
293 {
294         asm volatile("wrmsr" : : "d"((uint32_t)(val >> 32)),
295                                  "a"((uint32_t)(val & 0xFFFFFFFF)), 
296                                  "c"(reg));
297 }
298
299 static __inline void
300 write_mmreg32(uint32_t reg, uint32_t val)
301 {
302         {TRUSTEDBLOCK *((volatile uint32_t*)reg) = val; }
303         //the C ends up producing better asm than this:
304         //asm volatile("movl %0, (%1)" : : "r"(val), "r"(reg));
305 }
306
307 static __inline uint32_t
308 read_mmreg32(uint32_t reg)
309 {
310         {TRUSTEDBLOCK return *((volatile uint32_t*)reg); }
311 }
312
313 static __inline void
314 wbinvd(void)
315 {
316         asm volatile("wbinvd");
317 }
318
319 /* this version of cpu_relax is needed to resolve some circular dependencies
320  * with arch/arch.h and arch/apic.h */
321 static __inline void
322 __cpu_relax(void)
323 {
324         // in case the compiler doesn't serialize for pause, the "m" will make sure
325         // no memory is reordered around this instruction.
326         asm volatile("pause" : : : "memory");
327 }
328
329 #endif /* !ROS_INC_X86_H */