#![allow(function_casts_as_integer)]

use super::{
    entry::{set_intr_gate, set_system_intr_gate},
    TrapFrame,
};
use crate::{
    arch::{ipc::signal::Signal, x86_64::process::debugreg, CurrentIrqArch, MMArch},
    exception::{
        debug::DebugException, ebreak::EBreak, extable::ExceptionTableManager, InterruptArch,
    },
    ipc::signal::{force_kernel_signal_to_current, force_sig_fault_to_current},
    mm::VirtAddr,
    process::{ptrace, ProcessManager},
    smp::core::smp_get_processor_id,
};
use log::{error, trace, warn};
use system_error::SystemError;

extern "C" {
    fn trap_divide_error();
    fn trap_debug();
    fn trap_nmi();
    fn trap_int3();
    fn trap_overflow();
    fn trap_bounds();
    fn trap_undefined_opcode();
    fn trap_dev_not_avaliable();
    fn trap_double_fault();
    fn trap_coprocessor_segment_overrun();
    fn trap_invalid_TSS();
    fn trap_segment_not_exists();
    fn trap_stack_segment_fault();
    fn trap_general_protection();
    fn trap_page_fault();
    fn trap_x87_FPU_error();
    fn trap_alignment_check();
    fn trap_machine_check();
    fn trap_SIMD_exception();
    fn trap_virtualization_exception();
}

bitflags! {
    pub struct TrapNr: u64 {
        const X86_TRAP_DE = 0;
        const X86_TRAP_DB = 1;
        const X86_TRAP_NMI = 2;
        const X86_TRAP_BP = 3;
        const X86_TRAP_OF = 4;
        const X86_TRAP_BR = 5;
        const X86_TRAP_UD = 6;
        const X86_TRAP_NM = 7;
        const X86_TRAP_DF = 8;
        const X86_TRAP_OLD_MF = 9;
        const X86_TRAP_TS = 10;
        const X86_TRAP_NP = 11;
        const X86_TRAP_SS = 12;
        const X86_TRAP_GP = 13;
        const X86_TRAP_PF = 14;
        const X86_TRAP_SPURIOUS = 15;
        const X86_TRAP_MF = 16;
        const X86_TRAP_AC = 17;
        const X86_TRAP_MC = 18;
        const X86_TRAP_XF = 19;
        const X86_TRAP_VE = 20;
        const X86_TRAP_CP = 21;
        const X86_TRAP_VC = 29;
        const X86_TRAP_IRET = 32;
    }

        pub struct X86PfErrorCode : u32{
        const X86_PF_PROT = 1 << 0;
        const X86_PF_WRITE = 1 << 1;
        const X86_PF_USER = 1 << 2;
        const X86_PF_RSVD = 1 << 3;
        const X86_PF_INSTR = 1 << 4;
        const X86_PF_PK = 1 << 5;
        const X86_PF_SHSTK = 1 << 6;
        const X86_PF_SGX = 1 << 15;
    }
}

