Subversion Repositories HelenOS

Rev

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