Skip to main content

islet_rmm/exception/trap/
syndrome.rs

1use aarch64_cpu::registers::*;
2
3#[derive(Debug, Copy, Clone)]
4pub enum Fault {
5    AddressSize { level: u8 },
6    Translation { level: u8 },
7    AccessFlag { level: u8 },
8    Permission { level: u8 },
9    Alignment,
10    TLBConflict,
11    Other(u8),
12}
13
14const DFSC_MASK: u8 = 0x3f;
15const ISS_BRK_CMT_MASK: u16 = 0xffff;
16
17impl From<u32> for Fault {
18    fn from(origin: u32) -> Self {
19        let level = (origin & 0b11) as u8;
20        let origin = origin as u8;
21        match (origin & DFSC_MASK) >> 2 {
22            0b0000 => Fault::AddressSize { level },
23            0b0001 => Fault::Translation { level },
24            0b0010 => Fault::AccessFlag { level },
25            0b0011 => Fault::Permission { level },
26            0b1000 => Fault::Alignment,
27            0b1100 => Fault::TLBConflict,
28            _ => Fault::Other(origin & DFSC_MASK),
29        }
30    }
31}
32
33#[derive(Debug, Copy, Clone)]
34pub enum Syndrome {
35    Unknown,
36    PCAlignmentFault,
37    DataAbort(Fault),
38    InstructionAbort(Fault),
39    SPAlignmentFault,
40    Brk(u16),
41    HVC,
42    SMC,
43    SysRegInst,
44    WFX,
45    FPU,
46    SVE,
47    SME,
48    Other(u32),
49}
50
51impl From<u32> for Syndrome {
52    fn from(origin: u32) -> Self {
53        match (origin >> ESR_EL2::EC.shift) & ESR_EL2::EC.mask as u32 {
54            0b00_0000 => Syndrome::Unknown,
55            0b00_0001 => Syndrome::WFX,
56            0b00_0111 => Syndrome::FPU,
57            0b01_0010 => Syndrome::HVC,
58            0b01_0110 => Syndrome::HVC,
59            0b01_0011 => Syndrome::SMC,
60            0b01_0111 => Syndrome::SMC,
61            0b01_1000 => Syndrome::SysRegInst,
62            0b01_1001 => Syndrome::SVE,
63            0b01_1101 => Syndrome::SME,
64            0b10_0000 => {
65                debug!("Instruction Abort from a lower Exception level");
66                Syndrome::InstructionAbort(Fault::from(origin))
67            }
68            0b10_0001 => {
69                debug!("Instruction Abort taken without a change in Exception level");
70                Syndrome::InstructionAbort(Fault::from(origin))
71            }
72            0b10_0010 => Syndrome::PCAlignmentFault,
73            0b10_0100 => {
74                debug!("Data Abort from a lower Exception level");
75                Syndrome::DataAbort(Fault::from(origin))
76            }
77            0b10_0101 => {
78                debug!("Data Abort without a change in Exception level");
79                Syndrome::DataAbort(Fault::from(origin))
80            }
81            0b10_0110 => Syndrome::SPAlignmentFault,
82            0b11_1100 => Syndrome::Brk(origin as u16 & ISS_BRK_CMT_MASK),
83            ec => Syndrome::Other(ec),
84        }
85    }
86}
87
88impl Into<u64> for Syndrome {
89    fn into(self) -> u64 {
90        match self {
91            Syndrome::DataAbort(fault) => {
92                let ec: u64 = 0b10_0100 << ESR_EL2::EC.shift;
93                let iss: u64 = fault.into();
94                ec | iss
95            }
96            _ => {
97                panic!("Not implemented yet!");
98            }
99        }
100    }
101}
102
103impl Into<u64> for Fault {
104    fn into(self) -> u64 {
105        match self {
106            Fault::Translation { level } => (0b000100 | level) as u64,
107            _ => {
108                panic!("Not implemented yet!");
109            }
110        }
111    }
112}