Subversion Repositories HelenOS

Rev

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

Rev Author Line No. Line
173 jermar 1
/*
2071 jermar 2
 * Copyright (c) 2005 Jakub Jermar
173 jermar 3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
7
 * are met:
8
 *
9
 * - Redistributions of source code must retain the above copyright
10
 *   notice, this list of conditions and the following disclaimer.
11
 * - Redistributions in binary form must reproduce the above copyright
12
 *   notice, this list of conditions and the following disclaimer in the
13
 *   documentation and/or other materials provided with the distribution.
14
 * - The name of the author may not be used to endorse or promote products
15
 *   derived from this software without specific prior written permission.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
 */
28
 
4017 decky 29
/** @addtogroup amd64
1702 cejka 30
 * @{
31
 */
32
/** @file
33
 */
34
 
1888 jermar 35
#ifndef KERN_amd64_ASM_H_
36
#define KERN_amd64_ASM_H_
173 jermar 37
 
38
#include <config.h>
39
 
1780 jermar 40
extern void asm_delay_loop(uint32_t t);
41
extern void asm_fake_loop(uint32_t t);
200 palkovsky 42
 
253 jermar 43
/** Return base address of current stack.
44
 *
45
 * Return the base address of the current stack.
46
 * The stack is assumed to be STACK_SIZE bytes long.
47
 * The stack must start on page boundary.
4017 decky 48
 *
253 jermar 49
 */
1780 jermar 50
static inline uintptr_t get_stack_base(void)
173 jermar 51
{
1780 jermar 52
    uintptr_t v;
226 palkovsky 53
 
4017 decky 54
    asm volatile (
55
        "andq %%rsp, %[v]\n"
56
        : [v] "=r" (v)
57
        : "0" (~((uint64_t) STACK_SIZE-1))
58
    );
226 palkovsky 59
 
60
    return v;
173 jermar 61
}
62
 
2233 decky 63
static inline void cpu_sleep(void)
64
{
65
    asm volatile ("hlt\n");
2453 jermar 66
}
197 palkovsky 67
 
2233 decky 68
static inline void cpu_halt(void)
69
{
70
    asm volatile ("hlt\n");
2453 jermar 71
}
200 palkovsky 72
 
2233 decky 73
 
625 palkovsky 74
/** Byte from port
75
 *
76
 * Get byte from port
77
 *
78
 * @param port Port to read from
79
 * @return Value read
4017 decky 80
 *
625 palkovsky 81
 */
3929 jermar 82
static inline uint8_t pio_read_8(ioport8_t *port)
2453 jermar 83
{
84
    uint8_t val;
4017 decky 85
 
86
    asm volatile (
87
        "inb %w[port], %b[val]\n"
88
        : [val] "=a" (val)
89
        : [port] "d" (port)
90
    );
91
 
2453 jermar 92
    return val;
93
}
94
 
3948 jermar 95
/** Word from port
96
 *
97
 * Get word from port
98
 *
99
 * @param port Port to read from
100
 * @return Value read
4017 decky 101
 *
3948 jermar 102
 */
103
static inline uint16_t pio_read_16(ioport16_t *port)
104
{
105
    uint16_t val;
106
 
4017 decky 107
    asm volatile (
108
        "inw %w[port], %w[val]\n"
109
        : [val] "=a" (val)
110
        : [port] "d" (port)
111
    );
112
 
3948 jermar 113
    return val;
114
}
115
 
116
/** Double word from port
117
 *
118
 * Get double word from port
119
 *
120
 * @param port Port to read from
121
 * @return Value read
4017 decky 122
 *
3948 jermar 123
 */
124
static inline uint32_t pio_read_32(ioport32_t *port)
125
{
126
    uint32_t val;
127
 
4017 decky 128
    asm volatile (
129
        "inl %w[port], %[val]\n"
130
        : [val] "=a" (val)
131
        : [port] "d" (port)
132
    );
133
 
3948 jermar 134
    return val;
135
}
136
 
625 palkovsky 137
/** Byte to port
138
 *
139
 * Output byte to port
140
 *
141
 * @param port Port to write to
142
 * @param val Value to write
4017 decky 143
 *
625 palkovsky 144
 */
3929 jermar 145
static inline void pio_write_8(ioport8_t *port, uint8_t val)
2453 jermar 146
{
4017 decky 147
    asm volatile (
148
        "outb %b[val], %w[port]\n"
149
        :: [val] "a" (val), [port] "d" (port)
150
    );
2453 jermar 151
}
200 palkovsky 152
 
3948 jermar 153
/** Word to port
154
 *
155
 * Output word to port
156
 *
157
 * @param port Port to write to
158
 * @param val Value to write
4017 decky 159
 *
3948 jermar 160
 */
