Subversion Repositories HelenOS

Rev

Rev 4345 | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 4345 Rev 4346
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 <typedefs.h>
42
#include <config.h>
42
#include <config.h>
43
 
43
 
44
extern uint32_t interrupt_handler_size;
44
extern uint32_t interrupt_handler_size;
45
 
45
 
46
extern void paging_on(void);
46
extern void paging_on(void);
47
 
47
 
48
extern void interrupt_handlers(void);
48
extern void interrupt_handlers(void);
49
 
49
 
50
extern void enable_l_apic_in_msr(void);
50
extern void enable_l_apic_in_msr(void);
51
 
51
 
52
 
52
 
53
extern void asm_delay_loop(uint32_t t);
53
extern void asm_delay_loop(uint32_t t);
54
extern void asm_fake_loop(uint32_t t);
54
extern void asm_fake_loop(uint32_t t);
55
 
55
 
56
 
56
 
57
/** Halt CPU
57
/** Halt CPU
58
 *
58
 *
59
 * Halt the current CPU until interrupt event.
59
 * Halt the current CPU.
60
 *
60
 *
61
 */
61
 */
62
static inline void cpu_halt(void)
62
static inline void cpu_halt(void)
63
{
63
{
64
    asm volatile ("hlt\n");
64
    asm volatile (
-
 
65
        "0:\n"
-
 
66
        "   hlt\n"
-
 
67
        "   jmp 0b\n"
-
 
68
    );
65
}
69
}
66
 
70
 
67
static inline void cpu_sleep(void)
71
static inline void cpu_sleep(void)
68
{
72
{
69
    asm volatile ("hlt\n");
73
    asm volatile ("hlt\n");
70
}
74
}
71
 
75
 
72
#define GEN_READ_REG(reg) static inline unative_t read_ ##reg (void) \
76
#define GEN_READ_REG(reg) static inline unative_t read_ ##reg (void) \
73
    { \
77
    { \
74
        unative_t res; \
78
        unative_t res; \
75
        asm volatile ( \
79
        asm volatile ( \
76
            "movl %%" #reg ", %[res]" \
80
            "movl %%" #reg ", %[res]" \
77
            : [res] "=r" (res) \
81
            : [res] "=r" (res) \
78
        ); \
82
        ); \
79
        return res; \
83
        return res; \
80
    }
84
    }
81
 
85
 
82
#define GEN_WRITE_REG(reg) static inline void write_ ##reg (unative_t regn) \
86
#define GEN_WRITE_REG(reg) static inline void write_ ##reg (unative_t regn) \
83
    { \
87
    { \
84
        asm volatile ( \
88
        asm volatile ( \
85
            "movl %[regn], %%" #reg \
89
            "movl %[regn], %%" #reg \
86
            :: [regn] "r" (regn) \
90
            :: [regn] "r" (regn) \
87
        ); \
91
        ); \
88
    }
92
    }
89
 
93
 
90
GEN_READ_REG(cr0)
94
GEN_READ_REG(cr0)
91
GEN_READ_REG(cr2)
95
GEN_READ_REG(cr2)
92
GEN_READ_REG(cr3)
96
GEN_READ_REG(cr3)
93
GEN_WRITE_REG(cr3)
97
GEN_WRITE_REG(cr3)
94
 
98
 
95
GEN_READ_REG(dr0)
99
GEN_READ_REG(dr0)
96
GEN_READ_REG(dr1)
100
GEN_READ_REG(dr1)
97
GEN_READ_REG(dr2)
101
GEN_READ_REG(dr2)
98
GEN_READ_REG(dr3)
102
GEN_READ_REG(dr3)
99
GEN_READ_REG(dr6)
103
GEN_READ_REG(dr6)
100
GEN_READ_REG(dr7)
104
GEN_READ_REG(dr7)
101
 
105
 
102
GEN_WRITE_REG(dr0)
106
GEN_WRITE_REG(dr0)
103
GEN_WRITE_REG(dr1)
107
GEN_WRITE_REG(dr1)
104
GEN_WRITE_REG(dr2)
108
GEN_WRITE_REG(dr2)
105
GEN_WRITE_REG(dr3)
109
GEN_WRITE_REG(dr3)
106
GEN_WRITE_REG(dr6)
110
GEN_WRITE_REG(dr6)
107
GEN_WRITE_REG(dr7)
111
GEN_WRITE_REG(dr7)
108
 
