Commit c0d910ff authored by Zengruan Ye's avatar Zengruan Ye Committed by lishusen
Browse files

KVM: arm64: Support pvsched preempted via shared structure

virt inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I8WMFU


CVE: NA

--------------------------------

Implement the service call for configuring a shared structure between a
vCPU and the hypervisor in which the hypervisor can tell the vCPU that is
running or not.

Signed-off-by: default avatarZengruan Ye <yezengruan@huawei.com>
Signed-off-by: default avatarlishusen <lishusen2@huawei.com>
parent b4787311
Loading
Loading
Loading
Loading
+23 −0
Original line number Diff line number Diff line
@@ -596,6 +596,11 @@ struct kvm_vcpu_arch {
		gpa_t base;
	} steal;

	/* Guest PV sched state */
	struct {
		gpa_t base;
	} pvsched;

	/* Per-vcpu CCSIDR override or NULL */
	u32 *ccsidr;

@@ -1053,11 +1058,29 @@ static inline bool kvm_arm_is_pvtime_enabled(struct kvm_vcpu_arch *vcpu_arch)

#ifdef CONFIG_PARAVIRT_SCHED
long kvm_hypercall_pvsched_features(struct kvm_vcpu *vcpu);
void kvm_update_pvsched_preempted(struct kvm_vcpu *vcpu, u32 preempted);

static inline void kvm_arm_pvsched_vcpu_init(struct kvm_vcpu_arch *vcpu_arch)
{
	vcpu_arch->pvsched.base = INVALID_GPA;
}

static inline bool kvm_arm_is_pvsched_enabled(struct kvm_vcpu_arch *vcpu_arch)
{
	return (vcpu_arch->pvsched.base != INVALID_GPA);
}
#else
static inline long kvm_hypercall_pvsched_features(struct kvm_vcpu *vcpu)
{
	return 0;
}
static inline void kvm_update_pvsched_preempted(struct kvm_vcpu *vcpu,
						u32 preempted) {}
static inline void kvm_arm_pvsched_vcpu_init(struct kvm_vcpu_arch *vcpu_arch) {}
static inline bool kvm_arm_is_pvsched_enabled(struct kvm_vcpu_arch *vcpu_arch)
{
	return false;
}
#endif

void kvm_set_sei_esr(struct kvm_vcpu *vcpu, u64 syndrome);
+8 −0
Original line number Diff line number Diff line
@@ -408,6 +408,8 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)

	kvm_arm_pvtime_vcpu_init(&vcpu->arch);

	kvm_arm_pvsched_vcpu_init(&vcpu->arch);

	vcpu->arch.hw_mmu = &vcpu->kvm->arch.mmu;

	err = kvm_vgic_vcpu_init(vcpu);
@@ -495,6 +497,9 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
		vcpu_set_on_unsupported_cpu(vcpu);

	kvm_tlbi_dvmbm_vcpu_load(vcpu);

	if (kvm_arm_is_pvsched_enabled(&vcpu->arch))
		kvm_update_pvsched_preempted(vcpu, 0);
}

void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
@@ -512,6 +517,9 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
	vcpu->cpu = -1;

	kvm_tlbi_dvmbm_vcpu_put(vcpu);

	if (kvm_arm_is_pvsched_enabled(&vcpu->arch))
		kvm_update_pvsched_preempted(vcpu, 1);
}

static void __kvm_arm_vcpu_power_off(struct kvm_vcpu *vcpu)
+11 −0
Original line number Diff line number Diff line
@@ -348,6 +348,17 @@ int kvm_smccc_call_handler(struct kvm_vcpu *vcpu)
	case ARM_SMCCC_HV_PV_SCHED_FEATURES:
		val[0] = kvm_hypercall_pvsched_features(vcpu);
		break;
	case ARM_SMCCC_HV_PV_SCHED_IPA_INIT:
		gpa = smccc_get_arg1(vcpu);
		if (gpa != INVALID_GPA) {
			vcpu->arch.pvsched.base = gpa;
			val[0] = SMCCC_RET_SUCCESS;
		}
		break;
	case ARM_SMCCC_HV_PV_SCHED_IPA_RELEASE:
		vcpu->arch.pvsched.base = INVALID_GPA;
		val[0] = SMCCC_RET_SUCCESS;
		break;
	case ARM_SMCCC_VENDOR_HYP_CALL_UID_FUNC_ID:
		val[0] = ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_0;
		val[1] = ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_1;
+28 −0
Original line number Diff line number Diff line
@@ -6,9 +6,35 @@

#ifdef CONFIG_PARAVIRT_SCHED
#include <linux/arm-smccc.h>
#include <linux/kvm_host.h>

#include <asm/pvsched-abi.h>

#include <kvm/arm_hypercalls.h>

void kvm_update_pvsched_preempted(struct kvm_vcpu *vcpu, u32 preempted)
{
	struct kvm *kvm = vcpu->kvm;
	u64 base = vcpu->arch.pvsched.base;
	u64 offset = offsetof(struct pvsched_vcpu_state, preempted);
	int idx;

	if (base == INVALID_GPA)
		return;

	/*
	 * This function is called from atomic context, so we need to
	 * disable page faults.
	 */
	pagefault_disable();

	idx = srcu_read_lock(&kvm->srcu);
	kvm_put_guest(kvm, base + offset, cpu_to_le32(preempted));
	srcu_read_unlock(&kvm->srcu, idx);

	pagefault_enable();
}

long kvm_hypercall_pvsched_features(struct kvm_vcpu *vcpu)
{
	u32 feature = smccc_get_arg1(vcpu);
@@ -16,6 +42,8 @@ long kvm_hypercall_pvsched_features(struct kvm_vcpu *vcpu)

	switch (feature) {
	case ARM_SMCCC_HV_PV_SCHED_FEATURES:
	case ARM_SMCCC_HV_PV_SCHED_IPA_INIT:
	case ARM_SMCCC_HV_PV_SCHED_IPA_RELEASE:
		val = SMCCC_RET_SUCCESS;
		break;
	}