Skip to content

Commit

Permalink
KVM: arm64: introduce vcpu->arch.debug_ptr
Browse files Browse the repository at this point in the history
This introduces a level of indirection for the debug registers. Instead
of using the sys_regs[] directly we store registers in a structure in
the vcpu. The new kvm_arm_reset_debug_ptr() sets the debug ptr to the
guest context.

Because we no longer give the sys_regs offset for the sys_reg_desc->reg
field, but instead the index into a debug-specific struct we need to
add a number of additional trap functions for each register. Also as the
generic generic user-space access code no longer works we have
introduced a new pair of function pointers to the sys_reg_desc structure
to override the generic code when needed.

Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org>
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
  • Loading branch information
Alex Bennée authored and Marc Zyngier committed Jul 21, 2015
1 parent e0a1b9a commit 84e690b
Show file tree
Hide file tree
Showing 9 changed files with 316 additions and 47 deletions.
1 change: 1 addition & 0 deletions arch/arm/include/asm/kvm_host.h
Original file line number Diff line number Diff line change
Expand Up @@ -234,5 +234,6 @@ static inline void kvm_arch_sched_in(struct kvm_vcpu *vcpu, int cpu) {}
static inline void kvm_arm_init_debug(void) {}
static inline void kvm_arm_setup_debug(struct kvm_vcpu *vcpu) {}
static inline void kvm_arm_clear_debug(struct kvm_vcpu *vcpu) {}
static inline void kvm_arm_reset_debug_ptr(struct kvm_vcpu *vcpu) {}

#endif /* __ARM_KVM_HOST_H__ */
2 changes: 2 additions & 0 deletions arch/arm/kvm/arm.c
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,8 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
/* Set up the timer */
kvm_timer_vcpu_init(vcpu);

kvm_arm_reset_debug_ptr(vcpu);

return 0;
}

Expand Down
24 changes: 8 additions & 16 deletions arch/arm64/include/asm/kvm_asm.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,24 +46,16 @@
#define CNTKCTL_EL1 20 /* Timer Control Register (EL1) */
#define PAR_EL1 21 /* Physical Address Register */
#define MDSCR_EL1 22 /* Monitor Debug System Control Register */
#define DBGBCR0_EL1 23 /* Debug Breakpoint Control Registers (0-15) */
#define DBGBCR15_EL1 38
#define DBGBVR0_EL1 39 /* Debug Breakpoint Value Registers (0-15) */
#define DBGBVR15_EL1 54
#define DBGWCR0_EL1 55 /* Debug Watchpoint Control Registers (0-15) */
#define DBGWCR15_EL1 70
#define DBGWVR0_EL1 71 /* Debug Watchpoint Value Registers (0-15) */
#define DBGWVR15_EL1 86
#define MDCCINT_EL1 87 /* Monitor Debug Comms Channel Interrupt Enable Reg */
#define MDCCINT_EL1 23 /* Monitor Debug Comms Channel Interrupt Enable Reg */

/* 32bit specific registers. Keep them at the end of the range */
#define DACR32_EL2 88 /* Domain Access Control Register */
#define IFSR32_EL2 89 /* Instruction Fault Status Register */
#define FPEXC32_EL2 90 /* Floating-Point Exception Control Register */
#define DBGVCR32_EL2 91 /* Debug Vector Catch Register */
#define TEECR32_EL1 92 /* ThumbEE Configuration Register */
#define TEEHBR32_EL1 93 /* ThumbEE Handler Base Register */
#define NR_SYS_REGS 94
#define DACR32_EL2 24 /* Domain Access Control Register */
#define IFSR32_EL2 25 /* Instruction Fault Status Register */
#define FPEXC32_EL2 26 /* Floating-Point Exception Control Register */
#define DBGVCR32_EL2 27 /* Debug Vector Catch Register */
#define TEECR32_EL1 28 /* ThumbEE Configuration Register */
#define TEEHBR32_EL1 29 /* ThumbEE Handler Base Register */
#define NR_SYS_REGS 30