112
 
109
/** Byte to port
113
/** Byte to port
110
 *
114
 *
111
 * Output byte to port
115
 * Output byte to port
112
 *
116
 *
113
 * @param port Port to write to
117
 * @param port Port to write to
114
 * @param val Value to write
118
 * @param val Value to write
115
 *
119
 *
116
 */
120
 */
117
static inline void pio_write_8(ioport8_t *port, uint8_t val)
121
static inline void pio_write_8(ioport8_t *port, uint8_t val)
118
{
122
{
119
    asm volatile (
123
    asm volatile (
120
        "outb %b[val], %w[port]\n"
124
        "outb %b[val], %w[port]\n"
121
        :: [val] "a" (val), [port] "d" (port)
125
        :: [val] "a" (val), [port] "d" (port)
122
    );
126
    );
123
}
127
}
124
 
128
 
125
/** Word to port
129
/** Word to port
126
 *
130
 *
127
 * Output word to port
131
 * Output word to port
128
 *
132
 *
129
 * @param port Port to write to
133
 * @param port Port to write to
130
 * @param val Value to write
134
 * @param val Value to write
131
 *
135
 *
132
 */
136
 */
133
static inline void pio_write_16(ioport16_t *port, uint16_t val)
137
static inline void pio_write_16(ioport16_t *port, uint16_t val)
134
{
138
{
135
    asm volatile (
139
    asm volatile (
136
        "outw %w[val], %w[port]\n"
140
        "outw %w[val], %w[port]\n"
137
        :: [val] "a" (val), [port] "d" (port)
141
        :: [val] "a" (val), [port] "d" (port)
138
    );
142
    );
139
}
143
}
140
 
144
 
141
/** Double word to port
145
/** Double word to port
142
 *
146
 *
143
 * Output double word to port
147
 * Output double word to port
144
 *
148
 *
145
 * @param port Port to write to
149
 * @param port Port to write to
146
 * @param val Value to write
150
 * @param val Value to write
147
 *
151
 *
148
 */
152
 */
149
static inline void pio_write_32(ioport32_t *port, uint32_t val)
153
static inline void pio_write_32(ioport32_t *port, uint32_t val)
150
{
154
{
151
    asm volatile (
155
    asm volatile (
152
        "outl %[val], %w[port]\n"
156
        "outl %[val], %w[port]\n"
153
        :: [val] "a" (val), [port] "d" (port)
157
        :: [val] "a" (val), [port] "d" (port)
154
    );
158
    );
155
}
159
}
156
 
160
 
157
/** Byte from port
161
/** Byte from port
158
 *
162
 *
159
 * Get byte from port
163
 * Get byte from port
160
 *
164
 *
161
 * @param port Port to read from
165
 * @param port Port to read from
162
 * @return Value read
166
 * @return Value read
163
 *
167
 *
164
 */
168
 */
165
static inline uint8_t pio_read_8(ioport8_t *port)
169
static inline uint8_t pio_read_8(ioport8_t *port)
166
{
170
{
167
    uint8_t val;
171
    uint8_t val;
168
   
172
   
169
    asm volatile (
173
    asm volatile (
170
        "inb %w[port], %b[val]\n"
174
        "inb %w[port], %b[val]\n"
171
        : [val] "=a" (val)
175
        : [val] "=a" (val)
172
        : [port] "d" (port)
176
        : [port] "d" (port)
173
    );
177
    );
174
   
178
   
175
    return val;
179
    return val;
176
}
180
}
177
 
181
 
178
/** Word from port
182
/** Word from port
179
 *
183
 *
180
 * Get word from port
184
 * Get word from port
181
 *
185
 *
182
 * @param port Port to read from
186
 * @param port Port to read from
183
 * @return Value read
187
 * @return Value read
184
 *
188
 *
185
 */
189
 */
