beaab03dcee5b5924512559304f096e72fd89ad2
[akaros.git] / kern / arch / x86 / 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 // TODO: figure out which are intel specific, and name them accordingly
9 #define IA32_APIC_BASE                          0x1b
10 /* These two are intel-only */
11 #define IA32_FEATURE_CONTROL            0x3a
12 #define IA32_MISC_ENABLE                        0x1a0
13
14 #define IA32_MTRR_DEF_TYPE                      0x2ff
15 #define IA32_MTRR_PHYSBASE0                     0x200
16 #define IA32_MTRR_PHYSMASK0                     0x201
17 #define IA32_MTRR_PHYSBASE1                     0x202
18 #define IA32_MTRR_PHYSMASK1                     0x203
19 #define IA32_MTRR_PHYSBASE2                     0x204
20 #define IA32_MTRR_PHYSMASK2                     0x205
21 #define IA32_MTRR_PHYSBASE3                     0x206
22 #define IA32_MTRR_PHYSMASK3                     0x207
23 #define IA32_MTRR_PHYSBASE4                     0x208
24 #define IA32_MTRR_PHYSMASK4                     0x209
25 #define IA32_MTRR_PHYSBASE5                     0x20a
26 #define IA32_MTRR_PHYSMASK5                     0x20b
27 #define IA32_MTRR_PHYSBASE6                     0x20c
28 #define IA32_MTRR_PHYSMASK6                     0x20d
29 #define IA32_MTRR_PHYSBASE7                     0x20e
30 #define IA32_MTRR_PHYSMASK7                     0x20f
31
32 #define MSR_APIC_ENABLE                         0x00000800
33 #define MSR_APIC_BASE_ADDRESS           0x0000000FFFFFF000
34
35 #define IA32_EFER_MSR                           0xc0000080
36 # define IA32_EFER_SYSCALL                      (1 << 0)
37 # define IA32_EFER_IA32E_EN                     (1 << 8)
38 # define IA32_EFER_IA32E_ACT            (1 << 10)
39 # define IA32_EFER_EXE_DIS_BIT          (1 << 11)
40
41 #define MSR_TSC_AUX                                     0xc0000103
42
43 #define MSR_FS_BASE                                     0xc0000100
44 #define MSR_GS_BASE                                     0xc0000101
45 #define MSR_KERN_GS_BASE                        0xc0000102
46
47 #define MSR_STAR                                        0xc0000081
48 #define MSR_LSTAR                                       0xc0000082
49 #define MSR_CSTAR                                       0xc0000083
50 #define MSR_SFMASK                                      0xc0000084
51
52 /* CPUID */
53 #define CPUID_PSE_SUPPORT                       0x00000008
54
55 /* Arch Constants */
56 #define MAX_NUM_CPUS                            255
57
58 #ifdef CONFIG_X86_64
59
60 #define X86_REG_BP                                      "rbp"
61 #define X86_REG_SP                                      "rsp"
62 #define X86_REG_IP                                      "rip"
63 #define X86_REG_AX                                      "rax"
64 #define X86_REG_BX                                      "rbx"
65 #define X86_REG_CX                                      "rcx"
66 #define X86_REG_DX                                      "rdx"
67
68 #else /* 32 bit */
69
70 #define X86_REG_BP                                      "ebp"
71 #define X86_REG_SP                                      "esp"
72 #define X86_REG_IP                                      "eip"
73 #define X86_REG_AX                                      "eax"
74 #define X86_REG_BX                                      "ebx"
75 #define X86_REG_CX                                      "ecx"
76 #define X86_REG_DX                                      "edx"
77
78 #endif /* 64bit / 32bit */
79
80 #ifndef __ASSEMBLER__
81 static inline uint8_t inb(int port) __attribute__((always_inline));
82 static inline void insb(int port, void *addr, int cnt)
83               __attribute__((always_inline));
84 static inline uint16_t inw(int port) __attribute__((always_inline));
85 static inline void insw(int port, void *addr, int cnt)
86               __attribute__((always_inline));
87 static inline uint32_t inl(int port) __attribute__((always_inline));
88 static inline void insl(int port, void *addr, int cnt)
89               __attribute__((always_inline));
90 static inline void outb(int port, uint8_t data) __attribute__((always_inline));
91 static inline void outsb(int port, const void *addr, int cnt)
92               __attribute__((always_inline));
93 static inline void outw(int port, uint16_t data) __attribute__((always_inline));
94 static inline void outsw(int port, const void *addr, int cnt)
95               __attribute__((always_inline));
96 static inline void outsl(int port, const void *addr, int cnt)
97               __attribute__((always_inline));
98 static inline void outl(int port, uint32_t data) __attribute__((always_inline));
99 static inline void lidt(void *p) __attribute__((always_inline));
100 static inline void lldt(uint16_t sel) __attribute__((always_inline));
101 static inline void ltr(uint16_t sel) __attribute__((always_inline));
102 static inline void lcr0(unsigned long val) __attribute__((always_inline));
103 static inline unsigned long rcr0(void) __attribute__((always_inline));
104 static inline unsigned long rcr2(void) __attribute__((always_inline));
105 static inline void lcr3(unsigned long val) __attribute__((always_inline));
106 static inline unsigned long rcr3(void) __attribute__((always_inline));
107 static inline void lcr4(unsigned long val) __attribute__((always_inline));
108 static inline unsigned long rcr4(void) __attribute__((always_inline));
109 static inline unsigned long read_flags(void) __attribute__((always_inline));
110 static inline void write_eflags(unsigned long eflags)
111               __attribute__((always_inline));
112 static inline unsigned long read_bp(void) __attribute__((always_inline));
113 static inline unsigned long read_pc(void) __attribute__((always_inline));
114 static inline unsigned long read_sp(void) __attribute__((always_inline));
115 static inline void cpuid(uint32_t info1, uint32_t info2, uint32_t *eaxp,
116                          uint32_t *ebxp, uint32_t *ecxp, uint32_t *edxp)
117                                                                __attribute__((always_inline));
118 static inline uint64_t read_msr(uint32_t reg) __attribute__((always_inline));
119 static inline void write_msr(uint32_t reg, uint64_t val)
120               __attribute__((always_inline));
121 static inline void write_mmreg32(uintptr_t reg, uint32_t val)
122               __attribute__((always_inline));
123 static inline uint32_t read_mmreg32(uintptr_t reg)
124               __attribute__((always_inline));
125 static inline void wbinvd(void) __attribute__((always_inline));
126 static inline void __cpu_relax(void) __attribute__((always_inline));
127
128 static inline uint8_t inb(int port)
129 {
130         uint8_t data;
131         asm volatile("inb %w1,%0" : "=a" (data) : "d" (port));
132         return data;
133 }
134
135 static inline void insb(int port, void *addr, int cnt)
136 {
137         asm volatile("cld\n\trepne\n\tinsb"
138                      : "=D" (addr), "=c" (cnt)
139                      : "d" (port), "0" (addr), "1" (cnt)
140                      : "memory", "cc");
141 }
142
143 static inline uint16_t inw(int port)
144 {
145         uint16_t data;
146         asm volatile("inw %w1,%0" : "=a" (data) : "d" (port));
147         return data;
148 }
149
150 static inline void insw(int port, void *addr, int cnt)
151 {
152         asm volatile("cld\n\trepne\n\tinsw"
153                      : "=D" (addr), "=c" (cnt)
154                      : "d" (port), "0" (addr), "1" (cnt)
155                      : "memory", "cc");
156 }
157
158 static inline uint32_t inl(int port)
159 {
160         uint32_t data;
161         asm volatile("inl %w1,%0" : "=a" (data) : "d" (port));
162         return data;
163 }
164
165 static inline void insl(int port, void *addr, int cnt)
166 {
167         asm volatile("cld\n\trepne\n\tinsl"
168                      : "=D" (addr), "=c" (cnt)
169                      : "d" (port), "0" (addr), "1" (cnt)
170                      : "memory", "cc");
171 }
172
173 static inline void outb(int port, uint8_t data)
174 {
175         asm volatile("outb %0,%w1" : : "a" (data), "d" (port));
176 }
177
178 static inline void outsb(int port, const void *addr, int cnt)
179 {
180         asm volatile("cld\n\trepne\n\toutsb"
181                      : "=S" (addr), "=c" (cnt)
182                      : "d" (port), "0" (addr), "1" (cnt)
183                      : "cc");
184 }
185
186 static inline void outw(int port, uint16_t data)
187 {
188         asm volatile("outw %0,%w1" : : "a" (data), "d" (port));
189 }
190
191 static inline void outsw(int port, const void *addr, int cnt)
192 {
193         asm volatile("cld\n\trepne\n\toutsw"
194                      : "=S" (addr), "=c" (cnt)
195                      : "d" (port), "0" (addr), "1" (cnt)
196                      : "cc");
197 }
198
199 static inline void outsl(int port, const void *addr, int cnt)
200 {
201         asm volatile("cld\n\trepne\n\toutsl"
202                      : "=S" (addr), "=c" (cnt)
203                      : "d" (port), "0" (addr), "1" (cnt)
204                      : "cc");
205 }
206
207 static inline void outl(int port, uint32_t data)
208 {
209         asm volatile("outl %0,%w1" : : "a" (data), "d" (port));
210 }
211
212 static inline void lidt(void *p)
213 {
214         asm volatile("lidt (%0)" : : "r" (p));
215 }
216
217 static inline void lldt(uint16_t sel)
218 {
219         asm volatile("lldt %0" : : "r" (sel));
220 }
221
222 static inline void ltr(uint16_t sel)
223 {
224         asm volatile("ltr %0" : : "r" (sel));
225 }
226
227 static inline void lcr0(unsigned long val)
228 {
229         asm volatile("mov %0,%%cr0" : : "r" (val));
230 }
231
232 static inline unsigned long rcr0(void)
233 {
234         unsigned long val;
235         asm volatile("mov %%cr0,%0" : "=r" (val));
236         return val;
237 }
238
239 static inline unsigned long rcr2(void)
240 {
241         unsigned long val;
242         asm volatile("mov %%cr2,%0" : "=r" (val));
243         return val;
244 }
245
246 static inline void lcr3(unsigned long val)
247 {
248         asm volatile("mov %0,%%cr3" : : "r" (val));
249 }
250
251 static inline unsigned long rcr3(void)
252 {
253         unsigned long val;
254         asm volatile("mov %%cr3,%0" : "=r" (val));
255         return val;
256 }
257
258 static inline void lcr4(unsigned long val)
259 {
260         asm volatile("mov %0,%%cr4" : : "r" (val));
261 }
262
263 static inline unsigned long rcr4(void)
264 {
265         unsigned long cr4;
266         asm volatile("mov %%cr4,%0" : "=r" (cr4));
267         return cr4;
268 }
269
270 static inline unsigned long read_flags(void)
271 {
272         unsigned long eflags;
273         asm volatile("pushf; pop %0" : "=r" (eflags));
274         return eflags;
275 }
276
277 static inline void write_eflags(unsigned long eflags)
278 {
279         asm volatile("push %0; popf" : : "r" (eflags));
280 }
281
282 static inline unsigned long read_bp(void)
283 {
284         unsigned long bp;
285         asm volatile("mov %%"X86_REG_BP",%0" : "=r" (bp));
286         return bp;
287 }
288
289 static inline unsigned long read_pc(void)
290 {
291         unsigned long ip;
292         asm volatile("call 1f; 1: pop %0" : "=r"(ip));
293         return ip;
294 }
295
296 static inline unsigned long read_sp(void)
297 {
298         unsigned long sp;
299         asm volatile("mov %%"X86_REG_SP",%0" : "=r" (sp));
300         return sp;
301 }
302
303 static inline void cpuid(uint32_t info1, uint32_t info2, uint32_t *eaxp,
304                          uint32_t *ebxp, uint32_t *ecxp, uint32_t *edxp)
305 {
306         uint32_t eax, ebx, ecx, edx;
307         /* Can select with both eax (info1) and ecx (info2) */
308         asm volatile("cpuid" 
309                 : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx)
310                 : "a" (info1), "c" (info2));
311         if (eaxp)
312                 *eaxp = eax;
313         if (ebxp)
314                 *ebxp = ebx;
315         if (ecxp)
316                 *ecxp = ecx;
317         if (edxp)
318                 *edxp = edx;
319 }
320
321 // Might need to mfence rdmsr.  supposedly wrmsr serializes, but not for x2APIC
322 static inline uint64_t read_msr(uint32_t reg)
323 {
324         uint32_t edx, eax;
325         asm volatile("rdmsr; mfence" : "=d"(edx), "=a"(eax) : "c"(reg));
326         return (uint64_t)edx << 32 | eax;
327 }
328
329 static inline void write_msr(uint32_t reg, uint64_t val)
330 {
331         asm volatile("wrmsr" : : "d"((uint32_t)(val >> 32)),
332                                  "a"((uint32_t)(val & 0xFFFFFFFF)), 
333                                  "c"(reg));
334 }
335
336 static inline void write_mmreg32(uintptr_t reg, uint32_t val)
337 {
338         *((volatile uint32_t*)reg) = val;
339 }
340
341 static inline uint32_t read_mmreg32(uintptr_t reg)
342 {
343         return *((volatile uint32_t*)reg);
344 }
345
346 static inline void wbinvd(void)
347 {
348         asm volatile("wbinvd");
349 }
350
351 /* this version of cpu_relax is needed to resolve some circular dependencies
352  * with arch/arch.h and arch/apic.h */
353 static inline void __cpu_relax(void)
354 {
355         // in case the compiler doesn't serialize for pause, the "m" will make sure
356         // no memory is reordered around this instruction.
357         asm volatile("pause" : : : "memory");
358 }
359
360 #ifndef UNUSED_ARG
361 #define UNUSED_ARG(x) (void)x
362 #endif /* This prevents compiler warnings for UNUSED_ARG */ 
363 #endif /* !__ASSEMBLER__ */
364
365 #endif /* !ROS_INC_X86_H */