Skip to main content

kernel/arch/x86_64/
exception_table.rs

1// SPDX-License-Identifier: GPL-3.0-only
2//! x86_64 Page Fault Exception Table
3//!
4//! Authors: MarioS271
5
6unsafe extern "C" {
7    static __ex_table_start: u8;
8    static __ex_table_end: u8;
9}
10
11#[repr(C)]
12struct ExceptionTableEntry {
13    instruction_offset: i32,
14    fixup_offset: i32
15}
16
17pub fn search_exception_table(rip: u64) -> Option<u64> {
18    let table_start_addr = &raw const __ex_table_start as usize;
19    let table_end_addr = &raw const __ex_table_end as usize;
20
21    let num_entries = (table_end_addr - table_start_addr) / size_of::<ExceptionTableEntry>();
22
23    // Safety: the linker script places only 4-byte aligned, 8-byte long entries between the start
24    // and end addrs, and the section is read only
25    let entries = unsafe {
26        core::slice::from_raw_parts((&raw const __ex_table_start).cast::<ExceptionTableEntry>(), num_entries)
27    };
28
29    for entry in entries {
30        let instruction_field_addr = &raw const entry.instruction_offset as u64;
31
32        if instruction_field_addr.wrapping_add_signed(entry.instruction_offset as i64) != rip {
33            continue;
34        }
35
36        let fixup_field_addr = &raw const entry.fixup_offset as u64;
37        return Some(fixup_field_addr.wrapping_add_signed(entry.fixup_offset as i64));
38    }
39
40    None
41}