Skip to content

Commit 1928254

Browse files
lixianglaichenhuacai
authored andcommitted
LoongArch: KVM: Add irqfd support
Enable the KVM_IRQ_ROUTING/KVM_IRQCHIP/KVM_MSI configuration items, add the KVM_CAP_IRQCHIP capability, and implement the query interface of the in-kernel irqchip. Signed-off-by: Xianglai Li <[email protected]> Signed-off-by: Huacai Chen <[email protected]>
1 parent d206d95 commit 1928254

File tree

7 files changed

+146
-1
lines changed

7 files changed

+146
-1
lines changed

arch/loongarch/include/asm/kvm_host.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
#include <asm/kvm_pch_pic.h>
2424
#include <asm/loongarch.h>
2525

26+
#define __KVM_HAVE_ARCH_INTC_INITIALIZED
27+
2628
/* Loongarch KVM register ids */
2729
#define KVM_GET_IOC_CSR_IDX(id) ((id & KVM_CSR_IDX_MASK) >> LOONGARCH_REG_SHIFT)
2830
#define KVM_GET_IOC_CPUCFG_IDX(id) ((id & KVM_CPUCFG_IDX_MASK) >> LOONGARCH_REG_SHIFT)

arch/loongarch/include/uapi/asm/kvm.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
#include <linux/types.h>
1010

11+
#define __KVM_HAVE_IRQ_LINE
12+
1113
/*
1214
* KVM LoongArch specific structures and definitions.
1315
*

arch/loongarch/kvm/Kconfig

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,16 @@ config KVM
2121
tristate "Kernel-based Virtual Machine (KVM) support"
2222
depends on AS_HAS_LVZ_EXTENSION
2323
select HAVE_KVM_DIRTY_RING_ACQ_REL
24+
select HAVE_KVM_IRQ_ROUTING
25+
select HAVE_KVM_IRQCHIP
26+
select HAVE_KVM_MSI
27+
select HAVE_KVM_READONLY_MEM
2428
select HAVE_KVM_VCPU_ASYNC_IOCTL
2529
select KVM_COMMON
2630
select KVM_GENERIC_DIRTYLOG_READ_PROTECT
2731
select KVM_GENERIC_HARDWARE_ENABLING
2832
select KVM_GENERIC_MMU_NOTIFIER
2933
select KVM_MMIO
30-
select HAVE_KVM_READONLY_MEM
3134
select KVM_XFER_TO_GUEST_WORK
3235
select SCHED_INFO
3336
help

arch/loongarch/kvm/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,6 @@ kvm-y += vm.o
2121
kvm-y += intc/ipi.o
2222
kvm-y += intc/eiointc.o
2323
kvm-y += intc/pch_pic.o
24+
kvm-y += irqfd.o
2425

2526
CFLAGS_exit.o += $(call cc-option,-Wno-override-init,)

arch/loongarch/kvm/intc/pch_pic.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,15 +443,42 @@ static int kvm_pch_pic_set_attr(struct kvm_device *dev,
443443
}
444444
}
445445

446+
static int kvm_setup_default_irq_routing(struct kvm *kvm)
447+
{
448+
int i, ret;
449+
u32 nr = KVM_IRQCHIP_NUM_PINS;
450+
struct kvm_irq_routing_entry *entries;
451+
452+
entries = kcalloc(nr, sizeof(*entries), GFP_KERNEL);
453+
if (!entries)
454+
return -ENOMEM;
455+
456+
for (i = 0; i < nr; i++) {
457+
entries[i].gsi = i;
458+
entries[i].type = KVM_IRQ_ROUTING_IRQCHIP;
459+
entries[i].u.irqchip.irqchip = 0;
460+
entries[i].u.irqchip.pin = i;
461+
}
462+
ret = kvm_set_irq_routing(kvm, entries, nr, 0);
463+
kfree(entries);
464+
465+
return ret;
466+
}
467+
446468
static int kvm_pch_pic_create(struct kvm_device *dev, u32 type)
447469
{
470+
int ret;
448471
struct kvm *kvm = dev->kvm;
449472
struct loongarch_pch_pic *s;
450473

451474
/* pch pic should not has been created */
452475
if (kvm->arch.pch_pic)
453476
return -EINVAL;
454477

478+
ret = kvm_setup_default_irq_routing(kvm);
479+
if (ret)
480+
return -ENOMEM;
481+
455482
s = kzalloc(sizeof(struct loongarch_pch_pic), GFP_KERNEL);
456483
if (!s)
457484
return -ENOMEM;

arch/loongarch/kvm/irqfd.c

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

arch/loongarch/kvm/vm.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
#include <linux/kvm_host.h>
77
#include <asm/kvm_mmu.h>
88
#include <asm/kvm_vcpu.h>
9+
#include <asm/kvm_eiointc.h>
10+
#include <asm/kvm_pch_pic.h>
911

1012
const struct _kvm_stats_desc kvm_vm_stats_desc[] = {
1113
KVM_GENERIC_VM_STATS(),
@@ -76,6 +78,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
7678
int r;
7779

7880
switch (ext) {
81+
case KVM_CAP_IRQCHIP:
7982
case KVM_CAP_ONE_REG:
8083
case KVM_CAP_ENABLE_CAP:
8184
case KVM_CAP_READONLY_MEM:
@@ -161,6 +164,8 @@ int kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
161164
struct kvm_device_attr attr;
162165

163166
switch (ioctl) {
167+
case KVM_CREATE_IRQCHIP:
168+
return 0;
164169
case KVM_HAS_DEVICE_ATTR:
165170
if (copy_from_user(&attr, argp, sizeof(attr)))
166171
return -EFAULT;
@@ -170,3 +175,19 @@ int kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
170175
return -ENOIOCTLCMD;
171176
}
172177
}
178+
179+
int kvm_vm_ioctl_irq_line(struct kvm *kvm, struct kvm_irq_level *irq_event, bool line_status)
180+
{
181+
if (!kvm_arch_irqchip_in_kernel(kvm))
182+
return -ENXIO;
183+
184+
irq_event->status = kvm_set_irq(kvm, KVM_USERSPACE_IRQ_SOURCE_ID,
185+
irq_event->irq, irq_event->level, line_status);
186+
187+
return 0;
188+
}
189+
190+
bool kvm_arch_irqchip_in_kernel(struct kvm *kvm)
191+
{
192+
return (kvm->arch.ipi && kvm->arch.eiointc && kvm->arch.pch_pic);
193+
}

0 commit comments

Comments
 (0)