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