Rev 4055 | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 4055 | Rev 4156 | ||
---|---|---|---|
1 | /* |
1 | /* |
2 | * Copyright (c) 2005 Jakub Jermar |
2 | * Copyright (c) 2005 Jakub Jermar |
3 | * All rights reserved. |
3 | * All rights reserved. |
4 | * |
4 | * |
5 | * Redistribution and use in source and binary forms, with or without |
5 | * Redistribution and use in source and binary forms, with or without |
6 | * modification, are permitted provided that the following conditions |
6 | * modification, are permitted provided that the following conditions |
7 | * are met: |
7 | * are met: |
8 | * |
8 | * |
9 | * - Redistributions of source code must retain the above copyright |
9 | * - Redistributions of source code must retain the above copyright |
10 | * notice, this list of conditions and the following disclaimer. |
10 | * notice, this list of conditions and the following disclaimer. |
11 | * - Redistributions in binary form must reproduce the above copyright |
11 | * - Redistributions in binary form must reproduce the above copyright |
12 | * notice, this list of conditions and the following disclaimer in the |
12 | * notice, this list of conditions and the following disclaimer in the |
13 | * documentation and/or other materials provided with the distribution. |
13 | * documentation and/or other materials provided with the distribution. |
14 | * - The name of the author may not be used to endorse or promote products |
14 | * - The name of the author may not be used to endorse or promote products |
15 | * derived from this software without specific prior written permission. |
15 | * derived from this software without specific prior written permission. |
16 | * |
16 | * |
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
19 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
19 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
20 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
20 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
21 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
21 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
22 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
22 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
23 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
23 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
24 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
24 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 | */ |
27 | */ |
28 | 28 | ||
29 | /** @addtogroup amd64 |
29 | /** @addtogroup amd64 |
30 | * @{ |
30 | * @{ |
31 | */ |
31 | */ |
32 | /** @file |
32 | /** @file |
33 | */ |
33 | */ |
34 | 34 | ||
35 | #ifndef KERN_amd64_ASM_H_ |
35 | #ifndef KERN_amd64_ASM_H_ |
36 | #define KERN_amd64_ASM_H_ |
36 | #define KERN_amd64_ASM_H_ |
37 | 37 | ||
38 | #include <config.h> |
38 | #include <config.h> |
39 | #include <arch/types.h> |
39 | #include <arch/types.h> |
40 | #include <typedefs.h> |
40 | #include <typedefs.h> |
41 | 41 | ||
42 | extern void asm_delay_loop(uint32_t t); |
42 | extern void asm_delay_loop(uint32_t t); |
43 | extern void asm_fake_loop(uint32_t t); |
43 | extern void asm_fake_loop(uint32_t t); |
44 | 44 | ||
45 | /** Return base address of current stack. |
45 | /** Return base address of current stack. |
46 | * |
46 | * |
47 | * Return the base address of the current stack. |
47 | * Return the base address of the current stack. |
48 | * The stack is assumed to be STACK_SIZE bytes long. |
48 | * The stack is assumed to be STACK_SIZE bytes long. |
49 | * The stack must start on page boundary. |
49 | * The stack must start on page boundary. |
50 | * |
50 | * |
51 | */ |
51 | */ |
52 | static inline uintptr_t get_stack_base(void) |
52 | static inline uintptr_t get_stack_base(void) |
53 | { |
53 | { |
54 | uintptr_t v; |
54 | uintptr_t v; |
55 | 55 | ||
56 | asm volatile ( |
56 | asm volatile ( |
57 | "andq %%rsp, %[v]\n" |
57 | "andq %%rsp, %[v]\n" |
58 | : [v] "=r" (v) |
58 | : [v] "=r" (v) |
59 | : "0" (~((uint64_t) STACK_SIZE-1)) |
59 | : "0" (~((uint64_t) STACK_SIZE-1)) |
60 | ); |
60 | ); |
61 | 61 | ||
62 | return v; |
62 | return v; |
63 | } |
63 | } |
64 | 64 | ||
65 | static inline void cpu_sleep(void) |
65 | static inline void cpu_sleep(void) |
66 | { |
66 | { |
67 | asm volatile ("hlt\n"); |
67 | asm volatile ("hlt\n"); |
68 | } |
68 | } |
69 | 69 | ||
70 | static inline void cpu_halt(void) |
70 | static inline void cpu_halt(void) |
71 | { |
71 | { |
72 | asm volatile ("hlt\n"); |
72 | asm volatile ( |
- | 73 | "0:\n" |
|
- | 74 | " hlt\n" |
|
- | 75 | " jmp 0b\n" |
|
- | 76 | ); |
|
73 | } |
77 | } |
74 | 78 | ||
75 | 79 | ||
76 | /** Byte from port |
80 | /** Byte from port |
77 | * |
81 | * |
78 | * Get byte from port |
82 | * Get byte from port |
79 | * |
83 | * |
80 | * @param port Port to read from |
84 | * @param port Port to read from |
81 | * @return Value read |
85 | * @return Value read |
82 | * |
86 | * |
83 | */ |
87 | */ |
84 | static inline uint8_t pio_read_8(ioport8_t *port) |
88 | static inline uint8_t pio_read_8(ioport8_t *port) |
85 | { |
89 | { |
86 | uint8_t val; |
90 | uint8_t val; |
87 | 91 | ||
88 | asm volatile ( |
92 | asm volatile ( |
89 | "inb %w[port], %b[val]\n" |
93 | "inb %w[port], %b[val]\n" |
90 | : [val] "=a" (val) |
94 | : [val] "=a" (val) |
91 | : [port] "d" (port) |
95 | : [port] "d" (port) |
92 | ); |
96 | ); |
93 | 97 | ||
94 | return val; |
98 | return val; |
95 | } |
99 | } |
96 | 100 | ||
97 | /** Word from port |
101 | /** Word from port |
98 | * |
102 | * |
99 | * Get word from port |
103 | * Get word from port |
100 | * |
104 | * |
101 | * @param port Port to read from |
105 | * @param port Port to read from |
102 | * @return Value read |
106 | * @return Value read |
103 | * |
107 | * |
104 | */ |
108 | */ |
105 | static inline uint16_t pio_read_16(ioport16_t *port) |
109 | static inline uint16_t pio_read_16(ioport16_t *port) |
106 | { |
110 | { |
107 | uint16_t val; |
111 | uint16_t val; |
108 | 112 | ||
109 | asm volatile ( |
113 | asm volatile ( |
110 | "inw %w[port], %w[val]\n" |
114 | "inw %w[port], %w[val]\n" |
111 | : [val] "=a" (val) |
115 | : [val] "=a" (val) |
112 | : [port] "d" (port) |
116 | : [port] "d" (port) |
113 | ); |
117 | ); |
114 | 118 | ||
115 | return val; |
119 | return val; |
116 | } |
120 | } |
117 | 121 | ||
118 | /** Double word from port |
122 | /** Double word from port |
119 | * |
123 | * |
120 | * Get double word from port |
124 | * Get double word from port |
121 | * |
125 | * |
122 | * @param port Port to read from |
126 | * @param port Port to read from |
123 | * @return Value read |
127 | * @return Value read |
124 | * |
128 | * |
125 | */ |
129 | */ |
126 | static inline uint32_t pio_read_32(ioport32_t *port) |
130 | static inline uint32_t pio_read_32(ioport32_t *port) |
127 | { |
131 | { |
128 | uint32_t val; |
132 | uint32_t val; |
129 | 133 | ||
130 | asm volatile ( |
134 | asm volatile ( |
131 | "inl %w[port], %[val]\n" |
135 | "inl %w[port], %[val]\n" |
132 | : [val] "=a" (val) |
136 | : [val] "=a" (val) |
133 | : [port] "d" (port) |
137 | : [port] "d" (port) |
134 | ); |
138 | ); |
135 | 139 | ||
136 | return val; |
140 | return val; |
137 | } |
141 | } |
138 | 142 | ||
139 | /** Byte to port |
143 | /** Byte to port |
140 | * |
144 | * |
141 | * Output byte to port |
145 | * Output byte to port |
142 | * |
146 | * |
143 | * @param port Port to write to |
147 | * @param port Port to write to |
144 | * @param val Value to write |
148 | * @param val Value to write |
145 | * |
149 | * |
146 | */ |
150 | */ |
147 | static inline void pio_write_8(ioport8_t *port, uint8_t val) |
151 | static inline void pio_write_8(ioport8_t *port, uint8_t val) |
148 | { |
152 | { |
149 | asm volatile ( |
153 | asm volatile ( |
150 | "outb %b[val], %w[port]\n" |
154 | "outb %b[val], %w[port]\n" |
151 | :: [val] "a" (val), [port] "d" (port) |
155 | :: [val] "a" (val), [port] "d" (port) |
152 | ); |
156 | ); |
153 | } |
157 | } |
154 | 158 | ||
155 | /** Word to port |
159 | /** Word to port |
156 | * |
160 | * |
157 | * Output word to port |
161 | * Output word to port |
158 | * |
162 | * |
159 | * @param port Port to write to |
163 | * @param port Port to write to |
160 | * @param val Value to write |
164 | * @param val Value to write |
161 | * |
165 | * |
162 | */ |
166 | */ |
163 | static inline void pio_write_16(ioport16_t *port, uint16_t val) |
167 | static inline void pio_write_16(ioport16_t *port, uint16_t val) |
164 | { |
168 | { |
165 | asm volatile ( |
169 | asm volatile ( |
166 | "outw %w[val], %w[port]\n" |
170 | "outw %w[val], %w[port]\n" |
167 | :: [val] "a" (val), [port] "d" (port) |
171 | :: [val] "a" (val), [port] "d" (port) |
168 | ); |
172 | ); |
169 | } |
173 | } |
170 | 174 | ||
171 | /** Double word to port |
175 | /** Double word to port |
172 | * |
176 | * |
173 | * Output double word to port |
177 | * Output double word to port |
174 | * |
178 | * |
175 | * @param port Port to write to |
179 | * @param port Port to write to |
176 | * @param val Value to write |
180 | * @param val Value to write |
177 | * |
181 | * |
178 | */ |
182 | */ |
179 | static inline void pio_write_32(ioport32_t *port, uint32_t val) |
183 | static inline void pio_write_32(ioport32_t *port, uint32_t val) |
180 | { |
184 | { |
181 | asm volatile ( |
185 | asm volatile ( |
182 | "outl %[val], %w[port]\n" |
186 | "outl %[val], %w[port]\n" |
183 | :: [val] "a" (val), [port] "d" (port) |
187 | :: [val] "a" (val), [port] "d" (port) |
184 | ); |
188 | ); |
185 | } |
189 | } |
186 | 190 | ||
187 | /** Swap Hidden part of GS register with visible one */ |
191 | /** Swap Hidden part of GS register with visible one */ |
188 | static inline void swapgs(void) |
192 | static inline void swapgs(void) |
189 | { |
193 | { |
190 | asm volatile("swapgs"); |
194 | asm volatile("swapgs"); |
191 | } |
195 | } |
192 | 196 | ||
193 | /** Enable interrupts. |
197 | /** Enable interrupts. |
194 | * |
198 | * |
195 | * Enable interrupts and return previous |
199 | * Enable interrupts and return previous |
196 | * value of EFLAGS. |
200 | * value of EFLAGS. |
197 | * |
201 | * |
198 | * @return Old interrupt priority level. |
202 | * @return Old interrupt priority level. |
199 | * |
203 | * |
200 | */ |
204 | */ |
201 | static inline ipl_t interrupts_enable(void) { |
205 | static inline ipl_t interrupts_enable(void) { |
202 | ipl_t v; |
206 | ipl_t v; |
203 | 207 | ||
204 | asm volatile ( |
208 | asm volatile ( |
205 | "pushfq\n" |
209 | "pushfq\n" |
206 | "popq %[v]\n" |
210 | "popq %[v]\n" |
207 | "sti\n" |
211 | "sti\n" |
208 | : [v] "=r" (v) |
212 | : [v] "=r" (v) |
209 | ); |
213 | ); |
210 | 214 | ||
211 | return v; |
215 | return v; |
212 | } |
216 | } |
213 | 217 | ||
214 | /** Disable interrupts. |
218 | /** Disable interrupts. |
215 | * |
219 | * |
216 | * Disable interrupts and return previous |
220 | * Disable interrupts and return previous |
217 | * value of EFLAGS. |
221 | * value of EFLAGS. |
218 | * |
222 | * |
219 | * @return Old interrupt priority level. |
223 | * @return Old interrupt priority level. |
220 | * |
224 | * |
221 | */ |
225 | */ |
222 | static inline ipl_t interrupts_disable(void) { |
226 | static inline ipl_t interrupts_disable(void) { |
223 | ipl_t v; |
227 | ipl_t v; |
224 | 228 | ||
225 | asm volatile ( |
229 | asm volatile ( |
226 | "pushfq\n" |
230 | "pushfq\n" |
227 | "popq %[v]\n" |
231 | "popq %[v]\n" |
228 | "cli\n" |
232 | "cli\n" |
229 | : [v] "=r" (v) |
233 | : [v] "=r" (v) |
230 | ); |
234 | ); |
231 | 235 | ||
232 | return v; |
236 | return v; |
233 | } |
237 | } |
234 | 238 | ||
235 | /** Restore interrupt priority level. |
239 | /** Restore interrupt priority level. |
236 | * |
240 | * |
237 | * Restore EFLAGS. |
241 | * Restore EFLAGS. |
238 | * |
242 | * |
239 | * @param ipl Saved interrupt priority level. |
243 | * @param ipl Saved interrupt priority level. |
240 | * |
244 | * |
241 | */ |
245 | */ |
242 | static inline void interrupts_restore(ipl_t ipl) { |
246 | static inline void interrupts_restore(ipl_t ipl) { |
243 | asm volatile ( |
247 | asm volatile ( |
244 | "pushq %[ipl]\n" |
248 | "pushq %[ipl]\n" |
245 | "popfq\n" |
249 | "popfq\n" |
246 | :: [ipl] "r" (ipl) |
250 | :: [ipl] "r" (ipl) |
247 | ); |
251 | ); |
248 | } |
252 | } |
249 | 253 | ||
250 | /** Return interrupt priority level. |
254 | /** Return interrupt priority level. |
251 | * |
255 | * |
252 | * Return EFLAFS. |
256 | * Return EFLAFS. |
253 | * |
257 | * |
254 | * @return Current interrupt priority level. |
258 | * @return Current interrupt priority level. |
255 | * |
259 | * |
256 | */ |
260 | */ |
257 | static inline ipl_t interrupts_read(void) { |
261 | static inline ipl_t interrupts_read(void) { |
258 | ipl_t v; |
262 | ipl_t v; |
259 | 263 | ||
260 | asm volatile ( |
264 | asm volatile ( |
261 | "pushfq\n" |
265 | "pushfq\n" |
262 | "popq %[v]\n" |
266 | "popq %[v]\n" |
263 | : [v] "=r" (v) |
267 | : [v] "=r" (v) |
264 | ); |
268 | ); |
265 | 269 | ||
266 | return v; |
270 | return v; |
267 | } |
271 | } |
268 | 272 | ||
269 | /** Write to MSR */ |
273 | /** Write to MSR */ |
270 | static inline void write_msr(uint32_t msr, uint64_t value) |
274 | static inline void write_msr(uint32_t msr, uint64_t value) |
271 | { |
275 | { |
272 | asm volatile ( |
276 | asm volatile ( |
273 | "wrmsr\n" |
277 | "wrmsr\n" |
274 | :: "c" (msr), |
278 | :: "c" (msr), |
275 | "a" ((uint32_t) (value)), |
279 | "a" ((uint32_t) (value)), |
276 | "d" ((uint32_t) (value >> 32)) |
280 | "d" ((uint32_t) (value >> 32)) |
277 | ); |
281 | ); |
278 | } |
282 | } |
279 | 283 | ||
280 | static inline unative_t read_msr(uint32_t msr) |
284 | static inline unative_t read_msr(uint32_t msr) |
281 | { |
285 | { |
282 | uint32_t ax, dx; |
286 | uint32_t ax, dx; |
283 | 287 | ||
284 | asm volatile ( |
288 | asm volatile ( |
285 | "rdmsr\n" |
289 | "rdmsr\n" |
286 | : "=a" (ax), "=d" (dx) |
290 | : "=a" (ax), "=d" (dx) |
287 | : "c" (msr) |
291 | : "c" (msr) |
288 | ); |
292 | ); |
289 | 293 | ||
290 | return ((uint64_t) dx << 32) | ax; |
294 | return ((uint64_t) dx << 32) | ax; |
291 | } |
295 | } |
292 | 296 | ||
293 | 297 | ||
294 | /** Enable local APIC |
298 | /** Enable local APIC |
295 | * |
299 | * |
296 | * Enable local APIC in MSR. |
300 | * Enable local APIC in MSR. |
297 | * |
301 | * |
298 | */ |
302 | */ |
299 | static inline void enable_l_apic_in_msr() |
303 | static inline void enable_l_apic_in_msr() |
300 | { |
304 | { |
301 | asm volatile ( |
305 | asm volatile ( |
302 | "movl $0x1b, %%ecx\n" |
306 | "movl $0x1b, %%ecx\n" |
303 | "rdmsr\n" |
307 | "rdmsr\n" |
304 | "orl $(1 << 11),%%eax\n" |
308 | "orl $(1 << 11),%%eax\n" |
305 | "orl $(0xfee00000),%%eax\n" |
309 | "orl $(0xfee00000),%%eax\n" |
306 | "wrmsr\n" |
310 | "wrmsr\n" |
307 | ::: "%eax","%ecx","%edx" |
311 | ::: "%eax","%ecx","%edx" |
308 | ); |
312 | ); |
309 | } |
313 | } |
310 | 314 | ||
311 | static inline uintptr_t * get_ip() |
315 | static inline uintptr_t * get_ip() |
312 | { |
316 | { |
313 | uintptr_t *ip; |
317 | uintptr_t *ip; |
314 | 318 | ||
315 | asm volatile ( |
319 | asm volatile ( |
316 | "mov %%rip, %[ip]" |
320 | "mov %%rip, %[ip]" |
317 | : [ip] "=r" (ip) |
321 | : [ip] "=r" (ip) |
318 | ); |
322 | ); |
319 | 323 | ||
320 | return ip; |
324 | return ip; |
321 | } |
325 | } |
322 | 326 | ||
323 | /** Invalidate TLB Entry. |
327 | /** Invalidate TLB Entry. |
324 | * |
328 | * |
325 | * @param addr Address on a page whose TLB entry is to be invalidated. |
329 | * @param addr Address on a page whose TLB entry is to be invalidated. |
326 | * |
330 | * |
327 | */ |
331 | */ |
328 | static inline void invlpg(uintptr_t addr) |
332 | static inline void invlpg(uintptr_t addr) |
329 | { |
333 | { |
330 | asm volatile ( |
334 | asm volatile ( |
331 | "invlpg %[addr]\n" |
335 | "invlpg %[addr]\n" |
332 | :: [addr] "m" (*((unative_t *) addr)) |
336 | :: [addr] "m" (*((unative_t *) addr)) |
333 | ); |
337 | ); |
334 | } |
338 | } |
335 | 339 | ||
336 | /** Load GDTR register from memory. |
340 | /** Load GDTR register from memory. |
337 | * |
341 | * |
338 | * @param gdtr_reg Address of memory from where to load GDTR. |
342 | * @param gdtr_reg Address of memory from where to load GDTR. |
339 | * |
343 | * |
340 | */ |
344 | */ |
341 | static inline void gdtr_load(struct ptr_16_64 *gdtr_reg) |
345 | static inline void gdtr_load(ptr_16_64_t *gdtr_reg) |
342 | { |
346 | { |
343 | asm volatile ( |
347 | asm volatile ( |
344 | "lgdtq %[gdtr_reg]\n" |
348 | "lgdtq %[gdtr_reg]\n" |
345 | :: [gdtr_reg] "m" (*gdtr_reg) |
349 | :: [gdtr_reg] "m" (*gdtr_reg) |
346 | ); |
350 | ); |
347 | } |
351 | } |
348 | 352 | ||
349 | /** Store GDTR register to memory. |
353 | /** Store GDTR register to memory. |
350 | * |
354 | * |
351 | * @param gdtr_reg Address of memory to where to load GDTR. |
355 | * @param gdtr_reg Address of memory to where to load GDTR. |
352 | * |
356 | * |
353 | */ |
357 | */ |
354 | static inline void gdtr_store(struct ptr_16_64 *gdtr_reg) |
358 | static inline void gdtr_store(ptr_16_64_t *gdtr_reg) |
355 | { |
359 | { |
356 | asm volatile ( |
360 | asm volatile ( |
357 | "sgdtq %[gdtr_reg]\n" |
361 | "sgdtq %[gdtr_reg]\n" |
358 | :: [gdtr_reg] "m" (*gdtr_reg) |
362 | :: [gdtr_reg] "m" (*gdtr_reg) |
359 | ); |
363 | ); |
360 | } |
364 | } |
361 | 365 | ||
362 | /** Load IDTR register from memory. |
366 | /** Load IDTR register from memory. |
363 | * |
367 | * |
364 | * @param idtr_reg Address of memory from where to load IDTR. |
368 | * @param idtr_reg Address of memory from where to load IDTR. |
365 | * |
369 | * |
366 | */ |
370 | */ |
367 | static inline void idtr_load(struct ptr_16_64 *idtr_reg) |
371 | static inline void idtr_load(ptr_16_64_t *idtr_reg) |
368 | { |
372 | { |
369 | asm volatile ( |
373 | asm volatile ( |
370 | "lidtq %[idtr_reg]\n" |
374 | "lidtq %[idtr_reg]\n" |
371 | :: [idtr_reg] "m" (*idtr_reg)); |
375 | :: [idtr_reg] "m" (*idtr_reg)); |
372 | } |
376 | } |
373 | 377 | ||
374 | /** Load TR from descriptor table. |
378 | /** Load TR from descriptor table. |
375 | * |
379 | * |
376 | * @param sel Selector specifying descriptor of TSS segment. |
380 | * @param sel Selector specifying descriptor of TSS segment. |
377 | * |
381 | * |
378 | */ |
382 | */ |
379 | static inline void tr_load(uint16_t sel) |
383 | static inline void tr_load(uint16_t sel) |
380 | { |
384 | { |
381 | asm volatile ( |
385 | asm volatile ( |
382 | "ltr %[sel]" |
386 | "ltr %[sel]" |
383 | :: [sel] "r" (sel) |
387 | :: [sel] "r" (sel) |
384 | ); |
388 | ); |
385 | } |
389 | } |
386 | 390 | ||
387 | #define GEN_READ_REG(reg) static inline unative_t read_ ##reg (void) \ |
391 | #define GEN_READ_REG(reg) static inline unative_t read_ ##reg (void) \ |
388 | { \ |
392 | { \ |
389 | unative_t res; \ |
393 | unative_t res; \ |
390 | asm volatile ( \ |
394 | asm volatile ( \ |
391 | "movq %%" #reg ", %[res]" \ |
395 | "movq %%" #reg ", %[res]" \ |
392 | : [res] "=r" (res) \ |
396 | : [res] "=r" (res) \ |
393 | ); \ |
397 | ); \ |
394 | return res; \ |
398 | return res; \ |
395 | } |
399 | } |
396 | 400 | ||
397 | #define GEN_WRITE_REG(reg) static inline void write_ ##reg (unative_t regn) \ |
401 | #define GEN_WRITE_REG(reg) static inline void write_ ##reg (unative_t regn) \ |
398 | { \ |
402 | { \ |
399 | asm volatile ( \ |
403 | asm volatile ( \ |
400 | "movq %[regn], %%" #reg \ |
404 | "movq %[regn], %%" #reg \ |
401 | :: [regn] "r" (regn) \ |
405 | :: [regn] "r" (regn) \ |
402 | ); \ |
406 | ); \ |
403 | } |
407 | } |
404 | 408 | ||
405 | GEN_READ_REG(cr0) |
409 | GEN_READ_REG(cr0) |
406 | GEN_READ_REG(cr2) |
410 | GEN_READ_REG(cr2) |
407 | GEN_READ_REG(cr3) |
411 | GEN_READ_REG(cr3) |
408 | GEN_WRITE_REG(cr3) |
412 | GEN_WRITE_REG(cr3) |
409 | 413 | ||
410 | GEN_READ_REG(dr0) |
414 | GEN_READ_REG(dr0) |
411 | GEN_READ_REG(dr1) |
415 | GEN_READ_REG(dr1) |
412 | GEN_READ_REG(dr2) |
416 | GEN_READ_REG(dr2) |
413 | GEN_READ_REG(dr3) |
417 | GEN_READ_REG(dr3) |
414 | GEN_READ_REG(dr6) |
418 | GEN_READ_REG(dr6) |
415 | GEN_READ_REG(dr7) |
419 | GEN_READ_REG(dr7) |
416 | 420 | ||
417 | GEN_WRITE_REG(dr0) |
421 | GEN_WRITE_REG(dr0) |
418 | GEN_WRITE_REG(dr1) |
422 | GEN_WRITE_REG(dr1) |
419 | GEN_WRITE_REG(dr2) |
423 | GEN_WRITE_REG(dr2) |
420 | GEN_WRITE_REG(dr3) |
424 | GEN_WRITE_REG(dr3) |
421 | GEN_WRITE_REG(dr6) |
425 | GEN_WRITE_REG(dr6) |
422 | GEN_WRITE_REG(dr7) |
426 | GEN_WRITE_REG(dr7) |
423 | 427 | ||
424 | extern size_t interrupt_handler_size; |
428 | extern size_t interrupt_handler_size; |
425 | extern void interrupt_handlers(void); |
429 | extern void interrupt_handlers(void); |
426 | 430 | ||
427 | #endif |
431 | #endif |
428 | 432 | ||
429 | /** @} |
433 | /** @} |
430 | */ |
434 | */ |
431 | 435 |