diff --git a/Cargo.lock b/Cargo.lock index 5ee35c20..69f64363 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -827,6 +827,7 @@ dependencies = [ "cfg-if", "kernel-arch-aarch64", "kernel-arch-hosted", + "kernel-arch-i686", "kernel-arch-interface", "kernel-arch-x86_64", ] @@ -855,6 +856,20 @@ dependencies = [ "yggdrasil-abi", ] +[[package]] +name = "kernel-arch-i686" +version = "0.1.0" +dependencies = [ + "bitflags 2.6.0", + "device-api", + "kernel-arch-interface", + "libk-mm-interface", + "log", + "static_assertions", + "tock-registers", + "yggdrasil-abi", +] + [[package]] name = "kernel-arch-interface" version = "0.1.0" @@ -2167,6 +2182,7 @@ dependencies = [ "git-version", "kernel-arch", "kernel-arch-aarch64", + "kernel-arch-i686", "kernel-arch-x86_64", "kernel-fs", "libk", diff --git a/etc/i686-unknown-none.json b/etc/i686-unknown-none.json new file mode 100644 index 00000000..03ec0352 --- /dev/null +++ b/etc/i686-unknown-none.json @@ -0,0 +1,29 @@ +{ + "is-builtin": false, + "arch": "x86", + "cpu": "pentium4", + "os": "none", + "llvm-target": "i686-unknown-linux-gnu", + "data-layout": "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i128:128-f64:32:64-f80:32-n8:16:32-S128", + "max-atomic-width": 64, + "target-pointer-width": "32", + "features": "-avx,-sse,+soft-float", + + "executables": true, + "stack-probes": { + "kind": "inline" + }, + "dynamic-linking": true, + "panic-strategy": "abort", + "relocation-model": "pic", + + "has-thread-local": false, + + "supported-split-debuginfo": [ + "packed", + "unpacked", + "off" + ], + "linker": "rust-lld", + "linker-flavor": "ld.lld" +} diff --git a/etc/i686-unknown-none.ld b/etc/i686-unknown-none.ld new file mode 100644 index 00000000..36e6202c --- /dev/null +++ b/etc/i686-unknown-none.ld @@ -0,0 +1,53 @@ +ENTRY(__i686_entry); + +KERNEL_PHYS_BASE = 0x100000; +KERNEL_VIRT_OFFSET = 0xC0000000; + +SECTIONS { + . = KERNEL_PHYS_BASE; + PROVIDE(__kernel_start = . + KERNEL_VIRT_OFFSET); + + .text.entry : { + KEEP(*(.multiboot)) + *(.text.entry) + } + + . = ALIGN(16); + . = . + KERNEL_VIRT_OFFSET; + + .text : AT(. - KERNEL_VIRT_OFFSET) { + *(.text*) + } + + .export.text : AT(. - KERNEL_VIRT_OFFSET) { + KEEP(*(.export.text*)) + } + + . = ALIGN(4K); + .rodata : AT(. - KERNEL_VIRT_OFFSET) { + *(.eh_frame*) + *(.rodata*) + } + + . = ALIGN(4K); + .data.tables : AT (. - KERNEL_VIRT_OFFSET) { + KEEP(*(.data.tables)) + } + + .data : AT(. - KERNEL_VIRT_OFFSET) { + KEEP(*(.data.yboot)) + *(.data*) + *(.got*) + } + + . = ALIGN(4K); + PROVIDE(__bss_start_phys = . - KERNEL_VIRT_OFFSET); + .bss : AT(. - KERNEL_VIRT_OFFSET) { + *(COMMON) + *(.bss*) + } + . = ALIGN(4K); + PROVIDE(__bss_end_phys = . - KERNEL_VIRT_OFFSET); + + PROVIDE(__kernel_end = .); +}; diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index ce59130f..a840e818 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -66,6 +66,9 @@ acpi-system = { git = "https://github.com/alnyan/acpi-system.git" } ygg_driver_nvme = { path = "driver/block/nvme" } kernel-arch-x86_64 = { path = "arch/x86_64" } +[target.'cfg(target_arch = "x86")'.dependencies] +kernel-arch-i686 = { path = "arch/i686" } + [build-dependencies] prettyplease = "0.2.15" abi-generator = { path = "../tool/abi-generator" } @@ -75,6 +78,7 @@ abi-generator = { path = "../tool/abi-generator" } aarch64-cpu = "9.4.0" device-tree = { path = "lib/device-tree" } kernel-arch-aarch64 = { path = "arch/aarch64" } +kernel-arch-i686 = { path = "arch/i686" } [features] default = ["fb_console"] diff --git a/kernel/arch/Cargo.toml b/kernel/arch/Cargo.toml index 78a41e21..efda492d 100644 --- a/kernel/arch/Cargo.toml +++ b/kernel/arch/Cargo.toml @@ -11,6 +11,9 @@ kernel-arch-x86_64 = { path = "x86_64" } [target.'cfg(all(target_os = "none", target_arch = "aarch64"))'.dependencies] kernel-arch-aarch64 = { path = "aarch64" } +[target.'cfg(all(target_os = "none", target_arch = "x86"))'.dependencies] +kernel-arch-i686 = { path = "i686" } + [target.'cfg(not(target_os = "none"))'.dependencies] kernel-arch-hosted = { path = "hosted" } diff --git a/kernel/arch/i686/Cargo.toml b/kernel/arch/i686/Cargo.toml new file mode 100644 index 00000000..2b32c631 --- /dev/null +++ b/kernel/arch/i686/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "kernel-arch-i686" +version = "0.1.0" +edition = "2021" + +[dependencies] +yggdrasil-abi = { path = "../../../lib/abi" } +kernel-arch-interface = { path = "../interface" } +libk-mm-interface = { path = "../../libk/libk-mm/interface" } +device-api = { path = "../../lib/device-api", features = ["derive"] } + +bitflags = "2.6.0" +static_assertions = "1.1.0" +tock-registers = "0.8.1" + +log = "*" diff --git a/kernel/arch/i686/src/context.S b/kernel/arch/i686/src/context.S new file mode 100644 index 00000000..8af4a888 --- /dev/null +++ b/kernel/arch/i686/src/context.S @@ -0,0 +1,136 @@ +// vi: set ft=asm : + +.macro SAVE_TASK_STATE + push %edi + push %esi + push %ebp + push %ebx +.endm + +.macro LOAD_TASK_STATE + pop %ebx + pop %ebp + pop %esi + pop %edi +.endm + +.section .text + +.global __i686_task_enter_kernel +.global __i686_task_enter_user +.global __i686_task_enter_from_fork +.global __i686_switch_task +.global __i686_enter_task +.global __i686_switch_and_drop + +__i686_task_enter_kernel: + pop %eax // Argument + pop %ecx // Entry + + // Enable IRQ in EFLAGS + pushfl + pop %edx + or $(1 << 9), %edx + + // Setup iret + push %edx // eflags + pushl $0x08 // cs + push %ecx // eip + + iret + +__i686_task_enter_user: + pop %edx // User %esp + pop %ecx // entry + pop %eax // flags + + // Setup iret + + // %ss:%esp + pushl $0x23 + push %edx + + // %eflags + push %eax + + // %cs:%eip + pushl $0x1B + push %ecx + + mov $0x23, %bx + mov %bx, %ds + mov %bx, %es + mov %bx, %fs + mov %bx, %gs + + iret + +__i686_task_enter_from_fork: + jmp . + +__i686_switch_task: + // %esp + 0: return + // %esp + 4: destination + // %esp + 8: source + mov 4(%esp), %eax + mov 8(%esp), %ecx + + SAVE_TASK_STATE + + // TODO TSS + // Store stack to "from" context + mov %esp, (%ecx) + + // Load stack from "to" context + mov (%eax), %esp + + LOAD_TASK_STATE + + // TODO TSS + + ret + +__i686_enter_task: + // %esp + 0: return + // %esp + 4: destination + + // Switch to destination stack + mov 4(%esp), %eax + mov (%eax), %esp + + // TODO TSS + + LOAD_TASK_STATE + + ret + +__i686_switch_and_drop: + // %esp + 0: return + // %esp + 4: destination + // %esp + 8: thread to drop + + mov 4(%esp), %eax + // Switch to stack + mov (%eax), %esp + + LOAD_TASK_STATE + // TODO actually drop the thread + + ret + # // TSS.RSP0 + # mov 8(%rdi), %rax + # // Kernel stack + # mov 0(%rdi), %rdi + + # mov %rdi, %rsp + + # // Load TSS.RSP0 + # mov %gs:(8), %rdi + # mov %rax, 4(%rdi) + + # mov %rsi, %rdi + # call __arch_drop_thread + + # LOAD_TASK_STATE + + # ret diff --git a/kernel/arch/i686/src/context.rs b/kernel/arch/i686/src/context.rs new file mode 100644 index 00000000..e6f19015 --- /dev/null +++ b/kernel/arch/i686/src/context.rs @@ -0,0 +1,395 @@ +use core::{arch::global_asm, cell::UnsafeCell, marker::PhantomData}; + +use kernel_arch_interface::{ + mem::{KernelTableManager, PhysicalMemoryAllocator}, + task::{StackBuilder, TaskContext, TaskFrame, UserContextInfo}, +}; +use libk_mm_interface::address::{AsPhysicalAddress, PhysicalAddress}; +use tock_registers::interfaces::Writeable; +use yggdrasil_abi::{arch::SavedFrame, error::Error}; + +use crate::{gdt::TSS, mem::KERNEL_TABLES, registers::CR3}; + +#[repr(C)] +pub struct ExceptionFrame { + pub eax: u32, + pub ecx: u32, + pub edx: u32, + pub ebx: u32, + pub ebp: u32, + pub esi: u32, + pub edi: u32, + + pub exc_number: u32, + pub exc_code: u32, + + pub eip: u32, + pub cs: u32, + pub eflags: u32, + esp: u32, + ss: u32, +} + +#[derive(Debug)] +#[repr(C)] +pub struct SyscallFrame { + pub eax: usize, + // ebx, ecx, edx, esi, edi, ebp + pub args: [usize; 6], + + pub eip: u32, + pub cs: u32, + pub eflags: u32, + pub esp: u32, + pub ss: u32, +} + +#[repr(C)] +pub struct InterruptFrame { + pub eax: u32, + pub ecx: u32, + pub edx: u32, + pub ebx: u32, + pub ebp: u32, + pub esi: u32, + pub edi: u32, + + pub irq_number: u32, + + pub eip: u32, + pub cs: u32, + pub eflags: u32, + esp: u32, + ss: u32, +} + +#[repr(C, align(0x10))] +struct Inner { + // 0x00 + sp: usize, +} + +#[allow(dead_code)] +pub struct TaskContextImpl< + K: KernelTableManager, + PA: PhysicalMemoryAllocator
, +> { + inner: UnsafeCell