mirror of
https://github.com/torvalds/linux.git
synced 2025-12-07 20:06:24 +00:00
LoongArch: KVM: Add AVEC basic support
Check whether the host CPU supported AVEC, and save/restore CSR_MSGIS0- CSR_MSGIS3 when necessary. Reviewed-by: Bibo Mao <maobibo@loongson.cn> Signed-off-by: Song Gao <gaosong@loongson.cn> Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
This commit is contained in:
@@ -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))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user