186
static inline uint16_t pio_read_16(ioport16_t *port)
190
static inline uint16_t pio_read_16(ioport16_t *port)
187
{
191
{
188
    uint16_t val;
192
    uint16_t val;
189
   
193
   
190
    asm volatile (
194
    asm volatile (
191
        "inw %w[port], %w[val]\n"
195
        "inw %w[port], %w[val]\n"
192
        : [val] "=a" (val)
196
        : [val] "=a" (val)
193
        : [port] "d" (port)
197
        : [port] "d" (port)
194
    );
198
    );
195
   
199
   
196
    return val;
200
    return val;
197
}
201
}
198
 
202
 
199
/** Double word from port
203
/** Double word from port
200
 *
204
 *
201
 * Get double word from port
205
 * Get double word from port
202
 *
206
 *
203
 * @param port Port to read from
207
 * @param port Port to read from
204
 * @return Value read
208
 * @return Value read
205
 *
209
 *
206
 */
210
 */
207
static inline uint32_t pio_read_32(ioport32_t *port)
211
static inline uint32_t pio_read_32(ioport32_t *port)
208
{
212
{
209
    uint32_t val;
213
    uint32_t val;
210
   
214
   
211
    asm volatile (
215
    asm volatile (
212
        "inl %w[port], %[val]\n"
216
        "inl %w[port], %[val]\n"
213
        : [val] "=a" (val)
217
        : [val] "=a" (val)
214
        : [port] "d" (port)
218
        : [port] "d" (port)
215
    );
219
    );
216
   
220
   
217
    return val;
221
    return val;
218
}
222
}
219
 
223
 
220
/** Enable interrupts.
224
/** Enable interrupts.
221
 *
225
 *
222
 * Enable interrupts and return previous
226
 * Enable interrupts and return previous
223
 * value of EFLAGS.
227
 * value of EFLAGS.
224
 *
228
 *
225
 * @return Old interrupt priority level.
229
 * @return Old interrupt priority level.
226
 *
230
 *
227
 */
231
 */
228
static inline ipl_t interrupts_enable(void)
232
static inline ipl_t interrupts_enable(void)
229
{
233
{
230
    ipl_t v;
234
    ipl_t v;
231
   
235
   
232
    asm volatile (
236
    asm volatile (
233
        "pushf\n"
237
        "pushf\n"
234
        "popl %[v]\n"
238
        "popl %[v]\n"
235
        "sti\n"
239
        "sti\n"
236
        : [v] "=r" (v)
240
        : [v] "=r" (v)
237
    );
241
    );
238
   
242
   
239
    return v;
243
    return v;
240
}
244
}
241
 
245
 
242
/** Disable interrupts.
246
/** Disable interrupts.
243
 *
247
 *
244
 * Disable interrupts and return previous
248
 * Disable interrupts and return previous
245
 * value of EFLAGS.
249
 * value of EFLAGS.
246
 *
250
 *
247
 * @return Old interrupt priority level.
251
 * @return Old interrupt priority level.
248
 *
252
 *
249
 */
253
 */
250
static inline ipl_t interrupts_disable(void)
254
static inline ipl_t interrupts_disable(void)
251
{
255
{
252
    ipl_t v;
256
    ipl_t v;
253
   
257
   
254
    asm volatile (
258
    asm volatile (
255
        "pushf\n"
259
        "pushf\n"
256
        "popl %[v]\n"
260
        "popl %[v]\n"
257
        "cli\n"
261
        "cli\n"
258
        : [v] "=r" (v)
262
        : [v] "=r" (v)
259
    );
263
    );
260
   
264
   
261
    return v;
265
    return v;
262
}
266
}
263
 
267
 
264
/** Restore interrupt priority level.
268
/** Restore interrupt priority level.
265
 *
269
 *
266
 * Restore EFLAGS.
270
 * Restore EFLAGS.
267
 *
271
 *
268
 * @param ipl Saved interrupt priority level.
272
 * @param ipl Saved interrupt priority level.
269
 *
273
 *
270
 */
274
 */
