LAPIC memory mapping
[akaros.git] / inc / x86.h
1 #ifndef JOS_INC_X86_H
2 #define JOS_INC_X86_H
3
4 #include <inc/types.h>
5
6 /* Model Specific Registers */
7 #define IA32_APIC_BASE                          0x1b
8 #define IA32_MTRR_DEF_TYPE                      0x2ff
9
10 #define MSR_APIC_ENABLE                         0x00000800
11 #define MSR_APIC_BASE_ADDRESS           0x0000000FFFFFF000
12
13 /* CPUID */
14 #define CPUID_PSE_SUPPORT                       0x00000008
15
16 static __inline void breakpoint(void) __attribute__((always_inline));
17 static __inline uint8_t inb(int port) __attribute__((always_inline));
18 static __inline void insb(int port, void *addr, int cnt) __attribute__((always_inline));
19 static __inline uint16_t inw(int port) __attribute__((always_inline));
20 static __inline void insw(int port, void *addr, int cnt) __attribute__((always_inline));
21 static __inline uint32_t inl(int port) __attribute__((always_inline));
22 static __inline void insl(int port, void *addr, int cnt) __attribute__((always_inline));
23 static __inline void outb(int port, uint8_t data) __attribute__((always_inline));
24 static __inline void outsb(int port, const void *addr, int cnt) __attribute__((always_inline));
25 static __inline void outw(int port, uint16_t data) __attribute__((always_inline));
26 static __inline void outsw(int port, const void *addr, int cnt) __attribute__((always_inline));
27 static __inline void outsl(int port, const void *addr, int cnt) __attribute__((always_inline));
28 static __inline void outl(int port, uint32_t data) __attribute__((always_inline));
29 static __inline void invlpg(void *addr) __attribute__((always_inline));
30 static __inline void lidt(void *p) __attribute__((always_inline));
31 static __inline void lldt(uint16_t sel) __attribute__((always_inline));
32 static __inline void ltr(uint16_t sel) __attribute__((always_inline));
33 static __inline void lcr0(uint32_t val) __attribute__((always_inline));
34 static __inline uint32_t rcr0(void) __attribute__((always_inline));
35 static __inline uint32_t rcr2(void) __attribute__((always_inline));
36 static __inline void lcr3(uint32_t val) __attribute__((always_inline));
37 static __inline uint32_t rcr3(void) __attribute__((always_inline));
38 static __inline void lcr4(uint32_t val) __attribute__((always_inline));
39 static __inline uint32_t rcr4(void) __attribute__((always_inline));
40 static __inline void tlbflush(void) __attribute__((always_inline));
41 static __inline uint32_t read_eflags(void) __attribute__((always_inline));
42 static __inline void write_eflags(uint32_t eflags) __attribute__((always_inline));
43 static __inline uint32_t read_ebp(void) __attribute__((always_inline));
44 static __inline uint32_t read_esp(void) __attribute__((always_inline));
45 static __inline void cpuid(uint32_t info, uint32_t *eaxp, uint32_t *ebxp, uint32_t *ecxp, uint32_t *edxp);
46 static __inline uint64_t read_tsc(void) __attribute__((always_inline));
47 static __inline uint64_t read_msr(uint32_t reg) __attribute__((always_inline));
48 static __inline void write_msr(uint32_t reg, uint64_t val) __attribute__((always_inline));
49
50 static __inline void
51 breakpoint(void)
52 {
53         __asm __volatile("int3");
54 }
55
56 static __inline uint8_t
57 inb(int port)
58 {
59         uint8_t data;
60         __asm __volatile("inb %w1,%0" : "=a" (data) : "d" (port));
61         return data;
62 }
63
64 static __inline void
65 insb(int port, void *addr, int cnt)
66 {
67         __asm __volatile("cld\n\trepne\n\tinsb"                 :
68                          "=D" (addr), "=c" (cnt)                :
69                          "d" (port), "0" (addr), "1" (cnt)      :
70                          "memory", "cc");
71 }
72
73 static __inline uint16_t
74 inw(int port)
75 {
76         uint16_t data;
77         __asm __volatile("inw %w1,%0" : "=a" (data) : "d" (port));
78         return data;
79 }
80
81 static __inline void
82 insw(int port, void *addr, int cnt)
83 {
84         __asm __volatile("cld\n\trepne\n\tinsw"                 :
85                          "=D" (addr), "=c" (cnt)                :
86                          "d" (port), "0" (addr), "1" (cnt)      :
87                          "memory", "cc");
88 }
89
90 static __inline uint32_t
91 inl(int port)
92 {
93         uint32_t data;
94         __asm __volatile("inl %w1,%0" : "=a" (data) : "d" (port));
95         return data;
96 }
97
98 static __inline void
99 insl(int port, void *addr, int cnt)
100 {
101         __asm __volatile("cld\n\trepne\n\tinsl"                 :
102                          "=D" (addr), "=c" (cnt)                :
103                          "d" (port), "0" (addr), "1" (cnt)      :
104                          "memory", "cc");
105 }
106
107 static __inline void
108 outb(int port, uint8_t data)
109 {
110         __asm __volatile("outb %0,%w1" : : "a" (data), "d" (port));
111 }
112
113 static __inline void
114 outsb(int port, const void *addr, int cnt)
115 {
116         __asm __volatile("cld\n\trepne\n\toutsb"                :
117                          "=S" (addr), "=c" (cnt)                :
118                          "d" (port), "0" (addr), "1" (cnt)      :
119                          "cc");
120 }
121
122 static __inline void
123 outw(int port, uint16_t data)
124 {
125         __asm __volatile("outw %0,%w1" : : "a" (data), "d" (port));
126 }
127
128 static __inline void
129 outsw(int port, const void *addr, int cnt)
130 {
131         __asm __volatile("cld\n\trepne\n\toutsw"                :
132                          "=S" (addr), "=c" (cnt)                :
133                          "d" (port), "0" (addr), "1" (cnt)      :
134                          "cc");
135 }
136
137 static __inline void
138 outsl(int port, const void *addr, int cnt)
139 {
140         __asm __volatile("cld\n\trepne\n\toutsl"                :
141                          "=S" (addr), "=c" (cnt)                :
142                          "d" (port), "0" (addr), "1" (cnt)      :
143                          "cc");
144 }
145
146 static __inline void
147 outl(int port, uint32_t data)
148 {
149         __asm __volatile("outl %0,%w1" : : "a" (data), "d" (port));
150 }
151
152 static __inline void 
153 invlpg(void *addr)
154
155         __asm __volatile("invlpg (%0)" : : "r" (addr) : "memory");
156 }  
157
158 static __inline void
159 lidt(void *p)
160 {
161         __asm __volatile("lidt (%0)" : : "r" (p));
162 }
163
164 static __inline void
165 lldt(uint16_t sel)
166 {
167         __asm __volatile("lldt %0" : : "r" (sel));
168 }
169
170 static __inline void
171 ltr(uint16_t sel)
172 {
173         __asm __volatile("ltr %0" : : "r" (sel));
174 }
175
176 static __inline void
177 lcr0(uint32_t val)
178 {
179         __asm __volatile("movl %0,%%cr0" : : "r" (val));
180 }
181
182 static __inline uint32_t
183 rcr0(void)
184 {
185         uint32_t val;
186         __asm __volatile("movl %%cr0,%0" : "=r" (val));
187         return val;
188 }
189
190 static __inline uint32_t
191 rcr2(void)
192 {
193         uint32_t val;
194         __asm __volatile("movl %%cr2,%0" : "=r" (val));
195         return val;
196 }
197
198 static __inline void
199 lcr3(uint32_t val)
200 {
201         __asm __volatile("movl %0,%%cr3" : : "r" (val));
202 }
203
204 static __inline uint32_t
205 rcr3(void)
206 {
207         uint32_t val;
208         __asm __volatile("movl %%cr3,%0" : "=r" (val));
209         return val;
210 }
211
212 static __inline void
213 lcr4(uint32_t val)
214 {
215         __asm __volatile("movl %0,%%cr4" : : "r" (val));
216 }
217
218 static __inline uint32_t
219 rcr4(void)
220 {
221         uint32_t cr4;
222         __asm __volatile("movl %%cr4,%0" : "=r" (cr4));
223         return cr4;
224 }
225
226 static __inline void
227 tlbflush(void)
228 {
229         uint32_t cr3;
230         __asm __volatile("movl %%cr3,%0" : "=r" (cr3));
231         __asm __volatile("movl %0,%%cr3" : : "r" (cr3));
232 }
233
234 static __inline uint32_t
235 read_eflags(void)
236 {
237         uint32_t eflags;
238         __asm __volatile("pushfl; popl %0" : "=r" (eflags));
239         return eflags;
240 }
241
242 static __inline void
243 write_eflags(uint32_t eflags)
244 {
245         __asm __volatile("pushl %0; popfl" : : "r" (eflags));
246 }
247
248 static __inline uint32_t
249 read_ebp(void)
250 {
251         uint32_t ebp;
252         __asm __volatile("movl %%ebp,%0" : "=r" (ebp));
253         return ebp;
254 }
255
256 static __inline uint32_t
257 read_esp(void)
258 {
259         uint32_t esp;
260         __asm __volatile("movl %%esp,%0" : "=r" (esp));
261         return esp;
262 }
263
264 static __inline void
265 cpuid(uint32_t info, uint32_t *eaxp, uint32_t *ebxp, uint32_t *ecxp, uint32_t *edxp)
266 {
267         uint32_t eax, ebx, ecx, edx;
268         asm volatile("cpuid" 
269                 : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx)
270                 : "a" (info));
271         if (eaxp)
272                 *eaxp = eax;
273         if (ebxp)
274                 *ebxp = ebx;
275         if (ecxp)
276                 *ecxp = ecx;
277         if (edxp)
278                 *edxp = edx;
279 }
280
281 static __inline uint64_t
282 read_tsc(void)
283 {
284         uint64_t tsc;
285         __asm __volatile("rdtsc" : "=A" (tsc));
286         return tsc;
287 }
288
289 // Might need to mfence rdmsr.  supposedly wrmsr serializes, but not for x2APIC
290 static __inline uint64_t 
291 read_msr(uint32_t reg)
292 {
293         uint32_t edx, eax;
294         asm volatile("rdmsr" : "=d"(edx), "=a"(eax) : "c"(reg));
295         return (uint64_t)edx << 32 | eax;
296 }
297
298 static __inline void 
299 write_msr(uint32_t reg, uint64_t val)
300 {
301         asm volatile("wrmsr" : : "d"((uint32_t)(val >> 32)),
302                                  "a"((uint32_t)(val & 0xFFFFFFFF)), 
303                                  "c"(reg));
304 }
305 #endif /* !JOS_INC_X86_H */