1use bitflags::*;
5
6use core::arch::asm;
7use core::fmt;
8
9#[derive(Debug)]
11pub struct InterruptDescription {
12 pub vector: u8,
13 pub mnemonic: &'static str,
14 pub description: &'static str,
15 pub irqtype: &'static str,
16 pub source: &'static str,
17}
18
19impl fmt::Display for InterruptDescription {
20 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
21 write!(
22 f,
23 "{} ({}, vec={}) {}",
24 self.mnemonic, self.irqtype, self.vector, self.description
25 )
26 }
27}
28
29pub const DIVIDE_ERROR_VECTOR: u8 = 0;
30pub const DEBUG_VECTOR: u8 = 1;
31pub const NONMASKABLE_INTERRUPT_VECTOR: u8 = 2;
32pub const BREAKPOINT_VECTOR: u8 = 3;
33pub const OVERFLOW_VECTOR: u8 = 4;
34pub const BOUND_RANGE_EXCEEDED_VECTOR: u8 = 5;
35pub const INVALID_OPCODE_VECTOR: u8 = 6;
36pub const DEVICE_NOT_AVAILABLE_VECTOR: u8 = 7;
37pub const DOUBLE_FAULT_VECTOR: u8 = 8;
38pub const COPROCESSOR_SEGMENT_OVERRUN_VECTOR: u8 = 9;
39pub const INVALID_TSS_VECTOR: u8 = 10;
40pub const SEGMENT_NOT_PRESENT_VECTOR: u8 = 11;
41pub const STACK_SEGEMENT_FAULT_VECTOR: u8 = 12;
42pub const GENERAL_PROTECTION_FAULT_VECTOR: u8 = 13;
43pub const PAGE_FAULT_VECTOR: u8 = 14;
44pub const X87_FPU_VECTOR: u8 = 16;
45pub const ALIGNMENT_CHECK_VECTOR: u8 = 17;
46pub const MACHINE_CHECK_VECTOR: u8 = 18;
47pub const SIMD_FLOATING_POINT_VECTOR: u8 = 19;
48pub const VIRTUALIZATION_VECTOR: u8 = 20;
49
50pub static EXCEPTIONS: [InterruptDescription; 32] = [
52 InterruptDescription {
53 vector: DIVIDE_ERROR_VECTOR,
54 mnemonic: "#DE",
55 description: "Divide Error",
56 irqtype: "Fault",
57 source: "DIV and IDIV instructions.",
58 },
59 InterruptDescription {
60 vector: DEBUG_VECTOR,
61 mnemonic: "#DB",
62 description: "Debug",
63 irqtype: "Fault / Trap",
64 source: "Debug condition",
65 },
66 InterruptDescription {
67 vector: NONMASKABLE_INTERRUPT_VECTOR,
68 mnemonic: "NMI",
69 description: "Nonmaskable Interrupt",
70 irqtype: "Interrupt",
71 source: "Nonmaskable external interrupt.",
72 },
73 InterruptDescription {
74 vector: BREAKPOINT_VECTOR,
75 mnemonic: "#BP",
76 description: "Breakpoint",
77 irqtype: "Trap",
78 source: "INT 3 instruction.",
79 },
80 InterruptDescription {
81 vector: OVERFLOW_VECTOR,
82 mnemonic: "#OF",
83 description: "Overflow",
84 irqtype: "Trap",
85 source: "INTO instruction.",
86 },
87 InterruptDescription {
88 vector: BOUND_RANGE_EXCEEDED_VECTOR,
89 mnemonic: "#BR",
90 description: "BOUND Range Exceeded",
91 irqtype: "Fault",
92 source: "BOUND instruction.",
93 },
94 InterruptDescription {
95 vector: INVALID_OPCODE_VECTOR,
96 mnemonic: "#UD",
97 description: "Invalid Opcode (Undefined \
98 Opcode)",
99 irqtype: "Fault",
100 source: "UD2 instruction or reserved \
101 opcode.",
102 },
103 InterruptDescription {
104 vector: DEVICE_NOT_AVAILABLE_VECTOR,
105 mnemonic: "#NM",
106 description: "Device Not Available (No \
107 Math Coprocessor)",
108 irqtype: "Fault",
109 source: "Floating-point or WAIT/FWAIT \
110 instruction.",
111 },
112 InterruptDescription {
113 vector: DOUBLE_FAULT_VECTOR,
114 mnemonic: "#DF",
115 description: "Double Fault",
116 irqtype: "Abort",
117 source: "Any instruction that can \
118 generate an exception, an NMI, \
119 or an INTR.",
120 },
121 InterruptDescription {
122 vector: COPROCESSOR_SEGMENT_OVERRUN_VECTOR,
123 mnemonic: "",
124 description: "Coprocessor Segment Overrun",
125 irqtype: "Fault",
126 source: "Floating-point instruction.",
127 },
128 InterruptDescription {
129 vector: INVALID_TSS_VECTOR,
130 mnemonic: "#TS",
131 description: "Invalid TSS",
132 irqtype: "Fault",
133 source: "Task switch or TSS access.",
134 },
135 InterruptDescription {
136 vector: SEGMENT_NOT_PRESENT_VECTOR,
137 mnemonic: "#NP",
138 description: "Segment Not Present",
139 irqtype: "Fault",
140 source: "Loading segment registers or \
141 accessing system segments.",
142 },
143 InterruptDescription {
144 vector: STACK_SEGEMENT_FAULT_VECTOR,
145 mnemonic: "#SS",
146 description: "Stack-Segment Fault",
147 irqtype: "Fault",
148 source: "Stack operations and SS register \
149 loads.",
150 },
151 InterruptDescription {
152 vector: GENERAL_PROTECTION_FAULT_VECTOR,
153 mnemonic: "#GP",
154 description: "General Protection",
155 irqtype: "Fault",
156 source: "Any memory reference and other \
157 protection checks.",
158 },
159 InterruptDescription {
160 vector: PAGE_FAULT_VECTOR,
161 mnemonic: "#PF",
162 description: "Page Fault",
163 irqtype: "Fault",
164 source: "Any memory reference.",
165 },
166 InterruptDescription {
167 vector: 15,
168 mnemonic: "",
169 description: "RESERVED",
170 irqtype: "",
171 source: "None.",
172 },
173 InterruptDescription {
174 vector: X87_FPU_VECTOR,
175 mnemonic: "#MF",
176 description: "x87 FPU Floating-Point",
177 irqtype: "Fault",
178 source: "x87 FPU instructions.",
179 },
180 InterruptDescription {
181 vector: ALIGNMENT_CHECK_VECTOR,
182 mnemonic: "#AC",
183 description: "Alignment Check",
184 irqtype: "Fault",
185 source: "Unaligned memory access.",
186 },
187 InterruptDescription {
188 vector: MACHINE_CHECK_VECTOR,
189 mnemonic: "#MC",
190 description: "Machine Check",
191 irqtype: "Abort",
192 source: "Internal machine error.",
193 },
194 InterruptDescription {
195 vector: SIMD_FLOATING_POINT_VECTOR,
196 mnemonic: "#XM",
197 description: "SIMD Floating-Point",
198 irqtype: "Fault",
199 source: "SSE SIMD instructions.",
200 },
201 InterruptDescription {
202 vector: VIRTUALIZATION_VECTOR,
203 mnemonic: "#VE",
204 description: "Virtualization",
205 irqtype: "Fault",
206 source: "EPT violation.",
207 },
208 InterruptDescription {
209 vector: 21,
210 mnemonic: "",
211 description: "RESERVED",
212 irqtype: "",
213 source: ".",
214 },
215 InterruptDescription {
216 vector: 22,
217 mnemonic: "",
218 description: "RESERVED",
219 irqtype: "",
220 source: ".",
221 },
222 InterruptDescription {
223 vector: 23,
224 mnemonic: "",
225 description: "RESERVED",
226 irqtype: "",
227 source: ".",
228 },
229 InterruptDescription {
230 vector: 24,
231 mnemonic: "",
232 description: "RESERVED",
233 irqtype: "",
234 source: ".",
235 },
236 InterruptDescription {
237 vector: 25,
238 mnemonic: "",
239 description: "RESERVED",
240 irqtype: "",
241 source: ".",
242 },
243 InterruptDescription {
244 vector: 26,
245 mnemonic: "",
246 description: "RESERVED",
247 irqtype: "",
248 source: ".",
249 },
250 InterruptDescription {
251 vector: 27,
252 mnemonic: "",
253 description: "RESERVED",
254 irqtype: "",
255 source: "",
256 },
257 InterruptDescription {
258 vector: 28,
259 mnemonic: "",
260 description: "",
261 irqtype: "",
262 source: "",
263 },
264 InterruptDescription {
265 vector: 29,
266 mnemonic: "",
267 description: "RESERVED",
268 irqtype: "",
269 source: ".",
270 },
271 InterruptDescription {
272 vector: 30,
273 mnemonic: "",
274 description: "RESERVED",
275 irqtype: "",
276 source: "",
277 },
278 InterruptDescription {
279 vector: 31,
280 mnemonic: "",
281 description: "RESERVED",
282 irqtype: "",
283 source: "",
284 },
285];
286
287bitflags! {
288 pub struct PageFaultError: u32 {
290 const P = bit!(0);
293
294 const WR = bit!(1);
297
298 const US = bit!(2);
303
304 const RSVD = bit!(3);
307
308 const ID = bit!(4);
311
312 const PK = bit!(5);
315 }
316}
317
318impl fmt::Display for PageFaultError {
319 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
320 let p = match self.contains(PageFaultError::P) {
321 false => "The fault was caused by a non-present page.",
322 true => "The fault was caused by a page-level protection violation.",
323 };
324 let wr = match self.contains(PageFaultError::WR) {
325 false => "The access causing the fault was a read.",
326 true => "The access causing the fault was a write.",
327 };
328 let us = match self.contains(PageFaultError::US) {
329 false => {
330 "The access causing the fault originated when the processor was executing in \
331 supervisor mode."
332 }
333 true => {
334 "The access causing the fault originated when the processor was executing in user \
335 mode."
336 }
337 };
338 let rsvd = match self.contains(PageFaultError::RSVD) {
339 false => "The fault was not caused by reserved bit violation.",
340 true => "The fault was caused by reserved bits set to 1 in a page directory.",
341 };
342 let id = match self.contains(PageFaultError::ID) {
343 false => "The fault was not caused by an instruction fetch.",
344 true => "The fault was caused by an instruction fetch.",
345 };
346
347 write!(f, "{}\n{}\n{}\n{}\n{}", p, wr, us, rsvd, id)
348 }
349}
350
351pub unsafe fn enable() {
356 asm!("sti");
357}
358
359pub unsafe fn disable() {
364 asm!("cli");
365}
366
367#[macro_export]
370macro_rules! int {
371 ($x:expr) => {{
372 core::arch::asm!("int ${vec}", vec = const ($x));
373 }};
374}
375
376#[cfg(all(test, feature = "utest"))]
377mod test {
378 use super::*;
379 #[test]
380 fn bit_macro() {
381 assert!(PageFaultError::PK.bits() == 0b100000);
382 assert!(PageFaultError::ID.bits() == 0b10000);
383 assert!(PageFaultError::RSVD.bits() == 0b1000);
384 assert!(PageFaultError::US.bits() == 0b100);
385 assert!(PageFaultError::WR.bits() == 0b10);
386 assert!(PageFaultError::P.bits() == 0b1);
387 }
388}