Subversion Repositories HelenOS

Rev

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