kernel - v0.7 beta

+ acpi: add acpi support
+ lapic: add lapic support
+ ioapic: add ioapic support
+ arch/x86_64: add support for "syscall"/"sysret"
This commit is contained in:
RaphProductions 2025-05-15 18:49:09 +02:00
parent 4d52bac946
commit a8e919b033
53 changed files with 772 additions and 331 deletions

View file

@ -203,7 +203,8 @@ $(IMAGE_NAME).iso: limine/limine kernel
@mkdir -p iso_root/boot/limine
@cp -v limine.conf iso_root/boot/limine/
@mkdir -p iso_root/EFI/BOOT
@cp -v initramfs.tar iso_root/
@cp -v testing/sk-hello.elf iso_root/
# @cp -v initramfs.tar iso_root/
ifeq ($(ARCH),x86_64)
@cp -v limine/limine-bios.sys limine/limine-bios-cd.bin limine/limine-uefi-cd.bin iso_root/boot/limine/
@cp -v limine/BOOTX64.EFI iso_root/EFI/BOOT/

View file

@ -7,6 +7,7 @@ The Soaplin kernel is a new Unix-like operating system kernel.
* Simple pre-emptive scheduler
* Ring 3 (user mode) support
* ELF loader
* ACPI
## In the works
* Virtual File System
@ -29,3 +30,8 @@ To build Soaplin, you must ensure you have these:
* A linker
Clone the repo, and run "make" in it!
## Acknowledgements
Thanks to all these people :heart:
* Kevin Alavik (kevinalavik): VMAs implementation
* Astrido (asterd-og): IOAPIC/LAPIC (from ZanOS)

View file

