Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e8e7fcc5 authored by Anup Patel's avatar Anup Patel Committed by Christoffer Dall
Browse files

ARM/ARM64: KVM: Make kvm_psci_call() return convention more flexible



Currently, the kvm_psci_call() returns 'true' or 'false' based on whether
the PSCI function call was handled successfully or not. This does not help
us emulate system-level PSCI functions where the actual emulation work will
be done by user space (QEMU or KVMTOOL). Examples of such system-level PSCI
functions are: PSCI v0.2 SYSTEM_OFF and SYSTEM_RESET.

This patch updates kvm_psci_call() to return three types of values:
1) > 0 (success)
2) = 0 (success but exit to user space)
3) < 0 (errors)

Signed-off-by: default avatarAnup Patel <anup.patel@linaro.org>
Signed-off-by: default avatarPranavkumar Sawargaonkar <pranavkumar@linaro.org>
Reviewed-by: default avatarChristoffer Dall <christoffer.dall@linaro.org>
Acked-by: default avatarMarc Zyngier <marc.zyngier@arm.com>
Signed-off-by: default avatarChristoffer Dall <christoffer.dall@linaro.org>
parent 50bb0c94
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -22,6 +22,6 @@
#define KVM_ARM_PSCI_0_2	2

int kvm_psci_version(struct kvm_vcpu *vcpu);
bool kvm_psci_call(struct kvm_vcpu *vcpu);
int kvm_psci_call(struct kvm_vcpu *vcpu);

#endif /* __ARM_KVM_PSCI_H__ */
+7 −3
Original line number Diff line number Diff line
@@ -38,16 +38,20 @@ static int handle_svc_hyp(struct kvm_vcpu *vcpu, struct kvm_run *run)

static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run)
{
	int ret;

	trace_kvm_hvc(*vcpu_pc(vcpu), *vcpu_reg(vcpu, 0),
		      kvm_vcpu_hvc_get_imm(vcpu));

	if (kvm_psci_call(vcpu))
		return 1;

	ret = kvm_psci_call(vcpu);
	if (ret < 0) {
		kvm_inject_undefined(vcpu);
		return 1;
	}

	return ret;
}

static int handle_smc(struct kvm_vcpu *vcpu, struct kvm_run *run)
{
	kvm_inject_undefined(vcpu);
+16 −12
Original line number Diff line number Diff line
@@ -93,7 +93,7 @@ int kvm_psci_version(struct kvm_vcpu *vcpu)
	return KVM_ARM_PSCI_0_1;
}

static bool kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
{
	unsigned long psci_fn = *vcpu_reg(vcpu, 0) & ~((u32) 0);
	unsigned long val;
@@ -128,14 +128,14 @@ static bool kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
		val = PSCI_RET_NOT_SUPPORTED;
		break;
	default:
		return false;
		return -EINVAL;
	}

	*vcpu_reg(vcpu, 0) = val;
	return true;
	return 1;
}

static bool kvm_psci_0_1_call(struct kvm_vcpu *vcpu)
static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu)
{
	unsigned long psci_fn = *vcpu_reg(vcpu, 0) & ~((u32) 0);
	unsigned long val;
@@ -153,11 +153,11 @@ static bool kvm_psci_0_1_call(struct kvm_vcpu *vcpu)
		val = PSCI_RET_NOT_SUPPORTED;
		break;
	default:
		return false;
		return -EINVAL;
	}

	*vcpu_reg(vcpu, 0) = val;
	return true;
	return 1;
}

/**
@@ -165,12 +165,16 @@ static bool kvm_psci_0_1_call(struct kvm_vcpu *vcpu)
 * @vcpu: Pointer to the VCPU struct
 *
 * Handle PSCI calls from guests through traps from HVC instructions.
 * The calling convention is similar to SMC calls to the secure world where
 * the function number is placed in r0 and this function returns true if the
 * function number specified in r0 is withing the PSCI range, and false
 * otherwise.
 * The calling convention is similar to SMC calls to the secure world
 * where the function number is placed in r0.
 *
 * This function returns: > 0 (success), 0 (success but exit to user
 * space), and < 0 (errors)
 *
 * Errors:
 * -EINVAL: Unrecognized PSCI function
 */
bool kvm_psci_call(struct kvm_vcpu *vcpu)
int kvm_psci_call(struct kvm_vcpu *vcpu)
{
	switch (kvm_psci_version(vcpu)) {
	case KVM_ARM_PSCI_0_2:
@@ -178,6 +182,6 @@ bool kvm_psci_call(struct kvm_vcpu *vcpu)
	case KVM_ARM_PSCI_0_1:
		return kvm_psci_0_1_call(vcpu);
	default:
		return false;
		return -EINVAL;
	};
}
+1 −1
Original line number Diff line number Diff line
@@ -22,6 +22,6 @@
#define KVM_ARM_PSCI_0_2	2

int kvm_psci_version(struct kvm_vcpu *vcpu);
bool kvm_psci_call(struct kvm_vcpu *vcpu);
int kvm_psci_call(struct kvm_vcpu *vcpu);

#endif /* __ARM64_KVM_PSCI_H__ */
+7 −3
Original line number Diff line number Diff line
@@ -30,13 +30,17 @@ typedef int (*exit_handle_fn)(struct kvm_vcpu *, struct kvm_run *);

static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run)
{
	if (kvm_psci_call(vcpu))
		return 1;
	int ret;

	ret = kvm_psci_call(vcpu);
	if (ret < 0) {
		kvm_inject_undefined(vcpu);
		return 1;
	}

	return ret;
}

static int handle_smc(struct kvm_vcpu *vcpu, struct kvm_run *run)
{
	kvm_inject_undefined(vcpu);