271
static inline void interrupts_restore(ipl_t ipl)
275
static inline void interrupts_restore(ipl_t ipl)
272
{
276
{
273
    asm volatile (
277
    asm volatile (
274
        "pushl %[ipl]\n"
278
        "pushl %[ipl]\n"
275
        "popf\n"
279
        "popf\n"
276
        :: [ipl] "r" (ipl)
280
        :: [ipl] "r" (ipl)
277
    );
281
    );
278
}
282
}
279
 
283
 
280
/** Return interrupt priority level.
284
/** Return interrupt priority level.
281
 *
285
 *
282
 * @return EFLAFS.
286
 * @return EFLAFS.
283
 *
287
 *
284
 */
288
 */
285
static inline ipl_t interrupts_read(void)
289
static inline ipl_t interrupts_read(void)
286
{
290
{
287
    ipl_t v;
291
    ipl_t v;
288
   
292
   
289
    asm volatile (
293
    asm volatile (
290
        "pushf\n"
294
        "pushf\n"
291
        "popl %[v]\n"
295
        "popl %[v]\n"
292
        : [v] "=r" (v)
296
        : [v] "=r" (v)
293
    );
297
    );
294
   
298
   
295
    return v;
299
    return v;
296
}
300
}
297
 
301
 
298
/** Write to MSR */
302
/** Write to MSR */
299
static inline void write_msr(uint32_t msr, uint64_t value)
303
static inline void write_msr(uint32_t msr, uint64_t value)
300
{
304
{
301
    asm volatile (
305
    asm volatile (
302
        "wrmsr"
306
        "wrmsr"
303
        :: "c" (msr), "a" ((uint32_t) (value)),
307
        :: "c" (msr), "a" ((uint32_t) (value)),
304
           "d" ((uint32_t) (value >> 32))
308
           "d" ((uint32_t) (value >> 32))
305
    );
309
    );
306
}
310
}
307
 
311
 
308
static inline uint64_t read_msr(uint32_t msr)
312
static inline uint64_t read_msr(uint32_t msr)
309
{
313
{
310
    uint32_t ax, dx;
314
    uint32_t ax, dx;
311
   
315
   
312
    asm volatile (
316
    asm volatile (
313
        "rdmsr"
317
        "rdmsr"
314
        : "=a" (ax), "=d" (dx)
318
        : "=a" (ax), "=d" (dx)
315
        : "c" (msr)
319
        : "c" (msr)
316
    );
320
    );
317
   
321
   
318
    return ((uint64_t) dx << 32) | ax;
322
    return ((uint64_t) dx << 32) | ax;
319
}
323
}
320
 
324
 
321
 
325
 
322
/** Return base address of current stack
326
/** Return base address of current stack
323
 *
327
 *
324
 * Return the base address of the current stack.
328
 * Return the base address of the current stack.
325
 * The stack is assumed to be STACK_SIZE bytes long.
329
 * The stack is assumed to be STACK_SIZE bytes long.
326
 * The stack must start on page boundary.
330
 * The stack must start on page boundary.
327
 *
331
 *
328
 */
332
 */
329
static inline uintptr_t get_stack_base(void)
333
static inline uintptr_t get_stack_base(void)
330
{
334
{
331
    uintptr_t v;
335
    uintptr_t v;
332
   
336
   
333
    asm volatile (
337
    asm volatile (
334
        "andl %%esp, %[v]\n"
338
        "andl %%esp, %[v]\n"
335
        : [v] "=r" (v)
339
        : [v] "=r" (v)
336
        : "0" (~(STACK_SIZE - 1))
340
        : "0" (~(STACK_SIZE - 1))
337
    );
341
    );
338
   
342
   
339
    return v;
343
    return v;
340
}
344
}
341
 
345
 
342
/** Return current IP address */
346
/** Return current IP address */
343
static inline uintptr_t * get_ip()
347
static inline uintptr_t * get_ip()
344
{
348
{
345
    uintptr_t *ip;
349
    uintptr_t *ip;
346
   
350
   
347
    asm volatile (
351
    asm volatile (
348
        "mov %%eip, %[ip]"
352
        "mov %%eip, %[ip]"
349
        : [ip] "=r" (ip)
353
        : [ip] "=r" (ip)
350
    );
354
    );
351
   
355
   
352
    return ip;
356
    return ip;
353
}
357
}
354
 
