#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace arch { [[gnu::weak]] void disable_interrupts() { asm volatile("cli"); } [[gnu::weak]] void enable_interrupts() { asm volatile("sti"); } [[gnu::weak]] void wait_for_interrupt() { asm volatile("hlt"); } [[gnu::weak]] void hcf() { disable_interrupts(); while(true) { wait_for_interrupt(); } } [[gnu::weak]] void pause() { asm volatile("pause"); } [[gnu::weak]] std::uint64_t current_root() { std::uint64_t cr3; asm volatile("mov %%cr3, %0" : "=r"(cr3) : : "memory"); return cr3; } [[gnu::weak]] void tlb_flush(std::uintptr_t hint, std::uintptr_t len) { if (len / PAGE_SIZE > 256 || len == 0) { std::uint64_t cr3 = 0; asm volatile("mov %%cr3, %0" : "=r"(cr3) : : "memory"); asm volatile("mov %0, %%cr3" : : "r"(cr3) : "memory"); } else { for (std::uintptr_t i = 0; i < len; i += PAGE_SIZE) { asm volatile("invlpg (%0)" : : "b"(hint + i) : "memory"); } } } [[gnu::weak]] const char* name() { return "x86_64"; } [[gnu::weak]] int level_paging() { return bootloader::bootloader->is_5_level_paging() ? 5 : 4; } [[gnu::weak]] void init(int stage) { switch(stage) { case ARCH_INIT_EARLY: x86_64::init_cpu_data(); drivers::hpet::init(); drivers::tsc::init(); drivers::pvclock::bsp_init(); assert(time::timer != nullptr, "can't init orange without timer !"); x86_64::gdt::init(); x86_64::idt::init(); x86_64::lapic::init(1500); drivers::ioapic::init(); x86_64::schedule_timer::init(); x86_64::sse::init(); x86_64::sse::print_sse_features(); return; case ARCH_INIT_MP: enable_paging(gobject::kernel_root); x86_64::init_cpu_data(); drivers::tsc::init(); drivers::pvclock::init(); x86_64::gdt::init(); x86_64::idt::init(); x86_64::lapic::init(1500); x86_64::schedule_timer::init(); x86_64::sse::init(); return; case ARCH_INIT_COMMON: return; } } [[gnu::weak]] void panic(char* msg) { klibc::printf("Panic with message \"%s\"\r\n",msg); arch::hcf(); } [[gnu::weak]] void memory_barrier() { asm volatile("lfence" ::: "memory"); } [[gnu::weak]] int register_handler(int irq, int type, std::uint64_t flags, void (*func)(void* arg), void* arg) { return x86_64::irq::create(irq,type,func,arg,flags); } [[gnu::weak]] bool test_interrupts() { uint64_t rflags; __asm__ __volatile__ ( "pushfq\n\t" "pop %0" : "=rm" (rflags): : "memory" ); return (rflags & (1 << 9)) != 0; } }