vmm: Enable gdbstub on AArch64

The `gva_translate` function is still missing, it will be added with a
separate commit.

Signed-off-by: Michael Zhao <michael.zhao@arm.com>
This commit is contained in:
Michael Zhao 2022-07-18 15:55:11 +08:00 committed by Xin Wang
parent baa58ad8bf
commit 5febdec81a
3 changed files with 60 additions and 16 deletions

View File

@ -32,8 +32,12 @@ use anyhow::anyhow;
use arch::EntryPoint;
use arch::NumaNodes;
use devices::interrupt_controller::InterruptController;
#[cfg(all(target_arch = "aarch64", feature = "gdb"))]
use gdbstub_arch::aarch64::reg::AArch64CoreRegs as CoreRegs;
#[cfg(all(target_arch = "x86_64", feature = "gdb"))]
use gdbstub_arch::x86::reg::{X86SegmentRegs, X86_64CoreRegs};
use gdbstub_arch::x86::reg::{X86SegmentRegs, X86_64CoreRegs as CoreRegs};
#[cfg(all(target_arch = "aarch64", feature = "gdb"))]
use hypervisor::aarch64::StandardRegisters;
#[cfg(feature = "guest_debug")]
use hypervisor::arch::x86::msr_index;
#[cfg(target_arch = "x86_64")]
@ -133,7 +137,7 @@ pub enum Error {
#[error("Error initializing PMU: {0}")]
InitPmu(#[source] hypervisor::HypervisorCpuError),
#[cfg(all(target_arch = "x86_64", feature = "gdb"))]
#[cfg(feature = "gdb")]
#[error("Error during CPU debug: {0}")]
CpuDebug(#[source] hypervisor::HypervisorCpuError),
@ -950,7 +954,7 @@ impl CpuManager {
// vcpu.run() returns false on a triple-fault so trigger a reset
match vcpu.run() {
Ok(run) => match run {
#[cfg(all(target_arch = "x86_64", feature = "kvm"))]
#[cfg(feature = "kvm")]
VmExit::Debug => {
info!("VmExit::Debug");
#[cfg(feature = "gdb")]
@ -1436,7 +1440,7 @@ impl CpuManager {
pptt
}
#[cfg(all(target_arch = "x86_64", feature = "gdb"))]
#[cfg(feature = "gdb")]
fn get_regs(&self, cpu_id: u8) -> Result<StandardRegisters> {
self.vcpus[usize::from(cpu_id)]
.lock()
@ -1446,7 +1450,7 @@ impl CpuManager {
.map_err(Error::CpuDebug)
}
#[cfg(all(target_arch = "x86_64", feature = "gdb"))]
#[cfg(feature = "gdb")]
fn set_regs(&self, cpu_id: u8, regs: &StandardRegisters) -> Result<()> {
self.vcpus[usize::from(cpu_id)]
.lock()
@ -1486,6 +1490,11 @@ impl CpuManager {
.map_err(Error::TranslateVirtualAddress)?;
Ok(gpa)
}
#[cfg(all(target_arch = "aarch64", feature = "gdb"))]
fn translate_gva(&self, cpu_id: u8, gva: u64) -> Result<u64> {
unimplemented!()
}
}
struct Cpu {
@ -1931,7 +1940,7 @@ impl Debuggable for CpuManager {
}
#[cfg(target_arch = "x86_64")]
fn read_regs(&self, cpu_id: usize) -> std::result::Result<X86_64CoreRegs, DebuggableError> {
fn read_regs(&self, cpu_id: usize) -> std::result::Result<CoreRegs, DebuggableError> {
// General registers: RAX, RBX, RCX, RDX, RSI, RDI, RBP, RSP, r8-r15
let gregs = self
.get_regs(cpu_id as u8)
@ -1961,7 +1970,7 @@ impl Debuggable for CpuManager {
// TODO: Add other registers
Ok(X86_64CoreRegs {
Ok(CoreRegs {
regs,
eflags,
rip,
@ -1970,11 +1979,24 @@ impl Debuggable for CpuManager {
})
}
#[cfg(target_arch = "aarch64")]
fn read_regs(&self, cpu_id: usize) -> std::result::Result<CoreRegs, DebuggableError> {
let gregs = self
.get_regs(cpu_id as u8)
.map_err(DebuggableError::ReadRegs)?;
Ok(CoreRegs {
x: gregs.regs.regs,
sp: gregs.regs.sp,
pc: gregs.regs.pc,
..Default::default()
})
}
#[cfg(target_arch = "x86_64")]
fn write_regs(
&self,
cpu_id: usize,
regs: &X86_64CoreRegs,
regs: &CoreRegs,
) -> std::result::Result<(), DebuggableError> {
let orig_gregs = self
.get_regs(cpu_id as u8)
@ -2024,7 +2046,26 @@ impl Debuggable for CpuManager {
Ok(())
}
#[cfg(target_arch = "x86_64")]
#[cfg(target_arch = "aarch64")]
fn write_regs(
&self,
cpu_id: usize,
regs: &CoreRegs,
) -> std::result::Result<(), DebuggableError> {
let mut gregs = self
.get_regs(cpu_id as u8)
.map_err(DebuggableError::ReadRegs)?;
gregs.regs.regs = regs.x;
gregs.regs.sp = regs.sp;
gregs.regs.pc = regs.pc;
self.set_regs(cpu_id as u8, &gregs)
.map_err(DebuggableError::WriteRegs)?;
Ok(())
}
fn read_mem(
&self,
cpu_id: usize,
@ -2055,7 +2096,6 @@ impl Debuggable for CpuManager {
Ok(buf)
}
#[cfg(target_arch = "x86_64")]
fn write_mem(
&self,
cpu_id: usize,

View File

@ -24,6 +24,10 @@ use gdbstub::{
Target, TargetError, TargetResult,
},
};
#[cfg(target_arch = "aarch64")]
use gdbstub_arch::aarch64::reg::AArch64CoreRegs as CoreRegs;
#[cfg(target_arch = "aarch64")]
use gdbstub_arch::aarch64::AArch64 as GdbArch;
#[cfg(target_arch = "x86_64")]
use gdbstub_arch::x86::reg::X86_64CoreRegs as CoreRegs;
#[cfg(target_arch = "x86_64")]
@ -31,7 +35,6 @@ use gdbstub_arch::x86::X86_64_SSE as GdbArch;
use std::{os::unix::net::UnixListener, sync::mpsc};
use vm_memory::{GuestAddress, GuestMemoryError};
#[cfg(target_arch = "x86_64")]
type ArchUsize = u64;
#[derive(Debug)]
@ -121,7 +124,6 @@ pub struct GdbStub {
gdb_sender: mpsc::Sender<GdbRequest>,
gdb_event: vmm_sys_util::eventfd::EventFd,
vm_event: vmm_sys_util::eventfd::EventFd,
hw_breakpoints: Vec<GuestAddress>,
single_step: bool,
}

View File

@ -51,8 +51,10 @@ use devices::gic::GIC_V3_ITS_SNAPSHOT_ID;
#[cfg(target_arch = "aarch64")]
use devices::interrupt_controller::{self, InterruptController};
use devices::AcpiNotificationFlags;
#[cfg(all(target_arch = "aarch64", feature = "gdb"))]
use gdbstub_arch::aarch64::reg::AArch64CoreRegs as CoreRegs;
#[cfg(all(target_arch = "x86_64", feature = "gdb"))]
use gdbstub_arch::x86::reg::X86_64CoreRegs;
use gdbstub_arch::x86::reg::X86_64CoreRegs as CoreRegs;
use hypervisor::{HypervisorVmError, VmOps};
use linux_loader::cmdline::Cmdline;
#[cfg(feature = "guest_debug")]
@ -2522,7 +2524,7 @@ impl Vm {
self.memory_manager.lock().unwrap().snapshot_data()
}
#[cfg(all(target_arch = "x86_64", feature = "gdb"))]
#[cfg(feature = "gdb")]
pub fn debug_request(
&mut self,
gdb_request: &GdbRequestPayload,
@ -2973,14 +2975,14 @@ impl Debuggable for Vm {
Ok(())
}
fn read_regs(&self, cpu_id: usize) -> std::result::Result<X86_64CoreRegs, DebuggableError> {
fn read_regs(&self, cpu_id: usize) -> std::result::Result<CoreRegs, DebuggableError> {
self.cpu_manager.lock().unwrap().read_regs(cpu_id)
}
fn write_regs(
&self,
cpu_id: usize,
regs: &X86_64CoreRegs,
regs: &CoreRegs,
) -> std::result::Result<(), DebuggableError> {
self.cpu_manager.lock().unwrap().write_regs(cpu_id, regs)
}