/* 32bit mapping */
#define c0_MPIDR (MPIDR_EL1 * 2) /* MultiProcessor ID Register */
Expand Down
17 changes: 16 additions & 1 deletion arch/arm64/include/asm/kvm_host.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,11 +108,25 @@ struct kvm_vcpu_arch {
/* Exception Information */
struct kvm_vcpu_fault_info fault;

/* Debug state */
/* Guest debug state */
u64 debug_flags;

/*
* We maintain more than a single set of debug registers to support
* debugging the guest from the host and to maintain separate host and
* guest state during world switches. vcpu_debug_state are the debug
* registers of the vcpu as the guest sees them. host_debug_state are
* the host registers which are saved and restored during world switches.
*
* debug_ptr points to the set of debug registers that should be loaded
* onto the hardware when running the guest.
*/
struct kvm_guest_debug_arch *debug_ptr;
struct kvm_guest_debug_arch vcpu_debug_state;

/* Pointer to host CPU context */
kvm_cpu_context_t *host_cpu_context;
struct kvm_guest_debug_arch host_debug_state;

/* VGIC state */
struct vgic_cpu vgic_cpu;
Expand Down Expand Up @@ -242,5 +256,6 @@ static inline void kvm_arch_sched_in(struct kvm_vcpu *vcpu, int cpu) {}
void kvm_arm_init_debug(void);
void kvm_arm_setup_debug(struct kvm_vcpu *vcpu);
void kvm_arm_clear_debug(struct kvm_vcpu *vcpu);
void kvm_arm_reset_debug_ptr(struct kvm_vcpu *vcpu);

#endif /* __ARM64_KVM_HOST_H__ */
6 changes: 6 additions & 0 deletions arch/arm64/kernel/asm-offsets.c
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,16 @@ int main(void)
DEFINE(VCPU_FAR_EL2, offsetof(struct kvm_vcpu, arch.fault.far_el2));
DEFINE(VCPU_HPFAR_EL2, offsetof(struct kvm_vcpu, arch.fault.hpfar_el2));
DEFINE(VCPU_DEBUG_FLAGS, offsetof(struct kvm_vcpu, arch.debug_flags));
DEFINE(VCPU_DEBUG_PTR, offsetof(struct kvm_vcpu, arch.debug_ptr));
DEFINE(DEBUG_BCR, offsetof(struct kvm_guest_debug_arch, dbg_bcr));
DEFINE(DEBUG_BVR, offsetof(struct kvm_guest_debug_arch, dbg_bvr));
DEFINE(DEBUG_WCR, offsetof(struct kvm_guest_debug_arch, dbg_wcr));
DEFINE(DEBUG_WVR, offsetof(struct kvm_guest_debug_arch, dbg_wvr));
DEFINE(VCPU_HCR_EL2, offsetof(struct kvm_vcpu, arch.hcr_el2));
DEFINE(VCPU_MDCR_EL2, offsetof(struct kvm_vcpu, arch.mdcr_el2));
DEFINE(VCPU_IRQ_LINES, offsetof(struct kvm_vcpu, arch.irq_lines));
DEFINE(VCPU_HOST_CONTEXT, offsetof(struct kvm_vcpu, arch.host_cpu_context));
DEFINE(VCPU_HOST_DEBUG_STATE, offsetof(struct kvm_vcpu, arch.host_debug_state));
DEFINE(VCPU_TIMER_CNTV_CTL, offsetof(struct kvm_vcpu, arch.timer_cpu.cntv_ctl));
DEFINE(VCPU_TIMER_CNTV_CVAL, offsetof(struct kvm_vcpu, arch.timer_cpu.cntv_cval));
DEFINE(KVM_TIMER_CNTVOFF, offsetof(struct kvm, arch.timer.cntvoff));
Expand Down
9 changes: 9 additions & 0 deletions arch/arm64/kvm/debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,15 @@ void kvm_arm_init_debug(void)
__this_cpu_write(mdcr_el2, kvm_call_hyp(__kvm_get_mdcr_el2));
}

/**
* kvm_arm_reset_debug_ptr - reset the debug ptr to point to the vcpu state
*/

