xref: /openbmc/linux/arch/arm64/kvm/nested.c (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
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