aboutsummaryrefslogtreecommitdiff
path: root/src/arch
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch')
-rw-r--r--src/arch/mod.rs14
-rw-r--r--src/arch/riscv64/boot/entry.S37
-rw-r--r--src/arch/riscv64/io/mod.rs2
-rw-r--r--src/arch/riscv64/io/uart.rs27
-rw-r--r--src/arch/riscv64/mod.rs2
-rw-r--r--src/arch/x86/boot/boot.S126
-rw-r--r--src/arch/x86/common/boot/mod.rs2
-rw-r--r--src/arch/x86/common/boot/multiboot.S11
-rw-r--r--src/arch/x86/common/boot/multiboot.rs79
-rw-r--r--src/arch/x86/common/boot/multiboot2.S42
-rw-r--r--src/arch/x86/common/forall.rs5
-rw-r--r--src/arch/x86/common/io/mod.rs2
-rw-r--r--src/arch/x86/common/io/writer.rs72
-rw-r--r--src/arch/x86/common/mod.rs8
-rw-r--r--src/arch/x86/mod.rs10
-rw-r--r--src/arch/x86/once.rs6
-rw-r--r--src/arch/x86_64/boot/boot.S128
-rw-r--r--src/arch/x86_64/boot/boot64.S26
-rw-r--r--src/arch/x86_64/mod.rs4
-rw-r--r--src/arch/x86_64/once.rs6
20 files changed, 609 insertions, 0 deletions
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<Writer> = 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");
+}