furix
cute os
include/arch/x86_64/io.h
2251 bytes raw
1#ifndef FURIX_ARCH_X86_64_IO_H
2#define FURIX_ARCH_X86_64_IO_H
3
4#include <types.h>
5
6struct desc_ptr {
7 uint16_t limit;
8 uint64_t base;
9} __attribute__((packed));
10
11/*
12 * CR4.PAE is required for the 4-level page tables long mode uses. CR4.PSE is
13 * NOT needed there: in long mode 2 MiB pages come from PAE on its own.
14 *
15 * CR4.FSGSBASE is never set on this CPU model, see percpu.c.
16 */
17#define CR4_PAE (1u << 5)
18#define CR4_FSGSBASE (1u << 16)
19
20/* implemented in arch/x86_64/asm.S, so no inline asm elsewhere */
21
22uint8_t inb(uint16_t port);
23void outb(uint16_t port, uint8_t value);
24
25void cpu_cli(void);
26void cpu_sti(void);
27void cpu_hlt(void);
28
29/* mask interrupts, returning the prior EFLAGS word to pass back to restore */
30uint64_t cpu_irq_save(void);
31void cpu_irq_restore(uint64_t flags);
32uint32_t cpu_irqs_enabled(void);
33
34uint64_t rdmsr(uint32_t msr);
35void wrmsr(uint32_t msr, uint64_t value);
36void swapgs(void);
37
38uint32_t read_cr4(void);
39void write_cr4(uint32_t value);
40void wrgsbase(uint64_t value);
41uint64_t rdfsbase(void);
42
43uint64_t read_cr2(void);
44uint64_t read_cr3(void);
45
46/* result of the last cpuid() call: {eax, ebx, ecx, edx} */
47extern uint64_t cpuid_out[4];
48void cpuid(uint32_t leaf);
49
50void lgdt(const struct desc_ptr *ptr);
51void lidt(const struct desc_ptr *ptr);
52void ltr(uint16_t selector);
53void reload_cs(uint16_t selector);
54void load_data_segments(uint16_t selector);
55
56void gs_store(uint64_t value);
57uint64_t gs_load(void);
58
59/*
60 * atomics, implemented in asm.S because they need `lock` prefixes that are
61 * awkward and error-prone as inline asm (and cannot be written as a plain C
62 * `+=` without the compiler knowing the access is shared).
63 *
64 * fetch_add returns the value BEFORE the addition, so it doubles as a
65 * completion index. the u32 form is deliberate: a 64-bit add is not atomic on
66 * a 32-bit target and 32 bits is what the counters here need.
67 */
68uint32_t atomic_fetch_add_u32(volatile uint32_t *ptr, uint32_t value);
69
70/* returns the value read, having set *ptr to 1. nonzero means "lost the race" */
71uint8_t atomic_test_and_set_u8(volatile uint8_t *ptr);
72
73/* a volatile load; x86 makes an aligned 32-bit load atomic anyway */
74uint32_t atomic_load_u32(const volatile uint32_t *ptr);
75
76#endif /* FURIX_ARCH_X86_64_IO_H */