-
Notifications
You must be signed in to change notification settings - Fork 152
Introduce new Vm trait #924
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -16,16 +16,16 @@ limitations under the License. | |
|
|
||
| //! This file contains architecture specific code for the x86_64 | ||
|
|
||
| use std::collections::HashMap; | ||
|
|
||
| use super::VcpuStopReason; | ||
| use super::{DebuggableVm, VcpuStopReason}; | ||
| use crate::Result; | ||
| use crate::hypervisor::regs::CommonRegisters; | ||
|
|
||
| // Described in Table 6-1. Exceptions and Interrupts at Page 6-13 Vol. 1 | ||
| // of Intel 64 and IA-32 Architectures Software Developer's Manual | ||
| /// Exception id for #DB | ||
| const DB_EX_ID: u32 = 1; | ||
| pub(crate) const DB_EX_ID: u32 = 1; | ||
| /// Exception id for #BP - triggered by the INT3 instruction | ||
| const BP_EX_ID: u32 = 3; | ||
| pub(crate) const BP_EX_ID: u32 = 3; | ||
|
|
||
| /// Software Breakpoint size in memory | ||
| pub(crate) const SW_BP_SIZE: usize = 1; | ||
|
|
@@ -51,61 +51,52 @@ pub(crate) const DR6_HW_BP_FLAGS_MASK: u64 = 0x0F << DR6_HW_BP_FLAGS_POS; | |
|
|
||
| /// Determine the reason the vCPU stopped | ||
| /// This is done by checking the DR6 register and the exception id | ||
| /// NOTE: Additional checks are done for the entrypoint, stored hw_breakpoints | ||
| /// and sw_breakpoints to ensure the stop reason is valid with internal state | ||
| pub(crate) fn vcpu_stop_reason( | ||
| single_step: bool, | ||
| rip: u64, | ||
| dr6: u64, | ||
| vm: &mut dyn DebuggableVm, | ||
| entrypoint: u64, | ||
| dr6: u64, | ||
| exception: u32, | ||
| hw_breakpoints: &[u64], | ||
| sw_breakpoints: &HashMap<u64, [u8; SW_BP_SIZE]>, | ||
| ) -> VcpuStopReason { | ||
| ) -> Result<VcpuStopReason> { | ||
| let CommonRegisters { rip, .. } = vm.regs()?; | ||
| if DB_EX_ID == exception { | ||
| // If the BS flag in DR6 register is set, it means a single step | ||
| // instruction triggered the exit | ||
| // Check page 19-4 Vol. 3B of Intel 64 and IA-32 | ||
| // Architectures Software Developer's Manual | ||
| if dr6 & DR6_BS_FLAG_MASK != 0 && single_step { | ||
| return VcpuStopReason::DoneStep; | ||
| if dr6 & DR6_BS_FLAG_MASK != 0 { | ||
| return Ok(VcpuStopReason::DoneStep); | ||
| } | ||
|
|
||
| // If any of the B0-B3 flags in DR6 register is set, it means a | ||
| // hardware breakpoint triggered the exit | ||
| // Check page 19-4 Vol. 3B of Intel 64 and IA-32 | ||
| // Architectures Software Developer's Manual | ||
| if DR6_HW_BP_FLAGS_MASK & dr6 != 0 && hw_breakpoints.contains(&rip) { | ||
| if DR6_HW_BP_FLAGS_MASK & dr6 != 0 { | ||
| if rip == entrypoint { | ||
| return VcpuStopReason::EntryPointBp; | ||
| vm.remove_hw_breakpoint(entrypoint)?; | ||
| return Ok(VcpuStopReason::EntryPointBp); | ||
| } | ||
| return VcpuStopReason::HwBp; | ||
| return Ok(VcpuStopReason::HwBp); | ||
| } | ||
| } | ||
|
|
||
| if BP_EX_ID == exception && sw_breakpoints.contains_key(&rip) { | ||
| return VcpuStopReason::SwBp; | ||
| if BP_EX_ID == exception { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this might remove an option here. If the vCPU stops because of an issue, not a SW/HW breakpoint set by the debugger, it will not be transmitted as an I am not sure though if this means that the debugger won't show it as an |
||
| return Ok(VcpuStopReason::SwBp); | ||
| } | ||
|
|
||
| // Log an error and provide internal debugging info | ||
| log::error!( | ||
| r"The vCPU exited because of an unknown reason: | ||
| single_step: {:?} | ||
| rip: {:?} | ||
| dr6: {:?} | ||
| entrypoint: {:?} | ||
| exception: {:?} | ||
| hw_breakpoints: {:?} | ||
| sw_breakpoints: {:?} | ||
| ", | ||
| single_step, | ||
| rip, | ||
| dr6, | ||
| entrypoint, | ||
| exception, | ||
| hw_breakpoints, | ||
| sw_breakpoints, | ||
| ); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's unclear why these have been removed from the error log There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. They are not necessary to determine stop reason so I removed them in order not having to keep unnecessary state around and simplify the code |
||
|
|
||
| VcpuStopReason::Unknown | ||
| Ok(VcpuStopReason::Unknown) | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it is fine to remove the
single_stepvariable here. It was only an additional state for verifying the correct flag was in sync with internal state of debugging