major refactorings

Signed-off-by: kaguya3311 <kaguya3311@national.shitposting.agency>
This commit is contained in:
kaguya
2026-05-18 04:02:59 -04:00
parent f7aa6f913a
commit b28a6bcf29
211 changed files with 17699 additions and 8107 deletions
+39 -8
View File
@@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.16) cmake_minimum_required(VERSION 3.16)
project(KirkOS C ASM) project(KirkOS C ASM_NASM)
set(VERSION 1) set(VERSION 1)
set(PATCHLEVEL 0) set(PATCHLEVEL 0)
@@ -17,9 +17,11 @@ message(STATUS "Building KirkOS version: ${KIRKOS_VERSION_STRING}")
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
set(CMAKE_ASM_NASM_OBJECT_FORMAT elf64)
file(GLOB_RECURSE KIRKOS_SOURCES file(GLOB_RECURSE KIRKOS_SOURCES
"${CMAKE_SOURCE_DIR}/src/*.c" "${CMAKE_SOURCE_DIR}/src/*.c"
"${CMAKE_SOURCE_DIR}/src/*.S" "${CMAKE_SOURCE_DIR}/src/*.asm"
) )
@@ -51,6 +53,7 @@ target_compile_definitions(KirkOS PRIVATE
add_custom_command( add_custom_command(
OUTPUT ${ISO_ROOT}/boot/KirkOS OUTPUT ${ISO_ROOT}/boot/KirkOS
DEPENDS KirkOS DEPENDS KirkOS
@@ -68,6 +71,7 @@ add_custom_target(limine_files
COMMAND ${CMAKE_COMMAND} -E make_directory ${ISO_ROOT}/EFI/BOOT COMMAND ${CMAKE_COMMAND} -E make_directory ${ISO_ROOT}/EFI/BOOT
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/limine.conf ${ISO_ROOT}/boot/limine/ COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/limine.conf ${ISO_ROOT}/boot/limine/
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/ramdisk.tar ${ISO_ROOT}/boot/
COMMAND ${CMAKE_COMMAND} -E copy ${LIMINE_DIR}/limine-bios.sys ${ISO_ROOT}/boot/limine/ COMMAND ${CMAKE_COMMAND} -E copy ${LIMINE_DIR}/limine-bios.sys ${ISO_ROOT}/boot/limine/
COMMAND ${CMAKE_COMMAND} -E copy ${LIMINE_DIR}/limine-bios-cd.bin ${ISO_ROOT}/boot/limine/ COMMAND ${CMAKE_COMMAND} -E copy ${LIMINE_DIR}/limine-bios-cd.bin ${ISO_ROOT}/boot/limine/
COMMAND ${CMAKE_COMMAND} -E copy ${LIMINE_DIR}/limine-uefi-cd.bin ${ISO_ROOT}/boot/limine/ COMMAND ${CMAKE_COMMAND} -E copy ${LIMINE_DIR}/limine-uefi-cd.bin ${ISO_ROOT}/boot/limine/
@@ -106,9 +110,9 @@ add_custom_target(run
COMMAND qemu-system-x86_64 COMMAND qemu-system-x86_64
-cdrom ${ISO} -cdrom ${ISO}
-hda ${DISK_IMG} -hda ${DISK_IMG}
-debugcon stdio -serial stdio
-m 8G -m 8G
-smp 2 -smp 4
-device ich9-intel-hda -device ich9-intel-hda
-device hda-duplex -device hda-duplex
-cpu qemu64,+fsgsbase -cpu qemu64,+fsgsbase
@@ -119,7 +123,7 @@ add_custom_target(debug
COMMAND qemu-system-x86_64 COMMAND qemu-system-x86_64
-cdrom ${ISO} -cdrom ${ISO}
-hda ${DISK_IMG} -hda ${DISK_IMG}
-debugcon stdio -serial stdio
-s -S -s -S
-d int,cpu_reset -d int,cpu_reset
-m 8G -m 8G
@@ -129,6 +133,20 @@ add_custom_target(debug
-cpu qemu64,+fsgsbase -cpu qemu64,+fsgsbase
) )
add_custom_command(TARGET KirkOS POST_BUILD
COMMAND ${CMAKE_OBJCOPY} --only-keep-debug
$<TARGET_FILE:KirkOS>
${CMAKE_BINARY_DIR}/KirkOS.sym
COMMAND ${CMAKE_OBJCOPY} --strip-debug
$<TARGET_FILE:KirkOS>
COMMAND ${CMAKE_OBJCOPY} --add-gnu-debuglink=${CMAKE_BINARY_DIR}/KirkOS.sym
$<TARGET_FILE:KirkOS>
COMMENT "Splitting debug symbols (KirkOS.sym)"
)
target_include_directories(KirkOS PRIVATE target_include_directories(KirkOS PRIVATE
"${CMAKE_SOURCE_DIR}/src" "${CMAKE_SOURCE_DIR}/src"
) )
@@ -137,10 +155,13 @@ target_include_directories(KirkOS PRIVATE
# ---------------------------------------- # ----------------------------------------
# DEFAULT C FLAGS (cacheable overrides) # DEFAULT C FLAGS (cacheable overrides)
# ---------------------------------------- # ----------------------------------------
set(KIRKOS_CFLAGS "-g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fno-PIC -ffunction-sections -fdata-sections -m64 -march=x86-64 -mabi=sysv -mno-80387 -mno-red-zone -mcmodel=kernel" set(KIRKOS_CFLAGS "-g3 -m64 -march=x86-64 -mgeneral-regs-only -fsanitize=undefined -Wall -Wextra -Wno-error -Wno-builtin-declaration-mismatch -mno-red-zone -std=gnu11 -fms-extensions -ffreestanding -fno-stack-protector -fno-stack-check -fpie -MMD"
CACHE STRING "Default CFLAGS for KirkOS") CACHE STRING "Default CFLAGS for KirkOS")
set(KIRKOS_LDFLAGS "-nostdlib -static -Wl,--gc-sections -Wl,-T,../linker.lds -Wl,-z,max-page-size=0x1000 -Wl,-m,elf_x86_64" set(KIRKOS_ASM_NASM_FLAGS "-MD -MP -f elf64 -g"
CACHE STRING "Default ASM Flags for NASM in KirkOS")
set(KIRKOS_LDFLAGS "-nostdlib -Wl,-static,-pie -Wl,--gc-sections -Wl,--no-dynamic-linker -Wl,-z,max-page-size=0x1000 -Wl,-T../linker.lds -Wl,-m,elf_x86_64"
CACHE STRING "Default LDFLAGS for KirkOS") CACHE STRING "Default LDFLAGS for KirkOS")
# ---------------------------------------- # ----------------------------------------
@@ -149,5 +170,15 @@ set(KIRKOS_LDFLAGS "-nostdlib -static -Wl,--gc-sections -Wl,-T,../linker.lds -Wl
separate_arguments(_cflags UNIX_COMMAND "${KIRKOS_CFLAGS}") separate_arguments(_cflags UNIX_COMMAND "${KIRKOS_CFLAGS}")
separate_arguments(_ldflags UNIX_COMMAND "${KIRKOS_LDFLAGS}") separate_arguments(_ldflags UNIX_COMMAND "${KIRKOS_LDFLAGS}")
target_compile_options(KirkOS PRIVATE ${_cflags}) separate_arguments(_asmflags UNIX_COMMAND "${KIRKOS_ASM_NASM_FLAGS}")
set_target_properties(KirkOS PROPERTIES
LINK_FLAGS "-Wl,--build-id=none"
)
target_compile_options(KirkOS PRIVATE
$<$<COMPILE_LANGUAGE:C>:-masm=intel>
$<$<COMPILE_LANGUAGE:C>:${_cflags}>
$<$<COMPILE_LANGUAGE:ASM_NASM>:${_asmflags}>
)
target_link_options(KirkOS PRIVATE ${_ldflags}) target_link_options(KirkOS PRIVATE ${_ldflags})
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
+1
View File
@@ -6,5 +6,6 @@
#define HOST_NAME_MAX 64 #define HOST_NAME_MAX 64
#define NAME_MAX 255 #define NAME_MAX 255
#define OPEN_MAX 256 #define OPEN_MAX 256
#define _POSIX_PATH_MAX 256
#endif /*_ABIBITS_LIMITS_H */ #endif /*_ABIBITS_LIMITS_H */
@@ -1,8 +0,0 @@
#ifndef _ABIBITS_SIGSET_T_H
#define _ABIBITS_SIGSET_T_H
typedef struct {
unsigned long __sig[1024 / (8 * sizeof(long))];
} sigset_t;
#endif /* _ABIBITS_SIGSET_T_H */
+20
View File
@@ -0,0 +1,20 @@
#ifndef _ABIBITS_IOCTLS_H
#define _ABIBITS_IOCTLS_H
#define TIOCEXCL 0x540C
#define TIOCNXCL 0x540D
#define SIOCPROTOPRIVATE 0x89E0
#define SIOCGSTAMP 0x8906
#define SIOCGIFNAME 0x8910
#define SIOCGIFCONF 0x8912
#define SIOCGIFFLAGS 0x8913
#define SIOCSIFFLAGS 0x8914
#define SIOCGIFADDR 0x8915
#define SIOCGIFINDEX 0x8933
#define SIOCATMARK 0x8905
#define SIOCGIFHWADDR 0x8927
#define SIOCGIFBRDADDR 0x8919
#define SIOCGIFNETMASK 0x891B
#endif /* _ABIBITS_IOCTLS_H */
+1 -1
View File
@@ -264,7 +264,7 @@ unsigned int alarm(unsigned int __seconds);
int chdir(const char *__path); int chdir(const char *__path);
int chown(const char *__path, uid_t __uid, gid_t __gid); int chown(const char *__path, uid_t __uid, gid_t __gid);
int close(int __fd); int close(int __fd);
ssize_t confstr(int __name, char *__buf, size_t __size); size_t confstr(int __name, char *__buf, size_t __size);
char *ctermid(char *__s); char *ctermid(char *__s);
int dup(int __fd); int dup(int __fd);
int dup2(int __src_fd, int __dest_fd); int dup2(int __src_fd, int __dest_fd);
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+20 -5
View File
@@ -2,9 +2,24 @@
timeout: 5 timeout: 5
# The entry name that will be displayed in the boot menu. # The entry name that will be displayed in the boot menu.
/kirkOS /KirkOS
# We use the Limine boot protocol. //KirkOS
protocol: limine protocol: limine
kaslr: no
path: boot():/boot/kirkos
cmdline: kprintf
module_path: boot():/boot/ramdisk.tar
# Path to the kernel to boot. boot():/ represents the partition on which limine.conf is located. //KirkOS (Panic on deadlock)
path: boot():/boot/kirkos protocol: limine
kaslr: no
path: boot():/boot/kirkos
cmdline: kprintf panic-on-deadlock
module_path: boot():/ramdisk.tar
//KirkOS (NSA is watching me)
protocol: limine
kaslr: yes
path: boot():/boot/kirkos
cmdline: kprintf dont-trust-cpu-random-seed
module_path: boot():/ramdisk.tar
Binary file not shown.
+61 -28
View File
@@ -2,12 +2,14 @@
#include <uacpi/platform/arch_helpers.h> #include <uacpi/platform/arch_helpers.h>
#include "mm/memory.h" #include "mm/memory.h"
#include "arch/x86_64/cpu/io.h" #include "arch/x86_64/cpu/io.h"
#include "arch/x86_64/sys/irq.h"
#include "arch/x86_64/sys/pit.h" #include "arch/x86_64/sys/pit.h"
#include "arch/x86_64/sys/tsc.h" #include "arch/x86_64/sys/tsc.h"
#include <stdatomic.h> #include <stdatomic.h>
#include <stdarg.h> #include <stdarg.h>
#include "libk/debug.h"
#include "mm/vmm.h" #include "mm/vmm.h"
#include "arch/x86_64/sys/timer.h"
#include "arch/x86_64/boot/isr.h"
extern uint64_t g_rsdp_phys; extern uint64_t g_rsdp_phys;
@@ -70,19 +72,19 @@ void uacpi_kernel_unmap(void *addr, uacpi_size len)
static const char *uacpi_log_prefix(uacpi_log_level level) static const char *uacpi_log_prefix(uacpi_log_level level)
{ {
switch (level) { switch (level) {
case UACPI_LOG_DEBUG: return "[uACPI DBG ] "; case UACPI_LOG_DEBUG: return "[acpi] DBG: ";
case UACPI_LOG_TRACE: return "[uACPI TRC ] "; case UACPI_LOG_TRACE: return "[acpi] TRC: ";
case UACPI_LOG_INFO: return "[uACPI INFO] "; case UACPI_LOG_INFO: return "[acpi] INFO: ";
case UACPI_LOG_WARN: return "[uACPI WARN] "; case UACPI_LOG_WARN: return "[acpi] WARN: ";
case UACPI_LOG_ERROR: return "[uACPI ERR ] "; case UACPI_LOG_ERROR: return "[acpi] ERR: ";
default: return "[uACPI ] "; default: return "[acpi]: ";
} }
} }
#ifndef UACPI_FORMATTED_LOGGING #ifndef UACPI_FORMATTED_LOGGING
void uacpi_kernel_log(uacpi_log_level level, const uacpi_char *msg) void uacpi_kernel_log(uacpi_log_level level, const uacpi_char *msg)
{ {
printf("%s%s", uacpi_log_prefix(level), msg); kprintf("%s%s", uacpi_log_prefix(level), msg);
} }
#else #else
UACPI_PRINTF_DECL(2, 3) UACPI_PRINTF_DECL(2, 3)
@@ -97,7 +99,7 @@ void uacpi_kernel_log(uacpi_log_level level, const uacpi_char *fmt, ...)
void uacpi_kernel_vlog(uacpi_log_level level, const uacpi_char *fmt, void uacpi_kernel_vlog(uacpi_log_level level, const uacpi_char *fmt,
uacpi_va_list va) uacpi_va_list va)
{ {
printf("%s", uacpi_log_prefix(level)); kprintf("%s", uacpi_log_prefix(level));
vfprintf(fmt, va); vfprintf(fmt, va);
} }
#endif #endif
@@ -348,7 +350,7 @@ void uacpi_kernel_free(void *mem, uacpi_size size_hint)
*/ */
uacpi_u64 uacpi_kernel_get_nanoseconds_since_boot(void) uacpi_u64 uacpi_kernel_get_nanoseconds_since_boot(void)
{ {
return rdtsc() / (tsc_cycles_per_us / 1000); // rough ns return (rdtsc() * 1000ULL) / tsc_cycles_per_us;
} }
/** /**
@@ -368,13 +370,7 @@ void uacpi_kernel_stall(uacpi_u8 usec)
*/ */
void uacpi_kernel_sleep(uacpi_u64 msec) void uacpi_kernel_sleep(uacpi_u64 msec)
{ {
uint64_t start = g_Ticks; timer_sleep(msec);
uint64_t target = start + msec;
while (g_Ticks < target)
{
__asm__ volatile("hlt");
}
} }
typedef struct { atomic_flag flag; } uacpi_mutex_impl_t; typedef struct { atomic_flag flag; } uacpi_mutex_impl_t;
@@ -426,13 +422,26 @@ void uacpi_kernel_free_event(uacpi_handle handle)
uacpi_interrupt_state uacpi_kernel_disable_interrupts(void) uacpi_interrupt_state uacpi_kernel_disable_interrupts(void)
{ {
uint64_t flags; uint64_t flags;
asm volatile("pushfq; pop %0; cli" : "=r"(flags) :: "memory"); asm volatile(
"pushfq\n\t"
"pop %0\n\t"
"cli"
: "=r"(flags)
:
: "memory"
);
return (uacpi_interrupt_state)flags; return (uacpi_interrupt_state)flags;
} }
void uacpi_kernel_restore_interrupts(uacpi_interrupt_state state) void uacpi_kernel_restore_interrupts(uacpi_interrupt_state state)
{ {
asm volatile("push %0; popfq" :: "r"((uint64_t)state) : "memory", "cc"); asm volatile(
"push %0\n\t"
"popfq"
:
: "r"((uint64_t)state)
: "memory", "cc"
);
} }
@@ -542,10 +551,10 @@ uacpi_status uacpi_kernel_handle_firmware_request(uacpi_firmware_request *req)
{ {
switch (req->type) { switch (req->type) {
case UACPI_FIRMWARE_REQUEST_TYPE_BREAKPOINT: case UACPI_FIRMWARE_REQUEST_TYPE_BREAKPOINT:
printf("[uACPI] AML Breakpoint\n"); kprintf("[uACPI] AML Breakpoint\n");
return UACPI_STATUS_OK; return UACPI_STATUS_OK;
case UACPI_FIRMWARE_REQUEST_TYPE_FATAL: case UACPI_FIRMWARE_REQUEST_TYPE_FATAL:
printf("[uACPI] AML Fatal! type=0x%x code=0x%x arg=0x%lx\n", kprintf("[uACPI] AML Fatal! type=0x%x code=0x%x arg=0x%lx\n",
req->fatal.type, req->fatal.code, req->fatal.type, req->fatal.code,
(unsigned long)req->fatal.arg); (unsigned long)req->fatal.arg);
for (;;) asm volatile("hlt"); for (;;) asm volatile("hlt");
@@ -573,9 +582,9 @@ typedef struct {
static uacpi_irq_entry_t uacpi_irq_table[UACPI_MAX_IRQS]; static uacpi_irq_entry_t uacpi_irq_table[UACPI_MAX_IRQS];
static void uacpi_irq_shim(Registers *regs) static void uacpi_irq_shim(registers_t *regs)
{ {
int irq = (int)regs->interrupt - 0x20; /* PIC_REMAP_OFFSET */ int irq = (int)regs->isrNumber - 0x20; /* PIC_REMAP_OFFSET */
if ((unsigned)irq < UACPI_MAX_IRQS && uacpi_irq_table[irq].fn) if ((unsigned)irq < UACPI_MAX_IRQS && uacpi_irq_table[irq].fn)
uacpi_irq_table[irq].fn(uacpi_irq_table[irq].ctx); uacpi_irq_table[irq].fn(uacpi_irq_table[irq].ctx);
} }
@@ -589,7 +598,7 @@ uacpi_status uacpi_kernel_install_interrupt_handler(
uacpi_irq_table[irq].fn = handler; uacpi_irq_table[irq].fn = handler;
uacpi_irq_table[irq].ctx = ctx; uacpi_irq_table[irq].ctx = ctx;
x86_64_IRQ_RegisterHandler((int)irq, uacpi_irq_shim); isr_register_handler((int)irq, uacpi_irq_shim);
/* Return a non-NULL token the caller can pass to uninstall */ /* Return a non-NULL token the caller can pass to uninstall */
*out_irq_handle = (uacpi_handle)(uintptr_t)(irq + 1); *out_irq_handle = (uacpi_handle)(uintptr_t)(irq + 1);
@@ -610,7 +619,7 @@ uacpi_status uacpi_kernel_uninstall_interrupt_handler(
uacpi_irq_table[irq].fn = NULL; uacpi_irq_table[irq].fn = NULL;
uacpi_irq_table[irq].ctx = NULL; uacpi_irq_table[irq].ctx = NULL;
x86_64_IRQ_RegisterHandler((int)irq, NULL); isr_register_handler((int)irq, NULL);
return UACPI_STATUS_OK; return UACPI_STATUS_OK;
} }
@@ -646,18 +655,42 @@ void uacpi_kernel_free_spinlock(uacpi_handle handle)
uacpi_cpu_flags uacpi_kernel_lock_spinlock(uacpi_handle handle) uacpi_cpu_flags uacpi_kernel_lock_spinlock(uacpi_handle handle)
{ {
uint64_t flags; uint64_t flags;
asm volatile("pushfq; pop %0; cli" : "=r"(flags) :: "memory");
asm volatile(
"pushfq\n\t"
"pop %0\n\t"
"cli"
: "=r"(flags)
:
: "memory"
);
uacpi_spinlock_impl_t *sl = handle; uacpi_spinlock_impl_t *sl = handle;
while (atomic_flag_test_and_set_explicit(&sl->flag, memory_order_acquire)) while (atomic_flag_test_and_set_explicit(&sl->flag, memory_order_acquire))
asm volatile("pause" ::: "memory"); asm volatile(
"pause"
:
:
: "memory"
);
return (uacpi_cpu_flags)flags; return (uacpi_cpu_flags)flags;
} }
void uacpi_kernel_unlock_spinlock(uacpi_handle handle, uacpi_cpu_flags saved) void uacpi_kernel_unlock_spinlock(uacpi_handle handle, uacpi_cpu_flags saved)
{ {
uacpi_spinlock_impl_t *sl = handle; uacpi_spinlock_impl_t *sl = handle;
atomic_flag_clear_explicit(&sl->flag, memory_order_release); atomic_flag_clear_explicit(&sl->flag, memory_order_release);
asm volatile("push %0; popfq" :: "r"((uint64_t)saved) : "memory", "cc");
asm volatile(
"push %0\n\t"
"popfq"
:
: "r"((uint64_t)saved)
: "memory", "cc"
);
} }
typedef enum uacpi_work_type { typedef enum uacpi_work_type {
+20 -5
View File
@@ -2,9 +2,24 @@
timeout: 5 timeout: 5
# The entry name that will be displayed in the boot menu. # The entry name that will be displayed in the boot menu.
/kirkOS /KirkOS
# We use the Limine boot protocol. //KirkOS
protocol: limine protocol: limine
kaslr: no
path: boot():/boot/KirkOS
cmdline: kprintf
module_path: boot():/boot/ramdisk.tar
# Path to the kernel to boot. boot():/ represents the partition on which limine.conf is located. //KirkOS (Panic on deadlock)
path: boot():/boot/KirkOS protocol: limine
kaslr: no
path: boot():/boot/KirkOS
cmdline: kprintf panic-on-deadlock
module_path: boot():/boot/ramdisk.tar
//KirkOS (NSA is watching me)
protocol: limine
kaslr: yes
path: boot():/boot/KirkOS
cmdline: kprintf dont-trust-cpu-random-seed
module_path: boot():/boot/ramdisk.tar
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+53 -66
View File
@@ -1,81 +1,68 @@
/* Tell the linker that we want an x86_64 ELF64 output file */ /* Tell the linker that we want an x86_64 ELF64 output file */
OUTPUT_FORMAT(elf64-x86-64) OUTPUT_FORMAT(elf64-x86-64)
OUTPUT_ARCH(i386:x86-64)
/* We want the symbol kmain to be our entry point */ /* We want the symbol arch_entry to be our entry point */
ENTRY(kmain) ENTRY(_entry)
/* Define the program headers we want so the bootloader gives us the right */ /* Define the program headers we want so the bootloader gives us the right */
/* MMU permissions; this also allows us to exert more control over the linking */ /* MMU permissions */
/* process. */ PHDRS {
PHDRS text PT_LOAD FLAGS((1 << 0) | (1 << 2)) ; /* Execute + Read */
{ rodata PT_LOAD FLAGS((1 << 2)) ; /* Read only */
limine_requests PT_LOAD; data PT_LOAD FLAGS((1 << 1) | (1 << 2)) ; /* Write + Read */
text PT_LOAD; dynamic PT_DYNAMIC FLAGS((1 << 1) | (1 << 2)) ; /* Dynamic segment needed for PIE */
rodata PT_LOAD;
data PT_LOAD;
} }
SECTIONS SECTIONS {
{ /* We wanna be placed in the topmost 2GiB of the address space, for optimisations */
/* We want to be placed in the topmost 2GiB of the address space, for optimisations */ /* and because that is what the Limine spec mandates. */
/* and because that is what the Limine spec mandates. */ /* Any address in this region will do, but often 0xffffffff80000000 is chosen as */
/* Any address in this region will do, but often 0xffffffff80000000 is chosen as */ /* that is the beginning of the region. */
/* that is the beginning of the region. */ . = 0xffffffff80000000;
. = 0xffffffff80000000;
/* Define a section to contain the Limine requests and assign it to its own PHDR */ text_start_addr = .;
.limine_requests : {
KEEP(*(.limine_requests_start))
KEEP(*(.limine_requests))
KEEP(*(.limine_requests_end))
} :limine_requests
/* Move to the next memory page for .text */ .text : {
. = ALIGN(CONSTANT(MAXPAGESIZE)); *(.text .text.*)
__text_start_addr = .; } :text
.text : {
*(.text .text.*)
} :text
__text_end_addr = .;
/* Move to the next memory page for .rodata */ text_end_addr = .;
. = ALIGN(CONSTANT(MAXPAGESIZE));
__rodata_start_addr = .;
.rodata : {
*(.rodata .rodata.*)
} :rodata
__rodata_end_addr = .;
/* Add a .note.gnu.build-id output section in case a build ID flag is added to the */ /* Move to the next memory page for .rodata */
/* linker command. */ . += CONSTANT(MAXPAGESIZE);
.note.gnu.build-id : {
*(.note.gnu.build-id)
} :rodata
/* Move to the next memory page for .data */ rodata_start_addr = .;
. = ALIGN(CONSTANT(MAXPAGESIZE));
__data_start_addr = .;
.data : {
*(.data .data.*)
} :data
__data_end_addr = .;
/* NOTE: .bss needs to be the last thing mapped to :data, otherwise lots of */ .rodata : {
/* unnecessary zeros will be written to the binary. */ *(.rodata .rodata.*)
/* If you need, for example, .init_array and .fini_array, those should be placed */ } :rodata
/* above this. */
__bss_start_addr = .;
.bss : {
*(.bss .bss.*)
*(COMMON)
} :data
__bss_end_addr = .;
__kernel_end = .; rodata_end_addr = .;
/* Discard .note.* and .eh_frame* since they may cause issues on some hosts. */ /* Move to the next memory page for .data */
/DISCARD/ : { . += CONSTANT(MAXPAGESIZE);
*(.eh_frame*)
*(.note .note.*) data_start_addr = .;
}
} .data : {
*(.data .data.*)
} :data
.dynamic : {
*(.dynamic)
} :data :dynamic
.bss : {
*(.bss .bss.*)
*(COMMON)
} :data
data_end_addr = .;
/* Discard notes and eh_frame since they may cause issues on some hosts. */
/DISCARD/ : {
*(.eh_frame)
*(.note .note.*)
}
}
+24 -23
View File
@@ -3,6 +3,7 @@
#include "mm/pmm.h" #include "mm/pmm.h"
#include "mm/memory.h" #include "mm/memory.h"
#include "libk/stdio.h" #include "libk/stdio.h"
#include "libk/debug.h"
/* ── Module globals ─────────────────────────────────────────────────────────── */ /* ── Module globals ─────────────────────────────────────────────────────────── */
@@ -78,7 +79,7 @@ static uint64_t hda_send_verb(uint32_t cmd)
return g_rirb[g_rirb_rp]; return g_rirb[g_rirb_rp];
} }
} }
printf("[HDA] verb timeout cmd=%08x\n", cmd); kprintf("[HDA] verb timeout cmd=%08x\n", cmd);
return (uint64_t)-1; return (uint64_t)-1;
} }
@@ -144,7 +145,7 @@ static bool corb_init(void)
if (r8(HDA_CORBCTL) & 0x02) return true; if (r8(HDA_CORBCTL) & 0x02) return true;
asm volatile("pause"); asm volatile("pause");
} }
printf("[HDA] CORB DMA failed to start\n"); kprintf("[HDA] CORB DMA failed to start\n");
return false; return false;
} }
@@ -183,7 +184,7 @@ static bool rirb_init(void)
if (r8(HDA_RIRBCTL) & 0x02) return true; if (r8(HDA_RIRBCTL) & 0x02) return true;
asm volatile("pause"); asm volatile("pause");
} }
printf("[HDA] RIRB DMA failed to start\n"); kprintf("[HDA] RIRB DMA failed to start\n");
return false; return false;
} }
@@ -218,7 +219,7 @@ static bool enumerate_codec(uint8_t cad)
uint32_t type = hda_get_param(cad, n, HDA_PARAM_FUNC_GROUP_TYPE) & 0xFF; uint32_t type = hda_get_param(cad, n, HDA_PARAM_FUNC_GROUP_TYPE) & 0xFF;
if (type == 0x01) { afg = n; break; } if (type == 0x01) { afg = n; break; }
} }
if (!afg) { printf("[HDA] no AFG on codec %u\n", cad); return false; } if (!afg) { kprintf("[HDA] no AFG on codec %u\n", cad); return false; }
/* Enumerate widgets */ /* Enumerate widgets */
uint32_t w_info = hda_get_param(cad, afg, HDA_PARAM_NODE_COUNT); uint32_t w_info = hda_get_param(cad, afg, HDA_PARAM_NODE_COUNT);
@@ -241,11 +242,11 @@ static bool enumerate_codec(uint8_t cad)
} }
} }
if (!dac) { printf("[HDA] no DAC found\n"); return false; } if (!dac) { kprintf("[HDA] no DAC found\n"); return false; }
if (!pin) { printf("[HDA] no output pin found\n"); return false; } if (!pin) { kprintf("[HDA] no output pin found\n"); return false; }
g_afg = afg; g_dac = dac; g_pin = pin; g_afg = afg; g_dac = dac; g_pin = pin;
printf("[HDA] codec=%u AFG=%u DAC=%u Pin=%u\n", cad, afg, dac, pin); kprintf("[HDA] codec=%u AFG=%u DAC=%u Pin=%u\n", cad, afg, dac, pin);
/* Select DAC in pin's connection list if needed */ /* Select DAC in pin's connection list if needed */
uint8_t clen = (uint8_t)(hda_get_param(cad, pin, HDA_PARAM_CONN_LIST_LEN) & 0x7F); uint8_t clen = (uint8_t)(hda_get_param(cad, pin, HDA_PARAM_CONN_LIST_LEN) & 0x7F);
@@ -276,7 +277,7 @@ static uint16_t calc_format(hda_format_t f)
case 24: fmt |= (3u << 4); break; case 24: fmt |= (3u << 4); break;
case 32: fmt |= (4u << 4); break; case 32: fmt |= (4u << 4); break;
default: fmt |= (1u << 4); default: fmt |= (1u << 4);
printf("[HDA] unknown bit depth %u, using 16-bit\n", f.bits_per_sample); kprintf("[HDA] unknown bit depth %u, using 16-bit\n", f.bits_per_sample);
} }
/* /*
@@ -298,7 +299,7 @@ static uint16_t calc_format(hda_format_t f)
case 176400: fmt |= (1u << 14) | (3u << 11) | (0u << 8); break; /* 44100*4/ 1 */ case 176400: fmt |= (1u << 14) | (3u << 11) | (0u << 8); break; /* 44100*4/ 1 */
case 192000: fmt |= (0u << 14) | (3u << 11) | (0u << 8); break; /* 48000*4/ 1 */ case 192000: fmt |= (0u << 14) | (3u << 11) | (0u << 8); break; /* 48000*4/ 1 */
default: default:
printf("[HDA] unsupported sample rate %u, defaulting to 48000\n", kprintf("[HDA] unsupported sample rate %u, defaulting to 48000\n",
f.sample_rate); f.sample_rate);
} }
return fmt; return fmt;
@@ -347,13 +348,13 @@ bool hda_init(pci_device_t *dev)
} }
if (!mmio_phys) { if (!mmio_phys) {
printf("[HDA] BAR0 is zero, controller not properly enumerated by firmware\n"); kprintf("[HDA] BAR0 is zero, controller not properly enumerated by firmware\n");
return false; return false;
} }
/* Map via HHDM (all physical memory is already mapped with MEM_PHYS_OFFSET) */ /* Map via HHDM (all physical memory is already mapped with MEM_PHYS_OFFSET) */
g_mmio = mmio_phys + MEM_PHYS_OFFSET; g_mmio = mmio_phys + MEM_PHYS_OFFSET;
printf("[HDA] MMIO phys=%lx virt=%lx\n", (uint64_t)mmio_phys, (uint64_t)g_mmio); kprintf("[HDA] MMIO phys=%lx virt=%lx\n", (uint64_t)mmio_phys, (uint64_t)g_mmio);
/* ── 3. Controller reset ─────────────────────────────────────────────────── */ /* ── 3. Controller reset ─────────────────────────────────────────────────── */
/* Assert reset */ /* Assert reset */
@@ -379,45 +380,45 @@ bool hda_init(pci_device_t *dev)
uint16_t gcap = r16(HDA_GCAP); uint16_t gcap = r16(HDA_GCAP);
g_iss = (gcap >> 8) & 0xF; /* number of input SDs */ g_iss = (gcap >> 8) & 0xF; /* number of input SDs */
uint8_t oss = (gcap >> 12) & 0xF; /* number of output SDs */ uint8_t oss = (gcap >> 12) & 0xF; /* number of output SDs */
printf("[HDA] gcap=%04x ISS=%u OSS=%u\n", gcap, g_iss, oss); kprintf("[HDA] gcap=%04x ISS=%u OSS=%u\n", gcap, g_iss, oss);
if (!oss) { printf("[HDA] no output streams\n"); return false; } if (!oss) { kprintf("[HDA] no output streams\n"); return false; }
/* Output SD 0 starts immediately after all input SDs */ /* Output SD 0 starts immediately after all input SDs */
g_sd_base = 0x80u + (uint32_t)g_iss * HDA_SD_STRIDE; g_sd_base = 0x80u + (uint32_t)g_iss * HDA_SD_STRIDE;
/* ── 5. CORB + RIRB ─────────────────────────────────────────────────────── */ /* ── 5. CORB + RIRB ─────────────────────────────────────────────────────── */
if (!corb_init()) { printf("[HDA] CORB init failed\n"); return false; } if (!corb_init()) { kprintf("[HDA] CORB init failed\n"); return false; }
if (!rirb_init()) { printf("[HDA] RIRB init failed\n"); return false; } if (!rirb_init()) { kprintf("[HDA] RIRB init failed\n"); return false; }
/* ── 6. Detect and enumerate codecs ─────────────────────────────────────── */ /* ── 6. Detect and enumerate codecs ─────────────────────────────────────── */
uint16_t statests = r16(HDA_STATESTS); uint16_t statests = r16(HDA_STATESTS);
if (!statests) { printf("[HDA] no codecs detected\n"); return false; } if (!statests) { kprintf("[HDA] no codecs detected\n"); return false; }
bool found = false; bool found = false;
for (uint8_t c = 0; c < 15; c++) { for (uint8_t c = 0; c < 15; c++) {
if (!(statests & (1u << c))) continue; if (!(statests & (1u << c))) continue;
printf("[HDA] codec %u present\n", c); kprintf("[HDA] codec %u present\n", c);
if (!found && enumerate_codec(c)) { if (!found && enumerate_codec(c)) {
g_codec = c; g_codec = c;
found = true; found = true;
} }
} }
if (!found) { printf("[HDA] no usable codec\n"); return false; } if (!found) { kprintf("[HDA] no usable codec\n"); return false; }
/* ── 7. Allocate persistent BDL (1 page, 256 possible entries × 16 bytes) ─ */ /* ── 7. Allocate persistent BDL (1 page, 256 possible entries × 16 bytes) ─ */
void *bdl_phys = pmm_allocz(1); void *bdl_phys = pmm_allocz(1);
if (!bdl_phys) { printf("[HDA] OOM: BDL\n"); return false; } if (!bdl_phys) { kprintf("[HDA] OOM: BDL\n"); return false; }
g_bdl_phys = (uintptr_t)bdl_phys; g_bdl_phys = (uintptr_t)bdl_phys;
g_bdl = (hda_bdl_entry_t *)((uintptr_t)bdl_phys + MEM_PHYS_OFFSET); g_bdl = (hda_bdl_entry_t *)((uintptr_t)bdl_phys + MEM_PHYS_OFFSET);
printf("[HDA] init complete\n"); kprintf("[HDA] init complete\n");
return true; return true;
} }
bool hda_play_pcm(uintptr_t phys_buf, uint32_t size, hda_format_t fmt) bool hda_play_pcm(uintptr_t phys_buf, uint32_t size, hda_format_t fmt)
{ {
if (!g_mmio || !g_dac || !g_pin) { if (!g_mmio || !g_dac || !g_pin) {
printf("[HDA] not initialised\n"); kprintf("[HDA] not initialised\n");
return false; return false;
} }
if (!phys_buf || !size) return false; if (!phys_buf || !size) return false;
@@ -498,7 +499,7 @@ bool hda_play_pcm(uintptr_t phys_buf, uint32_t size, hda_format_t fmt)
ctl &= ~HDA_SD_CTL_SRST; ctl &= ~HDA_SD_CTL_SRST;
sd_w8(HDA_SD_CTL0, ctl); sd_w8(HDA_SD_CTL0, ctl);
printf("[HDA] playback started: %u Hz %u-bit %uch %u bytes\n", kprintf("[HDA] playback started: %u Hz %u-bit %uch %u bytes\n",
fmt.sample_rate, fmt.bits_per_sample, fmt.channels, size); fmt.sample_rate, fmt.bits_per_sample, fmt.channels, size);
return true; return true;
} }
@@ -524,7 +525,7 @@ void hda_wait_complete(void)
while (!(sd_r8(HDA_SD_STS) & HDA_SD_STS_BCIS)) while (!(sd_r8(HDA_SD_STS) & HDA_SD_STS_BCIS))
asm volatile("pause"); asm volatile("pause");
hda_stop(); hda_stop();
printf("[HDA] playback complete\n"); kprintf("[HDA] playback complete\n");
} }
bool hda_is_playing(void) bool hda_is_playing(void)
+11 -11
View File
@@ -1,10 +1,10 @@
#include "pcm.h" #include "pcm.h"
#include "hda.h" #include "hda.h"
#include "fs/ext2.h"
#include "mm/pmm.h" #include "mm/pmm.h"
#include "mm/vmm.h" #include "mm/vmm.h"
#include "mm/memory.h" #include "mm/memory.h"
#include "stdio.h" #include "libk/stdio.h"
#include "libk/debug.h"
/* ── WAV chunk scanner ──────────────────────────────────────────────────────── */ /* ── WAV chunk scanner ──────────────────────────────────────────────────────── */
@@ -44,7 +44,7 @@ static bool parse_wav(const uint8_t *buf, uint32_t buf_size,
uint16_t audio_fmt = *(uint16_t *)(buf + pos + 0); uint16_t audio_fmt = *(uint16_t *)(buf + pos + 0);
if (audio_fmt != 1) { if (audio_fmt != 1) {
printf("[PCM] WAV audio format %u not supported (only PCM=1)\n", kprintf("[PCM] WAV audio format %u not supported (only PCM=1)\n",
audio_fmt); audio_fmt);
return false; return false;
} }
@@ -79,19 +79,19 @@ static bool play_from_ext2(const char *filename,
/* ── 1. Resolve path and read inode ─────────────────────────────────────── */ /* ── 1. Resolve path and read inode ─────────────────────────────────────── */
uint32_t inum = ext2_resolve_path(filename); uint32_t inum = ext2_resolve_path(filename);
if (!inum) { if (!inum) {
printf("[PCM] file not found: %s\n", filename); kprintf("[PCM] file not found: %s\n", filename);
return false; return false;
} }
ext2_inode_t inode; ext2_inode_t inode;
if (!ext2_read_inode(inum, &inode)) { if (!ext2_read_inode(inum, &inode)) {
printf("[PCM] failed to read inode for %s\n", filename); kprintf("[PCM] failed to read inode for %s\n", filename);
return false; return false;
} }
uint32_t file_size = inode.i_size; uint32_t file_size = inode.i_size;
if (!file_size) { if (!file_size) {
printf("[PCM] %s is empty\n", filename); kprintf("[PCM] %s is empty\n", filename);
return false; return false;
} }
@@ -103,7 +103,7 @@ static bool play_from_ext2(const char *filename,
uint32_t pages = (file_size + PAGE_SIZE - 1) / PAGE_SIZE; uint32_t pages = (file_size + PAGE_SIZE - 1) / PAGE_SIZE;
void *phys = pmm_alloc(pages); void *phys = pmm_alloc(pages);
if (!phys) { if (!phys) {
printf("[PCM] OOM: cannot allocate %u pages for %s\n", pages, filename); kprintf("[PCM] OOM: cannot allocate %u pages for %s\n", pages, filename);
return false; return false;
} }
uint8_t *virt = (uint8_t *)((uintptr_t)phys + MEM_PHYS_OFFSET); uint8_t *virt = (uint8_t *)((uintptr_t)phys + MEM_PHYS_OFFSET);
@@ -113,7 +113,7 @@ static bool play_from_ext2(const char *filename,
/* ── 3. Read file data ───────────────────────────────────────────────────── */ /* ── 3. Read file data ───────────────────────────────────────────────────── */
if (!ext2_read_file(&inode, virt)) { if (!ext2_read_file(&inode, virt)) {
printf("[PCM] failed to read %s\n", filename); kprintf("[PCM] failed to read %s\n", filename);
pmm_free(phys, pages); pmm_free(phys, pages);
return false; return false;
} }
@@ -133,14 +133,14 @@ static bool play_from_ext2(const char *filename,
/* Adjust the physical pointer to skip the WAV headers */ /* Adjust the physical pointer to skip the WAV headers */
audio_phys += data_offset; audio_phys += data_offset;
audio_size = data_size; audio_size = data_size;
printf("[PCM] WAV: %u Hz %u-bit %u ch %u bytes of audio\n", kprintf("[PCM] WAV: %u Hz %u-bit %u ch %u bytes of audio\n",
fmt.sample_rate, fmt.bits_per_sample, fmt.channels, audio_size); fmt.sample_rate, fmt.bits_per_sample, fmt.channels, audio_size);
} else { } else {
/* Not a WAV assume raw 48 kHz, 16-bit stereo */ /* Not a WAV assume raw 48 kHz, 16-bit stereo */
fmt.sample_rate = 48000; fmt.sample_rate = 48000;
fmt.bits_per_sample = 16; fmt.bits_per_sample = 16;
fmt.channels = 2; fmt.channels = 2;
printf("[PCM] Raw PCM assumed: 48000 Hz 16-bit stereo %u bytes\n", kprintf("[PCM] Raw PCM assumed: 48000 Hz 16-bit stereo %u bytes\n",
audio_size); audio_size);
} }
} }
@@ -150,7 +150,7 @@ static bool play_from_ext2(const char *filename,
if (ok) if (ok)
hda_wait_complete(); /* blocks until the stream finishes */ hda_wait_complete(); /* blocks until the stream finishes */
else else
printf("[PCM] hda_play_pcm failed\n"); kprintf("[PCM] hda_play_pcm failed\n");
/* ── 6. Free the DMA buffer ─────────────────────────────────────────────── */ /* ── 6. Free the DMA buffer ─────────────────────────────────────────────── */
pmm_free(phys, pages); pmm_free(phys, pages);
+25 -24
View File
@@ -6,6 +6,7 @@
#include "libk/string.h" #include "libk/string.h"
#include "mp/spinlock.h" #include "mp/spinlock.h"
#include "arch/x86_64/sys/pit.h" #include "arch/x86_64/sys/pit.h"
#include "libk/debug.h"
// ── module state ───────────────────────────────────────────────────────────── // ── module state ─────────────────────────────────────────────────────────────
@@ -70,7 +71,7 @@ bool ext2_read_superblock_internal(void) {
if (!tmp) return false; if (!tmp) return false;
if (!ata_read_sectors(2, 2, tmp)) { if (!ata_read_sectors(2, 2, tmp)) {
printf("EXT2: failed to read superblock\n"); kprintf("EXT2: failed to read superblock\n");
kfree(tmp); kfree(tmp);
return false; return false;
} }
@@ -78,7 +79,7 @@ bool ext2_read_superblock_internal(void) {
kfree(tmp); kfree(tmp);
if (sb.s_magic != EXT2_MAGIC) { if (sb.s_magic != EXT2_MAGIC) {
printf("EXT2: bad magic 0x%04x\n", sb.s_magic); kprintf("EXT2: bad magic 0x%04x\n", sb.s_magic);
return false; return false;
} }
@@ -86,7 +87,7 @@ bool ext2_read_superblock_internal(void) {
num_groups = (sb.s_blocks_count + sb.s_blocks_per_group - 1) num_groups = (sb.s_blocks_count + sb.s_blocks_per_group - 1)
/ sb.s_blocks_per_group; / sb.s_blocks_per_group;
printf("EXT2: OK block_size=%u groups=%u\n", block_size, num_groups); kprintf("EXT2: OK block_size=%u groups=%u\n", block_size, num_groups);
return true; return true;
} }
@@ -124,7 +125,7 @@ bool ext2_read_group_desc_table_internal(void) {
uint8_t* buf = kmalloc(nblocks * block_size); uint8_t* buf = kmalloc(nblocks * block_size);
if (!buf) { if (!buf) {
printf("nah"); kprintf("nah");
return false; return false;
} }
@@ -532,7 +533,7 @@ static void ext2_free_inode_blocks(ext2_inode_t* inode) {
bool ext2_read_file_internal(ext2_inode_t* inode, uint8_t* buf) { bool ext2_read_file_internal(ext2_inode_t* inode, uint8_t* buf) {
if (((inode->i_mode & 0xF000) != EXT2_S_IFREG) && ((inode->i_mode & 0xF000) != EXT2_S_IFDIR)) { if (((inode->i_mode & 0xF000) != EXT2_S_IFREG) && ((inode->i_mode & 0xF000) != EXT2_S_IFDIR)) {
printf("EXT2: not a regular file or directory\n"); kprintf("EXT2: not a regular file or directory\n");
return false; return false;
} }
uint32_t size = inode->i_size; uint32_t size = inode->i_size;
@@ -909,7 +910,7 @@ bool ext2_read_dir_internal(ext2_inode_t* dir) {
uint8_t nl = e->name_len > EXT2_NAME_LEN ? EXT2_NAME_LEN : e->name_len; uint8_t nl = e->name_len > EXT2_NAME_LEN ? EXT2_NAME_LEN : e->name_len;
memcpy(name, e->name, nl); memcpy(name, e->name, nl);
name[nl] = '\0'; name[nl] = '\0';
printf(" %s inode=%u %s\n", kprintf(" %s inode=%u %s\n",
name, e->inode, ext2_file_type_string(e->file_type)); name, e->inode, ext2_file_type_string(e->file_type));
} }
off += e->rec_len; off += e->rec_len;
@@ -930,7 +931,7 @@ bool ext2_read_dir(ext2_inode_t* dir) {
bool ext2_read_root_dir_internal(void) { bool ext2_read_root_dir_internal(void) {
ext2_inode_t root; ext2_inode_t root;
if (!ext2_read_inode_internal(2, &root)) return false; if (!ext2_read_inode_internal(2, &root)) return false;
printf("Root directory:\n"); kprintf("Root directory:\n");
return ext2_read_dir_internal(&root); return ext2_read_dir_internal(&root);
} }
@@ -946,21 +947,21 @@ bool ext2_read_root_dir(void) {
bool ext2_read_file_from_root_internal(const char* name, uint8_t* buf, uint32_t* size) { bool ext2_read_file_from_root_internal(const char* name, uint8_t* buf, uint32_t* size) {
ext2_inode_t root; ext2_inode_t root;
printf("EXT2: reading file from root: %s\n", name); kprintf("EXT2: reading file from root: %s\n", name);
if (!ext2_read_inode_internal(2, &root)) return false; if (!ext2_read_inode_internal(2, &root)) return false;
printf("EXT2: root inode: size=%u blocks=%u\n", root.i_size, root.i_blocks); kprintf("EXT2: root inode: size=%u blocks=%u\n", root.i_size, root.i_blocks);
uint32_t inum; uint32_t inum;
if (!ext2_find_in_dir_internal(&root, name, &inum)) { if (!ext2_find_in_dir_internal(&root, name, &inum)) {
printf("EXT2: not found: %s\n", name); kprintf("EXT2: not found: %s\n", name);
return false; return false;
} }
printf("EXT2: found in root: inum=%u\n", inum); kprintf("EXT2: found in root: inum=%u\n", inum);
ext2_inode_t fi; ext2_inode_t fi;
if (!ext2_read_inode_internal(inum, &fi)) return false; if (!ext2_read_inode_internal(inum, &fi)) return false;
printf("EXT2: file inode: size=%u blocks=%u\n", fi.i_size, fi.i_blocks); kprintf("EXT2: file inode: size=%u blocks=%u\n", fi.i_size, fi.i_blocks);
*size = fi.i_size; *size = fi.i_size;
printf("EXT2: read file: size=%u\n", *size); kprintf("EXT2: read file: size=%u\n", *size);
return ext2_read_file_internal(&fi, buf); return ext2_read_file_internal(&fi, buf);
} }
@@ -983,7 +984,7 @@ bool ext2_write_file_from_root_internal(const char* name, const uint8_t* data,
uint32_t inum; uint32_t inum;
if (!ext2_find_in_dir_internal(&root, name, &inum)) { if (!ext2_find_in_dir_internal(&root, name, &inum)) {
printf("EXT2: not found: %s\n", name); kprintf("EXT2: not found: %s\n", name);
return false; return false;
} }
ext2_inode_t fi; ext2_inode_t fi;
@@ -1009,7 +1010,7 @@ bool ext2_create_file_internal(ext2_inode_t* dir, uint32_t dir_inum,
const char* name, uint16_t mode, uint32_t* out_inum) const char* name, uint16_t mode, uint32_t* out_inum)
{ {
if (dir_lookup_internal(dir, name)) { if (dir_lookup_internal(dir, name)) {
printf("EXT2: already exists: %s\n", name); kprintf("EXT2: already exists: %s\n", name);
return false; return false;
} }
@@ -1045,7 +1046,7 @@ bool ext2_mkdir_internal(ext2_inode_t* parent, uint32_t parent_inum,
const char* name, uint32_t* out_inum) const char* name, uint32_t* out_inum)
{ {
if (dir_lookup_internal(parent, name)) { if (dir_lookup_internal(parent, name)) {
printf("EXT2: already exists: %s\n", name); kprintf("EXT2: already exists: %s\n", name);
return false; return false;
} }
@@ -1113,13 +1114,13 @@ bool ext2_mkdir(ext2_inode_t* parent, uint32_t parent_inum,
bool ext2_unlink_internal(ext2_inode_t* dir, uint32_t dir_inum, const char* name) { bool ext2_unlink_internal(ext2_inode_t* dir, uint32_t dir_inum, const char* name) {
uint32_t inum = dir_lookup_internal(dir, name); uint32_t inum = dir_lookup_internal(dir, name);
if (!inum) { printf("EXT2: not found: %s\n", name); return false; } if (!inum) { kprintf("EXT2: not found: %s\n", name); return false; }
ext2_inode_t fi; ext2_inode_t fi;
if (!ext2_read_inode_internal(inum, &fi)) return false; if (!ext2_read_inode_internal(inum, &fi)) return false;
if ((fi.i_mode & 0xF000) == EXT2_S_IFDIR) { if ((fi.i_mode & 0xF000) == EXT2_S_IFDIR) {
printf("EXT2: is a directory, use rmdir\n"); kprintf("EXT2: is a directory, use rmdir\n");
return false; return false;
} }
if (!dir_remove_entry_internal(dir, dir_inum, name)) return false; if (!dir_remove_entry_internal(dir, dir_inum, name)) return false;
@@ -1148,17 +1149,17 @@ bool ext2_unlink(ext2_inode_t* dir, uint32_t dir_inum, const char* name) {
bool ext2_rmdir_internal(ext2_inode_t* parent, uint32_t parent_inum, const char* name) { bool ext2_rmdir_internal(ext2_inode_t* parent, uint32_t parent_inum, const char* name) {
uint32_t inum = dir_lookup_internal(parent, name); uint32_t inum = dir_lookup_internal(parent, name);
if (!inum) { printf("EXT2: not found: %s\n", name); return false; } if (!inum) { kprintf("EXT2: not found: %s\n", name); return false; }
ext2_inode_t dir; ext2_inode_t dir;
if (!ext2_read_inode_internal(inum, &dir)) return false; if (!ext2_read_inode_internal(inum, &dir)) return false;
if ((dir.i_mode & 0xF000) != EXT2_S_IFDIR) { if ((dir.i_mode & 0xF000) != EXT2_S_IFDIR) {
printf("EXT2: not a directory: %s\n", name); kprintf("EXT2: not a directory: %s\n", name);
return false; return false;
} }
if (!dir_is_empty_internal(&dir)) { if (!dir_is_empty_internal(&dir)) {
printf("EXT2: directory not empty: %s\n", name); kprintf("EXT2: directory not empty: %s\n", name);
return false; return false;
} }
@@ -1189,7 +1190,7 @@ bool ext2_rename_internal(ext2_inode_t* src_dir, uint32_t src_inum,
const char* old_name, const char* new_name) const char* old_name, const char* new_name)
{ {
uint32_t inum = dir_lookup_internal(src_dir, old_name); uint32_t inum = dir_lookup_internal(src_dir, old_name);
if (!inum) { printf("EXT2: not found: %s\n", old_name); return false; } if (!inum) { kprintf("EXT2: not found: %s\n", old_name); return false; }
ext2_inode_t fi; ext2_inode_t fi;
if (!ext2_read_inode_internal(inum, &fi)) return false; if (!ext2_read_inode_internal(inum, &fi)) return false;
@@ -1203,7 +1204,7 @@ bool ext2_rename_internal(ext2_inode_t* src_dir, uint32_t src_inum,
ext2_read_inode_internal(existing, &ex); ext2_read_inode_internal(existing, &ex);
if ((ex.i_mode & 0xF000) == EXT2_S_IFDIR) { if ((ex.i_mode & 0xF000) == EXT2_S_IFDIR) {
if (!dir_is_empty_internal(&ex)) { if (!dir_is_empty_internal(&ex)) {
printf("EXT2: rename: target dir not empty\n"); kprintf("EXT2: rename: target dir not empty\n");
return false; return false;
} }
ext2_rmdir_internal(dst_dir, dst_inum, new_name); ext2_rmdir_internal(dst_dir, dst_inum, new_name);
@@ -1261,7 +1262,7 @@ bool ext2_symlink_internal(ext2_inode_t* dir, uint32_t dir_inum,
const char* name, const char* target) const char* name, const char* target)
{ {
if (dir_lookup_internal(dir, name)) { if (dir_lookup_internal(dir, name)) {
printf("EXT2: already exists: %s\n", name); kprintf("EXT2: already exists: %s\n", name);
return false; return false;
} }
View File
@@ -6,6 +6,7 @@
#include "mm/memory.h" #include "mm/memory.h"
#include "libk/string.h" #include "libk/string.h"
#include <stddef.h> #include <stddef.h>
#include "libk/debug.h"
/* ------------------------------------------------------------------ * /* ------------------------------------------------------------------ *
* Event ring-buffer * Event ring-buffer
@@ -25,28 +26,32 @@ static spinlock_t s_lock = SPINLOCK_INIT;
/* Called from IRQ context */ /* Called from IRQ context */
void input_push_char(char c) void input_push_char(char c)
{ {
spinlock_acquire_or_wait(&s_lock); uint64_t flags;
spinlock_acquire_irqsave(&s_lock, &flags);
size_t next = (s_console_wpos + 1) % CONSOLE_BUF_SIZE; size_t next = (s_console_wpos + 1) % CONSOLE_BUF_SIZE;
if (next != s_console_rpos) { /* drop if full */ if (next != s_console_rpos) { /* drop if full */
s_console_buf[s_console_wpos] = c; s_console_buf[s_console_wpos] = c;
s_console_wpos = next; s_console_wpos = next;
} }
spinlock_drop(&s_lock); spinlock_release_irqrestore(&s_lock, flags);
} }
int input_read_console(void *buf, size_t len) int input_read_console(void *buf, size_t len)
{ {
uint8_t *p = buf; uint8_t *p = buf;
size_t count = 0; size_t count = 0;
uint64_t flags;
spinlock_acquire_irqsave(&s_lock, &flags);
spinlock_acquire_or_wait(&s_lock);
while (count < len && s_console_rpos != s_console_wpos) { while (count < len && s_console_rpos != s_console_wpos) {
p[count++] = s_console_buf[s_console_rpos]; p[count++] = s_console_buf[s_console_rpos];
s_console_rpos = (s_console_rpos + 1) % CONSOLE_BUF_SIZE; s_console_rpos = (s_console_rpos + 1) % CONSOLE_BUF_SIZE;
} }
spinlock_drop(&s_lock);
return (int)count; /* 0 = no data yet (non-blocking) */ spinlock_release_irqrestore(&s_lock, flags);
return (int)count;
} }
static void push_event(const input_event_t *ev) static void push_event(const input_event_t *ev)
@@ -141,5 +146,5 @@ void input_register_devnodes(void)
void input_init(void) void input_init(void)
{ {
input_register_devnodes(); input_register_devnodes();
printf("input: subsystem initialized\n"); kprintf("input: subsystem initialized\n");
} }
@@ -6,6 +6,7 @@
#include "arch/x86_64/sys/ioapic.h" #include "arch/x86_64/sys/ioapic.h"
#include "arch/x86_64/sys/apic.h" #include "arch/x86_64/sys/apic.h"
#include "libk/stdio.h" #include "libk/stdio.h"
#include "libk/debug.h"
#include "drivers/video/render.h" #include "drivers/video/render.h"
/* ── PS/2 I/O ports ───────────────────────────────────────────────────────── */ /* ── PS/2 I/O ports ───────────────────────────────────────────────────────── */
@@ -154,12 +155,6 @@ void ps2_kbd_handler(Registers *regs)
if (pressed && ascii) { if (pressed && ascii) {
input_push_char(ascii); input_push_char(ascii);
if (ascii == '\b') {
backspace();
} else {
putchar(ascii);
}
} }
} }
@@ -195,6 +190,6 @@ void ps2_kbd_init(void)
x86_64_APIC_IRQ_RedirectAndRegister(1, 0x21, ps2_kbd_handler); x86_64_APIC_IRQ_RedirectAndRegister(1, 0x21, ps2_kbd_handler);
printf("[PS2] Keyboard driver initialised (IRQ%d vector 0x%02x)\n", kprintf("[PS2] Keyboard driver initialised (IRQ%d vector 0x%02x)\n",
KBD_IRQ, KBD_IDT_VECTOR); KBD_IRQ, KBD_IDT_VECTOR);
} }
@@ -5,8 +5,11 @@
#include "arch/x86_64/sys/pit.h" #include "arch/x86_64/sys/pit.h"
#include "errno.h" #include "errno.h"
#include <stdbool.h> #include <stdbool.h>
#include <string.h> #include "libk/string.h"
#include "mm/memory.h"
#include "limine.h" #include "limine.h"
#include "libk/debug.h"
#include "libk/debug.h"
/* ChaCha20 core (public-domain, 20-round) */ /* ChaCha20 core (public-domain, 20-round) */
static inline void chacha20_quarterround(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d) { static inline void chacha20_quarterround(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d) {
@@ -124,7 +127,7 @@ int getrandom(void *buf, size_t buflen, unsigned int flags)
} }
void random_init(void) { void random_init(void) {
printf("Initializing ChaCha20-based CSPRNG for /dev/random and /dev/urandom...\n"); kprintf("Initializing ChaCha20-based CSPRNG for /dev/random and /dev/urandom...\n");
uint8_t entropy[64] = {0}; uint8_t entropy[64] = {0};
size_t epos = 0; size_t epos = 0;
@@ -162,7 +165,7 @@ void random_init(void) {
uint32_t eax, ebx, ecx, edx; uint32_t eax, ebx, ecx, edx;
asm volatile("cpuid" : "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx) : "a"(1)); asm volatile("cpuid" : "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx) : "a"(1));
if (ecx & (1u << 30)) { if (ecx & (1u << 30)) {
printf("RDRAND detected - using hardware RNG for seeding\n"); kprintf("RDRAND detected - using hardware RNG for seeding\n");
for (int i = 0; i < 4 && epos + 8 <= sizeof(entropy); ++i) { for (int i = 0; i < 4 && epos + 8 <= sizeof(entropy); ++i) {
uint64_t rd; uint64_t rd;
asm volatile("1: rdrand %0\n\tjnc 1b" : "=r"(rd)); asm volatile("1: rdrand %0\n\tjnc 1b" : "=r"(rd));
@@ -192,11 +195,11 @@ void random_init(void) {
rng_counter = rdtsc(); /* random starting counter */ rng_counter = rdtsc(); /* random starting counter */
rng_seeded = true; rng_seeded = true;
printf("ChaCha20 RNG seeded with %zu bytes of entropy (TSC, PIT, RDRAND, boot time, unix time, etc.)\n", epos); kprintf("ChaCha20 RNG seeded with %zu bytes of entropy (TSC, PIT, RDRAND, boot time, unix time, etc.)\n", epos);
/* Register both devices (open as "/dev/random" and "/dev/urandom") */ /* Register both devices (open as "/dev/random" and "/dev/urandom") */
VFS_RegisterCharDev("/dev/random", random_read, random_write); VFS_RegisterCharDev("/dev/random", random_read, random_write);
VFS_RegisterCharDev("/dev/urandom", random_read, random_write); VFS_RegisterCharDev("/dev/urandom", random_read, random_write);
printf("Registered chardevs: /dev/random and /dev/urandom (ChaCha20 CSPRNG)\n"); kprintf("Registered chardevs: /dev/random and /dev/urandom (ChaCha20 CSPRNG)\n");
} }
BIN
View File
Binary file not shown.
+44
View File
@@ -0,0 +1,44 @@
#include "asm.h"
#include <stdbool.h>
void halt(void) {
asm("hlt");
}
void cli(void) {
asm("cli");
}
void sti(void) {
asm("sti");
}
void pause(void) {
asm("pause");
}
void nop(void) {
asm("nop");
}
void dbgbrk(void) {
asm("int 3");
}
bool int_state(void) {
uint64_t flags;
asm volatile("pushfq; pop %0" : "=rm"(flags)::"memory");
return flags & (1 << 9);
}
bool int_toggle(bool state) {
bool ret = int_state();
if (state) {
sti();
} else {
cli();
}
return ret;
}
+20
View File
@@ -0,0 +1,20 @@
#pragma once
#include <stdint.h>
#include <stdbool.h>
#define FLAT_PTR(PTR) (*((uintptr_t(*)[])(PTR)))
#define BYTE_PTR(PTR) (*((uint8_t *)(PTR)))
#define WORD_PTR(PTR) (*((uint16_t *)(PTR)))
#define DWORD_PTR(PTR) (*((uint32_t *)(PTR)))
#define QWORD_PTR(PTR) (*((uint64_t *)(PTR)))
void halt(void);
void cli(void);
void sti(void);
void pause(void);
void nop(void);
void dbgbrk(void);
bool int_state(void);
bool int_toggle(bool state);
+66
View File
@@ -0,0 +1,66 @@
; Taken from Limine
; Added memset32
section .text
global memcpy
memcpy:
mov rcx, rdx
mov rax, rdi
rep movsb
ret
global memset
memset:
push rdi
mov rax, rsi
mov rcx, rdx
rep stosb
pop rax
ret
global memset32
memset32:
push rdi
mov rax, rsi
mov rcx, rdx
rep stosd
pop rax
ret
global memmove
memmove:
mov rcx, rdx
mov rax, rdi
cmp rdi, rsi
ja .copy_backwards
rep movsb
jmp .done
.copy_backwards:
lea rdi, [rdi+rcx-1]
lea rsi, [rsi+rcx-1]
std
rep movsb
cld
.done:
ret
global memcmp
memcmp:
mov rcx, rdx
repe cmpsb
je .equal
mov al, byte [rdi-1]
sub al, byte [rsi-1]
movsx rax, al
jmp .done
.equal:
xor eax, eax
.done:
ret
+15 -29
View File
@@ -2,8 +2,7 @@
#include "mm/memory.h" #include "mm/memory.h"
#include "mp/spinlock.h" #include "mp/spinlock.h"
#include <stddef.h> #include <stddef.h>
#include "libk/debug.h"
struct gdt_desc { struct gdt_desc {
uint16_t limit; uint16_t limit;
@@ -37,40 +36,28 @@ struct gdtr {
struct gdtr gdt = {0}; struct gdtr gdt = {0};
struct gdt_ptr gdt_pointer = {0}; struct gdt_ptr gdt_pointer = {0};
struct tss kernel_tss = {0}; spinlock_t gdt_lock;
spinlock_t s_gdt_lock = SPINLOCK_INIT;
extern void gdt_reload(void);
extern void tss_reload(void); extern void tss_reload(void);
void gdt_init(void) {
void x86_64_GDT_Initialize(void) { spinlock_acquire_or_wait(&gdt_lock);
uint64_t flags;
spinlock_acquire_irqsave(&s_gdt_lock, &flags);
// null desc
memset(&gdt.entries[0], 0, sizeof(struct gdt_desc));
// Kernel code // Kernel code
gdt.entries[1].limit = 0xFFFF; gdt.entries[1].access = 0b10011010;
gdt.entries[1].access = 0x9A; gdt.entries[1].granularity = 0b00100000;
gdt.entries[1].granularity = 0x20;
// Kernel data // Kernel data
gdt.entries[2].limit = 0xFFFF; gdt.entries[2].access = 0b10010010;
gdt.entries[2].access = 0x92;
gdt.entries[2].granularity = 0x00;
// User data // User data
gdt.entries[3].limit = 0xFFFF; gdt.entries[3].access = 0b11110010;
gdt.entries[3].access = 0xF2;
gdt.entries[3].granularity = 0x00;
// User code // User code
gdt.entries[4].limit = 0xFFFF; gdt.entries[4].access = 0b11111010;
gdt.entries[4].access = 0xFA; gdt.entries[4].granularity = 0b00100000;
gdt.entries[4].granularity = 0x20;
// TSS 0x28 // TSS
gdt.tss.length = sizeof(struct tss); gdt.tss.length = sizeof(struct tss);
gdt.tss.flags1 = 0b10001001; gdt.tss.flags1 = 0b10001001;
@@ -80,12 +67,11 @@ void x86_64_GDT_Initialize(void) {
gdt_reload(); gdt_reload();
tss_reload(); tss_reload();
spinlock_release_irqrestore(&s_gdt_lock, flags); spinlock_drop(&gdt_lock);
} }
void gdt_load_tss(size_t addr) { void gdt_load_tss(size_t addr) {
uint64_t flags; spinlock_acquire_or_wait(&gdt_lock);
spinlock_acquire_irqsave(&s_gdt_lock, &flags);
gdt.tss.base_low = (uint16_t)addr; gdt.tss.base_low = (uint16_t)addr;
gdt.tss.base_mid = (uint8_t)(addr >> 16); gdt.tss.base_mid = (uint8_t)(addr >> 16);
gdt.tss.flags1 = 0b10001001; gdt.tss.flags1 = 0b10001001;
@@ -93,5 +79,5 @@ void gdt_load_tss(size_t addr) {
gdt.tss.base_upper32 = (uint32_t)(addr >> 32); gdt.tss.base_upper32 = (uint32_t)(addr >> 32);
tss_reload(); tss_reload();
spinlock_release_irqrestore(&s_gdt_lock, flags); spinlock_drop(&gdt_lock);
} }
+5 -6
View File
@@ -3,14 +3,13 @@
#include <stddef.h> #include <stddef.h>
#define GDT_KERNEL_BASE 0x0 #define GDT_KERNEL_BASE 0x0
#define GDT_KERNEL_CODE64 0x8 #define GDT_KERNEL_CODE64 0x8
#define GDT_KERNEL_DATA64 0x10 #define GDT_KERNEL_DATA64 0x10
#define GDT_USER_BASE 0x18 #define GDT_USER_BASE 0x18
#define GDT_USER_DATA64 0x18 #define GDT_USER_DATA64 0x20
#define GDT_USER_CODE64 0x20 #define GDT_USER_CODE64 0x28
#define GDT_TSS 0x28 #define GDT_TSS 0x30
struct tss { struct tss {
uint32_t reserved; uint32_t reserved;
@@ -30,7 +29,7 @@ struct tss {
uint16_t iomap_base; uint16_t iomap_base;
} __attribute__((packed)); } __attribute__((packed));
extern struct tss kernel_tss; extern void gdt_reload(void);
void x86_64_GDT_Initialize(void); void gdt_init(void);
void gdt_load_tss(size_t addr); void gdt_load_tss(size_t addr);
-27
View File
@@ -1,27 +0,0 @@
.intel_syntax noprefix
.global x86_64_GDT_Load
.extern gdt_pointer
.global gdt_reload
gdt_reload:
lgdt [rip + gdt_pointer]
push 0x08
lea rax, [rip + .flush]
push rax
lretq
.flush:
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
ret
.global tss_reload
tss_reload:
mov ax, 0x2B
ltr ax
ret
+23
View File
@@ -0,0 +1,23 @@
extern gdt_pointer
global gdt_reload
gdt_reload:
lgdt [rel gdt_pointer]
push 8
lea rax, [rel .flush]
push rax
retfq
.flush:
mov eax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
ret
global tss_reload
tss_reload:
mov ax, 0x2B
ltr ax
ret
+30 -27
View File
@@ -1,35 +1,38 @@
#include "idt.h" #include "idt.h"
#include "libk/binary.h" #include <stddef.h>
#include <stdint.h>
struct idt_entry {
uint16_t offset_lo;
uint16_t selector;
uint8_t ist;
uint8_t flags;
uint16_t offset_mid;
uint32_t offset_hi;
uint32_t zero;
} __attribute__((packed));
IDTEntry g_IDT[256]; struct idt_register {
IDTDescriptor g_IDTDescriptor = { sizeof(g_IDT) - 1, g_IDT }; uint16_t size;
uint64_t address;
} __attribute__((packed));
extern void x86_64_IDT_Load(IDTDescriptor* descriptor); struct idt_entry idt[256] = {0};
void x86_64_IDT_SetGate(int interrupt, void* base, uint16_t segmentDescriptor, uint8_t flags) void idt_set_gate(size_t vec, void *handler, uint8_t ist) {
{ uint64_t p = (uint64_t)handler;
uintptr_t addr = (uintptr_t)base;
g_IDT[interrupt].BaseLow = addr & 0xFFFF; idt[vec].offset_lo = (uint16_t)p;
g_IDT[interrupt].SegmentSelector = segmentDescriptor; idt[vec].selector = 8;
g_IDT[interrupt].IST = 0; idt[vec].ist = ist;
g_IDT[interrupt].Flags = flags; idt[vec].flags = 0x8E;
g_IDT[interrupt].BaseMid = (addr >> 16) & 0xFFFF; idt[vec].offset_mid = (uint16_t)(p >> 16);
g_IDT[interrupt].BaseHigh = (addr >> 32) & 0xFFFFFFFF; idt[vec].offset_hi = (uint32_t)(p >> 32);
g_IDT[interrupt].Reserved = 0; idt[vec].zero = 0;
}
void x86_64_IDT_EnableGate(int interrupt)
{
FLAG_SET(g_IDT[interrupt].Flags, IDT_FLAG_PRESENT);
} }
void x86_64_IDT_DisableGate(int interrupt) void idt_reload(void) {
{ struct idt_register idt_ptr = {sizeof(idt) - 1, (uint64_t)idt};
FLAG_UNSET(g_IDT[interrupt].Flags, IDT_FLAG_PRESENT);
asm volatile("lidtq %0" : : "m"(idt_ptr));
} }
void x86_64_IDT_Initialize(void)
{
x86_64_IDT_Load(&g_IDTDescriptor);
}
+3 -40
View File
@@ -1,44 +1,7 @@
#pragma once #pragma once
#include <stdint.h> #include <stdint.h>
#include <stddef.h>
void idt_set_gate(size_t vec, void *handler, uint8_t ist);
typedef enum void idt_reload(void);
{
IDT_FLAG_GATE_TASK = 0x5,
IDT_FLAG_GATE_16BIT_INT = 0x6,
IDT_FLAG_GATE_16BIT_TRAP = 0x7,
IDT_FLAG_GATE_32BIT_INT = 0xE,
IDT_FLAG_GATE_32BIT_TRAP = 0xF,
IDT_FLAG_RING0 = (0 << 5),
IDT_FLAG_RING1 = (1 << 5),
IDT_FLAG_RING2 = (2 << 5),
IDT_FLAG_RING3 = (3 << 5),
IDT_FLAG_PRESENT = 0x80,
} IDT_FLAGS;
typedef struct
{
uint16_t BaseLow;
uint16_t SegmentSelector;
uint8_t IST; // Interrupt Stack Table (0 = default)
uint8_t Flags;
uint16_t BaseMid;
uint32_t BaseHigh;
uint32_t Reserved;
} __attribute__((packed)) IDTEntry;
typedef struct
{
uint16_t Limit;
IDTEntry* Ptr;
} __attribute__((packed)) IDTDescriptor;
void x86_64_IDT_Initialize(void);
void x86_64_IDT_SetGate(int interrupt, void* base, uint16_t segmentDescriptor, uint8_t flags);
void x86_64_IDT_EnableGate(int interrupt);
void x86_64_IDT_DisableGate(int interrupt);
-6
View File
@@ -1,6 +0,0 @@
.intel_syntax noprefix
.global x86_64_IDT_Load
x86_64_IDT_Load:
lidt [rdi] # descriptor in RDI
ret
+348 -110
View File
@@ -1,124 +1,362 @@
// ... includes ...
#include "arch/x86_64/cpu/io.h" #include "arch/x86_64/cpu/io.h"
#include "libk/debug.h" #include "libk/debug.h"
#include "arch/x86_64/boot/isr.h" #include "arch/x86_64/boot/isr.h"
#include "idt.h" #include "idt.h"
#define MODULE "ISR" #include "mm/vmm.h"
#include "arch/x86_64/cpu/reg.h"
#include "mp/mp.h"
#include "mm/memory.h"
#include "mm/pmm.h"
#include "arch/x86_64/sys/halt.h"
#include "sched/sched.h"
static inline uint64_t x86_64_read_cr2(void) void isr_install(void) {
{ idt_set_gate(0, isr0, 0);
uint64_t value; idt_set_gate(1, isr1, 0);
__asm__ volatile ("mov %%cr2, %0" : "=r"(value)); idt_set_gate(2, isr2, 0);
return value; idt_set_gate(3, isr3, 0);
idt_set_gate(4, isr4, 0);
idt_set_gate(5, isr5, 0);
idt_set_gate(6, isr6, 0);
idt_set_gate(7, isr7, 0);
idt_set_gate(8, isr8, 0);
idt_set_gate(9, isr9, 0);
idt_set_gate(10, isr10, 0);
idt_set_gate(11, isr11, 0);
idt_set_gate(12, isr12, 0);
idt_set_gate(13, isr13, 0);
idt_set_gate(14, isr14, 2);
idt_set_gate(15, isr15, 0);
idt_set_gate(16, isr16, 0);
idt_set_gate(17, isr17, 0);
idt_set_gate(18, isr18, 0);
idt_set_gate(19, isr19, 0);
idt_set_gate(20, isr20, 0);
idt_set_gate(21, isr21, 0);
idt_set_gate(22, isr22, 0);
idt_set_gate(23, isr23, 0);
idt_set_gate(24, isr24, 0);
idt_set_gate(25, isr25, 0);
idt_set_gate(26, isr26, 0);
idt_set_gate(27, isr27, 0);
idt_set_gate(28, isr28, 0);
idt_set_gate(29, isr29, 0);
idt_set_gate(30, isr30, 0);
idt_set_gate(31, isr31, 0);
idt_set_gate(32, isr32, 0);
idt_set_gate(33, isr33, 0);
idt_set_gate(34, isr34, 0);
idt_set_gate(35, isr35, 0);
idt_set_gate(36, isr36, 0);
idt_set_gate(37, isr37, 0);
idt_set_gate(38, isr38, 0);
idt_set_gate(39, isr39, 0);
idt_set_gate(40, isr40, 0);
idt_set_gate(41, isr41, 0);
idt_set_gate(42, isr42, 0);
idt_set_gate(43, isr43, 0);
idt_set_gate(44, isr44, 0);
idt_set_gate(45, isr45, 0);
idt_set_gate(46, isr46, 0);
idt_set_gate(47, isr47, 0);
idt_set_gate(48, isr48, 1);
idt_set_gate(49, isr49, 0);
idt_set_gate(50, isr50, 0);
idt_set_gate(51, isr51, 0);
idt_set_gate(52, isr52, 0);
idt_set_gate(53, isr53, 0);
idt_set_gate(54, isr54, 0);
idt_set_gate(55, isr55, 0);
idt_set_gate(56, isr56, 0);
idt_set_gate(57, isr57, 0);
idt_set_gate(58, isr58, 0);
idt_set_gate(59, isr59, 0);
idt_set_gate(60, isr60, 0);
idt_set_gate(61, isr61, 0);
idt_set_gate(62, isr62, 0);
idt_set_gate(63, isr63, 0);
idt_set_gate(64, isr64, 0);
idt_set_gate(65, isr65, 0);
idt_set_gate(66, isr66, 0);
idt_set_gate(67, isr67, 0);
idt_set_gate(68, isr68, 0);
idt_set_gate(69, isr69, 0);
idt_set_gate(70, isr70, 0);
idt_set_gate(71, isr71, 0);
idt_set_gate(72, isr72, 0);
idt_set_gate(73, isr73, 0);
idt_set_gate(74, isr74, 0);
idt_set_gate(75, isr75, 0);
idt_set_gate(76, isr76, 0);
idt_set_gate(77, isr77, 0);
idt_set_gate(78, isr78, 0);
idt_set_gate(79, isr79, 0);
idt_set_gate(80, isr80, 0);
idt_set_gate(81, isr81, 0);
idt_set_gate(82, isr82, 0);
idt_set_gate(83, isr83, 0);
idt_set_gate(84, isr84, 0);
idt_set_gate(85, isr85, 0);
idt_set_gate(86, isr86, 0);
idt_set_gate(87, isr87, 0);
idt_set_gate(88, isr88, 0);
idt_set_gate(89, isr89, 0);
idt_set_gate(90, isr90, 0);
idt_set_gate(91, isr91, 0);
idt_set_gate(92, isr92, 0);
idt_set_gate(93, isr93, 0);
idt_set_gate(94, isr94, 0);
idt_set_gate(95, isr95, 0);
idt_set_gate(96, isr96, 0);
idt_set_gate(97, isr97, 0);
idt_set_gate(98, isr98, 0);
idt_set_gate(99, isr99, 0);
idt_set_gate(100, isr100, 0);
idt_set_gate(101, isr101, 0);
idt_set_gate(102, isr102, 0);
idt_set_gate(103, isr103, 0);
idt_set_gate(104, isr104, 0);
idt_set_gate(105, isr105, 0);
idt_set_gate(106, isr106, 0);
idt_set_gate(107, isr107, 0);
idt_set_gate(108, isr108, 0);
idt_set_gate(109, isr109, 0);
idt_set_gate(110, isr110, 0);
idt_set_gate(111, isr111, 0);
idt_set_gate(112, isr112, 0);
idt_set_gate(113, isr113, 0);
idt_set_gate(114, isr114, 0);
idt_set_gate(115, isr115, 0);
idt_set_gate(116, isr116, 0);
idt_set_gate(117, isr117, 0);
idt_set_gate(118, isr118, 0);
idt_set_gate(119, isr119, 0);
idt_set_gate(120, isr120, 0);
idt_set_gate(121, isr121, 0);
idt_set_gate(122, isr122, 0);
idt_set_gate(123, isr123, 0);
idt_set_gate(124, isr124, 0);
idt_set_gate(125, isr125, 0);
idt_set_gate(126, isr126, 0);
idt_set_gate(127, isr127, 0);
idt_set_gate(128, isr128, 0);
idt_set_gate(129, isr129, 0);
idt_set_gate(130, isr130, 0);
idt_set_gate(131, isr131, 0);
idt_set_gate(132, isr132, 0);
idt_set_gate(133, isr133, 0);
idt_set_gate(134, isr134, 0);
idt_set_gate(135, isr135, 0);
idt_set_gate(136, isr136, 0);
idt_set_gate(137, isr137, 0);
idt_set_gate(138, isr138, 0);
idt_set_gate(139, isr139, 0);
idt_set_gate(140, isr140, 0);
idt_set_gate(141, isr141, 0);
idt_set_gate(142, isr142, 0);
idt_set_gate(143, isr143, 0);
idt_set_gate(144, isr144, 0);
idt_set_gate(145, isr145, 0);
idt_set_gate(146, isr146, 0);
idt_set_gate(147, isr147, 0);
idt_set_gate(148, isr148, 0);
idt_set_gate(149, isr149, 0);
idt_set_gate(150, isr150, 0);
idt_set_gate(151, isr151, 0);
idt_set_gate(152, isr152, 0);
idt_set_gate(153, isr153, 0);
idt_set_gate(154, isr154, 0);
idt_set_gate(155, isr155, 0);
idt_set_gate(156, isr156, 0);
idt_set_gate(157, isr157, 0);
idt_set_gate(158, isr158, 0);
idt_set_gate(159, isr159, 0);
idt_set_gate(160, isr160, 0);
idt_set_gate(161, isr161, 0);
idt_set_gate(162, isr162, 0);
idt_set_gate(163, isr163, 0);
idt_set_gate(164, isr164, 0);
idt_set_gate(165, isr165, 0);
idt_set_gate(166, isr166, 0);
idt_set_gate(167, isr167, 0);
idt_set_gate(168, isr168, 0);
idt_set_gate(169, isr169, 0);
idt_set_gate(170, isr170, 0);
idt_set_gate(171, isr171, 0);
idt_set_gate(172, isr172, 0);
idt_set_gate(173, isr173, 0);
idt_set_gate(174, isr174, 0);
idt_set_gate(175, isr175, 0);
idt_set_gate(176, isr176, 0);
idt_set_gate(177, isr177, 0);
idt_set_gate(178, isr178, 0);
idt_set_gate(179, isr179, 0);
idt_set_gate(180, isr180, 0);
idt_set_gate(181, isr181, 0);
idt_set_gate(182, isr182, 0);
idt_set_gate(183, isr183, 0);
idt_set_gate(184, isr184, 0);
idt_set_gate(185, isr185, 0);
idt_set_gate(186, isr186, 0);
idt_set_gate(187, isr187, 0);
idt_set_gate(188, isr188, 0);
idt_set_gate(189, isr189, 0);
idt_set_gate(190, isr190, 0);
idt_set_gate(191, isr191, 0);
idt_set_gate(192, isr192, 0);
idt_set_gate(193, isr193, 0);
idt_set_gate(194, isr194, 0);
idt_set_gate(195, isr195, 0);
idt_set_gate(196, isr196, 0);
idt_set_gate(197, isr197, 0);
idt_set_gate(198, isr198, 0);
idt_set_gate(199, isr199, 0);
idt_set_gate(200, isr200, 0);
idt_set_gate(201, isr201, 0);
idt_set_gate(202, isr202, 0);
idt_set_gate(203, isr203, 0);
idt_set_gate(204, isr204, 0);
idt_set_gate(205, isr205, 0);
idt_set_gate(206, isr206, 0);
idt_set_gate(207, isr207, 0);
idt_set_gate(208, isr208, 0);
idt_set_gate(209, isr209, 0);
idt_set_gate(210, isr210, 0);
idt_set_gate(211, isr211, 0);
idt_set_gate(212, isr212, 0);
idt_set_gate(213, isr213, 0);
idt_set_gate(214, isr214, 0);
idt_set_gate(215, isr215, 0);
idt_set_gate(216, isr216, 0);
idt_set_gate(217, isr217, 0);
idt_set_gate(218, isr218, 0);
idt_set_gate(219, isr219, 0);
idt_set_gate(220, isr220, 0);
idt_set_gate(221, isr221, 0);
idt_set_gate(222, isr222, 0);
idt_set_gate(223, isr223, 0);
idt_set_gate(224, isr224, 0);
idt_set_gate(225, isr225, 0);
idt_set_gate(226, isr226, 0);
idt_set_gate(227, isr227, 0);
idt_set_gate(228, isr228, 0);
idt_set_gate(229, isr229, 0);
idt_set_gate(230, isr230, 0);
idt_set_gate(231, isr231, 0);
idt_set_gate(232, isr232, 0);
idt_set_gate(233, isr233, 0);
idt_set_gate(234, isr234, 0);
idt_set_gate(235, isr235, 0);
idt_set_gate(236, isr236, 0);
idt_set_gate(237, isr237, 0);
idt_set_gate(238, isr238, 0);
idt_set_gate(239, isr239, 0);
idt_set_gate(240, isr240, 0);
idt_set_gate(241, isr241, 0);
idt_set_gate(242, isr242, 0);
idt_set_gate(243, isr243, 0);
idt_set_gate(244, isr244, 0);
idt_set_gate(245, isr245, 0);
idt_set_gate(246, isr246, 0);
idt_set_gate(247, isr247, 0);
idt_set_gate(248, isr248, 0);
idt_set_gate(249, isr249, 0);
idt_set_gate(250, isr250, 0);
idt_set_gate(251, isr251, 0);
idt_set_gate(252, isr252, 0);
idt_set_gate(253, isr253, 0);
idt_set_gate(254, isr254, 0);
idt_set_gate(255, isr255, 0);
idt_reload();
} }
ISRHandler g_ISRHandlers[256]; static const char *isr_exception_messages[] = {"Divide by zero",
static const char* const g_Exceptions[] = { "Debug",
"Divide by zero error", "NMI",
"Debug", "Breakpoint",
"Non-maskable Interrupt", "Overflow",
"Breakpoint", "Bound Range Exceeded",
"Overflow", "Invalid Opcode",
"Bound Range Exceeded", "Device Not Available",
"Invalid Opcode", "Double fault",
"Device Not Available", "Co-processor Segment Overrun",
"Double Fault", "Invalid TSS",
"Coprocessor Segment Overrun", "Segment not present",
"Invalid TSS", "Stack-Segment Fault",
"Segment Not Present", "GPF",
"Stack-Segment Fault", "Page Fault",
"General Protection Fault", "Reserved",
"Page Fault", "x87 Floating Point Exception",
"", "alignment check",
"x87 Floating-Point Exception", "Machine check",
"Alignment Check", "SIMD floating-point exception",
"Machine Check", "Virtualization Exception",
"SIMD Floating-Point Exception", "Deadlock",
"Virtualization Exception", "Reserved",
"Control Protection Exception ", "Reserved",
"", "Reserved",
"", "Reserved",
"", "Reserved",
"", "Reserved",
"", "Reserved",
"", "Reserved",
"Hypervisor Injection Exception", "Reserved",
"VMM Communication Exception", "Security Exception",
"Security Exception", "Reserved",
"" "Triple Fault",
}; "FPU error"};
extern void x86_64_ISR_InitializeGates(void); // defined in isrs_gen.c static event_handlers_t event_handlers[256] = {NULL};
void x86_64_ISR_Initialize(void) void isr_register_handler(int n, void *handler) {
{ event_handlers[n] = handler;
x86_64_ISR_InitializeGates();
for (int i = 0; i < 256; i++)
x86_64_IDT_EnableGate(i);
x86_64_IDT_DisableGate(0x80); // syscall gate
} }
void page_fault_handler(Registers* regs, uint64_t cr2) void isr_handle(registers_t *r) {
{ if (r->cs & 0x3) {
swapgs();
}
if (r->isrNumber < 256 && event_handlers[r->isrNumber] != NULL) {
event_handlers[r->isrNumber](r);
} else {
if (r->isrNumber < 32) {
if (r->cs & 0x3) {
struct thread *thrd = sched_get_running_thread();
kprintf(
"Killing user thread tid %d under process %s for exception "
"%s\n",
thrd->tid, thrd->mother_proc->name,
isr_exception_messages[r->isrNumber]);
kprintf("User thread crashed at address: %p\n", r->rip);
thread_kill(thrd, true);
} else {
halt_other_cpus();
kprintffos(0, "AH! UNHANDLED EXCEPTION!\n");
kprintffos(0, "RIP: %p RBP: %p RSP: %p\n", r->rip, r->rbp,
r->rsp);
kprintffos(0, "RAX: %p RBX: %p RCX: %p\n", r->rax, r->rbx,
r->rcx);
kprintffos(0, "RDX: %p RDI: %p RSI: %p\n", r->rdx, r->rdi,
r->rsi);
kprintffos(0, "R8 : %p R9 : %p R10: %p\n", r->r8, r->r9,
r->r10);
kprintffos(0, "R11: %p R12: %p R13: %p\n", r->r11, r->r12,
r->r13);
kprintffos(0, "R14: %p R15: %p ERR: 0b%b\n", r->r14, r->r15,
r->errorCode);
kprintffos(0, "CS : %p SS : %p RFLAGS: %p\n", r->cs, r->ss,
r->rflags);
kprintffos(0, "FS : %p UGS: %p KGS: %p\n", read_fs_base(),
read_user_gs(), read_kernel_gs());
panic_((void *)r->rip, (void *)r->rbp,
"Unhandled Exception: %s\n",
isr_exception_messages[r->isrNumber]);
}
}
}
if (r->cs & 0x3) {
// bit 0: present swapgs();
// bit 1: write }
// bit 2: user-mode
// bit 3: reserved overwrite
// bit 4: instruction fetch
log_crit(MODULE, "KERNEL PANIC! Exception %d (%s)", regs->interrupt, g_Exceptions[regs->interrupt]);
log_crit(MODULE, " rax=%x rbx=%x rcx=%x rdx=%x rsi=%x rdi=%x",
regs->rax, regs->rbx, regs->rcx, regs->rdx, regs->rsi, regs->rdi);
log_crit(MODULE, " rsp=%x rbp=%x rip=%x rflags=%x cs=%x ss=%x",
regs->rsp, regs->rbp, regs->rip, regs->rflags, regs->cs, regs->ss);
log_crit(MODULE, " interrupt=%x errorcode=%x", regs->interrupt, regs->error);
log_crit("PAGEFAULT", "Fault at address %lx (rip=%lx, err=%x)",
cr2, regs->rip, regs->error);
log_crit(MODULE, "KERNEL PANIC!");
x86_64_Panic(); // or attempt recovery
} }
void __attribute__((used)) x86_64_ISR_Handler(Registers* regs)
{
if (regs->interrupt == 14)
{
uint64_t cr2 = x86_64_read_cr2();
page_fault_handler(regs, cr2);
}
if (g_ISRHandlers[regs->interrupt])
g_ISRHandlers[regs->interrupt](regs);
else if (regs->interrupt >= 32)
log_err(MODULE, "Unhandled interrupt %d!", regs->interrupt);
else {
// panic log (use regs->rax etc. now)
log_crit(MODULE, "KERNEL PANIC! Exception %d (%s)", regs->interrupt, g_Exceptions[regs->interrupt]);
// ... print registers with rax/rbx etc. ...
log_crit(MODULE, " rax=%x rbx=%x rcx=%x rdx=%x rsi=%x rdi=%x",
regs->rax, regs->rbx, regs->rcx, regs->rdx, regs->rsi, regs->rdi);
log_crit(MODULE, " rsp=%x rbp=%x rip=%x rflags=%x cs=%x ss=%x",
regs->rsp, regs->rbp, regs->rip, regs->rflags, regs->cs, regs->ss);
log_crit(MODULE, " interrupt=%x errorcode=%x", regs->interrupt, regs->error);
log_crit(MODULE, "KERNEL PANIC!");
x86_64_Panic();
}
}
void x86_64_ISR_RegisterHandler(int interrupt, ISRHandler handler)
{
g_ISRHandlers[interrupt] = handler;
x86_64_IDT_EnableGate(interrupt);
}
+41 -10
View File
@@ -1,15 +1,46 @@
#pragma once #pragma once
#include <stdint.h> #include <stdint.h>
#include "arch/x86_64/cpu/reg.h"
typedef struct #define PASTER(x, y) x##y
{ #define EVALUATOR(x, y) PASTER(x, y)
uint64_t r15, r14, r13, r12, r11, r10, r9, r8; // This first macro makes functions like "void isr0(void)"
uint64_t rdi, rsi, rbp, rdx, rcx, rbx, rax; // But the number is summed up on each call
uint64_t interrupt, error; #define ONE EVALUATOR(void isr, __COUNTER__)(void)
uint64_t rip, cs, rflags, rsp, ss; // Different granularities
} __attribute__((packed)) Registers; #define TWO \
ONE; \
ONE
#define TEN \
TWO; \
TWO; \
TWO; \
TWO; \
TWO
#define TWENTY \
TEN; \
TEN
#define HUNDRED \
TWENTY; \
TWENTY; \
TWENTY; \
TWENTY; \
TWENTY
// Define 255 ISRs based on previous granularities
#define DEFISR \
HUNDRED; \
HUNDRED; \
TWENTY; \
TWENTY; \
TEN; \
TWO; \
TWO; \
TWO
typedef void (*ISRHandler)(Registers* regs); DEFISR;
void x86_64_ISR_Initialize(void); typedef void (*event_handlers_t)(registers_t *);
void x86_64_ISR_RegisterHandler(int interrupt, ISRHandler handler);
void isr_install(void);
extern void isr_handle(registers_t *r);
void isr_register_handler(int n, void *handler);
-58
View File
@@ -1,58 +0,0 @@
.intel_syntax noprefix
.extern x86_64_ISR_Handler
.macro ISR_NOERRORCODE num
.global x86_64_ISR\num
x86_64_ISR\num:
push 0
push \num
jmp isr_common
.endm
.macro ISR_ERRORCODE num
.global x86_64_ISR\num
x86_64_ISR\num:
push \num
jmp isr_common
.endm
.include "arch/x86_64/boot/isrs_gen.inc"
isr_common:
push rax
push rbx
push rcx
push rdx
push rbp
push rsi
push rdi
push r8
push r9
push r10
push r11
push r12
push r13
push r14
push r15
mov rdi, rsp // Registers* in RDI
call x86_64_ISR_Handler
pop r15
pop r14
pop r13
pop r12
pop r11
pop r10
pop r9
pop r8
pop rdi
pop rsi
pop rbp
pop rdx
pop rcx
pop rbx
pop rax
add rsp, 16 // pop interrupt + error code
iretq
+87
View File
@@ -0,0 +1,87 @@
%macro pushall 0
push rax
push rbx
push rcx
push rdx
push rbp
push rdi
push rsi
push r8
push r9
push r10
push r11
push r12
push r13
push r14
push r15
%endmacro
%macro popall 0
pop r15
pop r14
pop r13
pop r12
pop r11
pop r10
pop r9
pop r8
pop rsi
pop rdi
pop rbp
pop rdx
pop rcx
pop rbx
pop rax
%endmacro
extern isr_handle
; Common handler for the ISRs
isr_common_format:
pushall
cld
mov rdi, rsp
xor rbp, rbp
call isr_handle
popall
add rsp, 24
iretq
%macro isr 1
global isr%1
isr%1:
push 0
push %1
push fs
jmp isr_common_format
%endmacro
%macro error_isr 1
global isr%1
isr%1:
push %1
push fs
jmp isr_common_format
%endmacro
%define has_errcode(i) (i == 8 || (i >= 10 && i <= 14) || i == 17 || i == 21 || i == 29 || i == 30)
; Define ISRs
%assign i 0
%rep 256
%if !has_errcode(i)
isr i
%else
error_isr i
%endif
%assign i i + 1
%endrep
-520
View File
@@ -1,520 +0,0 @@
// !!! THIS FILE IS AUTOGENERATED !!!
#include "idt.h"
#include "gdt.h"
void x86_64_ISR0();
void x86_64_ISR1();
void x86_64_ISR2();
void x86_64_ISR3();
void x86_64_ISR4();
void x86_64_ISR5();
void x86_64_ISR6();
void x86_64_ISR7();
void x86_64_ISR8();
void x86_64_ISR9();
void x86_64_ISR10();
void x86_64_ISR11();
void x86_64_ISR12();
void x86_64_ISR13();
void x86_64_ISR14();
void x86_64_ISR15();
void x86_64_ISR16();
void x86_64_ISR17();
void x86_64_ISR18();
void x86_64_ISR19();
void x86_64_ISR20();
void x86_64_ISR21();
void x86_64_ISR22();
void x86_64_ISR23();
void x86_64_ISR24();
void x86_64_ISR25();
void x86_64_ISR26();
void x86_64_ISR27();
void x86_64_ISR28();
void x86_64_ISR29();
void x86_64_ISR30();
void x86_64_ISR31();
void x86_64_ISR32();
void x86_64_ISR33();
void x86_64_ISR34();
void x86_64_ISR35();
void x86_64_ISR36();
void x86_64_ISR37();
void x86_64_ISR38();
void x86_64_ISR39();
void x86_64_ISR40();
void x86_64_ISR41();
void x86_64_ISR42();
void x86_64_ISR43();
void x86_64_ISR44();
void x86_64_ISR45();
void x86_64_ISR46();
void x86_64_ISR47();
void x86_64_ISR48();
void x86_64_ISR49();
void x86_64_ISR50();
void x86_64_ISR51();
void x86_64_ISR52();
void x86_64_ISR53();
void x86_64_ISR54();
void x86_64_ISR55();
void x86_64_ISR56();
void x86_64_ISR57();
void x86_64_ISR58();
void x86_64_ISR59();
void x86_64_ISR60();
void x86_64_ISR61();
void x86_64_ISR62();
void x86_64_ISR63();
void x86_64_ISR64();
void x86_64_ISR65();
void x86_64_ISR66();
void x86_64_ISR67();
void x86_64_ISR68();
void x86_64_ISR69();
void x86_64_ISR70();
void x86_64_ISR71();
void x86_64_ISR72();
void x86_64_ISR73();
void x86_64_ISR74();
void x86_64_ISR75();
void x86_64_ISR76();
void x86_64_ISR77();
void x86_64_ISR78();
void x86_64_ISR79();
void x86_64_ISR80();
void x86_64_ISR81();
void x86_64_ISR82();
void x86_64_ISR83();
void x86_64_ISR84();
void x86_64_ISR85();
void x86_64_ISR86();
void x86_64_ISR87();
void x86_64_ISR88();
void x86_64_ISR89();
void x86_64_ISR90();
void x86_64_ISR91();
void x86_64_ISR92();
void x86_64_ISR93();
void x86_64_ISR94();
void x86_64_ISR95();
void x86_64_ISR96();
void x86_64_ISR97();
void x86_64_ISR98();
void x86_64_ISR99();
void x86_64_ISR100();
void x86_64_ISR101();
void x86_64_ISR102();
void x86_64_ISR103();
void x86_64_ISR104();
void x86_64_ISR105();
void x86_64_ISR106();
void x86_64_ISR107();
void x86_64_ISR108();
void x86_64_ISR109();
void x86_64_ISR110();
void x86_64_ISR111();
void x86_64_ISR112();
void x86_64_ISR113();
void x86_64_ISR114();
void x86_64_ISR115();
void x86_64_ISR116();
void x86_64_ISR117();
void x86_64_ISR118();
void x86_64_ISR119();
void x86_64_ISR120();
void x86_64_ISR121();
void x86_64_ISR122();
void x86_64_ISR123();
void x86_64_ISR124();
void x86_64_ISR125();
void x86_64_ISR126();
void x86_64_ISR127();
void x86_64_ISR128();
void x86_64_ISR129();
void x86_64_ISR130();
void x86_64_ISR131();
void x86_64_ISR132();
void x86_64_ISR133();
void x86_64_ISR134();
void x86_64_ISR135();
void x86_64_ISR136();
void x86_64_ISR137();
void x86_64_ISR138();
void x86_64_ISR139();
void x86_64_ISR140();
void x86_64_ISR141();
void x86_64_ISR142();
void x86_64_ISR143();
void x86_64_ISR144();
void x86_64_ISR145();
void x86_64_ISR146();
void x86_64_ISR147();
void x86_64_ISR148();
void x86_64_ISR149();
void x86_64_ISR150();
void x86_64_ISR151();
void x86_64_ISR152();
void x86_64_ISR153();
void x86_64_ISR154();
void x86_64_ISR155();
void x86_64_ISR156();
void x86_64_ISR157();
void x86_64_ISR158();
void x86_64_ISR159();
void x86_64_ISR160();
void x86_64_ISR161();
void x86_64_ISR162();
void x86_64_ISR163();
void x86_64_ISR164();
void x86_64_ISR165();
void x86_64_ISR166();
void x86_64_ISR167();
void x86_64_ISR168();
void x86_64_ISR169();
void x86_64_ISR170();
void x86_64_ISR171();
void x86_64_ISR172();
void x86_64_ISR173();
void x86_64_ISR174();
void x86_64_ISR175();
void x86_64_ISR176();
void x86_64_ISR177();
void x86_64_ISR178();
void x86_64_ISR179();
void x86_64_ISR180();
void x86_64_ISR181();
void x86_64_ISR182();
void x86_64_ISR183();
void x86_64_ISR184();
void x86_64_ISR185();
void x86_64_ISR186();
void x86_64_ISR187();
void x86_64_ISR188();
void x86_64_ISR189();
void x86_64_ISR190();
void x86_64_ISR191();
void x86_64_ISR192();
void x86_64_ISR193();
void x86_64_ISR194();
void x86_64_ISR195();
void x86_64_ISR196();
void x86_64_ISR197();
void x86_64_ISR198();
void x86_64_ISR199();
void x86_64_ISR200();
void x86_64_ISR201();
void x86_64_ISR202();
void x86_64_ISR203();
void x86_64_ISR204();
void x86_64_ISR205();
void x86_64_ISR206();
void x86_64_ISR207();
void x86_64_ISR208();
void x86_64_ISR209();
void x86_64_ISR210();
void x86_64_ISR211();
void x86_64_ISR212();
void x86_64_ISR213();
void x86_64_ISR214();
void x86_64_ISR215();
void x86_64_ISR216();
void x86_64_ISR217();
void x86_64_ISR218();
void x86_64_ISR219();
void x86_64_ISR220();
void x86_64_ISR221();
void x86_64_ISR222();
void x86_64_ISR223();
void x86_64_ISR224();
void x86_64_ISR225();
void x86_64_ISR226();
void x86_64_ISR227();
void x86_64_ISR228();
void x86_64_ISR229();
void x86_64_ISR230();
void x86_64_ISR231();
void x86_64_ISR232();
void x86_64_ISR233();
void x86_64_ISR234();
void x86_64_ISR235();
void x86_64_ISR236();
void x86_64_ISR237();
void x86_64_ISR238();
void x86_64_ISR239();
void x86_64_ISR240();
void x86_64_ISR241();
void x86_64_ISR242();
void x86_64_ISR243();
void x86_64_ISR244();
void x86_64_ISR245();
void x86_64_ISR246();
void x86_64_ISR247();
void x86_64_ISR248();
void x86_64_ISR249();
void x86_64_ISR250();
void x86_64_ISR251();
void x86_64_ISR252();
void x86_64_ISR253();
void x86_64_ISR254();
void x86_64_ISR255();
void x86_64_ISR_InitializeGates()
{
x86_64_IDT_SetGate(0, x86_64_ISR0, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(1, x86_64_ISR1, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(2, x86_64_ISR2, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(3, x86_64_ISR3, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(4, x86_64_ISR4, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(5, x86_64_ISR5, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(6, x86_64_ISR6, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(7, x86_64_ISR7, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(8, x86_64_ISR8, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(9, x86_64_ISR9, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(10, x86_64_ISR10, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(11, x86_64_ISR11, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(12, x86_64_ISR12, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(13, x86_64_ISR13, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(14, x86_64_ISR14, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(15, x86_64_ISR15, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(16, x86_64_ISR16, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(17, x86_64_ISR17, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(18, x86_64_ISR18, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(19, x86_64_ISR19, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(20, x86_64_ISR20, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(21, x86_64_ISR21, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(22, x86_64_ISR22, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(23, x86_64_ISR23, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(24, x86_64_ISR24, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(25, x86_64_ISR25, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(26, x86_64_ISR26, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(27, x86_64_ISR27, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(28, x86_64_ISR28, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(29, x86_64_ISR29, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(30, x86_64_ISR30, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(31, x86_64_ISR31, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(32, x86_64_ISR32, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(33, x86_64_ISR33, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(34, x86_64_ISR34, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(35, x86_64_ISR35, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(36, x86_64_ISR36, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(37, x86_64_ISR37, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(38, x86_64_ISR38, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(39, x86_64_ISR39, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(40, x86_64_ISR40, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(41, x86_64_ISR41, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(42, x86_64_ISR42, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(43, x86_64_ISR43, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(44, x86_64_ISR44, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(45, x86_64_ISR45, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(46, x86_64_ISR46, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(47, x86_64_ISR47, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(48, x86_64_ISR48, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(49, x86_64_ISR49, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(50, x86_64_ISR50, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(51, x86_64_ISR51, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(52, x86_64_ISR52, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(53, x86_64_ISR53, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(54, x86_64_ISR54, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(55, x86_64_ISR55, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(56, x86_64_ISR56, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(57, x86_64_ISR57, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(58, x86_64_ISR58, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(59, x86_64_ISR59, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(60, x86_64_ISR60, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(61, x86_64_ISR61, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(62, x86_64_ISR62, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(63, x86_64_ISR63, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(64, x86_64_ISR64, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(65, x86_64_ISR65, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(66, x86_64_ISR66, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(67, x86_64_ISR67, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(68, x86_64_ISR68, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(69, x86_64_ISR69, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(70, x86_64_ISR70, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(71, x86_64_ISR71, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(72, x86_64_ISR72, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(73, x86_64_ISR73, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(74, x86_64_ISR74, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(75, x86_64_ISR75, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(76, x86_64_ISR76, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(77, x86_64_ISR77, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(78, x86_64_ISR78, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(79, x86_64_ISR79, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(80, x86_64_ISR80, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(81, x86_64_ISR81, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(82, x86_64_ISR82, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(83, x86_64_ISR83, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(84, x86_64_ISR84, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(85, x86_64_ISR85, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(86, x86_64_ISR86, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(87, x86_64_ISR87, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(88, x86_64_ISR88, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(89, x86_64_ISR89, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(90, x86_64_ISR90, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(91, x86_64_ISR91, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(92, x86_64_ISR92, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(93, x86_64_ISR93, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(94, x86_64_ISR94, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(95, x86_64_ISR95, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(96, x86_64_ISR96, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(97, x86_64_ISR97, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(98, x86_64_ISR98, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(99, x86_64_ISR99, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(100, x86_64_ISR100, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(101, x86_64_ISR101, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(102, x86_64_ISR102, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(103, x86_64_ISR103, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(104, x86_64_ISR104, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(105, x86_64_ISR105, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(106, x86_64_ISR106, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(107, x86_64_ISR107, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(108, x86_64_ISR108, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(109, x86_64_ISR109, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(110, x86_64_ISR110, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(111, x86_64_ISR111, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(112, x86_64_ISR112, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(113, x86_64_ISR113, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(114, x86_64_ISR114, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(115, x86_64_ISR115, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(116, x86_64_ISR116, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(117, x86_64_ISR117, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(118, x86_64_ISR118, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(119, x86_64_ISR119, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(120, x86_64_ISR120, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(121, x86_64_ISR121, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(122, x86_64_ISR122, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(123, x86_64_ISR123, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(124, x86_64_ISR124, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(125, x86_64_ISR125, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(126, x86_64_ISR126, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(127, x86_64_ISR127, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(128, x86_64_ISR128, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(129, x86_64_ISR129, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(130, x86_64_ISR130, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(131, x86_64_ISR131, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(132, x86_64_ISR132, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(133, x86_64_ISR133, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(134, x86_64_ISR134, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(135, x86_64_ISR135, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(136, x86_64_ISR136, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(137, x86_64_ISR137, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(138, x86_64_ISR138, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(139, x86_64_ISR139, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(140, x86_64_ISR140, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(141, x86_64_ISR141, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(142, x86_64_ISR142, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(143, x86_64_ISR143, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(144, x86_64_ISR144, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(145, x86_64_ISR145, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(146, x86_64_ISR146, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(147, x86_64_ISR147, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(148, x86_64_ISR148, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(149, x86_64_ISR149, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(150, x86_64_ISR150, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(151, x86_64_ISR151, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(152, x86_64_ISR152, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(153, x86_64_ISR153, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(154, x86_64_ISR154, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(155, x86_64_ISR155, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(156, x86_64_ISR156, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(157, x86_64_ISR157, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(158, x86_64_ISR158, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(159, x86_64_ISR159, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(160, x86_64_ISR160, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(161, x86_64_ISR161, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(162, x86_64_ISR162, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(163, x86_64_ISR163, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(164, x86_64_ISR164, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(165, x86_64_ISR165, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(166, x86_64_ISR166, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(167, x86_64_ISR167, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(168, x86_64_ISR168, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(169, x86_64_ISR169, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(170, x86_64_ISR170, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(171, x86_64_ISR171, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(172, x86_64_ISR172, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(173, x86_64_ISR173, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(174, x86_64_ISR174, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(175, x86_64_ISR175, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(176, x86_64_ISR176, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(177, x86_64_ISR177, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(178, x86_64_ISR178, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(179, x86_64_ISR179, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(180, x86_64_ISR180, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(181, x86_64_ISR181, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(182, x86_64_ISR182, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(183, x86_64_ISR183, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(184, x86_64_ISR184, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(185, x86_64_ISR185, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(186, x86_64_ISR186, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(187, x86_64_ISR187, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(188, x86_64_ISR188, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(189, x86_64_ISR189, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(190, x86_64_ISR190, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(191, x86_64_ISR191, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(192, x86_64_ISR192, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(193, x86_64_ISR193, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(194, x86_64_ISR194, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(195, x86_64_ISR195, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(196, x86_64_ISR196, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(197, x86_64_ISR197, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(198, x86_64_ISR198, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(199, x86_64_ISR199, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(200, x86_64_ISR200, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(201, x86_64_ISR201, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(202, x86_64_ISR202, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(203, x86_64_ISR203, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(204, x86_64_ISR204, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(205, x86_64_ISR205, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(206, x86_64_ISR206, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(207, x86_64_ISR207, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(208, x86_64_ISR208, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(209, x86_64_ISR209, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(210, x86_64_ISR210, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(211, x86_64_ISR211, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(212, x86_64_ISR212, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(213, x86_64_ISR213, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(214, x86_64_ISR214, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(215, x86_64_ISR215, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(216, x86_64_ISR216, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(217, x86_64_ISR217, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(218, x86_64_ISR218, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(219, x86_64_ISR219, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(220, x86_64_ISR220, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(221, x86_64_ISR221, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(222, x86_64_ISR222, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(223, x86_64_ISR223, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(224, x86_64_ISR224, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(225, x86_64_ISR225, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(226, x86_64_ISR226, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(227, x86_64_ISR227, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(228, x86_64_ISR228, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(229, x86_64_ISR229, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(230, x86_64_ISR230, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(231, x86_64_ISR231, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(232, x86_64_ISR232, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(233, x86_64_ISR233, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(234, x86_64_ISR234, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(235, x86_64_ISR235, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(236, x86_64_ISR236, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(237, x86_64_ISR237, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(238, x86_64_ISR238, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(239, x86_64_ISR239, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(240, x86_64_ISR240, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(241, x86_64_ISR241, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(242, x86_64_ISR242, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(243, x86_64_ISR243, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(244, x86_64_ISR244, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(245, x86_64_ISR245, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(246, x86_64_ISR246, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(247, x86_64_ISR247, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(248, x86_64_ISR248, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(249, x86_64_ISR249, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(250, x86_64_ISR250, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(251, x86_64_ISR251, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(252, x86_64_ISR252, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(253, x86_64_ISR253, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(254, x86_64_ISR254, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
x86_64_IDT_SetGate(255, x86_64_ISR255, GDT_KERNEL_CODE64, IDT_FLAG_RING0 | IDT_FLAG_GATE_32BIT_INT);
}
-256
View File
@@ -1,256 +0,0 @@
ISR_NOERRORCODE 0
ISR_NOERRORCODE 1
ISR_NOERRORCODE 2
ISR_NOERRORCODE 3
ISR_NOERRORCODE 4
ISR_NOERRORCODE 5
ISR_NOERRORCODE 6
ISR_NOERRORCODE 7
ISR_ERRORCODE 8
ISR_NOERRORCODE 9
ISR_ERRORCODE 10
ISR_ERRORCODE 11
ISR_ERRORCODE 12
ISR_ERRORCODE 13
ISR_ERRORCODE 14
ISR_NOERRORCODE 15
ISR_NOERRORCODE 16
ISR_ERRORCODE 17
ISR_NOERRORCODE 18
ISR_NOERRORCODE 19
ISR_NOERRORCODE 20
ISR_ERRORCODE 21
ISR_NOERRORCODE 22
ISR_NOERRORCODE 23
ISR_NOERRORCODE 24
ISR_NOERRORCODE 25
ISR_NOERRORCODE 26
ISR_NOERRORCODE 27
ISR_NOERRORCODE 28
ISR_NOERRORCODE 29
ISR_NOERRORCODE 30
ISR_NOERRORCODE 31
ISR_NOERRORCODE 32
ISR_NOERRORCODE 33
ISR_NOERRORCODE 34
ISR_NOERRORCODE 35
ISR_NOERRORCODE 36
ISR_NOERRORCODE 37
ISR_NOERRORCODE 38
ISR_NOERRORCODE 39
ISR_NOERRORCODE 40
ISR_NOERRORCODE 41
ISR_NOERRORCODE 42
ISR_NOERRORCODE 43
ISR_NOERRORCODE 44
ISR_NOERRORCODE 45
ISR_NOERRORCODE 46
ISR_NOERRORCODE 47
ISR_NOERRORCODE 48
ISR_NOERRORCODE 49
ISR_NOERRORCODE 50
ISR_NOERRORCODE 51
ISR_NOERRORCODE 52
ISR_NOERRORCODE 53
ISR_NOERRORCODE 54
ISR_NOERRORCODE 55
ISR_NOERRORCODE 56
ISR_NOERRORCODE 57
ISR_NOERRORCODE 58
ISR_NOERRORCODE 59
ISR_NOERRORCODE 60
ISR_NOERRORCODE 61
ISR_NOERRORCODE 62
ISR_NOERRORCODE 63
ISR_NOERRORCODE 64
ISR_NOERRORCODE 65
ISR_NOERRORCODE 66
ISR_NOERRORCODE 67
ISR_NOERRORCODE 68
ISR_NOERRORCODE 69
ISR_NOERRORCODE 70
ISR_NOERRORCODE 71
ISR_NOERRORCODE 72
ISR_NOERRORCODE 73
ISR_NOERRORCODE 74
ISR_NOERRORCODE 75
ISR_NOERRORCODE 76
ISR_NOERRORCODE 77
ISR_NOERRORCODE 78
ISR_NOERRORCODE 79
ISR_NOERRORCODE 80
ISR_NOERRORCODE 81
ISR_NOERRORCODE 82
ISR_NOERRORCODE 83
ISR_NOERRORCODE 84
ISR_NOERRORCODE 85
ISR_NOERRORCODE 86
ISR_NOERRORCODE 87
ISR_NOERRORCODE 88
ISR_NOERRORCODE 89
ISR_NOERRORCODE 90
ISR_NOERRORCODE 91
ISR_NOERRORCODE 92
ISR_NOERRORCODE 93
ISR_NOERRORCODE 94
ISR_NOERRORCODE 95
ISR_NOERRORCODE 96
ISR_NOERRORCODE 97
ISR_NOERRORCODE 98
ISR_NOERRORCODE 99
ISR_NOERRORCODE 100
ISR_NOERRORCODE 101
ISR_NOERRORCODE 102
ISR_NOERRORCODE 103
ISR_NOERRORCODE 104
ISR_NOERRORCODE 105
ISR_NOERRORCODE 106
ISR_NOERRORCODE 107
ISR_NOERRORCODE 108
ISR_NOERRORCODE 109
ISR_NOERRORCODE 110
ISR_NOERRORCODE 111
ISR_NOERRORCODE 112
ISR_NOERRORCODE 113
ISR_NOERRORCODE 114
ISR_NOERRORCODE 115
ISR_NOERRORCODE 116
ISR_NOERRORCODE 117
ISR_NOERRORCODE 118
ISR_NOERRORCODE 119
ISR_NOERRORCODE 120
ISR_NOERRORCODE 121
ISR_NOERRORCODE 122
ISR_NOERRORCODE 123
ISR_NOERRORCODE 124
ISR_NOERRORCODE 125
ISR_NOERRORCODE 126
ISR_NOERRORCODE 127
ISR_NOERRORCODE 128
ISR_NOERRORCODE 129
ISR_NOERRORCODE 130
ISR_NOERRORCODE 131
ISR_NOERRORCODE 132
ISR_NOERRORCODE 133
ISR_NOERRORCODE 134
ISR_NOERRORCODE 135
ISR_NOERRORCODE 136
ISR_NOERRORCODE 137
ISR_NOERRORCODE 138
ISR_NOERRORCODE 139
ISR_NOERRORCODE 140
ISR_NOERRORCODE 141
ISR_NOERRORCODE 142
ISR_NOERRORCODE 143
ISR_NOERRORCODE 144
ISR_NOERRORCODE 145
ISR_NOERRORCODE 146
ISR_NOERRORCODE 147
ISR_NOERRORCODE 148
ISR_NOERRORCODE 149
ISR_NOERRORCODE 150
ISR_NOERRORCODE 151
ISR_NOERRORCODE 152
ISR_NOERRORCODE 153
ISR_NOERRORCODE 154
ISR_NOERRORCODE 155
ISR_NOERRORCODE 156
ISR_NOERRORCODE 157
ISR_NOERRORCODE 158
ISR_NOERRORCODE 159
ISR_NOERRORCODE 160
ISR_NOERRORCODE 161
ISR_NOERRORCODE 162
ISR_NOERRORCODE 163
ISR_NOERRORCODE 164
ISR_NOERRORCODE 165
ISR_NOERRORCODE 166
ISR_NOERRORCODE 167
ISR_NOERRORCODE 168
ISR_NOERRORCODE 169
ISR_NOERRORCODE 170
ISR_NOERRORCODE 171
ISR_NOERRORCODE 172
ISR_NOERRORCODE 173
ISR_NOERRORCODE 174
ISR_NOERRORCODE 175
ISR_NOERRORCODE 176
ISR_NOERRORCODE 177
ISR_NOERRORCODE 178
ISR_NOERRORCODE 179
ISR_NOERRORCODE 180
ISR_NOERRORCODE 181
ISR_NOERRORCODE 182
ISR_NOERRORCODE 183
ISR_NOERRORCODE 184
ISR_NOERRORCODE 185
ISR_NOERRORCODE 186
ISR_NOERRORCODE 187
ISR_NOERRORCODE 188
ISR_NOERRORCODE 189
ISR_NOERRORCODE 190
ISR_NOERRORCODE 191
ISR_NOERRORCODE 192
ISR_NOERRORCODE 193
ISR_NOERRORCODE 194
ISR_NOERRORCODE 195
ISR_NOERRORCODE 196
ISR_NOERRORCODE 197
ISR_NOERRORCODE 198
ISR_NOERRORCODE 199
ISR_NOERRORCODE 200
ISR_NOERRORCODE 201
ISR_NOERRORCODE 202
ISR_NOERRORCODE 203
ISR_NOERRORCODE 204
ISR_NOERRORCODE 205
ISR_NOERRORCODE 206
ISR_NOERRORCODE 207
ISR_NOERRORCODE 208
ISR_NOERRORCODE 209
ISR_NOERRORCODE 210
ISR_NOERRORCODE 211
ISR_NOERRORCODE 212
ISR_NOERRORCODE 213
ISR_NOERRORCODE 214
ISR_NOERRORCODE 215
ISR_NOERRORCODE 216
ISR_NOERRORCODE 217
ISR_NOERRORCODE 218
ISR_NOERRORCODE 219
ISR_NOERRORCODE 220
ISR_NOERRORCODE 221
ISR_NOERRORCODE 222
ISR_NOERRORCODE 223
ISR_NOERRORCODE 224
ISR_NOERRORCODE 225
ISR_NOERRORCODE 226
ISR_NOERRORCODE 227
ISR_NOERRORCODE 228
ISR_NOERRORCODE 229
ISR_NOERRORCODE 230
ISR_NOERRORCODE 231
ISR_NOERRORCODE 232
ISR_NOERRORCODE 233
ISR_NOERRORCODE 234
ISR_NOERRORCODE 235
ISR_NOERRORCODE 236
ISR_NOERRORCODE 237
ISR_NOERRORCODE 238
ISR_NOERRORCODE 239
ISR_NOERRORCODE 240
ISR_NOERRORCODE 241
ISR_NOERRORCODE 242
ISR_NOERRORCODE 243
ISR_NOERRORCODE 244
ISR_NOERRORCODE 245
ISR_NOERRORCODE 246
ISR_NOERRORCODE 247
ISR_NOERRORCODE 248
ISR_NOERRORCODE 249
ISR_NOERRORCODE 250
ISR_NOERRORCODE 251
ISR_NOERRORCODE 252
ISR_NOERRORCODE 253
ISR_NOERRORCODE 254
ISR_NOERRORCODE 255
+11 -11
View File
@@ -1,7 +1,7 @@
#include "ata.h" #include "ata.h"
#include "arch/x86_64/cpu/io.h" #include "arch/x86_64/cpu/io.h"
#include "libk/stdio.h"
#include <stdbool.h> #include <stdbool.h>
#include "libk/debug.h"
@@ -56,7 +56,7 @@ void ata_init(void)
ata_wait_ready(); ata_wait_ready();
x86_64_outb(ATA_PRIMARY_DRIVE, 0xA0); // select master x86_64_outb(ATA_PRIMARY_DRIVE, 0xA0); // select master
ata_wait_ready(); ata_wait_ready();
printf("ATA: Primary master (hda) initialized\n"); kprintf("ATA: Primary master (hda) initialized\n");
} }
void ata_identify(void) void ata_identify(void)
@@ -71,30 +71,30 @@ void ata_identify(void)
x86_64_outb(ATA_PRIMARY_COMMAND, ATA_CMD_IDENTIFY); x86_64_outb(ATA_PRIMARY_COMMAND, ATA_CMD_IDENTIFY);
if (x86_64_inb(ATA_PRIMARY_STATUS) == 0) { if (x86_64_inb(ATA_PRIMARY_STATUS) == 0) {
printf("ATA: No primary master drive detected\n"); kprintf("ATA: No primary master drive detected\n");
return; return;
} }
if (!ata_poll()) { if (!ata_poll()) {
printf("ATA poll failed at ATA_IDENTIFY\n"); kprintf("ATA poll failed at ATA_IDENTIFY\n");
} }
if (x86_64_inb(ATA_PRIMARY_STATUS) & ATA_STATUS_ERR) { if (x86_64_inb(ATA_PRIMARY_STATUS) & ATA_STATUS_ERR) {
printf("ATA: Identify error\n"); kprintf("ATA: Identify error\n");
return; return;
} }
x86_64_insw(ATA_PRIMARY_DATA, buffer, 256); x86_64_insw(ATA_PRIMARY_DATA, buffer, 256);
printf("ATA: Disk model: "); kprintf("ATA: Disk model: ");
for (int i = 27; i <= 46; i++) { for (int i = 27; i <= 46; i++) {
uint16_t w = buffer[i]; uint16_t w = buffer[i];
char high = w >> 8; char high = w >> 8;
char low = w & 0xFF; char low = w & 0xFF;
printf("%c%c", high, low); // swap bytes kprintf("%c%c", high, low); // swap bytes
} }
printf("\n"); kprintf("\n");
printf("ATA: Total sectors: %lu\n", (uint64_t)buffer[60] | ((uint64_t)buffer[61] << 16)); kprintf("ATA: Total sectors: %lu\n", (uint64_t)buffer[60] | ((uint64_t)buffer[61] << 16));
} }
bool ata_read_sectors(uint64_t lba, uint8_t sector_count, void* buffer) bool ata_read_sectors(uint64_t lba, uint8_t sector_count, void* buffer)
@@ -114,11 +114,11 @@ bool ata_read_sectors(uint64_t lba, uint8_t sector_count, void* buffer)
uint16_t* buf = buffer; uint16_t* buf = buffer;
for (uint8_t i = 0; i < sector_count; i++) { for (uint8_t i = 0; i < sector_count; i++) {
if (!ata_poll()) { if (!ata_poll()) {
printf("ATA poll failed at ATA_read_sectors\n"); kprintf("ATA poll failed at ATA_read_sectors\n");
} }
if (x86_64_inb(ATA_PRIMARY_STATUS) & ATA_STATUS_ERR) { if (x86_64_inb(ATA_PRIMARY_STATUS) & ATA_STATUS_ERR) {
printf("ATA read error at LBA %lu\n", lba + i); kprintf("ATA read error at LBA %lu\n", lba + i);
return false; return false;
} }
+61
View File
@@ -0,0 +1,61 @@
#pragma once
#include <stdint.h>
#include "arch/x86_64/asm/asm.h"
static inline void mmoutb(void *addr, uint8_t value) {
asm volatile("mov %0, %1\n\t"
: "=m"(BYTE_PTR(addr))
: "r"(value)
: "memory");
}
static inline void mmoutw(void *addr, uint16_t value) {
asm volatile("mov %0, %1\n\t"
: "=m"(WORD_PTR(addr))
: "r"(value)
: "memory");
}
static inline void mmoutd(void *addr, uint32_t value) {
asm volatile("mov %0, %1\n\t"
: "=m"(DWORD_PTR(addr))
: "r"(value)
: "memory");
}
static inline void mmoutq(void *addr, uint64_t value) {
asm volatile("mov %0, %1\n\t"
: "=m"(QWORD_PTR(addr))
: "r"(value)
: "memory");
}
static inline uint8_t mminb(void *addr) {
uint8_t ret;
asm volatile("mov %0, %1\n\t" : "=r"(ret) : "m"(BYTE_PTR(addr)) : "memory");
return ret;
}
static inline uint16_t mminw(void *addr) {
uint16_t ret;
asm volatile("mov %0, %1\n\t" : "=r"(ret) : "m"(WORD_PTR(addr)) : "memory");
return ret;
}
static inline uint32_t mmind(void *addr) {
uint32_t ret;
asm volatile("mov %0, %1\n\t"
: "=r"(ret)
: "m"(DWORD_PTR(addr))
: "memory");
return ret;
}
static inline uint64_t mminq(void *addr) {
uint64_t ret;
asm volatile("mov %0, %1\n\t"
: "=r"(ret)
: "m"(QWORD_PTR(addr))
: "memory");
return ret;
}
+3 -3
View File
@@ -1,6 +1,6 @@
#include "pci.h" #include "pci.h"
#include "arch/x86_64/cpu/io.h" #include "arch/x86_64/cpu/io.h"
#include "libk/stdio.h" #include "libk/debug.h"
#define PCI_CFG_ADDR 0x0CF8 #define PCI_CFG_ADDR 0x0CF8
#define PCI_CFG_DATA 0x0CFC #define PCI_CFG_DATA 0x0CFC
@@ -69,7 +69,7 @@ static void pci_read_bars(pci_device_t* dev)
void pci_init(void) void pci_init(void)
{ {
printf("[PCI] Scanning bus 0...\n"); kprintf("[PCI] Scanning bus 0...\n");
pci_print_all(); pci_print_all();
} }
@@ -101,7 +101,7 @@ void pci_print_all(void)
}; };
pci_read_bars(&d); pci_read_bars(&d);
printf("[PCI] %02x:%02x.%x %04x:%04x class %04x rev %02x\n", kprintf("[PCI] %02x:%02x.%x %04x:%04x class %04x rev %02x\n",
bus, dev, func, vendor, device_id, class_sub, revision); bus, dev, func, vendor, device_id, class_sub, revision);
if (func == 0 && (pci_read8(addr, 0x0E) & 0x80) == 0) if (func == 0 && (pci_read8(addr, 0x0E) & 0x80) == 0)
+63
View File
@@ -0,0 +1,63 @@
section .text
extern syscall_handler
global amd_syscall_entry
amd_syscall_entry:
swapgs
mov qword [gs:0016], rsp
mov rsp, qword [gs:0008]
push 0x1b ; ss
push qword [gs:0016] ; rsp
push r11 ; rflags
push 0x23 ; cs
push rcx ; rip
sub rsp, 24
push rax
push rbx
push rcx
push rdx
push rbp
push rdi
push rsi
push r8
push r9
push r10
push r11
push r12
push r13
push r14
push r15
mov rdi, rsp
sti
call syscall_handler
cli
pop r15
pop r14
pop r13
pop r12
pop r11
pop r10
pop r9
pop r8
pop rsi
pop rdi
pop rbp
pop rdx
pop rcx
pop rbx
pop rax
add rsp, 24
mov rsp, qword [gs:0016]
swapgs
o64 sysret
+11
View File
@@ -0,0 +1,11 @@
#pragma once
#define write_cr(reg, val) \
asm volatile("mov cr" reg ", %0" ::"r"(val) : "memory");
#define read_cr(reg) \
({ \
size_t cr; \
asm volatile("mov %0, cr" reg : "=r"(cr)::"memory"); \
cr; \
})
+10
View File
@@ -0,0 +1,10 @@
#pragma once
#define CPUID_INVARIANT_TSC (1 << 8)
#define CPUID_TSC_DEADLINE (1 << 24)
#define CPUID_SMEP (1 << 7)
#define CPUID_SMAP (1 << 20)
#define CPUID_UMIP (1 << 2)
#define CPUID_X2APIC (1 << 21)
#define CPUID_GBPAGE (1 << 26)
+1 -1
View File
@@ -13,4 +13,4 @@ void x86_64_iowait(void);
void x86_64_Panic(void) __attribute__((noreturn)); void x86_64_Panic(void) __attribute__((noreturn));
void x86_64_EnableInterrupts(void); void x86_64_EnableInterrupts(void);
void x86_64_DisableInterrupts(void); void x86_64_DisableInterrupts(void);
void x86_64_crashme(void); void x86_64_crashme(void);
@@ -1,96 +1,102 @@
.intel_syntax noprefix section .text
.global x86_64_outb global x86_64_outb
x86_64_outb: x86_64_outb:
mov dx, di mov dx, di
mov al, sil mov al, sil
out dx, al out dx, al
ret ret
.global x86_64_inb global x86_64_inb
x86_64_inb: x86_64_inb:
mov dx, di mov dx, di
xor eax, eax xor eax, eax
in al, dx in al, dx
ret ret
.global x86_64_inw global x86_64_inw
x86_64_inw: x86_64_inw:
mov dx, di mov dx, di
xor eax, eax xor eax, eax
in ax, dx in ax, dx
ret ret
.global x86_64_outw global x86_64_outw
x86_64_outw: x86_64_outw:
mov dx, di mov dx, di
mov ax, si mov ax, si
out dx, ax out dx, ax
ret ret
.global x86_64_outl global x86_64_outl
x86_64_outl: x86_64_outl:
mov dx, di mov dx, di
mov eax, esi mov eax, esi
out dx, eax out dx, eax
ret ret
.global x86_64_inl global x86_64_inl
x86_64_inl: x86_64_inl:
mov dx, di mov dx, di
xor eax, eax xor eax, eax
in eax, dx in eax, dx
ret ret
.global x86_64_insw global x86_64_insw
x86_64_insw: x86_64_insw:
test rdx, rdx test rdx, rdx
jz .inswdone jz .done
mov rcx, rdx mov rcx, rdx
mov dx, di mov dx, di
mov rdi, rsi mov rdi, rsi
cld cld
rep insw rep insw
.inswdone:
.done:
ret ret
.global x86_64_outsw global x86_64_outsw
x86_64_outsw: x86_64_outsw:
test rdx, rdx test rdx, rdx
jz .outswdone jz .done
mov rcx, rdx mov rcx, rdx
mov dx, di mov dx, di
mov rsi, rsi ; RSI already contains source pointer
cld cld
rep outsw rep outsw
.outswdone:
.done:
ret ret
.global x86_64_Panic global x86_64_Panic
x86_64_Panic: x86_64_Panic:
cli cli
hlt hlt
1: jmp 1b
.global x86_64_EnableInterrupts .hang:
jmp .hang
global x86_64_EnableInterrupts
x86_64_EnableInterrupts: x86_64_EnableInterrupts:
sti sti
ret ret
.global x86_64_DisableInterrupts global x86_64_DisableInterrupts
x86_64_DisableInterrupts: x86_64_DisableInterrupts:
cli cli
ret ret
.global x86_64_iowait global x86_64_iowait
x86_64_iowait: x86_64_iowait:
out 0x80, al // classic I/O wait out 0x80, al ; classic I/O wait
ret ret
.global x86_64_crashme global x86_64_crashme
x86_64_crashme: x86_64_crashme:
xor rdx, rdx xor rdx, rdx
mov rax, 1 mov rax, 1
mov rbx, 0 xor rbx, rbx
div rbx div rbx
ret ret
+15
View File
@@ -0,0 +1,15 @@
#pragma once
#include <stdint.h>
static inline uint64_t rdmsr(uint32_t msr) {
uint32_t edx, eax;
asm volatile("rdmsr" : "=a"(eax), "=d"(edx) : "c"(msr) : "memory");
return ((uint64_t)edx << 32) | eax;
}
static inline void wrmsr(uint32_t msr, uint64_t value) {
uint32_t edx = value >> 32;
uint32_t eax = (uint32_t)value;
asm volatile("wrmsr" ::"a"(eax), "c"(msr), "d"(edx) : "memory");
}
+28
View File
@@ -0,0 +1,28 @@
#pragma once
#include <stdint.h>
typedef struct {
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 core;
uint64_t isrNumber;
uint64_t errorCode;
uint64_t rip;
uint64_t cs;
uint64_t rflags;
uint64_t rsp;
uint64_t ss;
} __attribute__((packed)) registers_t;
+85
View File
@@ -0,0 +1,85 @@
#include "mp/mp.h"
#include "libk/debug.h"
#include "libk/errno.h"
#include "mm/vmm.h"
#include "sched/sched.h"
#include "sched/syscall.h"
#include "arch/x86_64/boot/isr.h"
#include "arch/x86_64/sys/prcb.h"
void syscall_handler(registers_t *reg) {
cli();
prcb_return_current_cpu()->running_thread->reg = *reg;
prcb_return_current_cpu()->running_thread->stack =
prcb_return_current_cpu()->user_stack;
prcb_return_current_cpu()->fpu_save(
prcb_return_current_cpu()->running_thread->fpu_storage);
sti();
struct syscall_arguments args = {.syscall_nr = reg->rax,
.args0 = reg->rdi,
.args1 = reg->rsi,
.args2 = reg->rdx,
.args3 = reg->r10,
.args4 = reg->r8,
.args5 = reg->r9,
.ret = reg->rax};
syscall_handle(&args);
int64_t ret = (int64_t)args.ret;
if (ret < 0) {
ret = -((int)errno);
reg->rax = ret;
} else
reg->rax = args.ret;
}
void syscall_install_handler(void) {
isr_register_handler(0x80, syscall_handler);
}
uint64_t syscall_helper_user_to_kernel_address(uintptr_t user_addr) {
struct process *proc = sched_get_running_thread()->mother_proc;
struct pagemap *target_pagemap = proc->process_pagemap;
uint64_t kernel_addr = vmm_virt_to_kernel(target_pagemap, user_addr);
return kernel_addr;
}
bool syscall_helper_copy_to_user(uintptr_t user_addr, void *buffer,
size_t count) {
vmm_switch_pagemap(kernel_pagemap);
struct process *proc = sched_get_running_thread()->mother_proc;
struct pagemap *target_pagemap = proc->process_pagemap;
uint64_t kernel_addr = vmm_virt_to_kernel(target_pagemap, user_addr);
if (!kernel_addr) {
errno = EFAULT;
return false;
}
memcpy((void *)kernel_addr, buffer, count);
vmm_switch_pagemap(target_pagemap);
return true;
}
bool syscall_helper_copy_from_user(uintptr_t user_addr, void *buffer,
size_t count) {
vmm_switch_pagemap(kernel_pagemap);
struct process *proc = sched_get_running_thread()->mother_proc;
struct pagemap *target_pagemap = proc->process_pagemap;
uint64_t kernel_addr = vmm_virt_to_kernel(target_pagemap, user_addr);
if (!kernel_addr) {
errno = EFAULT;
return false;
}
memcpy(buffer, (void *)kernel_addr, count);
vmm_switch_pagemap(target_pagemap);
return true;
}
-131
View File
@@ -1,131 +0,0 @@
#include <stdint.h>
#include "libk/string.h"
#include "mm/pmm.h"
#include "mm/vmm.h"
#include "mm/memory.h"
#include "libk/stdio.h"
#include "fs/elf.h"
#include "sched/scheduler.h"
extern uintptr_t g_hhdm_offset;
#define USER_STACK_TOP 0x00007FFFFFFFE000ULL
#define USER_STACK_PAGES 8
#define USER_STACK_SIZE (USER_STACK_PAGES * PAGE_SIZE)
static uint64_t user_stack_phys_base = 0;
//extern struct pagemap *kernel_pagemap;
struct pagemap *create_user_pagemap(void)
{
struct pagemap *pm = kmalloc(sizeof(struct pagemap));
if (!pm) {
printf("Failed to allocate user pagemap struct!\n");
return NULL;
}
spinlock_init(&pm->lock);
/* Allocate a fresh PML4 (physical page) */
pm->top_level = (uint64_t *)((uintptr_t)pmm_allocz(1) + MEM_PHYS_OFFSET);
if (!pm->top_level) {
printf("Failed to allocate user PML4!\n");
kfree(pm);
return NULL;
}
/* Copy kernel higher-half mappings (kernel + HHDM) */
for (size_t i = 0; i < 512; i++) {
pm->top_level[i] = kernel_pagemap->top_level[i];
}
for (size_t i = 0; i < 256; i++) {
pm->top_level[i] = 0;
}
/* Lower half remains zero (user address space) */
printf("[usermode] user pagemap created (PML4 phys = 0x%lx)\n",
(uint64_t)pm->top_level - MEM_PHYS_OFFSET);
return pm;
}
uintptr_t setup_user_stack(struct pagemap *pagemap)
{
user_stack_phys_base = (uint64_t)pmm_allocz(USER_STACK_PAGES);
if (!user_stack_phys_base) {
printf("Failed to allocate user stack pages!\n");
for (;;);
}
uintptr_t stack_bottom = USER_STACK_TOP - USER_STACK_SIZE;
for (int i = 0; i < USER_STACK_PAGES; i++) {
uintptr_t virt = stack_bottom + i * PAGE_SIZE;
uintptr_t phys = user_stack_phys_base + i * PAGE_SIZE;
if (!vmm_map_page(pagemap,
virt,
phys,
PAGE_READ | PAGE_WRITE | PAGE_USER,
Size4KiB))
{
printf("Failed mapping user stack page\n");
for (;;);
}
}
uintptr_t rsp = USER_STACK_TOP;
rsp &= ~0xFULL;
return rsp;
}
void start_userspace(void)
{
struct pagemap *user_pagemap = create_user_pagemap();
if (!user_pagemap) {
printf("Failed to create user pagemap\n");
for (;;);
}
void *elf_entry = NULL;
uint64_t tls_fs_base = 0;
uint64_t phdr_va = 0;
uint16_t phent = 0;
uint16_t phnum = 0;
if (!ELF_Read("helloworld.elf",
&elf_entry,
user_pagemap,
&tls_fs_base,
&phdr_va,
&phent,
&phnum)) {
printf("Failed to load helloworld.elf\n");
for(;;);
}
printf("ELF: entry=0x%lx TLS_FS=0x%lx PHDR=0x%lx PHENT=0x%x PHNUM=%u\n",
(uint64_t)elf_entry, tls_fs_base, phdr_va, phent, phnum);
uintptr_t user_rsp = setup_user_stack(user_pagemap);
printf("Entering usermode RIP=%p RSP=%p\n", elf_entry, (void*)user_rsp);
sched_create_user_task("init",
(uint64_t)elf_entry,
user_rsp,
user_pagemap,
tls_fs_base,
phdr_va,
phent,
phnum);
}
-4
View File
@@ -1,4 +0,0 @@
#pragma once
#include <stdint.h>
void start_userspace(void);
+54
View File
@@ -0,0 +1,54 @@
#include "libk/debug.h"
#include <stddef.h>
#include "mm/vmm.h"
void backtrace(uintptr_t *bp) {
kprintf("Stack trace:\n");
uintptr_t *rbp = (uintptr_t *)bp;
if (rbp == NULL)
asm volatile("mov %%rbp, %0" : "=g"(rbp)::"memory");
if (rbp == NULL || (uintptr_t)(rbp) < MEM_PHYS_OFFSET)
return;
for (;;) {
uintptr_t *old_rbp = (uintptr_t *)rbp[0];
uintptr_t *rip = (uintptr_t *)rbp[1];
if (rip == NULL || old_rbp == NULL ||
((uintptr_t)rip) < MEM_PHYS_OFFSET)
break;
kprintf("%p\n", rip);
rbp = old_rbp;
}
kprintf("Kernel base: %p Mem phys base: %p\n", KERNEL_BASE,
MEM_PHYS_OFFSET);
}
void backtrace_unsafe(uintptr_t *bp) {
kprintf("Stack trace:\n");
uintptr_t *rbp = (uintptr_t *)bp;
if (rbp == NULL)
asm volatile("mov %%rbp, %0" : "=g"(rbp)::"memory");
if (rbp == NULL)
return;
for (;;) {
uintptr_t *old_rbp = (uintptr_t *)rbp[0];
uintptr_t *rip = (uintptr_t *)rbp[1];
if (rip == NULL || old_rbp == NULL)
break;
kprintf("%p\n", rip);
rbp = old_rbp;
}
}
View File
+153
View File
@@ -0,0 +1,153 @@
#include <stddef.h>
#include <stdint.h>
#include "arch/x86_64/boot/isr.h"
#include "libk/debug.h"
#include "arch/x86_64/sys/halt.h"
#include "mp/mp.h"
#include "sched/sched.h"
#include "arch/x86_64/serial/serial.h"
static void backtrace_dump(registers_t *reg) {
kprintffos(0, "============ Backtrace ==========\n");
kprintffos(0, "-> %p\n", reg->rip);
uintptr_t *rbp = (uintptr_t *)reg->rbp;
if (rbp == NULL)
asm volatile("mov %%rbp, %0" : "=g"(rbp)::"memory");
if (rbp == NULL)
return;
for (;;) {
uintptr_t *old_rbp = (uintptr_t *)rbp[0];
uintptr_t *rip = (uintptr_t *)rbp[1];
if (rip == NULL || old_rbp == NULL)
break;
kprintffos(0, "%p\n", rip);
rbp = old_rbp;
}
kprintffos(0, "============ End of dumps ==========\n");
}
static void register_dump(registers_t *reg) {
kprintffos(0, "========= Register dumps =========\n");
kprintffos(0, "RIP: %p RBP: %p RSP: %p\n", reg->rip, reg->rbp, reg->rsp);
kprintffos(0, "RAX: %p RBX: %p RCX: %p\n", reg->rax, reg->rbx, reg->rcx);
kprintffos(0, "RDX: %p RDI: %p RSI: %p\n", reg->rdx, reg->rdi, reg->rsi);
kprintffos(0, "R8 : %p R9 : %p R10: %p\n", reg->r8, reg->r9, reg->r10);
kprintffos(0, "R11: %p R12: %p R13: %p\n", reg->r11, reg->r12, reg->r13);
kprintffos(0, "R14: %p R15: %p\n", reg->r14, reg->r15);
kprintffos(0, "CS : %p SS : %p RFLAGS: %p\n", reg->cs, reg->ss,
reg->rflags);
kprintffos(0, "FS: %p UGS: %p KGS: %p\n", read_fs_base(), read_user_gs(),
read_kernel_gs());
kprintffos(0, "============ End of dumps ==========\n");
}
static void tss_dump(void) {
kprintffos(0, "============ TSS Dumps ==========\n");
kprintffos(0, "tss.rsp0: %p\n", prcb_return_current_cpu()->cpu_tss.rsp0);
kprintffos(0, "tss.rsp1: %p\n", prcb_return_current_cpu()->cpu_tss.rsp1);
kprintffos(0, "tss.rsp2: %p\n", prcb_return_current_cpu()->cpu_tss.rsp2);
kprintffos(0, "tss.ist1: %p\n", prcb_return_current_cpu()->cpu_tss.ist1);
kprintffos(0, "tss.ist2: %p\n", prcb_return_current_cpu()->cpu_tss.ist2);
kprintffos(0, "tss.ist3: %p\n", prcb_return_current_cpu()->cpu_tss.ist3);
kprintffos(0, "tss.ist4: %p\n", prcb_return_current_cpu()->cpu_tss.ist4);
kprintffos(0, "tss.ist5: %p\n", prcb_return_current_cpu()->cpu_tss.ist5);
kprintffos(0, "tss.ist6: %p\n", prcb_return_current_cpu()->cpu_tss.ist6);
kprintffos(0, "tss.ist7: %p\n", prcb_return_current_cpu()->cpu_tss.ist7);
kprintffos(0, "tss.iomap_base: %p\n",
prcb_return_current_cpu()->cpu_tss.iomap_base);
kprintffos(0, "============ End of dumps ==========\n");
}
static void prcb_dump(void) {
kprintffos(0, "============ PRCB Dumps ==========\n");
kprintffos(0, "prcb->cpu_number: %u\n",
prcb_return_current_cpu()->cpu_number);
kprintffos(0, "prcb->kernel_stack: %p\n",
prcb_return_current_cpu()->kernel_stack);
kprintffos(0, "prcb->user_stack: %p\n",
prcb_return_current_cpu()->user_stack);
kprintffos(0, "prcb->running_thread: %p\n",
prcb_return_current_cpu()->running_thread);
kprintffos(0, "prcb->sched_ticks: %p\n",
prcb_return_current_cpu()->user_stack);
kprintffos(0, "prcb->lapic_id: %u\n", prcb_return_current_cpu()->lapic_id);
kprintffos(0, "prcb->fpu_storage_size: %p\n",
prcb_return_current_cpu()->fpu_storage_size);
kprintffos(0, "prcb->fpu_save: %p\n", prcb_return_current_cpu()->fpu_save);
kprintffos(0, "prcb->fpu_restore: %p\n",
prcb_return_current_cpu()->fpu_restore);
kprintffos(0, "============ End of dumps ==========\n");
}
void breakpoint_handler(registers_t *reg) {
if (reg->cs & 0x3) {
kprintffos(0, "Breakpoint hit in user!\n");
thread_kill(prcb_return_current_cpu()->running_thread, true);
return;
} else {
kprintffos(0, "Breakpoint hit in kernel!\n");
}
pause_other_cpus();
kprintffos(0, "=========== Start of dumps =========\n");
kprintffos(0, "Breakpoint hit on CPU%u\n",
prcb_return_current_cpu()->cpu_number);
kprintffos(0, "========= Register dumps =========\n");
kprintffos(0, "RIP: %p RBP: %p RSP: %p\n", reg->rip, reg->rbp, reg->rsp);
kprintffos(0, "RAX: %p RBX: %p RCX: %p\n", reg->rax, reg->rbx, reg->rcx);
kprintffos(0, "RDX: %p RDI: %p RSI: %p\n", reg->rdx, reg->rdi, reg->rsi);
kprintffos(0, "R8 : %p R9 : %p R10: %p\n", reg->r8, reg->r9, reg->r10);
kprintffos(0, "R11: %p R12: %p R13: %p\n", reg->r11, reg->r12, reg->r13);
kprintffos(0, "R14: %p R15: %p\n", reg->r14, reg->r15);
kprintffos(0, "CS : %p SS : %p RFLAGS: %p\n", reg->cs, reg->ss,
reg->rflags);
kprintffos(0, "FS: %p UGS: %p KGS: %p\n", read_fs_base(), read_user_gs(),
read_kernel_gs());
kprintffos(0, "============ End of dumps ==========\n");
char option = 0;
while (option != 'C') {
kprintffos(0, "(C)ontinue, Dump (P)RCB, Dump (R)egisters, Dump (T)SS, "
"(B)acktrace?\n");
option = serial_getchar();
serial_putchar('\n');
switch (option) {
case 'P':
prcb_dump();
break;
case 'R':
register_dump(reg);
break;
case 'T':
tss_dump();
break;
case 'B':
backtrace_dump(reg);
default:
break;
}
}
unpause_other_cpus();
}
+159
View File
@@ -0,0 +1,159 @@
#include "libk/debug.h"
#include "libk/kargs.h"
#include <stdint.h>
struct tu_source_location {
const char *file;
uint32_t line;
uint32_t column;
};
struct tu_type_descriptor {
uint16_t kind;
uint16_t info;
char name[];
};
struct tu_overflow_data {
struct tu_source_location location;
struct tu_type_descriptor *type;
};
struct tu_shift_out_of_bounds_data {
struct tu_source_location location;
struct tu_type_descriptor *left_type;
struct tu_type_descriptor *right_type;
};
struct tu_invalid_value_data {
struct tu_source_location location;
struct tu_type_descriptor *type;
};
struct tu_array_out_of_bounds_data {
struct tu_source_location location;
struct tu_type_descriptor *array_type;
struct tu_type_descriptor *index_type;
};
struct tu_type_mismatch_v1_data {
struct tu_source_location location;
struct tu_type_descriptor *type;
unsigned char log_alignment;
unsigned char type_check_kind;
};
struct tu_negative_vla_data {
struct tu_source_location location;
struct tu_type_descriptor *type;
};
struct tu_nonnull_return_data {
struct tu_source_location location;
};
struct tu_nonnull_arg_data {
struct tu_source_location location;
};
struct tu_unreachable_data {
struct tu_source_location location;
};
struct tu_invalid_builtin_data {
struct tu_source_location location;
unsigned char kind;
};
#ifdef __cplusplus
extern "C" {
#endif
extern bool print_now;
extern bool put_to_fb;
static void tu_print_location(const char *message,
struct tu_source_location loc) {
if (print_now &&
!(kernel_arguments.kernel_args & KERNEL_ARGS_SUPPRESS_UBSAN)) {
kprintffos(0, "tinyubsan: %s at file %s, line %d, column %d\n", message,
loc.file, loc.line, loc.column);
put_to_fb = 1;
}
}
void __ubsan_handle_add_overflow(struct tu_overflow_data *data) {
tu_print_location("addition overflow", data->location);
}
void __ubsan_handle_sub_overflow(struct tu_overflow_data *data) {
tu_print_location("subtraction overflow", data->location);
}
void __ubsan_handle_mul_overflow(struct tu_overflow_data *data) {
tu_print_location("multiplication overflow", data->location);
}
void __ubsan_handle_divrem_overflow(struct tu_overflow_data *data) {
tu_print_location("division overflow", data->location);
}
void __ubsan_handle_negate_overflow(struct tu_overflow_data *data) {
tu_print_location("negation overflow", data->location);
}
void __ubsan_handle_pointer_overflow(struct tu_overflow_data *data) {
tu_print_location("pointer overflow", data->location);
}
void __ubsan_handle_shift_out_of_bounds(
struct tu_shift_out_of_bounds_data *data) {
tu_print_location("shift out of bounds", data->location);
}
void __ubsan_handle_load_invalid_value(struct tu_invalid_value_data *data) {
tu_print_location("invalid load value", data->location);
}
void __ubsan_handle_out_of_bounds(struct tu_array_out_of_bounds_data *data) {
tu_print_location("array out of bounds", data->location);
}
void __ubsan_handle_type_mismatch_v1(struct tu_type_mismatch_v1_data *data,
uintptr_t ptr) {
if (!ptr) {
tu_print_location("use of NULL pointer", data->location);
}
else if (ptr & ((1 << data->log_alignment) - 1)) {
// tu_print_location("use of misaligned pointer", data->location);
} else {
tu_print_location("no space for object", data->location);
}
}
void __ubsan_handle_vla_bound_not_positive(struct tu_negative_vla_data *data) {
tu_print_location("variable-length argument is negative", data->location);
}
void __ubsan_handle_nonnull_return(struct tu_nonnull_return_data *data) {
tu_print_location("non-null return is null", data->location);
}
void __ubsan_handle_nonnull_arg(struct tu_nonnull_arg_data *data) {
tu_print_location("non-null argument is null", data->location);
}
void __ubsan_handle_builtin_unreachable(struct tu_unreachable_data *data) {
tu_print_location("unreachable code reached", data->location);
}
void __ubsan_handle_invalid_builtin(struct tu_invalid_builtin_data *data) {
tu_print_location("invalid builtin", data->location);
}
#ifdef __cplusplus
}
#endif
+66
View File
@@ -0,0 +1,66 @@
#include "arch/x86_64/sys/tsc.h"
#include <uacpi/uacpi.h>
#include <uacpi/event.h>
#include <uacpi/sleep.h>
#include <uacpi/tables.h>
#include "arch/x86_64/sys/timer.h"
#include "madt.h"
#include "libk/debug.h"
void acpi_init() {
calibrate_tsc();
/*
* Start with this as the first step of the initialization. This loads all
* tables, brings the event subsystem online, and enters ACPI mode. We pass
* in 0 as the flags as we don't want to override any default behavior for now.
*/
uacpi_status ret = uacpi_initialize(0);
if (uacpi_unlikely_error(ret)) {
kprintf("uacpi_initialize error: %s", uacpi_status_to_string(ret));
}
/*
* Load the AML namespace. This feeds DSDT and all SSDTs to the interpreter
* for execution.
*/
ret = uacpi_namespace_load();
if (uacpi_unlikely_error(ret)) {
kprintf("uacpi_namespace_load error: %s", uacpi_status_to_string(ret));
}
/*
* Initialize the namespace. This calls all necessary _STA/_INI AML methods,
* as well as _REG for registered operation region handlers.
*/
ret = uacpi_namespace_initialize();
if (uacpi_unlikely_error(ret)) {
kprintf("uacpi_namespace_initialize error: %s", uacpi_status_to_string(ret));
}
/*
* Tell uACPI that we have marked all GPEs we wanted for wake (even though we haven't
* actually marked any, as we have no power management support right now). This is
* needed to let uACPI enable all unmarked GPEs that have a corresponding AML handler.
* These handlers are used by the firmware to dynamically execute AML code at runtime
* to e.g. react to thermal events or device hotplug.
*/
ret = uacpi_finalize_gpe_initialization();
if (uacpi_unlikely_error(ret)) {
kprintf("uACPI GPE initialization error: %s", uacpi_status_to_string(ret));
}
timer_init();
madt_init();
}
void *acpi_find_sdt(const char *signature) {
struct uacpi_table sdt;
uacpi_status st = uacpi_table_find_by_signature(signature, &sdt);
if (uacpi_unlikely_error(st)) {
panic("Could not find %s: %s\n", signature, uacpi_status_to_string(st));
}
return (void *)sdt.ptr;
}
+25
View File
@@ -0,0 +1,25 @@
#pragma once
#include <stdint.h>
typedef struct acpi_header_t {
char signature[4];
uint32_t length;
uint8_t revision;
uint8_t checksum;
char oem[6];
char oem_table[8];
uint32_t oem_revision;
uint32_t creator_id;
uint32_t creator_revision;
} __attribute__((packed)) acpi_header_t;
typedef struct acpi_gas_t {
uint8_t address_space;
uint8_t bit_width;
uint8_t bit_offset;
uint8_t access_size;
uint64_t base;
} __attribute__((packed)) acpi_gas_t;
void acpi_init();
void *acpi_find_sdt(const char *signature);
+68
View File
@@ -0,0 +1,68 @@
#include <uacpi/tables.h>
#include "madt.h"
#include <stddef.h>
#include "libk/debug.h"
#include "arch/x86_64/asm/asm.h"
struct madt *madt;
lapic_vec_t madt_local_apics;
ioapic_vec_t madt_io_apics;
iso_vec_t madt_isos;
nmi_vec_t madt_nmis;
uintptr_t lapic_addr = 0;
uintptr_t acpi_get_lapic(void) {
return lapic_addr;
}
void madt_init(void) {
vec_init(&madt_local_apics);
vec_init(&madt_io_apics);
vec_init(&madt_isos);
vec_init(&madt_nmis);
struct uacpi_table madt_table;
uacpi_status st = uacpi_table_find_by_signature("APIC", &madt_table);
if (uacpi_unlikely_error(st)) {
panic("Could not find MADT: %s\n", uacpi_status_to_string(st));
}
madt = (struct madt *)madt_table.ptr;
lapic_addr = madt->local_controller_addr;
kprintf("MADT: MADT at %p\n", madt);
for (uint8_t *madt_ptr = (uint8_t *)madt->madt_entries_begin;
(uintptr_t)madt_ptr < (uintptr_t)madt + madt->sdt.length;
madt_ptr += *(madt_ptr + 1)) {
switch (*(madt_ptr)) {
case 0:
// Processor local APIC
kprintf("MADT: Got local APIC 0x%x\n", madt_local_apics.length);
vec_push(&madt_local_apics, (void *)madt_ptr);
break;
case 1:
// I/O APIC
kprintf("MADT: Got IO APIC 0x%x\n", madt_io_apics.length);
vec_push(&madt_io_apics, (void *)madt_ptr);
break;
case 2:
// Interrupt source override
kprintf("MADT: Got ISO 0x%x\n", madt_isos.length);
vec_push(&madt_isos, (void *)madt_ptr);
break;
case 4:
// NMI
kprintf("MADT: Got NMI 0x%x\n", madt_nmis.length);
vec_push(&madt_nmis, (void *)madt_ptr);
break;
case 5:
// Local APIC address override
lapic_addr = QWORD_PTR(madt_ptr + 4);
break;
}
}
}
+64
View File
@@ -0,0 +1,64 @@
#pragma once
#include <stdint.h>
#include "libk/vec.h"
#include <uacpi/acpi.h>
#include "acpi.h"
struct madt {
acpi_header_t sdt;
uint32_t local_controller_addr;
uint32_t flags;
char madt_entries_begin[];
} __attribute__((packed));
struct madt_header {
uint8_t type;
uint8_t length;
} __attribute__((packed));
struct madt_lapic {
struct madt_header madt_header;
uint8_t processor_id;
uint8_t apic_id;
uint32_t flags;
} __attribute__((packed));
struct madt_ioapic {
struct madt_header madt_header;
uint8_t apic_id;
uint8_t reserved;
uint32_t addr;
uint32_t gsib;
} __attribute__((packed));
struct madt_iso {
struct madt_header madt_header;
uint8_t bus_source;
uint8_t irq_source;
uint32_t gsi;
uint16_t flags;
} __attribute__((packed));
struct madt_nmi {
struct madt_header madt_header;
uint8_t processor;
uint16_t flags;
uint8_t lint;
} __attribute__((packed));
typedef vec_t(struct madt_lapic *) lapic_vec_t;
typedef vec_t(struct madt_ioapic *) ioapic_vec_t;
typedef vec_t(struct madt_iso *) iso_vec_t;
typedef vec_t(struct madt_nmi *) nmi_vec_t;
extern struct madt *madt;
extern lapic_vec_t madt_local_apics;
extern ioapic_vec_t madt_io_apics;
extern iso_vec_t madt_isos;
extern nmi_vec_t madt_nmis;
uintptr_t acpi_get_lapic(void);
void madt_init(void);
+297
View File
@@ -0,0 +1,297 @@
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include "mm/vmm.h"
#include "mm/memory.h"
#include "mm/pmm.h"
#include "mm/slab.h"
#include "mp/mp.h"
#include "mp/spinlock.h"
#include "fs/elf.h"
#include "sched/sched_types.h"
#include "sched/sched.h"
#include "arch/x86_64/cpu/reg.h"
#include "mm/mmap.h"
#include "libk/string.h"
#include "libk/misc.h"
void thread_setup_context(struct thread *thrd, uintptr_t pc_address,
uint64_t arguments, bool user) {
bool old_state = int_toggle(false);
thrd->reg.rip = pc_address;
thrd->reg.rdi = arguments;
thrd->kernel_stack = ((uint64_t)pmm_allocz(CPU_STACK_SIZE / PAGE_SIZE) +
MEM_PHYS_OFFSET + CPU_STACK_SIZE);
thrd->fpu_storage =
(void *)((uintptr_t)pmm_allocz(DIV_ROUNDUP(
prcb_return_current_cpu()->fpu_storage_size, PAGE_SIZE)) +
MEM_PHYS_OFFSET);
thrd->pf_stack = ((uint64_t)pmm_allocz(CPU_STACK_SIZE / PAGE_SIZE) +
MEM_PHYS_OFFSET + CPU_STACK_SIZE);
struct process *proc = thrd->mother_proc;
if (user) {
thrd->reg.cs = 0x23;
thrd->reg.ss = 0x1b;
thrd->reg.rsp = (uint64_t)pmm_allocz(STACK_SIZE / PAGE_SIZE);
thrd->stack = thrd->reg.rsp;
mmap_range(proc->process_pagemap, proc->stack_top - STACK_SIZE,
(uintptr_t)thrd->reg.rsp, STACK_SIZE, PROT_READ | PROT_WRITE,
MAP_ANONYMOUS);
thrd->reg.rsp = proc->stack_top;
proc->stack_top -= STACK_SIZE;
prcb_return_current_cpu()->fpu_restore(thrd->fpu_storage);
uint16_t default_fcw = 0b1100111111;
asm volatile("fldcw %0" ::"m"(default_fcw) : "memory");
uint32_t default_mxcsr = 0b1111110000000;
asm volatile("ldmxcsr %0" ::"m"(default_mxcsr) : "memory");
prcb_return_current_cpu()->fpu_save(thrd->fpu_storage);
thrd->fs_base = 0;
thrd->gs_base = 0;
} else {
thrd->reg.cs = 0x08;
thrd->reg.ss = 0x10;
thrd->stack = thrd->kernel_stack;
thrd->reg.rsp = thrd->stack;
thrd->fs_base = read_fs_base();
thrd->gs_base = read_kernel_gs();
}
thrd->reg.rflags = 0x202;
int_toggle(old_state);
}
void thread_setup_context_from_user(struct thread *thrd, uintptr_t pc_address,
uintptr_t sp) {
bool old_state = int_toggle(false);
thrd->reg.rip = pc_address;
thrd->kernel_stack = ((uint64_t)pmm_allocz(CPU_STACK_SIZE / PAGE_SIZE) +
MEM_PHYS_OFFSET + CPU_STACK_SIZE);
thrd->fpu_storage =
(void *)((uintptr_t)pmm_allocz(DIV_ROUNDUP(
prcb_return_current_cpu()->fpu_storage_size, PAGE_SIZE)) +
MEM_PHYS_OFFSET);
struct process *proc = thrd->mother_proc;
thrd->reg.cs = 0x23;
thrd->reg.ss = 0x1b;
thrd->reg.rsp = sp;
thrd->stack = thrd->reg.rsp;
thrd->pf_stack = ((uint64_t)pmm_allocz(CPU_STACK_SIZE / PAGE_SIZE) +
MEM_PHYS_OFFSET + CPU_STACK_SIZE);
prcb_return_current_cpu()->fpu_restore(thrd->fpu_storage);
uint16_t default_fcw = 0b1100111111;
asm volatile("fldcw %0" ::"m"(default_fcw) : "memory");
uint32_t default_mxcsr = 0b1111110000000;
asm volatile("ldmxcsr %0" ::"m"(default_mxcsr) : "memory");
prcb_return_current_cpu()->fpu_save(thrd->fpu_storage);
thrd->fs_base = 0;
thrd->gs_base = 0;
thrd->reg.rflags = 0x202;
int_toggle(old_state);
}
// I am still surprised that I still know how this works.
// I will properly document it sometime soon.
void thread_setup_context_for_execve(struct thread *thrd, uintptr_t pc_address,
char **argv, char **envp) {
bool old_state = int_toggle(false);
struct process *proc = thrd->mother_proc;
thrd->reg.rip = pc_address;
thrd->reg.rsp = (uint64_t)pmm_allocz(STACK_SIZE / PAGE_SIZE);
thrd->stack = thrd->reg.rsp;
thrd->reg.cs = 0x23;
thrd->reg.ss = 0x1b;
mmap_range(proc->process_pagemap, proc->stack_top - STACK_SIZE,
(uintptr_t)thrd->reg.rsp, STACK_SIZE + 1, PROT_READ | PROT_WRITE,
MAP_ANONYMOUS);
thrd->reg.rsp = proc->stack_top;
thrd->reg.rflags = 0x202;
prcb_return_current_cpu()->fpu_restore(thrd->fpu_storage);
uint16_t default_fcw = 0b1100111111;
asm volatile("fldcw %0" ::"m"(default_fcw) : "memory");
uint32_t default_mxcsr = 0b1111110000000;
asm volatile("ldmxcsr %0" ::"m"(default_mxcsr) : "memory");
prcb_return_current_cpu()->fpu_save(thrd->fpu_storage);
thrd->fs_base = 0;
thrd->gs_base = 0;
struct auxval auxv = proc->auxv;
// the stack structure.
// the address values are not accurate.
/*
* 0x70000000000 - "USER=root\0" // envp[0][9]
* 0x6fffffffff6 - proc->name // argv[0][255]
* 0x6fffffffef6 - 0x0, 0x0 // zeros
* 0x6fffffffee6 - AT_ENTRY
* 0x6fffffffede - 0x400789 // example values
* 0x6fffffffed6 - AT_PHDR
* 0x6fffffffece - 2
* 0x6fffffffec6 - AT_PHENT
* 0x6fffffffebe - 7
* 0x6fffffffeb6 - AT_PHNUM
* 0x6fffffffeae - 5
* 0x6fffffffea6 - 0x0 // START OF ENVP
* 0x6fffffffe9e - 0x6fffffffff6 // pointer to envp[0]
* 0x6fffffffe96 - 0x0 // START OF ARGV
* 0x6fffffffe8e - 0x6fffffffef6 // pointer to argv[0]
* 0x6fffffffe86 - 1 // argc
*/
uint64_t *stack = (uint64_t *)(thrd->stack + STACK_SIZE + MEM_PHYS_OFFSET);
int envp_len = 0;
uint64_t address_difference = 0;
uint8_t *stack_but_in_bytes = (uint8_t *)stack;
for (envp_len = 0; envp[envp_len] != NULL; envp_len++) {
stack_but_in_bytes -= (strlen(envp[envp_len]) + 1);
memcpy((void *)stack_but_in_bytes, envp[envp_len],
strlen(envp[envp_len]) + 1);
}
stack = (uint64_t *)stack_but_in_bytes;
address_difference =
(thrd->stack + STACK_SIZE) - ((uint64_t)stack - MEM_PHYS_OFFSET);
uint64_t addr_to_env = (uint64_t)proc->stack_top - address_difference;
int argv_len;
for (argv_len = 0; argv[argv_len] != NULL; argv_len++) {
stack_but_in_bytes -= (strlen(argv[argv_len]) + 1);
memcpy((void *)stack_but_in_bytes, argv[argv_len],
strlen(argv[argv_len]) + 1);
}
stack = (uint64_t *)stack_but_in_bytes;
address_difference =
(thrd->stack + STACK_SIZE) - ((uint64_t)stack - MEM_PHYS_OFFSET);
uint64_t addr_to_arg = (uint64_t)proc->stack_top - address_difference;
// alignments
stack = (uintptr_t *)ALIGN_DOWN((uintptr_t)stack, 16);
if (((argv_len + envp_len + 1) & 1) != 0)
stack--;
*(--stack) = 0;
*(--stack) = 0;
stack -= 2;
stack[0] = 23; // AT_SECURE
stack[1] = 0;
stack -= 2;
stack[0] = 9;
stack[1] = auxv.at_entry;
stack -= 2;
stack[0] = 3;
stack[1] = auxv.at_phdr;
stack -= 2;
stack[0] = 4;
stack[1] = auxv.at_phent;
stack -= 2;
stack[0] = 5;
stack[1] = auxv.at_phnum;
*(--stack) = 0;
stack -= envp_len;
uint64_t offset = 0;
for (int i = envp_len - 1; i >= 0; i--) {
if (i != envp_len - 1) {
offset += strlen(envp[i + 1]) + 1;
}
stack[i] = addr_to_env + offset;
}
*(--stack) = 0;
stack -= argv_len;
offset = 0;
for (int i = argv_len - 1; i >= 0; i--) {
if (i != argv_len - 1) {
offset += strlen(argv[i + 1]) + 1;
}
stack[i] = addr_to_arg + offset;
}
*(--stack) = argv_len;
address_difference =
(thrd->stack + STACK_SIZE) - ((uint64_t)stack - MEM_PHYS_OFFSET);
thrd->reg.rsp -= address_difference;
proc->stack_top -= STACK_SIZE;
int_toggle(old_state);
}
void thread_fork_context(struct thread *thrd, struct thread *fthrd) {
bool old_state = int_toggle(false);
fthrd->kernel_stack = ((uint64_t)pmm_allocz(CPU_STACK_SIZE / PAGE_SIZE) +
MEM_PHYS_OFFSET + CPU_STACK_SIZE);
fthrd->pf_stack = ((uint64_t)pmm_allocz(CPU_STACK_SIZE / PAGE_SIZE) +
MEM_PHYS_OFFSET + CPU_STACK_SIZE);
fthrd->reg = thrd->reg;
fthrd->reg.rax = 0;
fthrd->reg.rbx = 0;
fthrd->fs_base = thrd->fs_base;
fthrd->gs_base = thrd->gs_base;
fthrd->fpu_storage =
(void *)((uintptr_t)pmm_allocz(DIV_ROUNDUP(
prcb_return_current_cpu()->fpu_storage_size, PAGE_SIZE)) +
MEM_PHYS_OFFSET);
memcpy(fthrd->fpu_storage, thrd->fpu_storage,
prcb_return_current_cpu()->fpu_storage_size);
int_toggle(old_state);
}
void thread_destroy_context(struct thread *thrd) {
bool old_state = int_toggle(false);
pmm_free((void *)(thrd->kernel_stack - MEM_PHYS_OFFSET - CPU_STACK_SIZE),
CPU_STACK_SIZE / PAGE_SIZE);
pmm_free((void *)(thrd->pf_stack - MEM_PHYS_OFFSET - CPU_STACK_SIZE),
CPU_STACK_SIZE / PAGE_SIZE);
pmm_free(
(void *)((uint64_t)thrd->fpu_storage - MEM_PHYS_OFFSET),
DIV_ROUNDUP(prcb_return_current_cpu()->fpu_storage_size, PAGE_SIZE));
int_toggle(old_state);
}
void process_setup_context(struct process *proc, bool user) {
if (user) {
proc->process_pagemap = vmm_new_pagemap();
} else {
proc->process_pagemap = kernel_pagemap;
}
}
void process_fork_context(struct process *proc, struct process *fproc) {
fproc->process_pagemap = vmm_fork_pagemap(proc->process_pagemap);
}
void process_destroy_context(struct process *proc) {
(void)proc;
vmm_destroy_pagemap(proc->process_pagemap);
}
+43
View File
@@ -0,0 +1,43 @@
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include "mm/vmm.h"
#include "mm/memory.h"
#include "mm/pmm.h"
#include "mm/slab.h"
#include "mp/mp.h"
#include "mp/spinlock.h"
#include "sched/syscall.h"
#include "sched/sched.h"
#include "libk/errno.h"
#define ARCH_SET_GS 0x1001
#define ARCH_SET_FS 0x1002
#define ARCH_GET_FS 0x1003
#define ARCH_GET_GS 0x1004
void syscall_prctl(struct syscall_arguments *args) {
int option = (int)args->args0;
uint64_t value = args->args1;
switch (option) {
case ARCH_SET_GS: {
sched_get_running_thread()->gs_base = value;
// set_user_gs(prcb_return_current_cpu()->running_thread->gs_base);
break;
}
case ARCH_GET_GS:
args->ret = read_user_gs();
break;
case ARCH_SET_FS: {
sched_get_running_thread()->fs_base = value;
set_fs_base(sched_get_running_thread()->fs_base);
break;
}
case ARCH_GET_FS:
args->ret = read_fs_base();
break;
default:
errno = EINVAL;
break;
}
}
+125
View File
@@ -0,0 +1,125 @@
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include "mm/vmm.h"
#include "mm/memory.h"
#include "mm/pmm.h"
#include "mm/slab.h"
#include "mp/mp.h"
#include "mp/spinlock.h"
#include "arch/x86_64/cpu/reg.h"
#include "arch/x86_64/sys/timer.h"
#include "sched/sched.h"
#include "arch/x86_64/sys/apic.h"
#include "libk/time.h"
#include "arch/x86_64/sys/prcb.h"
extern uint32_t smp_bsp_lapic_id;
extern void resched_context_switch(registers_t *reg);
void sched_yield(bool save) {
cli();
timer_stop_sched();
struct thread *thrd = sched_get_running_thread();
if (save) {
spinlock_acquire_or_wait(&thrd->yield_lock);
} else {
spinlock_drop(&thrd->lock);
prcb_return_current_cpu()->running_thread = NULL;
}
apic_send_ipi(prcb_return_current_cpu()->lapic_id, 48);
sti();
if (save) {
spinlock_acquire_or_wait(
&thrd->yield_lock); // the lock is released when the thread is
// rescheduled
spinlock_drop(&thrd->yield_lock);
} else {
for (;;) {
halt();
}
}
}
void sched_trigger_yield(uint64_t cpu_number) {
struct prcb *target = NULL;
for (size_t i = 0; i < prcb_return_installed_cpus(); i++) {
if (prcbs[i].cpu_number == cpu_number) {
target = &prcbs[i];
break;
}
}
if (target) {
apic_send_ipi(target->lapic_id, 48);
}
}
uint64_t last = 0;
void resched(registers_t *reg) {
vmm_switch_pagemap(kernel_pagemap);
prcb_return_current_cpu()->sched_ticks++;
timer_stop_sched();
struct thread *running_thrd = prcb_return_current_cpu()->running_thread;
if (prcb_return_current_cpu()->lapic_id == smp_bsp_lapic_id) {
uint64_t current = timer_count();
if (timer_handler((current - last) * 1000000)) {
last = current;
}
}
if (running_thrd) {
spinlock_drop(&running_thrd->yield_lock);
running_thrd->reg = *reg;
running_thrd->fs_base = read_fs_base();
running_thrd->gs_base = read_user_gs();
prcb_return_current_cpu()->fpu_save(running_thrd->fpu_storage);
running_thrd->last_scheduled = timer_count();
running_thrd->running_on_cpu = -1;
running_thrd->stack = prcb_return_current_cpu()->user_stack;
if (running_thrd->state == THREAD_NORMAL) {
running_thrd->state = THREAD_READY_TO_RUN;
}
spinlock_drop(&running_thrd->lock);
}
running_thrd = sched_get_next_thread(running_thrd);
if (running_thrd == NULL) {
apic_eoi();
prcb_return_current_cpu()->running_thread = NULL;
timer_sched_oneshot(48, 20000);
for (;;) {
sti();
halt();
}
}
prcb_return_current_cpu()->running_thread = running_thrd;
prcb_return_current_cpu()->cpu_tss.ist2 = running_thrd->pf_stack;
prcb_return_current_cpu()->kernel_stack = running_thrd->kernel_stack;
prcb_return_current_cpu()->user_stack = running_thrd->stack;
prcb_return_current_cpu()->running_thread->state = THREAD_NORMAL;
prcb_return_current_cpu()->fpu_restore(running_thrd->fpu_storage);
running_thrd->running_on_cpu = prcb_return_current_cpu()->cpu_number;
set_fs_base(running_thrd->fs_base);
// set_user_gs(running_thrd->gs_base);
vmm_switch_pagemap(running_thrd->mother_proc->process_pagemap);
apic_eoi();
timer_sched_oneshot(48, running_thrd->runtime);
resched_context_switch(&running_thrd->reg);
}
+21
View File
@@ -0,0 +1,21 @@
global resched_context_switch
resched_context_switch:
mov rsp, rdi
pop r15
pop r14
pop r13
pop r12
pop r11
pop r10
pop r9
pop r8
pop rsi
pop rdi
pop rbp
pop rdx
pop rcx
pop rbx
pop rax
add rsp, 24
iretq
+64
View File
@@ -0,0 +1,64 @@
#include "serial.h"
#include <stdbool.h>
#include <stdint.h>
#include "arch/x86_64/cpu/io.h"
void serial_init(void) {
x86_64_outb(COM1 + 1, 0x1);
x86_64_outb(COM1 + 3, 0x80);
x86_64_outb(COM1, 0x1);
x86_64_outb(COM1 + 1, 0x0);
x86_64_outb(COM1 + 3, 0x3);
x86_64_outb(COM1 + 2, 0xC7);
x86_64_outb(COM1 + 4, 0xB);
}
static inline bool is_transmit_empty(void) {
return (x86_64_inb(COM1 + 5) & 0b1000000) != 0;
}
static inline void transmit_data(uint8_t value) {
while (!is_transmit_empty()) {
asm volatile("pause");
}
x86_64_outb(COM1, value);
}
void serial_putchar(char ch) {
transmit_data(ch);
}
void serial_puts(char *str) {
while (*str) {
if (*str == '\n')
transmit_data('\r');
transmit_data(*str++);
}
}
int serial_received(void) {
return x86_64_inb(COM1 + 5) & 1;
}
char serial_get_byte(void) {
while (serial_received() == 0)
;
return x86_64_inb(COM1);
}
char serial_getchar(void) {
char c = '\0';
char last_c = c;
while (1) {
if (c != '\0')
serial_putchar('\b');
serial_putchar(c);
c = serial_get_byte();
if (c == '\r')
break;
last_c = c;
}
return last_c;
}
+9
View File
@@ -0,0 +1,9 @@
#pragma once
#define COM1 0x3F8
void serial_init(void);
void serial_putchar(char ch);
void serial_puts(char *str);
char serial_get_byte(void);
char serial_getchar(void);
+219 -116
View File
@@ -2,146 +2,249 @@
#include "mm/vmm.h" #include "mm/vmm.h"
#include "mm/memory.h" #include "mm/memory.h"
#include "arch/x86_64/cpu/io.h" #include "arch/x86_64/cpu/io.h"
#include "libk/stdio.h" #include "arch/x86_64/cpu/features.h"
/* ── Internal state ───────────────────────────────────────────────────────── */ #include "libk/debug.h"
static volatile uint32_t *g_lapic = NULL; /* Virtual address of LAPIC MMIO */ #include "mp/mp.h"
#include "arch/x86_64/sys/prcb.h"
#include "arch/x86_64/fw/madt.h"
#include "pic.h"
#include "timer.h"
#include <cpuid.h>
#include "arch/x86_64/bus/mmio.h"
/* ── Low-level helpers ────────────────────────────────────────────────────── */ static uintptr_t lapic_addr = 0;
static bool x2apic = false;
static inline uint32_t lapic_read(uint32_t reg) { // Converts xAPIC MMIO offset into x2APIC MSR
return g_lapic[reg >> 2]; static inline uint32_t reg_to_x2apic(uint32_t reg) {
uint32_t x2apic_reg = 0;
// MSR 831H is reserved; read/write operations cause general-protection
// exceptions. The contents of the APIC register at MMIO offset 310H are
// accessible in x2APIC mode through the MSR at address 830H
// -- Intel SDM Volume 3A 10.12.1.2 Note 4
if (reg == 0x310) {
x2apic_reg = 0x30;
} else {
x2apic_reg = reg >> 4;
}
return x2apic_reg + 0x800;
} }
static inline void lapic_write(uint32_t reg, uint32_t val) { uint32_t lapic_read(uint32_t reg) {
g_lapic[reg >> 2] = val; if (x2apic) {
/* Serialise: read back a read-only register to ensure the write landed return rdmsr(reg_to_x2apic(reg));
* before we continue (required by the APIC spec). */ }
(void)g_lapic[LAPIC_ID >> 2]; return mmind((void *)lapic_addr + MEM_PHYS_OFFSET + reg);
} }
static inline void rdmsr(uint32_t msr, uint32_t *lo, uint32_t *hi) { void lapic_write(uint32_t reg, uint32_t value) {
asm volatile("rdmsr" : "=a"(*lo), "=d"(*hi) : "c"(msr)); if (x2apic) {
wrmsr(reg_to_x2apic(reg), value);
} else {
mmoutd((void *)lapic_addr + MEM_PHYS_OFFSET + reg, value);
}
} }
static inline void wrmsr(uint32_t msr, uint32_t lo, uint32_t hi) { static void lapic_set_nmi(uint8_t vec, uint8_t current_processor_id,
asm volatile("wrmsr" : : "a"(lo), "d"(hi), "c"(msr)); uint8_t processor_id, uint16_t flags, uint8_t lint) {
// A value of 0xFF means all the processors
if (processor_id != 0xFF) {
if (current_processor_id != processor_id) {
return;
}
}
// Set to raise in vector number "vec" and set NMI flag
uint32_t nmi = 0x400 | vec;
// Set to active low if needed
if (flags & 2) {
nmi |= 1 << 13;
}
// Set to level triggered if needed
if (flags & 8) {
nmi |= 1 << 15;
}
// Use the proper LINT register
if (lint == 0) {
lapic_write(0x350, nmi);
} else if (lint == 1) {
lapic_write(0x360, nmi);
}
} }
/* ── Public API ───────────────────────────────────────────────────────────── */ uint8_t lapic_get_id(void) {
return (uint8_t)(lapic_read(0x20) >> 24);
uint64_t lapic_get_phys_base(void) {
uint32_t lo, hi;
rdmsr(IA32_APIC_BASE_MSR, &lo, &hi);
/* Physical base is in bits [35:12] of the 64-bit MSR */
return ((uint64_t)(hi & 0xFu) << 32) | (lo & 0xFFFFF000u);
} }
void lapic_eoi(void) { void lapic_init(uint8_t processor_id) {
lapic_write(LAPIC_EOI, 0); kprintf("LAPIC: Setting up LAPIC on Processor %u\n", processor_id);
uint64_t apic_msr = rdmsr(0x1B);
// Set APIC enable flag
apic_msr |= 1 << 11;
uint32_t a = 0, b = 0, c = 0, d = 0;
if (__get_cpuid(1, &a, &b, &c, &d)) {
if (c & CPUID_X2APIC) {
x2apic = true;
// Set x2APIC flag if support is detected
apic_msr |= 1 << 10;
}
}
wrmsr(0x1B, apic_msr);
// Initialize local APIC
lapic_write(0x80, 0);
lapic_write(0xF0, lapic_read(0xF0) | 0x100);
if (!x2apic) {
lapic_write(0xE0, 0xF0000000);
lapic_write(0xD0, lapic_read(0x20));
}
// Set NMIs according to the MADT
for (int i = 0; i < madt_nmis.length; i++) {
struct madt_nmi *nmi = madt_nmis.data[i];
lapic_set_nmi(2, processor_id, nmi->processor, nmi->flags, nmi->lint);
}
// Set up APIC timer
// Tell APIC timer to divide by 16
lapic_write(0x3E0, 3);
// Set timer init counter to -1
lapic_write(0x380, 0xFFFFFFFF);
timer_sleep(10);
// Stop the APIC timer
lapic_write(0x320, 0x10000);
// How much the APIC timer ticked in 10ms
prcb_return_current_cpu()->tick_in_10ms = 0xFFFFFFFF - lapic_read(0x390);
// With divider 16
lapic_write(0x3E0, 3);
lapic_write(0x380, prcb_return_current_cpu()->tick_in_10ms / 10);
} }
uint32_t lapic_id(void) { static uint32_t ioapic_read(uintptr_t ioapic_address, size_t reg) {
/* On xAPIC the LAPIC ID sits in bits [31:24] of the ID register */ mmoutd((void *)ioapic_address + MEM_PHYS_OFFSET, reg & 0xFF);
return lapic_read(LAPIC_ID) >> 24; return mmind((void *)ioapic_address + MEM_PHYS_OFFSET + 16);
} }
void lapic_init(void) { static void ioapic_write(uintptr_t ioapic_address, size_t reg, uint32_t data) {
/* mmoutd((void *)ioapic_address + MEM_PHYS_OFFSET, reg & 0xFF);
* ── Step 1: Re-enable the APIC global enable bit ───────────────────── mmoutd((void *)ioapic_address + MEM_PHYS_OFFSET + 16, data);
* }
* Earlier in kmain (before pmm_init) we cleared bit 11 of IA32_APIC_BASE
* so that the i8259 PIC would raise interrupts properly under Limine.
* Now that the LAPIC is being brought online we must restore that bit;
* without it the LAPIC is completely off and nothing below will work.
*/
uint32_t lo, hi;
rdmsr(IA32_APIC_BASE_MSR, &lo, &hi);
lo |= IA32_APIC_BASE_ENABLE;
wrmsr(IA32_APIC_BASE_MSR, lo, hi);
/* static uint32_t get_gsi_count(uintptr_t ioapic_address) {
* ── Step 2: Locate the LAPIC MMIO window ───────────────────────────── return (ioapic_read(ioapic_address, 1) & 0xFF0000) >> 16;
* }
* The physical address is almost always 0xFEE00000 but we read it from
* the MSR to be correct. vmm_init() already identity-maps all physical
* memory through the HHDM (up to 256 GiB), so the MMIO page is reachable
* at phys + MEM_PHYS_OFFSET with no extra mapping needed.
*
* TODO: For strict correctness the LAPIC page should be mapped as
* uncacheable (PAT / PCD). In practice, QEMU / BOCHS work fine
* because MTRRs mark the 0xFEE00000 range as UC by default.
*/
uint64_t phys_base = ((uint64_t)(hi & 0xFu) << 32) | (lo & 0xFFFFF000u);
printf("[LAPIC] Physical base: 0x%08x%08x\n",
(uint32_t)(phys_base >> 32), (uint32_t)phys_base);
g_lapic = (volatile uint32_t *)(phys_base + MEM_PHYS_OFFSET); static struct madt_ioapic *get_ioapic_by_gsi(uint32_t gsi) {
// Search through every I/O APIC to find its GSI
for (int i = 0; i < madt_io_apics.length; i++) {
struct madt_ioapic *ioapic = madt_io_apics.data[i];
if (ioapic->gsib <= gsi &&
ioapic->gsib + get_gsi_count(ioapic->addr) > gsi) {
return ioapic;
}
}
/* // Return NULL if none was found
* ── Step 3: Software-enable the LAPIC via the SVR ──────────────────── return NULL;
* }
* Bit 8 = Software Enable. The lower 8 bits are the "spurious interrupt
* vector" delivered if the CPU acknowledges an interrupt that was
* retracted by the LAPIC; 0xFF is the conventional choice.
*/
lapic_write(LAPIC_SVR, LAPIC_SVR_ENABLE | 0xFF);
/* void ioapic_redirect_gsi(uint32_t gsi, uint8_t vec, uint16_t flags) {
* ── Step 4: Configure LINT0 as ExtINT (i8259 pass-through) ────────── // Get I/O APIC address of the GSI
* size_t io_apic = get_ioapic_by_gsi(gsi)->addr;
* On a standard PC the i8259 INTR pin is wired to the BSP's LINT0.
* Setting LINT0 to ExtINT delivery mode makes the LAPIC act as a
* transparent relay: the i8259 interrupt acknowledge cycle goes through
* normally, the full 8-bit vector comes from the i8259, and the CPU's
* existing IDT entries + irq.c EOI code all keep working unchanged.
*
* This is the "Virtual Wire" mode described in the Intel MP Spec.
*/
lapic_write(LAPIC_LVT_LINT0, LAPIC_LVT_DM_EXTINT);
/* uint32_t low_index = 0x10 + (gsi - get_ioapic_by_gsi(gsi)->gsib) * 2;
* ── Step 5: Configure LINT1 as NMI ─────────────────────────────────── uint32_t high_index = low_index + 1;
*
* LINT1 is the NMI pin on standard PCs. Delivery mode = 4 (NMI),
* unmasked, edge-triggered (the default when LAPIC_LVT_LEVEL is clear).
*/
lapic_write(LAPIC_LVT_LINT1, LAPIC_LVT_DM_NMI);
/* uint32_t high = ioapic_read(io_apic, high_index);
* ── Step 6: Mask LVT entries we are not yet using ────────────────────
*
* Timer, error, and (if present) thermal / perf entries all start masked.
* Assign distinct vectors in the 0xF0-0xFE range so that if one fires
* spuriously the IDT handler can identify it and send EOI.
*/
lapic_write(LAPIC_LVT_TIMER, LAPIC_LVT_MASKED | 0xFD);
lapic_write(LAPIC_LVT_ERROR, LAPIC_LVT_MASKED | 0xFE);
/* Version register: bits [23:16] = max LVT entry index */ // Set APIC ID
uint32_t ver = lapic_read(LAPIC_VER); high &= ~0xFF000000;
uint32_t max_lvt = (ver >> 16) & 0xFF; high |= ioapic_read(io_apic, 0) << 24;
if (max_lvt >= 4) lapic_write(LAPIC_LVT_THERMAL, LAPIC_LVT_MASKED | 0xFC); ioapic_write(io_apic, high_index, high);
if (max_lvt >= 5) lapic_write(LAPIC_LVT_PERF, LAPIC_LVT_MASKED | 0xFB);
/* uint32_t low = ioapic_read(io_apic, low_index);
* ── Step 7: Clear the Error Status Register ───────────────────────────
*
* The APIC spec requires writing ESR twice to clear stale error bits.
*/
lapic_write(LAPIC_ESR, 0);
lapic_write(LAPIC_ESR, 0);
/* Dismiss any stale in-service interrupt */ // Unmask the IRQ
lapic_write(LAPIC_EOI, 0); low &= ~(1 << 16);
/* // Set to physical delivery mode
* ── Step 8: Set Task Priority to 0 ─────────────────────────────────── low &= ~(1 << 11);
*
* TPR = 0 means the CPU will accept all interrupt priorities. // Set to fixed delivery mode
* Raise this later if need to block lower-priority interrupts. low &= ~0x700;
*/
lapic_write(LAPIC_TPR, 0); // Set delivery vector
low &= ~0xFF;
low |= vec;
// Active high(0) or low(1)
if (flags & 2) {
low |= 1 << 13;
}
// Edge(0) or level(1) triggered
if (flags & 8) {
low |= 1 << 15;
}
ioapic_write(io_apic, low_index, low);
}
void ioapic_redirect_irq(uint32_t irq, uint8_t vect) {
// Use ISO table to find flags and interrupt overrides
for (int i = 0; i < madt_isos.length; i++) {
if (madt_isos.data[i]->irq_source == irq) {
ioapic_redirect_gsi(madt_isos.data[i]->gsi, vect,
madt_isos.data[i]->flags);
return;
}
}
ioapic_redirect_gsi(irq, vect, 0);
}
void apic_send_ipi(uint32_t lapic_id, uint32_t flags) {
if (x2apic) {
// Write MSR directly, because lapic_write receives a 32-bit argument
// Whilst in x2APIC, 0x830 is a 64-bit register
wrmsr(0x830, ((uint64_t)lapic_id << 32) | flags);
} else {
lapic_write(0x310, (lapic_id << 24));
lapic_write(0x300, flags);
}
}
void apic_eoi(void) {
// Writing any other value different than 0 may cause a #GP exception
lapic_write(0xB0, 0);
}
void timer_stop_sched(void) {
lapic_write(0x380, 0);
lapic_write(0x320, (1 << 16));
}
void timer_sched_oneshot(uint8_t isr, uint32_t us) {
timer_stop_sched();
lapic_write(0x320, isr | 0x20000);
lapic_write(0x3E0, 3);
lapic_write(0x380,
((prcb_return_current_cpu()->tick_in_10ms * (us / 1000))) / 10);
}
void apic_init(void) {
pic_init();
lapic_addr = acpi_get_lapic();
ioapic_redirect_irq(0, 48);
}
printf("[LAPIC] Online. ID=%u version=0x%02x max_lvt=%u\n",
lapic_id(), ver & 0xFF, max_lvt);
}
+9 -69
View File
@@ -2,73 +2,13 @@
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
/*
* Local APIC (xAPIC mode, MMIO access)
* Register offsets are byte offsets; we shift right by 2 for uint32_t indexing.
*/
/* ── Register offsets ─────────────────────────────────────────────────────── */ void apic_eoi(void);
#define LAPIC_ID 0x020 /* LAPIC ID (bits [27:24] on P4, [31:24] on modern) */ void apic_init(void);
#define LAPIC_VER 0x030 /* Version register */ void apic_send_ipi(uint32_t lapic_id, uint32_t flags);
#define LAPIC_TPR 0x080 /* Task Priority Register */ void ioapic_redirect_irq(uint32_t irq, uint8_t vect);
#define LAPIC_APR 0x090 /* Arbitration Priority (RO) */ uint32_t lapic_read(uint32_t reg);
#define LAPIC_PPR 0x0A0 /* Processor Priority (RO) */ void lapic_write(uint32_t reg, uint32_t value);
#define LAPIC_EOI 0x0B0 /* End-Of-Interrupt (write 0 to ack) */ uint8_t lapic_get_id(void);
#define LAPIC_RRD 0x0C0 /* Remote Read (RO) */ void lapic_init(uint8_t processor_id);
#define LAPIC_LDR 0x0D0 /* Logical Destination */ void timer_sched_oneshot(uint8_t isr, uint32_t us);
#define LAPIC_DFR 0x0E0 /* Destination Format */
#define LAPIC_SVR 0x0F0 /* Spurious Interrupt Vector */
#define LAPIC_ESR 0x280 /* Error Status Register */
#define LAPIC_ICR_LO 0x300 /* Interrupt Command (low 32 bits) */
#define LAPIC_ICR_HI 0x310 /* Interrupt Command (high 32 bits) */
#define LAPIC_LVT_TIMER 0x320 /* LVT: APIC timer */
#define LAPIC_LVT_THERMAL 0x330 /* LVT: Thermal sensor */
#define LAPIC_LVT_PERF 0x340 /* LVT: Performance monitoring */
#define LAPIC_LVT_LINT0 0x350 /* LVT: Local interrupt pin 0 */
#define LAPIC_LVT_LINT1 0x360 /* LVT: Local interrupt pin 1 */
#define LAPIC_LVT_ERROR 0x370 /* LVT: Error */
#define LAPIC_TIMER_ICR 0x380 /* Timer Initial Count */
#define LAPIC_TIMER_CCR 0x390 /* Timer Current Count (RO) */
#define LAPIC_TIMER_DCR 0x3E0 /* Timer Divide Configuration */
/* ── SVR flags ────────────────────────────────────────────────────────────── */
#define LAPIC_SVR_ENABLE (1u << 8) /* Software-enable the LAPIC */
/* ── LVT delivery modes (bits [10:8]) ────────────────────────────────────── */
#define LAPIC_LVT_DM_FIXED (0u << 8) /* Fixed delivery */
#define LAPIC_LVT_DM_SMI (2u << 8)
#define LAPIC_LVT_DM_NMI (4u << 8) /* NMI */
#define LAPIC_LVT_DM_EXTINT (7u << 8) /* ExtINT: pass-through from i8259 */
/* ── LVT misc flags ───────────────────────────────────────────────────────── */
#define LAPIC_LVT_MASKED (1u << 16) /* Mask this LVT entry */
#define LAPIC_LVT_LEVEL (1u << 15) /* Level-triggered (vs edge) */
#define LAPIC_LVT_ACTIVE_LOW (1u << 13) /* Active-low polarity */
/* ── IA32_APIC_BASE MSR ───────────────────────────────────────────────────── */
#define IA32_APIC_BASE_MSR 0x1B
#define IA32_APIC_BASE_ENABLE (1u << 11) /* APIC global enable bit */
#define IA32_APIC_BASE_BSP (1u << 8) /* Bootstrap processor flag */
/* ── Public API ───────────────────────────────────────────────────────────── */
/**
* lapic_init - Map the LAPIC MMIO, re-enable the APIC global bit in the MSR
* (which was cleared earlier to let the i8259 work), then bring
* the LAPIC online with LINT0=ExtINT so the i8259/PIT path is
* completely preserved.
*
* Call AFTER uacpi_initialize() so that paging and the heap are live.
*/
void lapic_init(void);
/**
* lapic_eoi - Signal end-of-interrupt to the LAPIC.
*/
void lapic_eoi(void);
/** lapic_id - Return the LAPIC ID of the current CPU. */
uint32_t lapic_id(void);
/** lapic_get_phys_base - Return the physical base address from the MSR. */
uint64_t lapic_get_phys_base(void);
+59
View File
@@ -0,0 +1,59 @@
#include <stdint.h>
#include <stdbool.h>
#include "arch/x86_64/asm/asm.h"
#include "halt.h"
#include "arch/x86_64/sys/apic.h"
extern bool is_smp;
bool is_halting = false;
uint8_t is_pausing = false;
void halt_current_cpu(void) {
for (;;) {
cli();
halt();
}
}
void halt_other_cpus(void) {
if (!is_smp)
return;
is_halting = true;
uint64_t icr = 0;
icr |= (0b100) << 8; // set delivery mode to nmi
icr |= (0b11) << 18; // set destination shorthand to all excluding self
lapic_write(0x300, icr);
lapic_write(0x310, icr >> 32);
}
void pause_other_cpus(void) {
if (!is_smp)
return;
is_pausing = 0;
is_pausing |= PAUSING;
uint64_t icr = 0;
icr |= (0b100) << 8;
icr |= (0b11) << 18;
lapic_write(0x300, icr);
lapic_write(0x310, icr >> 32);
}
void unpause_other_cpus(void) {
if (!is_smp)
return;
is_pausing = 0;
is_pausing |= UNPAUSING;
uint64_t icr = 0;
icr |= (0b100) << 8;
icr |= (0b11) << 18;
lapic_write(0x300, icr);
lapic_write(0x310, icr >> 32);
}
+9
View File
@@ -0,0 +1,9 @@
#pragma once
#define PAUSING (1 << 0)
#define UNPAUSING (1 << 1)
void halt_current_cpu(void);
void halt_other_cpus(void);
void pause_other_cpus(void);
void unpause_other_cpus(void);
+32
View File
@@ -0,0 +1,32 @@
#include <uacpi/uacpi.h>
#include <stdint.h>
#include "arch/x86_64/fw/acpi.h"
struct hpet_table {
acpi_header_t header;
uint8_t hardware_rev_id;
uint8_t comparator_count : 5;
uint8_t counter_size : 1;
uint8_t reserved : 1;
uint8_t legacy_replacement : 1;
uint16_t pci_vendor_id;
acpi_gas_t address;
uint8_t hpet_number;
uint16_t minimum_tick;
uint8_t page_protection;
} __attribute__((packed));
struct hpet {
uint64_t general_capabilities;
uint64_t reserved;
uint64_t general_configuration;
uint64_t reserved2;
uint64_t general_int_status;
uint64_t reserved3;
uint64_t reserved4[24];
uint64_t main_counter_value;
uint64_t reserved5;
};
uint64_t hpet_counter_value(void);
void hpet_sleep(uint64_t us);
-166
View File
@@ -1,166 +0,0 @@
#include "pic.h"
#include "arch/x86_64/cpu/io.h"
#include <stdbool.h>
#define PIC1_COMMAND_PORT 0x20
#define PIC1_DATA_PORT 0x21
#define PIC2_COMMAND_PORT 0xA0
#define PIC2_DATA_PORT 0xA1
// Initialization Control Word 1
// -----------------------------
// 0 IC4 if set, the PIC expects to receive ICW4 during initialization
// 1 SGNL if set, only 1 PIC in the system; if unset, the PIC is cascaded with slave PICs
// and ICW3 must be sent to controller
// 2 ADI call address interval, set: 4, not set: 8; ignored on x86, set to 0
// 3 LTIM if set, operate in level triggered mode; if unset, operate in edge triggered mode
// 4 INIT set to 1 to initialize PIC
// 5-7 ignored on x86, set to 0
enum {
PIC_ICW1_ICW4 = 0x01,
PIC_ICW1_SINGLE = 0x02,
PIC_ICW1_INTERVAL4 = 0x04,
PIC_ICW1_LEVEL = 0x08,
PIC_ICW1_INITIALIZE = 0x10
} PIC_ICW1;
// Initialization Control Word 4
// -----------------------------
// 0 uPM if set, PIC is in 80x86 mode; if cleared, in MCS-80/85 mode
// 1 AEOI if set, on last interrupt acknowledge pulse, controller automatically performs
// end of interrupt operation
// 2 M/S only use if BUF is set; if set, selects buffer master; otherwise, selects buffer slave
// 3 BUF if set, controller operates in buffered mode
// 4 SFNM specially fully nested mode; used in systems with large number of cascaded controllers
// 5-7 reserved, set to 0
enum {
PIC_ICW4_8086 = 0x1,
PIC_ICW4_AUTO_EOI = 0x2,
PIC_ICW4_BUFFER_MASTER = 0x4,
PIC_ICW4_BUFFER_SLAVE = 0x0,
PIC_ICW4_BUFFERRED = 0x8,
PIC_ICW4_SFNM = 0x10,
} PIC_ICW4;
enum {
PIC_CMD_END_OF_INTERRUPT = 0x20,
PIC_CMD_READ_IRR = 0x0A,
PIC_CMD_READ_ISR = 0x0B,
} PIC_CMD;
static uint16_t g_PicMask = 0xffff;
static bool g_AutoEoi = false;
void i8259_SetMask(uint16_t newMask)
{
g_PicMask = newMask;
x86_64_outb(PIC1_DATA_PORT, g_PicMask & 0xFF);
x86_64_iowait();
x86_64_outb(PIC2_DATA_PORT, g_PicMask >> 8);
x86_64_iowait();
}
uint16_t i8259_GetMask()
{
return x86_64_inb(PIC1_DATA_PORT) | (x86_64_inb(PIC2_DATA_PORT) << 8);
}
void i8259_Configure(uint8_t offsetPic1, uint8_t offsetPic2, bool autoEoi)
{
// Mask everything
i8259_SetMask(0xFFFF);
// initialization control word 1
x86_64_outb(PIC1_COMMAND_PORT, PIC_ICW1_ICW4 | PIC_ICW1_INITIALIZE);
x86_64_iowait();
x86_64_outb(PIC2_COMMAND_PORT, PIC_ICW1_ICW4 | PIC_ICW1_INITIALIZE);
x86_64_iowait();
// initialization control word 2 - the offsets
x86_64_outb(PIC1_DATA_PORT, offsetPic1);
x86_64_iowait();
x86_64_outb(PIC2_DATA_PORT, offsetPic2);
x86_64_iowait();
// initialization control word 3
x86_64_outb(PIC1_DATA_PORT, 0x4); // tell PIC1 that it has a slave at IRQ2 (0000 0100)
x86_64_iowait();
x86_64_outb(PIC2_DATA_PORT, 0x2); // tell PIC2 its cascade identity (0000 0010)
x86_64_iowait();
// initialization control word 4
uint8_t icw4 = PIC_ICW4_8086;
if (autoEoi) {
icw4 |= PIC_ICW4_AUTO_EOI;
}
x86_64_outb(PIC1_DATA_PORT, icw4);
x86_64_iowait();
x86_64_outb(PIC2_DATA_PORT, icw4);
x86_64_iowait();
// mask all interrupts until they are enabled by the device driver
i8259_SetMask(0xFFFF);
}
void i8259_SendEndOfInterrupt(int irq)
{
if (irq >= 8)
x86_64_outb(PIC2_COMMAND_PORT, PIC_CMD_END_OF_INTERRUPT);
x86_64_outb(PIC1_COMMAND_PORT, PIC_CMD_END_OF_INTERRUPT);
}
void i8259_Disable()
{
i8259_SetMask(0xFFFF);
}
void i8259_Mask(int irq)
{
i8259_SetMask(g_PicMask | (1 << irq));
}
void i8259_Unmask(int irq)
{
i8259_SetMask(g_PicMask & ~(1 << irq));
}
uint16_t i8259_ReadIrqRequestRegister()
{
x86_64_outb(PIC1_COMMAND_PORT, PIC_CMD_READ_IRR);
x86_64_outb(PIC2_COMMAND_PORT, PIC_CMD_READ_IRR);
return ((uint16_t)x86_64_inb(PIC2_COMMAND_PORT)) | (((uint16_t)x86_64_inb(PIC2_COMMAND_PORT)) << 8);
}
uint16_t i8259_ReadInServiceRegister()
{
x86_64_outb(PIC1_COMMAND_PORT, PIC_CMD_READ_ISR);
x86_64_outb(PIC2_COMMAND_PORT, PIC_CMD_READ_ISR);
return ((uint16_t)x86_64_inb(PIC2_COMMAND_PORT)) | (((uint16_t)x86_64_inb(PIC2_COMMAND_PORT)) << 8);
}
bool i8259_Probe()
{
i8259_Disable();
i8259_SetMask(0x1337);
return i8259_GetMask() == 0x1337;
}
static const PICDriver g_PicDriver = {
.Name = "8259 PIC",
.Probe = &i8259_Probe,
.Initialize = &i8259_Configure,
.Disable = &i8259_Disable,
.SendEndOfInterrupt = &i8259_SendEndOfInterrupt,
.Mask = &i8259_Mask,
.Unmask = &i8259_Unmask,
};
const PICDriver* i8259_GetDriver()
{
return &g_PicDriver;
}
-10
View File
@@ -1,10 +0,0 @@
#pragma once
#include "pic.h"
const PICDriver* i8259_GetDriver();
uint16_t i8259_GetMask();
void i8259_SetMask(uint16_t newMask);
void i8259_Configure(uint8_t offsetPic1, uint8_t offsetPic2, bool autoEoi);
void i8259_Disable();
-359
View File
@@ -1,359 +0,0 @@
#include "ioapic.h"
#include "apic.h"
#include "mm/vmm.h"
#include "mm/memory.h"
#include "libk/stdio.h"
#include <uacpi/tables.h> /* uacpi_table_find_by_signature / uacpi_table_unref */
#include "pic.h"
/* ══════════════════════════════════════════════════════════════════════════
* ACPI MADT structures
* (Defined locally so we don't depend on uACPI's internal acpi.h layout.)
* ══════════════════════════════════════════════════════════════════════════ */
extern const PICDriver* g_Driver; // old pic driver
bool g_IOAPIC = false; // IOAPIC enabled
typedef struct {
uint8_t signature[4]; /* "APIC" */
uint32_t length;
uint8_t revision;
uint8_t checksum;
uint8_t oem_id[6];
uint8_t oem_table_id[8];
uint32_t oem_revision;
uint32_t creator_id;
uint32_t creator_revision;
/* --- MADT-specific -------------------------------------------------- */
uint32_t local_apic_addr; /* Default LAPIC physical address (32-bit) */
uint32_t flags; /* bit 0 = dual 8259 PICs present */
/* followed by variable-length Interrupt Controller Structure entries */
} __attribute__((packed)) madt_t;
typedef struct {
uint8_t type;
uint8_t length;
} __attribute__((packed)) madt_entry_hdr_t;
/* Type 0: Processor Local APIC */
typedef struct {
madt_entry_hdr_t hdr;
uint8_t uid;
uint8_t apic_id;
uint32_t flags; /* bit 0 = enabled */
} __attribute__((packed)) madt_lapic_t;
/* Type 1: I/O APIC */
typedef struct {
madt_entry_hdr_t hdr;
uint8_t id;
uint8_t reserved;
uint32_t address; /* Physical MMIO base */
uint32_t gsi_base; /* First GSI handled by this IOAPIC */
} __attribute__((packed)) madt_ioapic_t;
/* Type 2: Interrupt Source Override */
typedef struct {
madt_entry_hdr_t hdr;
uint8_t bus; /* 0 = ISA */
uint8_t source; /* ISA IRQ number */
uint32_t gsi; /* Remapped GSI */
uint16_t flags; /* bits [1:0] = polarity, bits [3:2] = trigger mode */
} __attribute__((packed)) madt_iso_t;
/* Type 4: Local APIC NMI */
typedef struct {
madt_entry_hdr_t hdr;
uint8_t uid; /* 0xFF = all processors */
uint16_t flags;
uint8_t lint; /* 0 or 1 */
} __attribute__((packed)) madt_nmi_t;
/* ══════════════════════════════════════════════════════════════════════════
* Internal state
* ══════════════════════════════════════════════════════════════════════════ */
typedef struct {
volatile uint32_t *base; /* Virtual address of IOAPIC MMIO */
uint32_t gsi_base;
uint32_t gsi_count; /* Number of redirection entries */
} ioapic_t;
static ioapic_t g_ioapics[IOAPIC_MAX];
static int g_ioapic_count = 0;
/* ISA interrupt source overrides (max 16 ISA IRQs) */
typedef struct {
bool present;
uint32_t gsi;
bool active_low;
bool level;
} iso_t;
static iso_t g_iso[16]; /* indexed by ISA IRQ (source) */
/* ══════════════════════════════════════════════════════════════════════════
* Low-level IOAPIC MMIO access
*
* The IOAPIC has two MMIO registers:
* base+0x00 IOREGSEL index register (write which register to access)
* base+0x10 IOWIN data window (read/write the selected register)
* ══════════════════════════════════════════════════════════════════════════ */
static uint32_t ioapic_read(const ioapic_t *io, uint8_t reg) {
*((volatile uint32_t *)(io->base + (0x00 >> 2))) = reg;
return *((volatile uint32_t *)(io->base + (0x10 >> 2)));
}
static void ioapic_write(const ioapic_t *io, uint8_t reg, uint32_t val) {
*((volatile uint32_t *)(io->base + (0x00 >> 2))) = reg;
*((volatile uint32_t *)(io->base + (0x10 >> 2))) = val;
}
/* ── Find which IOAPIC owns a given GSI ─────────────────────────────────── */
static ioapic_t *ioapic_for_gsi(uint32_t gsi) {
for (int i = 0; i < g_ioapic_count; i++) {
ioapic_t *io = &g_ioapics[i];
if (gsi >= io->gsi_base && gsi < io->gsi_base + io->gsi_count)
return io;
}
return NULL;
}
/* ══════════════════════════════════════════════════════════════════════════
* Public API
* ══════════════════════════════════════════════════════════════════════════ */
uint32_t ioapic_gsi_for_isa_irq(uint8_t isa_irq) {
if (isa_irq < 16 && g_iso[isa_irq].present)
return g_iso[isa_irq].gsi;
return isa_irq;
}
void ioapic_redirect(uint32_t gsi, uint8_t vector, uint8_t dest_lapic,
bool active_low, bool level, bool masked) {
ioapic_t *io = ioapic_for_gsi(gsi);
if (!io) {
printf("[IOAPIC] No IOAPIC for GSI %u\n", gsi);
return;
}
uint8_t idx = (uint8_t)(gsi - io->gsi_base);
uint32_t lo = (uint32_t)vector
| IOAPIC_RTE_DM_FIXED
| (active_low ? IOAPIC_RTE_ACTIVE_LOW : 0)
| (level ? IOAPIC_RTE_LEVEL : 0)
| (masked ? IOAPIC_RTE_MASKED : 0);
uint32_t hi = (uint32_t)dest_lapic << 24;
/* Write high word first, then low (avoids momentary spurious delivery) */
ioapic_write(io, IOAPIC_REDTBL_HI(idx), hi);
ioapic_write(io, IOAPIC_REDTBL_LO(idx), lo);
}
void ioapic_mask_gsi(uint32_t gsi) {
ioapic_t *io = ioapic_for_gsi(gsi);
if (!io) return;
uint8_t idx = (uint8_t)(gsi - io->gsi_base);
uint32_t lo = ioapic_read(io, IOAPIC_REDTBL_LO(idx));
ioapic_write(io, IOAPIC_REDTBL_LO(idx), lo | IOAPIC_RTE_MASKED);
}
void ioapic_unmask_gsi(uint32_t gsi) {
ioapic_t *io = ioapic_for_gsi(gsi);
if (!io) return;
uint8_t idx = (uint8_t)(gsi - io->gsi_base);
uint32_t lo = ioapic_read(io, IOAPIC_REDTBL_LO(idx));
ioapic_write(io, IOAPIC_REDTBL_LO(idx), lo & ~IOAPIC_RTE_MASKED);
}
/* ══════════════════════════════════════════════════════════════════════════
* Initialisation
* ══════════════════════════════════════════════════════════════════════════ */
void ioapic_init(void) {
/*
* ── Step 1: Find the MADT via uACPI ──────────────────────────────────
*
* The MADT signature in ACPI is "APIC" (not "MADT").
* uacpi_table_find_by_signature returns a handle whose .ptr field points
* to the raw table data in (HHDM-mapped) physical memory.
*/
struct uacpi_table madt_table;
uacpi_status st = uacpi_table_find_by_signature("APIC", &madt_table);
if (uacpi_unlikely_error(st)) {
printf("[IOAPIC] Could not find MADT: %s\n", uacpi_status_to_string(st));
return;
}
madt_t *madt = (madt_t *)madt_table.ptr;
printf("[IOAPIC] MADT @ virt 0x%lx len=%u lapic_addr=0x%08x\n",
(uint64_t)madt, madt->length, madt->local_apic_addr);
/*
* ── Step 2: Walk the MADT entry list ─────────────────────────────────
*
* Entries start immediately after the fixed 44-byte MADT header and run
* until madt->length bytes from the table base.
*/
const uint8_t *entry_ptr = (const uint8_t *)madt + sizeof(madt_t);
const uint8_t *madt_end = (const uint8_t *)madt + madt->length;
while (entry_ptr < madt_end) {
const madt_entry_hdr_t *hdr = (const madt_entry_hdr_t *)entry_ptr;
if (hdr->length < 2) {
printf("[IOAPIC] MADT entry with length < 2, stopping parse\n");
break;
}
switch (hdr->type) {
/* ── Type 0: Processor Local APIC ──────────────────────────────── */
case 0: {
const madt_lapic_t *e = (const madt_lapic_t *)entry_ptr;
printf("[IOAPIC] MADT[0] Processor UID=%u LAPIC ID=%u flags=0x%x%s\n",
e->uid, e->apic_id, e->flags,
(e->flags & 1) ? "" : " (disabled)");
break;
}
/* ── Type 1: I/O APIC ───────────────────────────────────────────── */
case 1: {
const madt_ioapic_t *e = (const madt_ioapic_t *)entry_ptr;
if (g_ioapic_count >= IOAPIC_MAX) {
printf("[IOAPIC] Too many IOAPICs, skipping ID=%u\n", e->id);
break;
}
ioapic_t *io = &g_ioapics[g_ioapic_count];
io->gsi_base = e->gsi_base;
/*
* Map the IOAPIC MMIO page. Like the LAPIC, the HHDM covers the
* IOAPIC's physical address (typically 0xFEC00000) so we just add
* MEM_PHYS_OFFSET. Two MMIO registers are accessed (offsets 0 and
* 0x10) so one 4 KiB page is sufficient.
*
* TODO: Mark the page UC (cache-disable) in the PTE when VMM
* gains support for PAT / PCD flags.
*/
uint64_t phys = (uint64_t)e->address;
uintptr_t virt = (uintptr_t)phys + MEM_PHYS_OFFSET;
/* The HHDM loop in vmm_init already covered this range; if not,
* uncomment the explicit map call below: */
/* vmm_map_page(kernel_pagemap, virt, phys,
PAGE_READ | PAGE_WRITE | PAGE_NO_EXECUTE, Size4KiB); */
io->base = (volatile uint32_t *)virt;
/* Read version register to discover number of redirection entries */
uint32_t ver = ioapic_read(io, IOAPIC_REG_VER);
io->gsi_count = ((ver >> 16) & 0xFF) + 1; /* bits [23:16] = max entry index */
printf("[IOAPIC] MADT[1] ID=%u phys=0x%08x GSI base=%u entries=%u\n",
e->id, e->address, io->gsi_base, io->gsi_count);
/*
* ── Mask every redirection entry ─────────────────────────────
*
* We keep all entries masked at boot time. Legacy ISA IRQs are
* handled by the i8259 → LAPIC LINT0 ExtINT path, not via the
* IOAPIC. PCI devices can be connected later with ioapic_redirect().
*/
for (uint32_t n = 0; n < io->gsi_count; n++) {
ioapic_write(io, IOAPIC_REDTBL_HI(n), 0);
ioapic_write(io, IOAPIC_REDTBL_LO(n), IOAPIC_RTE_MASKED | 0xFF);
}
g_ioapic_count++;
break;
}
/* ── Type 2: Interrupt Source Override ──────────────────────────── */
case 2: {
const madt_iso_t *e = (const madt_iso_t *)entry_ptr;
/* flags bits [1:0]: 00/11 = conforms to bus (ISA = active high edge)
* 01 = active high, 11 = active low
* flags bits [3:2]: 00/11 = conforms to bus (ISA = edge)
* 01 = edge, 11 = level */
bool active_low = ((e->flags & 0x3) == 3);
bool level = ((e->flags >> 2) & 0x3) == 3;
printf("[IOAPIC] MADT[2] ISA IRQ %u -> GSI %u %s %s\n",
e->source, e->gsi,
active_low ? "active-low" : "active-high",
level ? "level" : "edge");
if (e->source < 16) {
g_iso[e->source].present = true;
g_iso[e->source].gsi = e->gsi;
g_iso[e->source].active_low = active_low;
g_iso[e->source].level = level;
}
break;
}
/* ── Type 4: Local APIC NMI ─────────────────────────────────────── */
case 4: {
const madt_nmi_t *e = (const madt_nmi_t *)entry_ptr;
printf("[IOAPIC] MADT[4] NMI UID=0x%02x LINT%u\n",
e->uid, e->lint);
break;
}
default:
printf("[IOAPIC] MADT entry type=%u length=%u (skipped)\n",
hdr->type, hdr->length);
break;
}
entry_ptr += hdr->length;
}
uacpi_table_unref(&madt_table);
printf("[IOAPIC] Init done: %d IOAPIC(s) found\n", g_ioapic_count);
}
void irq_redirect_to_apic(uint8_t isa_irq, uint8_t vector,
uint8_t dest_lapic, bool masked)
{
if (isa_irq >= 16) {
printf("[IRQ] irq_redirect_to_apic: ISA IRQ %u out of range\n", isa_irq);
return;
}
uint32_t gsi = ioapic_gsi_for_isa_irq(isa_irq);
/* Get polarity/trigger from MADT ISO or use ISA defaults */
bool active_low = false;
bool level = false;
if (isa_irq < 16 && g_iso[isa_irq].present) {
active_low = g_iso[isa_irq].active_low;
level = g_iso[isa_irq].level;
} else {
/* Standard ISA: active-high, edge-triggered (except some like IRQ0/8) */
if (isa_irq == 0 || isa_irq == 8) {
level = true; /* often level on real hardware */
}
}
/* Mask in the 8259 so it stops firing through LINT0 */
if (g_Driver) {
g_Driver->Mask(isa_irq);
}
/* Programme IOAPIC redirection entry */
ioapic_redirect(gsi, vector, dest_lapic,
active_low, level, masked);
printf("[IRQ] Redirected ISA IRQ %u -> GSI %u vector 0x%02x LAPIC %u %s %s\n",
isa_irq, gsi, vector, dest_lapic,
active_low ? "active-low" : "active-high",
level ? "level" : "edge");
g_IOAPIC = true;
}
-76
View File
@@ -1,76 +0,0 @@
#pragma once
#include <stdint.h>
#include <stdbool.h>
/*
* I/O APIC driver
*
* The IOAPIC is found by parsing the ACPI MADT table via uACPI.
* All redirection entries are masked at init time; use ioapic_redirect() /
* ioapic_unmask_irq() to enable individual GSIs for PCI devices later.
*
* Legacy ISA IRQs (0-15) are intentionally left masked here because they are
* delivered through the i8259 → LAPIC LINT0 ExtINT path instead.
*/
/* Maximum IOAPICs supported (1 is typical for QEMU/BOCHS) */
#define IOAPIC_MAX 4
/* ── IOAPIC MMIO register indices (written to IOREGSEL) ─────────────────── */
#define IOAPIC_REG_ID 0x00 /* APIC ID */
#define IOAPIC_REG_VER 0x01 /* Version / max redirection entries */
#define IOAPIC_REG_ARB 0x02 /* Arbitration ID */
#define IOAPIC_REDTBL_LO(n) (0x10 + (n) * 2) /* Redirection entry n, low */
#define IOAPIC_REDTBL_HI(n) (0x10 + (n) * 2 + 1) /* Redirection entry n, high */
/* ── Redirection table entry flags (low 32-bit word) ────────────────────── */
#define IOAPIC_RTE_MASKED (1u << 16) /* 1 = masked (disabled) */
#define IOAPIC_RTE_LEVEL (1u << 15) /* 1 = level-triggered, 0 = edge */
#define IOAPIC_RTE_ACTIVE_LOW (1u << 13) /* 1 = active low, 0 = active high */
#define IOAPIC_RTE_LOGICAL (1u << 11) /* 1 = logical destination mode */
#define IOAPIC_RTE_DM_FIXED (0u << 8) /* Fixed delivery */
#define IOAPIC_RTE_DM_NMI (4u << 8) /* NMI */
/* bits [7:0] hold the IDT vector */
/* ── Public API ──────────────────────────────────────────────────────────── */
/**
* ioapic_init - Parse the ACPI MADT, locate all I/O APICs and their GSI
* bases, record any ISA interrupt source overrides, then mask
* every redirection entry.
*
* Must be called after uacpi_initialize() (needs MADT accessible).
*/
void ioapic_init(void);
/**
* ioapic_redirect - Programme a single redirection table entry.
*
* @gsi Global System Interrupt number (from MADT or known fixed GSI).
* @vector IDT vector the CPU will see (e.g. 0x20 + irq_number).
* @dest_lapic Physical LAPIC ID of the target CPU.
* @active_low true if device uses active-low polarity.
* @level true if device uses level-triggered signalling.
* @masked true to programme the entry but leave it masked.
*/
void ioapic_redirect(uint32_t gsi, uint8_t vector, uint8_t dest_lapic,
bool active_low, bool level, bool masked);
/**
* ioapic_mask_gsi - Mask (disable) a GSI redirection entry.
* ioapic_unmask_gsi - Unmask (enable) a GSI redirection entry.
*/
void ioapic_mask_gsi(uint32_t gsi);
void ioapic_unmask_gsi(uint32_t gsi);
/**
* ioapic_gsi_for_isa_irq - Look up the GSI that corresponds to an ISA IRQ
* number, accounting for any MADT interrupt source
* overrides (e.g. ISA IRQ 0 → GSI 2 on BOCHS).
*
* Returns the GSI, or the IRQ number itself if no override is defined.
*/
uint32_t ioapic_gsi_for_isa_irq(uint8_t isa_irq);
void irq_redirect_to_apic(uint8_t isa_irq, uint8_t vector, uint8_t dest_lapic, bool masked);
-112
View File
@@ -1,112 +0,0 @@
#include "irq.h"
#include "i8259.h"
#include "arch/x86_64/cpu/io.h"
#include <stddef.h>
#include "libk/arrays.h"
#include "libk/stdio.h"
#include "libk/debug.h"
#include "apic.h"
#include "ioapic.h"
#define PIC_REMAP_OFFSET 0x20
#define MODULE "PIC"
IRQHandler g_IRQHandlers[16];
static IRQHandler g_APICHandlers[256];
const PICDriver* g_Driver = NULL;
extern bool g_IOAPIC;
void x86_64_IRQ_Handler(Registers *regs)
{
int irq = regs->interrupt - PIC_REMAP_OFFSET;
g_Driver->SendEndOfInterrupt(irq);
if (g_IRQHandlers[irq] != NULL)
{
// handle IRQ
g_IRQHandlers[irq](regs);
}
else
{
log_warn(MODULE, "Unhandled IRQ %d...", irq);
}
}
void x86_64_APIC_IRQ_Handler(Registers* regs)
{
uint8_t vector = regs->interrupt;
lapic_eoi();
if (g_APICHandlers[vector] != NULL) {
g_APICHandlers[vector](regs);
} else {
log_warn("APIC", "Unhandled vector 0x%02x", vector);
}
// ← This is the key difference from PIC!
}
void x86_64_IRQ_Initialize(void)
{
const PICDriver* drivers[] = {
i8259_GetDriver(),
};
for (int i = 0; i < SIZE(drivers); i++) {
if (drivers[i]->Probe()) {
g_Driver = drivers[i];
}
}
if (g_Driver == NULL) {
log_warn(MODULE, "No PIC found!");
return;
}
log_info(MODULE, "Found %s PIC.", g_Driver->Name);
g_Driver->Initialize(PIC_REMAP_OFFSET, PIC_REMAP_OFFSET + 8, false);
// register ISR handlers for each of the 16 irq lines
for (int i = 0; i < 16; i++)
x86_64_ISR_RegisterHandler(PIC_REMAP_OFFSET + i, x86_64_IRQ_Handler);
g_Driver->Unmask(0);
}
void x86_64_IRQ_RegisterHandler(int irq, IRQHandler handler)
{
g_IRQHandlers[irq] = handler;
}
void x86_64_APIC_IRQ_RegisterHandler(uint8_t vector, IRQHandler handler)
{
if (vector < 32) {
printf("[APIC] Warning: vector %u is in reserved range!\n", vector);
}
g_APICHandlers[vector] = handler;
x86_64_ISR_RegisterHandler(vector, x86_64_APIC_IRQ_Handler);
}
void x86_64_APIC_IRQ_RedirectAndRegister(uint8_t isa_irq,
uint8_t vector,
IRQHandler handler)
{
x86_64_APIC_IRQ_RegisterHandler(vector, handler);
irq_redirect_to_apic(isa_irq, vector, lapic_id(), false);
}
void x86_64_IRQ_Unmask(int irq)
{
if (g_Driver) g_Driver->Unmask(irq);
}
-13
View File
@@ -1,13 +0,0 @@
#pragma once
#include "arch/x86_64/boot/isr.h"
typedef void (*IRQHandler)(Registers* regs);
void x86_64_IRQ_Initialize();
void x86_64_IRQ_RegisterHandler(int irq, IRQHandler handler);
void x86_64_IRQ_Unmask(int irq);
void x86_64_APIC_IRQ_RegisterHandler(uint8_t vector, IRQHandler handler);
void x86_64_APIC_IRQ_RedirectAndRegister(uint8_t isa_irq,
uint8_t vector,
IRQHandler handler);
+29
View File
@@ -0,0 +1,29 @@
#include "pic.h"
#include "arch/x86_64/cpu/io.h"
#include <stdbool.h>
#include "arch/x86_64/fw/madt.h"
static void pic_disable(void) {
x86_64_outb(0xA1, 0xFF);
x86_64_outb(0x21, 0xFF);
}
void pic_init(void) {
// There isn't any PIC
if (!(madt->flags & 1)) {
return;
}
// Remap the PIC
x86_64_outb(0x20, 0x11);
x86_64_outb(0xA0, 0x11);
x86_64_outb(0x21, 0x20);
x86_64_outb(0xA1, 0x28);
x86_64_outb(0x21, 4);
x86_64_outb(0xA1, 2);
x86_64_outb(0x21, 1);
x86_64_outb(0xA1, 1);
x86_64_outb(0x21, 0);
x86_64_outb(0xA1, 0);
pic_disable();
}
+1 -12
View File
@@ -1,14 +1,3 @@
#pragma once #pragma once
#include <stdint.h> void pic_init(void);
#include <stdbool.h>
typedef struct {
const char* Name;
bool (*Probe)();
void (*Initialize)(uint8_t offsetPic1, uint8_t offsetPic2, bool autoEoi);
void (*Disable)();
void (*SendEndOfInterrupt)(int irq);
void (*Mask)(int irq);
void (*Unmask)(int irq);
} PICDriver;
-74
View File
@@ -1,74 +0,0 @@
#include "pit.h"
#include "irq.h"
#include "arch/x86_64/cpu/io.h"
#include <stdint.h>
#include "libk/stdio.h"
#include "e9.h"
#include "limine.h"
#include "apic.h"
#include "sched/scheduler.h"
__attribute__((used, section(".limine_requests")))
volatile struct limine_date_at_boot_request boot_request = {
.id = LIMINE_DATE_AT_BOOT_REQUEST_ID,
.revision = 6,
};
#define PIT_BASE_FREQUENCY 1193182
#define PIT_COMMAND_PORT 0x43
#define PIT_CHANNEL0_PORT 0x40
volatile uint64_t g_Ticks = 0;
volatile uint64_t ticks = 0;
uint64_t g_Unixseconds = 0;
extern bool g_IOAPIC;
/* ========================= */
/* IRQ0 Handler (Timer Tick) */
/* ========================= */
void PIT_IRQ_Handler(Registers* regs)
{
(void)regs;
g_Ticks++;
ticks++;
if (ticks >= 1000) {
g_Unixseconds++;
ticks = 0;
}
if (g_IOAPIC == true) {
lapic_eoi();
}
sched_tick();
}
/* ========================= */
/* Initialize PIT */
/* ========================= */
void x86_64_PIT_Initialize(uint32_t frequency)
{
uint16_t divisor = (uint16_t)(PIT_BASE_FREQUENCY / frequency);
printf("PIT divisor = %u\n", divisor);
// Send command byte:
// Channel 0 | lobyte/hibyte | mode 3 (square wave) | binary
x86_64_outb(PIT_COMMAND_PORT, 0x36);
// Send divisor (low byte then high byte)
x86_64_outb(PIT_CHANNEL0_PORT, divisor & 0xFF);
x86_64_outb(PIT_CHANNEL0_PORT, (divisor >> 8) & 0xFF);
g_Unixseconds = boot_request.response->timestamp;
// Register IRQ0 handler (IRQ0 = timer)
x86_64_IRQ_RegisterHandler(0, PIT_IRQ_Handler);
}
/* ========================= */
/* Get tick count */
/* ========================= */
uint64_t PIT_GetTicks(void)
{
return g_Ticks;
}

Some files were not shown because too many files have changed in this diff Show More