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>pull/1354/merge
parent
74087611f0
commit
7bcd8d0b22
|
|
@ -15,6 +15,7 @@
|
||||||
#define CPU_PMU (_ULCAST_(1) << 10)
|
#define CPU_PMU (_ULCAST_(1) << 10)
|
||||||
#define CPU_TIMER (_ULCAST_(1) << 11)
|
#define CPU_TIMER (_ULCAST_(1) << 11)
|
||||||
#define CPU_IPI (_ULCAST_(1) << 12)
|
#define CPU_IPI (_ULCAST_(1) << 12)
|
||||||
|
#define CPU_AVEC (_ULCAST_(1) << 14)
|
||||||
|
|
||||||
/* Controlled by 0x52 guest exception VIP aligned to estat bit 5~12 */
|
/* Controlled by 0x52 guest exception VIP aligned to estat bit 5~12 */
|
||||||
#define CPU_IP0 (_ULCAST_(1))
|
#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_IPI 6
|
||||||
#define KVM_LOONGARCH_VM_FEAT_PV_STEALTIME 7
|
#define KVM_LOONGARCH_VM_FEAT_PV_STEALTIME 7
|
||||||
#define KVM_LOONGARCH_VM_FEAT_PTW 8
|
#define KVM_LOONGARCH_VM_FEAT_PTW 8
|
||||||
|
#define KVM_LOONGARCH_VM_FEAT_MSGINT 9
|
||||||
|
|
||||||
/* Device Control API on vcpu fd */
|
/* Device Control API on vcpu fd */
|
||||||
#define KVM_LOONGARCH_VCPU_CPUCFG 0
|
#define KVM_LOONGARCH_VCPU_CPUCFG 0
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ static unsigned int priority_to_irq[EXCCODE_INT_NUM] = {
|
||||||
[INT_HWI5] = CPU_IP5,
|
[INT_HWI5] = CPU_IP5,
|
||||||
[INT_HWI6] = CPU_IP6,
|
[INT_HWI6] = CPU_IP6,
|
||||||
[INT_HWI7] = CPU_IP7,
|
[INT_HWI7] = CPU_IP7,
|
||||||
|
[INT_AVEC] = CPU_AVEC,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int kvm_irq_deliver(struct kvm_vcpu *vcpu, unsigned int priority)
|
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)
|
if (priority < EXCCODE_INT_NUM)
|
||||||
irq = priority_to_irq[priority];
|
irq = priority_to_irq[priority];
|
||||||
|
|
||||||
|
if (cpu_has_msgint && (priority == INT_AVEC)) {
|
||||||
|
set_gcsr_estat(irq);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
switch (priority) {
|
switch (priority) {
|
||||||
case INT_TI:
|
case INT_TI:
|
||||||
case INT_IPI:
|
case INT_IPI:
|
||||||
|
|
@ -58,6 +64,11 @@ static int kvm_irq_clear(struct kvm_vcpu *vcpu, unsigned int priority)
|
||||||
if (priority < EXCCODE_INT_NUM)
|
if (priority < EXCCODE_INT_NUM)
|
||||||
irq = priority_to_irq[priority];
|
irq = priority_to_irq[priority];
|
||||||
|
|
||||||
|
if (cpu_has_msgint && (priority == INT_AVEC)) {
|
||||||
|
clear_gcsr_estat(irq);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
switch (priority) {
|
switch (priority) {
|
||||||
case INT_TI:
|
case INT_TI:
|
||||||
case INT_IPI:
|
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 = &vcpu->arch.irq_pending;
|
||||||
unsigned long *pending_clr = &vcpu->arch.irq_clear;
|
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);
|
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);
|
kvm_irq_deliver(vcpu, priority);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -659,8 +659,7 @@ static int _kvm_get_cpucfg_mask(int id, u64 *v)
|
||||||
*v = GENMASK(31, 0);
|
*v = GENMASK(31, 0);
|
||||||
return 0;
|
return 0;
|
||||||
case LOONGARCH_CPUCFG1:
|
case LOONGARCH_CPUCFG1:
|
||||||
/* CPUCFG1_MSGINT is not supported by KVM */
|
*v = GENMASK(26, 0);
|
||||||
*v = GENMASK(25, 0);
|
|
||||||
return 0;
|
return 0;
|
||||||
case LOONGARCH_CPUCFG2:
|
case LOONGARCH_CPUCFG2:
|
||||||
/* CPUCFG2 features unconditionally supported by KVM */
|
/* CPUCFG2 features unconditionally supported by KVM */
|
||||||
|
|
@ -728,6 +727,10 @@ static int kvm_check_cpucfg(int id, u64 val)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
switch (id) {
|
switch (id) {
|
||||||
|
case LOONGARCH_CPUCFG1:
|
||||||
|
if ((val & CPUCFG1_MSGINT) && !cpu_has_msgint)
|
||||||
|
return -EINVAL;
|
||||||
|
return 0;
|
||||||
case LOONGARCH_CPUCFG2:
|
case LOONGARCH_CPUCFG2:
|
||||||
if (!(val & CPUCFG2_LLFTP))
|
if (!(val & CPUCFG2_LLFTP))
|
||||||
/* Guests must have a constant timer */
|
/* 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_DMWIN2);
|
||||||
kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_DMWIN3);
|
kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_DMWIN3);
|
||||||
kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_LLBCTL);
|
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 */
|
/* Restore Root.GINTC from unused Guest.GINTC register */
|
||||||
write_csr_gintc(csr->csrs[LOONGARCH_CSR_GINTC]);
|
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_DMWIN1);
|
||||||
kvm_save_hw_gcsr(csr, LOONGARCH_CSR_DMWIN2);
|
kvm_save_hw_gcsr(csr, LOONGARCH_CSR_DMWIN2);
|
||||||
kvm_save_hw_gcsr(csr, LOONGARCH_CSR_DMWIN3);
|
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;
|
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)
|
if (cpu_has_ptw)
|
||||||
return 0;
|
return 0;
|
||||||
return -ENXIO;
|
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_PMU:
|
||||||
case KVM_LOONGARCH_VM_FEAT_PV_IPI:
|
case KVM_LOONGARCH_VM_FEAT_PV_IPI:
|
||||||
case KVM_LOONGARCH_VM_FEAT_PV_STEALTIME:
|
case KVM_LOONGARCH_VM_FEAT_PV_STEALTIME:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue