diff --git a/src/arch/process_asm.asm b/src/arch/process_asm.asm index 286d825..8be307b 100644 --- a/src/arch/process_asm.asm +++ b/src/arch/process_asm.asm @@ -18,7 +18,7 @@ process_jump_usermode: ; Build the IRETQ stack frame ; 1. SS (User Data Segment) - push 0x23 + push 0x1B ; 2. RSP (User Stack) push rsi @@ -27,7 +27,7 @@ process_jump_usermode: push 0x202 ; 4. CS (User Code Segment) - push 0x1B + push 0x23 ; 5. RIP (Entry Point) push rdi @@ -40,6 +40,12 @@ process_jump_usermode: global context_switch_to context_switch_to: mov rsp, rdi + mov rcx, [rsp + 8192] + xor ecx, ecx + xgetbv + xrstor [rsp] + add rsp, 8192 + add rsp, rcx pop r15 pop r14 diff --git a/src/core/kutils.c b/src/core/kutils.c index 59111f5..340ebde 100644 --- a/src/core/kutils.c +++ b/src/core/kutils.c @@ -7,15 +7,17 @@ #include "../drivers/ACPI/acpi.h" -void memset(void *dest, int val, size_t len) { +void *memset(void *dest, int val, size_t len) { unsigned char *ptr = (unsigned char *)dest; while (len-- > 0) *ptr++ = (unsigned char)val; + return dest; } -void memcpy(void *dest, const void *src, size_t len) { +void *memcpy(void *dest, const void *src, size_t len) { unsigned char *d = (unsigned char *)dest; const unsigned char *s = (const unsigned char *)src; while (len-- > 0) *d++ = *s++; + return dest; } int memcmp(const void *str1, const void *str2, size_t count) { diff --git a/src/core/kutils.h b/src/core/kutils.h index c453042..8ec4ffb 100644 --- a/src/core/kutils.h +++ b/src/core/kutils.h @@ -10,8 +10,8 @@ // Kernel string utilities void *memmove(void *dest, const void *src, uint64_t n); -void memset(void *dest, int val, size_t len); -void memcpy(void *dest, const void *src, size_t len); +void *memset(void *dest, int val, size_t len); +void *memcpy(void *dest, const void *src, size_t len); int memcmp (const void *str1, const void *str2, size_t count); size_t strlen(const char *str); int strcmp(const char *s1, const char *s2); diff --git a/src/core/main.c b/src/core/main.c index fd69d69..8d064e9 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -493,16 +493,23 @@ void kmain(void) { serial_write_hex(current_rsp); serial_write("\n"); + serial_write("[DBG] before graphics_init_fonts\n"); graphics_init_fonts(); + serial_write("[DBG] after graphics_init_fonts\n"); - asm("cli"); + serial_write("[DBG] before ps2_init\n"); ps2_init(); - asm("sti"); + serial_write("[DBG] after ps2_init\n"); + asm("sti"); // Enable interrupts + serial_write("[DBG] before keymap_init\n"); keymap_init(); - serial_write("[INIT] Keymap initialized"); + serial_write("[DBG] after keymap_init\n"); + serial_write("[INIT] Keymap initialized\n"); + serial_write("[DBG] before lapic_init\n"); lapic_init(); + serial_write("[DBG] after lapic_init\n"); if (smp_request.response != NULL) { uint32_t online = smp_init(smp_request.response); diff --git a/src/dev/ps2.c b/src/dev/ps2.c index 9225c3a..b3091f8 100644 --- a/src/dev/ps2.c +++ b/src/dev/ps2.c @@ -11,6 +11,8 @@ #include "input/keyboard.h" #include "input/keymap.h" +extern void serial_write(const char *s); +extern void serial_write_num(uint32_t n); extern void serial_print(const char *s); extern void serial_print_hex(uint64_t n); @@ -25,6 +27,12 @@ uint64_t timer_handler(registers_t *regs) { extern void k_beep_process(void); k_beep_process(); + + if (kernel_ticks % 100 == 0) { + serial_write("[TIMER] Heartbeat: "); + serial_write_num((uint32_t)kernel_ticks); + serial_write(" ticks\n"); + } } outb(0x20, 0x20); diff --git a/src/sys/lapic.c b/src/sys/lapic.c index f070ad2..04e896f 100644 --- a/src/sys/lapic.c +++ b/src/sys/lapic.c @@ -3,11 +3,13 @@ // This header needs to maintain in any file it is present in, as per the GPL license terms. #include "lapic.h" #include "platform.h" +#include "spinlock.h" extern void serial_write(const char *str); // LAPIC is at physical 0xFEE00000. Access via HHDM. static volatile uint32_t *lapic_base = 0; +static spinlock_t lapic_lock = SPINLOCK_INIT; // LAPIC register offsets (byte offsets, divided by 4 for uint32_t* indexing) #define LAPIC_ID (0x020 / 4) @@ -41,14 +43,27 @@ void lapic_send_ipi_all(void) { if (!lapic_base) return; // Send IPI to all excluding self - // ICR format: + // ICR format: // bits 7:0 = vector (IPI_SCHED_VECTOR = 0x41) // bits 10:8 = delivery mode (000 = Fixed) // bit 11 = destination mode (0 = Physical) - // bit 14 = level (1 = Assert) + // bit 14 = level: 0 = Edge // bits 19:18 = destination shorthand (11 = All Excluding Self) - uint32_t icr_low = IPI_SCHED_VECTOR | (0b11 << 18) | (1 << 14); + uint32_t icr_low = IPI_SCHED_VECTOR | (0b11 << 18); - // Writing ICR_LOW triggers the IPI send + uint64_t rflags = spinlock_acquire_irqsave(&lapic_lock); lapic_base[LAPIC_ICR_LOW] = icr_low; + while (lapic_base[LAPIC_ICR_LOW] & (1 << 12)) {} + spinlock_release_irqrestore(&lapic_lock, rflags); +} + +void lapic_send_ipi(uint32_t lapic_id, uint8_t vector) { + if (!lapic_base) return; + uint32_t icr_low = (uint32_t)vector; + + uint64_t rflags = spinlock_acquire_irqsave(&lapic_lock); + lapic_base[LAPIC_ICR_HIGH] = (lapic_id << 24); + lapic_base[LAPIC_ICR_LOW] = icr_low; + while (lapic_base[LAPIC_ICR_LOW] & (1 << 12)) {} + spinlock_release_irqrestore(&lapic_lock, rflags); } diff --git a/src/sys/lapic.h b/src/sys/lapic.h index 06e1cc9..54f196d 100644 --- a/src/sys/lapic.h +++ b/src/sys/lapic.h @@ -21,4 +21,7 @@ void lapic_eoi(void); // Send a scheduling IPI to all APs (excludes self) void lapic_send_ipi_all(void); +// Send a targeted IPI to a specific LAPIC ID +void lapic_send_ipi(uint32_t lapic_id, uint8_t vector); + #endif diff --git a/src/sys/process.c b/src/sys/process.c index 0b57d2c..64f2313 100644 --- a/src/sys/process.c +++ b/src/sys/process.c @@ -17,6 +17,7 @@ extern void cmd_write(const char *str); extern void serial_write(const char *str); +extern void serial_write_num(uint32_t n); #define MAX_PROCESSES 16 #define MAX_CPUS_SCHED 32 @@ -507,7 +508,7 @@ process_t* process_create_elf(const char* filepath, const char* args_str, bool t asm volatile("fninit"); new_proc->fpu_initialized = true; - // Assign to an AP core via round-robin (if SMP is active) + // Assign to a CPU core via round-robin across APs (if SMP is active) uint32_t cpu_count = smp_cpu_count(); if (cpu_count > 1) { new_proc->cpu_affinity = next_cpu_assign; @@ -517,15 +518,29 @@ process_t* process_create_elf(const char* filepath, const char* args_str, bool t new_proc->cpu_affinity = 0; } - // Add to linked list (Critical Section) + rflags = spinlock_acquire_irqsave(&runqueue_lock); - new_proc->next = current_process[0]->next; - current_process[0]->next = new_proc; + uint32_t target_cpu = new_proc->cpu_affinity; + process_t *target_head = current_process[target_cpu]; + if (target_head) { + new_proc->next = target_head->next; + target_head->next = new_proc; + } else { + new_proc->next = new_proc; + current_process[target_cpu] = new_proc; + } spinlock_release_irqrestore(&runqueue_lock, rflags); serial_write("[PROC] Exec: "); serial_write(filepath); + serial_write(" on CPU "); + serial_write_num(new_proc->cpu_affinity); serial_write("\n"); + uint32_t target_lapic = smp_get_lapic_id(new_proc->cpu_affinity); + if (target_lapic != 0xFF) { + lapic_send_ipi(target_lapic, IPI_SCHED_VECTOR); + } + return new_proc; } diff --git a/src/sys/smp.c b/src/sys/smp.c index 31d57ee..407e84c 100644 --- a/src/sys/smp.c +++ b/src/sys/smp.c @@ -121,7 +121,7 @@ static void ap_entry(struct limine_smp_info *info) { } void smp_init_bsp(void) { - static cpu_state_t bsp_state_static = {0}; + static cpu_state_t bsp_state_static __attribute__((aligned(64))) = {0}; bsp_state_static.cpu_id = 0; bsp_lapic_id = read_lapic_id(); bsp_state_static.lapic_id = bsp_lapic_id; @@ -138,7 +138,7 @@ void smp_init_bsp(void) { uint32_t smp_init(struct limine_smp_response *smp_resp) { if (!smp_resp || smp_resp->cpu_count <= 1) { total_cpus = 1; - cpu_states = (cpu_state_t *)kmalloc(sizeof(cpu_state_t)); + cpu_states = (cpu_state_t *)kmalloc_aligned(sizeof(cpu_state_t), 64); if (!cpu_states) return 1; extern void mem_memset(void *, int, size_t); mem_memset(cpu_states, 0, sizeof(cpu_state_t)); @@ -158,7 +158,7 @@ uint32_t smp_init(struct limine_smp_response *smp_resp) { serial_write_num(bsp_lapic_id); serial_write("\n"); - cpu_states = (cpu_state_t *)kmalloc(total_cpus * sizeof(cpu_state_t)); + cpu_states = (cpu_state_t *)kmalloc_aligned(total_cpus * sizeof(cpu_state_t), 64); if (!cpu_states) { serial_write("[SMP] ERROR: Failed to allocate CPU state array!\n"); total_cpus = 1; @@ -231,3 +231,8 @@ uint32_t smp_init(struct limine_smp_response *smp_resp) { return online_count; } + +uint32_t smp_get_lapic_id(uint32_t cpu_id) { + if (cpu_id >= total_cpus || !cpu_states) return 0xFF; + return cpu_states[cpu_id].lapic_id; +} diff --git a/src/sys/smp.h b/src/sys/smp.h index c4ae47e..d78fa2c 100644 --- a/src/sys/smp.h +++ b/src/sys/smp.h @@ -17,6 +17,7 @@ typedef struct cpu_state { volatile bool online; uint64_t user_rsp_scratch; uint64_t kernel_syscall_stack; + uint8_t xsave_area[8192] __attribute__((aligned(64))); } cpu_state_t; void smp_init_bsp(void); @@ -31,4 +32,6 @@ uint32_t smp_cpu_count(void); cpu_state_t *smp_get_cpu(uint32_t cpu_id); +uint32_t smp_get_lapic_id(uint32_t cpu_id); + #endif