Commit 28eda7b5 authored by Oliver Upton's avatar Oliver Upton Committed by Marc Zyngier
Browse files

KVM: arm64: Don't write to Rt unless sys_reg emulation succeeds



emulate_sys_reg() returns 1 unconditionally, even though a a system
register access can fail. Furthermore, kvm_handle_sys_reg() writes to Rt
for every register read, regardless of if it actually succeeded.

Though this pattern is safe (as params.regval is initialized with the
current value of Rt) it is a bit ugly. Indicate failure if the register
access could not be emulated and only write to Rt on success.

Signed-off-by: default avatarOliver Upton <oupton@google.com>
Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20220503060205.2823727-3-oupton@google.com
parent 001bb819
Loading
Loading
Loading
Loading
+16 −6
Original line number Diff line number Diff line
@@ -2401,7 +2401,14 @@ static bool is_imp_def_sys_reg(struct sys_reg_params *params)
	return params->Op0 == 3 && (params->CRn & 0b1011) == 0b1011;
}

static int emulate_sys_reg(struct kvm_vcpu *vcpu,
/**
 * emulate_sys_reg - Emulate a guest access to an AArch64 system register
 * @vcpu: The VCPU pointer
 * @params: Decoded system register parameters
 *
 * Return: true if the system register access was successful, false otherwise.
 */
static bool emulate_sys_reg(struct kvm_vcpu *vcpu,
			   struct sys_reg_params *params)
{
	const struct sys_reg_desc *r;
@@ -2410,7 +2417,10 @@ static int emulate_sys_reg(struct kvm_vcpu *vcpu,

	if (likely(r)) {
		perform_access(vcpu, params, r);
	} else if (is_imp_def_sys_reg(params)) {
		return true;
	}

	if (is_imp_def_sys_reg(params)) {
		kvm_inject_undefined(vcpu);
	} else {
		print_sys_reg_msg(params,
@@ -2418,7 +2428,7 @@ static int emulate_sys_reg(struct kvm_vcpu *vcpu,
				  *vcpu_pc(vcpu), *vcpu_cpsr(vcpu));
		kvm_inject_undefined(vcpu);
	}
	return 1;
	return false;
}

/**
@@ -2446,18 +2456,18 @@ int kvm_handle_sys_reg(struct kvm_vcpu *vcpu)
	struct sys_reg_params params;
	unsigned long esr = kvm_vcpu_get_esr(vcpu);
	int Rt = kvm_vcpu_sys_get_rt(vcpu);
	int ret;

	trace_kvm_handle_sys_reg(esr);

	params = esr_sys64_to_params(esr);
	params.regval = vcpu_get_reg(vcpu, Rt);

	ret = emulate_sys_reg(vcpu, &params);
	if (!emulate_sys_reg(vcpu, &params))
		return 1;

	if (!params.is_write)
		vcpu_set_reg(vcpu, Rt, params.regval);
	return ret;
	return 1;
}

/******************************************************************************