Skip to content

Commit 2c38234

Browse files
committed
Merge tag 'kvmarm-fixes-5.10-3' of git://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm into HEAD
KVM/arm64 fixes for v5.10, take GalliumOS#3 - Allow userspace to downgrade ID_AA64PFR0_EL1.CSV2 - Inject UNDEF on SCXTNUM_ELx access
2 parents 585e5b1 + ed4ffaf commit 2c38234

File tree

4 files changed

+89
-44
lines changed

4 files changed

+89
-44
lines changed

arch/arm64/include/asm/kvm_host.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,8 @@ struct kvm_arch {
118118
*/
119119
unsigned long *pmu_filter;
120120
unsigned int pmuver;
121+
122+
u8 pfr0_csv2;
121123
};
122124

123125
struct kvm_vcpu_fault_info {

arch/arm64/include/asm/sysreg.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,8 @@
372372
#define SYS_CONTEXTIDR_EL1 sys_reg(3, 0, 13, 0, 1)
373373
#define SYS_TPIDR_EL1 sys_reg(3, 0, 13, 0, 4)
374374

375+
#define SYS_SCXTNUM_EL1 sys_reg(3, 0, 13, 0, 7)
376+
375377
#define SYS_CNTKCTL_EL1 sys_reg(3, 0, 14, 1, 0)
376378

377379
#define SYS_CCSIDR_EL1 sys_reg(3, 1, 0, 0, 0)
@@ -404,6 +406,8 @@
404406
#define SYS_TPIDR_EL0 sys_reg(3, 3, 13, 0, 2)
405407
#define SYS_TPIDRRO_EL0 sys_reg(3, 3, 13, 0, 3)
406408

409+
#define SYS_SCXTNUM_EL0 sys_reg(3, 3, 13, 0, 7)
410+
407411
/* Definitions for system register interface to AMU for ARMv8.4 onwards */
408412
#define SYS_AM_EL0(crm, op2) sys_reg(3, 3, 13, (crm), (op2))
409413
#define SYS_AMCR_EL0 SYS_AM_EL0(2, 0)

arch/arm64/kvm/arm.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,20 @@ static int kvm_arm_default_max_vcpus(void)
102102
return vgic_present ? kvm_vgic_get_max_vcpus() : KVM_MAX_VCPUS;
103103
}
104104

105+
static void set_default_csv2(struct kvm *kvm)
106+
{
107+
/*
108+
* The default is to expose CSV2 == 1 if the HW isn't affected.
109+
* Although this is a per-CPU feature, we make it global because
110+
* asymmetric systems are just a nuisance.
111+
*
112+
* Userspace can override this as long as it doesn't promise
113+
* the impossible.
114+
*/
115+
if (arm64_get_spectre_v2_state() == SPECTRE_UNAFFECTED)
116+
kvm->arch.pfr0_csv2 = 1;
117+
}
118+
105119
/**
106120
* kvm_arch_init_vm - initializes a VM data structure
107121
* @kvm: pointer to the KVM struct
@@ -127,6 +141,8 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
127141
/* The maximum number of VCPUs is limited by the host's GIC model */
128142
kvm->arch.max_vcpus = kvm_arm_default_max_vcpus();
129143

144+
set_default_csv2(kvm);
145+
130146
return ret;
131147
out_free_stage2_pgd:
132148
kvm_free_stage2_pgd(&kvm->arch.mmu);

arch/arm64/kvm/sys_regs.c

Lines changed: 67 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1038,42 +1038,34 @@ static bool access_pmuserenr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
10381038
{ SYS_DESC(SYS_PMEVTYPERn_EL0(n)), \
10391039
access_pmu_evtyper, reset_unknown, (PMEVTYPER0_EL0 + n), }
10401040

1041-
static bool access_amu(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
1042-
const struct sys_reg_desc *r)
1041+
static bool undef_access(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
1042+
const struct sys_reg_desc *r)
10431043
{
10441044
kvm_inject_undefined(vcpu);
10451045

10461046
return false;
10471047
}
10481048

