rusty_mos/kernel/
trap.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
//! Handle exceptions(traps) and handler definitions.

use core::arch::asm;

use crate::println;

/// Things need to be stored in the trapframe.
#[repr(C)]
#[derive(Clone, Copy, Debug, Default)]
pub struct TrapFrame {
    /// All the regular registers.
    pub regs: [u32; 32],
    /// The Status register in CP0.
    pub cp0_status: u32,
    /// The HI register.
    pub hi: u32,
    /// The LO register.
    pub lo: u32,
    /// The BadAddr register in CP0.
    pub cp0_badvaddr: u32,
    /// The Cause register in CP0.
    pub cp0_cause: u32,
    /// The EPC register in CP0.
    pub cp0_epc: u32,
}

impl TrapFrame {
    /// The default value of the registers.
    pub const fn const_construct() -> Self {
        Self {
            regs: [0; 32],
            cp0_status: 0,
            hi: 0,
            lo: 0,
            cp0_badvaddr: 0,
            cp0_cause: 0,
            cp0_epc: 0,
        }
    }
}

extern "C" {
    /// Handle unknown exception code. Invoke a kernel panic.
    pub fn handle_reserved(trap_frame: *const TrapFrame);
    /// Skip the current instruction.
    pub fn handle_skip(trap_frame: *const TrapFrame);
    /// Handle the clock-interrupt.
    pub fn handle_int(trap_frame: *const TrapFrame);
    /// Handle the TLBL or TLBS exception.
    pub fn handle_tlb(trap_frame: *const TrapFrame);
    /// Handle the TLB Mod exception.
    pub fn handle_mod(trap_frame: *const TrapFrame);
    /// Handle the syscall.
    pub fn handle_sys(trap_frame: *const TrapFrame);
}

/// Exception handlers table. This will be exported as `exception_handlers`.
#[export_name = "exception_handlers"]
pub static EXCEPTION_HANDLERS: [unsafe extern "C" fn(*const TrapFrame); 32] = [
    /*  0 */ handle_int,
    /*  1 */ handle_mod, // TLB Mod
    /*  2 */ handle_tlb, // TLB L
    /*  3 */ handle_tlb, // TLB S
    /*  4 */ handle_skip, // AdEL
    /*  5 */ handle_skip, // AdES
    /*  6 */ handle_reserved,
    /*  7 */ handle_reserved,
    /*  8 */ handle_sys,
    /*  9 */ handle_reserved,
    /* 10 */ handle_skip, // RI
    /* 11 */ handle_reserved,
    /* 12 */ handle_skip, // Ov
    /* 13 */ handle_reserved,
    /* 14 */ handle_reserved,
    /* 15 */ handle_reserved,
    /* 16 */ handle_reserved,
    /* 17 */ handle_reserved,
    /* 18 */ handle_reserved,
    /* 19 */ handle_reserved,
    /* 20 */ handle_reserved,
    /* 21 */ handle_reserved,
    /* 22 */ handle_reserved,
    /* 23 */ handle_reserved,
    /* 24 */ handle_reserved,
    /* 25 */ handle_reserved,
    /* 26 */ handle_reserved,
    /* 27 */ handle_reserved,
    /* 28 */ handle_reserved,
    /* 29 */ handle_reserved,
    /* 30 */ handle_reserved,
    /* 31 */ handle_reserved,
];

/// Invoke a panic.
///
/// # Safety
///
/// The `trap_frame` *shall* be a valid address.
#[no_mangle]
pub unsafe fn do_reserved(trap_frame: *const TrapFrame) {
    panic!(
        "Unknown ExcCode {:2}",
        ((*trap_frame).cp0_cause >> 2) & 0x1f
    );
}

/// Skip the current instruction.
///
/// # Safety
///
/// The `trap_frame` *shall* be a valid address.
#[no_mangle]
pub unsafe fn do_skip(trap_frame: *mut TrapFrame) {
    println!(
        "\x1b[31mExcCode {:2} detected. Skipped!\x1b[0m",
        ((*trap_frame).cp0_cause >> 2) & 0x1f
    );
    (*trap_frame).cp0_epc += 4;
}

/// Set the exception base entry.
pub fn set_exc_base(exc_handler: u32) {
    println!(">> Exc Entry: 0x{:x} <<", exc_handler);
    unsafe { asm!("mtc0 {}, $15, 1", in(reg) exc_handler) };
}