161
static inline void pio_write_16(ioport16_t *port, uint16_t val)
162
{
4017 decky 163
    asm volatile (
164
        "outw %w[val], %w[port]\n"
165
        :: [val] "a" (val), [port] "d" (port)
166
    );
3948 jermar 167
}
168
 
169
/** Double word to port
170
 *
171
 * Output double word to port
172
 *
173
 * @param port Port to write to
174
 * @param val Value to write
4017 decky 175
 *
3948 jermar 176
 */
177
static inline void pio_write_32(ioport32_t *port, uint32_t val)
178
{
4017 decky 179
    asm volatile (
180
        "outl %[val], %w[port]\n"
181
        :: [val] "a" (val), [port] "d" (port)
182
    );
3948 jermar 183
}
184
 
806 palkovsky 185
/** Swap Hidden part of GS register with visible one */
2453 jermar 186
static inline void swapgs(void)
187
{
188
    asm volatile("swapgs");
189
}
806 palkovsky 190
 
413 jermar 191
/** Enable interrupts.
200 palkovsky 192
 *
193
 * Enable interrupts and return previous
194
 * value of EFLAGS.
413 jermar 195
 *
196
 * @return Old interrupt priority level.
4017 decky 197
 *
200 palkovsky 198
 */
413 jermar 199
static inline ipl_t interrupts_enable(void) {
200
    ipl_t v;
4017 decky 201
 
202
    asm volatile (
200 palkovsky 203
        "pushfq\n"
4017 decky 204
        "popq %[v]\n"
200 palkovsky 205
        "sti\n"
4017 decky 206
        : [v] "=r" (v)
200 palkovsky 207
    );
4017 decky 208
 
200 palkovsky 209
    return v;
210
}
211
 
413 jermar 212
/** Disable interrupts.
200 palkovsky 213
 *
214
 * Disable interrupts and return previous
215
 * value of EFLAGS.
413 jermar 216
 *
217
 * @return Old interrupt priority level.
4017 decky 218
 *
200 palkovsky 219
 */
413 jermar 220
static inline ipl_t interrupts_disable(void) {
221
    ipl_t v;
4017 decky 222
 
223
    asm volatile (
200 palkovsky 224
        "pushfq\n"
4017 decky 225
        "popq %[v]\n"
200 palkovsky 226
        "cli\n"
4017 decky 227
        : [v] "=r" (v)
228
    );
229
 
200 palkovsky 230
    return v;
231
}
232
 
413 jermar 233
/** Restore interrupt priority level.
200 palkovsky 234
 *
235
 * Restore EFLAGS.
413 jermar 236
 *
237
 * @param ipl Saved interrupt priority level.
4017 decky 238
 *
200 palkovsky 239
 */
413 jermar 240
static inline void interrupts_restore(ipl_t ipl) {
4017 decky 241
    asm volatile (
242
        "pushq %[ipl]\n"
200 palkovsky 243
        "popfq\n"
4017 decky 244
        :: [ipl] "r" (ipl)
245
    );
200 palkovsky 246
}
247
 
413 jermar 248
/** Return interrupt priority level.
206 palkovsky 249
 *
250
 * Return EFLAFS.
413 jermar 251
 *
252
 * @return Current interrupt priority level.
4017 decky 253
 *
206 palkovsky 254
 */
413 jermar 255
static inline ipl_t interrupts_read(void) {
256
    ipl_t v;
4017 decky 257
 
258
    asm volatile (
206 palkovsky 259
        "pushfq\n"
4017 decky 260
        "popq %[v]\n"
261
        : [v] "=r" (v)
206 palkovsky 262
    );
4017 decky 263
 
206 palkovsky 264
    return v;
265
}
200 palkovsky 266
 
803 palkovsky 267
/** Write to MSR */
1780 jermar 268
static inline void write_msr(uint32_t msr, uint64_t value)
803 palkovsky 269
{
4017 decky 270
    asm volatile (
271
        "wrmsr\n"
272
        :: "c" (msr),
273
           "a" ((uint32_t) (value)),
274
           "d" ((uint32_t) (value >> 32))
275
    );
803 palkovsky 276
}
219 palkovsky 277
 
1780 jermar 278
static inline unative_t read_msr(uint32_t msr)
803 palkovsky 279
{
1780 jermar 280
    uint32_t ax, dx;
4017 decky 281
 
282
    asm volatile (
283
        "rdmsr\n"
284
        : "=a" (ax), "=d" (dx)
285
        : "c" (msr)
286
    );
287
 
288
    return ((uint64_t) dx << 32) | ax;
803 palkovsky 289
}
290
 
291
 
268 palkovsky 292
/** Enable local APIC
293
 *
294
 * Enable local APIC in MSR.
4017 decky 295
 *
268 palkovsky 296
 */
