From 68933b9dfc83786d2a7753024436f3c66b415089 Mon Sep 17 00:00:00 2001 From: ParrotXray Date: Thu, 8 May 2025 21:53:16 +0800 Subject: [PATCH] feat: Refactoring the GDT table using the x86 crate --- Cargo.lock | 35 ++++++++++ Cargo.toml | 3 +- src/arch/x86/boot.S | 14 ++-- src/hal/io.rs | 1 + src/kernel/asm/x86/gdt.rs | 143 +++++++++++++++++++++----------------- src/kernel/kernel.rs | 16 +++-- 6 files changed, 135 insertions(+), 77 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4362ea5..c562bb5 100755 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,41 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "bit_field" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + [[package]] name = "cure" version = "0.1.0" +dependencies = [ + "x86", +] + +[[package]] +name = "raw-cpuid" +version = "10.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c297679cb867470fa8c9f67dbba74a78d78e3e98d7cf2b08d6d71540f797332" +dependencies = [ + "bitflags", +] + +[[package]] +name = "x86" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2781db97787217ad2a2845c396a5efe286f87467a5810836db6d74926e94a385" +dependencies = [ + "bit_field", + "bitflags", + "raw-cpuid", +] diff --git a/Cargo.toml b/Cargo.toml index 1e3ad07..0acaff5 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,4 +23,5 @@ test-success-exit-code = 33 default = [] debug = [] -[dependencies] \ No newline at end of file +[dependencies] +x86 = "0.52.0" \ No newline at end of file diff --git a/src/arch/x86/boot.S b/src/arch/x86/boot.S index f7203fc..51745b4 100644 --- a/src/arch/x86/boot.S +++ b/src/arch/x86/boot.S @@ -30,12 +30,14 @@ call _kernel_init /* install gdt */ - subl $0x6, %esp - movl $_GDT, 2(%esp) - movw _GDT_LIMIT, %ax - movw %ax, (%esp) - lgdt (%esp) - addl $0x6, %esp + call _load_gdt + // call _init_gdt + // subl $0x6, %esp + // movl $_GDT, 2(%esp) + // movw _GDT_LIMIT, %ax + // movw %ax, (%esp) + // lgdt (%esp) + // addl $0x6, %esp /* processing register (CS, ES, SS, DS, FS, GS) */ movw $0x10, %cx /* 0x10 in binary representation is 0001 0000. If you right-shift this number by 3 bits, you will get 0000 0010, so the index is 2. */ diff --git a/src/hal/io.rs b/src/hal/io.rs index ae8ac5f..b512d2a 100644 --- a/src/hal/io.rs +++ b/src/hal/io.rs @@ -1,4 +1,5 @@ // src/hal/io.rs +use x86::io; // :e - 32 位寄存器(如 eax, edx 等) // :x - 16 位寄存器(如 ax, dx 等) diff --git a/src/kernel/asm/x86/gdt.rs b/src/kernel/asm/x86/gdt.rs index 3f5cc77..c558b7d 100644 --- a/src/kernel/asm/x86/gdt.rs +++ b/src/kernel/asm/x86/gdt.rs @@ -1,34 +1,10 @@ // src/kernel/asm/x86/gdt.rs - use core::mem; - -#[allow(dead_code)] -pub const fn sd_type(x: u64) -> u64 { x << 8 } -#[allow(dead_code)] -pub const fn sd_code_data(x: u64) -> u64 { x << 12 } -#[allow(dead_code)] -pub const fn sd_dpl(x: u64) -> u64 { x << 13 } -#[allow(dead_code)] -pub const fn sd_present(x: u64) -> u64 { x << 15 } -#[allow(dead_code)] -pub const fn sd_avl(x: u64) -> u64 { x << 20 } -#[allow(dead_code)] -pub const fn sd_64bits(x: u64) -> u64 { x << 21 } -#[allow(dead_code)] -pub const fn sd_32bits(x: u64) -> u64 { x << 22 } -#[allow(dead_code)] -pub const fn sd_4k_gran(x: u64) -> u64 { x << 23 } - -#[allow(dead_code)] -pub const fn seg_lim_l(x: u64) -> u64 { x & 0x0ffff } -#[allow(dead_code)] -pub const fn seg_lim_h(x: u64) -> u64 { x & 0xf0000 } -#[allow(dead_code)] -pub const fn seg_base_l(x: u64) -> u64 { (x & 0x0000ffff) << 16 } -#[allow(dead_code)] -pub const fn seg_base_m(x: u64) -> u64 { (x & 0x00ff0000) >> 16 } -#[allow(dead_code)] -pub const fn seg_base_h(x: u64) -> u64 { x & 0xff000000 } +use core::ptr; +use x86::segmentation::{self, Descriptor, DataSegmentType, CodeSegmentType, SegmentSelector}; +use x86::segmentation::{SegmentDescriptorBuilder, BuildDescriptor}; +use x86::dtables::{DescriptorTablePointer, lgdt}; +use x86::Ring; #[allow(dead_code)] pub const SEG_DATA_RD: u64 = 0x00; // Read-Only @@ -64,52 +40,93 @@ pub const SEG_CODE_EXRDC: u64 = 0x0E; // Execute/Read, conforming pub const SEG_CODE_EXRDCA: u64 = 0x0F; // Execute/Read, conforming, accessed #[allow(dead_code)] -pub const SEG_R0_CODE: u64 = - sd_type(SEG_CODE_EXRD) | sd_code_data(1) | sd_dpl(0) | - sd_present(1) | sd_avl(0) | sd_64bits(0) | sd_32bits(1) | - sd_4k_gran(1); - +pub const NULL_SELECTOR: SegmentSelector = SegmentSelector::new(0, Ring::Ring0); #[allow(dead_code)] -pub const SEG_R0_DATA: u64 = - sd_type(SEG_DATA_RDWR) | sd_code_data(1) | sd_dpl(0) | - sd_present(1) | sd_avl(0) | sd_64bits(0) | sd_32bits(1) | - sd_4k_gran(1); - +pub const KERNEL_CODE_SELECTOR: SegmentSelector = SegmentSelector::new(1, Ring::Ring0); // Index 1 in GDT Table, Ring 0 segment selector. 0x8 #[allow(dead_code)] -pub const SEG_R3_CODE: u64 = - sd_type(SEG_CODE_EXRD) | sd_code_data(1) | sd_dpl(3) | - sd_present(1) | sd_avl(0) | sd_64bits(0) | sd_32bits(1) | - sd_4k_gran(1); - +pub const KERNEL_DATA_SELECTOR: SegmentSelector = SegmentSelector::new(2, Ring::Ring0); #[allow(dead_code)] -pub const SEG_R3_DATA: u64 = - sd_type(SEG_DATA_RDWR) | sd_code_data(1) | sd_dpl(3) | - sd_present(1) | sd_avl(0) | sd_64bits(0) | sd_32bits(1) | - sd_4k_gran(1); - -pub const GDT_ENTRY: usize = 5; +pub const USER_CODE_SELECTOR: SegmentSelector = SegmentSelector::new(3, Ring::Ring3); +#[allow(dead_code)] +pub const USER_DATA_SELECTOR: SegmentSelector = SegmentSelector::new(4, Ring::Ring3); #[no_mangle] -pub static mut _GDT: [u64; GDT_ENTRY] = [0; GDT_ENTRY]; +pub static KERNEL_CODE_SEL: u16 = KERNEL_CODE_SELECTOR.bits(); +#[no_mangle] +pub static KERNEL_DATA_SEL: u16 = KERNEL_DATA_SELECTOR.bits(); +#[no_mangle] +pub static USER_CODE_SEL: u16 = USER_CODE_SELECTOR.bits(); +#[no_mangle] +pub static USER_DATA_SEL: u16 = USER_DATA_SELECTOR.bits(); + +pub const GDT_ENTRY_COUNT: usize = 5; #[no_mangle] -pub static mut _GDT_LIMIT: u16 = (mem::size_of::<[u64; GDT_ENTRY]>() - 1) as u16; +pub static mut _GDT: [Descriptor; GDT_ENTRY_COUNT] = [Descriptor::NULL; GDT_ENTRY_COUNT]; #[no_mangle] -pub fn _set_gdt_entry(index: usize, base: u64, limit: u64, flags: u64) { +pub static mut _GDT_LIMIT: u16 = (mem::size_of::<[Descriptor; GDT_ENTRY_COUNT]>() - 1) as u16; + +#[no_mangle] +pub extern "C" fn _init_gdt() { unsafe { - _GDT[index] = seg_base_h(base) | flags | seg_lim_h(limit) | seg_base_m(base); - _GDT[index] <<= 32; - _GDT[index] |= seg_base_l(base) | seg_lim_l(limit); + _GDT[0] = Descriptor::NULL; + + _GDT[1] = segmentation::DescriptorBuilder::code_descriptor( + 0, + 0xFFFFF, + CodeSegmentType::ExecuteRead + ) + .present() + .dpl(Ring::Ring0) + .db() + .limit_granularity_4kb() + .finish(); + + _GDT[2] = segmentation::DescriptorBuilder::data_descriptor( + 0, + 0xFFFFF, + DataSegmentType::ReadWrite + ) + .present() + .dpl(Ring::Ring0) + .db() + .limit_granularity_4kb() + .finish(); + + _GDT[3] = segmentation::DescriptorBuilder::code_descriptor( + 0, + 0xFFFFF, + CodeSegmentType::ExecuteRead + ) + .present() + .dpl(Ring::Ring3) + .db() + .limit_granularity_4kb() + .finish(); + + _GDT[4] = segmentation::DescriptorBuilder::data_descriptor( + 0, + 0xFFFFF, + DataSegmentType::ReadWrite + ) + .present() + .dpl(Ring::Ring3) + .db() + .limit_granularity_4kb() + .finish(); } - } #[no_mangle] -pub fn _init_gdt() { - _set_gdt_entry(0, 0, 0, 0); - _set_gdt_entry(1, 0, 0xfffff, SEG_R0_CODE); - _set_gdt_entry(2, 0, 0xfffff, SEG_R0_DATA); - _set_gdt_entry(3, 0, 0xfffff, SEG_R3_CODE); - _set_gdt_entry(4, 0, 0xfffff, SEG_R3_DATA); +pub extern "C" fn _load_gdt() { + unsafe { + _init_gdt(); + + let gdtr = DescriptorTablePointer { + limit: _GDT_LIMIT, + base: ptr::addr_of!(_GDT), + }; + lgdt(&gdtr); + } } \ No newline at end of file diff --git a/src/kernel/kernel.rs b/src/kernel/kernel.rs index 3618820..33a7a46 100644 --- a/src/kernel/kernel.rs +++ b/src/kernel/kernel.rs @@ -13,8 +13,6 @@ pub extern "C" fn _kernel_init() { // TODO: 啟用分頁 tty::tty_init(tty::VGA_BUFFER_PADDR); tty::tty_set_theme(tty::VGA_COLOR_WHITE, tty::VGA_COLOR_BLACK); - - gdt::_init_gdt(); } #[no_mangle] @@ -39,11 +37,15 @@ pub extern "C" fn _kernel_main() { let value = 42; println!("10: {}, 16: {:x}", value, value); - - unsafe { - let x = gdt::_GDT_LIMIT; - println!("GDT Limit: {}", x); - } + + // unsafe { + // core::arch::asm!( + // "movl $0, %eax", + // "movl $0, %ebx", + // "divl %ebx", + // options(att_syntax) + // ); + // } loop {