Skip to content

Commit 922c557

Browse files
authored
Merge pull request #387 from Zildj1an/master
Add missing IDT entries #CP and #HV
2 parents 0e53eef + dc62de7 commit 922c557

File tree

1 file changed

+54
-11
lines changed

1 file changed

+54
-11
lines changed

src/structures/idt.rs

Lines changed: 54 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -340,8 +340,38 @@ pub struct InterruptDescriptorTable {
340340
/// vector nr. 20
341341
pub virtualization: Entry<HandlerFunc>,
342342

343-
/// vector nr. 21-28
344-
reserved_2: [Entry<HandlerFunc>; 8],
343+
/// A #CP exception is generated when shadow stacks are enabled and mismatch
344+
/// scenarios are detected (possible error code cases below).
345+
///
346+
/// The error code is the #CP error code, for each of the following situations:
347+
/// - A RET (near) instruction encountered a return address mismatch.
348+
/// - A RET (far) instruction encountered a return address mismatch.
349+
/// - A RSTORSSP instruction encountered an invalid shadow stack restore token.
350+
/// - A SETSSBY instruction encountered an invalid supervisor shadow stack token.
351+
/// - A missing ENDBRANCH instruction if indirect branch tracking is enabled.
352+
///
353+
/// vector nr. 21
354+
pub cp_protection_exception: Entry<HandlerFuncWithErrCode>,
355+
356+
/// vector nr. 22-27
357+
reserved_2: [Entry<HandlerFunc>; 6],
358+
359+
/// The Hypervisor Injection Exception (`#HV`) is injected by a hypervisor
360+
/// as a doorbell to inform an `SEV-SNP` enabled guest running with the
361+
/// `Restricted Injection` feature of events to be processed.
362+
///
363+
/// `SEV-SNP` stands for the _"Secure Nested Paging"_ feature of the _"AMD
364+
/// Secure Encrypted Virtualization"_ technology. The `Restricted
365+
/// Injection` feature disables all hypervisor-based interrupt queuing
366+
/// and event injection of all vectors except #HV.
367+
///
368+
/// The `#HV` exception is a benign exception and can only be injected as
369+
/// an exception and without an error code. `SEV-SNP` enabled guests are
370+
/// expected to communicate with the hypervisor about events via a
371+
/// software-managed para-virtualization interface.
372+
///
373+
/// The vector number of the ``#HV`` exception is 28.
374+
pub hv_injection_exception: Entry<HandlerFunc>,
345375

346376
/// The VMM Communication Exception (`#VC`) is always generated by hardware when an `SEV-ES`
347377
/// enabled guest is running and an `NAE` event occurs.
@@ -436,7 +466,9 @@ impl InterruptDescriptorTable {
436466
machine_check: Entry::missing(),
437467
simd_floating_point: Entry::missing(),
438468
virtualization: Entry::missing(),
439-
reserved_2: [Entry::missing(); 8],
469+
cp_protection_exception: Entry::missing(),
470+
reserved_2: [Entry::missing(); 6],
471+
hv_injection_exception: Entry::missing(),
440472
vmm_communication_exception: Entry::missing(),
441473
security_exception: Entry::missing(),
442474
reserved_3: Entry::missing(),
@@ -555,9 +587,10 @@ impl Index<usize> for InterruptDescriptorTable {
555587
16 => &self.x87_floating_point,
556588
19 => &self.simd_floating_point,
557589
20 => &self.virtualization,
590+
28 => &self.hv_injection_exception,
558591
i @ 32..=255 => &self.interrupts[i - 32],
559-
i @ 15 | i @ 31 | i @ 21..=28 => panic!("entry {} is reserved", i),
560-
i @ 8 | i @ 10..=14 | i @ 17 | i @ 29 | i @ 30 => {
592+
i @ 15 | i @ 31 | i @ 22..=27 => panic!("entry {} is reserved", i),
593+
i @ 8 | i @ 10..=14 | i @ 17 | i @ 21 | i @ 29 | i @ 30 => {
561594
panic!("entry {} is an exception with error code", i)
562595
}
563596
i @ 18 => panic!("entry {} is an diverging exception (must not return)", i),
@@ -586,9 +619,10 @@ impl IndexMut<usize> for InterruptDescriptorTable {
586619
16 => &mut self.x87_floating_point,
587620
19 => &mut self.simd_floating_point,
588621
20 => &mut self.virtualization,
622+
28 => &mut self.hv_injection_exception,
589623
i @ 32..=255 => &mut self.interrupts[i - 32],
590-
i @ 15 | i @ 31 | i @ 21..=28 => panic!("entry {} is reserved", i),
591-
i @ 8 | i @ 10..=14 | i @ 17 | i @ 29 | i @ 30 => {
624+
i @ 15 | i @ 31 | i @ 22..=27 => panic!("entry {} is reserved", i),
625+
i @ 8 | i @ 10..=14 | i @ 17 | i @ 21 | i @ 29 | i @ 30 => {
592626
panic!("entry {} is an exception with error code", i)
593627
}
594628
i @ 18 => panic!("entry {} is an diverging exception (must not return)", i),
@@ -1290,6 +1324,15 @@ macro_rules! set_general_handler_entry {
12901324
}
12911325
$idt.machine_check.set_handler_fn(handler);
12921326
}};
1327+
($idt:expr, $handler:ident, $idx:ident, 0, 0, 0, 1, 0, 1, 0, 1) => {{
1328+
extern "x86-interrupt" fn handler(
1329+
frame: $crate::structures::idt::InterruptStackFrame,
1330+
error_code: u64,
1331+
) {
1332+
$handler(frame, $idx.into(), Some(error_code));
1333+
}
1334+
$idt.cp_protection_exception.set_handler_fn(handler);
1335+
}};
12931336
($idt:expr, $handler:ident, $idx:ident, 0, 0, 0, 1, 1, 1, 0, 1) => {
12941337
extern "x86-interrupt" fn handler(
12951338
frame: $crate::structures::idt::InterruptStackFrame,
@@ -1312,14 +1355,12 @@ macro_rules! set_general_handler_entry {
13121355
// reserved_1
13131356
($idt:expr, $handler:ident, $idx:ident, 0, 0, 0, 0, 1, 1, 1, 1) => {};
13141357
// reserved_2
1315-
($idt:expr, $handler:ident, $idx:ident, 0, 0, 0, 1, 0, 1, 0, 1) => {};
13161358
($idt:expr, $handler:ident, $idx:ident, 0, 0, 0, 1, 0, 1, 1, 0) => {};
13171359
($idt:expr, $handler:ident, $idx:ident, 0, 0, 0, 1, 0, 1, 1, 1) => {};
13181360
($idt:expr, $handler:ident, $idx:ident, 0, 0, 0, 1, 1, 0, 0, 0) => {};
13191361
($idt:expr, $handler:ident, $idx:ident, 0, 0, 0, 1, 1, 0, 0, 1) => {};
13201362
($idt:expr, $handler:ident, $idx:ident, 0, 0, 0, 1, 1, 0, 1, 0) => {};
13211363
($idt:expr, $handler:ident, $idx:ident, 0, 0, 0, 1, 1, 0, 1, 1) => {};
1322-
($idt:expr, $handler:ident, $idx:ident, 0, 0, 0, 1, 1, 1, 0, 0) => {};
13231364
// reserved_3
13241365
($idt:expr, $handler:ident, $idx:ident, 0, 0, 0, 1, 1, 1, 1, 1) => {};
13251366

@@ -1348,7 +1389,9 @@ mod test {
13481389
15 => &idt.reserved_1.options,
13491390
17 => &idt.alignment_check.options,
13501391
18 => &idt.machine_check.options,
1351-
i @ 21..=28 => &idt.reserved_2[i - 21].options,
1392+
21 => &idt.cp_protection_exception.options,
1393+
i @ 22..=27 => &idt.reserved_2[i - 22].options,
1394+
28 => &idt.hv_injection_exception.options,
13521395
29 => &idt.vmm_communication_exception.options,
13531396
30 => &idt.security_exception.options,
13541397
31 => &idt.reserved_3.options,
@@ -1404,7 +1447,7 @@ mod test {
14041447
}
14051448
set_general_handler!(&mut idt, general_handler);
14061449
for i in 0..256 {
1407-
if i == 15 || i == 31 || (21..=28).contains(&i) {
1450+
if i == 15 || i == 31 || (22..=27).contains(&i) {
14081451
// reserved entries should not be set
14091452
assert!(!entry_present(&idt, i));
14101453
} else {

0 commit comments

Comments
 (0)