Subject: linux-next: manual merge of the kvm-arm tree with the arm64 tree

From: Stephen Rothwell <[email-masked]>
Date: Wed, 4 May 2022 14:35:29 +1000

Hi all,

Today's linux-next merge of the kvm-arm tree got a conflict in:

  arch/arm64/kvm/sys_regs.c

between commit:

  0b12620fddb8 ("KVM: arm64: Treat ESR_EL2 as a 64-bit register")

from the arm64 tree and commits:

  e65197666773 ("KVM: arm64: Wire up CP15 feature registers to their AArch64 equivalents")
  9369bc5c5e35 ("KVM: arm64: Plumb cp10 ID traps through the AArch64 sysreg handler")

from the kvm-arm tree.

I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging.  You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.

-- 
Cheers,
Stephen Rothwell

diff --cc arch/arm64/kvm/sys_regs.c
index a4ef986adb5e,031d913cd79e..000000000000
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@@ -2351,6 -2355,123 +2355,123 @@@ static int kvm_handle_cp_64(struct kvm_
  	return 1;
  }
  
+ static bool emulate_sys_reg(struct kvm_vcpu *vcpu, struct sys_reg_params *params);
+ 
+ /*
+  * The CP10 ID registers are architecturally mapped to AArch64 feature
+  * registers. Abuse that fact so we can rely on the AArch64 handler for accesses
+  * from AArch32.
+  */
 -static bool kvm_esr_cp10_id_to_sys64(u32 esr, struct sys_reg_params *params)
++static bool kvm_esr_cp10_id_to_sys64(u64 esr, struct sys_reg_params *params)
+ {
+ 	u8 reg_id = (esr >> 10) & 0xf;
+ 	bool valid;
+ 
+ 	params->is_write = ((esr & 1) == 0);
+ 	params->Op0 = 3;
+ 	params->Op1 = 0;
+ 	params->CRn = 0;
+ 	params->CRm = 3;
+ 
+ 	/* CP10 ID registers are read-only */
+ 	valid = !params->is_write;
+ 
+ 	switch (reg_id) {
+ 	/* MVFR0 */
+ 	case 0b0111:
+ 		params->Op2 = 0;
+ 		break;
+ 	/* MVFR1 */
+ 	case 0b0110:
+ 		params->Op2 = 1;
+ 		break;
+ 	/* MVFR2 */
+ 	case 0b0101:
+ 		params->Op2 = 2;
+ 		break;
+ 	default:
+ 		valid = false;
+ 	}
+ 
+ 	if (valid)
+ 		return true;
+ 
+ 	kvm_pr_unimpl("Unhandled cp10 register %s: %u\n",
+ 		      params->is_write ? "write" : "read", reg_id);
+ 	return false;
+ }
+ 
+ /**
+  * kvm_handle_cp10_id() - Handles a VMRS trap on guest access to a 'Media and
+  *			  VFP Register' from AArch32.
+  * @vcpu: The vCPU pointer
+  *
+  * MVFR{0-2} are architecturally mapped to the AArch64 MVFR{0-2}_EL1 registers.
+  * Work out the correct AArch64 system register encoding and reroute to the
+  * AArch64 system register emulation.
+  */
+ int kvm_handle_cp10_id(struct kvm_vcpu *vcpu)
+ {
+ 	int Rt = kvm_vcpu_sys_get_rt(vcpu);
 -	u32 esr = kvm_vcpu_get_esr(vcpu);
++	u64 esr = kvm_vcpu_get_esr(vcpu);
+ 	struct sys_reg_params params;
+ 
+ 	/* UNDEF on any unhandled register access */
+ 	if (!kvm_esr_cp10_id_to_sys64(esr, &params)) {
+ 		kvm_inject_undefined(vcpu);
+ 		return 1;
+ 	}
+ 
+ 	if (emulate_sys_reg(vcpu, &params))
+ 		vcpu_set_reg(vcpu, Rt, params.regval);
+ 
+ 	return 1;
+ }
+ 
+ /**
+  * kvm_emulate_cp15_id_reg() - Handles an MRC trap on a guest CP15 access where
+  *			       CRn=0, which corresponds to the AArch32 feature
+  *			       registers.
+  * @vcpu: the vCPU pointer
+  * @params: the system register access parameters.
+  *
+  * Our cp15 system register tables do not enumerate the AArch32 feature
+  * registers. Conveniently, our AArch64 table does, and the AArch32 system
+  * register encoding can be trivially remapped into the AArch64 for the feature
+  * registers: Append op0=3, leaving op1, CRn, CRm, and op2 the same.
+  *
+  * According to DDI0487G.b G7.3.1, paragraph "Behavior of VMSAv8-32 32-bit
+  * System registers with (coproc=0b1111, CRn==c0)", read accesses from this
+  * range are either UNKNOWN or RES0. Rerouting remains architectural as we
+  * treat undefined registers in this range as RAZ.
+  */
+ static int kvm_emulate_cp15_id_reg(struct kvm_vcpu *vcpu,
+ 				   struct sys_reg_params *params)
+ {
+ 	int Rt = kvm_vcpu_sys_get_rt(vcpu);
+ 
+ 	/* Treat impossible writes to RO registers as UNDEFINED */
+ 	if (params->is_write) {
+ 		unhandled_cp_access(vcpu, params);
+ 		return 1;
+ 	}
+ 
+ 	params->Op0 = 3;
+ 
+ 	/*
+ 	 * All registers where CRm > 3 are known to be UNKNOWN/RAZ from AArch32.
+ 	 * Avoid conflicting with future expansion of AArch64 feature registers
+ 	 * and simply treat them as RAZ here.
+ 	 */
+ 	if (params->CRm > 3)
+ 		params->regval = 0;
+ 	else if (!emulate_sys_reg(vcpu, params))
+ 		return 1;
+ 
+ 	vcpu_set_reg(vcpu, Rt, params->regval);
+ 	return 1;
+ }
+ 
  /**
   * kvm_handle_cp_32 -- handles a mrc/mcr trap on a guest CP14/CP15 access
   * @vcpu: The VCPU pointer