kvm.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC v3 00/12] kvm: arm64: emulate ID registers
@ 2020-11-02  3:34 Peng Liang
  2020-11-02  3:34 ` [RFC v3 01/12] arm64: Add a helper function to traverse arm64_ftr_regs Peng Liang
                   ` (11 more replies)
  0 siblings, 12 replies; 13+ messages in thread
From: Peng Liang @ 2020-11-02  3:34 UTC (permalink / raw)
  To: kvmarm
  Cc: kvm, maz, will, drjones, zhang.zhanghailiang, xiexiangyou, Peng Liang

In AArch64, guest will read the same values of the ID regsiters with
host.  Both of them read the values from arm64_ftr_regs.  This patch
series add support to emulate and configure ID registers so that we can
control the value of ID registers that guest read.

v2 -> v3:
 - remove check_user and split some set_user for some ID registers
 - check the consistency of ID registers of vCPUS
 - add more doc for the limits

v1 -> v2:
 - save the ID registers in sysreg file instead of a new struct
 - apply a checker before setting the value to the register
 - add doc for new KVM_CAP_ARM_CPU_FEATURE

Peng Liang (12):
  arm64: Add a helper function to traverse arm64_ftr_regs
  arm64: Introduce check_features
  kvm: arm64: Save ID registers to sys_regs file
  kvm: arm64: Make ID_AA64PFR0_EL1 configurable
  kvm: arm64: Make ID_AA64DFR0_EL1 configurable
  kvm: arm64: Make ID_AA64ISAR0_EL1 configurable
  kvm: arm64: Make ID_AA64ISAR1_EL1 configurable
  kvm: arm64: Make ID_DFR0_EL1 configurable
  kvm: arm64: Make MVFR1_EL1 configurable
  kvm: arm64: Make other ID registers configurable
  kvm: arm64: Check consistent of ID register
  kvm: arm64: add KVM_CAP_ARM_CPU_FEATURE extension

 Documentation/virt/kvm/api.rst      |  36 ++++
 arch/arm64/include/asm/cpufeature.h |   4 +
 arch/arm64/include/asm/kvm_coproc.h |   2 +
 arch/arm64/include/asm/kvm_host.h   |   9 +
 arch/arm64/kernel/cpufeature.c      |  36 ++++
 arch/arm64/kvm/arm.c                |  22 +++
 arch/arm64/kvm/sys_regs.c           | 272 ++++++++++++++++++++++++++--
 include/uapi/linux/kvm.h            |   1 +
 8 files changed, 365 insertions(+), 17 deletions(-)

-- 
2.26.2


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [RFC v3 01/12] arm64: Add a helper function to traverse arm64_ftr_regs
  2020-11-02  3:34 [RFC v3 00/12] kvm: arm64: emulate ID registers Peng Liang
@ 2020-11-02  3:34 ` Peng Liang
  2020-11-02  3:34 ` [RFC v3 02/12] arm64: Introduce check_features Peng Liang
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Peng Liang @ 2020-11-02  3:34 UTC (permalink / raw)
  To: kvmarm
  Cc: kvm, maz, will, drjones, zhang.zhanghailiang, xiexiangyou, Peng Liang

If we want to emulate ID registers, we need to initialize ID registers
firstly.  This commit is to add a helper function to traverse
arm64_ftr_regs so that we can initialize ID registers from
arm64_ftr_regs.

Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
Signed-off-by: Peng Liang <liangpeng10@huawei.com>
---
 arch/arm64/include/asm/cpufeature.h |  2 ++
 arch/arm64/kernel/cpufeature.c      | 13 +++++++++++++
 2 files changed, 15 insertions(+)

diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index f7e7144af174..8ea2c4307708 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -79,6 +79,8 @@ struct arm64_ftr_reg {
 
 extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
 
+int arm64_cpu_ftr_regs_traverse(int (*op)(u32, u64, void *), void *argp);
+
 /*
  * CPU capabilities:
  *
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index dcc165b3fc04..6e31d3fbd791 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -2855,3 +2855,16 @@ ssize_t cpu_show_meltdown(struct device *dev, struct device_attribute *attr,
 
 	return sprintf(buf, "Vulnerable\n");
 }
+
+int arm64_cpu_ftr_regs_traverse(int (*op)(u32, u64, void *), void *argp)
+{
+	int i, ret;
+
+	for (i = 0; i <  ARRAY_SIZE(arm64_ftr_regs); i++) {
+		ret = (*op)(arm64_ftr_regs[i].sys_id,
+			    arm64_ftr_regs[i].reg->sys_val, argp);
+		if (ret < 0)
+			return ret;
+	}
+	return 0;
+}
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [RFC v3 02/12] arm64: Introduce check_features
  2020-11-02  3:34 [RFC v3 00/12] kvm: arm64: emulate ID registers Peng Liang
  2020-11-02  3:34 ` [RFC v3 01/12] arm64: Add a helper function to traverse arm64_ftr_regs Peng Liang
@ 2020-11-02  3:34 ` Peng Liang
  2020-11-02  3:34 ` [RFC v3 03/12] kvm: arm64: Save ID registers to sys_regs file Peng Liang
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Peng Liang @ 2020-11-02  3:34 UTC (permalink / raw)
  To: kvmarm
  Cc: kvm, maz, will, drjones, zhang.zhanghailiang, xiexiangyou, Peng Liang

To emulate ID registers, we need to validate the value of the register
defined by user space.  For most ID registers, we need to check whether
each field defined by user space is no more than that of host (whether
host support the corresponding features) and whether the fields are
supposed to be exposed to guest.  Introduce check_features to do those
jobs.

Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
Signed-off-by: Peng Liang <liangpeng10@huawei.com>
---
 arch/arm64/include/asm/cpufeature.h |  2 ++
 arch/arm64/kernel/cpufeature.c      | 23 +++++++++++++++++++++++
 2 files changed, 25 insertions(+)

diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index 8ea2c4307708..e0e5dcffe58a 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -579,6 +579,8 @@ void check_local_cpu_capabilities(void);
 
 u64 read_sanitised_ftr_reg(u32 id);
 
+int check_features(u32 sys_reg, u64 val);
+
 static inline bool cpu_supports_mixed_endian_el0(void)
 {
 	return id_aa64mmfr0_mixed_endian_el0(read_cpuid(ID_AA64MMFR0_EL1));
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 6e31d3fbd791..f78cd50a1980 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -2868,3 +2868,26 @@ int arm64_cpu_ftr_regs_traverse(int (*op)(u32, u64, void *), void *argp)
 	}
 	return 0;
 }
+
+int check_features(u32 sys_reg, u64 val)
+{
+	struct arm64_ftr_reg *reg = get_arm64_ftr_reg(sys_reg);
+	const struct arm64_ftr_bits *ftrp;
+	u64 exposed_mask = 0;
+
+	if (!reg)
+		return -ENOENT;
+
+	for (ftrp = reg->ftr_bits; ftrp->width; ftrp++) {
+		if (arm64_ftr_value(ftrp, reg->sys_val) <
+		    arm64_ftr_value(ftrp, val)) {
+			return -EINVAL;
+		}
+		exposed_mask |= arm64_ftr_mask(ftrp);
+	}
+
+	if (val & ~exposed_mask)
+		return -EINVAL;
+
+	return 0;
+}
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [RFC v3 03/12] kvm: arm64: Save ID registers to sys_regs file
  2020-11-02  3:34 [RFC v3 00/12] kvm: arm64: emulate ID registers Peng Liang
  2020-11-02  3:34 ` [RFC v3 01/12] arm64: Add a helper function to traverse arm64_ftr_regs Peng Liang
  2020-11-02  3:34 ` [RFC v3 02/12] arm64: Introduce check_features Peng Liang
@ 2020-11-02  3:34 ` Peng Liang
  2020-11-02  3:34 ` [RFC v3 04/12] kvm: arm64: Make ID_AA64PFR0_EL1 configurable Peng Liang
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Peng Liang @ 2020-11-02  3:34 UTC (permalink / raw)
  To: kvmarm
  Cc: kvm, maz, will, drjones, zhang.zhanghailiang, xiexiangyou, Peng Liang

To emulate the ID registers, we need a place to storage the values of
the ID regsiters.  Maybe putting them in sysreg file is a good idea.

This commit has no functional changes but only code refactor.  When
initializing a vCPU, get the values of the ID registers from
arm64_ftr_regs and storage them in sysreg file.  And we just read
the value from sysreg file when getting/setting the value of the ID
regs.

Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
Signed-off-by: Peng Liang <liangpeng10@huawei.com>
---
 arch/arm64/include/asm/kvm_coproc.h |  2 ++
 arch/arm64/include/asm/kvm_host.h   |  9 ++++++++
 arch/arm64/kvm/arm.c                |  2 ++
 arch/arm64/kvm/sys_regs.c           | 33 +++++++++++++++++++++++++----
 4 files changed, 42 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_coproc.h b/arch/arm64/include/asm/kvm_coproc.h
index d6bb40122fdb..76e8c3cb0662 100644
--- a/arch/arm64/include/asm/kvm_coproc.h
+++ b/arch/arm64/include/asm/kvm_coproc.h
@@ -35,4 +35,6 @@ int kvm_arm_sys_reg_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *);
 int kvm_arm_sys_reg_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *);
 unsigned long kvm_arm_num_sys_reg_descs(struct kvm_vcpu *vcpu);
 
+void kvm_arm_sys_reg_init(struct kvm_vcpu *vcpu);
+
 #endif /* __ARM64_KVM_COPROC_H__ */
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 0aecbab6a7fb..1b18c53f519a 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -40,6 +40,12 @@
 
 #define KVM_VCPU_MAX_FEATURES 7
 
+/*
+ * (Op0, Op1, CRn, CRm, Op2) of ID registers is (3, 0, 0, crm, op2), where
+ * 1<=crm<8, 0<=op2<8.  Hence, the max number of ID registers is 56.
+ */
+#define KVM_ARM_ID_REG_MAX_NUM 56
+
 #define KVM_REQ_SLEEP \
 	KVM_ARCH_REQ_FLAGS(0, KVM_REQUEST_WAIT | KVM_REQUEST_NO_WAKEUP)
 #define KVM_REQ_IRQ_PENDING	KVM_ARCH_REQ(1)
@@ -192,6 +198,9 @@ enum vcpu_sysreg {
 	CNTP_CVAL_EL0,
 	CNTP_CTL_EL0,
 
+	ID_REG_BASE,
+	ID_REG_END = ID_REG_BASE + KVM_ARM_ID_REG_MAX_NUM - 1,
+
 	/* 32bit specific registers. Keep them at the end of the range */
 	DACR32_EL2,	/* Domain Access Control Register */
 	IFSR32_EL2,	/* Instruction Fault Status Register */
diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index 8f8fca47abfc..5a153a109317 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -278,6 +278,8 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
 	if (err)
 		return err;
 
+	kvm_arm_sys_reg_init(vcpu);
+
 	return create_hyp_mappings(vcpu, vcpu + 1, PAGE_HYP);
 }
 
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 41348a7781d9..68ed83657c07 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -1116,13 +1116,16 @@ static bool access_arch_timer(struct kvm_vcpu *vcpu,
 	return true;
 }
 
+#define ID_REG_INDEX(id)						\
+	(ID_REG_BASE + (((sys_reg_CRm(id) - 1) << 3) | sys_reg_Op2(id)))
+
 /* Read a sanitised cpufeature ID register by sys_reg_desc */
-static u64 read_id_reg(const struct kvm_vcpu *vcpu,
+static u64 read_id_reg(struct kvm_vcpu *vcpu,
 		struct sys_reg_desc const *r, bool raz)
 {
 	u32 id = sys_reg((u32)r->Op0, (u32)r->Op1,
 			 (u32)r->CRn, (u32)r->CRm, (u32)r->Op2);
-	u64 val = raz ? 0 : read_sanitised_ftr_reg(id);
+	u64 val = raz ? 0 : __vcpu_sys_reg(vcpu, ID_REG_INDEX(id));
 
 	if (id == SYS_ID_AA64PFR0_EL1) {
 		if (!vcpu_has_sve(vcpu))
@@ -1267,7 +1270,7 @@ static int set_id_aa64zfr0_el1(struct kvm_vcpu *vcpu,
  * are stored, and for set_id_reg() we don't allow the effective value
  * to be changed.
  */
-static int __get_id_reg(const struct kvm_vcpu *vcpu,
+static int __get_id_reg(struct kvm_vcpu *vcpu,
 			const struct sys_reg_desc *rd, void __user *uaddr,
 			bool raz)
 {
@@ -1277,7 +1280,7 @@ static int __get_id_reg(const struct kvm_vcpu *vcpu,
 	return reg_to_user(uaddr, &val, id);
 }
 
-static int __set_id_reg(const struct kvm_vcpu *vcpu,
+static int __set_id_reg(struct kvm_vcpu *vcpu,
 			const struct sys_reg_desc *rd, void __user *uaddr,
 			bool raz)
 {
@@ -2870,3 +2873,25 @@ void kvm_sys_reg_table_init(void)
 	/* Clear all higher bits. */
 	cache_levels &= (1 << (i*3))-1;
 }
+
+static int save_id_reg(u32 id, u64 val, void *argp)
+{
+	struct kvm_vcpu *vcpu = argp;
+
+	/*
+	 * (Op0, Op1, CRn, CRm, Op2) of ID registers is (3, 0, 0, crm, op2),
+	 * where 1<=crm<8, 0<=op2<8.
+	 */
+	if (sys_reg_Op0(id) == 3 && sys_reg_Op1(id) == 0 &&
+	    sys_reg_CRn(id) == 0 && sys_reg_CRm(id) > 0 &&
+	    sys_reg_CRm(id) < 8) {
+		__vcpu_sys_reg(vcpu, ID_REG_INDEX(id)) = val;
+	}
+
+	return 0;
+}
+
+void kvm_arm_sys_reg_init(struct kvm_vcpu *vcpu)
+{
+	arm64_cpu_ftr_regs_traverse(save_id_reg, vcpu);
+}
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [RFC v3 04/12] kvm: arm64: Make ID_AA64PFR0_EL1 configurable
  2020-11-02  3:34 [RFC v3 00/12] kvm: arm64: emulate ID registers Peng Liang
                   ` (2 preceding siblings ...)
  2020-11-02  3:34 ` [RFC v3 03/12] kvm: arm64: Save ID registers to sys_regs file Peng Liang
@ 2020-11-02  3:34 ` Peng Liang
  2020-11-02  3:34 ` [RFC v3 05/12] kvm: arm64: Make ID_AA64DFR0_EL1 configurable Peng Liang
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Peng Liang @ 2020-11-02  3:34 UTC (permalink / raw)
  To: kvmarm
  Cc: kvm, maz, will, drjones, zhang.zhanghailiang, xiexiangyou, Peng Liang

Except CSV2, which is allowed to set 1 if the value of host is 0, each
ID field should be not greater than that of host.  And FP and AdvSIMD
must have the same value.

Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
Signed-off-by: Peng Liang <liangpeng10@huawei.com>
---
 arch/arm64/kvm/sys_regs.c | 46 ++++++++++++++++++++++++++++++++++++++-
 1 file changed, 45 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 68ed83657c07..bcc57cbe0421 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -1323,6 +1323,50 @@ static int set_raz_id_reg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd,
 	return __set_id_reg(vcpu, rd, uaddr, true);
 }
 
+static int set_id_aa64pfr0_el1(struct kvm_vcpu *vcpu,
+		const struct sys_reg_desc *rd,
+		const struct kvm_one_reg *reg, void __user *uaddr)
+{
+	u32 reg_id = sys_reg((u32)rd->Op0, (u32)rd->Op1, (u32)rd->CRn,
+			     (u32)rd->CRm, (u32)rd->Op2);
+	int err;
+	u64 val, host_val, tmp_val;
+	unsigned int fp, asimd;
+
+	err = reg_from_user(&val, uaddr, sys_reg_to_index(rd));
+	if (err)
+		return err;
+
+	/*
+	 * If the hardware is not affected by Spectre-v2 and doesn't support
+	 * CSV2 but userspace set CSV2 to 1, we can ignore it when checking.
+	 */
+	host_val = read_sanitised_ftr_reg(reg_id);
+	tmp_val = val;
+	if (arm64_get_spectre_v2_state() == SPECTRE_UNAFFECTED &&
+	    !cpuid_feature_extract_unsigned_field(host_val, ID_AA64PFR0_CSV2_SHIFT) &&
+	    cpuid_feature_extract_unsigned_field(tmp_val, ID_AA64PFR0_CSV2_SHIFT) == 1) {
+		tmp_val &= ~(0xfULL << ID_AA64PFR0_CSV2_SHIFT);
+	}
+	err = check_features(reg_id, tmp_val);
+	if (err)
+		return err;
+
+	fp = cpuid_feature_extract_signed_field(val, ID_AA64PFR0_FP_SHIFT);
+	asimd = cpuid_feature_extract_signed_field(val, ID_AA64PFR0_ASIMD_SHIFT);
+	if (fp != asimd)
+		return -EINVAL;
+
+	if (!vcpu_has_sve(vcpu) &&
+	    cpuid_feature_extract_unsigned_field(val, ID_AA64PFR0_SVE_SHIFT))
+		return -EINVAL;
+	if (cpuid_feature_extract_unsigned_field(val, ID_AA64PFR0_AMU_SHIFT))
+		return -EINVAL;
+
+	__vcpu_sys_reg(vcpu, ID_REG_INDEX(reg_id)) = val;
+	return 0;
+}
+
 static bool access_ctr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
 		       const struct sys_reg_desc *r)
 {
@@ -1517,7 +1561,7 @@ static const struct sys_reg_desc sys_reg_descs[] = {
 
 	/* AArch64 ID registers */
 	/* CRm=4 */
-	ID_SANITISED(ID_AA64PFR0_EL1),
+	{ SYS_DESC(SYS_ID_AA64PFR0_EL1), access_id_reg, .get_user = get_id_reg, .set_user = set_id_aa64pfr0_el1 },
 	ID_SANITISED(ID_AA64PFR1_EL1),
 	ID_UNALLOCATED(4,2),
 	ID_UNALLOCATED(4,3),
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [RFC v3 05/12] kvm: arm64: Make ID_AA64DFR0_EL1 configurable
  2020-11-02  3:34 [RFC v3 00/12] kvm: arm64: emulate ID registers Peng Liang
                   ` (3 preceding siblings ...)
  2020-11-02  3:34 ` [RFC v3 04/12] kvm: arm64: Make ID_AA64PFR0_EL1 configurable Peng Liang
@ 2020-11-02  3:34 ` Peng Liang
  2020-11-02  3:34 ` [RFC v3 06/12] kvm: arm64: Make ID_AA64ISAR0_EL1 configurable Peng Liang
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Peng Liang @ 2020-11-02  3:34 UTC (permalink / raw)
  To: kvmarm
  Cc: kvm, maz, will, drjones, zhang.zhanghailiang, xiexiangyou, Peng Liang

Except that each ID field should be not greater than that of host,
PMUVer must be 0b0100 (PMUv3 for Armv8.1).

Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
Signed-off-by: Peng Liang <liangpeng10@huawei.com>
---
 arch/arm64/kvm/sys_regs.c | 28 +++++++++++++++++++++++++++-
 1 file changed, 27 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index bcc57cbe0421..3954b7a21a4b 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -1367,6 +1367,32 @@ static int set_id_aa64pfr0_el1(struct kvm_vcpu *vcpu,
 	return 0;
 }
 
+static int set_id_aa64dfr0_el1(struct kvm_vcpu *vcpu,
+		const struct sys_reg_desc *rd,
+		const struct kvm_one_reg *reg, void __user *uaddr)
+{
+	u32 reg_id = sys_reg((u32)rd->Op0, (u32)rd->Op1, (u32)rd->CRn,
+			     (u32)rd->CRm, (u32)rd->Op2);
+	int err;
+	u64 val;
+
+	err = reg_from_user(&val, uaddr, sys_reg_to_index(rd));
+	if (err)
+		return err;
+
+	err = check_features(reg_id, val);
+	if (err)
+		return err;
+
+	/* Limit guests to PMUv3 for ARMv8.1 */
+	if (cpuid_feature_extract_signed_field(val, ID_AA64DFR0_PMUVER_SHIFT) !=
+	    ID_AA64DFR0_PMUVER_8_1)
+		return -EINVAL;
+
+	__vcpu_sys_reg(vcpu, ID_REG_INDEX(reg_id)) = val;
+	return 0;
+}
+
 static bool access_ctr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
 		       const struct sys_reg_desc *r)
 {
@@ -1571,7 +1597,7 @@ static const struct sys_reg_desc sys_reg_descs[] = {
 	ID_UNALLOCATED(4,7),
 
 	/* CRm=5 */
-	ID_SANITISED(ID_AA64DFR0_EL1),
+	{ SYS_DESC(SYS_ID_AA64DFR0_EL1), access_id_reg, .get_user = get_id_reg, .set_user = set_id_aa64dfr0_el1 },
 	ID_SANITISED(ID_AA64DFR1_EL1),
 	ID_UNALLOCATED(5,2),
 	ID_UNALLOCATED(5,3),
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [RFC v3 06/12] kvm: arm64: Make ID_AA64ISAR0_EL1 configurable
  2020-11-02  3:34 [RFC v3 00/12] kvm: arm64: emulate ID registers Peng Liang
                   ` (4 preceding siblings ...)
  2020-11-02  3:34 ` [RFC v3 05/12] kvm: arm64: Make ID_AA64DFR0_EL1 configurable Peng Liang
@ 2020-11-02  3:34 ` Peng Liang
  2020-11-02  3:34 ` [RFC v3 07/12] kvm: arm64: Make ID_AA64ISAR1_EL1 configurable Peng Liang
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Peng Liang @ 2020-11-02  3:34 UTC (permalink / raw)
  To: kvmarm
  Cc: kvm, maz, will, drjones, zhang.zhanghailiang, xiexiangyou, Peng Liang

Except that each ID field should be not greater than that of host, SM3
and SM4 must have the same value; if the value of SHA1 is 0, then SHA2
must have the value 0, and vice versa; if the value of SHA2 is 2, then
SHA3 must have the value 1, and vice versa; if the value of SHA1 is 0,
then SHA3 must have the value 0.

Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
Signed-off-by: Peng Liang <liangpeng10@huawei.com>
---
 arch/arm64/kvm/sys_regs.c | 46 ++++++++++++++++++++++++++++++++++++++-
 1 file changed, 45 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 3954b7a21a4b..76b39cab50b8 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -1393,6 +1393,50 @@ static int set_id_aa64dfr0_el1(struct kvm_vcpu *vcpu,
 	return 0;
 }
 
+static int set_id_aa64isar0_el1(struct kvm_vcpu *vcpu,
+		const struct sys_reg_desc *rd,
+		const struct kvm_one_reg *reg, void __user *uaddr)
+{
+	u32 reg_id = sys_reg((u32)rd->Op0, (u32)rd->Op1, (u32)rd->CRn,
+			     (u32)rd->CRm, (u32)rd->Op2);
+	int err;
+	u64 val;
+	unsigned int sm3, sm4, sha1, sha2, sha3;
+
+	err = reg_from_user(&val, uaddr, sys_reg_to_index(rd));
+	if (err)
+		return err;
+	err = check_features(reg_id, val);
+	if (err)
+		return err;
+
+	sm3 = cpuid_feature_extract_unsigned_field(val, ID_AA64ISAR0_SM3_SHIFT);
+	sm4 = cpuid_feature_extract_unsigned_field(val, ID_AA64ISAR0_SM4_SHIFT);
+	/*
+	 * ID_AA64ISAR0_EL1.SM3 and ID_AA64ISAR0_EL1.SM4 must have the same
+	 * value.
+	 */
+	if (sm3 != sm4)
+		return -EINVAL;
+
+	sha1 = cpuid_feature_extract_unsigned_field(val, ID_AA64ISAR0_SHA1_SHIFT);
+	sha2 = cpuid_feature_extract_unsigned_field(val, ID_AA64ISAR0_SHA2_SHIFT);
+	sha3 = cpuid_feature_extract_unsigned_field(val, ID_AA64ISAR0_SHA3_SHIFT);
+	/*
+	 * 1. If the value of ID_AA64ISAR0_EL1.SHA1 is 0, then
+	 *    ID_AA64ISAR0_EL1.SHA2 must have the value 0, and vice versa;
+	 * 2. If the value of ID_AA64ISAR0_EL1.SHA2 is 2, then
+	 *    ID_AA64ISAR0_EL1.SHA3 must have the value 1, and vice versa;
+	 * 3. If the value of ID_AA64ISAR0_EL1.SHA1 is 0, then
+	 *    ID_AA64ISAR0_EL1.SHA3 must have the value 0;
+	 */
+	if ((sha1 ^ sha2) || ((sha2 == 2) ^ (sha3 == 1)) || (!sha1 && sha3))
+		return -EINVAL;
+
+	__vcpu_sys_reg(vcpu, ID_REG_INDEX(reg_id)) = val;
+	return 0;
+}
+
 static bool access_ctr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
 		       const struct sys_reg_desc *r)
 {
@@ -1607,7 +1651,7 @@ static const struct sys_reg_desc sys_reg_descs[] = {
 	ID_UNALLOCATED(5,7),
 
 	/* CRm=6 */
-	ID_SANITISED(ID_AA64ISAR0_EL1),
+	{ SYS_DESC(SYS_ID_AA64ISAR0_EL1), access_id_reg, .get_user = get_id_reg, .set_user = set_id_aa64isar0_el1 },
 	ID_SANITISED(ID_AA64ISAR1_EL1),
 	ID_UNALLOCATED(6,2),
 	ID_UNALLOCATED(6,3),
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [RFC v3 07/12] kvm: arm64: Make ID_AA64ISAR1_EL1 configurable
  2020-11-02  3:34 [RFC v3 00/12] kvm: arm64: emulate ID registers Peng Liang
                   ` (5 preceding siblings ...)
  2020-11-02  3:34 ` [RFC v3 06/12] kvm: arm64: Make ID_AA64ISAR0_EL1 configurable Peng Liang
@ 2020-11-02  3:34 ` Peng Liang
  2020-11-02  3:34 ` [RFC v3 08/12] kvm: arm64: Make ID_DFR0_EL1 configurable Peng Liang
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Peng Liang @ 2020-11-02  3:34 UTC (permalink / raw)
  To: kvmarm
  Cc: kvm, maz, will, drjones, zhang.zhanghailiang, xiexiangyou, Peng Liang

Except that each ID field should be not greater than that of host, if
the vCPU has not enabled Generic Pointer authentication, then GPA, GPI,
APA, and API must be 0.  Otherwise, GPA and GPI are exclusive; APA and
API are exclusive.

Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
Signed-off-by: Peng Liang <liangpeng10@huawei.com>
---
 arch/arm64/kvm/sys_regs.c | 42 ++++++++++++++++++++++++++++++++++++++-
 1 file changed, 41 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 76b39cab50b8..2ea165d09c7b 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -1437,6 +1437,46 @@ static int set_id_aa64isar0_el1(struct kvm_vcpu *vcpu,
 	return 0;
 }
 
+static int set_id_aa64isar1_el1(struct kvm_vcpu *vcpu,
+		const struct sys_reg_desc *rd,
+		const struct kvm_one_reg *reg, void __user *uaddr)
+{
+	u32 reg_id = sys_reg((u32)rd->Op0, (u32)rd->Op1, (u32)rd->CRn,
+			     (u32)rd->CRm, (u32)rd->Op2);
+	int err;
+	u64 val;
+	unsigned int gpi, gpa, api, apa;
+
+	err = reg_from_user(&val, uaddr, sys_reg_to_index(rd));
+	if (err)
+		return err;
+	err = check_features(reg_id, val);
+	if (err)
+		return err;
+
+	gpi = cpuid_feature_extract_unsigned_field(val, ID_AA64ISAR1_GPI_SHIFT);
+	gpa = cpuid_feature_extract_unsigned_field(val, ID_AA64ISAR1_GPA_SHIFT);
+	api = cpuid_feature_extract_unsigned_field(val, ID_AA64ISAR1_API_SHIFT);
+	apa = cpuid_feature_extract_unsigned_field(val, ID_AA64ISAR1_APA_SHIFT);
+	if (!vcpu_has_ptrauth(vcpu) && (gpa || gpi || apa || api))
+		return -EINVAL;
+	/*
+	 * 1. If the value of ID_AA64ISAR1_EL1.GPA is non-zero, then
+	 *    ID_AA64ISAR1_EL1.GPI must have the value 0;
+	 * 2. If the value of ID_AA64ISAR1_EL1.GPI is non-zero, then
+	 *    ID_AA64ISAR1_EL1.GPA must have the value 0;
+	 * 3. If the value of ID_AA64ISAR1_EL1.APA is non-zero, then
+	 *    ID_AA64ISAR1_EL1.API must have the value 0;
+	 * 4. If the value of ID_AA64ISAR1_EL1.API is non-zero, then
+	 *    ID_AA64ISAR1_EL1.APA must have the value 0;
+	 */
+	if ((gpi && gpa) || (api && apa))
+		return -EINVAL;
+
+	__vcpu_sys_reg(vcpu, ID_REG_INDEX(reg_id)) = val;
+	return 0;
+}
+
 static bool access_ctr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
 		       const struct sys_reg_desc *r)
 {
@@ -1652,7 +1692,7 @@ static const struct sys_reg_desc sys_reg_descs[] = {
 
 	/* CRm=6 */
 	{ SYS_DESC(SYS_ID_AA64ISAR0_EL1), access_id_reg, .get_user = get_id_reg, .set_user = set_id_aa64isar0_el1 },
-	ID_SANITISED(ID_AA64ISAR1_EL1),
+	{ SYS_DESC(SYS_ID_AA64ISAR1_EL1), access_id_reg, .get_user = get_id_reg, .set_user = set_id_aa64isar1_el1 },
 	ID_UNALLOCATED(6,2),
 	ID_UNALLOCATED(6,3),
 	ID_UNALLOCATED(6,4),
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [RFC v3 08/12] kvm: arm64: Make ID_DFR0_EL1 configurable
  2020-11-02  3:34 [RFC v3 00/12] kvm: arm64: emulate ID registers Peng Liang
                   ` (6 preceding siblings ...)
  2020-11-02  3:34 ` [RFC v3 07/12] kvm: arm64: Make ID_AA64ISAR1_EL1 configurable Peng Liang
@ 2020-11-02  3:34 ` Peng Liang
  2020-11-02  3:34 ` [RFC v3 09/12] kvm: arm64: Make MVFR1_EL1 configurable Peng Liang
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Peng Liang @ 2020-11-02  3:34 UTC (permalink / raw)
  To: kvmarm
  Cc: kvm, maz, will, drjones, zhang.zhanghailiang, xiexiangyou, Peng Liang

Except that each ID field should be not greater than that of host,
PerfMon must be 0b0100 (PMUv3 for Armv8.1).

Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
Signed-off-by: Peng Liang <liangpeng10@huawei.com>
---
 arch/arm64/kvm/sys_regs.c | 28 +++++++++++++++++++++++++++-
 1 file changed, 27 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 2ea165d09c7b..aac62f6fa846 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -1323,6 +1323,32 @@ static int set_raz_id_reg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd,
 	return __set_id_reg(vcpu, rd, uaddr, true);
 }
 
+static int set_id_dfr0_el1(struct kvm_vcpu *vcpu,
+		const struct sys_reg_desc *rd,
+		const struct kvm_one_reg *reg, void __user *uaddr)
+{
+	u32 reg_id = sys_reg((u32)rd->Op0, (u32)rd->Op1, (u32)rd->CRn,
+			     (u32)rd->CRm, (u32)rd->Op2);
+	int err;
+	u64 val;
+
+	err = reg_from_user(&val, uaddr, sys_reg_to_index(rd));
+	if (err)
+		return err;
+
+	err = check_features(reg_id, val);
+	if (err)
+		return err;
+
+	/* Limit guests to PMUv3 for ARMv8.1 */
+	if (cpuid_feature_extract_signed_field(val, ID_DFR0_PERFMON_SHIFT) !=
+	    ID_DFR0_PERFMON_8_1)
+		return -EINVAL;
+
+	__vcpu_sys_reg(vcpu, ID_REG_INDEX(reg_id)) = val;
+	return 0;
+}
+
 static int set_id_aa64pfr0_el1(struct kvm_vcpu *vcpu,
 		const struct sys_reg_desc *rd,
 		const struct kvm_one_reg *reg, void __user *uaddr)
@@ -1642,7 +1668,7 @@ static const struct sys_reg_desc sys_reg_descs[] = {
 	/* CRm=1 */
 	ID_SANITISED(ID_PFR0_EL1),
 	ID_SANITISED(ID_PFR1_EL1),
-	ID_SANITISED(ID_DFR0_EL1),
+	{ SYS_DESC(SYS_ID_DFR0_EL1), access_id_reg, .get_user = get_id_reg, .set_user = set_id_dfr0_el1 },
 	ID_HIDDEN(ID_AFR0_EL1),
 	ID_SANITISED(ID_MMFR0_EL1),
 	ID_SANITISED(ID_MMFR1_EL1),
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [RFC v3 09/12] kvm: arm64: Make MVFR1_EL1 configurable
  2020-11-02  3:34 [RFC v3 00/12] kvm: arm64: emulate ID registers Peng Liang
                   ` (7 preceding siblings ...)
  2020-11-02  3:34 ` [RFC v3 08/12] kvm: arm64: Make ID_DFR0_EL1 configurable Peng Liang
@ 2020-11-02  3:34 ` Peng Liang
  2020-11-02  3:34 ` [RFC v3 10/12] kvm: arm64: Make other ID registers configurable Peng Liang
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Peng Liang @ 2020-11-02  3:34 UTC (permalink / raw)
  To: kvmarm
  Cc: kvm, maz, will, drjones, zhang.zhanghailiang, xiexiangyou, Peng Liang

Except that each ID field should be not greater than that of host, the
allowed value par of (FPHP, SIMDHP) are (0, 0), (2, 1), (3, 2).

Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
Signed-off-by: Peng Liang <liangpeng10@huawei.com>
---
 arch/arm64/kvm/sys_regs.c | 30 +++++++++++++++++++++++++++++-
 1 file changed, 29 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index aac62f6fa846..1bcfaf738491 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -1349,6 +1349,34 @@ static int set_id_dfr0_el1(struct kvm_vcpu *vcpu,
 	return 0;
 }
 
+static int set_mvfr1_el1(struct kvm_vcpu *vcpu,
+		const struct sys_reg_desc *rd,
+		const struct kvm_one_reg *reg, void __user *uaddr)
+{
+	u32 reg_id = sys_reg((u32)rd->Op0, (u32)rd->Op1, (u32)rd->CRn,
+			     (u32)rd->CRm, (u32)rd->Op2);
+	int err;
+	u64 val;
+	unsigned int fphp, simdhp;
+
+	err = reg_from_user(&val, uaddr, sys_reg_to_index(rd));
+	if (err)
+		return err;
+
+	err = check_features(reg_id, val);
+	if (err)
+		return err;
+
+	fphp = cpuid_feature_extract_unsigned_field(val, MVFR1_FPHP_SHIFT);
+	simdhp = cpuid_feature_extract_unsigned_field(val, MVFR1_SIMDHP_SHIFT);
+	if (!((fphp == 0 && simdhp == 0) || (fphp == 2 && simdhp == 1) ||
+	      (fphp == 3 && simdhp == 2)))
+		return -EINVAL;
+
+	__vcpu_sys_reg(vcpu, ID_REG_INDEX(reg_id)) = val;
+	return 0;
+}
+
 static int set_id_aa64pfr0_el1(struct kvm_vcpu *vcpu,
 		const struct sys_reg_desc *rd,
 		const struct kvm_one_reg *reg, void __user *uaddr)
@@ -1687,7 +1715,7 @@ static const struct sys_reg_desc sys_reg_descs[] = {
 
 	/* CRm=3 */
 	ID_SANITISED(MVFR0_EL1),
-	ID_SANITISED(MVFR1_EL1),
+	{ SYS_DESC(SYS_MVFR1_EL1), access_id_reg, .get_user = get_id_reg, .set_user = set_mvfr1_el1 },
 	ID_SANITISED(MVFR2_EL1),
 	ID_UNALLOCATED(3,3),
 	ID_SANITISED(ID_PFR2_EL1),
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [RFC v3 10/12] kvm: arm64: Make other ID registers configurable
  2020-11-02  3:34 [RFC v3 00/12] kvm: arm64: emulate ID registers Peng Liang
                   ` (8 preceding siblings ...)
  2020-11-02  3:34 ` [RFC v3 09/12] kvm: arm64: Make MVFR1_EL1 configurable Peng Liang
@ 2020-11-02  3:34 ` Peng Liang
  2020-11-02  3:34 ` [RFC v3 11/12] kvm: arm64: Check consistent of ID register Peng Liang
  2020-11-02  3:34 ` [RFC v3 12/12] kvm: arm64: add KVM_CAP_ARM_CPU_FEATURE extension Peng Liang
  11 siblings, 0 replies; 13+ messages in thread
From: Peng Liang @ 2020-11-02  3:34 UTC (permalink / raw)
  To: kvmarm
  Cc: kvm, maz, will, drjones, zhang.zhanghailiang, xiexiangyou, Peng Liang

For other ID registers, we only need to check that each ID field is no
greater than that of host (host support corresponding feature).

Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
Signed-off-by: Peng Liang <liangpeng10@huawei.com>
---
 arch/arm64/kvm/sys_regs.c | 19 ++++++++++++-------
 1 file changed, 12 insertions(+), 7 deletions(-)

diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 1bcfaf738491..42880800941a 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -1265,10 +1265,6 @@ static int set_id_aa64zfr0_el1(struct kvm_vcpu *vcpu,
 
 /*
  * cpufeature ID register user accessors
- *
- * For now, these registers are immutable for userspace, so no values
- * are stored, and for set_id_reg() we don't allow the effective value
- * to be changed.
  */
 static int __get_id_reg(struct kvm_vcpu *vcpu,
 			const struct sys_reg_desc *rd, void __user *uaddr,
@@ -1292,9 +1288,18 @@ static int __set_id_reg(struct kvm_vcpu *vcpu,
 	if (err)
 		return err;
 
-	/* This is what we mean by invariant: you can't change it. */
-	if (val != read_id_reg(vcpu, rd, raz))
-		return -EINVAL;
+	if (raz) {
+		if (val != 0)
+			return -EINVAL;
+	} else {
+		u32 reg_id = sys_reg((u32)rd->Op0, (u32)rd->Op1, (u32)rd->CRn,
+				     (u32)rd->CRm, (u32)rd->Op2);
+
+		err = check_features(reg_id, val);
+		if (err)
+			return err;
+		__vcpu_sys_reg(vcpu, ID_REG_INDEX(reg_id)) = val;
+	}
 
 	return 0;
 }
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [RFC v3 11/12] kvm: arm64: Check consistent of ID register
  2020-11-02  3:34 [RFC v3 00/12] kvm: arm64: emulate ID registers Peng Liang
                   ` (9 preceding siblings ...)
  2020-11-02  3:34 ` [RFC v3 10/12] kvm: arm64: Make other ID registers configurable Peng Liang
@ 2020-11-02  3:34 ` Peng Liang
  2020-11-02  3:34 ` [RFC v3 12/12] kvm: arm64: add KVM_CAP_ARM_CPU_FEATURE extension Peng Liang
  11 siblings, 0 replies; 13+ messages in thread
From: Peng Liang @ 2020-11-02  3:34 UTC (permalink / raw)
  To: kvmarm
  Cc: kvm, maz, will, drjones, zhang.zhanghailiang, xiexiangyou, Peng Liang

All vCPUs in same VM need to have same values of ID registers.  If not,
the vCPU is not allowed to run.

Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
Signed-off-by: Peng Liang <liangpeng10@huawei.com>
---
 arch/arm64/kvm/arm.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index 5a153a109317..0d7c4d4ab204 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -515,6 +515,22 @@ static void update_vmid(struct kvm_vmid *vmid)
 	spin_unlock(&kvm_vmid_lock);
 }
 
+static bool kvm_arm_id_regs_are_consistent(const struct kvm_vcpu *vcpu)
+{
+	int i, j;
+	int online_vcpus = atomic_read(&vcpu->kvm->online_vcpus);
+
+	for (i = 0; i < online_vcpus; ++i) {
+		if (memcmp(vcpu->arch.ctxt.sys_regs + ID_REG_BASE,
+			   vcpu->kvm->vcpus[i]->arch.ctxt.sys_regs + ID_REG_BASE,
+			   sizeof(vcpu->arch.ctxt.sys_regs[0]) * KVM_ARM_ID_REG_MAX_NUM)) {
+			return false;
+		}
+	}
+
+	return true;
+}
+
 static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu)
 {
 	struct kvm *kvm = vcpu->kvm;
@@ -526,6 +542,9 @@ static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu)
 	if (!kvm_arm_vcpu_is_finalized(vcpu))
 		return -EPERM;
 
+	if (!kvm_arm_id_regs_are_consistent(vcpu))
+		return -EPERM;
+
 	vcpu->arch.has_run_once = true;
 
 	if (likely(irqchip_in_kernel(kvm))) {
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [RFC v3 12/12] kvm: arm64: add KVM_CAP_ARM_CPU_FEATURE extension
  2020-11-02  3:34 [RFC v3 00/12] kvm: arm64: emulate ID registers Peng Liang
                   ` (10 preceding siblings ...)
  2020-11-02  3:34 ` [RFC v3 11/12] kvm: arm64: Check consistent of ID register Peng Liang
@ 2020-11-02  3:34 ` Peng Liang
  11 siblings, 0 replies; 13+ messages in thread
From: Peng Liang @ 2020-11-02  3:34 UTC (permalink / raw)
  To: kvmarm
  Cc: kvm, maz, will, drjones, zhang.zhanghailiang, xiexiangyou, Peng Liang

Add KVM_CAP_ARM_CPU_FEATURE extension for userpace to check whether KVM
supports to set CPU features in AArch64.  Also add documents for it.

Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
Signed-off-by: Peng Liang <liangpeng10@huawei.com>
---
 Documentation/virt/kvm/api.rst | 36 ++++++++++++++++++++++++++++++++++
 arch/arm64/kvm/arm.c           |  1 +
 include/uapi/linux/kvm.h       |  1 +
 3 files changed, 38 insertions(+)

diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst
index 36d5f1f3c6dd..3086a0d24548 100644
--- a/Documentation/virt/kvm/api.rst
+++ b/Documentation/virt/kvm/api.rst
@@ -2488,6 +2488,34 @@ EINVAL.
 After the vcpu's SVE configuration is finalized, further attempts to
 write this register will fail with EPERM.
 
+In AArch64, ID registers (where Op0=3, Op1=0, CRn=0, 1<=CRm<8, 0<=Op2<8)
+are allowed to set by userspace but there are some limits:
+1. Each ID field in ID registers should be no greater than that of host.
+   Except ID_AA64PFR0_EL1.CSV2, which is allowed to set to 1 if the value of
+   host is 0;
+2. ID_AA64PFR0_EL1.FP and ID_AA64PFR0_EL1.AdvSIMD must have the same value;
+3. If the vCPU has no SVE, then ID_AA64PFR0_EL1.SVE must be 0;
+4. ID_AA64PFR0_EL1.AMU must be 0;
+5. ID_AA64DFR0_EL1.PMUVer must be 0b0100 (PMUv3 for Armv8.1);
+   ID_DFR0_EL1.PerfMon must be 0b0100 (PMUv3 for Armv8.1);
+6. ID_AA64ISAR0_EL1.SM3 and ID_AA64ISAR0_EL1.SM4 must have the same value;
+7. If the value of ID_AA64ISAR0_EL1.SHA1 is 0, then ID_AA64ISAR0_EL1.SHA2
+   must have the value 0, and vice versa; if the value of
+   ID_AA64ISAR0_EL1.SHA2 is 2, then ID_AA64ISAR0_EL1.SHA3 must have the value
+   1, and vice versa; if the value of ID_AA64ISAR0_EL1.SHA1 is 0, then
+   ID_AA64ISAR0_EL1.SHA3 must have the value 0;
+8. If the vCPU has not enabled Generic Pointer authentication, then
+   ID_AA64ISAR1_EL1.GPA, ID_AA64ISAR1_EL1.GPI, ID_AA64ISAR1_EL1.APA, and
+   ID_AA64ISAR1_EL1.API must be 0.  Otherwise, if the value of
+   ID_AA64ISAR1_EL1.GPA is non-zero, then ID_AA64ISAR1_EL1.GPI must have
+   the value 0; if the value of ID_AA64ISAR1_EL1.GPI is non-zero, then
+   ID_AA64ISAR1_EL1.GPA must have the value 0; if the value of
+   ID_AA64ISAR1_EL1.APA is non-zero, then ID_AA64ISAR1_EL1.API must have the
+   value 0; if the value of ID_AA64ISAR1_EL1.API is non-zero, then
+   ID_AA64ISAR1_EL1.APA must have the value 0;
+9. The allowed value pair of (MVFR1_EL1.FPHP, MVFR1_EL1.SIMDHP) are (0, 0),
+   (2, 1), and (3, 2).
+
 
 MIPS registers are mapped using the lower 32 bits.  The upper 16 of that is
 the register group type:
@@ -6391,3 +6419,11 @@ When enabled, KVM will disable paravirtual features provided to the
 guest according to the bits in the KVM_CPUID_FEATURES CPUID leaf
 (0x40000001). Otherwise, a guest may use the paravirtual features
 regardless of what has actually been exposed through the CPUID leaf.
+
+8.27 KVM_CAP_ARM_CPU_FEATURE
+----------------------------
+
+:Architecture: arm64
+
+This capability indicates that userspace can modify the ID registers via
+KVM_SET_ONE_REG ioctl.  See KVM_SET_ONE_REG:ARM64 ID Registers for limits.
diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index 0d7c4d4ab204..e184756b2b37 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -182,6 +182,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
 	case KVM_CAP_ARM_IRQ_LINE_LAYOUT_2:
 	case KVM_CAP_ARM_NISV_TO_USER:
 	case KVM_CAP_ARM_INJECT_EXT_DABT:
+	case KVM_CAP_ARM_CPU_FEATURE:
 		r = 1;
 		break;
 	case KVM_CAP_ARM_SET_DEVICE_ADDR:
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index ca41220b40b8..bce49fab436c 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -1053,6 +1053,7 @@ struct kvm_ppc_resize_hpt {
 #define KVM_CAP_X86_USER_SPACE_MSR 188
 #define KVM_CAP_X86_MSR_FILTER 189
 #define KVM_CAP_ENFORCE_PV_FEATURE_CPUID 190
+#define KVM_CAP_ARM_CPU_FEATURE 191
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2020-11-02  3:37 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-11-02  3:34 [RFC v3 00/12] kvm: arm64: emulate ID registers Peng Liang
2020-11-02  3:34 ` [RFC v3 01/12] arm64: Add a helper function to traverse arm64_ftr_regs Peng Liang
2020-11-02  3:34 ` [RFC v3 02/12] arm64: Introduce check_features Peng Liang
2020-11-02  3:34 ` [RFC v3 03/12] kvm: arm64: Save ID registers to sys_regs file Peng Liang
2020-11-02  3:34 ` [RFC v3 04/12] kvm: arm64: Make ID_AA64PFR0_EL1 configurable Peng Liang
2020-11-02  3:34 ` [RFC v3 05/12] kvm: arm64: Make ID_AA64DFR0_EL1 configurable Peng Liang
2020-11-02  3:34 ` [RFC v3 06/12] kvm: arm64: Make ID_AA64ISAR0_EL1 configurable Peng Liang
2020-11-02  3:34 ` [RFC v3 07/12] kvm: arm64: Make ID_AA64ISAR1_EL1 configurable Peng Liang
2020-11-02  3:34 ` [RFC v3 08/12] kvm: arm64: Make ID_DFR0_EL1 configurable Peng Liang
2020-11-02  3:34 ` [RFC v3 09/12] kvm: arm64: Make MVFR1_EL1 configurable Peng Liang
2020-11-02  3:34 ` [RFC v3 10/12] kvm: arm64: Make other ID registers configurable Peng Liang
2020-11-02  3:34 ` [RFC v3 11/12] kvm: arm64: Check consistent of ID register Peng Liang
2020-11-02  3:34 ` [RFC v3 12/12] kvm: arm64: add KVM_CAP_ARM_CPU_FEATURE extension Peng Liang

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).