#[inline(never)]
pub fn arch_trap_init() -> Result<(), SystemError> {
    unsafe {
        set_intr_gate(0, 0, VirtAddr::new(trap_divide_error as usize));
        set_intr_gate(1, 0, VirtAddr::new(trap_debug as usize));
        set_intr_gate(2, 0, VirtAddr::new(trap_nmi as usize));
        // #BP must enter with maskable interrupts disabled. Uprobe teardown
        // uses a synchronous IPI as the grace point between restoring the
        // opcode and removing its hit-table entry; a trap gate could
        // acknowledge that IPI before do_int3 acquires the entry. The user
        // uprobe path reenables interrupts after capturing its XOL slot lease.
        set_system_intr_gate(3, 0, VirtAddr::new(trap_int3 as usize));
        // Context tracking requires every userspace entry to run with
        // maskable interrupts disabled until user_exit() has made RCU watch
        // the CPU. Keep DPL3, but use interrupt gates so an IRQ cannot nest in
        // the low-level entry window with a kernel-mode frame.
        set_system_intr_gate(4, 0, VirtAddr::new(trap_overflow as usize));
        set_system_intr_gate(5, 0, VirtAddr::new(trap_bounds as usize));
        set_intr_gate(6, 0, VirtAddr::new(trap_undefined_opcode as usize));
        set_intr_gate(7, 0, VirtAddr::new(trap_dev_not_avaliable as usize));
        set_intr_gate(8, 0, VirtAddr::new(trap_double_fault as usize));
        set_intr_gate(
            9,
            0,
            VirtAddr::new(trap_coprocessor_segment_overrun as usize),
        );
        set_intr_gate(10, 0, VirtAddr::new(trap_invalid_TSS as usize));
        set_intr_gate(11, 0, VirtAddr::new(trap_segment_not_exists as usize));
        set_intr_gate(12, 0, VirtAddr::new(trap_stack_segment_fault as usize));
        set_intr_gate(13, 0, VirtAddr::new(trap_general_protection as usize));
        set_intr_gate(14, 0, VirtAddr::new(trap_page_fault as usize));
        // 中断号15由Intel保留，不能使用
        set_intr_gate(16, 0, VirtAddr::new(trap_x87_FPU_error as usize));
        set_intr_gate(17, 0, VirtAddr::new(trap_alignment_check as usize));
        set_intr_gate(18, 0, VirtAddr::new(trap_machine_check as usize));
        set_intr_gate(19, 0, VirtAddr::new(trap_SIMD_exception as usize));
        set_intr_gate(20, 0, VirtAddr::new(trap_virtualization_exception as usize));
    }
    return Ok(());
}

/// 处理除法错误 0 #DE
#[no_mangle]
unsafe extern "C" fn do_divide_error(regs: &'static mut TrapFrame, error_code: u64) {
    if regs.is_from_user() {
        // A divide fault from an XOL instruction is a synchronous user fault,
        // not a kernel failure.  Mark the transaction trapped so the signal
        // gate restores the original probe context before building sigframe.
        let fault_addr = crate::exception::uprobe::mark_current_xol_trapped_and_get_probe_addr()
            .unwrap_or(regs.rip as usize);
        CurrentIrqArch::interrupt_enable();
        const FPE_INTDIV: i32 = 1;
        if let Err(err) =
            force_sig_fault_to_current(Signal::SIGFPE, FPE_INTDIV, VirtAddr::new(fault_addr))
        {
            error!("failed to send SIGFPE for user divide error: {:?}", err);
        }
        return;
    }
    error!(
        "do_divide_error(0), \tError code: {:#x},\trsp: {:#x},\trip: {:#x},\t CPU: {}, \tpid: {:?}",
        error_code,
        regs.rsp,
        regs.rip,
        smp_get_processor_id().data(),
        ProcessManager::current_pid()
    );
    panic!("Divide Error");
}

