Skip to content

Commit d400c5b

Browse files
David BrazdilMarc Zyngier
authored andcommitted
KVM: arm64: Split hyp/debug-sr.c to VHE/nVHE
debug-sr.c contains KVM's code for context-switching debug registers, with some code shared between VHE/nVHE. These common routines are moved to a header file, VHE-specific code is moved to vhe/debug-sr.c and nVHE-specific code to nvhe/debug-sr.c. Functions are slightly refactored to move code hidden behind `has_vhe()` checks to the corresponding .c files. Signed-off-by: David Brazdil <[email protected]> Signed-off-by: Marc Zyngier <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 09cf57e commit d400c5b

File tree

7 files changed

+118
-74
lines changed

7 files changed

+118
-74
lines changed

arch/arm64/kernel/image-vars.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,6 @@ __efistub__ctype = _ctype;
6666
/* Symbols defined in aarch32.c (not yet compiled with nVHE build rules). */
6767
KVM_NVHE_ALIAS(kvm_skip_instr32);
6868

69-
/* Symbols defined in debug-sr.c (not yet compiled with nVHE build rules). */
70-
KVM_NVHE_ALIAS(__debug_switch_to_guest);
71-
KVM_NVHE_ALIAS(__debug_switch_to_host);
72-
KVM_NVHE_ALIAS(__kvm_get_mdcr_el2);
73-
7469
/* Symbols defined in entry.S (not yet compiled with nVHE build rules). */
7570
KVM_NVHE_ALIAS(__guest_enter);
7671
KVM_NVHE_ALIAS(__guest_exit);

arch/arm64/kvm/hyp/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ obj-$(CONFIG_KVM) += hyp.o vhe/ nvhe/
1414
obj-$(CONFIG_KVM_INDIRECT_VECTORS) += smccc_wa.o
1515

1616
hyp-y := vgic-v3-sr.o timer-sr.o aarch32.o vgic-v2-cpuif-proxy.o sysreg-sr.o \
17-
debug-sr.o entry.o fpsimd.o
17+
entry.o fpsimd.o
1818

1919
# KVM code is run at a different exception code with a different map, so
2020
# compiler instrumentation that inserts callbacks or checks into the code may

arch/arm64/kvm/hyp/debug-sr.c renamed to arch/arm64/kvm/hyp/include/hyp/debug-sr.h

Lines changed: 12 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
* Author: Marc Zyngier <[email protected]>
55
*/
66

7+
#ifndef __ARM64_KVM_HYP_DEBUG_SR_H__
8+
#define __ARM64_KVM_HYP_DEBUG_SR_H__
9+
710
#include <linux/compiler.h>
811
#include <linux/kvm_host.h>
912

@@ -85,53 +88,9 @@
8588
default: write_debug(ptr[0], reg, 0); \
8689
}
8790

