Skip to content

Commit a016202

Browse files
Marc Zyngieroupton
authored andcommitted
KVM: arm64: Extend masking facility to arbitrary registers
We currently only use the masking (RES0/RES1) facility for VNCR registers, as they are memory-based and thus easy to sanitise. But we could apply the same thing to other registers if we: - split the sanitisation from __VNCR_START__ - apply the sanitisation when reading from a HW register This involves a new "marker" in the vcpu_sysreg enum, which defines the point at which the sanitisation applies (the VNCR registers being of course after this marker). Whle we are at it, rename kvm_vcpu_sanitise_vncr_reg() to kvm_vcpu_apply_reg_masks(), which is vaguely more explicit, and harden set_sysreg_masks() against setting masks for random registers... Signed-off-by: Marc Zyngier <[email protected]> Reviewed-by: Joey Gouly <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Oliver Upton <[email protected]>
1 parent 14ca930 commit a016202

File tree

3 files changed

+24
-10
lines changed

3 files changed

+24
-10
lines changed

arch/arm64/include/asm/kvm_host.h

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -374,7 +374,7 @@ struct kvm_arch {
374374

375375
u64 ctr_el0;
376376

377-
/* Masks for VNCR-baked sysregs */
377+
/* Masks for VNCR-backed and general EL2 sysregs */
378378
struct kvm_sysreg_masks *sysreg_masks;
379379

380380
/*
@@ -408,6 +408,9 @@ struct kvm_vcpu_fault_info {
408408
r = __VNCR_START__ + ((VNCR_ ## r) / 8), \
409409
__after_##r = __MAX__(__before_##r - 1, r)
410410

411+
#define MARKER(m) \
412+
m, __after_##m = m - 1
413+
411414
enum vcpu_sysreg {
412415
__INVALID_SYSREG__, /* 0 is reserved as an invalid value */
413416
MPIDR_EL1, /* MultiProcessor Affinity Register */
@@ -494,7 +497,11 @@ enum vcpu_sysreg {
494497
CNTHV_CTL_EL2,
495498
CNTHV_CVAL_EL2,
496499

497-
__VNCR_START__, /* Any VNCR-capable reg goes after this point */
500+
/* Anything from this can be RES0/RES1 sanitised */
501+
MARKER(__SANITISED_REG_START__),
502+
503+
/* Any VNCR-capable reg goes after this point */
504+
MARKER(__VNCR_START__),
498505

499506
VNCR(SCTLR_EL1),/* System Control Register */
500507
VNCR(ACTLR_EL1),/* Auxiliary Control Register */
@@ -554,7 +561,7 @@ struct kvm_sysreg_masks {
554561
struct {
555562
u64 res0;
556563
u64 res1;
557-
} mask[NR_SYS_REGS - __VNCR_START__];
564+
} mask[NR_SYS_REGS - __SANITISED_REG_START__];
558565
};
559566

560567
struct kvm_cpu_context {
@@ -1002,13 +1009,13 @@ static inline u64 *___ctxt_sys_reg(const struct kvm_cpu_context *ctxt, int r)
10021009

10031010
#define ctxt_sys_reg(c,r) (*__ctxt_sys_reg(c,r))
10041011

1005-
u64 kvm_vcpu_sanitise_vncr_reg(const struct kvm_vcpu *, enum vcpu_sysreg);
1012+
u64 kvm_vcpu_apply_reg_masks(const struct kvm_vcpu *, enum vcpu_sysreg, u64);
10061013
#define __vcpu_sys_reg(v,r) \
10071014
(*({ \
10081015
const struct kvm_cpu_context *ctxt = &(v)->arch.ctxt; \
10091016
u64 *__r = __ctxt_sys_reg(ctxt, (r)); \
1010-
if (vcpu_has_nv((v)) && (r) >= __VNCR_START__) \
1011-
*__r = kvm_vcpu_sanitise_vncr_reg((v), (r)); \
1017+
if (vcpu_has_nv((v)) && (r) >= __SANITISED_REG_START__) \
1018+
*__r = kvm_vcpu_apply_reg_masks((v), (r), *__r);\
10121019
__r; \
10131020
}))
10141021

arch/arm64/kvm/nested.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -933,15 +933,15 @@ static void limit_nv_id_regs(struct kvm *kvm)
933933
kvm_set_vm_id_reg(kvm, SYS_ID_AA64DFR0_EL1, val);
934934
}
935935

936-
u64 kvm_vcpu_sanitise_vncr_reg(const struct kvm_vcpu *vcpu, enum vcpu_sysreg sr)
936+
u64 kvm_vcpu_apply_reg_masks(const struct kvm_vcpu *vcpu,
937+
enum vcpu_sysreg sr, u64 v)
937938
{
938-
u64 v = ctxt_sys_reg(&vcpu->arch.ctxt, sr);
939939
struct kvm_sysreg_masks *masks;
940940

941941
masks = vcpu->kvm->arch.sysreg_masks;
942942

943943
if (masks) {
944-
sr -= __VNCR_START__;
944+
sr -= __SANITISED_REG_START__;
945945

946946
v &= ~masks->mask[sr].res0;
947947
v |= masks->mask[sr].res1;
@@ -952,7 +952,11 @@ u64 kvm_vcpu_sanitise_vncr_reg(const struct kvm_vcpu *vcpu, enum vcpu_sysreg sr)
952952

953953
static void set_sysreg_masks(struct kvm *kvm, int sr, u64 res0, u64 res1)
954954
{
955-
int i = sr - __VNCR_START__;
955+
int i = sr - __SANITISED_REG_START__;
956+
957+
BUILD_BUG_ON(!__builtin_constant_p(sr));
958+
BUILD_BUG_ON(sr < __SANITISED_REG_START__);
959+
BUILD_BUG_ON(sr >= NR_SYS_REGS);
956960

957961
kvm->arch.sysreg_masks->mask[i].res0 = res0;
958962
kvm->arch.sysreg_masks->mask[i].res1 = res1;

arch/arm64/kvm/sys_regs.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,9 @@ u64 vcpu_read_sys_reg(const struct kvm_vcpu *vcpu, int reg)
189189

190190
/* Get the current version of the EL1 counterpart. */
191191
WARN_ON(!__vcpu_read_sys_reg_from_cpu(el1r, &val));
192+
if (reg >= __SANITISED_REG_START__)
193+
val = kvm_vcpu_apply_reg_masks(vcpu, reg, val);
194+
192195
return val;
193196
}
194197

0 commit comments

Comments
 (0)