/// 处理调试异常 1 #DB
#[no_mangle]
unsafe extern "C" fn do_debug(regs: &'static mut TrapFrame, error_code: u64) {
    // DR6 can report BS (single-step) and B0-B3 (hardware breakpoint) together.
    // It must be saved and reset before any handler runs, so a stale cause cannot
    // pollute the next #DB.
    let dr6 = read_and_reset_dr6() & !ptrace::DR6_RESERVED;
    let from_user = regs.is_from_user();
    let dr7: u64;
    core::arch::asm!(
        "mov {}, dr7",
        out(reg) dr7,
        options(nomem, nostack, preserves_flags)
    );
    let owner_generation = crate::arch::process::cpu_debug_owner_generation()
        .load(core::sync::atomic::Ordering::Relaxed);
    // Disable hardware breakpoints before touching any kernel state. They stay
    // disabled across signal/ptrace work and are restored from the current
    // task state only at the final return-to-user boundary.
    debugreg::write_dr7(0);
    crate::arch::process::cpu_dr7().store(0, core::sync::atomic::Ordering::Relaxed);
    trace!(
        "do_debug(1), \tError code: {:#x},\tdr6: {:#x},\trsp: {:#x},\trip: {:#x},\t CPU: {}, \tpid: {:?}",
        error_code,
        dr6,
        regs.rsp,
        regs.rip,
        smp_get_processor_id().data(),
        ProcessManager::current_pid()
    );
    if from_user {
        // User-mode #DB: a completed uprobe XOL single-step takes priority (whether
        // the handler consumes it is reviewed in R4); an unconsumed user single-step
        // goes to SIGTRAP/ptrace via the unified signal path. DebugException only
        // consults the kernel kprobe table and cannot handle user-mode #DB, otherwise
        // it would silently swallow the debug exception.
        let current = ProcessManager::current_pcb();
        let uprobe = crate::exception::uprobe::uprobe_debug_handler(regs, dr6).unwrap();
        let (active_generation, current_generation) =
            ptrace::ptrace_debug_session_snapshot(&current);
        // Uprobe consumes only its XOL single-step reason. A simultaneous
        // hardware B0-B3 hit is independent and must still be reported.
        let report_bits = if uprobe.consumed {
            (dr6 & ptrace::X86_DR_B_MASK)
                | if uprobe.report_single_step {
                    ptrace::X86_DR_BS
                } else {
                    0
                }
        } else {
            dr6 & (ptrace::X86_DR_B_MASK | ptrace::X86_DR_BS)
        };
        let icebp = !uprobe.consumed && dr6 == 0;
        let forced_step = current.record_ptrace_debug_status(report_bits);
        let breakpoint_bits = report_bits & ptrace::X86_DR_B_MASK;
        let owned_breakpoints =
            if active_generation.is_some() || owner_generation != current_generation {
                breakpoint_bits
            } else {
                0
            };
        let owned_step = if active_generation.is_some() && forced_step {
            report_bits & ptrace::X86_DR_BS
        } else {
            0
        };
        let owned_bits = owned_breakpoints | owned_step;
        let unowned_bits = report_bits & !owned_bits;

        // Execution breakpoints require RF or the same instruction would
        // immediately retrigger when DR7 is restored.
        if report_bits & ptrace::X86_DR_BS == 0 {
            for i in 0..4u32 {
                if (breakpoint_bits & (1u64 << i)) != 0 && ((dr7 >> (16 + i * 4)) & 0b11) == 0 {
                    regs.rflags |= ptrace::X86_EFLAGS_RF;
                    break;
                }
            }
        }
        // Record even a fully consumed uprobe #DB so DR7 restoration remains
        // deferred until all return-to-user work has completed.
        current.record_pending_debug(
            owned_bits,
            unowned_bits,
            icebp,
            regs.rip as usize,
            active_generation.unwrap_or(owner_generation),
        );
    } else {
        let current = ProcessManager::current_pcb();
        let breakpoint_bits = dr6 & ptrace::X86_DR_B_MASK;
        if breakpoint_bits != 0 {
            // Match Linux exc_debug_kernel()/ptrace_triggered(): remember the
            // virtual DR6 cause, but do not synthesize a signal at syscall
            // return. A later user #DB starts a fresh virtual DR6 report.
            current.merge_ptrace_debug_status(breakpoint_bits);
        }
        // B0-B3 belong to the user ptrace watchpoint. Preserve any coexisting
        // BS reason for the kernel kprobe single-step handler.
        if dr6 & !ptrace::X86_DR_B_MASK != 0 {
            DebugException::handle(regs).unwrap();
        }
        // local_db_restore() semantics: kernel #DB handling must leave the
        // current task's breakpoint state armed, including after a B0-B3 hit.
        crate::arch::process::restore_current_debug_regs();
    }
}

#[inline]
unsafe fn read_and_reset_dr6() -> u64 {
    let dr6: u64;
    core::arch::asm!(
        "mov {}, dr6",
        out(reg) dr6,
        options(nomem, nostack, preserves_flags)
    );
    // Intel/Linux requires preserving DR6's fixed 1 bits and clearing the writable status bits.
    const DR6_RESET: u64 = 0xffff_0ff0;
    core::arch::asm!(
        "mov dr6, {}",
        in(reg) DR6_RESET,
        options(nomem, nostack, preserves_flags)
    );
    dr6
}

/// 处理NMI中断 2 NMI
#[no_mangle]
unsafe extern "C" fn do_nmi(regs: &'static TrapFrame, error_code: u64) {
    error!(
        "do_nmi(2), \tError code: {:#x},\trsp: {:#x},\trip: {:#x},\t CPU: {}, \tpid: {:?}",
        error_code,
        regs.rsp,
        regs.rip,
        smp_get_processor_id().data(),
        ProcessManager::current_pid()
    );
    panic!("NMI Interrupt");
}