void kvm_arm_reset_debug_ptr(struct kvm_vcpu *vcpu)
{
vcpu->arch.debug_ptr = &vcpu->arch.vcpu_debug_state;
}

/**
* kvm_arm_setup_debug - set up debug related stuff
*
Expand Down
24 changes: 16 additions & 8 deletions arch/arm64/kvm/hyp.S
Original file line number Diff line number Diff line change
Expand Up @@ -596,6 +596,7 @@ __restore_sysregs:
/* Save debug state */
__save_debug:
// x2: ptr to CPU context
// x3: ptr to debug reg struct
// x4/x5/x6-22/x24-26: trashed

mrs x26, id_aa64dfr0_el1
Expand All @@ -606,15 +607,15 @@ __save_debug:
sub w25, w26, w25 // How many WPs to skip

mov x5, x24
add x4, x2, #CPU_SYSREG_OFFSET(DBGBCR0_EL1)
add x4, x3, #DEBUG_BCR
save_debug dbgbcr
add x4, x2, #CPU_SYSREG_OFFSET(DBGBVR0_EL1)
add x4, x3, #DEBUG_BVR
save_debug dbgbvr

mov x5, x25
add x4, x2, #CPU_SYSREG_OFFSET(DBGWCR0_EL1)
add x4, x3, #DEBUG_WCR
save_debug dbgwcr
add x4, x2, #CPU_SYSREG_OFFSET(DBGWVR0_EL1)
add x4, x3, #DEBUG_WVR
save_debug dbgwvr

mrs x21, mdccint_el1
Expand All @@ -624,6 +625,7 @@ __save_debug:
/* Restore debug state */
__restore_debug:
// x2: ptr to CPU context
// x3: ptr to debug reg struct
// x4/x5/x6-22/x24-26: trashed

mrs x26, id_aa64dfr0_el1
Expand All @@ -634,15 +636,15 @@ __restore_debug:
sub w25, w26, w25 // How many WPs to skip

mov x5, x24
add x4, x2, #CPU_SYSREG_OFFSET(DBGBCR0_EL1)
add x4, x3, #DEBUG_BCR
restore_debug dbgbcr
add x4, x2, #CPU_SYSREG_OFFSET(DBGBVR0_EL1)
add x4, x3, #DEBUG_BVR
restore_debug dbgbvr

mov x5, x25
add x4, x2, #CPU_SYSREG_OFFSET(DBGWCR0_EL1)
add x4, x3, #DEBUG_WCR
restore_debug dbgwcr
add x4, x2, #CPU_SYSREG_OFFSET(DBGWVR0_EL1)
add x4, x3, #DEBUG_WVR
restore_debug dbgwvr

ldr x21, [x2, #CPU_SYSREG_OFFSET(MDCCINT_EL1)]
Expand Down Expand Up @@ -682,6 +684,7 @@ ENTRY(__kvm_vcpu_run)
bl __save_sysregs

compute_debug_state 1f
add x3, x0, #VCPU_HOST_DEBUG_STATE
bl __save_debug
1:
activate_traps
Expand All @@ -697,6 +700,8 @@ ENTRY(__kvm_vcpu_run)
bl __restore_fpsimd

skip_debug_state x3, 1f
ldr x3, [x0, #VCPU_DEBUG_PTR]
kern_hyp_va x3
bl __restore_debug
1:
restore_guest_32bit_state
Expand All @@ -717,6 +722,8 @@ __kvm_vcpu_return:
bl __save_sysregs

skip_debug_state x3, 1f
ldr x3, [x0, #VCPU_DEBUG_PTR]
kern_hyp_va x3
bl __save_debug
1:
save_guest_32bit_state
Expand All @@ -739,6 +746,7 @@ __kvm_vcpu_return:
// already been saved. Note that we nuke the whole 64bit word.
// If we ever add more flags, we'll have to be more careful...
str xzr, [x0, #VCPU_DEBUG_FLAGS]
add x3, x0, #VCPU_HOST_DEBUG_STATE
bl __restore_debug
1:
restore_host_regs
Expand Down
Loading

0 comments on commit 84e690b

Please sign in to comment.