xref: /kvmtool/arm/gic.c (revision a5d36dd12d40380024e4c905f11b43a55fd2523b)
17c0e8b0cSWill Deacon #include "kvm/fdt.h"
2bed2bd9eSMarc Zyngier #include "kvm/irq.h"
37c0e8b0cSWill Deacon #include "kvm/kvm.h"
47c0e8b0cSWill Deacon #include "kvm/virtio.h"
57c0e8b0cSWill Deacon 
67c0e8b0cSWill Deacon #include "arm-common/gic.h"
77c0e8b0cSWill Deacon 
87c0e8b0cSWill Deacon #include <linux/byteorder.h>
9bed2bd9eSMarc Zyngier #include <linux/kernel.h>
107c0e8b0cSWill Deacon #include <linux/kvm.h>
1112ca1401SAndre Przywara #include <linux/sizes.h>
127c0e8b0cSWill Deacon 
1369ae77c5SAndre Przywara #define IRQCHIP_GIC 0
1469ae77c5SAndre Przywara 
1569b9a17aSMarc Zyngier static int gic_fd = -1;
16bfb2c703SAndre Przywara static u64 gic_redists_base;
17bfb2c703SAndre Przywara static u64 gic_redists_size;
1812ca1401SAndre Przywara static u64 gic_msi_base;
1912ca1401SAndre Przywara static u64 gic_msi_size = 0;
2069b9a17aSMarc Zyngier 
2143d2781cSAndre Przywara int irqchip_parser(const struct option *opt, const char *arg, int unset)
2243d2781cSAndre Przywara {
2343d2781cSAndre Przywara 	enum irqchip_type *type = opt->value;
2443d2781cSAndre Przywara 
2543d2781cSAndre Przywara 	if (!strcmp(arg, "gicv2")) {
2643d2781cSAndre Przywara 		*type = IRQCHIP_GICV2;
27f6108d72SJean-Philippe Brucker 	} else if (!strcmp(arg, "gicv2m")) {
28f6108d72SJean-Philippe Brucker 		*type = IRQCHIP_GICV2M;
2943d2781cSAndre Przywara 	} else if (!strcmp(arg, "gicv3")) {
3043d2781cSAndre Przywara 		*type = IRQCHIP_GICV3;
3176392d29SAndre Przywara 	} else if (!strcmp(arg, "gicv3-its")) {
3276392d29SAndre Przywara 		*type = IRQCHIP_GICV3_ITS;
3343d2781cSAndre Przywara 	} else {
3443d2781cSAndre Przywara 		pr_err("irqchip: unknown type \"%s\"\n", arg);
3543d2781cSAndre Przywara 		return -1;
3643d2781cSAndre Przywara 	}
3743d2781cSAndre Przywara 
3843d2781cSAndre Przywara 	return 0;
3943d2781cSAndre Przywara }
4043d2781cSAndre Przywara 
4169ae77c5SAndre Przywara static int irq__routing_init(struct kvm *kvm)
4269ae77c5SAndre Przywara {
4369ae77c5SAndre Przywara 	int r;
4469ae77c5SAndre Przywara 	int irqlines = ALIGN(irq__get_nr_allocated_lines(), 32);
4569ae77c5SAndre Przywara 
4669ae77c5SAndre Przywara 	/*
4769ae77c5SAndre Przywara 	 * This describes the default routing that the kernel uses without
4869ae77c5SAndre Przywara 	 * any routing explicitly set up via KVM_SET_GSI_ROUTING. So we
4969ae77c5SAndre Przywara 	 * don't need to commit these setting right now. The first actual
5069ae77c5SAndre Przywara 	 * user (MSI routing) will engage these mappings then.
5169ae77c5SAndre Przywara 	 */
5269ae77c5SAndre Przywara 	for (next_gsi = 0; next_gsi < irqlines; next_gsi++) {
5369ae77c5SAndre Przywara 		r = irq__allocate_routing_entry();
5469ae77c5SAndre Przywara 		if (r)
5569ae77c5SAndre Przywara 			return r;
5669ae77c5SAndre Przywara 
5769ae77c5SAndre Przywara 		irq_routing->entries[irq_routing->nr++] =
5869ae77c5SAndre Przywara 			(struct kvm_irq_routing_entry) {
5969ae77c5SAndre Przywara 				.gsi = next_gsi,
6069ae77c5SAndre Przywara 				.type = KVM_IRQ_ROUTING_IRQCHIP,
6169ae77c5SAndre Przywara 				.u.irqchip.irqchip = IRQCHIP_GIC,
6269ae77c5SAndre Przywara 				.u.irqchip.pin = next_gsi,
6369ae77c5SAndre Przywara 		};
6469ae77c5SAndre Przywara 	}
6569ae77c5SAndre Przywara 
6669ae77c5SAndre Przywara 	return 0;
6769ae77c5SAndre Przywara }
6869ae77c5SAndre Przywara 
6912ca1401SAndre Przywara static int gic__create_its_frame(struct kvm *kvm, u64 its_frame_addr)
7012ca1401SAndre Przywara {
7112ca1401SAndre Przywara 	struct kvm_create_device its_device = {
7212ca1401SAndre Przywara 		.type = KVM_DEV_TYPE_ARM_VGIC_ITS,
7312ca1401SAndre Przywara 		.flags	= 0,
7412ca1401SAndre Przywara 	};
7512ca1401SAndre Przywara 	struct kvm_device_attr its_attr = {
7612ca1401SAndre Przywara 		.group	= KVM_DEV_ARM_VGIC_GRP_ADDR,
7712ca1401SAndre Przywara 		.attr	= KVM_VGIC_ITS_ADDR_TYPE,
7812ca1401SAndre Przywara 		.addr	= (u64)(unsigned long)&its_frame_addr,
7912ca1401SAndre Przywara 	};
8012ca1401SAndre Przywara 	struct kvm_device_attr its_init_attr = {
8112ca1401SAndre Przywara 		.group	= KVM_DEV_ARM_VGIC_GRP_CTRL,
8212ca1401SAndre Przywara 		.attr	= KVM_DEV_ARM_VGIC_CTRL_INIT,
8312ca1401SAndre Przywara 	};
8412ca1401SAndre Przywara 	int err;
8512ca1401SAndre Przywara 
8612ca1401SAndre Przywara 	err = ioctl(kvm->vm_fd, KVM_CREATE_DEVICE, &its_device);
8712ca1401SAndre Przywara 	if (err) {
8812ca1401SAndre Przywara 		fprintf(stderr,
8912ca1401SAndre Przywara 			"GICv3 ITS requested, but kernel does not support it.\n");
9012ca1401SAndre Przywara 		fprintf(stderr, "Try --irqchip=gicv3 instead\n");
9112ca1401SAndre Przywara 		return err;
9212ca1401SAndre Przywara 	}
9312ca1401SAndre Przywara 
9412ca1401SAndre Przywara 	err = ioctl(its_device.fd, KVM_HAS_DEVICE_ATTR, &its_attr);
9512ca1401SAndre Przywara 	if (err) {
9612ca1401SAndre Przywara 		close(its_device.fd);
9712ca1401SAndre Przywara 		its_device.fd = -1;
9812ca1401SAndre Przywara 		return err;
9912ca1401SAndre Przywara 	}
10012ca1401SAndre Przywara 
10112ca1401SAndre Przywara 	err = ioctl(its_device.fd, KVM_SET_DEVICE_ATTR, &its_attr);
10212ca1401SAndre Przywara 	if (err)
10312ca1401SAndre Przywara 		return err;
10412ca1401SAndre Przywara 
10512ca1401SAndre Przywara 	return ioctl(its_device.fd, KVM_SET_DEVICE_ATTR, &its_init_attr);
10612ca1401SAndre Przywara }
10712ca1401SAndre Przywara 
10812ca1401SAndre Przywara static int gic__create_msi_frame(struct kvm *kvm, enum irqchip_type type,
10912ca1401SAndre Przywara 				 u64 msi_frame_addr)
11012ca1401SAndre Przywara {
11112ca1401SAndre Przywara 	switch (type) {
112f6108d72SJean-Philippe Brucker 	case IRQCHIP_GICV2M:
113f6108d72SJean-Philippe Brucker 		return gic__create_gicv2m_frame(kvm, msi_frame_addr);
11412ca1401SAndre Przywara 	case IRQCHIP_GICV3_ITS:
11512ca1401SAndre Przywara 		return gic__create_its_frame(kvm, msi_frame_addr);
11612ca1401SAndre Przywara 	default:	/* No MSI frame needed */
11712ca1401SAndre Przywara 		return 0;
11812ca1401SAndre Przywara 	}
11912ca1401SAndre Przywara }
12012ca1401SAndre Przywara 
12102017c1dSAndre Przywara static int gic__create_device(struct kvm *kvm, enum irqchip_type type)
12269b9a17aSMarc Zyngier {
12369b9a17aSMarc Zyngier 	int err;
12469b9a17aSMarc Zyngier 	u64 cpu_if_addr = ARM_GIC_CPUI_BASE;
12569b9a17aSMarc Zyngier 	u64 dist_addr = ARM_GIC_DIST_BASE;
12669b9a17aSMarc Zyngier 	struct kvm_create_device gic_device = {
12702017c1dSAndre Przywara 		.flags	= 0,
12869b9a17aSMarc Zyngier 	};
12969b9a17aSMarc Zyngier 	struct kvm_device_attr cpu_if_attr = {
13069b9a17aSMarc Zyngier 		.group	= KVM_DEV_ARM_VGIC_GRP_ADDR,
13169b9a17aSMarc Zyngier 		.attr	= KVM_VGIC_V2_ADDR_TYPE_CPU,
13269b9a17aSMarc Zyngier 		.addr	= (u64)(unsigned long)&cpu_if_addr,
13369b9a17aSMarc Zyngier 	};
13469b9a17aSMarc Zyngier 	struct kvm_device_attr dist_attr = {
13569b9a17aSMarc Zyngier 		.group	= KVM_DEV_ARM_VGIC_GRP_ADDR,
13669b9a17aSMarc Zyngier 		.addr	= (u64)(unsigned long)&dist_addr,
13769b9a17aSMarc Zyngier 	};
138bfb2c703SAndre Przywara 	struct kvm_device_attr redist_attr = {
139bfb2c703SAndre Przywara 		.group	= KVM_DEV_ARM_VGIC_GRP_ADDR,
140bfb2c703SAndre Przywara 		.attr	= KVM_VGIC_V3_ADDR_TYPE_REDIST,
141bfb2c703SAndre Przywara 		.addr	= (u64)(unsigned long)&gic_redists_base,
142bfb2c703SAndre Przywara 	};
14369b9a17aSMarc Zyngier 
14402017c1dSAndre Przywara 	switch (type) {
145f6108d72SJean-Philippe Brucker 	case IRQCHIP_GICV2M:
14602017c1dSAndre Przywara 	case IRQCHIP_GICV2:
14702017c1dSAndre Przywara 		gic_device.type = KVM_DEV_TYPE_ARM_VGIC_V2;
14802017c1dSAndre Przywara 		dist_attr.attr  = KVM_VGIC_V2_ADDR_TYPE_DIST;
14902017c1dSAndre Przywara 		break;
150bfb2c703SAndre Przywara 	case IRQCHIP_GICV3:
15112ca1401SAndre Przywara 	case IRQCHIP_GICV3_ITS:
152bfb2c703SAndre Przywara 		gic_device.type = KVM_DEV_TYPE_ARM_VGIC_V3;
153bfb2c703SAndre Przywara 		dist_attr.attr  = KVM_VGIC_V3_ADDR_TYPE_DIST;
154bfb2c703SAndre Przywara 		break;
15502017c1dSAndre Przywara 	}
15602017c1dSAndre Przywara 
15769b9a17aSMarc Zyngier 	err = ioctl(kvm->vm_fd, KVM_CREATE_DEVICE, &gic_device);
15869b9a17aSMarc Zyngier 	if (err)
15969b9a17aSMarc Zyngier 		return err;
16069b9a17aSMarc Zyngier 
16169b9a17aSMarc Zyngier 	gic_fd = gic_device.fd;
16269b9a17aSMarc Zyngier 
16302017c1dSAndre Przywara 	switch (type) {
164f6108d72SJean-Philippe Brucker 	case IRQCHIP_GICV2M:
16502017c1dSAndre Przywara 	case IRQCHIP_GICV2:
16669b9a17aSMarc Zyngier 		err = ioctl(gic_fd, KVM_SET_DEVICE_ATTR, &cpu_if_attr);
16702017c1dSAndre Przywara 		break;
16812ca1401SAndre Przywara 	case IRQCHIP_GICV3_ITS:
169bfb2c703SAndre Przywara 	case IRQCHIP_GICV3:
170bfb2c703SAndre Przywara 		err = ioctl(gic_fd, KVM_SET_DEVICE_ATTR, &redist_attr);
171bfb2c703SAndre Przywara 		break;
17202017c1dSAndre Przywara 	}
17369b9a17aSMarc Zyngier 	if (err)
17469b9a17aSMarc Zyngier 		goto out_err;
17569b9a17aSMarc Zyngier 
17669b9a17aSMarc Zyngier 	err = ioctl(gic_fd, KVM_SET_DEVICE_ATTR, &dist_attr);
17769b9a17aSMarc Zyngier 	if (err)
17869b9a17aSMarc Zyngier 		goto out_err;
17969b9a17aSMarc Zyngier 
18012ca1401SAndre Przywara 	err = gic__create_msi_frame(kvm, type, gic_msi_base);
18112ca1401SAndre Przywara 	if (err)
18212ca1401SAndre Przywara 		goto out_err;
18312ca1401SAndre Przywara 
18469b9a17aSMarc Zyngier 	return 0;
18569b9a17aSMarc Zyngier 
18669b9a17aSMarc Zyngier out_err:
18769b9a17aSMarc Zyngier 	close(gic_fd);
18869b9a17aSMarc Zyngier 	gic_fd = -1;
18969b9a17aSMarc Zyngier 	return err;
19069b9a17aSMarc Zyngier }
19169b9a17aSMarc Zyngier 
19269b9a17aSMarc Zyngier static int gic__create_irqchip(struct kvm *kvm)
1937c0e8b0cSWill Deacon {
1947c0e8b0cSWill Deacon 	int err;
195aa7a0e79SWill Deacon 	struct kvm_arm_device_addr gic_addr[] = {
1967c0e8b0cSWill Deacon 		[0] = {
197aa7a0e79SWill Deacon 			.id = KVM_VGIC_V2_ADDR_TYPE_DIST |
198aa7a0e79SWill Deacon 			(KVM_ARM_DEVICE_VGIC_V2 << KVM_ARM_DEVICE_ID_SHIFT),
1997c0e8b0cSWill Deacon 			.addr = ARM_GIC_DIST_BASE,
2007c0e8b0cSWill Deacon 		},
2017c0e8b0cSWill Deacon 		[1] = {
202aa7a0e79SWill Deacon 			.id = KVM_VGIC_V2_ADDR_TYPE_CPU |
203aa7a0e79SWill Deacon 			(KVM_ARM_DEVICE_VGIC_V2 << KVM_ARM_DEVICE_ID_SHIFT),
2047c0e8b0cSWill Deacon 			.addr = ARM_GIC_CPUI_BASE,
2057c0e8b0cSWill Deacon 		}
2067c0e8b0cSWill Deacon 	};
2077c0e8b0cSWill Deacon 
2087c0e8b0cSWill Deacon 	err = ioctl(kvm->vm_fd, KVM_CREATE_IRQCHIP);
2097c0e8b0cSWill Deacon 	if (err)
2107c0e8b0cSWill Deacon 		return err;
2117c0e8b0cSWill Deacon 
212aa7a0e79SWill Deacon 	err = ioctl(kvm->vm_fd, KVM_ARM_SET_DEVICE_ADDR, &gic_addr[0]);
2137c0e8b0cSWill Deacon 	if (err)
2147c0e8b0cSWill Deacon 		return err;
2157c0e8b0cSWill Deacon 
216aa7a0e79SWill Deacon 	err = ioctl(kvm->vm_fd, KVM_ARM_SET_DEVICE_ADDR, &gic_addr[1]);
2177c0e8b0cSWill Deacon 	return err;
2187c0e8b0cSWill Deacon }
2197c0e8b0cSWill Deacon 
22002017c1dSAndre Przywara int gic__create(struct kvm *kvm, enum irqchip_type type)
22169b9a17aSMarc Zyngier {
22269b9a17aSMarc Zyngier 	int err;
22369b9a17aSMarc Zyngier 
22402017c1dSAndre Przywara 	switch (type) {
225f6108d72SJean-Philippe Brucker 	case IRQCHIP_GICV2M:
226f6108d72SJean-Philippe Brucker 		gic_msi_size = KVM_VGIC_V2M_SIZE;
227f6108d72SJean-Philippe Brucker 		gic_msi_base = ARM_GIC_DIST_BASE - gic_msi_size;
228f6108d72SJean-Philippe Brucker 		break;
22902017c1dSAndre Przywara 	case IRQCHIP_GICV2:
23002017c1dSAndre Przywara 		break;
23112ca1401SAndre Przywara 	case IRQCHIP_GICV3_ITS:
232*a5d36dd1SAndre Przywara 		/* The 64K page with the doorbell is included. */
233*a5d36dd1SAndre Przywara 		gic_msi_size = KVM_VGIC_V3_ITS_SIZE;
23412ca1401SAndre Przywara 		/* fall through */
235bfb2c703SAndre Przywara 	case IRQCHIP_GICV3:
236bfb2c703SAndre Przywara 		gic_redists_size = kvm->cfg.nrcpus * ARM_GIC_REDIST_SIZE;
237bfb2c703SAndre Przywara 		gic_redists_base = ARM_GIC_DIST_BASE - gic_redists_size;
23812ca1401SAndre Przywara 		gic_msi_base = gic_redists_base - gic_msi_size;
239bfb2c703SAndre Przywara 		break;
24002017c1dSAndre Przywara 	default:
24102017c1dSAndre Przywara 		return -ENODEV;
24202017c1dSAndre Przywara 	}
24302017c1dSAndre Przywara 
24469b9a17aSMarc Zyngier 	/* Try the new way first, and fallback on legacy method otherwise */
24502017c1dSAndre Przywara 	err = gic__create_device(kvm, type);
24602017c1dSAndre Przywara 	if (err && type == IRQCHIP_GICV2)
24769b9a17aSMarc Zyngier 		err = gic__create_irqchip(kvm);
24869b9a17aSMarc Zyngier 
24969b9a17aSMarc Zyngier 	return err;
25069b9a17aSMarc Zyngier }
25169b9a17aSMarc Zyngier 
252b5790302SAndre Przywara /*
253b5790302SAndre Przywara  * Sets the number of used interrupts and finalizes the GIC init explicitly.
254b5790302SAndre Przywara  */
255bed2bd9eSMarc Zyngier static int gic__init_gic(struct kvm *kvm)
256bed2bd9eSMarc Zyngier {
257b5790302SAndre Przywara 	int ret;
258b5790302SAndre Przywara 
259bed2bd9eSMarc Zyngier 	int lines = irq__get_nr_allocated_lines();
260bed2bd9eSMarc Zyngier 	u32 nr_irqs = ALIGN(lines, 32) + GIC_SPI_IRQ_BASE;
261bed2bd9eSMarc Zyngier 	struct kvm_device_attr nr_irqs_attr = {
262bed2bd9eSMarc Zyngier 		.group	= KVM_DEV_ARM_VGIC_GRP_NR_IRQS,
263bed2bd9eSMarc Zyngier 		.addr	= (u64)(unsigned long)&nr_irqs,
264bed2bd9eSMarc Zyngier 	};
265b5790302SAndre Przywara 	struct kvm_device_attr vgic_init_attr = {
266b5790302SAndre Przywara 		.group	= KVM_DEV_ARM_VGIC_GRP_CTRL,
267b5790302SAndre Przywara 		.attr	= KVM_DEV_ARM_VGIC_CTRL_INIT,
268b5790302SAndre Przywara 	};
269bed2bd9eSMarc Zyngier 
270bed2bd9eSMarc Zyngier 	/*
271bed2bd9eSMarc Zyngier 	 * If we didn't use the KVM_CREATE_DEVICE method, KVM will
272b5790302SAndre Przywara 	 * give us some default number of interrupts. The GIC initialization
273b5790302SAndre Przywara 	 * will be done automatically in this case.
274bed2bd9eSMarc Zyngier 	 */
275bed2bd9eSMarc Zyngier 	if (gic_fd < 0)
276bed2bd9eSMarc Zyngier 		return 0;
277bed2bd9eSMarc Zyngier 
278b5790302SAndre Przywara 	if (!ioctl(gic_fd, KVM_HAS_DEVICE_ATTR, &nr_irqs_attr)) {
279b5790302SAndre Przywara 		ret = ioctl(gic_fd, KVM_SET_DEVICE_ATTR, &nr_irqs_attr);
280b5790302SAndre Przywara 		if (ret)
281b5790302SAndre Przywara 			return ret;
282b5790302SAndre Przywara 	}
283b5790302SAndre Przywara 
28469ae77c5SAndre Przywara 	irq__routing_init(kvm);
28569ae77c5SAndre Przywara 
286b5790302SAndre Przywara 	if (!ioctl(gic_fd, KVM_HAS_DEVICE_ATTR, &vgic_init_attr)) {
287b5790302SAndre Przywara 		ret = ioctl(gic_fd, KVM_SET_DEVICE_ATTR, &vgic_init_attr);
288b5790302SAndre Przywara 		if (ret)
289b5790302SAndre Przywara 			return ret;
290b5790302SAndre Przywara 	}
291bed2bd9eSMarc Zyngier 
292714ab9e6SAndre Przywara 	kvm->msix_needs_devid = kvm__supports_vm_extension(kvm,
293714ab9e6SAndre Przywara 							   KVM_CAP_MSI_DEVID);
294714ab9e6SAndre Przywara 
295bed2bd9eSMarc Zyngier 	return 0;
296bed2bd9eSMarc Zyngier }
297bed2bd9eSMarc Zyngier late_init(gic__init_gic)
298bed2bd9eSMarc Zyngier 
2990063d50cSAndre Przywara void gic__generate_fdt_nodes(void *fdt, enum irqchip_type type)
3007c0e8b0cSWill Deacon {
30114421de9SAndre Przywara 	const char *compatible, *msi_compatible = NULL;
30214421de9SAndre Przywara 	u64 msi_prop[2];
3037c0e8b0cSWill Deacon 	u64 reg_prop[] = {
3047c0e8b0cSWill Deacon 		cpu_to_fdt64(ARM_GIC_DIST_BASE), cpu_to_fdt64(ARM_GIC_DIST_SIZE),
305bfb2c703SAndre Przywara 		0, 0,				/* to be filled */
3067c0e8b0cSWill Deacon 	};
3077c0e8b0cSWill Deacon 
30802017c1dSAndre Przywara 	switch (type) {
309f6108d72SJean-Philippe Brucker 	case IRQCHIP_GICV2M:
310f6108d72SJean-Philippe Brucker 		msi_compatible = "arm,gic-v2m-frame";
311f6108d72SJean-Philippe Brucker 		/* fall-through */
31202017c1dSAndre Przywara 	case IRQCHIP_GICV2:
31302017c1dSAndre Przywara 		compatible = "arm,cortex-a15-gic";
314bfb2c703SAndre Przywara 		reg_prop[2] = cpu_to_fdt64(ARM_GIC_CPUI_BASE);
315bfb2c703SAndre Przywara 		reg_prop[3] = cpu_to_fdt64(ARM_GIC_CPUI_SIZE);
316bfb2c703SAndre Przywara 		break;
31714421de9SAndre Przywara 	case IRQCHIP_GICV3_ITS:
31814421de9SAndre Przywara 		msi_compatible = "arm,gic-v3-its";
31914421de9SAndre Przywara 		/* fall-through */
320bfb2c703SAndre Przywara 	case IRQCHIP_GICV3:
321bfb2c703SAndre Przywara 		compatible = "arm,gic-v3";
322bfb2c703SAndre Przywara 		reg_prop[2] = cpu_to_fdt64(gic_redists_base);
323bfb2c703SAndre Przywara 		reg_prop[3] = cpu_to_fdt64(gic_redists_size);
32402017c1dSAndre Przywara 		break;
32502017c1dSAndre Przywara 	default:
32602017c1dSAndre Przywara 		return;
32702017c1dSAndre Przywara 	}
32802017c1dSAndre Przywara 
3297c0e8b0cSWill Deacon 	_FDT(fdt_begin_node(fdt, "intc"));
33002017c1dSAndre Przywara 	_FDT(fdt_property_string(fdt, "compatible", compatible));
3317c0e8b0cSWill Deacon 	_FDT(fdt_property_cell(fdt, "#interrupt-cells", GIC_FDT_IRQ_NUM_CELLS));
3327c0e8b0cSWill Deacon 	_FDT(fdt_property(fdt, "interrupt-controller", NULL, 0));
3337c0e8b0cSWill Deacon 	_FDT(fdt_property(fdt, "reg", reg_prop, sizeof(reg_prop)));
3340063d50cSAndre Przywara 	_FDT(fdt_property_cell(fdt, "phandle", PHANDLE_GIC));
33514421de9SAndre Przywara 	_FDT(fdt_property_cell(fdt, "#address-cells", 2));
33614421de9SAndre Przywara 	_FDT(fdt_property_cell(fdt, "#size-cells", 2));
33714421de9SAndre Przywara 
33814421de9SAndre Przywara 	if (msi_compatible) {
33914421de9SAndre Przywara 		_FDT(fdt_property(fdt, "ranges", NULL, 0));
34014421de9SAndre Przywara 
34114421de9SAndre Przywara 		_FDT(fdt_begin_node(fdt, "msic"));
34214421de9SAndre Przywara 		_FDT(fdt_property_string(fdt, "compatible", msi_compatible));
34314421de9SAndre Przywara 		_FDT(fdt_property(fdt, "msi-controller", NULL, 0));
34414421de9SAndre Przywara 		_FDT(fdt_property_cell(fdt, "phandle", PHANDLE_MSI));
34514421de9SAndre Przywara 		msi_prop[0] = cpu_to_fdt64(gic_msi_base);
34614421de9SAndre Przywara 		msi_prop[1] = cpu_to_fdt64(gic_msi_size);
34714421de9SAndre Przywara 		_FDT(fdt_property(fdt, "reg", msi_prop, sizeof(msi_prop)));
34814421de9SAndre Przywara 		_FDT(fdt_end_node(fdt));
34914421de9SAndre Przywara 	}
35014421de9SAndre Przywara 
3517c0e8b0cSWill Deacon 	_FDT(fdt_end_node(fdt));
3527c0e8b0cSWill Deacon }
3537c0e8b0cSWill Deacon 
3547c0e8b0cSWill Deacon #define KVM_IRQCHIP_IRQ(x) (KVM_ARM_IRQ_TYPE_SPI << KVM_ARM_IRQ_TYPE_SHIFT) |\
3557c0e8b0cSWill Deacon 			   ((x) & KVM_ARM_IRQ_NUM_MASK)
3567c0e8b0cSWill Deacon 
3577c0e8b0cSWill Deacon void kvm__irq_line(struct kvm *kvm, int irq, int level)
3587c0e8b0cSWill Deacon {
3597c0e8b0cSWill Deacon 	struct kvm_irq_level irq_level = {
3607c0e8b0cSWill Deacon 		.irq	= KVM_IRQCHIP_IRQ(irq),
3617c0e8b0cSWill Deacon 		.level	= !!level,
3627c0e8b0cSWill Deacon 	};
3637c0e8b0cSWill Deacon 
3647c0e8b0cSWill Deacon 	if (irq < GIC_SPI_IRQ_BASE || irq > GIC_MAX_IRQ)
3657c0e8b0cSWill Deacon 		pr_warning("Ignoring invalid GIC IRQ %d", irq);
3667c0e8b0cSWill Deacon 	else if (ioctl(kvm->vm_fd, KVM_IRQ_LINE, &irq_level) < 0)
3677c0e8b0cSWill Deacon 		pr_warning("Could not KVM_IRQ_LINE for irq %d", irq);
3687c0e8b0cSWill Deacon }
3697c0e8b0cSWill Deacon 
3707c0e8b0cSWill Deacon void kvm__irq_trigger(struct kvm *kvm, int irq)
3717c0e8b0cSWill Deacon {
3727c0e8b0cSWill Deacon 	kvm__irq_line(kvm, irq, VIRTIO_IRQ_HIGH);
3737c0e8b0cSWill Deacon 	kvm__irq_line(kvm, irq, VIRTIO_IRQ_LOW);
3747c0e8b0cSWill Deacon }
375