// MIT License, Copyright (c) 2020 Marvin Borner // This file is a wrapper around some CPU asm calls #include #include #include u8 inb(u16 port) { u8 value; __asm__ volatile("inb %1, %0" : "=a"(value) : "Nd"(port)); return value; } u16 inw(u16 port) { u16 value; __asm__ volatile("inw %1, %0" : "=a"(value) : "Nd"(port)); return value; } u32 inl(u16 port) { u32 value; __asm__ volatile("inl %1, %0" : "=a"(value) : "Nd"(port)); return value; } void insl(u16 port, void *addr, int n) { __asm__ volatile("rep insl" ::"c"(n), // Count "d"(port), // Port # "D"(addr)); // Buffer } void outb(u16 port, u8 data) { __asm__ volatile("outb %0, %1" ::"a"(data), "Nd"(port)); } void outw(u16 port, u16 data) { __asm__ volatile("outw %0, %1" ::"a"(data), "Nd"(port)); } void outl(u16 port, u32 data) { __asm__ volatile("outl %0, %1" ::"a"(data), "Nd"(port)); } #ifdef kernel static void cpuid(int code, u32 *a, u32 *b, u32 *c, u32 *d) { __asm__ volatile("cpuid" : "=a"(*a), "=b"(*b), "=c"(*c), "=d"(*d) : "a"(code)); } static char *cpu_string(char buf[16]) { // wtf cpuid(CPUID_VENDOR_STRING, (u32 *)(buf + 12), (u32 *)(buf), (u32 *)(buf + 8), (u32 *)(buf + 4)); return buf; } void cpu_print(void) { char buf[16] = { 0 }; printf("CPU vendor: %s\n", cpu_string(buf)); } u32 cr0_get(void) { u32 cr0; __asm__ volatile("movl %%cr0, %%eax" : "=a"(cr0)); return cr0; } void cr0_set(u32 cr0) { __asm__ volatile("movl %%eax, %%cr0" ::"a"(cr0)); } u32 cr3_get(void) { u32 cr3; __asm__ volatile("movl %%cr0, %%eax" : "=a"(cr3)); return cr3; } void cr3_set(u32 cr3) { __asm__ volatile("movl %%eax, %%cr3" ::"a"(cr3)); } u32 cr4_get(void) { u32 cr4; __asm__ volatile("movl %%cr4, %%eax" : "=a"(cr4)); return cr4; } void cr4_set(u32 cr4) { __asm__ volatile("movl %%eax, %%cr4" ::"a"(cr4)); } static u32 cpu_cfeatures = 0; u8 cpu_has_cfeature(enum cpuid_features feature) { return (cpu_cfeatures & feature) != 0; } static u32 cpu_dfeatures = 0; u8 cpu_has_dfeature(enum cpuid_features feature) { return (cpu_dfeatures & feature) != 0; } static void fpu_handler(struct regs *r) { UNUSED(r); __asm__ volatile("clts"); } static u8 fpu_state[512] ALIGNED(16); void fpu_restore(void) { __asm__ volatile("fxrstor (%0)" ::"r"(fpu_state)); } void cpu_enable_features(void) { u32 a, b, c, d; cpuid(CPUID_FEATURES, &a, &b, &c, &d); cpu_cfeatures = c; cpu_dfeatures = d; if (cpu_has_dfeature(CPUID_FEAT_EDX_SSE)) { cr0_set(cr0_get() & ~(1 << 2)); cr0_set(cr0_get() | (1 << 1)); cr4_set(cr4_get() | (3 << 9)); } else { panic("No SSE support!\n"); } if (cpu_has_dfeature(CPUID_FEAT_EDX_FPU)) { __asm__ volatile("fninit"); __asm__ volatile("fxsave %0" : "=m"(fpu_state)); irq_install_handler(7, fpu_handler); } else { panic("No FPU support!\n"); } } void cli(void) { __asm__ volatile("cli"); } void sti(void) { __asm__ volatile("sti"); } void hlt(void) { __asm__ volatile("hlt"); } void idle(void) { while (1) hlt(); } void loop(void) { cli(); idle(); } #endif