小编lor*_*et3的帖子

当 CPL=3 时发生硬件中断时,导致仅设置写入位的 x86-64 页面错误的原因

我正在使用 Rust 编写自己的内核(大致基于 phil-opp 的博客,https://os.phil-opp.com/),到目前为止,我已经成功复制了 4 级页表,为用户模式应用程序代码和数据,将裸函数映射到虚拟地址0x40000000000,设置堆栈并跳转到代码。我还有一个使用 syscall/sysret 工作的系统调用处理程序,它在遇到系统调用时简单地打印一条消息。我注意到,每当 PIC 定时器中断发生时,它总是在 CPL=0 时发生,因为系统调用处理程序的代码比用户模式应用程序长很多倍,后者只是在无限循环中执行系统调用。如果我禁用打印(这需要大多数指令),则在循环数百次迭代之后,当 CPL=3 时会发生计时器中断。然而,CPU 没有调用中断处理程序,而是抛出一个页面错误,错误代码为 2(仅对应于写入位设置)。在我看来,这没有任何意义,问题可能出在哪里?

总表:

static ref GDT: (gdt::GlobalDescriptorTable, Selectors) = {
    let mut gdt = gdt::GlobalDescriptorTable::new();
    let kernel_code_selector = gdt.add_entry(gdt::Descriptor::kernel_code_segment());
    let kernel_data_selector = gdt.add_entry(gdt::Descriptor::kernel_data_segment());
    let tss_selector = gdt.add_entry(gdt::Descriptor::tss_segment(&TSS));
    let user_data_selector = gdt.add_entry(gdt::Descriptor::user_data_segment());
    let user_code_selector = gdt.add_entry(gdt::Descriptor::user_code_segment());
    (gdt, Selectors { kernel_code_selector, kernel_data_selector, tss_selector, user_code_selector, user_data_selector })
    };
Run Code Online (Sandbox Code Playgroud)

离散时间:

const DOUBLE_FAULT_IST_INDEX: u16 = 0;
let mut IDT: idt::InterruptDescriptorTable = idt::InterruptDescriptorTable::new();
IDT.breakpoint.set_handler_fn(interrupts::breakpoint::breakpoint_handler);
IDT.double_fault.set_handler_fn(interrupts::double_fault::double_fault_handler).set_stack_index(DOUBLE_FAULT_IST_INDEX);
IDT.page_fault.set_handler_fn(interrupts::page_fault::page_fault_handler);
IDT.general_protection_fault.set_handler_fn(interrupts::general_protection_fault::general_protection_fault_handler);
IDT.stack_segment_fault.set_handler_fn(interrupts::stack_segment_fault::stack_segment_fault_handler);
IDT.segment_not_present.set_handler_fn(interrupts::segment_not_present::segment_not_present_handler); …
Run Code Online (Sandbox Code Playgroud)

c x86 assembly osdev rust

3
推荐指数
1
解决办法
440
查看次数

标签 统计

assembly ×1

c ×1

osdev ×1

rust ×1

x86 ×1