Re: [PATCH v2 2/3] hvf: implement guest debugging on Apple Silicon hosts

2022-12-20 Thread Alex Bennée


Francesco Cagnin  writes:

> Hi,
> indeed, the patch doesn't keep separate copies of debug registers and
> just directly sets cp15.* values, as I was not aware of the issue—thanks
> for the detailed explanation.
>
> I remain available to implement the required fixes, but I'd need
> some guidance on how to proceed. Thanks,

In the KVM world we put of the final setting of the registers until
right before the context switch. I guess the equivalent in HVF would be
to modify hvf_put_registers() and make the decision about if to use the
QEMU supplied debug registers or the env values there.

Something like:

for (i = 0; i < ARRAY_SIZE(hvf_sreg_match); i++) {
if (hvf_sreg_match[i].cp_idx == -1) {
continue;
}
if (hvf_sref_match[i].can_override && should_override) {
val = get_from_debug(...)
} else {
val = arm_cpu->cpreg_values[hvf_sreg_match[i].cp_idx];
}
ret = hv_vcpu_set_sys_reg(cpu->hvf->fd, hvf_sreg_match[i].reg, val);
assert_hvf_ok(ret);
}

You will of course have to ensure the get_registers doesn't
inadvertently splat the env values with what we have just written here.

I'm not super familiar with the HVF architecture but maybe its possible
to do directly call hv_vcpu_set_sys_reg steps in your current
update_guest_debug function instead of copying to env and then and just
skip setting/getting them again in the final put registers just before
you exec.

-- 
Alex Bennée
Virtualisation Tech Lead @ Linaro



Re: [PATCH v2 2/3] hvf: implement guest debugging on Apple Silicon hosts

2022-12-19 Thread Francesco Cagnin
Hi,
indeed, the patch doesn't keep separate copies of debug registers and
just directly sets cp15.* values, as I was not aware of the issue—thanks
for the detailed explanation.

I remain available to implement the required fixes, but I'd need
some guidance on how to proceed. Thanks,
-- 
Francesco



Re: [PATCH v2 2/3] hvf: implement guest debugging on Apple Silicon hosts

2022-12-12 Thread Peter Maydell
On Wed, 16 Nov 2022 at 17:48,  wrote:
>
> From: Francesco Cagnin 
>
> Support is added for single-stepping, software breakpoints, hardware
> breakpoints and watchpoints. The code has been structured like the KVM
> counterpart (and many parts are basically identical).
>
> Guests can be debugged through the gdbstub.
>
> Signed-off-by: Francesco Cagnin 

Hi; sorry it's taken me a while to get to this patchset.

> +void hvf_arch_update_guest_debug(CPUState *cpu)
> +{
> +ARMCPU *arm_cpu = ARM_CPU(cpu);
> +CPUARMState *env = _cpu->env;
> +hv_return_t r = HV_SUCCESS;
> +bool trap_debug_exceptions = false;
> +
> +cpu_synchronize_state(cpu);
> +
> +if (cpu->singlestep_enabled) {
> +trap_debug_exceptions = true;
> +
> +env->cp15.mdscr_el1 =
> +deposit64(env->cp15.mdscr_el1, MDSCR_EL1_SS_SHIFT, 1, 1);
> +pstate_write(env, pstate_read(env) | PSTATE_SS);
> +} else {
> +env->cp15.mdscr_el1 =
> +deposit64(env->cp15.mdscr_el1, MDSCR_EL1_SS_SHIFT, 1, 0);
> +}
> +
> +if (hvf_sw_breakpoints_active(cpu)) {
> +trap_debug_exceptions = true;
> +}
> +
> +if (hvf_arm_hw_debug_active(cpu)) {
> +trap_debug_exceptions = true;
> +
> +env->cp15.mdscr_el1 =
> +deposit64(env->cp15.mdscr_el1, MDSCR_EL1_MDE_SHIFT, 1, 1);
> +
> +int i;
> +for (i = 0; i < cur_hw_bps; i++) {
> +HWBreakpoint *bp = get_hw_bp(i);
> +env->cp15.dbgbcr[i] = bp->bcr;
> +env->cp15.dbgbvr[i] = bp->bvr;
> +}
> +for (i = 0; i < cur_hw_wps; i++) {
> +HWWatchpoint *bp = get_hw_wp(i);
> +env->cp15.dbgwcr[i] = bp->wcr;
> +env->cp15.dbgwvr[i] = bp->wvr;
> +}

Can you explain how the patches keep the guest's idea of the debug
registers distinct from the QEMU debugstub's values from them?
Looking at this patch it seems like we just directly set the
cp15.* values with what the debug stub wants them to be here;
but in patch 3 any trapped guest writes to the debug registers
also simply write to the same env fields.

With KVM, this is handled by the host kernel: QEMU tells KVM
that it wants to do guest debug, and then uses the KVM_SET_GUEST_DEBUG
ioctl to say what the bp/wp etc register values should be. The
KVM kernel then uses those values when it runs the VM, as well
as ensuring that debug exceptions go to EL2 rather than EL1,
and that EL1 accesses to the debug regs are also trapped to EL2.
Guest attempts to access the debug registers are then handled by
having reads and writes access fields which correspond to the
guest's view of the debug registers, which is separate from the
values that the QEMU debug stub is using. The effect is that while
QEMU is doing debug of the VM, the guest can still read and write
the debug registers, they just don't have any effect. The guest
can't do anything that messes with the state of the debug registers
that QEMU's debug stub is relying on. If/when QEMU says it's
done with doing guest debug, then the host kernel goes back to using
the guest's values of the debug registers. (In the kernel sources
this is done in arch/arm64/kvm/debug.c, with the trapping of debug
registers done in arch/arm64/kvm/sys_regs.c.)

I suspect that with HVF we need to do the equivalent of this ourselves
in QEMU.

thanks
-- PMM



Re: [PATCH v2 2/3] hvf: implement guest debugging on Apple Silicon hosts

2022-11-17 Thread Mads Ynddal


> On 16 Nov 2022, at 18.47, francesco.cag...@gmail.com wrote:
> 
> From: Francesco Cagnin 
> 
> Support is added for single-stepping, software breakpoints, hardware
> breakpoints and watchpoints. The code has been structured like the KVM
> counterpart (and many parts are basically identical).
> 
> Guests can be debugged through the gdbstub.
> 
> Signed-off-by: Francesco Cagnin 
> ---
> accel/hvf/hvf-accel-ops.c | 123 
> accel/hvf/hvf-all.c   |  24 +
> cpu.c |   3 +
> include/sysemu/hvf.h  |  29 ++
> include/sysemu/hvf_int.h  |   1 +
> target/arm/hvf/hvf.c  | 194 +-
> 6 files changed, 372 insertions(+), 2 deletions(-)

Looks good. I've tested hw/sw breakpoints, hw watchpoints and single-stepping.

Reviewed-by: Mads Ynddal