Skip to content

Commit 6d8fb3c

Browse files
Fuad TabbaMarc Zyngier
authored andcommitted
KVM: arm64: Abstract set/clear of CPTR_EL2 bits behind helper
The same traps controlled by CPTR_EL2 or CPACR_EL1 need to be toggled in different parts of the code, but the exact bits and their polarity differ between these two formats and the mode (vhe/nvhe/hvhe). To reduce the amount of duplicated code and the chance of getting the wrong bit/polarity or missing a field, abstract the set/clear of CPTR_EL2 bits behind a helper. Since (h)VHE is the way of the future, use the CPACR_EL1 format, which is a subset of the VHE CPTR_EL2, as a reference. No functional change intended. Suggested-by: Oliver Upton <[email protected]> Reviewed-by: Oliver Upton <[email protected]> Signed-off-by: Fuad Tabba <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Marc Zyngier <[email protected]>
1 parent 45f4ea9 commit 6d8fb3c

File tree

4 files changed

+73
-19
lines changed

4 files changed

+73
-19
lines changed

arch/arm64/include/asm/kvm_arm.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,12 @@
305305
GENMASK(19, 14) | \
306306
BIT(11))
307307

308+
#define CPTR_VHE_EL2_RES0 (GENMASK(63, 32) | \
309+
GENMASK(27, 26) | \
310+
GENMASK(23, 22) | \
311+
GENMASK(19, 18) | \
312+
GENMASK(15, 0))
313+
308314
/* Hyp Debug Configuration Register bits */
309315
#define MDCR_EL2_E2TB_MASK (UL(0x3))
310316
#define MDCR_EL2_E2TB_SHIFT (UL(24))

arch/arm64/include/asm/kvm_emulate.h

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -557,6 +557,68 @@ static __always_inline void kvm_incr_pc(struct kvm_vcpu *vcpu)
557557
vcpu_set_flag((v), e); \
558558
} while (0)
559559

560+
#define __build_check_all_or_none(r, bits) \
561+
BUILD_BUG_ON(((r) & (bits)) && ((r) & (bits)) != (bits))
562+
563+
#define __cpacr_to_cptr_clr(clr, set) \
564+
({ \
565+
u64 cptr = 0; \
566+
\
567+
if ((set) & CPACR_ELx_FPEN) \
568+
cptr |= CPTR_EL2_TFP; \
569+
if ((set) & CPACR_ELx_ZEN) \
570+
cptr |= CPTR_EL2_TZ; \
571+
if ((set) & CPACR_ELx_SMEN) \
572+
cptr |= CPTR_EL2_TSM; \
573+
if ((clr) & CPACR_ELx_TTA) \
574+
cptr |= CPTR_EL2_TTA; \
575+
if ((clr) & CPTR_EL2_TAM) \
576+
cptr |= CPTR_EL2_TAM; \
577+
if ((clr) & CPTR_EL2_TCPAC) \
578+
cptr |= CPTR_EL2_TCPAC; \
579+
\
580+
cptr; \
581+
})
582+
583+
#define __cpacr_to_cptr_set(clr, set) \
584+
({ \
585+
u64 cptr = 0; \
586+
\
587+
if ((clr) & CPACR_ELx_FPEN) \
588+
cptr |= CPTR_EL2_TFP; \
589+
if ((clr) & CPACR_ELx_ZEN) \
590+
cptr |= CPTR_EL2_TZ; \
591+
if ((clr) & CPACR_ELx_SMEN) \
592+
cptr |= CPTR_EL2_TSM; \
593+
if ((set) & CPACR_ELx_TTA) \
594+
cptr |= CPTR_EL2_TTA; \
595+
if ((set) & CPTR_EL2_TAM) \
596+
cptr |= CPTR_EL2_TAM; \
597+
if ((set) & CPTR_EL2_TCPAC) \
598+
cptr |= CPTR_EL2_TCPAC; \
599+
\
600+
cptr; \
601+
})
602+
603+
#define cpacr_clear_set(clr, set) \
604+
do { \
605+
BUILD_BUG_ON((set) & CPTR_VHE_EL2_RES0); \
606+
BUILD_BUG_ON((clr) & CPACR_ELx_E0POE); \
607+
__build_check_all_or_none((clr), CPACR_ELx_FPEN); \
608+
__build_check_all_or_none((set), CPACR_ELx_FPEN); \
609+
__build_check_all_or_none((clr), CPACR_ELx_ZEN); \
610+
__build_check_all_or_none((set), CPACR_ELx_ZEN); \
611+
__build_check_all_or_none((clr), CPACR_ELx_SMEN); \
612+
__build_check_all_or_none((set), CPACR_ELx_SMEN); \
613+
\
614+
if (has_vhe() || has_hvhe()) \
615+
sysreg_clear_set(cpacr_el1, clr, set); \
616+
else \
617+
sysreg_clear_set(cptr_el2, \
618+
__cpacr_to_cptr_clr(clr, set), \
619+
__cpacr_to_cptr_set(clr, set));\
620+
} while (0)
621+
560622
static __always_inline void kvm_write_cptr_el2(u64 val)
561623
{
562624
if (has_vhe() || has_hvhe())

arch/arm64/kvm/hyp/include/hyp/switch.h

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,6 @@ static bool kvm_hyp_handle_fpsimd(struct kvm_vcpu *vcpu, u64 *exit_code)
331331
{
332332
bool sve_guest;
333333
u8 esr_ec;
334-
u64 reg;
335334

336335
if (!system_supports_fpsimd())
337336
return false;
@@ -354,19 +353,10 @@ static bool kvm_hyp_handle_fpsimd(struct kvm_vcpu *vcpu, u64 *exit_code)
354353
/* Valid trap. Switch the context: */
355354

356355
/* First disable enough traps to allow us to update the registers */
357-
if (has_vhe() || has_hvhe()) {
358-
reg = CPACR_EL1_FPEN_EL0EN | CPACR_EL1_FPEN_EL1EN;
359-
if (sve_guest)
360-
reg |= CPACR_EL1_ZEN_EL0EN | CPACR_EL1_ZEN_EL1EN;
361-
362-
sysreg_clear_set(cpacr_el1, 0, reg);
363-
} else {
364-
reg = CPTR_EL2_TFP;
365-
if (sve_guest)
366-
reg |= CPTR_EL2_TZ;
367-
368-
sysreg_clear_set(cptr_el2, reg, 0);
369-
}
356+
if (sve_guest)
357+
cpacr_clear_set(0, CPACR_ELx_FPEN | CPACR_ELx_ZEN);
358+
else
359+
cpacr_clear_set(0, CPACR_ELx_FPEN);
370360
isb();
371361

372362
/* Write out the host state if it's in the registers */

arch/arm64/kvm/hyp/nvhe/hyp-main.c

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -405,11 +405,7 @@ void handle_trap(struct kvm_cpu_context *host_ctxt)
405405
handle_host_smc(host_ctxt);
406406
break;
407407
case ESR_ELx_EC_SVE:
408-
if (has_hvhe())
409-
sysreg_clear_set(cpacr_el1, 0, (CPACR_EL1_ZEN_EL1EN |
410-
CPACR_EL1_ZEN_EL0EN));
411-
else
412-
sysreg_clear_set(cptr_el2, CPTR_EL2_TZ, 0);
408+
cpacr_clear_set(0, CPACR_ELx_ZEN);
413409
isb();
414410
sve_cond_update_zcr_vq(ZCR_ELx_LEN_MASK, SYS_ZCR_EL2);
415411
break;

0 commit comments

Comments
 (0)