Viewing: cpu.c
📄 cpu.c (Read Only) ⬅ To go back
#include "hal/cpu.h"

#include "arch/x86/gdt.h"

#if defined(__i386__) || defined(__x86_64__)

uintptr_t hal_cpu_get_stack_pointer(void) {
    uintptr_t sp;
#if defined(__x86_64__)
    __asm__ volatile("mov %%rsp, %0" : "=r"(sp));
#else
    __asm__ volatile("mov %%esp, %0" : "=r"(sp));
#endif
    return sp;
}

uintptr_t hal_cpu_get_address_space(void) {
    uintptr_t as;
#if defined(__x86_64__)
    __asm__ volatile("mov %%cr3, %0" : "=r"(as));
#else
    __asm__ volatile("mov %%cr3, %0" : "=r"(as));
#endif
    return as;
}

void hal_cpu_set_address_space(uintptr_t as) {
#if defined(__x86_64__)
    __asm__ volatile("mov %0, %%cr3" : : "r"(as) : "memory");
#else
    __asm__ volatile("mov %0, %%cr3" : : "r"(as) : "memory");
#endif
}

void hal_cpu_set_kernel_stack(uintptr_t sp_top) {
    tss_set_kernel_stack(sp_top);
}

void hal_cpu_enable_interrupts(void) {
    __asm__ volatile("sti");
}

void hal_cpu_disable_interrupts(void) {
    __asm__ volatile("cli");
}

void hal_cpu_idle(void) {
    __asm__ volatile("hlt");
}

uint64_t hal_cpu_read_timestamp(void) {
    uint32_t lo, hi;
    __asm__ volatile("rdtsc" : "=a"(lo), "=d"(hi));
    return ((uint64_t)hi << 32) | lo;
}

void hal_cpu_set_tls(uintptr_t base) {
    /* GDT entry 22: user TLS segment (ring 3, data RW) */
    gdt_set_gate_ext(22, (uint32_t)base, 0xFFFFF, 0xF2, 0xCF);
    /* Do NOT reload GS here — kernel GS must stay as percpu selector.
     * The user TLS GS (selector 0xB3) is loaded when returning to ring3
     * via the saved register state on the interrupt/syscall stack. */
}

#else

uintptr_t hal_cpu_get_stack_pointer(void) {
    return 0;
}

uintptr_t hal_cpu_get_address_space(void) {
    return 0;
}

void hal_cpu_set_address_space(uintptr_t as) {
    (void)as;
}

void hal_cpu_set_kernel_stack(uintptr_t sp_top) {
    (void)sp_top;
}

void hal_cpu_enable_interrupts(void) {
}

void hal_cpu_disable_interrupts(void) {
}

void hal_cpu_idle(void) {
}

uint64_t hal_cpu_read_timestamp(void) {
    return 0;
}

void hal_cpu_set_tls(uintptr_t base) {
    (void)base;
}

#endif