Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/workflows/rust-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ on:
- "**.ps1"
- "**.yml"
- "**.toml"
- "**.S"
- "**.ld"
- "!**.md"
pull_request:
types: [opened, synchronize]
Expand All @@ -21,6 +23,8 @@ on:
- "**.ps1"
- "**.yml"
- "**.toml"
- "**.S"
- "**.ld"
- "!**.md"

env:
Expand Down
154 changes: 154 additions & 0 deletions crates/rkos-arch/src/x86/head_64.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
/*
Bootstrapping x86_64 kernel
see also: https://wiki.osdev.org/Entering_Long_Mode
*/
/* prepare space for 4-level paging to entering long mode
.bss: | PML4 | PML3 | PML2 | Kernel_Stack(.bss.stack)|
| 4kb | 4kb | 4kb | 16kb |
*/
.section .bss
.align 4096
p4_table:
.skip 4096
p3_table:
.skip 4096
p2_table:
.skip 4096

/* Kernel Stack */
.section .bss.stack
.align 16
stack_bottom:
.skip 16384
stack_top:

/*
64-bit Global Descriptor Table (GDT)
see also: https://wiki.osdev.org/Global_Descriptor_Table
*/

/* because of .rodata is read only now,when adding more features,we should move it to .data */
.section .rodata
/* every items in gdt64 is 8 bytes */
.align 8
gdt64:
/* the first item is null */
.quad 0x0000000000000000

/* the second item is 64-bit code segment
Base 63:56 0x00000000
G 55 0
D/B 54 0
L 53 1 (64-bit code segment)
AVL 52 0
Limit 51:48 0x0000
P 47 1
DPL 46:45 0x00
S 44 1
Type 43:40 0x10
Base 39:16 0x000000
Limit 15:0 0x0000
*/
.quad 0x0020980000000000
gdt64_pointer:
/* length of gdt64 minus 1 */
.word 15
/* pointer to gdt64 */
.quad gdt64

/*
multiboot header
see also: https://wiki.osdev.org/Multiboot_Specification
*/
.section .text.entry
.align 4

.global multiboot_header
multiboot_header:
/* 0x1badb002: magic number for multiboot protocol*/
.long 0x1badb002
/* 0x00010000: flags */
.long 0x00010000
/* checksum */
.long -(0x1badb002 + 0x00010000)

/* pointer to multiboot_header */
.long multiboot_header
.long stext
.long edata
.long ebss
.long _start

/*
start of 32-bit code
*/
.global _start
_start:
.code32
/* set stack pointer */
mov esp, offset stack_top

/*
set up temporary page table
map first 2MB of physical memory to virtual memory
*/
mov eax, offset p3_table
or eax, 0b11 /* 0b11 means present and writable */
mov dword ptr [p4_table], eax

/* p3_table[0] -> p2_table */
mov eax, offset p2_table
or eax, 0b11
mov dword ptr [p3_table], eax

/* map first 2MB of physical memory to virtual memory as huge page */
mov eax, 0x83 /* 0x80 (Huge) + 0x02 (Writable) + 0x01 (Present) */
mov dword ptr [p2_table], eax

/* into long mode */
/* step 1: set CR3 to p4_table */
mov eax, offset p4_table
mov cr3, eax

/* step 2: enable PAE in CR4 */
mov eax, cr4
or eax, 1 << 5
mov cr4, eax

/* step 3: enable LME in EFER */
mov ecx, 0xC0000080
rdmsr
or eax, 1 << 8
wrmsr

/* step 4: enable paging in CR0 */
mov eax, cr0
or eax, 1 << 31
mov cr0, eax

/* step 5: load gdt64 */
lgdt [gdt64_pointer]

/* jump to 64-bit code */
push 8 /* push 64-bit code segment */
mov eax, offset long_mode_start
push eax /* push 64-bit code entry point */
retf /* retf to long mode */

.code64
long_mode_start:
/* first thing: set all data segment registers to 0 */
mov ax, 0
mov ss, ax
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax

/* call _main */
call _main

/* if _main returns, loop forever */
.loop64:
hlt
jmp .loop64
28 changes: 21 additions & 7 deletions crates/rkos-arch/src/x86/link.ld
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
/*
linker script for x86_64 kernel
see also: https://wiki.osdev.org/Linker_Scripts
*/
OUTPUT_ARCH(i386:x86-64)
ENTRY(_start)

Expand All @@ -8,32 +12,40 @@ KERNEL_BASE_ADDRESS = 0x100000;
SECTIONS {
. = KERNEL_BASE_ADDRESS;

/* kernel code */
/*
.text: kernel code
start at 0x100000
*/
.text : {
stext = .;
*(.text.entry)
*(.text.entry)
*(.text .text.*)
. = ALIGN(4096);
etext = .;
}

/* kernel rodata */
/*
.rodata: kernel rodata
*/
.rodata : {
srodata = .;
*(.rodata .rodata.*)
. = ALIGN(4096);
erodata = .;
}

/* kernel data */
/*
.data: kernel data
*/
.data : {
sdata = .;
*(.data .data.*)
. = ALIGN(4096);
edata = .;
}

/* kernel bss */
/*
.bss: kernel bss
*/
.bss : {
sbss = .;
*(.bss.stack) /* kernel stack */
Expand All @@ -43,7 +55,9 @@ SECTIONS {
ebss = .;
}

/* kernel end */
/*
kernel end
*/
. = ALIGN(4096);
ekernel = .;
}
57 changes: 28 additions & 29 deletions crates/rkos/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,35 +4,34 @@
use core::arch::global_asm;
use core::panic::PanicInfo;

global_asm!(
r#"
.section .text.entry
.align 4

.global multiboot_header
multiboot_header:

.long 0x1badb002
.long 0x00010000
.long -(0x1badb002 + 0x00010000)

.long multiboot_header
.long stext
.long edata
.long ebss
.long _start

.global _start
_start:
.code32
mov eax, 0x4f4f4f4f
mov dword ptr [0xb8000], eax

.loop:
hlt
jmp .loop
"#
);
#[cfg(target_arch = "x86_64")]
global_asm!(include_str!("../../rkos-arch/src/x86/head_64.S"));

#[unsafe(no_mangle)]
pub extern "C" fn _main() {
// VGA_BASE: 0xb8000
let vga_buffer = 0xb8000 as *mut u8;

let text = b"[OK] Barrensea rkos has conquered 64-bit Long Mode!!!";
let color_byte = 0x0a;

for (i, &byte) in text.iter().enumerate() {
unsafe {
*vga_buffer.add(i * 2) = byte;
*vga_buffer.add(i * 2 + 1) = color_byte;
}
}

unsafe extern "C" {
fn stext();
fn edata();
fn ebss();
}
let _text_size = edata as *const () as usize - stext as *const () as usize;
let _bss_size = ebss as *const () as usize - edata as *const () as usize;

//loop {}
}

#[panic_handler]
fn panic(_info: &PanicInfo) -> ! {
Expand Down
Loading