【问题标题】:Triple fault when loading the GDT加载 GDT 时出现三重故障
【发布时间】:2021-06-13 11:05:05
【问题描述】:

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

【问题讨论】:

  • 在我看来,如果您能准确说明您正在使用哪种 CPU/系统与 qemu、486、i686 或最近的东西一起使用,这可能会很有用?你能提供你的 qemu 命令行吗?
  • 我在您的 github 上看到您正在尝试使用较旧的汇编程序。三重错误让我认为它更多地与执行环境有关(带有向量中断的 qemu 沙箱不应该启动)。使用相同的执行上下文,您的代码的 C(或其他)版本是否有效?有了rust,你能不能用--emit asm得到全局asm并提供它?

标签: rust operating-system gdt


【解决方案1】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-06-12
    • 1970-01-01
    • 1970-01-01
    • 2017-09-12
    • 1970-01-01
    • 1970-01-01
    • 2022-08-06
    • 2021-02-28
    相关资源
    最近更新 更多