#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))
#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
[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)
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:
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:
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);
}
*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 */
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 */
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]);
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;
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: