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

View File

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

View File

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