From 36137438446c1754a522c5b3cc3aff92c43ac1ee Mon Sep 17 00:00:00 2001 From: Aleksa Vuckovic Date: Wed, 13 Dec 2023 01:38:14 +0100 Subject: Initial commit X86/X86_64 debug/release WORKING riscv64 WORKING uart idk --- src/arch/mod.rs | 14 ++++ src/arch/riscv64/boot/entry.S | 37 ++++++++++ src/arch/riscv64/io/mod.rs | 2 + src/arch/riscv64/io/uart.rs | 27 +++++++ src/arch/riscv64/mod.rs | 2 + src/arch/x86/boot/boot.S | 126 +++++++++++++++++++++++++++++++++ src/arch/x86/common/boot/mod.rs | 2 + src/arch/x86/common/boot/multiboot.S | 11 +++ src/arch/x86/common/boot/multiboot.rs | 79 +++++++++++++++++++++ src/arch/x86/common/boot/multiboot2.S | 42 +++++++++++ src/arch/x86/common/forall.rs | 5 ++ src/arch/x86/common/io/mod.rs | 2 + src/arch/x86/common/io/writer.rs | 72 +++++++++++++++++++ src/arch/x86/common/mod.rs | 8 +++ src/arch/x86/mod.rs | 10 +++ src/arch/x86/once.rs | 6 ++ src/arch/x86_64/boot/boot.S | 128 ++++++++++++++++++++++++++++++++++ src/arch/x86_64/boot/boot64.S | 26 +++++++ src/arch/x86_64/mod.rs | 4 ++ src/arch/x86_64/once.rs | 6 ++ 20 files changed, 609 insertions(+) create mode 100644 src/arch/mod.rs create mode 100644 src/arch/riscv64/boot/entry.S create mode 100644 src/arch/riscv64/io/mod.rs create mode 100644 src/arch/riscv64/io/uart.rs create mode 100644 src/arch/riscv64/mod.rs create mode 100644 src/arch/x86/boot/boot.S create mode 100644 src/arch/x86/common/boot/mod.rs create mode 100644 src/arch/x86/common/boot/multiboot.S create mode 100644 src/arch/x86/common/boot/multiboot.rs create mode 100644 src/arch/x86/common/boot/multiboot2.S create mode 100644 src/arch/x86/common/forall.rs create mode 100644 src/arch/x86/common/io/mod.rs create mode 100644 src/arch/x86/common/io/writer.rs create mode 100644 src/arch/x86/common/mod.rs create mode 100644 src/arch/x86/mod.rs create mode 100644 src/arch/x86/once.rs create mode 100644 src/arch/x86_64/boot/boot.S create mode 100644 src/arch/x86_64/boot/boot64.S create mode 100644 src/arch/x86_64/mod.rs create mode 100644 src/arch/x86_64/once.rs (limited to 'src/arch') diff --git a/src/arch/mod.rs b/src/arch/mod.rs new file mode 100644 index 0000000..5735bed --- /dev/null +++ b/src/arch/mod.rs @@ -0,0 +1,14 @@ +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +mod x86; +#[cfg(target_arch = "x86")] +pub use x86::*; + +#[cfg(target_arch = "x86_64")] +mod x86_64; +#[cfg(target_arch = "x86_64")] +pub use x86_64::*; + +#[cfg(target_arch = "riscv64")] +mod riscv64; +#[cfg(target_arch = "riscv64")] +pub use riscv64::*; diff --git a/src/arch/riscv64/boot/entry.S b/src/arch/riscv64/boot/entry.S new file mode 100644 index 0000000..f5fa092 --- /dev/null +++ b/src/arch/riscv64/boot/entry.S @@ -0,0 +1,37 @@ +.section .init + +.option norvc + +.type start, @function +.global start +start: + .cfi_startproc + +.option push +.option norelax + la gp, global_pointer +.option pop + + /* Reset satp */ + csrw satp, zero + + /* Setup stack */ + la sp, stack_top + + /* Clear the BSS section */ + la t5, bss_start + la t6, bss_end +bss_clear: + sd zero, (t5) + addi t5, t5, 8 + bltu t5, t6, bss_clear + + la t0, kernel_main + csrw sepc, t0 + + /* Jump to kernel! */ + tail kernel_main + + .cfi_endproc + +.end diff --git a/src/arch/riscv64/io/mod.rs b/src/arch/riscv64/io/mod.rs new file mode 100644 index 0000000..6d91cab --- /dev/null +++ b/src/arch/riscv64/io/mod.rs @@ -0,0 +1,2 @@ +mod uart; +pub use uart::*; diff --git a/src/arch/riscv64/io/uart.rs b/src/arch/riscv64/io/uart.rs new file mode 100644 index 0000000..7aafeef --- /dev/null +++ b/src/arch/riscv64/io/uart.rs @@ -0,0 +1,27 @@ +use core::fmt; +use core::fmt::Write; + +pub fn _print(args: fmt::Arguments) { + // Not thread safe but no dependencies + let mut stdout = Stdout; + fmt::write(&mut stdout, args); +} + +struct Stdout; +impl Write for Stdout { + fn write_str(&mut self, s: &str) -> fmt::Result { + print_string(s); + Ok(()) + } +} + +pub fn print_string(s: &str) { + let uart_base = 0x10000000 as *mut u8; + while unsafe { uart_base.add(5).read_volatile() } & 0x20 == 0 {} + + for c in s.chars() { + unsafe { + uart_base.write_volatile(c as u8); + } + } +} diff --git a/src/arch/riscv64/mod.rs b/src/arch/riscv64/mod.rs new file mode 100644 index 0000000..608d4e1 --- /dev/null +++ b/src/arch/riscv64/mod.rs @@ -0,0 +1,2 @@ +mod io; +pub use io::*; diff --git a/src/arch/x86/boot/boot.S b/src/arch/x86/boot/boot.S new file mode 100644 index 0000000..02f6e91 --- /dev/null +++ b/src/arch/x86/boot/boot.S @@ -0,0 +1,126 @@ +.section .bootstrap_stack, "aw", @nobits +stack_bottom: +.skip 16384 +stack_top: + +.section .bss, "aw", @nobits + .align 4096 +page_directory: + .skip 4096 +page_table1: + .skip 4096 +page_table2: + .skip 4096 + + +.set P, 1<<0 +.set RW, 1<<1 +.set FLAGS, P | RW +.set KERNEL_VM, 0xC0000000 + + +.section .multiboot.text, "a" +.global _start +.type _start, @function +_start: +_start: + cli + mov $stack_top - KERNEL_VM, %esp + pushl %eax + pushl %ebx + + movl $page_table1 - KERNEL_VM + FLAGS, page_directory - KERNEL_VM + 0 * 4 + movl $page_table2 - KERNEL_VM + FLAGS, page_directory - KERNEL_VM + 1 * 4 + movl $page_table1 - KERNEL_VM + FLAGS, page_directory - KERNEL_VM + 768 * 4 + movl $page_table2 - KERNEL_VM + FLAGS, page_directory - KERNEL_VM + 769 * 4 + + mov $0, %ecx +not_done: + mov $0x1000, %eax + mul %ecx + orl $FLAGS, %eax + mov %eax, %edi + + // page_table1[%ecx] = 0x1000 * %ecx | 0x3 + mov $4, %eax + mul %ecx + add $page_table1 - KERNEL_VM, %eax + movl %edi, (%eax) + + // page_table2[%ecx] = 0x1000 * %ecx | 0x3 + mov $4, %eax + mul %ecx + add $1024 * 0x1000, %edi + add $page_table2 - KERNEL_VM, %eax + movl %edi, (%eax) + + inc %ecx + cmp $1024, %ecx + je done + jmp not_done +done: + + movl $(page_directory - KERNEL_VM), %ecx + movl %ecx, %cr3 + + movl %cr0, %ecx + orl $0x80001000, %ecx + movl %ecx, %cr0 + + lea 7f, %ecx + jmp *%ecx + + +.section .boot32.rodata + +gdt: +gdt_null = . - gdt + .quad 0 +kernel_code = . - gdt + .long 0xFFFF + .byte 0 + .byte 0x9A + .byte 0xCF + .byte 0 +kernel_data = . - gdt + .long 0xFFFF + .byte 0 + .byte 0x92 + .byte 0xCF + .byte 0 +user_code = . - gdt + .long 0xFFFF + .byte 0 + .byte 0xFA + .byte 0xCF + .byte 0 +user_data = . - gdt + .long 0xFFFF + .byte 0 + .byte 0xF2 + .byte 0xCF + .byte 0 + +.global gdtp +gdtp: + .word . - gdt - 1 + .long gdt + + +.section .text + +7: + addl $KERNEL_VM, %esp + lgdtl gdtp + ljmp $0x08, $code + +code: + movw $0x10, %ax + movw %ax, %ds + movw %ax, %es + movw %ax, %fs + movw %ax, %gs + movw %ax, %ss + + call kernel_main + hlt diff --git a/src/arch/x86/common/boot/mod.rs b/src/arch/x86/common/boot/mod.rs new file mode 100644 index 0000000..b6aebe5 --- /dev/null +++ b/src/arch/x86/common/boot/mod.rs @@ -0,0 +1,2 @@ +mod multiboot; +pub use multiboot::*; diff --git a/src/arch/x86/common/boot/multiboot.S b/src/arch/x86/common/boot/multiboot.S new file mode 100644 index 0000000..8773b1f --- /dev/null +++ b/src/arch/x86/common/boot/multiboot.S @@ -0,0 +1,11 @@ +.set ALIGN, 1<<0 +.set MEMINFO, 1<<1 +.set FLAGS, ALIGN | MEMINFO +.set MAGIC, 0x1BADB002 +.set CHECKSUM, -(MAGIC + FLAGS) + +.section .multiboot.header, "aw" +.align 4 +.long MAGIC +.long FLAGS +.long CHECKSUM diff --git a/src/arch/x86/common/boot/multiboot.rs b/src/arch/x86/common/boot/multiboot.rs new file mode 100644 index 0000000..09789ce --- /dev/null +++ b/src/arch/x86/common/boot/multiboot.rs @@ -0,0 +1,79 @@ +pub const MULTIBOOT2_BOOTLOADER_MAGIC: u32 = 0x36d76289; +pub const MULTIBOOT_TAG_TYPE_END: u32 = 0; +pub const MULTIBOOT_TAG_TYPE_MMAP: u32 = 6; +pub const MULTIBOOT_TAG_TYPE_FB: u32 = 8; + +use crate::{print, println}; + +pub fn parse_fb_multiboot(mut mem: *mut u32) { + let framebuffer_addr: u64 = unsafe { *(mem as *mut u64) }; + let framebuffer_pitch: u32 = unsafe { *mem.wrapping_add(2) }; + let framebuffer_width: u32 = unsafe { *mem.wrapping_add(3) }; + let framebuffer_height: u32 = unsafe { *mem.wrapping_add(4) }; + let framebuffer_bpp: u8 = unsafe { *(mem.wrapping_add(5) as *mut u8) }; + let framebuffer_type: u8 = unsafe { *(mem.wrapping_add(5) as *mut u8).wrapping_add(1) }; + let reserved: u8 = unsafe { *(mem.wrapping_add(5) as *mut u8).wrapping_add(1) }; + + println!( + "0x{:x} {:x} {:x} {:x}", + framebuffer_addr, framebuffer_pitch, framebuffer_width, framebuffer_height + ); +} + +pub fn parse_mem_multiboot(mut mem: *mut u32, _size: u32) { + let mut curr_size: u32 = 16; + + while curr_size < _size { + let base_addr: u64 = unsafe { *(mem as *mut u64) }; + let length: u64 = unsafe { *(mem.wrapping_add(2) as *mut u64) }; + let _type: u32 = unsafe { *mem.wrapping_add(4) }; + let reserved: u32 = unsafe { *mem.wrapping_add(5) }; + assert_eq!(reserved, 0, "reserved not 0"); + + //println!("{:x} {:x} {:x}", base_addr, length, _type); + + mem = mem.wrapping_add(6); + curr_size += 24; + } +} + +pub fn parse_multiboot(mut multiboot_bootinfo: *mut u32, multiboot_magic: u32) { + assert_eq!( + multiboot_magic, MULTIBOOT2_BOOTLOADER_MAGIC, + "MULTIBOOT2_BOOTLOADER_MAGIC" + ); + + let total_size: u32 = unsafe { *multiboot_bootinfo }; + let mut size = 8; + multiboot_bootinfo = multiboot_bootinfo.wrapping_add(2); + + while size < total_size { + let _type: u32 = unsafe { *multiboot_bootinfo }; + let _size: u32 = unsafe { *(multiboot_bootinfo.wrapping_add(1)) }; + let mem: *mut u32 = multiboot_bootinfo.wrapping_add(4); + let mem2: *mut u32 = multiboot_bootinfo.wrapping_add(2); + + match _type { + MULTIBOOT_TAG_TYPE_FB => { + parse_fb_multiboot(mem2); + } + MULTIBOOT_TAG_TYPE_MMAP => { + parse_mem_multiboot(mem, _size); + } + _ => {} + } + + let inc_size = (_size / 8 + (_size % 8 != 0) as u32) * 8; + size += inc_size; + + println!("{} {} {}", _type, _size, inc_size); + multiboot_bootinfo = multiboot_bootinfo.wrapping_add((inc_size / 4).try_into().unwrap()); + + if _type == MULTIBOOT_TAG_TYPE_END { + assert_eq!(_size, 8, "MULTIBOOT_TAG_TYPE_END"); + break; + } + } + + assert_eq!(total_size, size, "Multiboot"); +} diff --git a/src/arch/x86/common/boot/multiboot2.S b/src/arch/x86/common/boot/multiboot2.S new file mode 100644 index 0000000..d767ca0 --- /dev/null +++ b/src/arch/x86/common/boot/multiboot2.S @@ -0,0 +1,42 @@ +/* multiboot tags */ +.set TAG_END, 0 +.set TAG_FRAMEBUFFER, 5 + +/* multiboot flags */ +.set TAG_REQUIRED, 0 +.set TAG_OPTIONAL, 1 + +/* multiboot2 header constants */ +.set MAGIC, 0xe85250d6 +.set ARCH, 0 +.set HEADER_LENGTH, (header_end - header_start) +.set CHECKSUM, 0x100000000 - (MAGIC + ARCH + HEADER_LENGTH) + +.section .multiboot2.header, "a" +.align 4 +header_start: + /* magic */ + .align 8 + .long MAGIC + .long ARCH + .long HEADER_LENGTH + .long CHECKSUM + +/* + // framebuffer + .align 8 + .word TAG_FRAMEBUFFER + .word TAG_REQUIRED + .long 20 + .long 1024 + .long 768 + .long 32 +*/ + + /* end tag */ + .align 8 + .word TAG_END + .word TAG_REQUIRED + .long 8 + +header_end: diff --git a/src/arch/x86/common/forall.rs b/src/arch/x86/common/forall.rs new file mode 100644 index 0000000..39988e6 --- /dev/null +++ b/src/arch/x86/common/forall.rs @@ -0,0 +1,5 @@ +use crate::{print, println}; + +pub fn forall() { + println!("forall"); +} diff --git a/src/arch/x86/common/io/mod.rs b/src/arch/x86/common/io/mod.rs new file mode 100644 index 0000000..604e84c --- /dev/null +++ b/src/arch/x86/common/io/mod.rs @@ -0,0 +1,2 @@ +mod writer; +pub use writer::*; diff --git a/src/arch/x86/common/io/writer.rs b/src/arch/x86/common/io/writer.rs new file mode 100644 index 0000000..7361693 --- /dev/null +++ b/src/arch/x86/common/io/writer.rs @@ -0,0 +1,72 @@ +use core::fmt; +use core::fmt::Write; +use lazy_static::lazy_static; +use spin::Mutex; + +#[doc(hidden)] +pub fn _print(args: fmt::Arguments) { + WRITER.lock().write_fmt(args).unwrap(); +} + +lazy_static! { + pub static ref WRITER: Mutex = Mutex::new(Writer::new()); +} + +#[derive(Default)] +pub struct Writer { + max_y: isize, + max_x: isize, + x: isize, + y: isize, + addr: u32, +} + +impl Writer { + pub fn new() -> Self { + Self { + x: 0, + y: 0, + max_y: 25, + max_x: 80, + addr: 0xb8000, + } + } + + pub fn write(&mut self, c: char, b: u8) { + let off: isize = self.y * self.max_x + self.x; + let vga_buffer = self.addr as *mut u8; + + if c != '\n' { + unsafe { + *vga_buffer.offset(2 * off) = c as u8; + *vga_buffer.offset(2 * off + 1) = b; + } + self.x += 1; + } else { + self.x = 0; + self.y += 1; + } + + if self.x >= self.max_x { + self.x = 0; + self.y += 1; + } + + if self.y >= self.max_y { + self.y = 0; + } + } + + pub fn print(&mut self, s: &str, b: u8) { + for i in s.chars() { + self.write(i, b); + } + } +} + +impl fmt::Write for Writer { + fn write_str(&mut self, s: &str) -> fmt::Result { + self.print(s, 0xb); + Ok(()) + } +} diff --git a/src/arch/x86/common/mod.rs b/src/arch/x86/common/mod.rs new file mode 100644 index 0000000..d1d4d98 --- /dev/null +++ b/src/arch/x86/common/mod.rs @@ -0,0 +1,8 @@ +mod forall; +pub use forall::*; + +mod io; +pub use io::*; + +mod boot; +pub use boot::*; diff --git a/src/arch/x86/mod.rs b/src/arch/x86/mod.rs new file mode 100644 index 0000000..c47ad74 --- /dev/null +++ b/src/arch/x86/mod.rs @@ -0,0 +1,10 @@ +#[cfg(target_arch = "x86")] +mod common; +#[cfg(target_arch = "x86")] +pub use common::*; + +#[cfg(target_arch = "x86_64")] +pub mod common; + +mod once; +pub use once::*; diff --git a/src/arch/x86/once.rs b/src/arch/x86/once.rs new file mode 100644 index 0000000..9397afb --- /dev/null +++ b/src/arch/x86/once.rs @@ -0,0 +1,6 @@ +use crate::{print, println}; + +pub fn once() +{ + println!("x86"); +} diff --git a/src/arch/x86_64/boot/boot.S b/src/arch/x86_64/boot/boot.S new file mode 100644 index 0000000..1dc2320 --- /dev/null +++ b/src/arch/x86_64/boot/boot.S @@ -0,0 +1,128 @@ +.code32 +.extern begin_long_mode + +.section .boot32.text, "a" + +.set STACK_TOP, 0x03008000 + +.global _start +_start: + cli + mov $STACK_TOP, %esp + pushl $0 + pushl %eax + pushl $0 + pushl %ebx + + call setup_page_tables + call enable_paging + + lgdt gdtp + ljmp $0x08, $begin_long_mode + +setup_page_tables: +/* first 2mb */ + mov $pt_lvl3, %eax + or $0x3, %eax + mov %eax, pt_lvl4 + + mov $pt_lvl2, %eax + or $0x3, %eax + mov %eax, pt_lvl3 + + xor %ecx, %ecx +1: + movl $0x00200000, %eax + mul %ecx + or $0b10000011, %eax + movl $pt_lvl2, %edx + leal (%edx, %ecx, 8), %edx + movl %eax, (%edx) + inc %ecx + cmp $25, %ecx + jne 1b + +/* first 2mb in hh */ + mov $pt_lvl3_hh, %eax + or $0x3, %eax + mov %eax, pt_lvl4 + 4096 - 8 + + mov $pt_lvl2_hh, %eax + or $0x3, %eax + mov %eax, pt_lvl3_hh + 4096 - 16 + + xor %ecx, %ecx +2: + movl $0x00200000, %eax + mul %ecx + or $0b10000011, %eax + movl $pt_lvl2_hh, %edx + leal (%edx, %ecx, 8), %edx + movl %eax, (%edx) + inc %ecx + cmp $25, %ecx + jne 2b + + ret + +.global enable_paging +enable_paging: + /* enable PAE */ + mov %cr4, %edx + or $1<<5 ,%edx + mov %edx, %cr4 + + /* set LME (long mode enable) */ + mov $0xC0000080, %ecx + rdmsr + or $1<<8, %eax + wrmsr + + /* pt_lvl4 */ + mov $pt_lvl4, %eax + mov %eax, %cr3 + + /* enable paging (+ protected mode if not already enabled) */ + mov %cr0, %eax + or $1<<31 + 1<<0, %eax + mov %eax, %cr0 + + ret + + +.section .boot32.rodata + +gdt: +gdt_null = . - gdt + .quad 0 +gdt_code = . - gdt + .long 0xFFFF + .byte 0 + .byte 0x9A + .byte 0xAF + .byte 0 +gdt_data = . - gdt + .long 0xFFFF + .byte 0 + .byte 0x92 + .byte 0xAF + .byte 0 +.global gdtp +gdtp: + .word . - gdt - 1 + .quad gdt + + +.section .boot32.bss +.align 4096 + +pt_lvl4: + .skip 4096 +pt_lvl3: + .skip 4096 +pt_lvl3_hh: + .skip 4096 +pt_lvl2: + .skip 4096 +pt_lvl2_hh: + .skip 4096 diff --git a/src/arch/x86_64/boot/boot64.S b/src/arch/x86_64/boot/boot64.S new file mode 100644 index 0000000..848256f --- /dev/null +++ b/src/arch/x86_64/boot/boot64.S @@ -0,0 +1,26 @@ +.code64 + +.set KERNEL_VMA, 0xffffffff80000000 +.set GDT_KERNEL_CS, 0x10 + +.section .boot64.text, "a" + +.global begin_long_mode +begin_long_mode: + mov $GDT_KERNEL_CS, %ax + mov %ax, %ds + mov %ax, %es + mov %ax, %ss + mov %ax, %fs + mov %ax, %gs + + add $KERNEL_VMA, %rsp + movabs $jump_main, %rax + jmp *%rax + +.section .text +jump_main: + popq %rdi + popq %rsi + call kernel_main + hlt diff --git a/src/arch/x86_64/mod.rs b/src/arch/x86_64/mod.rs new file mode 100644 index 0000000..a5f019b --- /dev/null +++ b/src/arch/x86_64/mod.rs @@ -0,0 +1,4 @@ +pub use crate::arch::x86::common::*; + +mod once; +pub use once::*; diff --git a/src/arch/x86_64/once.rs b/src/arch/x86_64/once.rs new file mode 100644 index 0000000..8aebbcb --- /dev/null +++ b/src/arch/x86_64/once.rs @@ -0,0 +1,6 @@ +use crate::{print, println}; + +pub fn once() +{ + println!("x86_64"); +} -- cgit v1.2.3