source: mainline/kernel/arch/ia32/include/asm.h@ add04f7

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since add04f7 was add04f7, checked in by Martin Decky <martin@…>, 16 years ago

better inline assembler readability using the new symbolic syntax

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