Subversion Repositories HelenOS

Rev

Rev 4016 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

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