10491049
/* Macro to expand the AMU counter and type registers*/
1050-
#define AMU_AMEVCNTR0_EL0(n) { SYS_DESC(SYS_AMEVCNTR0_EL0(n)), access_amu }
1051-
#define AMU_AMEVTYPER0_EL0(n) { SYS_DESC(SYS_AMEVTYPER0_EL0(n)), access_amu }
1052-
#define AMU_AMEVCNTR1_EL0(n) { SYS_DESC(SYS_AMEVCNTR1_EL0(n)), access_amu }
1053-
#define AMU_AMEVTYPER1_EL0(n) { SYS_DESC(SYS_AMEVTYPER1_EL0(n)), access_amu }
1054-
1055-
static bool trap_ptrauth(struct kvm_vcpu *vcpu,
1056-
struct sys_reg_params *p,
1057-
const struct sys_reg_desc *rd)
1058-
{
1059-
/*
1060-
* If we land here, that is because we didn't fixup the access on exit
1061-
* by allowing the PtrAuth sysregs. The only way this happens is when
1062-
* the guest does not have PtrAuth support enabled.
1063-
*/
1064-
kvm_inject_undefined(vcpu);
1065-
1066-
return false;
1067-
}
1050+
#define AMU_AMEVCNTR0_EL0(n) { SYS_DESC(SYS_AMEVCNTR0_EL0(n)), undef_access }
1051+
#define AMU_AMEVTYPER0_EL0(n) { SYS_DESC(SYS_AMEVTYPER0_EL0(n)), undef_access }
1052+
#define AMU_AMEVCNTR1_EL0(n) { SYS_DESC(SYS_AMEVCNTR1_EL0(n)), undef_access }
1053+
#define AMU_AMEVTYPER1_EL0(n) { SYS_DESC(SYS_AMEVTYPER1_EL0(n)), undef_access }
10681054

10691055
static unsigned int ptrauth_visibility(const struct kvm_vcpu *vcpu,
10701056
const struct sys_reg_desc *rd)
10711057
{
10721058
return vcpu_has_ptrauth(vcpu) ? 0 : REG_HIDDEN;
10731059
}
10741060

