加载 GDT 时出现三重故障

时间:2021-03-16 07:18:29

标签: rust operating-system gdt

我正在尝试在 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

1 个答案:

答案 0 :(得分:1)

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

相关问题