@ -1,7 +1,7 @@
// #include "sys/log.h"
#include <arch/x86_64/gdt.h>
#include <mm/memop.h>
#include <stdint.h>
#include <sys/arch/x86_64/gdt.h>
#include <sys/log.h>
gdt_table def_table = {{

View file

@ -42,7 +42,7 @@ isr_stub_%+%1:
mov rdi, rsp
call exception_handler
call idt_int_handler
popall
@ -58,7 +58,7 @@ isr_stub_%+%1:
mov rdi, rsp
call exception_handler
call idt_int_handler
popall
@ -66,7 +66,7 @@ isr_stub_%+%1:
iretq
%endmacro
extern exception_handler
extern idt_int_handler
isr_no_err_stub 0
isr_no_err_stub 1
isr_no_err_stub 2

View file

@ -0,0 +1,83 @@
// #include "sys/log.h"
#include "dev/ioapic.h"
#include "dev/lapic.h"
#include "mm/vmm.h"
#include "arch/x86_64/smp.h"
#include "sys/errhnd/panic.h"
#include <stdbool.h>
#include <arch//x86_64/idt.h>
#include <sys/log.h>
__attribute__((aligned(0x10))) static idt_entry_t idt[256];
static idtr_t idtr;
static int vectors[256];
extern void *isr_stub_table[];
idt_irq_handler_t irq_handler_table[256 - 32];
void idt_set_descriptor(uint8_t vector, void *isr, uint8_t flags) {
idt_entry_t *descriptor = &idt[vector];
descriptor->isr_low = (uint64_t)isr & 0xFFFF;
descriptor->kernel_cs = 0x28;
descriptor->ist = 0;
descriptor->attributes = flags;
descriptor->isr_mid = ((uint64_t)isr >> 16) & 0xFFFF;
descriptor->isr_high = ((uint64_t)isr >> 32) & 0xFFFFFFFF;
descriptor->reserved = 0;
}
void idt_register_irq(uint8_t vector, void *isr) {
if (vector <= 14)
ioapic_redirect_irq(bootstrap_lapic_id, vector + 32, vector, false);
irq_handler_table[vector] = isr;
vectors[vector <= 14 ? vector + 32 : vector] = IDT_VT_IRQ;
}
void idt_init() {
idtr.base = (uintptr_t)&idt[0];
idtr.limit = (uint16_t)sizeof(idt_entry_t) * 256 - 1;
for (uint16_t vector = 0; vector < 32; vector++) {
idt_set_descriptor(vector, isr_stub_table[vector], 0x8E);
vectors[vector] = IDT_VT_EXCEPTION;
}
for (uint16_t vector = 32; vector < 256; vector++) {
idt_set_descriptor(vector, isr_stub_table[vector], 0x8E);
vectors[vector] = IDT_VT_UNDEFINED;
}
// Do not use the legacy PIC.
//pic_init();
//pic_unmask_irq(1);
//pic_unmask_irq(8);
__asm__ volatile("lidt %0" : : "m"(idtr)); // load the new IDT
__asm__ volatile("sti"); // set the interrupt flag
log("idt - initialized\n");
}
void idt_int_handler(registers_t *regs) {
vmm_load_pagemap(vmm_kernel_pm);
//log("kernel - Interrupt %d\n", regs->int_no);
if (regs->int_no < 32) {
panic_ctx("A CPU exception occured.", regs);
}
int vec = regs->int_no;
if (vec >= 32 && vec < 47)
vec -= 32;
if (vectors[regs->int_no] == IDT_VT_IRQ) {
idt_irq_handler_t i = irq_handler_table[vec];
i(regs);
}
lapic_eoi();
//pic_ack(regs->int_no - 32);
}

View file

@ -2,6 +2,11 @@
#include <stdint.h>
// VT = Vector type
#define IDT_VT_UNDEFINED 0
#define IDT_VT_EXCEPTION 1
#define IDT_VT_IRQ 2
typedef struct {
uint64_t r15;
uint64_t r14;
@ -50,5 +55,8 @@ typedef struct {
uint64_t base;
} __attribute__((packed)) idtr_t;
typedef void(*idt_irq_handler_t)(registers_t *regs);
void idt_register_irq(uint8_t vector, void *isr);
void idt_set_descriptor(uint8_t vector, void *isr, uint8_t flags);
void idt_init(void);

View file

@ -0,0 +1,28 @@
#pragma once
#include <stdint.h>
#define IA32_GS_MSR 0xC0000101
#define IA32_GS_KERNEL_MSR 0xC0000102
static inline void wrmsr(uint64_t msr, uint64_t value)
{
uint32_t low = value & 0xFFFFFFFF;
uint32_t high = value >> 32;
asm volatile (
"wrmsr"
:
: "c"(msr), "a"(low), "d"(high)
);
}
static inline uint64_t rdmsr(uint64_t msr)
{
uint32_t low, high;
asm volatile (
"rdmsr"
: "=a"(low), "=d"(high)
: "c"(msr)
);
return ((uint64_t)high << 32) | low;
}

View file

@ -0,0 +1,29 @@
#include "arch//x86_64/idt.h"
#include "sched/sched.h"
#include <stdint.h>
#include <sys/log.h>
#include <arch//x86_64/idt.h>
#include <arch//x86_64/pit.h>
uint32_t tick = 0;
void pit_handler(registers_t *regs) {
//log("PIT");
tick++;
schedule(regs);
}
void pit_init() {
outb(0x43, 0x36);
uint16_t div = (uint16_t)(1193180 / 1000);
outb(0x40, (uint8_t)div);
outb(0x40, (uint8_t)(div >> 8));
idt_register_irq(0, pit_handler);
}
void pit_sleep(uint32_t ms) {
uint64_t start = tick;
while (tick - start < ms) {
__asm__ volatile ("nop");
}
}

12
kernel/src/arch/x86_64/pit.h Executable file
View file

@ -0,0 +1,12 @@
#ifndef PIT_H
#define PIT_H
#include <stdint.h>
#include <arch//x86_64/io.h>
extern uint32_t tick;
void pit_init();
void pit_sleep(uint32_t ms);
#endif

View file

@ -0,0 +1,49 @@
#include "arch//x86_64/smp.h"
#include "lib/spinlock.h"
#include "sys/log.h"
#include "limine.h"
#include <stdint.h>
__attribute__((
used,
section(".limine_requests"))) static volatile struct limine_mp_request
smp_request = {.id = LIMINE_MP_REQUEST, .revision = 0};
uint32_t bootstrap_lapic_id = 0;
uint32_t smp_cpu_count = 0; // Number of processors
spinlock_t smp_lock = { 0 };
uint32_t ctr = 0;
void smp_entry(struct limine_mp_info* smp_info) {
//spinlock_acquire(&smp_lock);
log("smp - CPU %d started (LAPIC ID: %d)\n", smp_info->processor_id, smp_info->lapic_id);
__atomic_fetch_add(&ctr, 1, __ATOMIC_SEQ_CST);
while (1)
;;
//spinlock_release(&smp_lock);
}
void smp_init() {
bootstrap_lapic_id = smp_request.response->bsp_lapic_id;
smp_cpu_count = smp_request.response->cpu_count;
log("smp - detected %d CPUs\n", smp_cpu_count);
for (uint64_t i = 0; i < smp_cpu_count; i++) {
if (smp_request.response->cpus[i]->lapic_id != bootstrap_lapic_id) {
uint32_t old_ctr = __atomic_load_n(&ctr, __ATOMIC_SEQ_CST);
__atomic_store_n(&smp_request.response->cpus[i]->goto_address, smp_entry, __ATOMIC_SEQ_CST);
while (__atomic_load_n(&ctr, __ATOMIC_SEQ_CST) == old_ctr)
;
} else {
log("smp - CPU %d is the bootstrap processor (LAPIC ID: %d)\n", i, smp_request.response->cpus[i]->lapic_id);
}
}
log("smp - initialized\n");
}

View file

@ -0,0 +1,7 @@
#pragma once
#include <stdint.h>
extern uint32_t bootstrap_lapic_id;
void smp_init();

View file

@ -1,4 +1,4 @@
#include <sys/arch/x86_64/sse.h>
#include <arch//x86_64/sse.h>
#include <sys/log.h>
#include <sys/printf.h>

View file

@ -0,0 +1,53 @@
bits 64
section .text
global syscall_entry
extern syscall_handle
syscall_entry:
swapgs ; switch
mov [gs:0], rsp
mov rsp, [gs:8]
push 0
push 0
push rax
push rcx
push rdx
push rbx
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
call syscall_handle
pop r15
pop r14
pop r13
pop r12
pop r11
pop r10
pop r9
pop r8
pop rdi
pop rsi
pop rbp
pop rbx
pop rdx
pop rcx
pop rax
add rsp, 16
mov [gs:8], rsp
mov rsp, [gs:0]
swapgs
o64 sysret

View file

@ -0,0 +1,18 @@
#include <arch/x86_64/msr.h>
#include <arch/x86_64/syscall.h>
#include <stdint.h>
extern void syscall_entry();
void __x86_64_syscall_init() {
uint64_t efer = rdmsr(IA32_EFER);
efer |= (1 << 0);
wrmsr(IA32_EFER, efer);
uint64_t star = 0;
star |= ((uint64_t)0x28 << 32); // kernel cs
star |= ((uint64_t)0x30 << 48); // user cs base (SYSCALL adds 16 for CS=0x38, 24 for SS=0x40)
wrmsr(IA32_STAR, star);
wrmsr(IA32_LSTAR, (uint64_t)syscall_entry);
wrmsr(IA32_CSTAR, 0x0);
wrmsr(IA32_CSTAR + 1, 0x200);
}

View file

@ -0,0 +1,7 @@
#pragma once
#define IA32_EFER 0xC0000080
#define IA32_STAR 0xC0000081
#define IA32_LSTAR 0xC0000082
#define IA32_CSTAR 0xC0000083
#define IA32_SFMASK 0xC0000084

105
kernel/src/dev/ioapic.c Normal file
View file

@ -0,0 +1,105 @@
#include "sys/acpi/madt.h"
#include <dev/ioapic.h>
#include <sys/log.h>
#include <mm/pmm.h>
void ioapic_init() {
madt_ioapic* ioapic = acpi_madt_ioapic_list[0];
uint32_t val = ioapic_read(ioapic, IOAPIC_VER);
uint32_t count = ((val >> 16) & 0xFF);
if ((ioapic_read(ioapic, 0) >> 24) != ioapic->apic_id) {
return;
}
for (uint8_t i = 0; i <= count; ++i) {
ioapic_write(ioapic, IOAPIC_REDTBL+2*i, 0x00010000 | (32 + i));
ioapic_write(ioapic, IOAPIC_REDTBL+2*i+1, 0);
}
log("ioapic - initialized\n");
}
void ioapic_write(madt_ioapic* ioapic, uint8_t reg, uint32_t val) {
*((volatile uint32_t*)(HIGHER_HALF(ioapic->apic_addr) + IOAPIC_REGSEL)) = reg;
*((volatile uint32_t*)(HIGHER_HALF(ioapic->apic_addr) + IOAPIC_IOWIN)) = val;
}
uint32_t ioapic_read(madt_ioapic* ioapic, uint8_t reg) {
*((volatile uint32_t*)(HIGHER_HALF(ioapic->apic_addr) + IOAPIC_REGSEL)) = reg;
return *((volatile uint32_t*)(HIGHER_HALF(ioapic->apic_addr) + IOAPIC_IOWIN));
}
void ioapic_set_entry(madt_ioapic* ioapic, uint8_t idx, uint64_t data) {
ioapic_write(ioapic, (uint8_t)(IOAPIC_REDTBL + idx * 2), (uint32_t)data);
ioapic_write(ioapic, (uint8_t)(IOAPIC_REDTBL + idx * 2 + 1), (uint32_t)(data >> 32));
}
uint64_t ioapic_gsi_count(madt_ioapic* ioapic) {
return (ioapic_read(ioapic, 1) & 0xff0000) >> 16;
}
madt_ioapic* ioapic_get_gsi(uint32_t gsi) {
for (uint64_t i = 0; i < acpi_madt_ioapic_length; i++) {
madt_ioapic* ioapic = acpi_madt_ioapic_list[i];
if (ioapic->gsi_base <= gsi && ioapic->gsi_base + ioapic_gsi_count(ioapic) > gsi)
return ioapic;
}
return (madt_ioapic*)0;
}
void ioapic_redirect_gsi(uint32_t lapic_id, uint8_t vec, uint32_t gsi, uint16_t flags, bool mask) {
madt_ioapic* ioapic = ioapic_get_gsi(gsi);
uint64_t redirect = vec;
if ((flags & (1 << 1)) != 0) {
redirect |= (1 << 13);
}
if ((flags & (1 << 3)) != 0) {
redirect |= (1 << 15);
}
if (mask) redirect |= (1 << 16);
else redirect &= ~(1 << 16);
redirect |= (uint64_t)lapic_id << 56;
uint32_t redir_table = (gsi - ioapic->gsi_base) * 2 + 16;
ioapic_write(ioapic, redir_table, (uint32_t)redirect);
ioapic_write(ioapic, redir_table + 1, (uint32_t)(redirect >> 32));
}
void ioapic_redirect_irq(uint32_t lapic_id, uint8_t vec, uint8_t irq, bool mask) {
uint8_t idx = 0;
madt_iso* iso = (madt_iso*)0;
while (idx < acpi_madt_iso_length) {
iso = acpi_madt_iso_list[idx];
if (iso->irq_src == irq) {
ioapic_redirect_gsi(lapic_id, vec, iso->gsi, iso->flags, mask);
return;
}
idx++;
}
ioapic_redirect_gsi(lapic_id, vec, irq, 0, mask);
}
uint32_t ioapic_get_redirect_irq(uint8_t irq) {
uint8_t idx = 0;
madt_iso* iso;
while (idx < acpi_madt_iso_length) {
iso = acpi_madt_iso_list[idx];
if (iso->irq_src == irq) {
return iso->gsi;
}
idx++;
}
return irq;
}

24
kernel/src/dev/ioapic.h Normal file
View file

@ -0,0 +1,24 @@
#pragma once
#include <stdbool.h>
#include <sys/acpi.h>
#include <sys/acpi/madt.h>
#define IOAPIC_REGSEL 0x0
#define IOAPIC_IOWIN 0x10
#define IOAPIC_ID 0x0
#define IOAPIC_VER 0x01
#define IOAPIC_ARB 0x02
#define IOAPIC_REDTBL 0x10
void ioapic_write(madt_ioapic* ioapic, uint8_t reg, uint32_t val);
uint32_t ioapic_read(madt_ioapic* ioapic, uint8_t reg);
void ioapic_redirect_irq(uint32_t lapic_id, uint8_t vec, uint8_t irq, bool mask);
uint32_t ioapic_get_redirect_irq(uint8_t irq);
void ioapic_set_entry(madt_ioapic* ioapic, uint8_t idx, uint64_t data);
void ioapic_init();

64
kernel/src/dev/lapic.c Normal file
View file

@ -0,0 +1,64 @@
#include "mm/pmm.h"
#include <dev/lapic.h>
#include <sys/log.h>
uint64_t apic_ticks = 0;
void lapic_init() {
lapic_write(0xf0, 0x1ff);
log("lapic - initialized\n");
}
void lapic_stop_timer() {
// We do this to avoid overlapping oneshots
lapic_write(LAPIC_TIMER_INITCNT, 0);
lapic_write(LAPIC_TIMER_LVT, LAPIC_TIMER_DISABLE);
}
void lapic_oneshot(uint8_t vec, uint64_t ms) {
lapic_stop_timer();
lapic_write(LAPIC_TIMER_DIV, 0);
lapic_write(LAPIC_TIMER_LVT, vec);
lapic_write(LAPIC_TIMER_INITCNT, apic_ticks * ms);
}
void lapic_calibrate_timer() {
lapic_stop_timer();
lapic_write(LAPIC_TIMER_DIV, 0);
lapic_write(LAPIC_TIMER_LVT, (1 << 16) | 0xff);
lapic_write(LAPIC_TIMER_INITCNT, 0xFFFFFFFF);
//pit_sleep(1); // 1 ms
lapic_write(LAPIC_TIMER_LVT, LAPIC_TIMER_DISABLE);
uint32_t ticks = 0xFFFFFFFF - lapic_read(LAPIC_TIMER_CURCNT);
apic_ticks = ticks;
lapic_stop_timer();
}
void lapic_write(uint32_t reg, uint32_t val) {
*((volatile uint32_t*)(HIGHER_HALF(0xfee00000) + reg)) = val;
}
uint32_t lapic_read(uint32_t reg) {
return *((volatile uint32_t*)(HIGHER_HALF(0xfee00000) + reg));
}
void lapic_eoi() {
lapic_write((uint8_t)0xb0, 0x0);
}
void lapic_ipi(uint32_t id, uint8_t dat) {
lapic_write(LAPIC_ICRHI, id << LAPIC_ICDESTSHIFT);
lapic_write(LAPIC_ICRLO, dat);
}
void lapic_send_all_int(uint32_t id, uint32_t vec) {
lapic_ipi(id, vec | LAPIC_ICRAIS);
}
void lapic_send_others_int(uint32_t id, uint32_t vec) {
lapic_ipi(id, vec | LAPIC_ICRAES);
}
uint32_t lapic_get_id() {
return lapic_read(0x0020) >> LAPIC_ICDESTSHIFT;
}

52
kernel/src/dev/lapic.h Normal file
View file

@ -0,0 +1,52 @@
#pragma once
#include <sys/acpi.h>
#include <sys/acpi/madt.h>
#define LAPIC_PPR 0x00a0
#define LAPIC_ICRLO 0x0300
#define LAPIC_ICRHI 0x0310
#define LAPIC_ICINI 0x0500
#define LAPIC_ICSTR 0x0600
#define LAPIC_ICEDGE 0x0000
#define LAPIC_ICPEND 0x00001000
#define LAPIC_ICPHYS 0x00000000
#define LAPIC_ICASSR 0x00004000
#define LAPIC_ICSHRTHND 0x00000000
#define LAPIC_ICDESTSHIFT 24
#define LAPIC_ICRAIS 0x00080000
#define LAPIC_ICRAES 0x000c0000
// Timer
#define LAPIC_TIMER_DIV 0x3E0
#define LAPIC_TIMER_INITCNT 0x380
#define LAPIC_TIMER_LVT 0x320
#define LAPIC_TIMER_DISABLE 0x10000
#define LAPIC_TIMER_CURCNT 0x390
#define LAPIC_TIMER_PERIODIC 0x20000
void lapic_init();
void lapic_stop_timer();
void lapic_oneshot(uint8_t vec, uint64_t ms);
void lapic_calibrate_timer();
void lapic_write(uint32_t reg, uint32_t val);
uint32_t lapic_read(uint32_t reg);
void lapic_eoi();
void lapic_ipi(uint32_t id, uint8_t dat);
void lapic_send_all_int(uint32_t id, uint32_t vec);
void lapic_send_others_int(uint32_t id, uint32_t vec);
void lapic_init_cpu(uint32_t id);
void lapic_start_cpu(uint32_t id, uint32_t vec);
uint32_t lapic_get_id();

View file

@ -1,17 +1,31 @@
#pragma once
#include <stdbool.h>
#include <stdint.h>
typedef struct spinlock {
volatile int locked;
} spinlock_t;
inline void spinlock_acquire(spinlock_t *lock) {
while (__sync_lock_test_and_set(&(lock)->locked, 1))
while ((lock)->locked)
__asm__ volatile("pause");
static inline void spinlock_acquire(spinlock_t *lock) {
//uint64_t timeout = 1000000; // Adjust this value based on your needs
for (;;) {
if (__atomic_exchange_n(&lock->locked, 1, __ATOMIC_ACQUIRE) == 0) {
return;
}
inline void spinlock_release(spinlock_t *lock) {
__sync_lock_release(&(lock)->locked);
while (__atomic_load_n(&lock->locked, __ATOMIC_RELAXED)) {
/**if (--timeout == 0) {
// Force unlock after too many attempts
__atomic_store_n(&lock->locked, 0, __ATOMIC_RELEASE);
continue;
}**/
__asm__ volatile("pause" ::: "memory");
}
}
}
static inline void spinlock_release(spinlock_t *lock) {
__atomic_store_n(&lock->locked, 0, __ATOMIC_RELEASE);
}

View file

@ -1,3 +1,5 @@
#include "dev/ioapic.h"
#include "dev/lapic.h"
#include "exec/elf.h"
#include "exec/exec.h"
#include "mm/liballoc/liballoc.h"
@ -6,8 +8,10 @@
#include "mm/vmm.h"
#include "sched/sched.h"
#include "sys/acpi.h"
#include "sys/arch/x86_64/pit.h"
#include "sys/arch/x86_64/sse.h"
#include "sys/acpi/madt.h"
#include "arch//x86_64/pit.h"
#include "arch//x86_64/smp.h"
#include "arch//x86_64/sse.h"
#include "sys/syscall.h"
#include <font.h>
#include <limine.h>
@ -15,9 +19,9 @@
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <sys/arch/x86_64/fpu.h>
#include <sys/arch/x86_64/gdt.h>
#include <sys/arch/x86_64/idt.h>
#include <arch//x86_64/fpu.h>
#include <arch//x86_64/gdt.h>
#include <arch//x86_64/idt.h>
#include <sys/errhnd/panic.h>
#include <sys/gfx/flanterm/backends/fb.h>
#include <sys/gfx/flanterm/flanterm.h>
@ -69,7 +73,7 @@ void kmain(void) {
VGA8, 8, 16, 0, 0, 0, 0);
}
printf("\n Soaplin 1.0-sild is booting up your computer...\n\n");
printf("\n Soaplin 0.7-sild is booting up your computer...\n\n");
gdt_init(&kstack[8192]);
idt_init();
@ -85,16 +89,26 @@ void kmain(void) {
}
acpi_init();
madt_init();
ioapic_init();
lapic_init();
pit_init();
smp_init();
syscall_init();
//pit_init(1000);
//sched_init();
sched_init();
//vfs_init();
panic("No working initialization program found. (This is normal due to "
"Soaplin's current state, so please do not report this as a bug)");
//panic("No working initialization program found. (This is normal due to "
// "Soaplin's current state, so please do not report this as a bug)");
program_t *p = elf_load(module_request.response->modules[0]->address, 1);
sched_process *proc = sched_create("Test", p->entry, p->pm,
SCHED_USER_PROCESS);
log("kernel - Soaplin initialized sucessfully.\n");

View file

@ -1,11 +1,13 @@
#include "sched/sched.h"
#include "arch/x86_64/msr.h"
#include "mm/memop.h"
#include "mm/pmm.h"
#include "mm/vmm.h"
#include "sys/arch/x86_64/idt.h"
#include "arch//x86_64/idt.h"
#include "sys/log.h"
#include <lib/string.h>
#include <stddef.h>
#include <mm/liballoc/liballoc.h>
sched_process *proc_list;
sched_process *curr_proc;
@ -31,7 +33,7 @@ void sched_init() {
// We must initialize the process list.
// By default, sched_create will append to this list.
proc_list = pmm_request_page();
proc_list = malloc(sizeof(sched_process));
memcpy(proc_list->name, "System\0", 7);
proc_list->pid = -1;
proc_list->type = SCHED_EMPTY;
@ -49,7 +51,7 @@ void sched_init() {
sched_process *sched_create(char *name, uint64_t entry_point, pagemap_t *pm,
uint32_t flags) {
sched_process *proc = pmm_request_page();
sched_process *proc = malloc(sizeof(sched_process));
memset(proc, 0, sizeof(sched_process));
memcpy(proc->name, name, strlen(name) > 128 ? 128 : strlen(name));
@ -64,10 +66,12 @@ sched_process *sched_create(char *name, uint64_t entry_point, pagemap_t *pm,
proc->pm = pm;
uint64_t *stack_phys = pmm_request_page();
uint64_t *kstack_phys = pmm_request_page();
uint64_t *stack_virt = (uint64_t *)0x40000000;
proc->kernel_stack = HIGHER_HALF(kstack_phys) + PMM_PAGE_SIZE;
if (flags == SCHED_KERNEL_PROCESS) {
proc->stack_base = stack_phys;
proc->stack_base = HIGHER_HALF(stack_phys);
proc->stack_base_physical = stack_phys;
proc->stack_end = proc->stack_base + PMM_PAGE_SIZE;
} else if (flags == SCHED_USER_PROCESS) {
@ -110,6 +114,7 @@ sched_process *sched_create(char *name, uint64_t entry_point, pagemap_t *pm,
"disabled.\n");
}
log("sched - created process '%s' (pid: %d, rip: %p)\n", proc->name,
proc->pid, proc->regs.rip);
return proc;
@ -152,5 +157,7 @@ void schedule(registers_t *regs) {
memcpy(regs, &curr_proc->regs, sizeof(registers_t));
wrmsr(IA32_GS_KERNEL_MSR, (uint64_t)curr_proc);
//log("sched - proc %d\n", curr_proc->pid);
vmm_load_pagemap(curr_proc->pm);
}

View file

@ -1,7 +1,7 @@
#pragma once
#include "mm/vmm.h"
#include "sys/arch/x86_64/idt.h"
#include "arch/x86_64/idt.h"
#define SCHED_KERNEL_PROCESS 0 // A process that runs in kernel mode.
#define SCHED_USER_PROCESS \
@ -11,6 +11,9 @@
typedef enum { SCHED_RUNNING, SCHED_DIED, SCHED_EMPTY } sched_proc_type;
typedef struct _sched_process {
uint64_t *stack_base;
uint64_t *kernel_stack; // Kernel-mode stack used for "syscall"
char name[128];
int pid;
int type;
@ -20,7 +23,6 @@ typedef struct _sched_process {
pagemap_t *pm;
uint64_t *stack_end;
uint64_t *stack_base;
uint64_t *stack_base_physical;
struct _sched_process *next;

View file

@ -0,0 +1,42 @@
#include "sys/acpi.h"
#include <stdint.h>
#include <sys/acpi/madt.h>
#include <sys/errhnd/panic.h>
#include <sys/log.h>
madt_ioapic* acpi_madt_ioapic_list[256] = {0};
madt_iso* acpi_madt_iso_list[256] = {0};
uint32_t acpi_madt_ioapic_length = 0;
uint32_t acpi_madt_iso_length = 0;
uint64_t* acpi_lapic_addr = 0;
void madt_init() {
void *addr = acpi_find_table("APIC");
if (!addr)
panic("madt: Failed to find MADT table!");
acpi_madt *madt = (acpi_madt *)addr;
uint64_t offset = 0;
int i = 0;
while (1) {
if (offset > madt->sdt.len - sizeof(acpi_madt))
break;
madt_entry* entry = (madt_entry*)(madt->table + offset);
if (entry->type == 0)
i++;
else if (entry->type == 1)
acpi_madt_ioapic_list[acpi_madt_ioapic_length++] = (madt_ioapic*)entry;
else if (entry->type == 2)
acpi_madt_iso_list[acpi_madt_iso_length++] = (madt_iso*)entry;
else if (entry->type == 5)
acpi_lapic_addr = (uint64_t*)((madt_lapic_addr*)entry)->phys_lapic;
offset += entry->length;
}
}

View file

@ -0,0 +1,56 @@
#pragma once
#include "sys/acpi.h"
#include <stdint.h>
typedef struct {
acpi_sdt sdt;
uint32_t lapic_address;
uint32_t flags;
char table[];
} acpi_madt;
typedef struct {
uint8_t type;
uint8_t length;
} madt_entry;
typedef struct {
madt_entry un;
uint8_t cpu_id;
uint8_t apic_id;
uint32_t flags;
} madt_cpu_lapic;
typedef struct {
madt_entry un;
uint8_t apic_id;
uint8_t reserved;
uint32_t apic_addr;
uint32_t gsi_base;
} madt_ioapic;
typedef struct {
madt_entry un;
uint8_t bus_src;
uint8_t irq_src;
uint32_t gsi;
uint16_t flags;
} madt_iso;
typedef struct {
madt_entry un;
uint16_t reserved;
uint64_t phys_lapic;
} madt_lapic_addr;
extern madt_ioapic* acpi_madt_ioapic_list[256];
extern madt_iso* acpi_madt_iso_list[256];
extern uint32_t acpi_madt_ioapic_length;
extern uint32_t acpi_madt_iso_length;
extern uint64_t* acpi_lapic_addr;
void madt_init();

View file

@ -1,51 +0,0 @@
// #include "sys/log.h"
#include "sys/arch/x86_64/pic.h"
#include <sys/arch/x86_64/idt.h>
#include <sys/log.h>
__attribute__((aligned(0x10))) static idt_entry_t idt[256];
static idtr_t idtr;
void idt_set_descriptor(uint8_t vector, void *isr, uint8_t flags) {
idt_entry_t *descriptor = &idt[vector];
descriptor->isr_low = (uint64_t)isr & 0xFFFF;
descriptor->kernel_cs = 0x28;
descriptor->ist = 0;
descriptor->attributes = flags;
descriptor->isr_mid = ((uint64_t)isr >> 16) & 0xFFFF;
descriptor->isr_high = ((uint64_t)isr >> 32) & 0xFFFFFFFF;
descriptor->reserved = 0;
}
static int vectors[256];
extern void *isr_stub_table[];
void idt_init() {
idtr.base = (uintptr_t)&idt[0];
idtr.limit = (uint16_t)sizeof(idt_entry_t) * 256 - 1;
for (uint16_t vector = 0; vector <= 256; vector++) {
if (vector == 0x80)
continue; // We skip the syscall handler, since it should be called from
// user space.
idt_set_descriptor(vector, isr_stub_table[vector], 0x8E);
vectors[vector] = 1;
}
uint16_t vector = 0x80;
idt_set_descriptor(vector, isr_stub_table[vector], 0xEE);
vectors[vector] = 1;
// Do not use the legacy PIC.
//pic_init();
//pic_unmask_irq(1);
//pic_unmask_irq(8);
__asm__ volatile("lidt %0" : : "m"(idtr)); // load the new IDT
__asm__ volatile("sti"); // set the interrupt flag
log("idt - initialized\n");
}

View file

@ -1,60 +0,0 @@
#include "mm/pmm.h"
#include "mm/vmm.h"
#include "sched/sched.h"
#include "sys/arch/x86_64/pic.h"
#include "sys/arch/x86_64/rtc.h"
#include "sys/log.h"
#include "sys/syscall.h"
#include <stdint.h>
#include <sys/arch/x86_64/idt.h>
#include <sys/arch/x86_64/io.h>
#include <sys/errhnd/panic.h>
int pit_millis = 0;
int pit_secs = 0;
extern int vmm_kernel_pm_exists;
void pit_handler(registers_t *regs);
void exception_handler(registers_t *regs) {
vmm_load_pagemap(vmm_kernel_pm);
if (regs->int_no < 32) {
// Should only be called if the exception is unrecoverable.
panic_ctx("A CPU exception occured.", regs);
//log("ints - %d (RIP: %p, ERR: %d)\n", regs->int_no, regs->rip,
// regs->err_code);
//if (regs->int_no == 0xe && vmm_kernel_pm_exists) {
// uint64_t cr2;
// asm("mov %%cr2, %0" : "=r"(cr2));
// log("ints - PF: Faulting location: %p (%p)\n", cr2,
// virt_to_phys(vmm_current_pm, cr2));
// log("ints - PF: Faulting page flags: %p\n",
// vmm_get_flags(vmm_current_pm, cr2));
// log("ints - PF: Faulting page map: %p\n", PHYSICAL(vmm_current_pm));
//}
//asm("cli");
//while (1)
// asm("hlt");
}
if (regs->int_no == 1 + 32) {
if (inb(0x60) & 0x80) {
pic_ack(regs->int_no - 32);
return;
}
log("ints - keyboard\n");
} else if (regs->int_no == 32 + 8) {
log("rtc\n");
} else if (regs->int_no == 0x80 - 32 || regs->int_no == 32) {
pit_handler(regs);
} else if (regs->int_no == 0x80) {
syscall_handle(regs);
}
pic_ack(regs->int_no - 32);
}

View file

@ -1,76 +0,0 @@
// #include "sys/log.h"
#include <sys/arch/x86_64/pic.h>
// #include <sys/acpi.h>
#include <sys/arch/x86_64/io.h>
void pic_init() {
// if (acpi_available)
// return;
uint8_t a1, a2;
a1 = inb(PIC1_DATA);
a2 = inb(PIC2_DATA);
outb(PIC1_COMMAND, ICW1_INIT | ICW1_ICW4);
io_wait();
outb(PIC2_COMMAND, ICW1_INIT | ICW1_ICW4);
io_wait();
outb(PIC1_DATA, 0x20);
io_wait();
outb(PIC2_DATA, 8);
io_wait();
outb(PIC1_DATA, 4);
io_wait();
outb(PIC2_DATA, 2);
io_wait();
outb(PIC1_DATA, ICW4_8086);
io_wait();
outb(PIC2_DATA, ICW4_8086);
io_wait();
outb(PIC1_DATA, a1);
outb(PIC2_DATA, a2);
}
void pic_ack(int intno) {
if (intno >= 8) {
outb(PIC2_COMMAND, 0x20);
}
outb(PIC1_COMMAND, 0x20);
}
void pic_disable() // if we want APIC
{
outb(PIC2_DATA, 0xff);
outb(PIC1_DATA, 0xff);
}
void pic_mask_irq(uint8_t irq) {
uint16_t port;
uint8_t value;
if (irq < 8) {
port = PIC1_DATA;
} else {
port = PIC2_DATA;
irq -= 8;
}
value = inb(port) | (1 << irq);
outb(port, value);
}
void pic_unmask_irq(uint8_t irq) {
uint16_t port;
uint8_t value;
if (irq < 8) {
port = PIC1_DATA;
} else {
port = PIC2_DATA;
irq -= 8;
}
value = inb(port) & ~(1 << irq);
outb(port, value);
}

View file

@ -1,23 +0,0 @@
// Copyright (C) 2024 Sipaa Projects
// This code is part of the Soaplin kernel and is licensed under the terms of
// the MIT License.
#pragma once
#include <stdint.h>
#define PIC1_COMMAND 0x20
#define PIC1_DATA 0x21
#define PIC2_COMMAND 0xA0
#define PIC2_DATA 0xA1
#define PIC_EOI 0x20
#define ICW1_INIT 0x10
#define ICW1_ICW4 0x01
#define ICW4_8086 0x01
void pic_init();
void pic_ack(int intno);
void pic_disable(); // if we want APIC
void pic_mask_irq(uint8_t irq);
void pic_unmask_irq(uint8_t irq);

View file

@ -1,52 +0,0 @@
#include "sched/sched.h"
#include "sys/arch/x86_64/idt.h"
#include "sys/arch/x86_64/pic.h"
#include <stdint.h>
#include <sys/log.h>
#ifdef __x86_64__
#include <sys/arch/x86_64/idt.h>
#include <sys/arch/x86_64/pit.h>
// #include <sipaa/sched.h>
uint32_t tick = 0;
void pit_handler(registers_t *regs) {
tick++;
schedule(regs);
// Scheduler_Schedule(regs);
}
void pit_init(uint32_t frequency) {
uint32_t divisor = PIT_FREQUENCY / frequency;
outb(0x43, 0x34);
outb(0x40, (uint8_t)(divisor & 0xFF));
outb(0x40, (uint8_t)((divisor >> 8) & 0xFF));
pic_unmask_irq(0);
}
void sleep(uint32_t seconds) {
uint32_t eticks = tick + seconds * HZ;
while (tick < eticks) {
__asm__ __volatile__("hlt");
}
}
void sleep_ms(uint32_t milliseconds) {
uint32_t eticks = tick + (milliseconds * HZ) / 1000;
while (tick < eticks) {
__asm__ __volatile__("hlt");
}
}
// todo: unistd: add usleep function
void usleep(uint32_t usecs) {
uint32_t eticks = tick + (usecs * HZ);
while (tick < eticks) {
__asm__ __volatile__("hlt");
}
}
#endif

View file

@ -1,17 +0,0 @@
#ifndef PIT_H
#define PIT_H
#include <stdint.h>
#include <sys/arch/x86_64/io.h>
#define PIT_FREQUENCY 1193182
#define HZ 1000
extern uint32_t tick;
void pit_init(uint32_t frequency);
void sleep(uint32_t seconds);
void sleep_ms(uint32_t milliseconds);
void usleep(uint32_t usecs);
#endif

View file

@ -1,4 +0,0 @@
#include "sys/arch/x86_64/smp.h"
#include "limine.h"
void smp_init() {}

View file

@ -1,3 +0,0 @@
#pragma once
void smp_init();

View file

@ -1,4 +1,5 @@
#include "sys/arch/x86_64/idt.h"
#include "arch//x86_64/idt.h"
#include "lib/spinlock.h"
#include <mm/memop.h>
#include <sys/log.h>
@ -49,6 +50,39 @@ static void __panic_dump_regs() {
__panic_regdump.ss = 0;
}
static void __panic_display_page_fault(registers_t *regs) {
if (regs->int_no != 14) // 14 is the page fault interrupt number
return;
uint64_t cr2;
asm volatile("mov %%cr2, %0" : "=r"(cr2));
log("Page Fault Details:\n");
log("Faulting Address (CR2): 0x%lx\n", cr2);
log("Error Code: %d\n", regs->err_code);
log("Flags:\n");
if (!(regs->err_code & (1 << 0)))
log(" - Page Not Present\n");
else
log(" - Protection Violation\n");
if (regs->err_code & (1 << 1))
log(" - Write Access\n");
else
log(" - Read Access\n");
if (regs->err_code & (1 << 2))
log(" - User-Mode Access\n");
else
log(" - Kernel-Mode Access\n");
if (regs->err_code & (1 << 3))
log(" - Reserved Bits Set\n");
if (regs->err_code & (1 << 4))
log(" - Instruction Fetch\n");
}
static void __panic_display_regs(registers_t *regs) {
log("-- REGISTER DUMP --\n");
log("RDI: %p, RSI: %p, RDX: %p, RCX: %p, R8: %p, R9: %p\n",
@ -59,10 +93,13 @@ static void __panic_display_regs(registers_t *regs) {
regs->r10, regs->r11, regs->r12);
log("R13: %p, R14: %p, R15: %p\n", regs->r13, regs->r14,
regs->r15);
log("RIP: %p, CS: %d, SS: %d, RFLAGS: %d, INTERRUPT: %d, ERROR CODE: %d\n",
log("RIP: %p, CS: %x, SS: %x, RFLAGS: %d, INTERRUPT: %d, ERROR CODE: %d\n",
regs->rip, regs->cs, regs->ss,
regs->rflags, regs->int_no, regs->err_code);
log("RSP: %p\n", regs->rsp);
if (regs->int_no == 14) // If it's a page fault
__panic_display_page_fault(regs);
}
void __panic_display_ascii_art() {
@ -104,6 +141,8 @@ void panic_ctx(char *msg, registers_t *regs) {
else
log("No register context provided.\n");
log("System halted: Please restart your computer manually.\n");
asm("cli");

View file

@ -1,5 +1,5 @@
#pragma once
#include "sys/arch/x86_64/idt.h"
#include "arch/x86_64/idt.h"
void panic(char *msg);
void panic_ctx(char *msg, registers_t *regs);

View file

@ -1,4 +1,4 @@
#include "sys/arch/x86_64/io.h"
#include "arch//x86_64/io.h"
#include "sys/gfx/flanterm/flanterm.h"
#include <lib/spinlock.h>
#include <lib/string.h>
@ -10,10 +10,11 @@ extern struct flanterm_context *ft_ctx;
static spinlock_t log_lock = {0};
void log(char *format, ...) {
// spinlock_acquire(&log_lock);
// TODO: replace this call with a call to printf() when the RTC is
// implemented.
//spinlock_acquire(&log_lock);
char *date = "1970-01-01 00:00:00 | ";
if (ft_ctx)
flanterm_write(ft_ctx, date, strlen(date));

View file

@ -8,6 +8,8 @@ static syscall syscall_table[1024];
static int syscall_initialized = 0;
extern void __x86_64_syscall_init();
// Stub function for undefined syscalls.
static uint64_t __syscall_undefined() { return 0; }
@ -30,6 +32,8 @@ void syscall_handle(registers_t *regs) {
return;
}
log("Hello!\n");
regs->rax = syscall_table[regs->rax](regs->rdi, regs->rsi, regs->rdx,
regs->rcx, regs->r8, regs->r9);
return;
@ -53,4 +57,6 @@ void syscall_init() {
syscall_table[i] = (syscall)__syscall_undefined;
syscall_register(0, (syscall)syscall_exit);
__x86_64_syscall_init();
}

View file

@ -1,6 +1,6 @@
#pragma once
#include "sys/arch/x86_64/idt.h"
#include "arch//x86_64/idt.h"
#include <stdint.h>
/// A function that defines a system call.

View file

@ -6,4 +6,4 @@ verbose: yes
protocol: limine
path: boot():/boot/soaplin
module_path: boot():/initramfs.tar
module_path: boot():/sk-hello.elf

Binary file not shown.

View file

@ -3,7 +3,6 @@ section .text
global _start
_start:
mov rax, 10
.hey:
add rax, 1
jmp .hey
syscall
.loop:
jmp .loop

1
testing/test.bin Normal file
View file

@ -0,0 +1 @@
<05>

Binary file not shown.