1061+
/*
1062+
* If we land here on a PtrAuth access, that is because we didn't
1063+
* fixup the access on exit by allowing the PtrAuth sysregs. The only
1064+
* way this happens is when the guest does not have PtrAuth support
1065+
* enabled.
1066+
*/
10751067
#define __PTRAUTH_KEY(k) \
1076-
{ SYS_DESC(SYS_## k), trap_ptrauth, reset_unknown, k, \
1068+
{ SYS_DESC(SYS_## k), undef_access, reset_unknown, k, \
10771069
.visibility = ptrauth_visibility}
10781070

10791071
#define PTRAUTH_KEY(k) \
@@ -1128,9 +1120,8 @@ static u64 read_id_reg(const struct kvm_vcpu *vcpu,
11281120
if (!vcpu_has_sve(vcpu))
11291121
val &= ~(0xfUL << ID_AA64PFR0_SVE_SHIFT);
11301122
val &= ~(0xfUL << ID_AA64PFR0_AMU_SHIFT);
1131-
if (!(val & (0xfUL << ID_AA64PFR0_CSV2_SHIFT)) &&
1132-
arm64_get_spectre_v2_state() == SPECTRE_UNAFFECTED)
1133-
val |= (1UL << ID_AA64PFR0_CSV2_SHIFT);
1123+
val &= ~(0xfUL << ID_AA64PFR0_CSV2_SHIFT);
1124+
val |= ((u64)vcpu->kvm->arch.pfr0_csv2 << ID_AA64PFR0_CSV2_SHIFT);
11341125
} else if (id == SYS_ID_AA64PFR1_EL1) {
11351126
val &= ~(0xfUL << ID_AA64PFR1_MTE_SHIFT);
11361127
} else if (id == SYS_ID_AA64ISAR1_EL1 && !vcpu_has_ptrauth(vcpu)) {
@@ -1213,6 +1204,40 @@ static unsigned int sve_visibility(const struct kvm_vcpu *vcpu,
12131204
return REG_HIDDEN;
12141205
}
12151206

1207+
static int set_id_aa64pfr0_el1(struct kvm_vcpu *vcpu,
1208+
const struct sys_reg_desc *rd,
1209+
const struct kvm_one_reg *reg, void __user *uaddr)
1210+
{
1211+
const u64 id = sys_reg_to_index(rd);
1212+
int err;
1213+
u64 val;
1214+
u8 csv2;
1215+
1216+
err = reg_from_user(&val, uaddr, id);
1217+
if (err)
1218+
return err;
1219+
1220+
/*
1221+
* Allow AA64PFR0_EL1.CSV2 to be set from userspace as long as
1222+
* it doesn't promise more than what is actually provided (the
1223+
* guest could otherwise be covered in ectoplasmic residue).
1224+
*/
1225+
csv2 = cpuid_feature_extract_unsigned_field(val, ID_AA64PFR0_CSV2_SHIFT);
1226+
if (csv2 > 1 ||
1227+
(csv2 && arm64_get_spectre_v2_state() != SPECTRE_UNAFFECTED))
1228+
return -EINVAL;
1229+
1230+
/* We can only differ with CSV2, and anything else is an error */
1231+
val ^= read_id_reg(vcpu, rd, false);
1232+
val &= ~(0xFUL << ID_AA64PFR0_CSV2_SHIFT);
1233+
if (val)
1234+
return -EINVAL;
1235+
1236+
vcpu->kvm->arch.pfr0_csv2 = csv2;
1237+
1238+
return 0;
1239+
}
1240+
12161241
/*
12171242
* cpufeature ID register user accessors
12181243
*
@@ -1341,13 +1366,6 @@ static bool access_ccsidr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
13411366
return true;
13421367
}
13431368

1344-
static bool access_mte_regs(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
1345-
const struct sys_reg_desc *r)
1346-
{
1347-
kvm_inject_undefined(vcpu);
1348-
return false;
1349-
}
1350-
13511369
/* sys_reg_desc initialiser for known cpufeature ID registers */
13521370
#define ID_SANITISED(name) { \
13531371
SYS_DESC(SYS_##name), \
@@ -1472,7 +1490,8 @@ static const struct sys_reg_desc sys_reg_descs[] = {
14721490

14731491
/* AArch64 ID registers */
14741492
/* CRm=4 */
1475-
ID_SANITISED(ID_AA64PFR0_EL1),
1493+
{ SYS_DESC(SYS_ID_AA64PFR0_EL1), .access = access_id_reg,
1494+
.get_user = get_id_reg, .set_user = set_id_aa64pfr0_el1, },
14761495
ID_SANITISED(ID_AA64PFR1_EL1),
14771496
ID_UNALLOCATED(4,2),
14781497
ID_UNALLOCATED(4,3),
@@ -1515,8 +1534,8 @@ static const struct sys_reg_desc sys_reg_descs[] = {
15151534
{ SYS_DESC(SYS_ACTLR_EL1), access_actlr, reset_actlr, ACTLR_EL1 },
15161535
{ SYS_DESC(SYS_CPACR_EL1), NULL, reset_val, CPACR_EL1, 0 },
15171536

1518-
{ SYS_DESC(SYS_RGSR_EL1), access_mte_regs },
1519-
{ SYS_DESC(SYS_GCR_EL1), access_mte_regs },
1537+
{ SYS_DESC(SYS_RGSR_EL1), undef_access },
1538+
{ SYS_DESC(SYS_GCR_EL1), undef_access },
15201539

15211540
{ SYS_DESC(SYS_ZCR_EL1), NULL, reset_val, ZCR_EL1, 0, .visibility = sve_visibility },
15221541
{ SYS_DESC(SYS_TTBR0_EL1), access_vm_reg, reset_unknown, TTBR0_EL1 },
@@ -1542,8 +1561,8 @@ static const struct sys_reg_desc sys_reg_descs[] = {
15421561
{ SYS_DESC(SYS_ERXMISC0_EL1), trap_raz_wi },
15431562
{ SYS_DESC(SYS_ERXMISC1_EL1), trap_raz_wi },
15441563

1545-
{ SYS_DESC(SYS_TFSR_EL1), access_mte_regs },
1546-
{ SYS_DESC(SYS_TFSRE0_EL1), access_mte_regs },
1564+
{ SYS_DESC(SYS_TFSR_EL1), undef_access },
1565+
{ SYS_DESC(SYS_TFSRE0_EL1), undef_access },
15471566

15481567
{ SYS_DESC(SYS_FAR_EL1), access_vm_reg, reset_unknown, FAR_EL1 },
15491568
{ SYS_DESC(SYS_PAR_EL1), NULL, reset_unknown, PAR_EL1 },
@@ -1579,6 +1598,8 @@ static const struct sys_reg_desc sys_reg_descs[] = {
15791598
{ SYS_DESC(SYS_CONTEXTIDR_EL1), access_vm_reg, reset_val, CONTEXTIDR_EL1, 0 },
15801599
{ SYS_DESC(SYS_TPIDR_EL1), NULL, reset_unknown, TPIDR_EL1 },
15811600

1601+
{ SYS_DESC(SYS_SCXTNUM_EL1), undef_access },
1602+
15821603
{ SYS_DESC(SYS_CNTKCTL_EL1), NULL, reset_val, CNTKCTL_EL1, 0},
15831604

15841605
{ SYS_DESC(SYS_CCSIDR_EL1), access_ccsidr },
@@ -1607,14 +1628,16 @@ static const struct sys_reg_desc sys_reg_descs[] = {
16071628
{ SYS_DESC(SYS_TPIDR_EL0), NULL, reset_unknown, TPIDR_EL0 },
16081629
{ SYS_DESC(SYS_TPIDRRO_EL0), NULL, reset_unknown, TPIDRRO_EL0 },
16091630

1610-
{ SYS_DESC(SYS_AMCR_EL0), access_amu },
1611-
{ SYS_DESC(SYS_AMCFGR_EL0), access_amu },
1612-
{ SYS_DESC(SYS_AMCGCR_EL0), access_amu },
1613-
{ SYS_DESC(SYS_AMUSERENR_EL0), access_amu },
1614-
{ SYS_DESC(SYS_AMCNTENCLR0_EL0), access_amu },
1615-
{ SYS_DESC(SYS_AMCNTENSET0_EL0), access_amu },
1616-
{ SYS_DESC(SYS_AMCNTENCLR1_EL0), access_amu },
1617-
{ SYS_DESC(SYS_AMCNTENSET1_EL0), access_amu },
1631+
{ SYS_DESC(SYS_SCXTNUM_EL0), undef_access },
1632+
1633+
{ SYS_DESC(SYS_AMCR_EL0), undef_access },
1634+
{ SYS_DESC(SYS_AMCFGR_EL0), undef_access },
1635+
{ SYS_DESC(SYS_AMCGCR_EL0), undef_access },
1636+
{ SYS_DESC(SYS_AMUSERENR_EL0), undef_access },
1637+
{ SYS_DESC(SYS_AMCNTENCLR0_EL0), undef_access },
1638+
{ SYS_DESC(SYS_AMCNTENSET0_EL0), undef_access },
1639+
{ SYS_DESC(SYS_AMCNTENCLR1_EL0), undef_access },
1640+
{ SYS_DESC(SYS_AMCNTENSET1_EL0), undef_access },
16181641
AMU_AMEVCNTR0_EL0(0),
16191642
AMU_AMEVCNTR0_EL0(1),
16201643
AMU_AMEVCNTR0_EL0(2),

0 commit comments

Comments
 (0)