358
 
355
/** Invalidate TLB Entry.
359
/** Invalidate TLB Entry.
356
 *
360
 *
357
 * @param addr Address on a page whose TLB entry is to be invalidated.
361
 * @param addr Address on a page whose TLB entry is to be invalidated.
358
 *
362
 *
359
 */
363
 */
360
static inline void invlpg(uintptr_t addr)
364
static inline void invlpg(uintptr_t addr)
361
{
365
{
362
    asm volatile (
366
    asm volatile (
363
        "invlpg %[addr]\n"
367
        "invlpg %[addr]\n"
364
        :: [addr] "m" (*(unative_t *) addr)
368
        :: [addr] "m" (*(unative_t *) addr)
365
    );
369
    );
366
}
370
}
367
 
371
 
368
/** Load GDTR register from memory.
372
/** Load GDTR register from memory.
369
 *
373
 *
370
 * @param gdtr_reg Address of memory from where to load GDTR.
374
 * @param gdtr_reg Address of memory from where to load GDTR.
371
 *
375
 *
372
 */
376
 */
373
static inline void gdtr_load(ptr_16_32_t *gdtr_reg)
377
static inline void gdtr_load(ptr_16_32_t *gdtr_reg)
374
{
378
{
375
    asm volatile (
379
    asm volatile (
376
        "lgdtl %[gdtr_reg]\n"
380
        "lgdtl %[gdtr_reg]\n"
377
        :: [gdtr_reg] "m" (*gdtr_reg)
381
        :: [gdtr_reg] "m" (*gdtr_reg)
378
    );
382
    );
379
}
383
}
380
 
384
 
381
/** Store GDTR register to memory.
385
/** Store GDTR register to memory.
382
 *
386
 *
383
 * @param gdtr_reg Address of memory to where to load GDTR.
387
 * @param gdtr_reg Address of memory to where to load GDTR.
384
 *
388
 *
385
 */
389
 */
386
static inline void gdtr_store(ptr_16_32_t *gdtr_reg)
390
static inline void gdtr_store(ptr_16_32_t *gdtr_reg)
387
{
391
{
388
    asm volatile (
392
    asm volatile (
389
        "sgdtl %[gdtr_reg]\n"
393
        "sgdtl %[gdtr_reg]\n"
390
        :: [gdtr_reg] "m" (*gdtr_reg)
394
        :: [gdtr_reg] "m" (*gdtr_reg)
391
    );
395
    );
392
}
396
}
393
 
397
 
394
/** Load IDTR register from memory.
398
/** Load IDTR register from memory.
395
 *
399
 *
396
 * @param idtr_reg Address of memory from where to load IDTR.
400
 * @param idtr_reg Address of memory from where to load IDTR.
397
 *
401
 *
398
 */
402
 */
399
static inline void idtr_load(ptr_16_32_t *idtr_reg)
403
static inline void idtr_load(ptr_16_32_t *idtr_reg)
400
{
404
{
401
    asm volatile (
405
    asm volatile (
402
        "lidtl %[idtr_reg]\n"
406
        "lidtl %[idtr_reg]\n"
403
        :: [idtr_reg] "m" (*idtr_reg)
407
        :: [idtr_reg] "m" (*idtr_reg)
404
    );
408
    );
405
}
409
}
406
 
410
 
407
/** Load TR from descriptor table.
411
/** Load TR from descriptor table.
408
 *
412
 *
409
 * @param sel Selector specifying descriptor of TSS segment.
413
 * @param sel Selector specifying descriptor of TSS segment.
410
 *
414
 *
411
 */
415
 */
412
static inline void tr_load(uint16_t sel)
416
static inline void tr_load(uint16_t sel)
413
{
417
{
414
    asm volatile (
418
    asm volatile (
415
        "ltr %[sel]"
419
        "ltr %[sel]"
416
        :: [sel] "r" (sel)
420
        :: [sel] "r" (sel)
417
    );
421
    );
418
}
422
}
419
 
423
 
420
#endif
424
#endif
421
 
425
 
422
/** @}
426
/** @}
423
 */
427
 */
424
 
428