2

我正在尝试在 rust 和 global asm 中设置 GDT,但是当我尝试加载 GDT 时,它似乎出现了三重故障。

# init_gdt.asm.
.intel_syntax noprefix

# **Notes**: 0x00: The Kernel Null Segment.
#            0x10: The Kernel Data Segment.
#            0x08: The Kernel Code Segment.

# Load the GDT and set all of the segments.
LoadGDT:
    # Use the `lgdt` Load GDT instruction to set the new GDT.
    # The rdi register contains the first argument of the function.
    lgdt [rdi]

    mov ax, 0x10
    
    mov ds, ax
    mov es, ax
    mov fs, ax
    mov gs, ax
    mov ss, ax

    pop rdi
    
    mov rax, 0x08
    
    push rax
    push rdi
    
    retfq

.global LoadGDT
global_asm!(include_str!("load_gdt.asm"));

#[repr(C, packed)]
struct GDTDescriptor {
    size: u16,
    offset: u64,
}

impl GDTDescriptor {
    #[inline]
    pub fn new(size: u16, offset: u64) -> Self {
        Self { size, offset }
    }
}

#[repr(C)]
struct GDTEntry {
    limit_low: u16,
    base_low: u16,
    base_middle: u8,
    access_byte: u8,
    limit_hi_flags: u8,
    base_hi: u8,
}

impl GDTEntry {
    #[inline]
    fn new(
        limit_low: u16,
        base_low: u16,
        base_middle: u8,
        access_byte: u8,
        limit_hi_flags: u8,
        base_hi: u8,
    ) -> Self {
        Self {
            limit_low,
            base_low,
            base_middle,
            access_byte,
            limit_hi_flags,
            base_hi,
        }
    }
}

/// The GDT.
#[repr(C, align(0x1000))]
struct GDT {
    kernel_null: GDTEntry,
    kernel_code: GDTEntry,
    kernel_data: GDTEntry,
    user_null: GDTEntry,
    user_code: GDTEntry,
    user_data: GDTEntry,
}

/// Initialize the GDT.
pub fn init() {
    unsafe {
        let gdt_descriptor = GDTDescriptor::new(
            (size_of::<GDT>() - 1) as u16,
            (&GLOBAL_DESCRIPTOR_TABLE as *const _) as u64,
        );

        LoadGDT(&gdt_descriptor as *const _)
    }
}

lazy_static! {
    /// The GDT (Global Descriptor Table).
    static ref GLOBAL_DESCRIPTOR_TABLE: GDT = GDT {
        kernel_null: GDTEntry::new(0, 0, 0, 0x00, 0x00, 0),
        kernel_code: GDTEntry::new(0, 0, 0, 0x9a, 0xa0, 0),
        kernel_data: GDTEntry::new(0, 0, 0, 0x92, 0xa0, 0),
        user_null: GDTEntry::new(0, 0, 0, 0x00, 0x00, 0),
        user_code: GDTEntry::new(0, 0, 0, 0x9a, 0xa0, 0),
        user_data: GDTEntry::new(0, 0, 0, 0x92, 0xa0, 0)
    };
}

根据 qemu 日志,它发生在mov ds, ax指令中。我遵循了 osdev.org 的指令,我很确定我的程序集是完全有效的。

我也一直在尝试更改并尝试一些随机的 GDTEntries 以查看它们是否有效,但这里没有运气。

回购:https ://github.com/Andy-Python-Programmer/aero

4

1 回答 1

1

我不知道这是一个简单的答案!我只需要 dref(*) GDT,因为它是惰性静态的,并且解决了所有问题:D

于 2021-03-16T10:08:45.850 回答