19f75b6d4SMarc Zyngier // SPDX-License-Identifier: GPL-2.0-only
29f75b6d4SMarc Zyngier /*
39f75b6d4SMarc Zyngier * Copyright (C) 2017 - Columbia University and Linaro Ltd.
49f75b6d4SMarc Zyngier * Author: Jintack Lim <jintack.lim@linaro.org>
59f75b6d4SMarc Zyngier */
69f75b6d4SMarc Zyngier
79f75b6d4SMarc Zyngier #include <linux/kvm.h>
89f75b6d4SMarc Zyngier #include <linux/kvm_host.h>
99f75b6d4SMarc Zyngier
109f75b6d4SMarc Zyngier #include <asm/kvm_emulate.h>
119f75b6d4SMarc Zyngier #include <asm/kvm_nested.h>
129f75b6d4SMarc Zyngier #include <asm/sysreg.h>
139f75b6d4SMarc Zyngier
149f75b6d4SMarc Zyngier #include "sys_regs.h"
159f75b6d4SMarc Zyngier
169f75b6d4SMarc Zyngier /* Protection against the sysreg repainting madness... */
179f75b6d4SMarc Zyngier #define NV_FTR(r, f) ID_AA64##r##_EL1_##f
189f75b6d4SMarc Zyngier
199f75b6d4SMarc Zyngier /*
209f75b6d4SMarc Zyngier * Our emulated CPU doesn't support all the possible features. For the
219f75b6d4SMarc Zyngier * sake of simplicity (and probably mental sanity), wipe out a number
229f75b6d4SMarc Zyngier * of feature bits we don't intend to support for the time being.
239f75b6d4SMarc Zyngier * This list should get updated as new features get added to the NV
249f75b6d4SMarc Zyngier * support, and new extension to the architecture.
259f75b6d4SMarc Zyngier */
access_nested_id_reg(struct kvm_vcpu * v,struct sys_reg_params * p,const struct sys_reg_desc * r)269f75b6d4SMarc Zyngier void access_nested_id_reg(struct kvm_vcpu *v, struct sys_reg_params *p,
279f75b6d4SMarc Zyngier const struct sys_reg_desc *r)
289f75b6d4SMarc Zyngier {
293fb901cdSOliver Upton u32 id = reg_to_encoding(r);
309f75b6d4SMarc Zyngier u64 val, tmp;
319f75b6d4SMarc Zyngier
329f75b6d4SMarc Zyngier val = p->regval;
339f75b6d4SMarc Zyngier
349f75b6d4SMarc Zyngier switch (id) {
359f75b6d4SMarc Zyngier case SYS_ID_AA64ISAR0_EL1:
369f75b6d4SMarc Zyngier /* Support everything but TME, O.S. and Range TLBIs */
379f75b6d4SMarc Zyngier val &= ~(NV_FTR(ISAR0, TLB) |
389f75b6d4SMarc Zyngier NV_FTR(ISAR0, TME));
399f75b6d4SMarc Zyngier break;
409f75b6d4SMarc Zyngier
419f75b6d4SMarc Zyngier case SYS_ID_AA64ISAR1_EL1:
429f75b6d4SMarc Zyngier /* Support everything but PtrAuth and Spec Invalidation */
439f75b6d4SMarc Zyngier val &= ~(GENMASK_ULL(63, 56) |
449f75b6d4SMarc Zyngier NV_FTR(ISAR1, SPECRES) |
459f75b6d4SMarc Zyngier NV_FTR(ISAR1, GPI) |
469f75b6d4SMarc Zyngier NV_FTR(ISAR1, GPA) |
479f75b6d4SMarc Zyngier NV_FTR(ISAR1, API) |
489f75b6d4SMarc Zyngier NV_FTR(ISAR1, APA));
499f75b6d4SMarc Zyngier break;
509f75b6d4SMarc Zyngier
519f75b6d4SMarc Zyngier case SYS_ID_AA64PFR0_EL1:
529f75b6d4SMarc Zyngier /* No AMU, MPAM, S-EL2, RAS or SVE */
539f75b6d4SMarc Zyngier val &= ~(GENMASK_ULL(55, 52) |
549f75b6d4SMarc Zyngier NV_FTR(PFR0, AMU) |
559f75b6d4SMarc Zyngier NV_FTR(PFR0, MPAM) |
569f75b6d4SMarc Zyngier NV_FTR(PFR0, SEL2) |
579f75b6d4SMarc Zyngier NV_FTR(PFR0, RAS) |
589f75b6d4SMarc Zyngier NV_FTR(PFR0, SVE) |
599f75b6d4SMarc Zyngier NV_FTR(PFR0, EL3) |
609f75b6d4SMarc Zyngier NV_FTR(PFR0, EL2) |
619f75b6d4SMarc Zyngier NV_FTR(PFR0, EL1));
629f75b6d4SMarc Zyngier /* 64bit EL1/EL2/EL3 only */
639f75b6d4SMarc Zyngier val |= FIELD_PREP(NV_FTR(PFR0, EL1), 0b0001);
649f75b6d4SMarc Zyngier val |= FIELD_PREP(NV_FTR(PFR0, EL2), 0b0001);
659f75b6d4SMarc Zyngier val |= FIELD_PREP(NV_FTR(PFR0, EL3), 0b0001);
669f75b6d4SMarc Zyngier break;
679f75b6d4SMarc Zyngier
689f75b6d4SMarc Zyngier case SYS_ID_AA64PFR1_EL1:
699f75b6d4SMarc Zyngier /* Only support SSBS */
709f75b6d4SMarc Zyngier val &= NV_FTR(PFR1, SSBS);
719f75b6d4SMarc Zyngier break;
729f75b6d4SMarc Zyngier
739f75b6d4SMarc Zyngier case SYS_ID_AA64MMFR0_EL1:
740a5d2843SMarc Zyngier /* Hide ECV, ExS, Secure Memory */
750a5d2843SMarc Zyngier val &= ~(NV_FTR(MMFR0, ECV) |
760a5d2843SMarc Zyngier NV_FTR(MMFR0, EXS) |
779f75b6d4SMarc Zyngier NV_FTR(MMFR0, TGRAN4_2) |
789f75b6d4SMarc Zyngier NV_FTR(MMFR0, TGRAN16_2) |
799f75b6d4SMarc Zyngier NV_FTR(MMFR0, TGRAN64_2) |
809f75b6d4SMarc Zyngier NV_FTR(MMFR0, SNSMEM));
819f75b6d4SMarc Zyngier
829f75b6d4SMarc Zyngier /* Disallow unsupported S2 page sizes */
839f75b6d4SMarc Zyngier switch (PAGE_SIZE) {
849f75b6d4SMarc Zyngier case SZ_64K:
859f75b6d4SMarc Zyngier val |= FIELD_PREP(NV_FTR(MMFR0, TGRAN16_2), 0b0001);
869f75b6d4SMarc Zyngier fallthrough;
879f75b6d4SMarc Zyngier case SZ_16K:
889f75b6d4SMarc Zyngier val |= FIELD_PREP(NV_FTR(MMFR0, TGRAN4_2), 0b0001);
899f75b6d4SMarc Zyngier fallthrough;
909f75b6d4SMarc Zyngier case SZ_4K:
919f75b6d4SMarc Zyngier /* Support everything */
929f75b6d4SMarc Zyngier break;
939f75b6d4SMarc Zyngier }
949f75b6d4SMarc Zyngier /*
959f75b6d4SMarc Zyngier * Since we can't support a guest S2 page size smaller than
969f75b6d4SMarc Zyngier * the host's own page size (due to KVM only populating its
979f75b6d4SMarc Zyngier * own S2 using the kernel's page size), advertise the
989f75b6d4SMarc Zyngier * limitation using FEAT_GTG.
999f75b6d4SMarc Zyngier */
1009f75b6d4SMarc Zyngier switch (PAGE_SIZE) {
1019f75b6d4SMarc Zyngier case SZ_4K:
1029f75b6d4SMarc Zyngier val |= FIELD_PREP(NV_FTR(MMFR0, TGRAN4_2), 0b0010);
1039f75b6d4SMarc Zyngier fallthrough;
1049f75b6d4SMarc Zyngier case SZ_16K:
1059f75b6d4SMarc Zyngier val |= FIELD_PREP(NV_FTR(MMFR0, TGRAN16_2), 0b0010);
1069f75b6d4SMarc Zyngier fallthrough;
1079f75b6d4SMarc Zyngier case SZ_64K:
1089f75b6d4SMarc Zyngier val |= FIELD_PREP(NV_FTR(MMFR0, TGRAN64_2), 0b0010);
1099f75b6d4SMarc Zyngier break;
1109f75b6d4SMarc Zyngier }
1119f75b6d4SMarc Zyngier /* Cap PARange to 48bits */
1129f75b6d4SMarc Zyngier tmp = FIELD_GET(NV_FTR(MMFR0, PARANGE), val);
1139f75b6d4SMarc Zyngier if (tmp > 0b0101) {
1149f75b6d4SMarc Zyngier val &= ~NV_FTR(MMFR0, PARANGE);
1159f75b6d4SMarc Zyngier val |= FIELD_PREP(NV_FTR(MMFR0, PARANGE), 0b0101);
1169f75b6d4SMarc Zyngier }
1179f75b6d4SMarc Zyngier break;
1189f75b6d4SMarc Zyngier
1199f75b6d4SMarc Zyngier case SYS_ID_AA64MMFR1_EL1:
120*03fb54d0SMarc Zyngier val &= (NV_FTR(MMFR1, HCX) |
121*03fb54d0SMarc Zyngier NV_FTR(MMFR1, PAN) |
1229f75b6d4SMarc Zyngier NV_FTR(MMFR1, LO) |
1239f75b6d4SMarc Zyngier NV_FTR(MMFR1, HPDS) |
1249f75b6d4SMarc Zyngier NV_FTR(MMFR1, VH) |
1259f75b6d4SMarc Zyngier NV_FTR(MMFR1, VMIDBits));
1269f75b6d4SMarc Zyngier break;
1279f75b6d4SMarc Zyngier
1289f75b6d4SMarc Zyngier case SYS_ID_AA64MMFR2_EL1:
129a0b70fb0SMarc Zyngier val &= ~(NV_FTR(MMFR2, BBM) |
1309f75b6d4SMarc Zyngier NV_FTR(MMFR2, TTL) |
1319f75b6d4SMarc Zyngier GENMASK_ULL(47, 44) |
1329f75b6d4SMarc Zyngier NV_FTR(MMFR2, ST) |
1339f75b6d4SMarc Zyngier NV_FTR(MMFR2, CCIDX) |
1349f75b6d4SMarc Zyngier NV_FTR(MMFR2, VARange));
1359f75b6d4SMarc Zyngier
1369f75b6d4SMarc Zyngier /* Force TTL support */
1379f75b6d4SMarc Zyngier val |= FIELD_PREP(NV_FTR(MMFR2, TTL), 0b0001);
1389f75b6d4SMarc Zyngier break;
1399f75b6d4SMarc Zyngier
1409f75b6d4SMarc Zyngier case SYS_ID_AA64DFR0_EL1:
1419f75b6d4SMarc Zyngier /* Only limited support for PMU, Debug, BPs and WPs */
1429f75b6d4SMarc Zyngier val &= (NV_FTR(DFR0, PMUVer) |
1439f75b6d4SMarc Zyngier NV_FTR(DFR0, WRPs) |
1449f75b6d4SMarc Zyngier NV_FTR(DFR0, BRPs) |
1459f75b6d4SMarc Zyngier NV_FTR(DFR0, DebugVer));
1469f75b6d4SMarc Zyngier
1479f75b6d4SMarc Zyngier /* Cap Debug to ARMv8.1 */
1489f75b6d4SMarc Zyngier tmp = FIELD_GET(NV_FTR(DFR0, DebugVer), val);
1499f75b6d4SMarc Zyngier if (tmp > 0b0111) {
1509f75b6d4SMarc Zyngier val &= ~NV_FTR(DFR0, DebugVer);
1519f75b6d4SMarc Zyngier val |= FIELD_PREP(NV_FTR(DFR0, DebugVer), 0b0111);
1529f75b6d4SMarc Zyngier }
1539f75b6d4SMarc Zyngier break;
1549f75b6d4SMarc Zyngier
1559f75b6d4SMarc Zyngier default:
1569f75b6d4SMarc Zyngier /* Unknown register, just wipe it clean */
1579f75b6d4SMarc Zyngier val = 0;
1589f75b6d4SMarc Zyngier break;
1599f75b6d4SMarc Zyngier }
1609f75b6d4SMarc Zyngier
1619f75b6d4SMarc Zyngier p->regval = val;
1629f75b6d4SMarc Zyngier }
163