Skip to content

Commit b7bf7c8

Browse files
author
Marc Zyngier
committed
Merge branch kvm-arm64/debug-6.14 into kvmarm-master/next
* kvm-arm64/debug-6.14: : . : Large rework of the debug code to make it a bit less horrid, : courtesy of Oliver Upton. From the original cover letter: : : "The debug code has become a bit difficult to reason about, especially : all the hacks and bandaids for state tracking + trap configuration. : : This series reworks the entire mess around using a single enumeration to : track the state of the debug registers (free, guest-owned, host-owned), : using that to drive trap configuration and save/restore. : : On top of that, this series wires most of the implementation into vCPU : load/put rather than the main KVM_RUN loop. This has been a long time : coming for VHE, as a lot of the trap configuration and EL1 state gets : loaded into hardware at that point anyway. : : The save/restore of the debug registers is simplified quite a bit as : well. KVM will now restore the registers for *any* access rather than : just writes, and keep doing so until the next vcpu_put() instead of : dropping it on the floor after the next exception." : . KVM: arm64: Promote guest ownership for DBGxVR/DBGxCR reads KVM: arm64: Fold DBGxVR/DBGxCR accessors into common set KVM: arm64: Avoid reading ID_AA64DFR0_EL1 for debug save/restore KVM: arm64: nv: Honor MDCR_EL2.TDE routing for debug exceptions KVM: arm64: Manage software step state at load/put KVM: arm64: Don't hijack guest context MDSCR_EL1 KVM: arm64: Compute MDCR_EL2 at vcpu_load() KVM: arm64: Reload vCPU for accesses to OSLAR_EL1 KVM: arm64: Use debug_owner to track if debug regs need save/restore KVM: arm64: Remove vestiges of debug_ptr KVM: arm64: Remove debug tracepoints KVM: arm64: Select debug state to save/restore based on debug owner KVM: arm64: Clean up KVM_SET_GUEST_DEBUG handler KVM: arm64: Evaluate debug owner at vcpu_load() KVM: arm64: Write MDCR_EL2 directly from kvm_arm_setup_mdcr_el2() KVM: arm64: Move host SME/SVE tracking flags to host data KVM: arm64: Track presence of SPE/TRBE in kvm_host_data instead of vCPU KVM: arm64: Get rid of __kvm_get_mdcr_el2() and related warts KVM: arm64: Drop MDSCR_EL1_DEBUG_MASK Signed-off-by: Marc Zyngier <[email protected]>
2 parents 78d4f34 + c4a6ed8 commit b7bf7c8

File tree

16 files changed

+350
-650
lines changed

16 files changed

+350
-650
lines changed

