Skip to content

Commit 00f918f

Browse files
committed
RISC-V: KVM: Skeletal in-kernel AIA irqchip support
To incrementally implement in-kernel AIA irqchip support, we first add minimal skeletal support which only compiles but does not provide any functionality. Signed-off-by: Anup Patel <apatel@ventanamicro.com> Reviewed-by: Atish Patra <atishp@rivosinc.com> Signed-off-by: Anup Patel <anup@brainfault.org>
1 parent f0607e6 commit 00f918f

6 files changed

Lines changed: 158 additions & 0 deletions

File tree

arch/riscv/include/asm/kvm_aia.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ struct kvm_vcpu_aia {
4545
#define irqchip_in_kernel(k) ((k)->arch.aia.in_kernel)
4646

4747
extern unsigned int kvm_riscv_aia_nr_hgei;
48+
extern unsigned int kvm_riscv_aia_max_ids;
4849
DECLARE_STATIC_KEY_FALSE(kvm_riscv_aia_available);
4950
#define kvm_riscv_aia_available() \
5051
static_branch_unlikely(&kvm_riscv_aia_available)
@@ -116,6 +117,25 @@ static inline void kvm_riscv_vcpu_aia_deinit(struct kvm_vcpu *vcpu)
116117
{
117118
}
118119

120+
static inline int kvm_riscv_aia_inject_msi_by_id(struct kvm *kvm,
121+
u32 hart_index,
122+
u32 guest_index, u32 iid)
123+
{
124+
return 0;
125+
}
126+
127+
static inline int kvm_riscv_aia_inject_msi(struct kvm *kvm,
128+
struct kvm_msi *msi)
129+
{
130+
return 0;
131+
}
132+
133+
static inline int kvm_riscv_aia_inject_irq(struct kvm *kvm,
134+
unsigned int irq, bool level)
135+
{
136+
return 0;
137+
}
138+
119139
static inline void kvm_riscv_aia_init_vm(struct kvm *kvm)
120140
{
121141
}

arch/riscv/include/asm/kvm_host.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727

2828
#define KVM_VCPU_MAX_FEATURES 0
2929

30+
#define KVM_IRQCHIP_NUM_PINS 1024
31+
3032
#define KVM_REQ_SLEEP \
3133
KVM_ARCH_REQ_FLAGS(0, KVM_REQUEST_WAIT | KVM_REQUEST_NO_WAKEUP)
3234
#define KVM_REQ_VCPU_RESET KVM_ARCH_REQ(1)
@@ -318,6 +320,8 @@ int kvm_riscv_gstage_vmid_init(struct kvm *kvm);
318320
bool kvm_riscv_gstage_vmid_ver_changed(struct kvm_vmid *vmid);
319321
void kvm_riscv_gstage_vmid_update(struct kvm_vcpu *vcpu);
320322

323+
int kvm_riscv_setup_default_irq_routing(struct kvm *kvm, u32 lines);
324+
321325
void __kvm_riscv_unpriv_trap(void);
322326

323327
unsigned long kvm_riscv_vcpu_unpriv_read(struct kvm_vcpu *vcpu,

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <asm/bitsperlong.h>
1616
#include <asm/ptrace.h>
1717

18+
#define __KVM_HAVE_IRQ_LINE
1819
#define __KVM_HAVE_READONLY_MEM
1920

2021
#define KVM_COALESCED_MMIO_PAGE_OFFSET 1
@@ -203,6 +204,9 @@ enum KVM_RISCV_SBI_EXT_ID {
203204
#define KVM_REG_RISCV_SBI_MULTI_REG_LAST \
204205
KVM_REG_RISCV_SBI_MULTI_REG(KVM_RISCV_SBI_EXT_MAX - 1)
205206

207+
/* One single KVM irqchip, ie. the AIA */
208+
#define KVM_NR_IRQCHIPS 1
209+
206210
#endif
207211

208212
#endif /* __LINUX_KVM_RISCV_H */

arch/riscv/kvm/Kconfig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ config KVM
2121
tristate "Kernel-based Virtual Machine (KVM) support (EXPERIMENTAL)"
2222
depends on RISCV_SBI && MMU
2323
select HAVE_KVM_EVENTFD
24+
select HAVE_KVM_IRQCHIP
25+
select HAVE_KVM_IRQFD
26+
select HAVE_KVM_IRQ_ROUTING
27+
select HAVE_KVM_MSI
2428
select HAVE_KVM_VCPU_ASYNC_IOCTL
2529
select KVM_GENERIC_DIRTYLOG_READ_PROTECT
2630
select KVM_GENERIC_HARDWARE_ENABLING

arch/riscv/kvm/aia.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ static DEFINE_PER_CPU(struct aia_hgei_control, aia_hgei);
2626
static int hgei_parent_irq;
2727

2828
unsigned int kvm_riscv_aia_nr_hgei;
29+
unsigned int kvm_riscv_aia_max_ids;
2930
DEFINE_STATIC_KEY_FALSE(kvm_riscv_aia_available);
3031

3132
static int aia_find_hgei(struct kvm_vcpu *owner)
@@ -618,6 +619,13 @@ int kvm_riscv_aia_init(void)
618619
*/
619620
kvm_riscv_aia_nr_hgei = 0;
620621

622+
/*
623+
* Find number of guest MSI IDs
624+
*
625+
* TODO: To be updated later by AIA IMSIC HW guest file support
626+
*/
627+
kvm_riscv_aia_max_ids = IMSIC_MAX_ID;
628+
621629
/* Initialize guest external interrupt line management */
622630
rc = aia_hgei_init();
623631
if (rc)

arch/riscv/kvm/vm.c

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,129 @@ void kvm_arch_destroy_vm(struct kvm *kvm)
5555
kvm_riscv_aia_destroy_vm(kvm);
5656
}
5757

58+
int kvm_vm_ioctl_irq_line(struct kvm *kvm, struct kvm_irq_level *irql,
59+
bool line_status)
60+
{
61+
if (!irqchip_in_kernel(kvm))
62+
return -ENXIO;
63+
64+
return kvm_riscv_aia_inject_irq(kvm, irql->irq, irql->level);
65+
}
66+
67+
int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e,
68+
struct kvm *kvm, int irq_source_id,
69+
int level, bool line_status)
70+
{
71+
struct kvm_msi msi;
72+
73+
if (!level)
74+
return -1;
75+
76+
msi.address_lo = e->msi.address_lo;
77+
msi.address_hi = e->msi.address_hi;
78+
msi.data = e->msi.data;
79+
msi.flags = e->msi.flags;
80+
msi.devid = e->msi.devid;
81+
82+
return kvm_riscv_aia_inject_msi(kvm, &msi);
83+
}
84+
85+
static int kvm_riscv_set_irq(struct kvm_kernel_irq_routing_entry *e,
86+
struct kvm *kvm, int irq_source_id,
87+
int level, bool line_status)
88+
{
89+
return kvm_riscv_aia_inject_irq(kvm, e->irqchip.pin, level);
90+
}
91+
92+
int kvm_riscv_setup_default_irq_routing(struct kvm *kvm, u32 lines)
93+
{
94+
struct kvm_irq_routing_entry *ents;
95+
int i, rc;
96+
97+
ents = kcalloc(lines, sizeof(*ents), GFP_KERNEL);
98+
if (!ents)
99+
return -ENOMEM;
100+
101+
for (i = 0; i < lines; i++) {
102+
ents[i].gsi = i;
103+
ents[i].type = KVM_IRQ_ROUTING_IRQCHIP;
104+
ents[i].u.irqchip.irqchip = 0;
105+
ents[i].u.irqchip.pin = i;
106+
}
107+
rc = kvm_set_irq_routing(kvm, ents, lines, 0);
108+
kfree(ents);
109+
110+
return rc;
111+
}
112+
113+
bool kvm_arch_can_set_irq_routing(struct kvm *kvm)
114+
{
115+
return irqchip_in_kernel(kvm);
116+
}
117+
118+
int kvm_set_routing_entry(struct kvm *kvm,
119+
struct kvm_kernel_irq_routing_entry *e,
120+
const struct kvm_irq_routing_entry *ue)
121+
{
122+
int r = -EINVAL;
123+
124+
switch (ue->type) {
125+
case KVM_IRQ_ROUTING_IRQCHIP:
126+
e->set = kvm_riscv_set_irq;
127+
e->irqchip.irqchip = ue->u.irqchip.irqchip;
128+
e->irqchip.pin = ue->u.irqchip.pin;
129+
if ((e->irqchip.pin >= KVM_IRQCHIP_NUM_PINS) ||
130+
(e->irqchip.irqchip >= KVM_NR_IRQCHIPS))
131+
goto out;
132+
break;
133+
case KVM_IRQ_ROUTING_MSI:
134+
e->set = kvm_set_msi;
135+
e->msi.address_lo = ue->u.msi.address_lo;
136+
e->msi.address_hi = ue->u.msi.address_hi;
137+
e->msi.data = ue->u.msi.data;
138+
e->msi.flags = ue->flags;
139+
e->msi.devid = ue->u.msi.devid;
140+
break;
141+
default:
142+
goto out;
143+
}
144+
r = 0;
145+
out:
146+
return r;
147+
}
148+
149+
int kvm_arch_set_irq_inatomic(struct kvm_kernel_irq_routing_entry *e,
150+
struct kvm *kvm, int irq_source_id, int level,
151+
bool line_status)
152+
{
153+
if (!level)
154+
return -EWOULDBLOCK;
155+
156+
switch (e->type) {
157+
case KVM_IRQ_ROUTING_MSI:
158+
return kvm_set_msi(e, kvm, irq_source_id, level, line_status);
159+
160+
case KVM_IRQ_ROUTING_IRQCHIP:
161+
return kvm_riscv_set_irq(e, kvm, irq_source_id,
162+
level, line_status);
163+
}
164+
165+
return -EWOULDBLOCK;
166+
}
167+
168+
bool kvm_arch_irqchip_in_kernel(struct kvm *kvm)
169+
{
170+
return irqchip_in_kernel(kvm);
171+
}
172+
58173
int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
59174
{
60175
int r;
61176

62177
switch (ext) {
178+
case KVM_CAP_IRQCHIP:
179+
r = kvm_riscv_aia_available();
180+
break;
63181
case KVM_CAP_IOEVENTFD:
64182
case KVM_CAP_DEVICE_CTRL:
65183
case KVM_CAP_USER_MEMORY:

0 commit comments

Comments
 (0)