Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 86 additions & 31 deletions src/migtd/src/driver/crash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,27 @@
use alloc::vec::Vec;
use core::sync::atomic::{AtomicBool, Ordering};
use raw_cpuid::{CpuId, CpuIdReader, CpuIdReaderNative, CpuIdResult};
#[cfg(not(test))]
use td_payload::mm::shared::alloc_shared_pages;
#[cfg(not(test))]
use x86_64::registers::model_specific::Msr;
const CPUID_HYPERV_VENDOR_MAX_FUNCTION: u32 = 0x40000000;
const CPUID_HYPERV_FEATURE_ID: u32 = 0x40000003;
const GUEST_CRASH_MSR_SUPPORT_BIT: u32 = 1 << 10;
#[cfg(not(test))]
const CRASH_NOTIFY_BIT: u64 = 1;
#[cfg(not(test))]
const CRASH_MESSAGE_BIT: u64 = 1 << 1;
#[cfg(not(test))]
const MSR_CRASH_P0: u32 = 0x40000100;
#[cfg(not(test))]
const MSR_CRASH_P3: u32 = 0x40000103;
#[cfg(not(test))]
const MSR_CRASH_P4: u32 = 0x40000104;
#[cfg(not(test))]
const MSR_CRASH_CTL: u32 = 0x40000105;
static GUEST_CRASH_MSR_SUPPORTED: AtomicBool = AtomicBool::new(false);
#[cfg(not(test))]
const PAGE_SIZE: usize = 0x1_000;

pub fn guest_crash_reg_supported() -> bool {
Expand All @@ -43,43 +52,89 @@ pub fn initialize_crash_msr_support() {
}
}

pub fn update_guest_crash_reg_report(errorcode: u64, crash_message: Vec<u8>) {
pub fn update_guest_crash_reg_report(
errorcode: u64,
crash_message: Vec<u8>,
#[cfg(test)] msr_crash_p0: &mut u64,
) {
if guest_crash_reg_supported() {
// Guest crash MSR
let mut msr_crash_p0 = Msr::new(MSR_CRASH_P0);
let mut msr_crash_p3 = Msr::new(MSR_CRASH_P3);
let mut msr_crash_p4 = Msr::new(MSR_CRASH_P4);
let mut msr_crash_ctl = Msr::new(MSR_CRASH_CTL);
#[cfg(not(test))]
{
// Guest crash MSR
let mut msr_crash_p0 = Msr::new(MSR_CRASH_P0);
let mut msr_crash_p3 = Msr::new(MSR_CRASH_P3);
let mut msr_crash_p4 = Msr::new(MSR_CRASH_P4);
let mut msr_crash_ctl = Msr::new(MSR_CRASH_CTL);

let mut crash_ctl_bits: u64 = 0;
let mut crash_ctl_bits: u64 = 0;

crash_ctl_bits |= CRASH_NOTIFY_BIT;
unsafe {
// Error Code
msr_crash_p0.write(errorcode);
if crash_message.len() > 0 && crash_message.len() < PAGE_SIZE {
let data_buffer = match alloc_shared_pages(1) {
Some(addr) => addr,
None => {
// CrashNotify
msr_crash_ctl.write(crash_ctl_bits);
return;
}
};
let data_buffer =
core::slice::from_raw_parts_mut(data_buffer as *mut u8, PAGE_SIZE);
let data_buffer_as_u64 = data_buffer.as_ptr() as u64;
crash_ctl_bits |= CRASH_NOTIFY_BIT;
unsafe {
// Error Code
msr_crash_p0.write(errorcode);
if crash_message.len() > 0 && crash_message.len() < PAGE_SIZE {
let data_buffer = match alloc_shared_pages(1) {
Some(addr) => addr,
None => {
// CrashNotify
msr_crash_ctl.write(crash_ctl_bits);
return;
}
};
let data_buffer =
core::slice::from_raw_parts_mut(data_buffer as *mut u8, PAGE_SIZE);
let data_buffer_as_u64 = data_buffer.as_ptr() as u64;

data_buffer[0..crash_message.len()]
.copy_from_slice(&crash_message[0..crash_message.len()]);
data_buffer[0..crash_message.len()]
.copy_from_slice(&crash_message[0..crash_message.len()]);

// GPA of the message
msr_crash_p3.write(data_buffer_as_u64);
// Message size
msr_crash_p4.write(crash_message.len() as u64);
crash_ctl_bits |= CRASH_MESSAGE_BIT;
// GPA of the message
msr_crash_p3.write(data_buffer_as_u64);
// Message size
msr_crash_p4.write(crash_message.len() as u64);
crash_ctl_bits |= CRASH_MESSAGE_BIT;
}
msr_crash_ctl.write(crash_ctl_bits);
}
msr_crash_ctl.write(crash_ctl_bits);
}
#[cfg(test)]
{
*msr_crash_p0 = errorcode;
}
}
}

#[cfg(test)]
mod test {
use super::*;

#[test]
fn test_crash_msr_support_enabling() {
GUEST_CRASH_MSR_SUPPORTED.store(false, Ordering::SeqCst);
assert_eq!(guest_crash_reg_supported(), false);

// Test enabling it
GUEST_CRASH_MSR_SUPPORTED.store(true, Ordering::SeqCst);
assert_eq!(guest_crash_reg_supported(), true);
}

#[test]
fn test_crash_msr_support_update_without_enabling() {
GUEST_CRASH_MSR_SUPPORTED.store(false, Ordering::SeqCst);
let mut msr_crash_p0: u64 = 0;
let test_message = Vec::new();
update_guest_crash_reg_report(0x123, test_message, &mut msr_crash_p0);
assert_eq!(msr_crash_p0, 0);
}

#[test]
fn test_crash_msr_support_update_with_enabling() {
GUEST_CRASH_MSR_SUPPORTED.store(false, Ordering::SeqCst);
let mut msr_crash_p0: u64 = 0;
let test_message = Vec::new();

GUEST_CRASH_MSR_SUPPORTED.store(true, Ordering::SeqCst);
update_guest_crash_reg_report(0x123, test_message, &mut msr_crash_p0);
assert_eq!(msr_crash_p0, 0x123);
}
}
3 changes: 3 additions & 0 deletions src/migtd/src/driver/vmcall_raw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
// SPDX-License-Identifier: BSD-2-Clause-Patent

use crate::alloc::string::ToString;
#[cfg(not(test))]
#[cfg(feature = "vmcall-raw")]
use crate::driver::crash::update_guest_crash_reg_report;
#[cfg(not(test))]
#[cfg(feature = "vmcall-raw")]
use alloc::format;

Expand All @@ -27,6 +29,7 @@ pub fn panic_with_guest_crash_reg_report(errorcode: u64, msg: &[u8]) {
" non-UTF8 message".to_string()
};

#[cfg(not(test))]
#[cfg(feature = "vmcall-raw")]
{
let crash_message = format!(
Expand Down
Loading