xref: /kvmtool/riscv/irq.c (revision 0dff350174f8da2b65dd43a3e569e5377f4ee906)
12e996783SAnup Patel #include "kvm/kvm.h"
22e996783SAnup Patel #include "kvm/kvm-cpu.h"
32e996783SAnup Patel #include "kvm/irq.h"
4*0dff3501SAnup Patel #include "kvm/fdt.h"
5*0dff3501SAnup Patel #include "kvm/virtio.h"
6*0dff3501SAnup Patel 
7*0dff3501SAnup Patel enum irqchip_type riscv_irqchip = IRQCHIP_UNKNOWN;
8*0dff3501SAnup Patel bool riscv_irqchip_inkernel;
9*0dff3501SAnup Patel void (*riscv_irqchip_trigger)(struct kvm *kvm, int irq, int level, bool edge)
10*0dff3501SAnup Patel 				= NULL;
11*0dff3501SAnup Patel void (*riscv_irqchip_generate_fdt_node)(void *fdt, struct kvm *kvm) = NULL;
12*0dff3501SAnup Patel u32 riscv_irqchip_phandle = PHANDLE_RESERVED;
13*0dff3501SAnup Patel u32 riscv_irqchip_msi_phandle = PHANDLE_RESERVED;
14*0dff3501SAnup Patel bool riscv_irqchip_line_sensing;
152e996783SAnup Patel 
162e996783SAnup Patel void kvm__irq_line(struct kvm *kvm, int irq, int level)
172e996783SAnup Patel {
18*0dff3501SAnup Patel 	struct kvm_irq_level irq_level;
19*0dff3501SAnup Patel 
20*0dff3501SAnup Patel 	if (riscv_irqchip_inkernel) {
21*0dff3501SAnup Patel 		irq_level.irq = irq;
22*0dff3501SAnup Patel 		irq_level.level = !!level;
23*0dff3501SAnup Patel 		if (ioctl(kvm->vm_fd, KVM_IRQ_LINE, &irq_level) < 0)
24*0dff3501SAnup Patel 			pr_warning("%s: Could not KVM_IRQ_LINE for irq %d\n",
25*0dff3501SAnup Patel 				   __func__, irq);
26*0dff3501SAnup Patel 	} else {
27*0dff3501SAnup Patel 		if (riscv_irqchip_trigger)
28*0dff3501SAnup Patel 			riscv_irqchip_trigger(kvm, irq, level, false);
29*0dff3501SAnup Patel 		else
30*0dff3501SAnup Patel 			pr_warning("%s: Can't change level for irq %d\n",
31*0dff3501SAnup Patel 				   __func__, irq);
32*0dff3501SAnup Patel 	}
332e996783SAnup Patel }
342e996783SAnup Patel 
352e996783SAnup Patel void kvm__irq_trigger(struct kvm *kvm, int irq)
362e996783SAnup Patel {
37*0dff3501SAnup Patel 	if (riscv_irqchip_inkernel) {
38*0dff3501SAnup Patel 		kvm__irq_line(kvm, irq, VIRTIO_IRQ_HIGH);
39*0dff3501SAnup Patel 		kvm__irq_line(kvm, irq, VIRTIO_IRQ_LOW);
40*0dff3501SAnup Patel 	} else {
41*0dff3501SAnup Patel 		if (riscv_irqchip_trigger)
42*0dff3501SAnup Patel 			riscv_irqchip_trigger(kvm, irq, 1, true);
43*0dff3501SAnup Patel 		else
44*0dff3501SAnup Patel 			pr_warning("%s: Can't trigger irq %d\n",
45*0dff3501SAnup Patel 				   __func__, irq);
46*0dff3501SAnup Patel 	}
47*0dff3501SAnup Patel }
48*0dff3501SAnup Patel 
49*0dff3501SAnup Patel void riscv__generate_irq_prop(void *fdt, u8 irq, enum irq_type irq_type)
50*0dff3501SAnup Patel {
51*0dff3501SAnup Patel 	u32 prop[2], size;
52*0dff3501SAnup Patel 
53*0dff3501SAnup Patel 	prop[0] = cpu_to_fdt32(irq);
54*0dff3501SAnup Patel 	size = sizeof(u32);
55*0dff3501SAnup Patel 	if (riscv_irqchip_line_sensing) {
56*0dff3501SAnup Patel 		prop[1] = cpu_to_fdt32(irq_type);
57*0dff3501SAnup Patel 		size += sizeof(u32);
58*0dff3501SAnup Patel 	}
59*0dff3501SAnup Patel 
60*0dff3501SAnup Patel 	_FDT(fdt_property(fdt, "interrupts", prop, size));
61*0dff3501SAnup Patel }
62*0dff3501SAnup Patel 
63*0dff3501SAnup Patel void riscv__irqchip_create(struct kvm *kvm)
64*0dff3501SAnup Patel {
65*0dff3501SAnup Patel 	/* Try PLIC irqchip */
66*0dff3501SAnup Patel 	plic__create(kvm);
67*0dff3501SAnup Patel 
68*0dff3501SAnup Patel 	/* Fail if irqchip unknown */
69*0dff3501SAnup Patel 	if (riscv_irqchip == IRQCHIP_UNKNOWN)
70*0dff3501SAnup Patel 		die("No IRQCHIP found\n");
712e996783SAnup Patel }
72