/// 处理断点异常 3 #BP
#[no_mangle]
unsafe extern "C" fn do_int3(regs: &'static mut TrapFrame, error_code: u64) {
    trace!(
        "do_int3(3), \tError code: {:#x},\trsp: {:#x},\trip: {:#x},\t CPU: {}, \tpid: {:?}",
        error_code,
        regs.rsp,
        regs.rip,
        smp_get_processor_id().data(),
        ProcessManager::current_pid()
    );
    if regs.is_from_user() {
        // User-mode #BP: an uprobe hit or an unconsumed #BP (→ SIGTRAP).
        crate::exception::uprobe::uprobe_breakpoint_handler(regs).unwrap();
    } else {
        // Vector 3 is now an interrupt gate for the user-uprobe entry race.
        // Preserve the old trap-gate behavior for kernel breakpoints: a
        // context entered with IF set may run kprobe callbacks with interrupts
        // enabled, while an irq-off context remains irq-off.
        if regs.rflags & (1 << 9) != 0 {
            CurrentIrqArch::interrupt_enable();
        }
        // Kernel-mode #BP: a kprobe hit.
        EBreak::handle(regs).unwrap();
    }
}

/// 处理溢出异常 4 #OF
#[no_mangle]
unsafe extern "C" fn do_overflow(regs: &'static TrapFrame, error_code: u64) {
    error!(
        "do_overflow(4), \tError code: {:#x},\trsp: {:#x},\trip: {:#x},\t CPU: {}, \tpid: {:?}",
        error_code,
        regs.rsp,
        regs.rip,
        smp_get_processor_id().data(),
        ProcessManager::current_pid()
    );
    panic!("Overflow Exception");
}

/// 处理BOUND指令检查异常 5 #BR
#[no_mangle]
unsafe extern "C" fn do_bounds(regs: &'static TrapFrame, error_code: u64) {
    error!(
        "do_bounds(5), \tError code: {:#x},\trsp: {:#x},\trip: {:#x},\t CPU: {}, \tpid: {:?}",
        error_code,
        regs.rsp,
        regs.rip,
        smp_get_processor_id().data(),
        ProcessManager::current_pid()
    );
    panic!("Bounds Check");
}

/// 处理未定义操作码异常 6 #UD
#[no_mangle]
unsafe extern "C" fn do_undefined_opcode(regs: &'static mut TrapFrame, error_code: u64) {
    if regs.is_from_user() {
        // #UD is unrecoverable and SIGILL is definitely delivered below; if it
        // happens in XOL, the signal frame must see the original probe address
        // rather than the slot address.
        crate::exception::uprobe::mark_current_xol_trapped();
        CurrentIrqArch::interrupt_enable();
        if let Err(err) = force_kernel_signal_to_current(Signal::SIGILL) {
            error!(
                "failed to send SIGILL for user undefined opcode, pid: {:?}, rip: {:#x}, error_code: {:#x}, err: {:?}",
                ProcessManager::current_pid(),
                regs.rip,
                error_code,
                err
            );
        }
        return;
    }

    error!(
        "do_undefined_opcode(6), \tError code: {:#x},\trsp: {:#x},\trip: {:#x},\t CPU: {}, \tpid: {:?}",
        error_code,
        regs.rsp,
        regs.rip,
        smp_get_processor_id().data(),
        ProcessManager::current_pid()
    );
    panic!("Undefined Opcode");
}

/// 处理设备不可用异常(FPU不存在) 7 #NM
#[no_mangle]
unsafe extern "C" fn do_dev_not_avaliable(regs: &'static TrapFrame, error_code: u64) {
    error!(
        "do_dev_not_avaliable(7), \tError code: {:#x},\trsp: {:#x},\trip: {:#x},\t CPU: {}, \tpid: {:?}",
        error_code,
        regs.rsp,
        regs.rip,
        smp_get_processor_id().data(),
        ProcessManager::current_pid()
    );
    panic!("Device Not Available");
}

