Skip to content

Commit

Permalink
Merge pull request #387 from Zildj1an/master
Browse files Browse the repository at this point in the history
Add missing IDT entries #CP and #HV
  • Loading branch information
Freax13 authored Jul 21, 2022
2 parents 0e53eef + dc62de7 commit 922c557
Showing 1 changed file with 54 additions and 11 deletions.
65 changes: 54 additions & 11 deletions src/structures/idt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -340,8 +340,38 @@ pub struct InterruptDescriptorTable {
/// vector nr. 20
pub virtualization: Entry<HandlerFunc>,

/// vector nr. 21-28
reserved_2: [Entry<HandlerFunc>; 8],
/// A #CP exception is generated when shadow stacks are enabled and mismatch
/// scenarios are detected (possible error code cases below).
///
/// The error code is the #CP error code, for each of the following situations:
/// - A RET (near) instruction encountered a return address mismatch.
/// - A RET (far) instruction encountered a return address mismatch.
/// - A RSTORSSP instruction encountered an invalid shadow stack restore token.
/// - A SETSSBY instruction encountered an invalid supervisor shadow stack token.
/// - A missing ENDBRANCH instruction if indirect branch tracking is enabled.
///
/// vector nr. 21
pub cp_protection_exception: Entry<HandlerFuncWithErrCode>,

/// vector nr. 22-27
reserved_2: [Entry<HandlerFunc>; 6],

/// The Hypervisor Injection Exception (`#HV`) is injected by a hypervisor
/// as a doorbell to inform an `SEV-SNP` enabled guest running with the
/// `Restricted Injection` feature of events to be processed.
///
/// `SEV-SNP` stands for the _"Secure Nested Paging"_ feature of the _"AMD
/// Secure Encrypted Virtualization"_ technology. The `Restricted
/// Injection` feature disables all hypervisor-based interrupt queuing
/// and event injection of all vectors except #HV.
///
/// The `#HV` exception is a benign exception and can only be injected as
/// an exception and without an error code. `SEV-SNP` enabled guests are
/// expected to communicate with the hypervisor about events via a
/// software-managed para-virtualization interface.
///
/// The vector number of the ``#HV`` exception is 28.
pub hv_injection_exception: Entry<HandlerFunc>,

/// The VMM Communication Exception (`#VC`) is always generated by hardware when an `SEV-ES`
/// enabled guest is running and an `NAE` event occurs.
Expand Down Expand Up @@ -436,7 +466,9 @@ impl InterruptDescriptorTable {
machine_check: Entry::missing(),
simd_floating_point: Entry::missing(),
virtualization: Entry::missing(),
reserved_2: [Entry::missing(); 8],
cp_protection_exception: Entry::missing(),
reserved_2: [Entry::missing(); 6],
hv_injection_exception: Entry::missing(),
vmm_communication_exception: Entry::missing(),
security_exception: Entry::missing(),
reserved_3: Entry::missing(),
Expand Down Expand Up @@ -555,9 +587,10 @@ impl Index<usize> for InterruptDescriptorTable {
16 => &self.x87_floating_point,
19 => &self.simd_floating_point,
20 => &self.virtualization,
28 => &self.hv_injection_exception,
i @ 32..=255 => &self.interrupts[i - 32],
i @ 15 | i @ 31 | i @ 21..=28 => panic!("entry {} is reserved", i),
i @ 8 | i @ 10..=14 | i @ 17 | i @ 29 | i @ 30 => {
i @ 15 | i @ 31 | i @ 22..=27 => panic!("entry {} is reserved", i),
i @ 8 | i @ 10..=14 | i @ 17 | i @ 21 | i @ 29 | i @ 30 => {
panic!("entry {} is an exception with error code", i)
}
i @ 18 => panic!("entry {} is an diverging exception (must not return)", i),
Expand Down Expand Up @@ -586,9 +619,10 @@ impl IndexMut<usize> for InterruptDescriptorTable {
16 => &mut self.x87_floating_point,
19 => &mut self.simd_floating_point,
20 => &mut self.virtualization,
28 => &mut self.hv_injection_exception,
i @ 32..=255 => &mut self.interrupts[i - 32],
i @ 15 | i @ 31 | i @ 21..=28 => panic!("entry {} is reserved", i),
i @ 8 | i @ 10..=14 | i @ 17 | i @ 29 | i @ 30 => {
i @ 15 | i @ 31 | i @ 22..=27 => panic!("entry {} is reserved", i),
i @ 8 | i @ 10..=14 | i @ 17 | i @ 21 | i @ 29 | i @ 30 => {
panic!("entry {} is an exception with error code", i)
}
i @ 18 => panic!("entry {} is an diverging exception (must not return)", i),
Expand Down Expand Up @@ -1290,6 +1324,15 @@ macro_rules! set_general_handler_entry {
}
$idt.machine_check.set_handler_fn(handler);
}};
($idt:expr, $handler:ident, $idx:ident, 0, 0, 0, 1, 0, 1, 0, 1) => {{
extern "x86-interrupt" fn handler(
frame: $crate::structures::idt::InterruptStackFrame,
error_code: u64,
) {
$handler(frame, $idx.into(), Some(error_code));
}
$idt.cp_protection_exception.set_handler_fn(handler);
}};
($idt:expr, $handler:ident, $idx:ident, 0, 0, 0, 1, 1, 1, 0, 1) => {
extern "x86-interrupt" fn handler(
frame: $crate::structures::idt::InterruptStackFrame,
Expand All @@ -1312,14 +1355,12 @@ macro_rules! set_general_handler_entry {
// reserved_1
($idt:expr, $handler:ident, $idx:ident, 0, 0, 0, 0, 1, 1, 1, 1) => {};
// reserved_2
($idt:expr, $handler:ident, $idx:ident, 0, 0, 0, 1, 0, 1, 0, 1) => {};
($idt:expr, $handler:ident, $idx:ident, 0, 0, 0, 1, 0, 1, 1, 0) => {};
($idt:expr, $handler:ident, $idx:ident, 0, 0, 0, 1, 0, 1, 1, 1) => {};
($idt:expr, $handler:ident, $idx:ident, 0, 0, 0, 1, 1, 0, 0, 0) => {};
($idt:expr, $handler:ident, $idx:ident, 0, 0, 0, 1, 1, 0, 0, 1) => {};
($idt:expr, $handler:ident, $idx:ident, 0, 0, 0, 1, 1, 0, 1, 0) => {};
($idt:expr, $handler:ident, $idx:ident, 0, 0, 0, 1, 1, 0, 1, 1) => {};
($idt:expr, $handler:ident, $idx:ident, 0, 0, 0, 1, 1, 1, 0, 0) => {};
// reserved_3
($idt:expr, $handler:ident, $idx:ident, 0, 0, 0, 1, 1, 1, 1, 1) => {};

Expand Down Expand Up @@ -1348,7 +1389,9 @@ mod test {
15 => &idt.reserved_1.options,
17 => &idt.alignment_check.options,
18 => &idt.machine_check.options,
i @ 21..=28 => &idt.reserved_2[i - 21].options,
21 => &idt.cp_protection_exception.options,
i @ 22..=27 => &idt.reserved_2[i - 22].options,
28 => &idt.hv_injection_exception.options,
29 => &idt.vmm_communication_exception.options,
30 => &idt.security_exception.options,
31 => &idt.reserved_3.options,
Expand Down Expand Up @@ -1404,7 +1447,7 @@ mod test {
}
set_general_handler!(&mut idt, general_handler);
for i in 0..256 {
if i == 15 || i == 31 || (21..=28).contains(&i) {
if i == 15 || i == 31 || (22..=27).contains(&i) {
// reserved entries should not be set
assert!(!entry_present(&idt, i));
} else {
Expand Down

0 comments on commit 922c557

Please sign in to comment.