Commit 7bcd8d0b authored by Song Gao's avatar Song Gao Committed by Huacai Chen
Browse files

LoongArch: KVM: Add AVEC basic support



Check whether the host CPU supported AVEC, and save/restore CSR_MSGIS0-
CSR_MSGIS3 when necessary.

Reviewed-by: default avatarBibo Mao <maobibo@loongson.cn>
Signed-off-by: default avatarSong Gao <gaosong@loongson.cn>
Signed-off-by: default avatarHuacai Chen <chenhuacai@loongson.cn>
parent 74087611
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
#define CPU_PMU				(_ULCAST_(1) << 10)
#define CPU_TIMER			(_ULCAST_(1) << 11)
#define CPU_IPI				(_ULCAST_(1) << 12)
#define CPU_AVEC                        (_ULCAST_(1) << 14)

/* Controlled by 0x52 guest exception VIP aligned to estat bit 5~12 */
#define CPU_IP0				(_ULCAST_(1))
+1 −0
Original line number Diff line number Diff line
@@ -104,6 +104,7 @@ struct kvm_fpu {
#define  KVM_LOONGARCH_VM_FEAT_PV_IPI		6
#define  KVM_LOONGARCH_VM_FEAT_PV_STEALTIME	7
#define  KVM_LOONGARCH_VM_FEAT_PTW		8
#define  KVM_LOONGARCH_VM_FEAT_MSGINT		9

/* Device Control API on vcpu fd */
#define KVM_LOONGARCH_VCPU_CPUCFG	0
+13 −2
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ static unsigned int priority_to_irq[EXCCODE_INT_NUM] = {
	[INT_HWI5]	= CPU_IP5,
	[INT_HWI6]	= CPU_IP6,
	[INT_HWI7]	= CPU_IP7,
	[INT_AVEC]	= CPU_AVEC,
};

static int kvm_irq_deliver(struct kvm_vcpu *vcpu, unsigned int priority)
@@ -31,6 +32,11 @@ static int kvm_irq_deliver(struct kvm_vcpu *vcpu, unsigned int priority)
	if (priority < EXCCODE_INT_NUM)
		irq = priority_to_irq[priority];

	if (cpu_has_msgint && (priority == INT_AVEC)) {
		set_gcsr_estat(irq);
		return 1;
	}

	switch (priority) {
	case INT_TI:
	case INT_IPI:
@@ -58,6 +64,11 @@ static int kvm_irq_clear(struct kvm_vcpu *vcpu, unsigned int priority)
	if (priority < EXCCODE_INT_NUM)
		irq = priority_to_irq[priority];

	if (cpu_has_msgint && (priority == INT_AVEC)) {
		clear_gcsr_estat(irq);
		return 1;
	}

	switch (priority) {
	case INT_TI:
	case INT_IPI:
@@ -83,10 +94,10 @@ void kvm_deliver_intr(struct kvm_vcpu *vcpu)
	unsigned long *pending = &vcpu->arch.irq_pending;
	unsigned long *pending_clr = &vcpu->arch.irq_clear;

	for_each_set_bit(priority, pending_clr, INT_IPI + 1)
	for_each_set_bit(priority, pending_clr, EXCCODE_INT_NUM)
		kvm_irq_clear(vcpu, priority);

	for_each_set_bit(priority, pending, INT_IPI + 1)
	for_each_set_bit(priority, pending, EXCCODE_INT_NUM)
		kvm_irq_deliver(vcpu, priority);
}

+17 −2
Original line number Diff line number Diff line
@@ -659,8 +659,7 @@ static int _kvm_get_cpucfg_mask(int id, u64 *v)
		*v = GENMASK(31, 0);
		return 0;
	case LOONGARCH_CPUCFG1:
		/* CPUCFG1_MSGINT is not supported by KVM */
		*v = GENMASK(25, 0);
		*v = GENMASK(26, 0);
		return 0;
	case LOONGARCH_CPUCFG2:
		/* CPUCFG2 features unconditionally supported by KVM */
@@ -728,6 +727,10 @@ static int kvm_check_cpucfg(int id, u64 val)
		return -EINVAL;

	switch (id) {
	case LOONGARCH_CPUCFG1:
		if ((val & CPUCFG1_MSGINT) && !cpu_has_msgint)
			return -EINVAL;
		return 0;
	case LOONGARCH_CPUCFG2:
		if (!(val & CPUCFG2_LLFTP))
			/* Guests must have a constant timer */
@@ -1657,6 +1660,12 @@ static int _kvm_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
	kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_DMWIN2);
	kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_DMWIN3);
	kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_LLBCTL);
	if (cpu_has_msgint) {
		kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_ISR0);
		kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_ISR1);
		kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_ISR2);
		kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_ISR3);
	}

	/* Restore Root.GINTC from unused Guest.GINTC register */
	write_csr_gintc(csr->csrs[LOONGARCH_CSR_GINTC]);
@@ -1746,6 +1755,12 @@ static int _kvm_vcpu_put(struct kvm_vcpu *vcpu, int cpu)
	kvm_save_hw_gcsr(csr, LOONGARCH_CSR_DMWIN1);
	kvm_save_hw_gcsr(csr, LOONGARCH_CSR_DMWIN2);
	kvm_save_hw_gcsr(csr, LOONGARCH_CSR_DMWIN3);
	if (cpu_has_msgint) {
		kvm_save_hw_gcsr(csr, LOONGARCH_CSR_ISR0);
		kvm_save_hw_gcsr(csr, LOONGARCH_CSR_ISR1);
		kvm_save_hw_gcsr(csr, LOONGARCH_CSR_ISR2);
		kvm_save_hw_gcsr(csr, LOONGARCH_CSR_ISR3);
	}

	vcpu->arch.aux_inuse |= KVM_LARCH_SWCSR_LATEST;

+4 −0
Original line number Diff line number Diff line
@@ -154,6 +154,10 @@ static int kvm_vm_feature_has_attr(struct kvm *kvm, struct kvm_device_attr *attr
		if (cpu_has_ptw)
			return 0;
		return -ENXIO;
	case KVM_LOONGARCH_VM_FEAT_MSGINT:
		if (cpu_has_msgint)
			return 0;
		return -ENXIO;
	case KVM_LOONGARCH_VM_FEAT_PMU:
	case KVM_LOONGARCH_VM_FEAT_PV_IPI:
	case KVM_LOONGARCH_VM_FEAT_PV_STEALTIME: