Subversion Repositories HelenOS

Rev

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

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