/// 处理双重错误 8 #DF
#[no_mangle]
unsafe extern "C" fn do_double_fault(regs: &'static TrapFrame, error_code: u64) {
    error!(
        "do_double_fault(8), \tError code: {:#x},\trsp: {:#x},\trip: {:#x},\t CPU: {}, \tpid: {:?}",
        error_code,
        regs.rsp,
        regs.rip,
        smp_get_processor_id().data(),
        ProcessManager::current_pid()
    );
    panic!("Double Fault");
}

/// 处理协处理器段越界 9 #MF
#[no_mangle]
unsafe extern "C" fn do_coprocessor_segment_overrun(regs: &'static TrapFrame, error_code: u64) {
    error!(
        "do_coprocessor_segment_overrun(9), \tError code: {:#x},\trsp: {:#x},\trip: {:#x},\t CPU: {}, \tpid: {:?}",
        error_code,
        regs.rsp,
        regs.rip,
        smp_get_processor_id().data(),
        ProcessManager::current_pid()
    );
    panic!("Coprocessor Segment Overrun");
}

/// 处理无效TSS 10 #TS
#[no_mangle]
unsafe extern "C" fn do_invalid_TSS(regs: &'static TrapFrame, error_code: u64) {
    const ERR_MSG_1: &str =
        "The exception occurred during delivery of an event external to the program.\n";
    const ERR_MSG_2: &str = "Refers to a descriptor in the IDT.\n";
    const ERR_MSG_3: &str = "Refers to a descriptor in the current LDT.\n";
    const ERR_MSG_4: &str = "Refers to a descriptor in the GDT.\n";

    let msg1: &str = if (error_code & 0x1) != 0 {
        ERR_MSG_1
    } else {
        ""
    };

    let msg2: &str = if (error_code & 0x02) != 0 {
        ERR_MSG_2
    } else if (error_code & 0x04) != 0 {
        ERR_MSG_3
    } else {
        ERR_MSG_4
    };

    error!(
        "do_invalid_TSS(10), \tError code: {:#x},\trsp: {:#x},\trip: {:#x},\t CPU: {}, \tpid: {:?}\n{}{}",
        error_code,
        regs.rsp,
        regs.rip,
        smp_get_processor_id().data(),
        ProcessManager::current_pid(),
        msg1,
        msg2
    );
    panic!("Invalid TSS");
}

/// 处理段不存在 11 #NP
#[no_mangle]
unsafe extern "C" fn do_segment_not_exists(regs: &'static mut TrapFrame, error_code: u64) {
    if try_fixup_kernel_exception(regs) {
        return;
    }

    if regs.is_from_user() {
        crate::exception::uprobe::mark_current_xol_trapped();
        CurrentIrqArch::interrupt_enable();
        if let Err(err) = force_kernel_signal_to_current(Signal::SIGBUS) {
            error!(
                "failed to send SIGBUS for user segment-not-present fault, pid: {:?}, rip: {:#x}, error_code: {:#x}, err: {:?}",
                ProcessManager::current_pid(),
                regs.rip,
                error_code,
                err
            );
        }
        return;
    }

    error!(
        "do_segment_not_exists(11), \tError code: {:#x},\trsp: {:#x},\trip: {:#x},\t CPU: {}, \tpid: {:?}",
        error_code,
        regs.rsp,
        regs.rip,
        smp_get_processor_id().data(),
        ProcessManager::current_pid()
    );
    panic!("Segment Not Exists");
}

/// 处理栈段错误 12 #SS
#[no_mangle]
unsafe extern "C" fn do_stack_segment_fault(regs: &'static mut TrapFrame, error_code: u64) {
    if regs.is_from_user() {
        crate::exception::uprobe::mark_current_xol_trapped();
        CurrentIrqArch::interrupt_enable();
        if let Err(err) = force_kernel_signal_to_current(Signal::SIGBUS) {
            error!(
                "failed to send SIGBUS for user stack-segment fault, pid: {:?}, rip: {:#x}, error_code: {:#x}, err: {:?}",
                ProcessManager::current_pid(),
                regs.rip,
                error_code,
                err
            );
        }
        return;
    }

    error!(
        "do_stack_segment_fault(12), \tError code: {:#x},\trsp: {:#x},\trip: {:#x},\t CPU: {}, \tpid: {:?}",
        error_code,
        regs.rsp,
        regs.rip,
        smp_get_processor_id().data(),
        ProcessManager::current_pid()
    );
    panic!("Stack Segment Fault");
}