arch/arm64/include/asm/kvm_asm.h

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,7 @@
5353
enum __kvm_host_smccc_func {
5454
/* Hypercalls available only prior to pKVM finalisation */
5555
/* __KVM_HOST_SMCCC_FUNC___kvm_hyp_init */
56-
__KVM_HOST_SMCCC_FUNC___kvm_get_mdcr_el2 = __KVM_HOST_SMCCC_FUNC___kvm_hyp_init + 1,
57-
__KVM_HOST_SMCCC_FUNC___pkvm_init,
56+
__KVM_HOST_SMCCC_FUNC___pkvm_init = __KVM_HOST_SMCCC_FUNC___kvm_hyp_init + 1,
5857
__KVM_HOST_SMCCC_FUNC___pkvm_create_private_mapping,
5958
__KVM_HOST_SMCCC_FUNC___pkvm_cpu_set_vector,
6059
__KVM_HOST_SMCCC_FUNC___kvm_enable_ssbs,
@@ -247,8 +246,6 @@ extern void __kvm_adjust_pc(struct kvm_vcpu *vcpu);
247246
extern u64 __vgic_v3_get_gic_config(void);
248247
extern void __vgic_v3_init_lrs(void);
249248

250-
extern u64 __kvm_get_mdcr_el2(void);
251-
252249
#define __KVM_EXTABLE(from, to) \
253250
" .pushsection __kvm_ex_table, \"a\"\n" \
254251
" .align 3\n" \

arch/arm64/include/asm/kvm_host.h

Lines changed: 50 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -610,6 +610,12 @@ struct cpu_sve_state {
610610
* field.
611611
*/
612612
struct kvm_host_data {
613+
#define KVM_HOST_DATA_FLAG_HAS_SPE 0
614+
#define KVM_HOST_DATA_FLAG_HAS_TRBE 1
615+
#define KVM_HOST_DATA_FLAG_HOST_SVE_ENABLED 2
616+
#define KVM_HOST_DATA_FLAG_HOST_SME_ENABLED 3
617+
unsigned long flags;
618+
613619
struct kvm_cpu_context host_ctxt;
614620

615621
/*
@@ -642,7 +648,7 @@ struct kvm_host_data {
642648
* host_debug_state contains the host registers which are
643649
* saved and restored during world switches.
644650
*/
645-
struct {
651+
struct {
646652
/* {Break,watch}point registers */
647653
struct kvm_guest_debug_arch regs;
648654
/* Statistical profiling extension */
@@ -652,6 +658,13 @@ struct kvm_host_data {
652658
/* Values of trap registers for the host before guest entry. */
653659
u64 mdcr_el2;
654660
} host_debug_state;
661+
662+
/* Number of programmable event counters (PMCR_EL0.N) for this CPU */
663+
unsigned int nr_event_counters;
664+
665+
/* Number of debug breakpoints/watchpoints for this CPU (minus 1) */
666+
unsigned int debug_brps;
667+
unsigned int debug_wrps;
655668
};
656669

657670
struct kvm_host_psci_config {
@@ -739,31 +752,22 @@ struct kvm_vcpu_arch {
739752
*
740753
* external_debug_state contains the debug values we want to debug the
741754
* guest. This is set via the KVM_SET_GUEST_DEBUG ioctl.
742-
*
743-
* debug_ptr points to the set of debug registers that should be loaded
744-
* onto the hardware when running the guest.
745755
*/
746-
struct kvm_guest_debug_arch *debug_ptr;
747756
struct kvm_guest_debug_arch vcpu_debug_state;
748757
struct kvm_guest_debug_arch external_debug_state;
758+
u64 external_mdscr_el1;
759+
760+
enum {
761+
VCPU_DEBUG_FREE,
762+
VCPU_DEBUG_HOST_OWNED,
763+
VCPU_DEBUG_GUEST_OWNED,
764+
} debug_owner;
749765

750766
/* VGIC state */
751767
struct vgic_cpu vgic_cpu;
752768
struct arch_timer_cpu timer_cpu;
753769
struct kvm_pmu pmu;
754770

755-
/*
756-
* Guest registers we preserve during guest debugging.
757-
*
758-
* These shadow registers are updated by the kvm_handle_sys_reg
759-
* trap handler if the guest accesses or updates them while we
760-
* are using guest debug.
761-
*/
762-
struct {
763-
u32 mdscr_el1;
764-
bool pstate_ss;
765-
} guest_debug_preserved;
766-
767771
/* vcpu power state */
768772
struct kvm_mp_state mp_state;
769773
spinlock_t mp_state_lock;
@@ -906,29 +910,21 @@ struct kvm_vcpu_arch {
906910
#define EXCEPT_AA64_EL2_IRQ __vcpu_except_flags(5)
907911
#define EXCEPT_AA64_EL2_FIQ __vcpu_except_flags(6)
908912
#define EXCEPT_AA64_EL2_SERR __vcpu_except_flags(7)
909-
/* Guest debug is live */
910-
#define DEBUG_DIRTY __vcpu_single_flag(iflags, BIT(4))
911-
/* Save SPE context if active */
912-
#define DEBUG_STATE_SAVE_SPE __vcpu_single_flag(iflags, BIT(5))
913-
/* Save TRBE context if active */
914-
#define DEBUG_STATE_SAVE_TRBE __vcpu_single_flag(iflags, BIT(6))
915-
916-
/* SVE enabled for host EL0 */
917-
#define HOST_SVE_ENABLED __vcpu_single_flag(sflags, BIT(0))
918-
/* SME enabled for EL0 */
919-
#define HOST_SME_ENABLED __vcpu_single_flag(sflags, BIT(1))
913+
920914
/* Physical CPU not in supported_cpus */
921-
#define ON_UNSUPPORTED_CPU __vcpu_single_flag(sflags, BIT(2))
915+
#define ON_UNSUPPORTED_CPU __vcpu_single_flag(sflags, BIT(0))
922916
/* WFIT instruction trapped */
923-
#define IN_WFIT __vcpu_single_flag(sflags, BIT(3))
917+
#define IN_WFIT __vcpu_single_flag(sflags, BIT(1))
924918
/* vcpu system registers loaded on physical CPU */
925-
#define SYSREGS_ON_CPU __vcpu_single_flag(sflags, BIT(4))
926-
/* Software step state is Active-pending */
927-
#define DBG_SS_ACTIVE_PENDING __vcpu_single_flag(sflags, BIT(5))
919+
#define SYSREGS_ON_CPU __vcpu_single_flag(sflags, BIT(2))
920+
/* Software step state is Active-pending for external debug */
921+
#define HOST_SS_ACTIVE_PENDING __vcpu_single_flag(sflags, BIT(3))
922+
/* Software step state is Active pending for guest debug */
923+
#define GUEST_SS_ACTIVE_PENDING __vcpu_single_flag(sflags, BIT(4))
928924
/* PMUSERENR for the guest EL0 is on physical CPU */
929-
#define PMUSERENR_ON_CPU __vcpu_single_flag(sflags, BIT(6))
925+
#define PMUSERENR_ON_CPU __vcpu_single_flag(sflags, BIT(5))
930926
/* WFI instruction trapped */
931-
#define IN_WFI __vcpu_single_flag(sflags, BIT(7))
927+
#define IN_WFI __vcpu_single_flag(sflags, BIT(6))
932928

933929

934930
/* Pointer to the vcpu's SVE FFR for sve_{save,load}_state() */
@@ -1307,6 +1303,13 @@ DECLARE_KVM_HYP_PER_CPU(struct kvm_host_data, kvm_host_data);
13071303
&this_cpu_ptr_hyp_sym(kvm_host_data)->f)
13081304
#endif
13091305

1306+
#define host_data_test_flag(flag) \
1307+
(test_bit(KVM_HOST_DATA_FLAG_##flag, host_data_ptr(flags)))
1308+
#define host_data_set_flag(flag) \
1309+
set_bit(KVM_HOST_DATA_FLAG_##flag, host_data_ptr(flags))
1310+
#define host_data_clear_flag(flag) \
1311+
clear_bit(KVM_HOST_DATA_FLAG_##flag, host_data_ptr(flags))
1312+
13101313
/* Check whether the FP regs are owned by the guest */
13111314
static inline bool guest_owns_fp_regs(void)
13121315
{
@@ -1332,15 +1335,22 @@ static inline bool kvm_system_needs_idmapped_vectors(void)
13321335

13331336
static inline void kvm_arch_sync_events(struct kvm *kvm) {}
13341337

1335-
void kvm_arm_init_debug(void);
1336-
void kvm_arm_vcpu_init_debug(struct kvm_vcpu *vcpu);
1337-
void kvm_arm_setup_debug(struct kvm_vcpu *vcpu);
1338-
void kvm_arm_clear_debug(struct kvm_vcpu *vcpu);
1339-
void kvm_arm_reset_debug_ptr(struct kvm_vcpu *vcpu);
1338+
void kvm_init_host_debug_data(void);
1339+
void kvm_vcpu_load_debug(struct kvm_vcpu *vcpu);
1340+
void kvm_vcpu_put_debug(struct kvm_vcpu *vcpu);
1341+
void kvm_debug_set_guest_ownership(struct kvm_vcpu *vcpu);
1342+
void kvm_debug_handle_oslar(struct kvm_vcpu *vcpu, u64 val);
13401343

13411344
#define kvm_vcpu_os_lock_enabled(vcpu) \
13421345
(!!(__vcpu_sys_reg(vcpu, OSLSR_EL1) & OSLSR_EL1_OSLK))
13431346

1347+
#define kvm_debug_regs_in_use(vcpu) \
1348+
((vcpu)->arch.debug_owner != VCPU_DEBUG_FREE)
1349+
#define kvm_host_owns_debug_regs(vcpu) \
1350+
((vcpu)->arch.debug_owner == VCPU_DEBUG_HOST_OWNED)
1351+
#define kvm_guest_owns_debug_regs(vcpu) \
1352+
((vcpu)->arch.debug_owner == VCPU_DEBUG_GUEST_OWNED)
1353+
13441354
int kvm_arm_vcpu_arch_set_attr(struct kvm_vcpu *vcpu,
13451355
struct kvm_device_attr *attr);
13461356
int kvm_arm_vcpu_arch_get_attr(struct kvm_vcpu *vcpu,
@@ -1367,10 +1377,6 @@ static inline bool kvm_pmu_counter_deferred(struct perf_event_attr *attr)
13671377
return (!has_vhe() && attr->exclude_host);
13681378
}
13691379

1370-
/* Flags for host debug state */
1371-
void kvm_arch_vcpu_load_debug_state_flags(struct kvm_vcpu *vcpu);
1372-
void kvm_arch_vcpu_put_debug_state_flags(struct kvm_vcpu *vcpu);
1373-
13741380
#ifdef CONFIG_KVM
13751381
void kvm_set_pmu_events(u64 set, struct perf_event_attr *attr);
13761382
void kvm_clr_pmu_events(u64 clr);

arch/arm64/include/asm/kvm_nested.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ static inline u64 translate_ttbr0_el2_to_ttbr0_el1(u64 ttbr0)
6464
}
6565

6666
extern bool forward_smc_trap(struct kvm_vcpu *vcpu);
67+
extern bool forward_debug_exception(struct kvm_vcpu *vcpu);
6768
extern void kvm_init_nested(struct kvm *kvm);
6869
extern int kvm_vcpu_init_nested(struct kvm_vcpu *vcpu);
6970
extern void kvm_init_nested_s2_mmu(struct kvm_s2_mmu *mmu);

arch/arm64/kvm/arm.c

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -476,8 +476,6 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
476476

477477
kvm_pmu_vcpu_init(vcpu);
478478

479-
kvm_arm_reset_debug_ptr(vcpu);
480-
481479
kvm_arm_pvtime_vcpu_init(&vcpu->arch);
482480

483481
vcpu->arch.hw_mmu = &vcpu->kvm->arch.mmu;
@@ -598,6 +596,7 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
598596

599597
kvm_vgic_load(vcpu);
600598
kvm_timer_vcpu_load(vcpu);
599+
kvm_vcpu_load_debug(vcpu);
601600
if (has_vhe())
602601
kvm_vcpu_load_vhe(vcpu);
603602
kvm_arch_vcpu_load_fp(vcpu);
@@ -617,15 +616,13 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
617616

618617
vcpu_set_pauth_traps(vcpu);
619618

620-
kvm_arch_vcpu_load_debug_state_flags(vcpu);
621-
622619
if (!cpumask_test_cpu(cpu, vcpu->kvm->arch.supported_cpus))
623620
vcpu_set_on_unsupported_cpu(vcpu);
624621
}
625622

626623
void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
627624
{
628-
kvm_arch_vcpu_put_debug_state_flags(vcpu);
625+
kvm_vcpu_put_debug(vcpu);
629626
kvm_arch_vcpu_put_fp(vcpu);
630627
if (has_vhe())
631628
kvm_vcpu_put_vhe(vcpu);
@@ -808,8 +805,6 @@ int kvm_arch_vcpu_run_pid_change(struct kvm_vcpu *vcpu)
808805

809806
kvm_init_mpidr_data(kvm);
810807

811-
kvm_arm_vcpu_init_debug(vcpu);
812-
813808
if (likely(irqchip_in_kernel(kvm))) {
814809
/*
815810
* Map the VGIC hardware resources before running a vcpu the
@@ -1187,7 +1182,6 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
11871182
continue;
11881183
}
11891184

1190-
kvm_arm_setup_debug(vcpu);
11911185
kvm_arch_vcpu_ctxflush_fp(vcpu);
11921186

11931187
/**************************************************************
@@ -1204,8 +1198,6 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
12041198
* Back from guest
12051199
*************************************************************/
12061200

1207-
kvm_arm_clear_debug(vcpu);
1208-
12091201
/*
12101202
* We must sync the PMU state before the vgic state so
12111203
* that the vgic can properly sample the updated state of the
@@ -2109,6 +2101,7 @@ static void cpu_set_hyp_vector(void)
21092101
static void cpu_hyp_init_context(void)
21102102
{
21112103
kvm_init_host_cpu_context(host_data_ptr(host_ctxt));
2104+
kvm_init_host_debug_data();
21122105

21132106
if (!is_kernel_in_hyp_mode())
21142107
cpu_init_hyp_mode();
@@ -2117,7 +2110,6 @@ static void cpu_hyp_init_context(void)
21172110
static void cpu_hyp_init_features(void)
21182111
{
21192112
cpu_set_hyp_vector();
2120-
kvm_arm_init_debug();
21212113

21222114
if (is_kernel_in_hyp_mode())
21232115
kvm_timer_init_vhe();

0 commit comments

Comments
 (0)