Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add missing IDT entries #CP and #HV #387

Merged
merged 8 commits into from
Jul 21, 2022
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.
Zildj1an marked this conversation as resolved.
Show resolved Hide resolved
/// - 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