Subversion Repositories HelenOS

Rev

Rev 4016 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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