fix: added stability for SMP on Tiger Lake processors

This commit is contained in:
boreddevnl 2026-05-15 17:35:46 +02:00
parent 85c93cbcfa
commit 9c2096f737
10 changed files with 84 additions and 20 deletions

View file

@ -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

View file

@ -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) {

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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);
}

View file

@ -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

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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