加载 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,) -> 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,0x00,0),kernel_code: GDTEntry::new(0,0x9a,0xa0,kernel_data: GDTEntry::new(0,0x92,user_null: GDTEntry::new(0,user_code: GDTEntry::new(0,user_data: GDTEntry::new(0,0)
    };
}

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

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

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

解决方法

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