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:
parent
4d52bac946
commit
a8e919b033
53 changed files with 772 additions and 331 deletions
|
@ -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/
|
||||
|
|
|
@ -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)
|
|
@ -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 = {{
|
|
@ -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
|
83
kernel/src/arch/x86_64/idt.c
Normal file
83
kernel/src/arch/x86_64/idt.c
Normal 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);
|
||||
}
|
|
@ -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);
|
28
kernel/src/arch/x86_64/msr.h
Normal file
28
kernel/src/arch/x86_64/msr.h
Normal 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;
|
||||
}
|
29
kernel/src/arch/x86_64/pit.c
Normal file
29
kernel/src/arch/x86_64/pit.c
Normal 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
12
kernel/src/arch/x86_64/pit.h
Executable 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
|
49
kernel/src/arch/x86_64/smp.c
Normal file
49
kernel/src/arch/x86_64/smp.c
Normal 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");
|
||||
}
|
7
kernel/src/arch/x86_64/smp.h
Normal file
7
kernel/src/arch/x86_64/smp.h
Normal file
|
@ -0,0 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
extern uint32_t bootstrap_lapic_id;
|
||||
|
||||
void smp_init();
|
|
@ -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>
|
||||
|
53
kernel/src/arch/x86_64/syscall.asm
Normal file
53
kernel/src/arch/x86_64/syscall.asm
Normal 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
|
18
kernel/src/arch/x86_64/syscall.c
Normal file
18
kernel/src/arch/x86_64/syscall.c
Normal 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);
|
||||
}
|
7
kernel/src/arch/x86_64/syscall.h
Normal file
7
kernel/src/arch/x86_64/syscall.h
Normal 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
105
kernel/src/dev/ioapic.c
Normal 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
24
kernel/src/dev/ioapic.h
Normal 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
64
kernel/src/dev/lapic.c
Normal 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
52
kernel/src/dev/lapic.h
Normal 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();
|
|
@ -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;
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void spinlock_release(spinlock_t *lock) {
|
||||
__sync_lock_release(&(lock)->locked);
|
||||
static inline void spinlock_release(spinlock_t *lock) {
|
||||
__atomic_store_n(&lock->locked, 0, __ATOMIC_RELEASE);
|
||||
}
|
|
@ -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");
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
|
|
42
kernel/src/sys/acpi/madt.c
Normal file
42
kernel/src/sys/acpi/madt.c
Normal 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;
|
||||
}
|
||||
}
|
56
kernel/src/sys/acpi/madt.h
Normal file
56
kernel/src/sys/acpi/madt.h
Normal 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();
|
|
@ -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");
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
|
@ -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
|
|
@ -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
|
|
@ -1,4 +0,0 @@
|
|||
#include "sys/arch/x86_64/smp.h"
|
||||
#include "limine.h"
|
||||
|
||||
void smp_init() {}
|
|
@ -1,3 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
void smp_init();
|
|
@ -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");
|
||||
|
|
|
@ -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);
|
|
@ -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));
|
||||
|
@ -41,5 +42,5 @@ void log(char *format, ...) {
|
|||
outb(0xE9, buf[i]);
|
||||
}
|
||||
|
||||
// spinlock_release(&log_lock);
|
||||
//spinlock_release(&log_lock);
|
||||
}
|
|
@ -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();
|
||||
}
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
@ -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
1
testing/test.bin
Normal file
|
@ -0,0 +1 @@
|
|||
<05>
|
BIN
testing/test.o
BIN
testing/test.o
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue