test
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include <zinnia/elf.h>
|
||||
|
||||
#define ELF_ARCH_CLASS ELFCLASS64
|
||||
#define ELF_ARCH_DATA ELFDATA2LSB
|
||||
#define ELF_ARCH_MACHINE EM_X86_64
|
||||
|
||||
#define ELF_R_SYM ELF64_R_SYM
|
||||
#define ELF_R_TYPE ELF64_R_TYPE
|
||||
#define ELF_ST_BIND ELF64_ST_BIND
|
||||
#define ELF_ST_TYPE ELF64_ST_TYPE
|
||||
|
||||
#define elf_ehdr elf64_ehdr
|
||||
#define elf_phdr elf64_phdr
|
||||
#define elf_dyn elf64_dyn
|
||||
#define elf_addr elf64_addr
|
||||
#define elf_off elf64_off
|
||||
#define elf_nhdr elf64_nhdr
|
||||
#define elf_auxv elf64_auxv
|
||||
#define elf_sym elf64_sym
|
||||
#define elf_rela elf64_rela
|
||||
#define elf_rel elf64_rel
|
||||
|
||||
enum {
|
||||
R_NONE = 0,
|
||||
R_COPY = 5,
|
||||
R_GLOB_DAT = 6,
|
||||
R_JUMP_SLOT = 7,
|
||||
R_RELATIVE = 8,
|
||||
R_IRELATIVE = 37,
|
||||
};
|
||||
@@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <x86_64/defs.h>
|
||||
|
||||
static inline bool arch_irq_get_state() {
|
||||
uint64_t flags;
|
||||
asm volatile("pushf; pop %0" : "=r"(flags)::"memory");
|
||||
return flags & RFLAGS_IF;
|
||||
}
|
||||
|
||||
static inline void arch_irq_set_state(bool state) {
|
||||
if (state)
|
||||
asm volatile("sti");
|
||||
else
|
||||
asm volatile("cli");
|
||||
}
|
||||
|
||||
static inline void arch_irq_wait() {
|
||||
asm volatile("hlt");
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <zinnia/types.h>
|
||||
|
||||
static inline size_t arch_mem_page_size() {
|
||||
return 1 << 12;
|
||||
}
|
||||
|
||||
static inline size_t arch_mem_page_bits() {
|
||||
return 12;
|
||||
}
|
||||
|
||||
static inline size_t arch_mem_level_bits() {
|
||||
return 9;
|
||||
}
|
||||
|
||||
static inline size_t arch_mem_num_levels() {
|
||||
return 4;
|
||||
}
|
||||
|
||||
static inline uintptr_t arch_mem_hhdm_addr() {
|
||||
return 0xFFFF'8000'0000'0000;
|
||||
}
|
||||
|
||||
static inline uintptr_t arch_vm_pfndb_addr() {
|
||||
return 0xFFFF'A000'0000'0000;
|
||||
}
|
||||
|
||||
static inline uintptr_t arch_mem_mapping_addr() {
|
||||
return 0xFFFF'C000'0000'0000;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef uint64_t pte_t;
|
||||
@@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <x86_64/apic.h>
|
||||
#include <x86_64/gdt.h>
|
||||
#include <x86_64/tss.h>
|
||||
#include <zinnia/irq.h>
|
||||
|
||||
static inline struct percpu* arch_percpu_get() {
|
||||
struct percpu* result;
|
||||
asm volatile("mov %0, gs:0" : "=r"(result)::"memory");
|
||||
return result;
|
||||
}
|
||||
|
||||
struct arch_percpu {
|
||||
struct gdt gdt;
|
||||
struct tss tss;
|
||||
struct local_apic lapic;
|
||||
struct irq_line* irq_lines[128];
|
||||
size_t fpu_size;
|
||||
void (*fpu_save)(void*);
|
||||
void (*fpu_restore)(const void*);
|
||||
bool can_smap;
|
||||
};
|
||||
|
||||
void arch_percpu_bsp_init();
|
||||
void arch_percpu_init();
|
||||
@@ -0,0 +1,48 @@
|
||||
#pragma once
|
||||
|
||||
#include <bits/types.h>
|
||||
#include <stdint.h>
|
||||
|
||||
struct arch_task_context {
|
||||
uint64_t rsp;
|
||||
uint8_t* fpu_region;
|
||||
uint16_t ds, es, fs, gs;
|
||||
uint64_t fs_base, gs_base;
|
||||
};
|
||||
|
||||
struct arch_context {
|
||||
uint64_t r15;
|
||||
uint64_t r14;
|
||||
uint64_t r13;
|
||||
uint64_t r12;
|
||||
uint64_t r11;
|
||||
uint64_t r10;
|
||||
uint64_t r9;
|
||||
uint64_t r8;
|
||||
uint64_t rsi;
|
||||
uint64_t rdi;
|
||||
uint64_t rbp;
|
||||
uint64_t rdx;
|
||||
uint64_t rcx;
|
||||
uint64_t rbx;
|
||||
uint64_t rax;
|
||||
uint64_t isr; // Pushed onto the stack by the interrupt handler stubs.
|
||||
uint64_t error; // Pushed onto the stack by the CPU if the interrupt has an error code.
|
||||
uint64_t rip; // The rest is pushed onto the stack by the CPU during an interrupt.
|
||||
uint64_t cs;
|
||||
uint64_t rflags;
|
||||
uint64_t rsp;
|
||||
uint64_t ss;
|
||||
};
|
||||
|
||||
#define ARCH_CTX_NUM rax
|
||||
#define ARCH_CTX_A0 rdi
|
||||
#define ARCH_CTX_A1 rsi
|
||||
#define ARCH_CTX_A2 rdx
|
||||
#define ARCH_CTX_A3 r9
|
||||
#define ARCH_CTX_A4 r8
|
||||
#define ARCH_CTX_A5 r10
|
||||
#define ARCH_CTX_A6 r12
|
||||
#define ARCH_CTX_A7 r13
|
||||
#define ARCH_CTX_RET0 rax
|
||||
#define ARCH_CTX_RET1 rdx
|
||||
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef uint64_t phys_t;
|
||||
typedef uint64_t reg_t;
|
||||
@@ -0,0 +1,57 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <zinnia/mmio.h>
|
||||
|
||||
struct local_apic {
|
||||
uint32_t id;
|
||||
uint32_t ticks_per_10ms;
|
||||
struct mmio_view xapic_regs;
|
||||
};
|
||||
|
||||
enum apic_delivery_mode {
|
||||
APIC_DELIVERY_FIXED = 0b000,
|
||||
APIC_DELIVERY_LOWESTPRIO = 0b001,
|
||||
APIC_DELIVERY_SMI = 0b010,
|
||||
APIC_DELIVERY_NMI = 0b100,
|
||||
APIC_DELIVERY_INIT = 0b101,
|
||||
APIC_DELIVERY_STARTUP = 0b110,
|
||||
};
|
||||
|
||||
enum apic_dest_mode {
|
||||
APIC_DEST_PHYSICAL = 0,
|
||||
APIC_DEST_LOGICAL = 1,
|
||||
};
|
||||
|
||||
enum apic_delivery_status {
|
||||
APIC_DELIVERY_STATUS_IDLE = 0,
|
||||
APIC_DELIVERY_STATUS_PENDING = 1,
|
||||
};
|
||||
|
||||
enum apic_level {
|
||||
APIC_LEVEL_DEASSERT = 0,
|
||||
APIC_LEVEL_ASSERT = 1,
|
||||
};
|
||||
|
||||
enum apic_trigger_mode {
|
||||
APIC_TRIGGER_EDGE = 0,
|
||||
APIC_TRIGGER_LEVEL = 1,
|
||||
};
|
||||
|
||||
constexpr mmio_reg32 APIC_REG_ID = {.offset = 0x20};
|
||||
constexpr mmio_reg32 APIC_REG_TPR = {.offset = 0x80};
|
||||
constexpr mmio_reg32 APIC_REG_EOI = {.offset = 0xB0};
|
||||
constexpr mmio_reg32 APIC_REG_LDR = {.offset = 0xD0};
|
||||
constexpr mmio_reg32 APIC_REG_DFR = {.offset = 0xE0};
|
||||
constexpr mmio_reg32 APIC_REG_SIVR = {.offset = 0xF0};
|
||||
constexpr mmio_reg32 APIC_REG_ESR = {.offset = 0x280};
|
||||
constexpr mmio_reg32 APIC_REG_ICR = {.offset = 0x300};
|
||||
constexpr mmio_reg32 APIC_REG_ICR_HI = {.offset = 0x310};
|
||||
constexpr mmio_reg32 APIC_REG_LVT_TR = {.offset = 0x320};
|
||||
constexpr mmio_reg32 APIC_REG_ICR_TIMER = {.offset = 0x380};
|
||||
constexpr mmio_reg32 APIC_REG_CCR = {.offset = 0x390};
|
||||
constexpr mmio_reg32 APIC_REG_DCR = {.offset = 0x3E0};
|
||||
|
||||
void lapic_init(struct local_apic* lapic);
|
||||
void lapic_eoi(struct local_apic* lapic);
|
||||
void pic_disable();
|
||||
@@ -0,0 +1,135 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
struct cpuid {
|
||||
uint32_t eax, ebx, ecx, edx;
|
||||
};
|
||||
|
||||
static inline struct cpuid asm_cpuid(uint32_t leaf, uint32_t subleaf) {
|
||||
struct cpuid out = {0};
|
||||
asm volatile("cpuid" : "=a"(out.eax), "=b"(out.ebx), "=c"(out.ecx), "=d"(out.edx) : "0"(leaf), "2"(subleaf));
|
||||
return out;
|
||||
}
|
||||
|
||||
static inline uint64_t asm_rdmsr(uint32_t msr) {
|
||||
uint32_t eax;
|
||||
uint32_t edx;
|
||||
asm volatile("rdmsr" : "=a"(eax), "=d"(edx) : "c"(msr) : "memory");
|
||||
return ((uint64_t)edx << 32) | eax;
|
||||
}
|
||||
|
||||
static inline uint64_t asm_rdtsc() {
|
||||
uint32_t eax;
|
||||
uint32_t edx;
|
||||
asm volatile("rdtsc" : "=a"(eax), "=d"(edx) : : "memory");
|
||||
return ((uint64_t)edx << 32) | eax;
|
||||
}
|
||||
|
||||
// Writes a 64-bit value to a given MSR.
|
||||
static inline void asm_wrmsr(uint32_t msr, uint64_t val) {
|
||||
uint32_t eax = (uint32_t)val;
|
||||
uint32_t edx = val >> 32;
|
||||
asm volatile("wrmsr" : : "a"(eax), "d"(edx), "c"(msr) : "memory");
|
||||
}
|
||||
|
||||
// Writes a 64-bit value to a control register using XSETBV.
|
||||
static inline void asm_wrxcr(uint32_t reg, uint64_t val) {
|
||||
uint32_t eax = val;
|
||||
uint32_t edx = val >> 32;
|
||||
asm volatile("xsetbv" ::"a"(eax), "d"(edx), "c"(reg) : "memory");
|
||||
}
|
||||
|
||||
// Saves the FPU state to a 512-byte region of memory using FXSAVE.
|
||||
// Pointer must be 16-byte aligned.
|
||||
static inline void asm_fxsave(void* mem) {
|
||||
asm volatile("fxsave [%0]" ::"r"(mem) : "memory");
|
||||
}
|
||||
|
||||
// Restores the FPU state from a 512-byte region of memory using FXRSTOR.
|
||||
// Pointer must be 16-byte aligned.
|
||||
static inline void asm_fxrstor(const void* mem) {
|
||||
asm volatile("fxrstor [%0]" ::"r"(mem) : "memory");
|
||||
}
|
||||
|
||||
// Saves the FPU state to a region of memory using XSAVE.
|
||||
// Pointer must be 16-byte aligned.
|
||||
static inline void asm_xsave(void* mem) {
|
||||
asm volatile("xsave [%0]" ::"r"(mem) : "memory");
|
||||
}
|
||||
|
||||
// Restores the FPU state from a region of memory using XRSTOR.
|
||||
// Pointer must be 16-byte aligned.
|
||||
static inline void asm_xrstor(const void* mem) {
|
||||
asm volatile("xrstor [%0]" ::"r"(mem) : "memory");
|
||||
}
|
||||
|
||||
static inline uint8_t asm_inb(uint16_t port) {
|
||||
uint8_t result;
|
||||
asm volatile("in %0, %1" : "=a"(result) : "Nd"(port));
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline uint16_t asm_inw(uint16_t port) {
|
||||
uint16_t result;
|
||||
asm volatile("in %0, %1" : "=a"(result) : "Nd"(port));
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline uint32_t asm_inl(uint16_t port) {
|
||||
uint32_t result;
|
||||
asm volatile("in %0, %1" : "=a"(result) : "Nd"(port));
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline void asm_outb(uint16_t port, uint8_t value) {
|
||||
asm volatile("out %0, %1" : : "Nd"(port), "a"(value));
|
||||
}
|
||||
|
||||
static inline void asm_outw(uint16_t port, uint16_t value) {
|
||||
asm volatile("out %0, %1" : : "Nd"(port), "a"(value));
|
||||
}
|
||||
|
||||
static inline void asm_outl(uint16_t port, uint32_t value) {
|
||||
asm volatile("out %0, %1" : : "Nd"(port), "a"(value));
|
||||
}
|
||||
|
||||
static inline uint16_t asm_read_ds() {
|
||||
uint16_t value = 0;
|
||||
asm volatile("mov %0, ds" : "=r"(value));
|
||||
return value;
|
||||
}
|
||||
|
||||
static inline uint16_t asm_read_es() {
|
||||
uint16_t value = 0;
|
||||
asm volatile("mov %0, es" : "=r"(value));
|
||||
return value;
|
||||
}
|
||||
|
||||
static inline uint16_t asm_read_fs() {
|
||||
uint16_t value = 0;
|
||||
asm volatile("mov %0, fs" : "=r"(value));
|
||||
return value;
|
||||
}
|
||||
|
||||
static inline uint16_t asm_read_gs() {
|
||||
uint16_t value = 0;
|
||||
asm volatile("mov %0, gs" : "=r"(value));
|
||||
return value;
|
||||
}
|
||||
|
||||
static inline void asm_write_ds(uint16_t value) {
|
||||
asm volatile("mov ds, %0" ::"r"(value));
|
||||
}
|
||||
|
||||
static inline void asm_write_es(uint16_t value) {
|
||||
asm volatile("mov es, %0" ::"r"(value));
|
||||
}
|
||||
|
||||
static inline void asm_write_fs(uint16_t value) {
|
||||
asm volatile("mov fs, %0" ::"r"(value));
|
||||
}
|
||||
|
||||
static inline void asm_write_gs(uint16_t value) {
|
||||
asm volatile("mov gs, %0" ::"r"(value));
|
||||
}
|
||||
@@ -0,0 +1,201 @@
|
||||
#pragma once
|
||||
|
||||
#define CPUID_1C_SSE3 (1 << 0)
|
||||
#define CPUID_1C_PCLMUL (1 << 1)
|
||||
#define CPUID_1C_DTES64 (1 << 2)
|
||||
#define CPUID_1C_MONITOR (1 << 3)
|
||||
#define CPUID_1C_DS_CPL (1 << 4)
|
||||
#define CPUID_1C_VMX (1 << 5)
|
||||
#define CPUID_1C_SMX (1 << 6)
|
||||
#define CPUID_1C_EST (1 << 7)
|
||||
#define CPUID_1C_TM2 (1 << 8)
|
||||
#define CPUID_1C_SSSE3 (1 << 9)
|
||||
#define CPUID_1C_CID (1 << 10)
|
||||
#define CPUID_1C_SDBG (1 << 11)
|
||||
#define CPUID_1C_FMA (1 << 12)
|
||||
#define CPUID_1C_CX16 (1 << 13)
|
||||
#define CPUID_1C_XTPR (1 << 14)
|
||||
#define CPUID_1C_PDCM (1 << 15)
|
||||
#define CPUID_1C_PCID (1 << 17)
|
||||
#define CPUID_1C_DCA (1 << 18)
|
||||
#define CPUID_1C_SSE4_1 (1 << 19)
|
||||
#define CPUID_1C_SSE4_2 (1 << 20)
|
||||
#define CPUID_1C_X2APIC (1 << 21)
|
||||
#define CPUID_1C_MOVBE (1 << 22)
|
||||
#define CPUID_1C_POPCNT (1 << 23)
|
||||
#define CPUID_1C_TSC (1 << 24)
|
||||
#define CPUID_1C_AES (1 << 25)
|
||||
#define CPUID_1C_XSAVE (1 << 26)
|
||||
#define CPUID_1C_OSXSAVE (1 << 27)
|
||||
#define CPUID_1C_AVX (1 << 28)
|
||||
#define CPUID_1C_F16C (1 << 29)
|
||||
#define CPUID_1C_RDRAND (1 << 30)
|
||||
#define CPUID_1C_HYPERVISOR (1 << 31)
|
||||
|
||||
#define CPUID_1D_FPU (1 << 0)
|
||||
#define CPUID_1D_VME (1 << 1)
|
||||
#define CPUID_1D_DE (1 << 2)
|
||||
#define CPUID_1D_PSE (1 << 3)
|
||||
#define CPUID_1D_TSC (1 << 4)
|
||||
#define CPUID_1D_MSR (1 << 5)
|
||||
#define CPUID_1D_PAE (1 << 6)
|
||||
#define CPUID_1D_MCE (1 << 7)
|
||||
#define CPUID_1D_CX8 (1 << 8)
|
||||
#define CPUID_1D_APIC (1 << 9)
|
||||
#define CPUID_1D_SEP (1 << 11)
|
||||
#define CPUID_1D_MTRR (1 << 12)
|
||||
#define CPUID_1D_PGE (1 << 13)
|
||||
#define CPUID_1D_MCA (1 << 14)
|
||||
#define CPUID_1D_CMOV (1 << 15)
|
||||
#define CPUID_1D_PAT (1 << 16)
|
||||
#define CPUID_1D_PSE36 (1 << 17)
|
||||
#define CPUID_1D_PSN (1 << 18)
|
||||
#define CPUID_1D_CLFLUSH (1 << 19)
|
||||
#define CPUID_1D_DS (1 << 21)
|
||||
#define CPUID_1D_ACPI (1 << 22)
|
||||
#define CPUID_1D_MMX (1 << 23)
|
||||
#define CPUID_1D_FXSR (1 << 24)
|
||||
#define CPUID_1D_SSE (1 << 25)
|
||||
#define CPUID_1D_SSE2 (1 << 26)
|
||||
#define CPUID_1D_SS (1 << 27)
|
||||
#define CPUID_1D_HTT (1 << 28)
|
||||
#define CPUID_1D_TM (1 << 29)
|
||||
#define CPUID_1D_IA64 (1 << 30)
|
||||
#define CPUID_1D_PBE (1 << 31)
|
||||
|
||||
#define CPUID_7B_FSGSBASE (1 << 0)
|
||||
#define CPUID_7B_SGX (1 << 2)
|
||||
#define CPUID_7B_BMI (1 << 3)
|
||||
#define CPUID_7B_HLE (1 << 4)
|
||||
#define CPUID_7B_AVX2 (1 << 5)
|
||||
#define CPUID_7B_SMEP (1 << 7)
|
||||
#define CPUID_7B_BMI2 (1 << 8)
|
||||
#define CPUID_7B_RTM (1 << 11)
|
||||
#define CPUID_7B_AVX512F (1 << 16)
|
||||
#define CPUID_7B_AVX512DQ (1 << 17)
|
||||
#define CPUID_7B_RDSEED (1 << 18)
|
||||
#define CPUID_7B_ADX (1 << 19)
|
||||
#define CPUID_7B_SMAP (1 << 20)
|
||||
#define CPUID_7B_AVX512IFMA (1 << 21)
|
||||
#define CPUID_7B_CLFLUSHOPT (1 << 23)
|
||||
#define CPUID_7B_CLWB (1 << 24)
|
||||
#define CPUID_7B_AVX512CD (1 << 28)
|
||||
#define CPUID_7B_SHA (1 << 29)
|
||||
#define CPUID_7B_AVX512BW (1 << 30)
|
||||
#define CPUID_7B_AVX512VL (1 << 31)
|
||||
|
||||
#define CPUID_7C_AVX512VBMI (1 << 1)
|
||||
#define CPUID_7C_UMIP (1 << 2)
|
||||
#define CPUID_7C_PKU (1 << 3)
|
||||
#define CPUID_7C_OSPKE (1 << 4)
|
||||
#define CPUID_7C_WAITPKG (1 << 5)
|
||||
#define CPUID_7C_AVX512VBMI2 (1 << 6)
|
||||
#define CPUID_7C_SHSTK (1 << 7)
|
||||
#define CPUID_7C_GFNI (1 << 8)
|
||||
#define CPUID_7C_VAES (1 << 9)
|
||||
#define CPUID_7C_VPCLMULQDQ (1 << 10)
|
||||
#define CPUID_7C_AVX512VNNI (1 << 11)
|
||||
#define CPUID_7C_AVX512BITALG (1 << 12)
|
||||
#define CPUID_7C_TME_EN (1 << 13)
|
||||
#define CPUID_7C_AVX512VPOPCNTDQ (1 << 14)
|
||||
#define CPUID_7C_RDPID (1 << 22)
|
||||
#define CPUID_7C_KL (1 << 23)
|
||||
#define CPUID_7C_CLDEMOTE (1 << 25)
|
||||
#define CPUID_7C_MOVDIRI (1 << 27)
|
||||
#define CPUID_7C_MOVDIR64B (1 << 28)
|
||||
#define CPUID_7C_ENQCMD (1 << 29)
|
||||
|
||||
#define CPUID_7D_UINTR (1 << 5)
|
||||
#define CPUID_7D_AVX512VP2INTERSECT (1 << 8)
|
||||
#define CPUID_7D_SERIALIZE (1 << 14)
|
||||
#define CPUID_7D_TSXLDTRK (1 << 16)
|
||||
#define CPUID_7D_PCONFIG (1 << 18)
|
||||
#define CPUID_7D_IBT (1 << 20)
|
||||
#define CPUID_7D_AMX_BF16 (1 << 22)
|
||||
#define CPUID_7D_AVX512FP16 (1 << 23)
|
||||
#define CPUID_7D_AMX_TILE (1 << 24)
|
||||
#define CPUID_7D_AMX_INT8 (1 << 25)
|
||||
|
||||
#define RFLAGS_CF (1u << 0)
|
||||
#define RFLAGS_PF (1u << 2)
|
||||
#define RFLAGS_AF (1u << 4)
|
||||
#define RFLAGS_ZF (1u << 6)
|
||||
#define RFLAGS_SF (1u << 7)
|
||||
#define RFLAGS_TF (1u << 8)
|
||||
#define RFLAGS_IF (1u << 9)
|
||||
#define RFLAGS_DF (1u << 10)
|
||||
#define RFLAGS_OF (1u << 11)
|
||||
#define RFLAGS_IOPL (3u << 12)
|
||||
#define RFLAGS_NT (1u << 14)
|
||||
#define RFLAGS_RF (1u << 16)
|
||||
#define RFLAGS_VM (1u << 17)
|
||||
#define RFLAGS_AC (1u << 18)
|
||||
#define RFLAGS_VIF (1u << 19)
|
||||
#define RFLAGS_VIP (1u << 20)
|
||||
#define RFLAGS_ID (1u << 21)
|
||||
|
||||
#define XCR0_X87 (1 << 0)
|
||||
#define XCR0_SSE (1 << 1)
|
||||
#define XCR0_AVX (1 << 2)
|
||||
#define XCR0_AXV512_OPMASK (1 << 5)
|
||||
#define XCR0_AVX512_ZMM_HI256 (1 << 6)
|
||||
#define XCR0_AVX512_HI16_ZMM (1 << 7)
|
||||
|
||||
#define CR0_PE (1 << 0)
|
||||
#define CR0_MP (1 << 1)
|
||||
#define CR0_EM (1 << 2)
|
||||
#define CR0_TS (1 << 3)
|
||||
#define CR0_ET (1 << 4)
|
||||
#define CR0_NE (1 << 5)
|
||||
#define CR0_WP (1 << 16)
|
||||
#define CR0_AM (1 << 18)
|
||||
#define CR0_NW (1 << 29)
|
||||
#define CR0_CD (1 << 30)
|
||||
#define CR0_PG (1 << 31)
|
||||
|
||||
#define CR4_VME (1 << 0)
|
||||
#define CR4_PVI (1 << 1)
|
||||
#define CR4_TSD (1 << 2)
|
||||
#define CR4_DE (1 << 3)
|
||||
#define CR4_PSE (1 << 4)
|
||||
#define CR4_PAE (1 << 5)
|
||||
#define CR4_MCE (1 << 6)
|
||||
#define CR4_PGE (1 << 7)
|
||||
#define CR4_PCE (1 << 8)
|
||||
#define CR4_OSFXSR (1 << 9)
|
||||
#define CR4_OSXMMEXCPT (1 << 10)
|
||||
#define CR4_UMIP (1 << 11)
|
||||
#define CR4_VMXE (1 << 13)
|
||||
#define CR4_SMXE (1 << 14)
|
||||
#define CR4_FSGSBASE (1 << 16)
|
||||
#define CR4_PCIDE (1 << 17)
|
||||
#define CR4_OSXSAVE (1 << 18)
|
||||
#define CR4_SMEP (1 << 20)
|
||||
#define CR4_SMAP (1 << 21)
|
||||
#define CR4_PKE (1 << 22)
|
||||
#define CR4_CET (1 << 23)
|
||||
#define CR4_PKS (1 << 24)
|
||||
|
||||
#define MSR_EFER_SCE (1 << 0)
|
||||
#define MSR_EFER_LME (1 << 8)
|
||||
#define MSR_EFER_LMA (1 << 10)
|
||||
#define MSR_EFER_NXE (1 << 11)
|
||||
#define MSR_EFER_SVME (1 << 12)
|
||||
#define MSR_EFER_LMSLE (1 << 13)
|
||||
#define MSR_EFER_FFXSR (1 << 14)
|
||||
#define MSR_EFER_TCE (1 << 15)
|
||||
|
||||
#define MSR_EFER (0xC0000080)
|
||||
#define MSR_STAR (0xC0000081)
|
||||
#define MSR_LSTAR (0xC0000082)
|
||||
#define MSR_CSTAR (0xC0000083)
|
||||
#define MSR_SFMASK (0xC0000084)
|
||||
#define MSR_FS_BASE (0xC0000100)
|
||||
#define MSR_GS_BASE (0xC0000101)
|
||||
#define MSR_KERNEL_GS_BASE (0xC0000102)
|
||||
|
||||
#define CPL_USER (0b11)
|
||||
#define CPL_KERNEL (0b00)
|
||||
|
||||
#define IDT_PF (0xE)
|
||||
#define IDT_IPI_RESCHED (0xFF)
|
||||
@@ -0,0 +1,56 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <zinnia/compiler.h>
|
||||
|
||||
union gdt_desc {
|
||||
uint64_t val;
|
||||
struct {
|
||||
uint16_t limit0;
|
||||
uint16_t base0;
|
||||
uint8_t base1;
|
||||
uint8_t access;
|
||||
uint8_t limit1_flags;
|
||||
uint8_t base2;
|
||||
};
|
||||
};
|
||||
|
||||
static_assert(sizeof(union gdt_desc) == 0x8);
|
||||
|
||||
union gdt_long_desc {
|
||||
uint64_t val[2];
|
||||
struct {
|
||||
uint16_t limit0;
|
||||
uint16_t base0;
|
||||
uint8_t base1;
|
||||
uint8_t access;
|
||||
uint8_t limit1_flags;
|
||||
uint8_t base2;
|
||||
uint32_t base3;
|
||||
uint32_t reserved;
|
||||
};
|
||||
};
|
||||
|
||||
static_assert(sizeof(union gdt_long_desc) == 0x10);
|
||||
|
||||
struct [[__packed]] gdt {
|
||||
union gdt_desc null;
|
||||
union gdt_desc kernel_code32;
|
||||
union gdt_desc kernel_data32;
|
||||
union gdt_desc kernel_code64;
|
||||
union gdt_desc kernel_data64;
|
||||
union gdt_desc user_code32;
|
||||
union gdt_desc user_data;
|
||||
union gdt_desc user_code64;
|
||||
union gdt_long_desc tss;
|
||||
};
|
||||
|
||||
struct [[__packed]] gdtr {
|
||||
uint16_t limit;
|
||||
struct gdt* base;
|
||||
};
|
||||
|
||||
struct percpu;
|
||||
|
||||
// Initializes a GDT on the local CPU.
|
||||
void gdt_load();
|
||||
@@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
void hpet_init();
|
||||
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <zinnia/init.h>
|
||||
|
||||
[[__init]]
|
||||
void idt_init();
|
||||
|
||||
// Loads the IDT on this CPU.
|
||||
void idt_load();
|
||||
|
||||
void interrupt_return();
|
||||
@@ -0,0 +1,49 @@
|
||||
#pragma once
|
||||
|
||||
#define SMP_GDTR_OFFSET 80
|
||||
#define SMP_FARJMP_OFFSET 90
|
||||
#define SMP_TEMP_STACK_OFFSET 98
|
||||
#define SMP_TEMP_CR3_OFFSET 102
|
||||
#define SMP_ENTRY_OFFSET 106
|
||||
#define SMP_HHDM_OFFSET 114
|
||||
#define SMP_KERNEL32_DS 16
|
||||
#define SMP_KERNEL64_CS 24
|
||||
#define SMP_KERNEL64_DS 32
|
||||
#define SMP_INFO_SIZE 127
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <x86_64/gdt.h>
|
||||
#include <zinnia/compiler.h>
|
||||
#include <zinnia/utils.h>
|
||||
|
||||
struct [[__packed]] smp_info {
|
||||
struct gdt gdt;
|
||||
struct gdtr gdtr;
|
||||
uint32_t farjmp_offset;
|
||||
uint32_t farjmp_segment;
|
||||
uint32_t temp_stack;
|
||||
uint32_t temp_cr3;
|
||||
uint64_t entry;
|
||||
uint64_t hhdm_offset;
|
||||
uint32_t lapic_id;
|
||||
uint8_t booted;
|
||||
};
|
||||
|
||||
static_assert(SMP_GDTR_OFFSET == offsetof(struct smp_info, gdtr));
|
||||
static_assert(SMP_FARJMP_OFFSET == offsetof(struct smp_info, farjmp_offset));
|
||||
static_assert(SMP_TEMP_STACK_OFFSET == offsetof(struct smp_info, temp_stack));
|
||||
static_assert(SMP_TEMP_CR3_OFFSET == offsetof(struct smp_info, temp_cr3));
|
||||
static_assert(SMP_ENTRY_OFFSET == offsetof(struct smp_info, entry));
|
||||
static_assert(SMP_HHDM_OFFSET == offsetof(struct smp_info, hhdm_offset));
|
||||
static_assert(SMP_KERNEL32_DS == offsetof(struct gdt, kernel_data32));
|
||||
static_assert(SMP_KERNEL64_CS == offsetof(struct gdt, kernel_code64));
|
||||
static_assert(SMP_KERNEL64_DS == offsetof(struct gdt, kernel_data64));
|
||||
static_assert(SMP_INFO_SIZE == sizeof(struct smp_info));
|
||||
|
||||
// Initializes a LAPIC.
|
||||
void x86_64_smp_init(uint32_t id);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
void arch_syscall_stub();
|
||||
@@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
void tsc_init();
|
||||
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <zinnia/compiler.h>
|
||||
|
||||
struct [[__packed]] tss {
|
||||
uint32_t reserved0;
|
||||
uint64_t rsp0;
|
||||
uint64_t rsp1;
|
||||
uint64_t rsp2;
|
||||
uint32_t reserved1;
|
||||
uint32_t reserved2;
|
||||
uint64_t ist1;
|
||||
uint64_t ist2;
|
||||
uint64_t ist3;
|
||||
uint64_t ist4;
|
||||
uint64_t ist5;
|
||||
uint64_t ist6;
|
||||
uint64_t ist7;
|
||||
uint32_t reserved3;
|
||||
uint32_t reserved4;
|
||||
uint16_t reserved5;
|
||||
uint16_t iopb;
|
||||
};
|
||||
|
||||
static_assert(sizeof(struct tss) == 0x68);
|
||||
Reference in New Issue
Block a user