88-
static void __hyp_text __debug_save_spe_nvhe(u64 *pmscr_el1)
89-
{
90-
u64 reg;
91-
92-
/* Clear pmscr in case of early return */
93-
*pmscr_el1 = 0;
94-
95-
/* SPE present on this CPU? */
96-
if (!cpuid_feature_extract_unsigned_field(read_sysreg(id_aa64dfr0_el1),
97-
ID_AA64DFR0_PMSVER_SHIFT))
98-
return;
99-
100-
/* Yes; is it owned by EL3? */
101-
reg = read_sysreg_s(SYS_PMBIDR_EL1);
102-
if (reg & BIT(SYS_PMBIDR_EL1_P_SHIFT))
103-
return;
104-
105-
/* No; is the host actually using the thing? */
106-
reg = read_sysreg_s(SYS_PMBLIMITR_EL1);
107-
if (!(reg & BIT(SYS_PMBLIMITR_EL1_E_SHIFT)))
108-
return;
109-
110-
/* Yes; save the control register and disable data generation */
111-
*pmscr_el1 = read_sysreg_s(SYS_PMSCR_EL1);
112-
write_sysreg_s(0, SYS_PMSCR_EL1);
113-
isb();
114-
115-
/* Now drain all buffered data to memory */
116-
psb_csync();
117-
dsb(nsh);
118-
}
119-
120-
static void __hyp_text __debug_restore_spe_nvhe(u64 pmscr_el1)
121-
{
122-
if (!pmscr_el1)
123-
return;
124-
125-
/* The host page table is installed, but not yet synchronised */
126-
isb();
127-
128-
/* Re-enable data generation */
129-
write_sysreg_s(pmscr_el1, SYS_PMSCR_EL1);
130-
}
131-
132-
static void __hyp_text __debug_save_state(struct kvm_vcpu *vcpu,
133-
struct kvm_guest_debug_arch *dbg,
134-
struct kvm_cpu_context *ctxt)
91+
static inline void __hyp_text __debug_save_state(struct kvm_vcpu *vcpu,
92+
struct kvm_guest_debug_arch *dbg,
93+
struct kvm_cpu_context *ctxt)
13594
{
13695
u64 aa64dfr0;
13796
int brps, wrps;
@@ -148,9 +107,9 @@ static void __hyp_text __debug_save_state(struct kvm_vcpu *vcpu,
148107
ctxt->sys_regs[MDCCINT_EL1] = read_sysreg(mdccint_el1);
149108
}
150109

151-
static void __hyp_text __debug_restore_state(struct kvm_vcpu *vcpu,
152-
struct kvm_guest_debug_arch *dbg,
153-
struct kvm_cpu_context *ctxt)
110+
static inline void __hyp_text __debug_restore_state(struct kvm_vcpu *vcpu,
111+
struct kvm_guest_debug_arch *dbg,
112+
struct kvm_cpu_context *ctxt)
154113
{
155114
u64 aa64dfr0;
156115
int brps, wrps;
@@ -168,20 +127,13 @@ static void __hyp_text __debug_restore_state(struct kvm_vcpu *vcpu,
168127
write_sysreg(ctxt->sys_regs[MDCCINT_EL1], mdccint_el1);
169128
}
170129

171-
void __hyp_text __debug_switch_to_guest(struct kvm_vcpu *vcpu)
130+
static inline void __hyp_text __debug_switch_to_guest_common(struct kvm_vcpu *vcpu)
172131
{
173132
struct kvm_cpu_context *host_ctxt;
174133
struct kvm_cpu_context *guest_ctxt;
175134
struct kvm_guest_debug_arch *host_dbg;
176135
struct kvm_guest_debug_arch *guest_dbg;
177136

178-
/*
179-
* Non-VHE: Disable and flush SPE data generation
180-
* VHE: The vcpu can run, but it can't hide.
181-
*/
182-
if (!has_vhe())
183-
__debug_save_spe_nvhe(&vcpu->arch.host_debug_state.pmscr_el1);
184-
185137
if (!(vcpu->arch.flags & KVM_ARM64_DEBUG_DIRTY))
186138
return;
187139

@@ -194,16 +146,13 @@ void __hyp_text __debug_switch_to_guest(struct kvm_vcpu *vcpu)
194146
__debug_restore_state(vcpu, guest_dbg, guest_ctxt);
195147
}
196148

197-
void __hyp_text __debug_switch_to_host(struct kvm_vcpu *vcpu)
149+
static inline void __hyp_text __debug_switch_to_host_common(struct kvm_vcpu *vcpu)
198150
{
199151
struct kvm_cpu_context *host_ctxt;
200152
struct kvm_cpu_context *guest_ctxt;
201153
struct kvm_guest_debug_arch *host_dbg;
202154
struct kvm_guest_debug_arch *guest_dbg;
203155

204-
if (!has_vhe())
205-
__debug_restore_spe_nvhe(vcpu->arch.host_debug_state.pmscr_el1);
206-
207156
if (!(vcpu->arch.flags & KVM_ARM64_DEBUG_DIRTY))
208157
return;
209158

@@ -218,7 +167,4 @@ void __hyp_text __debug_switch_to_host(struct kvm_vcpu *vcpu)
218167
vcpu->arch.flags &= ~KVM_ARM64_DEBUG_DIRTY;
219168
}
220169

221-
u32 __hyp_text __kvm_get_mdcr_el2(void)
222-
{
223-
return read_sysreg(mdcr_el2);
224-
}
170+
#endif /* __ARM64_KVM_HYP_DEBUG_SR_H__ */

arch/arm64/kvm/hyp/nvhe/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
asflags-y := -D__KVM_NVHE_HYPERVISOR__
77
ccflags-y := -D__KVM_NVHE_HYPERVISOR__
88

9-
obj-y := switch.o tlb.o hyp-init.o ../hyp-entry.o
9+
obj-y := debug-sr.o switch.o tlb.o hyp-init.o ../hyp-entry.o
1010

1111
obj-y := $(patsubst %.o,%.hyp.o,$(obj-y))
1212
extra-y := $(patsubst %.hyp.o,%.hyp.tmp.o,$(obj-y))

arch/arm64/kvm/hyp/nvhe/debug-sr.c

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
// SPDX-License-Identifier: GPL-2.0-only
2+
/*
3+
* Copyright (C) 2015 - ARM Ltd
4+
* Author: Marc Zyngier <[email protected]>
5+
*/
6+
7+
#include <hyp/debug-sr.h>
8+
9+
#include <linux/compiler.h>
10+
#include <linux/kvm_host.h>
11+
12+
#include <asm/debug-monitors.h>
13+
#include <asm/kvm_asm.h>
14+
#include <asm/kvm_hyp.h>
15+
#include <asm/kvm_mmu.h>
16+
17+
static void __hyp_text __debug_save_spe(u64 *pmscr_el1)
18+
{
19+
u64 reg;
20+
21+
/* Clear pmscr in case of early return */
22+
*pmscr_el1 = 0;
23+
24+
/* SPE present on this CPU? */
25+
if (!cpuid_feature_extract_unsigned_field(read_sysreg(id_aa64dfr0_el1),
26+
ID_AA64DFR0_PMSVER_SHIFT))
27+
return;
28+
29+
/* Yes; is it owned by EL3? */
30+
reg = read_sysreg_s(SYS_PMBIDR_EL1);
31+
if (reg & BIT(SYS_PMBIDR_EL1_P_SHIFT))
32+
return;
33+
34+
/* No; is the host actually using the thing? */
35+
reg = read_sysreg_s(SYS_PMBLIMITR_EL1);
36+
if (!(reg & BIT(SYS_PMBLIMITR_EL1_E_SHIFT)))
37+
return;
38+
39+
/* Yes; save the control register and disable data generation */
40+
*pmscr_el1 = read_sysreg_s(SYS_PMSCR_EL1);
41+
write_sysreg_s(0, SYS_PMSCR_EL1);
42+
isb();
43+
44+
/* Now drain all buffered data to memory */
45+
psb_csync();
46+
dsb(nsh);
47+
}
48+
49+
static void __hyp_text __debug_restore_spe(u64 pmscr_el1)
50+
{
51+
if (!pmscr_el1)
52+
return;
53+
54+
/* The host page table is installed, but not yet synchronised */
55+
isb();
56+
57+
/* Re-enable data generation */
58+
write_sysreg_s(pmscr_el1, SYS_PMSCR_EL1);
59+
}
60+
61+
void __hyp_text __debug_switch_to_guest(struct kvm_vcpu *vcpu)
62+
{
63+
/* Disable and flush SPE data generation */
64+
__debug_save_spe(&vcpu->arch.host_debug_state.pmscr_el1);
65+
__debug_switch_to_guest_common(vcpu);
66+
}
67+
68+
void __hyp_text __debug_switch_to_host(struct kvm_vcpu *vcpu)
69+
{
70+
__debug_restore_spe(vcpu->arch.host_debug_state.pmscr_el1);
71+
__debug_switch_to_host_common(vcpu);
72+
}
73+
74+
u32 __hyp_text __kvm_get_mdcr_el2(void)
75+
{
76+
return read_sysreg(mdcr_el2);
77+
}

arch/arm64/kvm/hyp/vhe/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
asflags-y := -D__KVM_VHE_HYPERVISOR__
77
ccflags-y := -D__KVM_VHE_HYPERVISOR__
88

9-
obj-y := switch.o tlb.o ../hyp-entry.o
9+
obj-y := debug-sr.o switch.o tlb.o ../hyp-entry.o
1010

1111
# KVM code is run at a different exception code with a different map, so
1212
# compiler instrumentation that inserts callbacks or checks into the code may

arch/arm64/kvm/hyp/vhe/debug-sr.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// SPDX-License-Identifier: GPL-2.0-only
2+
/*
3+
* Copyright (C) 2015 - ARM Ltd
4+
* Author: Marc Zyngier <[email protected]>
5+
*/
6+
7+
#include <hyp/debug-sr.h>
8+
9+
#include <linux/kvm_host.h>
10+
11+
#include <asm/kvm_hyp.h>
12+
13+
void __debug_switch_to_guest(struct kvm_vcpu *vcpu)
14+
{
15+
__debug_switch_to_guest_common(vcpu);
16+
}
17+
18+
void __debug_switch_to_host(struct kvm_vcpu *vcpu)
19+
{
20+
__debug_switch_to_host_common(vcpu);
21+
}
22+
23+
u32 __kvm_get_mdcr_el2(void)
24+
{
25+
return read_sysreg(mdcr_el2);
26+
}

0 commit comments

Comments
 (0)