xref: /openbmc/linux/arch/arm64/kvm/vgic/vgic-mmio.h (revision 38cf0bb7)
19ed24f4bSMarc Zyngier /* SPDX-License-Identifier: GPL-2.0-only */
29ed24f4bSMarc Zyngier /*
39ed24f4bSMarc Zyngier  * Copyright (C) 2015, 2016 ARM Ltd.
49ed24f4bSMarc Zyngier  */
59ed24f4bSMarc Zyngier #ifndef __KVM_ARM_VGIC_MMIO_H__
69ed24f4bSMarc Zyngier #define __KVM_ARM_VGIC_MMIO_H__
79ed24f4bSMarc Zyngier 
89ed24f4bSMarc Zyngier struct vgic_register_region {
99ed24f4bSMarc Zyngier 	unsigned int reg_offset;
109ed24f4bSMarc Zyngier 	unsigned int len;
119ed24f4bSMarc Zyngier 	unsigned int bits_per_irq;
129ed24f4bSMarc Zyngier 	unsigned int access_flags;
139ed24f4bSMarc Zyngier 	union {
149ed24f4bSMarc Zyngier 		unsigned long (*read)(struct kvm_vcpu *vcpu, gpa_t addr,
159ed24f4bSMarc Zyngier 				      unsigned int len);
169ed24f4bSMarc Zyngier 		unsigned long (*its_read)(struct kvm *kvm, struct vgic_its *its,
179ed24f4bSMarc Zyngier 					  gpa_t addr, unsigned int len);
189ed24f4bSMarc Zyngier 	};
199ed24f4bSMarc Zyngier 	union {
209ed24f4bSMarc Zyngier 		void (*write)(struct kvm_vcpu *vcpu, gpa_t addr,
219ed24f4bSMarc Zyngier 			      unsigned int len, unsigned long val);
229ed24f4bSMarc Zyngier 		void (*its_write)(struct kvm *kvm, struct vgic_its *its,
239ed24f4bSMarc Zyngier 				  gpa_t addr, unsigned int len,
249ed24f4bSMarc Zyngier 				  unsigned long val);
259ed24f4bSMarc Zyngier 	};
269ed24f4bSMarc Zyngier 	unsigned long (*uaccess_read)(struct kvm_vcpu *vcpu, gpa_t addr,
279ed24f4bSMarc Zyngier 				      unsigned int len);
289ed24f4bSMarc Zyngier 	union {
299ed24f4bSMarc Zyngier 		int (*uaccess_write)(struct kvm_vcpu *vcpu, gpa_t addr,
309ed24f4bSMarc Zyngier 				     unsigned int len, unsigned long val);
319ed24f4bSMarc Zyngier 		int (*uaccess_its_write)(struct kvm *kvm, struct vgic_its *its,
329ed24f4bSMarc Zyngier 					 gpa_t addr, unsigned int len,
339ed24f4bSMarc Zyngier 					 unsigned long val);
349ed24f4bSMarc Zyngier 	};
359ed24f4bSMarc Zyngier };
369ed24f4bSMarc Zyngier 
37636dcd02SRikard Falkeborn extern const struct kvm_io_device_ops kvm_io_gic_ops;
389ed24f4bSMarc Zyngier 
399ed24f4bSMarc Zyngier #define VGIC_ACCESS_8bit	1
409ed24f4bSMarc Zyngier #define VGIC_ACCESS_32bit	2
419ed24f4bSMarc Zyngier #define VGIC_ACCESS_64bit	4
429ed24f4bSMarc Zyngier 
439ed24f4bSMarc Zyngier /*
449ed24f4bSMarc Zyngier  * Generate a mask that covers the number of bytes required to address
459ed24f4bSMarc Zyngier  * up to 1024 interrupts, each represented by <bits> bits. This assumes
469ed24f4bSMarc Zyngier  * that <bits> is a power of two.
479ed24f4bSMarc Zyngier  */
489ed24f4bSMarc Zyngier #define VGIC_ADDR_IRQ_MASK(bits) (((bits) * 1024 / 8) - 1)
499ed24f4bSMarc Zyngier 
509ed24f4bSMarc Zyngier /*
519ed24f4bSMarc Zyngier  * (addr & mask) gives us the _byte_ offset for the INT ID.
529ed24f4bSMarc Zyngier  * We multiply this by 8 the get the _bit_ offset, then divide this by
539ed24f4bSMarc Zyngier  * the number of bits to learn the actual INT ID.
549ed24f4bSMarc Zyngier  * But instead of a division (which requires a "long long div" implementation),
559ed24f4bSMarc Zyngier  * we shift by the binary logarithm of <bits>.
569ed24f4bSMarc Zyngier  * This assumes that <bits> is a power of two.
579ed24f4bSMarc Zyngier  */
589ed24f4bSMarc Zyngier #define VGIC_ADDR_TO_INTID(addr, bits)  (((addr) & VGIC_ADDR_IRQ_MASK(bits)) * \
599ed24f4bSMarc Zyngier 					8 >> ilog2(bits))
609ed24f4bSMarc Zyngier 
619ed24f4bSMarc Zyngier /*
629ed24f4bSMarc Zyngier  * Some VGIC registers store per-IRQ information, with a different number
639ed24f4bSMarc Zyngier  * of bits per IRQ. For those registers this macro is used.
649ed24f4bSMarc Zyngier  * The _WITH_LENGTH version instantiates registers with a fixed length
659ed24f4bSMarc Zyngier  * and is mutually exclusive with the _PER_IRQ version.
669ed24f4bSMarc Zyngier  */
679ed24f4bSMarc Zyngier #define REGISTER_DESC_WITH_BITS_PER_IRQ(off, rd, wr, ur, uw, bpi, acc)	\
689ed24f4bSMarc Zyngier 	{								\
699ed24f4bSMarc Zyngier 		.reg_offset = off,					\
709ed24f4bSMarc Zyngier 		.bits_per_irq = bpi,					\
719ed24f4bSMarc Zyngier 		.len = bpi * 1024 / 8,					\
729ed24f4bSMarc Zyngier 		.access_flags = acc,					\
739ed24f4bSMarc Zyngier 		.read = rd,						\
749ed24f4bSMarc Zyngier 		.write = wr,						\
759ed24f4bSMarc Zyngier 		.uaccess_read = ur,					\
769ed24f4bSMarc Zyngier 		.uaccess_write = uw,					\
779ed24f4bSMarc Zyngier 	}
789ed24f4bSMarc Zyngier 
799ed24f4bSMarc Zyngier #define REGISTER_DESC_WITH_LENGTH(off, rd, wr, length, acc)		\
809ed24f4bSMarc Zyngier 	{								\
819ed24f4bSMarc Zyngier 		.reg_offset = off,					\
829ed24f4bSMarc Zyngier 		.bits_per_irq = 0,					\
839ed24f4bSMarc Zyngier 		.len = length,						\
849ed24f4bSMarc Zyngier 		.access_flags = acc,					\
859ed24f4bSMarc Zyngier 		.read = rd,						\
869ed24f4bSMarc Zyngier 		.write = wr,						\
879ed24f4bSMarc Zyngier 	}
889ed24f4bSMarc Zyngier 
899ed24f4bSMarc Zyngier #define REGISTER_DESC_WITH_LENGTH_UACCESS(off, rd, wr, urd, uwr, length, acc) \
909ed24f4bSMarc Zyngier 	{								\
919ed24f4bSMarc Zyngier 		.reg_offset = off,					\
929ed24f4bSMarc Zyngier 		.bits_per_irq = 0,					\
939ed24f4bSMarc Zyngier 		.len = length,						\
949ed24f4bSMarc Zyngier 		.access_flags = acc,					\
959ed24f4bSMarc Zyngier 		.read = rd,						\
969ed24f4bSMarc Zyngier 		.write = wr,						\
979ed24f4bSMarc Zyngier 		.uaccess_read = urd,					\
989ed24f4bSMarc Zyngier 		.uaccess_write = uwr,					\
999ed24f4bSMarc Zyngier 	}
1009ed24f4bSMarc Zyngier 
1019ed24f4bSMarc Zyngier unsigned long vgic_data_mmio_bus_to_host(const void *val, unsigned int len);
1029ed24f4bSMarc Zyngier 
1039ed24f4bSMarc Zyngier void vgic_data_host_to_mmio_bus(void *buf, unsigned int len,
1049ed24f4bSMarc Zyngier 				unsigned long data);
1059ed24f4bSMarc Zyngier 
1069ed24f4bSMarc Zyngier unsigned long extract_bytes(u64 data, unsigned int offset,
1079ed24f4bSMarc Zyngier 			    unsigned int num);
1089ed24f4bSMarc Zyngier 
1099ed24f4bSMarc Zyngier u64 update_64bit_reg(u64 reg, unsigned int offset, unsigned int len,
1109ed24f4bSMarc Zyngier 		     unsigned long val);
1119ed24f4bSMarc Zyngier 
1129ed24f4bSMarc Zyngier unsigned long vgic_mmio_read_raz(struct kvm_vcpu *vcpu,
1139ed24f4bSMarc Zyngier 				 gpa_t addr, unsigned int len);
1149ed24f4bSMarc Zyngier 
1159ed24f4bSMarc Zyngier unsigned long vgic_mmio_read_rao(struct kvm_vcpu *vcpu,
1169ed24f4bSMarc Zyngier 				 gpa_t addr, unsigned int len);
1179ed24f4bSMarc Zyngier 
1189ed24f4bSMarc Zyngier void vgic_mmio_write_wi(struct kvm_vcpu *vcpu, gpa_t addr,
1199ed24f4bSMarc Zyngier 			unsigned int len, unsigned long val);
1209ed24f4bSMarc Zyngier 
1219ed24f4bSMarc Zyngier int vgic_mmio_uaccess_write_wi(struct kvm_vcpu *vcpu, gpa_t addr,
1229ed24f4bSMarc Zyngier 			       unsigned int len, unsigned long val);
1239ed24f4bSMarc Zyngier 
1249ed24f4bSMarc Zyngier unsigned long vgic_mmio_read_group(struct kvm_vcpu *vcpu, gpa_t addr,
1259ed24f4bSMarc Zyngier 				   unsigned int len);
1269ed24f4bSMarc Zyngier 
1279ed24f4bSMarc Zyngier void vgic_mmio_write_group(struct kvm_vcpu *vcpu, gpa_t addr,
1289ed24f4bSMarc Zyngier 			   unsigned int len, unsigned long val);
1299ed24f4bSMarc Zyngier 
1309ed24f4bSMarc Zyngier unsigned long vgic_mmio_read_enable(struct kvm_vcpu *vcpu,
1319ed24f4bSMarc Zyngier 				    gpa_t addr, unsigned int len);
1329ed24f4bSMarc Zyngier 
1339ed24f4bSMarc Zyngier void vgic_mmio_write_senable(struct kvm_vcpu *vcpu,
1349ed24f4bSMarc Zyngier 			     gpa_t addr, unsigned int len,
1359ed24f4bSMarc Zyngier 			     unsigned long val);
1369ed24f4bSMarc Zyngier 
1379ed24f4bSMarc Zyngier void vgic_mmio_write_cenable(struct kvm_vcpu *vcpu,
1389ed24f4bSMarc Zyngier 			     gpa_t addr, unsigned int len,
1399ed24f4bSMarc Zyngier 			     unsigned long val);
1409ed24f4bSMarc Zyngier 
1419ed24f4bSMarc Zyngier int vgic_uaccess_write_senable(struct kvm_vcpu *vcpu,
1429ed24f4bSMarc Zyngier 			       gpa_t addr, unsigned int len,
1439ed24f4bSMarc Zyngier 			       unsigned long val);
1449ed24f4bSMarc Zyngier 
1459ed24f4bSMarc Zyngier int vgic_uaccess_write_cenable(struct kvm_vcpu *vcpu,
1469ed24f4bSMarc Zyngier 			       gpa_t addr, unsigned int len,
1479ed24f4bSMarc Zyngier 			       unsigned long val);
1489ed24f4bSMarc Zyngier 
1499ed24f4bSMarc Zyngier unsigned long vgic_mmio_read_pending(struct kvm_vcpu *vcpu,
1509ed24f4bSMarc Zyngier 				     gpa_t addr, unsigned int len);
1519ed24f4bSMarc Zyngier 
1522cdea19aSMarc Zyngier unsigned long vgic_uaccess_read_pending(struct kvm_vcpu *vcpu,
1532cdea19aSMarc Zyngier 					gpa_t addr, unsigned int len);
1542cdea19aSMarc Zyngier 
1559ed24f4bSMarc Zyngier void vgic_mmio_write_spending(struct kvm_vcpu *vcpu,
1569ed24f4bSMarc Zyngier 			      gpa_t addr, unsigned int len,
1579ed24f4bSMarc Zyngier 			      unsigned long val);
1589ed24f4bSMarc Zyngier 
1599ed24f4bSMarc Zyngier void vgic_mmio_write_cpending(struct kvm_vcpu *vcpu,
1609ed24f4bSMarc Zyngier 			      gpa_t addr, unsigned int len,
1619ed24f4bSMarc Zyngier 			      unsigned long val);
1629ed24f4bSMarc Zyngier 
1639ed24f4bSMarc Zyngier int vgic_uaccess_write_spending(struct kvm_vcpu *vcpu,
1649ed24f4bSMarc Zyngier 				gpa_t addr, unsigned int len,
1659ed24f4bSMarc Zyngier 				unsigned long val);
1669ed24f4bSMarc Zyngier 
1679ed24f4bSMarc Zyngier int vgic_uaccess_write_cpending(struct kvm_vcpu *vcpu,
1689ed24f4bSMarc Zyngier 				gpa_t addr, unsigned int len,
1699ed24f4bSMarc Zyngier 				unsigned long val);
1709ed24f4bSMarc Zyngier 
1719ed24f4bSMarc Zyngier unsigned long vgic_mmio_read_active(struct kvm_vcpu *vcpu,
1729ed24f4bSMarc Zyngier 				    gpa_t addr, unsigned int len);
1739ed24f4bSMarc Zyngier 
1749ed24f4bSMarc Zyngier unsigned long vgic_uaccess_read_active(struct kvm_vcpu *vcpu,
1759ed24f4bSMarc Zyngier 				    gpa_t addr, unsigned int len);
1769ed24f4bSMarc Zyngier 
1779ed24f4bSMarc Zyngier void vgic_mmio_write_cactive(struct kvm_vcpu *vcpu,
1789ed24f4bSMarc Zyngier 			     gpa_t addr, unsigned int len,
1799ed24f4bSMarc Zyngier 			     unsigned long val);
1809ed24f4bSMarc Zyngier 
1819ed24f4bSMarc Zyngier void vgic_mmio_write_sactive(struct kvm_vcpu *vcpu,
1829ed24f4bSMarc Zyngier 			     gpa_t addr, unsigned int len,
1839ed24f4bSMarc Zyngier 			     unsigned long val);
1849ed24f4bSMarc Zyngier 
1859ed24f4bSMarc Zyngier int vgic_mmio_uaccess_write_cactive(struct kvm_vcpu *vcpu,
1869ed24f4bSMarc Zyngier 				    gpa_t addr, unsigned int len,
1879ed24f4bSMarc Zyngier 				    unsigned long val);
1889ed24f4bSMarc Zyngier 
1899ed24f4bSMarc Zyngier int vgic_mmio_uaccess_write_sactive(struct kvm_vcpu *vcpu,
1909ed24f4bSMarc Zyngier 				    gpa_t addr, unsigned int len,
1919ed24f4bSMarc Zyngier 				    unsigned long val);
1929ed24f4bSMarc Zyngier 
1939ed24f4bSMarc Zyngier unsigned long vgic_mmio_read_priority(struct kvm_vcpu *vcpu,
1949ed24f4bSMarc Zyngier 				      gpa_t addr, unsigned int len);
1959ed24f4bSMarc Zyngier 
1969ed24f4bSMarc Zyngier void vgic_mmio_write_priority(struct kvm_vcpu *vcpu,
1979ed24f4bSMarc Zyngier 			      gpa_t addr, unsigned int len,
1989ed24f4bSMarc Zyngier 			      unsigned long val);
1999ed24f4bSMarc Zyngier 
2009ed24f4bSMarc Zyngier unsigned long vgic_mmio_read_config(struct kvm_vcpu *vcpu,
2019ed24f4bSMarc Zyngier 				    gpa_t addr, unsigned int len);
2029ed24f4bSMarc Zyngier 
2039ed24f4bSMarc Zyngier void vgic_mmio_write_config(struct kvm_vcpu *vcpu,
2049ed24f4bSMarc Zyngier 			    gpa_t addr, unsigned int len,
2059ed24f4bSMarc Zyngier 			    unsigned long val);
2069ed24f4bSMarc Zyngier 
2079ed24f4bSMarc Zyngier int vgic_uaccess(struct kvm_vcpu *vcpu, struct vgic_io_device *dev,
2089ed24f4bSMarc Zyngier 		 bool is_write, int offset, u32 *val);
2099ed24f4bSMarc Zyngier 
210*38cf0bb7SMarc Zyngier u32 vgic_read_irq_line_level_info(struct kvm_vcpu *vcpu, u32 intid);
2119ed24f4bSMarc Zyngier 
2129ed24f4bSMarc Zyngier void vgic_write_irq_line_level_info(struct kvm_vcpu *vcpu, u32 intid,
213*38cf0bb7SMarc Zyngier 				    const u32 val);
2149ed24f4bSMarc Zyngier 
2159ed24f4bSMarc Zyngier unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev);
2169ed24f4bSMarc Zyngier 
2179ed24f4bSMarc Zyngier unsigned int vgic_v3_init_dist_iodev(struct vgic_io_device *dev);
2189ed24f4bSMarc Zyngier 
2199ed24f4bSMarc Zyngier u64 vgic_sanitise_outer_cacheability(u64 reg);
2209ed24f4bSMarc Zyngier u64 vgic_sanitise_inner_cacheability(u64 reg);
2219ed24f4bSMarc Zyngier u64 vgic_sanitise_shareability(u64 reg);
2229ed24f4bSMarc Zyngier u64 vgic_sanitise_field(u64 reg, u64 field_mask, int field_shift,
2239ed24f4bSMarc Zyngier 			u64 (*sanitise_fn)(u64));
2249ed24f4bSMarc Zyngier 
2259ed24f4bSMarc Zyngier /* Find the proper register handler entry given a certain address offset */
2269ed24f4bSMarc Zyngier const struct vgic_register_region *
2279ed24f4bSMarc Zyngier vgic_find_mmio_region(const struct vgic_register_region *regions,
2289ed24f4bSMarc Zyngier 		      int nr_regions, unsigned int offset);
2299ed24f4bSMarc Zyngier 
2309ed24f4bSMarc Zyngier #endif
231