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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since b808660 was b808660, checked in by Jakub Jermar <jakub@…>, 15 years ago

Do not align ia32 int handlers on any pre-defined power-of-two boundary but
rather define each one as a separate procedure with its own global label. The
label is used to populate the IDT and it also helps to maintain consistency
between C and assembly.

The old way was very error-prone because one did not get a warning when a
handler exceeded the size limit given by the alignment, which usually resulted
in very weird crashes.

In principle, the old way was also rather wasteful as the handler had to be
aligned on a power-of-two address. With the int handler size around 160 bytes,
the bytes 160 - 255 in each handler were simply wasted. In practice, however,
the image.iso size did not change (I'd expect it to drop by around 8K).

The old way did not detect a mistmatch between the C code idea of how many IDT
entries there are and the assembly language code idea of the same thing. It was
possible to initialize an IDT entry to point to some garbage and nobody would
notice until the int occurred.

The new method was a bit tiresome to write as there was a lot of copy'n'paste.
But since it was a one-time effort, I lumped it. If you know of a way to write a
for-loop in C preprocessor or use GAS assmebler macros in a sensible way, I will
gladly use your improvement.

  • Property mode set to 100644
File size: 9.3 KB
RevLine 
[f761f1eb]1/*
[df4ed85]2 * Copyright (c) 2001-2004 Jakub Jermar
3 * Copyright (c) 2005 Sergey Bondari
[f761f1eb]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
[add04f7]30/** @addtogroup ia32
[b45c443]31 * @{
32 */
33/** @file
34 */
35
[06e1e95]36#ifndef KERN_ia32_ASM_H_
37#define KERN_ia32_ASM_H_
[f761f1eb]38
[897ad60]39#include <arch/pm.h>
[2b4a9f26]40#include <arch/cpu.h>
[c22e964]41#include <typedefs.h>
[361635c]42#include <config.h>
[7a0359b]43#include <trace.h>
[f761f1eb]44
[7f1c620]45extern uint32_t interrupt_handler_size;
[f761f1eb]46
[18e0a6c]47/** Halt CPU
48 *
[3a1c048]49 * Halt the current CPU.
[add04f7]50 *
[18e0a6c]51 */
[7a0359b]52NO_TRACE static inline __attribute__((noreturn)) void cpu_halt(void)
[e7b7be3f]53{
[82474ef]54 while (true) {
55 asm volatile (
56 "hlt\n"
57 );
58 }
[60133d0]59}
[e7b7be3f]60
[7a0359b]61NO_TRACE static inline void cpu_sleep(void)
[e7b7be3f]62{
[7a0359b]63 asm volatile (
64 "hlt\n"
65 );
[60133d0]66}
[f761f1eb]67
[7a0359b]68#define GEN_READ_REG(reg) NO_TRACE static inline unative_t read_ ##reg (void) \
[add04f7]69 { \
70 unative_t res; \
71 asm volatile ( \
72 "movl %%" #reg ", %[res]" \
73 : [res] "=r" (res) \
74 ); \
75 return res; \
76 }
[0f4e706]77
[7a0359b]78#define GEN_WRITE_REG(reg) NO_TRACE static inline void write_ ##reg (unative_t regn) \
[add04f7]79 { \
80 asm volatile ( \
81 "movl %[regn], %%" #reg \
82 :: [regn] "r" (regn) \
83 ); \
84 }
[18e0a6c]85
[60133d0]86GEN_READ_REG(cr0)
87GEN_READ_REG(cr2)
88GEN_READ_REG(cr3)
89GEN_WRITE_REG(cr3)
90
91GEN_READ_REG(dr0)
92GEN_READ_REG(dr1)
93GEN_READ_REG(dr2)
94GEN_READ_REG(dr3)
95GEN_READ_REG(dr6)
96GEN_READ_REG(dr7)
97
98GEN_WRITE_REG(dr0)
99GEN_WRITE_REG(dr1)
100GEN_WRITE_REG(dr2)
101GEN_WRITE_REG(dr3)
102GEN_WRITE_REG(dr6)
103GEN_WRITE_REG(dr7)
[18e0a6c]104
[a5556b4]105/** Byte to port
106 *
107 * Output byte to port
108 *
109 * @param port Port to write to
110 * @param val Value to write
[add04f7]111 *
[a5556b4]112 */
[7a0359b]113NO_TRACE static inline void pio_write_8(ioport8_t *port, uint8_t val)
[e7b7be3f]114{
[add04f7]115 asm volatile (
116 "outb %b[val], %w[port]\n"
[7a0359b]117 :: [val] "a" (val),
118 [port] "d" (port)
[add04f7]119 );
[e7b7be3f]120}
[a5556b4]121
[714675b]122/** Word to port
123 *
124 * Output word to port
125 *
126 * @param port Port to write to
127 * @param val Value to write
[add04f7]128 *
[714675b]129 */
[7a0359b]130NO_TRACE static inline void pio_write_16(ioport16_t *port, uint16_t val)
[e7b7be3f]131{
[add04f7]132 asm volatile (
133 "outw %w[val], %w[port]\n"
[7a0359b]134 :: [val] "a" (val),
135 [port] "d" (port)
[add04f7]136 );
[e7b7be3f]137}
[714675b]138
139/** Double word to port
140 *
141 * Output double word to port
142 *
143 * @param port Port to write to
144 * @param val Value to write
[add04f7]145 *
[714675b]146 */
[7a0359b]147NO_TRACE static inline void pio_write_32(ioport32_t *port, uint32_t val)
[e7b7be3f]148{
[add04f7]149 asm volatile (
150 "outl %[val], %w[port]\n"
[7a0359b]151 :: [val] "a" (val),
152 [port] "d" (port)
[add04f7]153 );
[e7b7be3f]154}
[a5556b4]155
[105a0dc]156/** Byte from port
157 *
158 * Get byte from port
159 *
160 * @param port Port to read from
161 * @return Value read
[add04f7]162 *
[105a0dc]163 */
[7a0359b]164NO_TRACE static inline uint8_t pio_read_8(ioport8_t *port)
[e7b7be3f]165{
166 uint8_t val;
167
[add04f7]168 asm volatile (
169 "inb %w[port], %b[val]\n"
170 : [val] "=a" (val)
171 : [port] "d" (port)
172 );
173
[e7b7be3f]174 return val;
175}
[105a0dc]176
177/** Word from port
178 *
179 * Get word from port
180 *
181 * @param port Port to read from
182 * @return Value read
[add04f7]183 *
[105a0dc]184 */
[7a0359b]185NO_TRACE static inline uint16_t pio_read_16(ioport16_t *port)
[e7b7be3f]186{
187 uint16_t val;
188
[add04f7]189 asm volatile (
190 "inw %w[port], %w[val]\n"
191 : [val] "=a" (val)
192 : [port] "d" (port)
193 );
194
[e7b7be3f]195 return val;
196}
[105a0dc]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
[add04f7]204 *
[105a0dc]205 */
[7a0359b]206NO_TRACE static inline uint32_t pio_read_32(ioport32_t *port)
[e7b7be3f]207{
208 uint32_t val;
209
[add04f7]210 asm volatile (
211 "inl %w[port], %[val]\n"
212 : [val] "=a" (val)
213 : [port] "d" (port)
214 );
215
[e7b7be3f]216 return val;
217}
[105a0dc]218
[22f7769]219/** Enable interrupts.
[18e0a6c]220 *
221 * Enable interrupts and return previous
222 * value of EFLAGS.
[22f7769]223 *
224 * @return Old interrupt priority level.
[add04f7]225 *
[18e0a6c]226 */
[7a0359b]227NO_TRACE static inline ipl_t interrupts_enable(void)
[0259524]228{
[22f7769]229 ipl_t v;
[add04f7]230
[e7b7be3f]231 asm volatile (
[add04f7]232 "pushf\n"
233 "popl %[v]\n"
[18e0a6c]234 "sti\n"
[add04f7]235 : [v] "=r" (v)
[18e0a6c]236 );
[add04f7]237
[18e0a6c]238 return v;
239}
240
[22f7769]241/** Disable interrupts.
[18e0a6c]242 *
243 * Disable interrupts and return previous
244 * value of EFLAGS.
[22f7769]245 *
246 * @return Old interrupt priority level.
[add04f7]247 *
[18e0a6c]248 */
[7a0359b]249NO_TRACE static inline ipl_t interrupts_disable(void)
[0259524]250{
[22f7769]251 ipl_t v;
[add04f7]252
[e7b7be3f]253 asm volatile (
[add04f7]254 "pushf\n"
255 "popl %[v]\n"
[18e0a6c]256 "cli\n"
[add04f7]257 : [v] "=r" (v)
[18e0a6c]258 );
[add04f7]259
[18e0a6c]260 return v;
261}
262
[22f7769]263/** Restore interrupt priority level.
[18e0a6c]264 *
265 * Restore EFLAGS.
[22f7769]266 *
267 * @param ipl Saved interrupt priority level.
[add04f7]268 *
[18e0a6c]269 */
[7a0359b]270NO_TRACE static inline void interrupts_restore(ipl_t ipl)
[0259524]271{
[e7b7be3f]272 asm volatile (
[add04f7]273 "pushl %[ipl]\n"
[18e0a6c]274 "popf\n"
[add04f7]275 :: [ipl] "r" (ipl)
[18e0a6c]276 );
277}
278
[22f7769]279/** Return interrupt priority level.
[18e0a6c]280 *
[22f7769]281 * @return EFLAFS.
[add04f7]282 *
[18e0a6c]283 */
[7a0359b]284NO_TRACE static inline ipl_t interrupts_read(void)
[0259524]285{
[22f7769]286 ipl_t v;
[add04f7]287
[e7b7be3f]288 asm volatile (
[add04f7]289 "pushf\n"
290 "popl %[v]\n"
291 : [v] "=r" (v)
[18e0a6c]292 );
[add04f7]293
[18e0a6c]294 return v;
295}
[c9b8c5c]296
[2b4a9f26]297/** Check interrupts state.
298 *
299 * @return True if interrupts are disabled.
300 *
301 */
[7a0359b]302NO_TRACE static inline bool interrupts_disabled(void)
[2b4a9f26]303{
304 ipl_t v;
305
306 asm volatile (
307 "pushf\n"
308 "popl %[v]\n"
309 : [v] "=r" (v)
310 );
311
312 return ((v & EFLAGS_IF) == 0);
313}
314
[f2ef7fd]315/** Write to MSR */
[7a0359b]316NO_TRACE static inline void write_msr(uint32_t msr, uint64_t value)
[f2ef7fd]317{
[add04f7]318 asm volatile (
319 "wrmsr"
[7a0359b]320 :: "c" (msr),
321 "a" ((uint32_t) (value)),
[add04f7]322 "d" ((uint32_t) (value >> 32))
323 );
[f2ef7fd]324}
325
[7a0359b]326NO_TRACE static inline uint64_t read_msr(uint32_t msr)
[f2ef7fd]327{
328 uint32_t ax, dx;
[add04f7]329
330 asm volatile (
331 "rdmsr"
[7a0359b]332 : "=a" (ax),
333 "=d" (dx)
[add04f7]334 : "c" (msr)
335 );
336
337 return ((uint64_t) dx << 32) | ax;
[f2ef7fd]338}
339
340
[361635c]341/** Return base address of current stack
342 *
343 * Return the base address of the current stack.
344 * The stack is assumed to be STACK_SIZE bytes long.
[1fbbcd6]345 * The stack must start on page boundary.
[add04f7]346 *
[361635c]347 */
[7a0359b]348NO_TRACE static inline uintptr_t get_stack_base(void)
[361635c]349{
[7f1c620]350 uintptr_t v;
[361635c]351
[7f043c0]352 asm volatile (
[add04f7]353 "andl %%esp, %[v]\n"
354 : [v] "=r" (v)
[7f043c0]355 : "0" (~(STACK_SIZE - 1))
356 );
[361635c]357
358 return v;
359}
360
[7910cff]361/** Invalidate TLB Entry.
362 *
363 * @param addr Address on a page whose TLB entry is to be invalidated.
[add04f7]364 *
[7910cff]365 */
[7a0359b]366NO_TRACE static inline void invlpg(uintptr_t addr)
[7910cff]367{
[add04f7]368 asm volatile (
369 "invlpg %[addr]\n"
370 :: [addr] "m" (*(unative_t *) addr)
371 );
[7910cff]372}
373
[897ad60]374/** Load GDTR register from memory.
375 *
376 * @param gdtr_reg Address of memory from where to load GDTR.
[add04f7]377 *
[897ad60]378 */
[7a0359b]379NO_TRACE static inline void gdtr_load(ptr_16_32_t *gdtr_reg)
[897ad60]380{
[add04f7]381 asm volatile (
382 "lgdtl %[gdtr_reg]\n"
383 :: [gdtr_reg] "m" (*gdtr_reg)
384 );
[897ad60]385}
386
387/** Store GDTR register to memory.
388 *
389 * @param gdtr_reg Address of memory to where to load GDTR.
[add04f7]390 *
[897ad60]391 */
[7a0359b]392NO_TRACE static inline void gdtr_store(ptr_16_32_t *gdtr_reg)
[897ad60]393{
[add04f7]394 asm volatile (
395 "sgdtl %[gdtr_reg]\n"
[c4d11c5]396 : [gdtr_reg] "=m" (*gdtr_reg)
[add04f7]397 );
[897ad60]398}
399
400/** Load IDTR register from memory.
401 *
402 * @param idtr_reg Address of memory from where to load IDTR.
[add04f7]403 *
[897ad60]404 */
[7a0359b]405NO_TRACE static inline void idtr_load(ptr_16_32_t *idtr_reg)
[897ad60]406{
[add04f7]407 asm volatile (
408 "lidtl %[idtr_reg]\n"
409 :: [idtr_reg] "m" (*idtr_reg)
410 );
[897ad60]411}
412
413/** Load TR from descriptor table.
414 *
415 * @param sel Selector specifying descriptor of TSS segment.
[add04f7]416 *
[897ad60]417 */
[7a0359b]418NO_TRACE static inline void tr_load(uint16_t sel)
[897ad60]419{
[add04f7]420 asm volatile (
421 "ltr %[sel]"
422 :: [sel] "r" (sel)
423 );
[897ad60]424}
425
[7a0359b]426extern void paging_on(void);
427extern void enable_l_apic_in_msr(void);
428
429extern void asm_delay_loop(uint32_t);
430extern void asm_fake_loop(uint32_t);
431
[b808660]432extern uintptr_t int_0;
433extern uintptr_t int_1;
434extern uintptr_t int_2;
435extern uintptr_t int_3;
436extern uintptr_t int_4;
437extern uintptr_t int_5;
438extern uintptr_t int_6;
439extern uintptr_t int_7;
440extern uintptr_t int_8;
441extern uintptr_t int_9;
442extern uintptr_t int_10;
443extern uintptr_t int_11;
444extern uintptr_t int_12;
445extern uintptr_t int_13;
446extern uintptr_t int_14;
447extern uintptr_t int_15;
448extern uintptr_t int_16;
449extern uintptr_t int_17;
450extern uintptr_t int_18;
451extern uintptr_t int_19;
452extern uintptr_t int_20;
453extern uintptr_t int_21;
454extern uintptr_t int_22;
455extern uintptr_t int_23;
456extern uintptr_t int_24;
457extern uintptr_t int_25;
458extern uintptr_t int_26;
459extern uintptr_t int_27;
460extern uintptr_t int_28;
461extern uintptr_t int_29;
462extern uintptr_t int_30;
463extern uintptr_t int_31;
464extern uintptr_t int_32;
465extern uintptr_t int_33;
466extern uintptr_t int_34;
467extern uintptr_t int_35;
468extern uintptr_t int_36;
469extern uintptr_t int_37;
470extern uintptr_t int_38;
471extern uintptr_t int_39;
472extern uintptr_t int_40;
473extern uintptr_t int_41;
474extern uintptr_t int_42;
475extern uintptr_t int_43;
476extern uintptr_t int_44;
477extern uintptr_t int_45;
478extern uintptr_t int_46;
479extern uintptr_t int_47;
480extern uintptr_t int_48;
481extern uintptr_t int_49;
482extern uintptr_t int_50;
483extern uintptr_t int_51;
484extern uintptr_t int_52;
485extern uintptr_t int_53;
486extern uintptr_t int_54;
487extern uintptr_t int_55;
488extern uintptr_t int_56;
489extern uintptr_t int_57;
490extern uintptr_t int_58;
491extern uintptr_t int_59;
492extern uintptr_t int_60;
493extern uintptr_t int_61;
494extern uintptr_t int_62;
495extern uintptr_t int_63;
496
[f761f1eb]497#endif
[b45c443]498
[06e1e95]499/** @}
[b45c443]500 */
Note: See TracBrowser for help on using the repository browser.