1*1928254cSXianglai Li // SPDX-License-Identifier: GPL-2.0 2*1928254cSXianglai Li /* 3*1928254cSXianglai Li * Copyright (C) 2024 Loongson Technology Corporation Limited 4*1928254cSXianglai Li */ 5*1928254cSXianglai Li 6*1928254cSXianglai Li #include <linux/kvm_host.h> 7*1928254cSXianglai Li #include <trace/events/kvm.h> 8*1928254cSXianglai Li #include <asm/kvm_pch_pic.h> 9*1928254cSXianglai Li 10*1928254cSXianglai Li static int kvm_set_pic_irq(struct kvm_kernel_irq_routing_entry *e, 11*1928254cSXianglai Li struct kvm *kvm, int irq_source_id, int level, bool line_status) 12*1928254cSXianglai Li { 13*1928254cSXianglai Li /* PCH-PIC pin (0 ~ 64) <---> GSI (0 ~ 64) */ 14*1928254cSXianglai Li pch_pic_set_irq(kvm->arch.pch_pic, e->irqchip.pin, level); 15*1928254cSXianglai Li 16*1928254cSXianglai Li return 0; 17*1928254cSXianglai Li } 18*1928254cSXianglai Li 19*1928254cSXianglai Li /* 20*1928254cSXianglai Li * kvm_set_msi: inject the MSI corresponding to the 21*1928254cSXianglai Li * MSI routing entry 22*1928254cSXianglai Li * 23*1928254cSXianglai Li * This is the entry point for irqfd MSI injection 24*1928254cSXianglai Li * and userspace MSI injection. 25*1928254cSXianglai Li */ 26*1928254cSXianglai Li int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e, 27*1928254cSXianglai Li struct kvm *kvm, int irq_source_id, int level, bool line_status) 28*1928254cSXianglai Li { 29*1928254cSXianglai Li if (!level) 30*1928254cSXianglai Li return -1; 31*1928254cSXianglai Li 32*1928254cSXianglai Li pch_msi_set_irq(kvm, e->msi.data, level); 33*1928254cSXianglai Li 34*1928254cSXianglai Li return 0; 35*1928254cSXianglai Li } 36*1928254cSXianglai Li 37*1928254cSXianglai Li /* 38*1928254cSXianglai Li * kvm_set_routing_entry: populate a kvm routing entry 39*1928254cSXianglai Li * from a user routing entry 40*1928254cSXianglai Li * 41*1928254cSXianglai Li * @kvm: the VM this entry is applied to 42*1928254cSXianglai Li * @e: kvm kernel routing entry handle 43*1928254cSXianglai Li * @ue: user api routing entry handle 44*1928254cSXianglai Li * return 0 on success, -EINVAL on errors. 45*1928254cSXianglai Li */ 46*1928254cSXianglai Li int kvm_set_routing_entry(struct kvm *kvm, 47*1928254cSXianglai Li struct kvm_kernel_irq_routing_entry *e, 48*1928254cSXianglai Li const struct kvm_irq_routing_entry *ue) 49*1928254cSXianglai Li { 50*1928254cSXianglai Li switch (ue->type) { 51*1928254cSXianglai Li case KVM_IRQ_ROUTING_IRQCHIP: 52*1928254cSXianglai Li e->set = kvm_set_pic_irq; 53*1928254cSXianglai Li e->irqchip.irqchip = ue->u.irqchip.irqchip; 54*1928254cSXianglai Li e->irqchip.pin = ue->u.irqchip.pin; 55*1928254cSXianglai Li 56*1928254cSXianglai Li if (e->irqchip.pin >= KVM_IRQCHIP_NUM_PINS) 57*1928254cSXianglai Li return -EINVAL; 58*1928254cSXianglai Li 59*1928254cSXianglai Li return 0; 60*1928254cSXianglai Li case KVM_IRQ_ROUTING_MSI: 61*1928254cSXianglai Li e->set = kvm_set_msi; 62*1928254cSXianglai Li e->msi.address_lo = ue->u.msi.address_lo; 63*1928254cSXianglai Li e->msi.address_hi = ue->u.msi.address_hi; 64*1928254cSXianglai Li e->msi.data = ue->u.msi.data; 65*1928254cSXianglai Li return 0; 66*1928254cSXianglai Li default: 67*1928254cSXianglai Li return -EINVAL; 68*1928254cSXianglai Li } 69*1928254cSXianglai Li } 70*1928254cSXianglai Li 71*1928254cSXianglai Li int kvm_arch_set_irq_inatomic(struct kvm_kernel_irq_routing_entry *e, 72*1928254cSXianglai Li struct kvm *kvm, int irq_source_id, int level, bool line_status) 73*1928254cSXianglai Li { 74*1928254cSXianglai Li switch (e->type) { 75*1928254cSXianglai Li case KVM_IRQ_ROUTING_IRQCHIP: 76*1928254cSXianglai Li pch_pic_set_irq(kvm->arch.pch_pic, e->irqchip.pin, level); 77*1928254cSXianglai Li return 0; 78*1928254cSXianglai Li case KVM_IRQ_ROUTING_MSI: 79*1928254cSXianglai Li pch_msi_set_irq(kvm, e->msi.data, level); 80*1928254cSXianglai Li return 0; 81*1928254cSXianglai Li default: 82*1928254cSXianglai Li return -EWOULDBLOCK; 83*1928254cSXianglai Li } 84*1928254cSXianglai Li } 85*1928254cSXianglai Li 86*1928254cSXianglai Li bool kvm_arch_intc_initialized(struct kvm *kvm) 87*1928254cSXianglai Li { 88*1928254cSXianglai Li return kvm_arch_irqchip_in_kernel(kvm); 89*1928254cSXianglai Li } 90