Coverage Report

Created: 2026-01-13 06:58

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/x86-0.47.0/src/irq.rs
Line
Count
Source
1
//! Shared interrupt description and set-up code.
2
//! See the `bits*::irq` modules for arch-specific portions.
3
4
use bitflags::*;
5
6
use core::arch::asm;
7
use core::fmt;
8
9
/// x86 Exception description (see also Intel Vol. 3a Chapter 6).
10
#[derive(Debug)]
11
pub 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
19
impl fmt::Display for InterruptDescription {
20
0
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
21
0
        write!(
22
0
            f,
23
0
            "{} ({}, vec={}) {}",
24
            self.mnemonic, self.irqtype, self.vector, self.description
25
        )
26
0
    }
27
}
28
29
pub const DIVIDE_ERROR_VECTOR: u8 = 0;
30
pub const DEBUG_VECTOR: u8 = 1;
31
pub const NONMASKABLE_INTERRUPT_VECTOR: u8 = 2;
32
pub const BREAKPOINT_VECTOR: u8 = 3;
33
pub const OVERFLOW_VECTOR: u8 = 4;
34
pub const BOUND_RANGE_EXCEEDED_VECTOR: u8 = 5;
35
pub const INVALID_OPCODE_VECTOR: u8 = 6;
36
pub const DEVICE_NOT_AVAILABLE_VECTOR: u8 = 7;
37
pub const DOUBLE_FAULT_VECTOR: u8 = 8;
38
pub const COPROCESSOR_SEGMENT_OVERRUN_VECTOR: u8 = 9;
39
pub const INVALID_TSS_VECTOR: u8 = 10;
40
pub const SEGMENT_NOT_PRESENT_VECTOR: u8 = 11;
41
pub const STACK_SEGEMENT_FAULT_VECTOR: u8 = 12;
42
pub const GENERAL_PROTECTION_FAULT_VECTOR: u8 = 13;
43
pub const PAGE_FAULT_VECTOR: u8 = 14;
44
pub const X87_FPU_VECTOR: u8 = 16;
45
pub const ALIGNMENT_CHECK_VECTOR: u8 = 17;
46
pub const MACHINE_CHECK_VECTOR: u8 = 18;
47
pub const SIMD_FLOATING_POINT_VECTOR: u8 = 19;
48
pub const VIRTUALIZATION_VECTOR: u8 = 20;
49
50
/// x86 External Interrupts (1-32).
51
pub 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
287
bitflags! {
288
    // Taken from Intel Manual Section 4.7 Page-Fault Exceptions.
289
    pub struct PageFaultError: u32 {
290
        /// 0: The fault was caused by a non-present page.
291
        /// 1: The fault was caused by a page-level protection violation
292
        const P = bit!(0);
293
294
        /// 0: The access causing the fault was a read.
295
        /// 1: The access causing the fault was a write.
296
        const WR = bit!(1);
297
298
        /// 0: The access causing the fault originated when the processor
299
        /// was executing in supervisor mode.
300
        /// 1: The access causing the fault originated when the processor
301
        /// was executing in user mode.
302
        const US = bit!(2);
303
304
        /// 0: The fault was not caused by reserved bit violation.
305
        /// 1: The fault was caused by reserved bits set to 1 in a page directory.
306
        const RSVD = bit!(3);
307
308
        /// 0: The fault was not caused by an instruction fetch.
309
        /// 1: The fault was caused by an instruction fetch.
310
        const ID = bit!(4);
311
312
        /// 0: The fault was not by protection keys.
313
        /// 1: There was a protection key violation.
314
        const PK = bit!(5);
315
    }
316
}
317
318
impl fmt::Display for PageFaultError {
319
0
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
320
0
        let p = match self.contains(PageFaultError::P) {
321
0
            false => "The fault was caused by a non-present page.",
322
0
            true => "The fault was caused by a page-level protection violation.",
323
        };
324
0
        let wr = match self.contains(PageFaultError::WR) {
325
0
            false => "The access causing the fault was a read.",
326
0
            true => "The access causing the fault was a write.",
327
        };
328
0
        let us = match self.contains(PageFaultError::US) {
329
            false => {
330
0
                "The access causing the fault originated when the processor was executing in \
331
0
                 supervisor mode."
332
            }
333
            true => {
334
0
                "The access causing the fault originated when the processor was executing in user \
335
0
                 mode."
336
            }
337
        };
338
0
        let rsvd = match self.contains(PageFaultError::RSVD) {
339
0
            false => "The fault was not caused by reserved bit violation.",
340
0
            true => "The fault was caused by reserved bits set to 1 in a page directory.",
341
        };
342
0
        let id = match self.contains(PageFaultError::ID) {
343
0
            false => "The fault was not caused by an instruction fetch.",
344
0
            true => "The fault was caused by an instruction fetch.",
345
        };
346
347
0
        write!(f, "{}\n{}\n{}\n{}\n{}", p, wr, us, rsvd, id)
348
0
    }
349
}
350
351
/// Enable Interrupts.
352
///
353
/// # Safety
354
/// Only allowed if we have IO privileges for the current operating level in RFlags.
355
0
pub unsafe fn enable() {
356
0
    asm!("sti");
357
0
}
358
359
/// Disable Interrupts.
360
///
361
/// # Safety
362
/// Only allowed if we have IO privileges for the current operating level in RFlags.
363
0
pub unsafe fn disable() {
364
0
    asm!("cli");
365
0
}
366
367
/// Generate a software interrupt.
368
/// This is a macro argument needs to be an immediate.
369
#[macro_export]
370
macro_rules! int {
371
    ($x:expr) => {{
372
        asm!("int ${vec}", vec = const ($x));
373
    }};
374
}
375
376
#[cfg(all(test, feature = "utest"))]
377
mod 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
}