Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
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
29 changes: 22 additions & 7 deletions src/hyperlight_host/src/hypervisor/gdb/mshv_debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,17 @@ extern crate mshv_bindings3 as mshv_bindings;
#[cfg(mshv3)]
extern crate mshv_ioctls3 as mshv_ioctls;

use std::collections::HashMap;

use mshv_bindings::{
DebugRegisters, StandardRegisters, HV_TRANSLATE_GVA_VALIDATE_READ,
HV_TRANSLATE_GVA_VALIDATE_WRITE,
};
use mshv_ioctls::VcpuFd;

use super::{
GuestDebug, VcpuStopReason, X86_64Regs, DR6_BS_FLAG_MASK, DR6_HW_BP_FLAGS_MASK, MAX_NO_OF_HW_BP,
GuestDebug, VcpuStopReason, X86_64Regs, DR6_BS_FLAG_MASK, DR6_HW_BP_FLAGS_MASK,
MAX_NO_OF_HW_BP, SW_BP_SIZE,
};
use crate::{new_error, HyperlightError, Result};

Expand All @@ -42,6 +45,9 @@ pub(crate) struct MshvDebug {

/// Array of addresses for HW breakpoints
hw_breakpoints: Vec<u64>,
/// Saves the bytes modified to enable SW breakpoints
sw_breakpoints: HashMap<u64, [u8; SW_BP_SIZE]>,

/// Debug registers
dbg_cfg: DebugRegisters,
}
Expand All @@ -51,6 +57,7 @@ impl MshvDebug {
Self {
single_step: false,
hw_breakpoints: vec![],
sw_breakpoints: HashMap::new(),
dbg_cfg: DebugRegisters::default(),
}
}
Expand Down Expand Up @@ -163,6 +170,14 @@ impl MshvDebug {
return Ok(VcpuStopReason::HwBp);
}

// mshv does not provide a way to specify which exception triggered the
// vCPU exit as the mshv intercepts both #DB and #BP
// We check against the SW breakpoints Hashmap to detect whether the
// vCPU exited due to a SW breakpoint
if self.sw_breakpoints.contains_key(&gpa) {
return Ok(VcpuStopReason::SwBp);
}

Ok(VcpuStopReason::Unknown)
}
}
Expand All @@ -173,8 +188,8 @@ impl GuestDebug for MshvDebug {
fn is_hw_breakpoint(&self, addr: &u64) -> bool {
self.hw_breakpoints.contains(addr)
}
fn is_sw_breakpoint(&self, _addr: &u64) -> bool {
unimplemented!()
fn is_sw_breakpoint(&self, addr: &u64) -> bool {
self.sw_breakpoints.contains_key(addr)
}
fn save_hw_breakpoint(&mut self, addr: &u64) -> bool {
if self.hw_breakpoints.len() >= MAX_NO_OF_HW_BP {
Expand All @@ -185,14 +200,14 @@ impl GuestDebug for MshvDebug {
true
}
}
fn save_sw_breakpoint_data(&mut self, _addr: u64, _data: [u8; 1]) {
unimplemented!()
fn save_sw_breakpoint_data(&mut self, addr: u64, data: [u8; 1]) {
_ = self.sw_breakpoints.insert(addr, data);
}
fn delete_hw_breakpoint(&mut self, addr: &u64) {
self.hw_breakpoints.retain(|&a| a != *addr);
}
fn delete_sw_breakpoint_data(&mut self, _addr: &u64) -> Option<[u8; 1]> {
unimplemented!()
fn delete_sw_breakpoint_data(&mut self, addr: &u64) -> Option<[u8; 1]> {
self.sw_breakpoints.remove(addr)
}

fn read_regs(&self, vcpu_fd: &Self::Vcpu, regs: &mut X86_64Regs) -> Result<()> {
Expand Down
23 changes: 22 additions & 1 deletion src/hyperlight_host/src/hypervisor/hyperv_linux.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,11 @@ mod debug {
DebugMsg::AddHwBreakpoint(addr) => Ok(DebugResponse::AddHwBreakpoint(
debug.add_hw_breakpoint(&self.vcpu_fd, addr).is_ok(),
)),
DebugMsg::AddSwBreakpoint(addr) => Ok(DebugResponse::AddSwBreakpoint(
debug
.add_sw_breakpoint(&self.vcpu_fd, addr, dbg_mem_access_fn)
.is_ok(),
)),
DebugMsg::Continue => {
debug.set_single_step(&self.vcpu_fd, false)?;
Ok(DebugResponse::Continue)
Expand All @@ -127,6 +132,13 @@ mod debug {

Ok(DebugResponse::GetCodeSectionOffset(offset as u64))
}
DebugMsg::ReadAddr(addr, len) => {
let mut data = vec![0u8; len];

debug.read_addrs(&self.vcpu_fd, addr, &mut data, dbg_mem_access_fn)?;

Ok(DebugResponse::ReadAddr(data))
}
DebugMsg::ReadRegisters => {
let mut regs = X86_64Regs::default();

Expand All @@ -137,14 +149,23 @@ mod debug {
DebugMsg::RemoveHwBreakpoint(addr) => Ok(DebugResponse::RemoveHwBreakpoint(
debug.remove_hw_breakpoint(&self.vcpu_fd, addr).is_ok(),
)),
DebugMsg::RemoveSwBreakpoint(addr) => Ok(DebugResponse::RemoveSwBreakpoint(
debug
.remove_sw_breakpoint(&self.vcpu_fd, addr, dbg_mem_access_fn)
.is_ok(),
)),
DebugMsg::Step => {
debug.set_single_step(&self.vcpu_fd, true)?;
Ok(DebugResponse::Step)
}
DebugMsg::WriteAddr(addr, data) => {
debug.write_addrs(&self.vcpu_fd, addr, &data, dbg_mem_access_fn)?;

Ok(DebugResponse::WriteAddr)
}
DebugMsg::WriteRegisters(regs) => debug
.write_regs(&self.vcpu_fd, &regs)
.map(|_| DebugResponse::WriteRegisters),
_ => Err(new_error!("Not yet implemented")),
}
} else {
Err(new_error!("Debugging is not enabled"))
Expand Down