/// 处理一般保护异常 13 #GP
#[no_mangle]
unsafe extern "C" fn do_general_protection(regs: &'static mut TrapFrame, error_code: u64) {
    if try_fixup_kernel_exception(regs) {
        return;
    }

    if regs.is_from_user() {
        // A user #GP is definitively converted to SIGSEGV here; do not abort
        // unconditionally at the exception entry, only mark the actual signal
        // delivery path.
        crate::exception::uprobe::mark_current_xol_trapped();
        CurrentIrqArch::interrupt_enable();
        if let Err(err) = force_kernel_signal_to_current(Signal::SIGSEGV) {
            error!(
                "failed to send SIGSEGV for user general protection fault, pid: {:?}, rip: {:#x}, error_code: {:#x}, err: {:?}",
                ProcessManager::current_pid(),
                regs.rip,
                error_code,
                err
            );
        }
        return;
    }

    const ERR_MSG_1: &str = "The exception occurred during delivery of an event external to the program, such as an interrupt or an earlier exception.";
    const ERR_MSG_2: &str = "Refers to a gate descriptor in the IDT;\n";
    const ERR_MSG_3: &str = "Refers to a descriptor in the GDT or the current LDT;\n";
    const ERR_MSG_4: &str = "Refers to a segment or gate descriptor in the LDT;\n";
    const ERR_MSG_5: &str = "Refers to a descriptor in the current GDT;\n";

    let msg1: &str = if (error_code & 0x1) != 0 {
        ERR_MSG_1
    } else {
        ""
    };

    let msg2: &str = if (error_code & 0x02) != 0 {
        ERR_MSG_2
    } else {
        ERR_MSG_3
    };

    let msg3: &str = if (error_code & 0x02) == 0 {
        if (error_code & 0x04) != 0 {
            ERR_MSG_4
        } else {
            ERR_MSG_5
        }
    } else {
        ""
    };
    error!(
        "do_general_protection(13), \tError code: {:#x},\trsp: {:#x},\trip: {:#x},\t rflags: {:#x}\t CPU: {}, \tpid: {:?}
{}{}{}
Segment Selector Index: {:#x}\n
",
        error_code,
        regs.rsp,
        regs.rip,
        regs.rflags,
        smp_get_processor_id().data(),
        ProcessManager::current_pid(),
        msg1, msg2, msg3,
        error_code & 0xfff8
    );
    panic!("General Protection");
}

#[inline]
fn try_fixup_kernel_exception(regs: &mut TrapFrame) -> bool {
    if regs.is_from_user() {
        return false;
    }
    let Some(fixup_addr) = ExceptionTableManager::search_exception_table(regs.rip as usize) else {
        return false;
    };
    regs.rip = fixup_addr as u64;
    true
}

/// 处理页错误 14 #PF
#[no_mangle]
unsafe extern "C" fn do_page_fault(regs: &'static mut TrapFrame, error_code: u64) {
    // error!(
    //     "do_page_fault(14), \tError code: {:#x},\trsp: {:#x},\trip: {:#x},\t CPU: {}, \tpid: {:?}, \nFault Address: {:#x}",
    //     error_code,
    //     regs.rsp,
    //     regs.rip,
    //     smp_get_processor_id().data(),
    //     ProcessManager::current_pid(),
    //     x86::controlregs::cr2()
    // );

    // if (error_code & 0x01) == 0 {
    //     print!("Page Not Present,\t");
    // }
    // if (error_code & 0x02) != 0 {
    //     print!("Write Access,\t");
    // } else {
    //     print!("Read Access,\t");
    // }

    // if (error_code & 0x04) != 0 {
    //     print!("Fault in user(3),\t");
    // } else {
    //     print!("Fault in supervisor(0,1,2),\t");
    // }

    // if (error_code & 0x08) != 0 {
    //     print!("Reserved bit violation cause fault,\t");
    // }

    // if (error_code & 0x10) != 0 {
    //     print!("Instruction fetch cause fault,\t");
    // }
    // print!("\n");

    // CurrentIrqArch::interrupt_enable();
    // panic!("Page Fault");
    CurrentIrqArch::interrupt_disable();
    let address = x86::controlregs::cr2();
    // log::info!(
    //     "fault address: {:#x}, error_code: {:#b}, pid: {}\n",
    //     address,
    //     error_code,
    //     ProcessManager::current_pid().data()
    // );

    let address = VirtAddr::new(address);
    let error_code = X86PfErrorCode::from_bits_truncate(error_code as u32);
    // NOTE:
    // - 是否“用户态缺页”应优先以 TrapFrame/错误码反映的访问发起者(CPL)为准，
    //   而不是仅以地址落在用户区间来判断。
    // - 用户态访问高地址（例如 x86_64 的 vsyscall 0xffffffffff600000 区域，或
    //   用户态误跳转到内核地址空间）应当产生 SIGSEGV，而不是触发内核 panic。
    // - 内核态访问用户地址（如 copy_from_user/copy_to_user）应当走用户态 fault
    //   处理路径，以便使用异常表进行修复并返回 -EFAULT。
    if regs.is_from_user()
        || error_code.contains(X86PfErrorCode::X86_PF_USER)
        || address.check_user()
    {
        MMArch::do_user_addr_fault(regs, error_code, address);
    } else {
        MMArch::do_kern_addr_fault(regs, error_code, address);
    }
    CurrentIrqArch::interrupt_enable();
}

/// 处理x87 FPU错误 16 #MF
#[no_mangle]
unsafe extern "C" fn do_x87_FPU_error(regs: &'static TrapFrame, error_code: u64) {
    error!(
        "do_x87_FPU_error(16), \tError code: {:#x},\trsp: {:#x},\trip: {:#x},\t CPU: {}, \tpid: {:?}",
        error_code,
        regs.rsp,
        regs.rip,
        smp_get_processor_id().data(),
        ProcessManager::current_pid()
    );
    panic!("x87 FPU Error");
}

/// 处理对齐检查 17 #AC
#[no_mangle]
unsafe extern "C" fn do_alignment_check(regs: &'static TrapFrame, error_code: u64) {
    error!(
        "do_alignment_check(17), \tError code: {:#x},\trsp: {:#x},\trip: {:#x},\t CPU: {}, \tpid: {:?}",
        error_code,
        regs.rsp,
        regs.rip,
        smp_get_processor_id().data(),
        ProcessManager::current_pid()
    );
    panic!("Alignment Check");
}

/// 处理机器检查 18 #MC
#[no_mangle]
unsafe extern "C" fn do_machine_check(regs: &'static TrapFrame, error_code: u64) {
    error!(
        "do_machine_check(18), \tError code: {:#x},\trsp: {:#x},\trip: {:#x},\t CPU: {}, \tpid: {:?}",
        error_code,
        regs.rsp,
        regs.rip,
        smp_get_processor_id().data(),
        ProcessManager::current_pid()
    );
    panic!("Machine Check");
}

/// 处理SIMD异常 19 #XM
#[no_mangle]
unsafe extern "C" fn do_SIMD_exception(regs: &'static TrapFrame, error_code: u64) {
    error!(
        "do_SIMD_exception(19), \tError code: {:#x},\trsp: {:#x},\trip: {:#x},\t CPU: {}, \tpid: {:?}",
        error_code,
        regs.rsp,
        regs.rip,
        smp_get_processor_id().data(),
        ProcessManager::current_pid()
    );
    panic!("SIMD Exception");
}

/// 处理虚拟化异常 20 #VE
#[no_mangle]
unsafe extern "C" fn do_virtualization_exception(regs: &'static TrapFrame, error_code: u64) {
    error!(
        "do_virtualization_exception(20), \tError code: {:#x},\trsp: {:#x},\trip: {:#x},\t CPU: {}, \tpid: {:?}",
        error_code,
        regs.rsp,
        regs.rip,
        smp_get_processor_id().data(),
        ProcessManager::current_pid()
    );
    panic!("Virtualization Exception");
}

#[no_mangle]
unsafe extern "C" fn ignore_int_handler(_regs: &'static TrapFrame, _error_code: u64) {
    warn!("Unknown interrupt.");
}