297
static inline void enable_l_apic_in_msr()
298
{
4017 decky 299
    asm volatile (
348 jermar 300
        "movl $0x1b, %%ecx\n"
301
        "rdmsr\n"
4017 decky 302
        "orl $(1 << 11),%%eax\n"
348 jermar 303
        "orl $(0xfee00000),%%eax\n"
304
        "wrmsr\n"
4017 decky 305
        ::: "%eax","%ecx","%edx"
306
    );
268 palkovsky 307
}
308
 
1780 jermar 309
static inline uintptr_t * get_ip()
581 palkovsky 310
{
1780 jermar 311
    uintptr_t *ip;
4017 decky 312
 
313
    asm volatile (
314
        "mov %%rip, %[ip]"
315
        : [ip] "=r" (ip)
316
    );
317
 
581 palkovsky 318
    return ip;
319
}
320
 
597 jermar 321
/** Invalidate TLB Entry.
322
 *
323
 * @param addr Address on a page whose TLB entry is to be invalidated.
4017 decky 324
 *
597 jermar 325
 */
1780 jermar 326
static inline void invlpg(uintptr_t addr)
597 jermar 327
{
4017 decky 328
    asm volatile (
329
        "invlpg %[addr]\n"
330
        :: [addr] "m" (*((unative_t *) addr))
331
    );
597 jermar 332
}
581 palkovsky 333
 
1186 jermar 334
/** Load GDTR register from memory.
335
 *
336
 * @param gdtr_reg Address of memory from where to load GDTR.
4017 decky 337
 *
1186 jermar 338
 */
339
static inline void gdtr_load(struct ptr_16_64 *gdtr_reg)
340
{
4017 decky 341
    asm volatile (
342
        "lgdtq %[gdtr_reg]\n"
343
        :: [gdtr_reg] "m" (*gdtr_reg)
344
    );
1186 jermar 345
}
346
 
347
/** Store GDTR register to memory.
348
 *
349
 * @param gdtr_reg Address of memory to where to load GDTR.
4017 decky 350
 *
1186 jermar 351
 */
352
static inline void gdtr_store(struct ptr_16_64 *gdtr_reg)
353
{
4017 decky 354
    asm volatile (
355
        "sgdtq %[gdtr_reg]\n"
356
        :: [gdtr_reg] "m" (*gdtr_reg)
357
    );
1186 jermar 358
}
359
 
360
/** Load IDTR register from memory.
361
 *
362
 * @param idtr_reg Address of memory from where to load IDTR.
4017 decky 363
 *
1186 jermar 364
 */
365
static inline void idtr_load(struct ptr_16_64 *idtr_reg)
366
{
4017 decky 367
    asm volatile (
368
        "lidtq %[idtr_reg]\n"
369
        :: [idtr_reg] "m" (*idtr_reg));
1186 jermar 370
}
371
 
372
/** Load TR from descriptor table.
373
 *
374
 * @param sel Selector specifying descriptor of TSS segment.
4017 decky 375
 *
1186 jermar 376
 */
1780 jermar 377
static inline void tr_load(uint16_t sel)
1186 jermar 378
{
4017 decky 379
    asm volatile (
380
        "ltr %[sel]"
381
        :: [sel] "r" (sel)
382
    );
1186 jermar 383
}
384
 
1780 jermar 385
#define GEN_READ_REG(reg) static inline unative_t read_ ##reg (void) \
4017 decky 386
    { \
387
        unative_t res; \
388
        asm volatile ( \
389
            "movq %%" #reg ", %[res]" \
390
            : [res] "=r" (res) \
391
        ); \
392
        return res; \
393
    }
1072 palkovsky 394
 
1780 jermar 395
#define GEN_WRITE_REG(reg) static inline void write_ ##reg (unative_t regn) \
4017 decky 396
    { \
397
        asm volatile ( \
398
            "movq %[regn], %%" #reg \
399
            :: [regn] "r" (regn) \
400
        ); \
401
    }
1072 palkovsky 402
 
2452 jermar 403
GEN_READ_REG(cr0)
404
GEN_READ_REG(cr2)
405
GEN_READ_REG(cr3)
406
GEN_WRITE_REG(cr3)
1072 palkovsky 407
 
2452 jermar 408
GEN_READ_REG(dr0)
409
GEN_READ_REG(dr1)
410
GEN_READ_REG(dr2)
411
GEN_READ_REG(dr3)
412
GEN_READ_REG(dr6)
413
GEN_READ_REG(dr7)
1072 palkovsky 414
 
2452 jermar 415
GEN_WRITE_REG(dr0)
416
GEN_WRITE_REG(dr1)
417
GEN_WRITE_REG(dr2)
418
GEN_WRITE_REG(dr3)
419
GEN_WRITE_REG(dr6)
420
GEN_WRITE_REG(dr7)
1072 palkovsky 421
 
206 palkovsky 422
extern size_t interrupt_handler_size;
423
extern void interrupt_handlers(void);
424
 
173 jermar 425
#endif
1702 cejka 426
 
1888 jermar 427
/** @}
1702 cejka 428
 */