18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2015, 2016 ARM Ltd. 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci#ifndef __KVM_ARM_VGIC_MMIO_H__ 68c2ecf20Sopenharmony_ci#define __KVM_ARM_VGIC_MMIO_H__ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_cistruct vgic_register_region { 98c2ecf20Sopenharmony_ci unsigned int reg_offset; 108c2ecf20Sopenharmony_ci unsigned int len; 118c2ecf20Sopenharmony_ci unsigned int bits_per_irq; 128c2ecf20Sopenharmony_ci unsigned int access_flags; 138c2ecf20Sopenharmony_ci union { 148c2ecf20Sopenharmony_ci unsigned long (*read)(struct kvm_vcpu *vcpu, gpa_t addr, 158c2ecf20Sopenharmony_ci unsigned int len); 168c2ecf20Sopenharmony_ci unsigned long (*its_read)(struct kvm *kvm, struct vgic_its *its, 178c2ecf20Sopenharmony_ci gpa_t addr, unsigned int len); 188c2ecf20Sopenharmony_ci }; 198c2ecf20Sopenharmony_ci union { 208c2ecf20Sopenharmony_ci void (*write)(struct kvm_vcpu *vcpu, gpa_t addr, 218c2ecf20Sopenharmony_ci unsigned int len, unsigned long val); 228c2ecf20Sopenharmony_ci void (*its_write)(struct kvm *kvm, struct vgic_its *its, 238c2ecf20Sopenharmony_ci gpa_t addr, unsigned int len, 248c2ecf20Sopenharmony_ci unsigned long val); 258c2ecf20Sopenharmony_ci }; 268c2ecf20Sopenharmony_ci unsigned long (*uaccess_read)(struct kvm_vcpu *vcpu, gpa_t addr, 278c2ecf20Sopenharmony_ci unsigned int len); 288c2ecf20Sopenharmony_ci union { 298c2ecf20Sopenharmony_ci int (*uaccess_write)(struct kvm_vcpu *vcpu, gpa_t addr, 308c2ecf20Sopenharmony_ci unsigned int len, unsigned long val); 318c2ecf20Sopenharmony_ci int (*uaccess_its_write)(struct kvm *kvm, struct vgic_its *its, 328c2ecf20Sopenharmony_ci gpa_t addr, unsigned int len, 338c2ecf20Sopenharmony_ci unsigned long val); 348c2ecf20Sopenharmony_ci }; 358c2ecf20Sopenharmony_ci}; 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ciextern struct kvm_io_device_ops kvm_io_gic_ops; 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci#define VGIC_ACCESS_8bit 1 408c2ecf20Sopenharmony_ci#define VGIC_ACCESS_32bit 2 418c2ecf20Sopenharmony_ci#define VGIC_ACCESS_64bit 4 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci/* 448c2ecf20Sopenharmony_ci * Generate a mask that covers the number of bytes required to address 458c2ecf20Sopenharmony_ci * up to 1024 interrupts, each represented by <bits> bits. This assumes 468c2ecf20Sopenharmony_ci * that <bits> is a power of two. 478c2ecf20Sopenharmony_ci */ 488c2ecf20Sopenharmony_ci#define VGIC_ADDR_IRQ_MASK(bits) (((bits) * 1024 / 8) - 1) 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci/* 518c2ecf20Sopenharmony_ci * (addr & mask) gives us the _byte_ offset for the INT ID. 528c2ecf20Sopenharmony_ci * We multiply this by 8 the get the _bit_ offset, then divide this by 538c2ecf20Sopenharmony_ci * the number of bits to learn the actual INT ID. 548c2ecf20Sopenharmony_ci * But instead of a division (which requires a "long long div" implementation), 558c2ecf20Sopenharmony_ci * we shift by the binary logarithm of <bits>. 568c2ecf20Sopenharmony_ci * This assumes that <bits> is a power of two. 578c2ecf20Sopenharmony_ci */ 588c2ecf20Sopenharmony_ci#define VGIC_ADDR_TO_INTID(addr, bits) (((addr) & VGIC_ADDR_IRQ_MASK(bits)) * \ 598c2ecf20Sopenharmony_ci 8 >> ilog2(bits)) 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci/* 628c2ecf20Sopenharmony_ci * Some VGIC registers store per-IRQ information, with a different number 638c2ecf20Sopenharmony_ci * of bits per IRQ. For those registers this macro is used. 648c2ecf20Sopenharmony_ci * The _WITH_LENGTH version instantiates registers with a fixed length 658c2ecf20Sopenharmony_ci * and is mutually exclusive with the _PER_IRQ version. 668c2ecf20Sopenharmony_ci */ 678c2ecf20Sopenharmony_ci#define REGISTER_DESC_WITH_BITS_PER_IRQ(off, rd, wr, ur, uw, bpi, acc) \ 688c2ecf20Sopenharmony_ci { \ 698c2ecf20Sopenharmony_ci .reg_offset = off, \ 708c2ecf20Sopenharmony_ci .bits_per_irq = bpi, \ 718c2ecf20Sopenharmony_ci .len = bpi * 1024 / 8, \ 728c2ecf20Sopenharmony_ci .access_flags = acc, \ 738c2ecf20Sopenharmony_ci .read = rd, \ 748c2ecf20Sopenharmony_ci .write = wr, \ 758c2ecf20Sopenharmony_ci .uaccess_read = ur, \ 768c2ecf20Sopenharmony_ci .uaccess_write = uw, \ 778c2ecf20Sopenharmony_ci } 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci#define REGISTER_DESC_WITH_LENGTH(off, rd, wr, length, acc) \ 808c2ecf20Sopenharmony_ci { \ 818c2ecf20Sopenharmony_ci .reg_offset = off, \ 828c2ecf20Sopenharmony_ci .bits_per_irq = 0, \ 838c2ecf20Sopenharmony_ci .len = length, \ 848c2ecf20Sopenharmony_ci .access_flags = acc, \ 858c2ecf20Sopenharmony_ci .read = rd, \ 868c2ecf20Sopenharmony_ci .write = wr, \ 878c2ecf20Sopenharmony_ci } 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci#define REGISTER_DESC_WITH_LENGTH_UACCESS(off, rd, wr, urd, uwr, length, acc) \ 908c2ecf20Sopenharmony_ci { \ 918c2ecf20Sopenharmony_ci .reg_offset = off, \ 928c2ecf20Sopenharmony_ci .bits_per_irq = 0, \ 938c2ecf20Sopenharmony_ci .len = length, \ 948c2ecf20Sopenharmony_ci .access_flags = acc, \ 958c2ecf20Sopenharmony_ci .read = rd, \ 968c2ecf20Sopenharmony_ci .write = wr, \ 978c2ecf20Sopenharmony_ci .uaccess_read = urd, \ 988c2ecf20Sopenharmony_ci .uaccess_write = uwr, \ 998c2ecf20Sopenharmony_ci } 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ciunsigned long vgic_data_mmio_bus_to_host(const void *val, unsigned int len); 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_civoid vgic_data_host_to_mmio_bus(void *buf, unsigned int len, 1048c2ecf20Sopenharmony_ci unsigned long data); 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ciunsigned long extract_bytes(u64 data, unsigned int offset, 1078c2ecf20Sopenharmony_ci unsigned int num); 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ciu64 update_64bit_reg(u64 reg, unsigned int offset, unsigned int len, 1108c2ecf20Sopenharmony_ci unsigned long val); 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ciunsigned long vgic_mmio_read_raz(struct kvm_vcpu *vcpu, 1138c2ecf20Sopenharmony_ci gpa_t addr, unsigned int len); 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ciunsigned long vgic_mmio_read_rao(struct kvm_vcpu *vcpu, 1168c2ecf20Sopenharmony_ci gpa_t addr, unsigned int len); 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_civoid vgic_mmio_write_wi(struct kvm_vcpu *vcpu, gpa_t addr, 1198c2ecf20Sopenharmony_ci unsigned int len, unsigned long val); 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ciint vgic_mmio_uaccess_write_wi(struct kvm_vcpu *vcpu, gpa_t addr, 1228c2ecf20Sopenharmony_ci unsigned int len, unsigned long val); 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ciunsigned long vgic_mmio_read_group(struct kvm_vcpu *vcpu, gpa_t addr, 1258c2ecf20Sopenharmony_ci unsigned int len); 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_civoid vgic_mmio_write_group(struct kvm_vcpu *vcpu, gpa_t addr, 1288c2ecf20Sopenharmony_ci unsigned int len, unsigned long val); 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ciunsigned long vgic_mmio_read_enable(struct kvm_vcpu *vcpu, 1318c2ecf20Sopenharmony_ci gpa_t addr, unsigned int len); 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_civoid vgic_mmio_write_senable(struct kvm_vcpu *vcpu, 1348c2ecf20Sopenharmony_ci gpa_t addr, unsigned int len, 1358c2ecf20Sopenharmony_ci unsigned long val); 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_civoid vgic_mmio_write_cenable(struct kvm_vcpu *vcpu, 1388c2ecf20Sopenharmony_ci gpa_t addr, unsigned int len, 1398c2ecf20Sopenharmony_ci unsigned long val); 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ciint vgic_uaccess_write_senable(struct kvm_vcpu *vcpu, 1428c2ecf20Sopenharmony_ci gpa_t addr, unsigned int len, 1438c2ecf20Sopenharmony_ci unsigned long val); 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ciint vgic_uaccess_write_cenable(struct kvm_vcpu *vcpu, 1468c2ecf20Sopenharmony_ci gpa_t addr, unsigned int len, 1478c2ecf20Sopenharmony_ci unsigned long val); 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ciunsigned long vgic_mmio_read_pending(struct kvm_vcpu *vcpu, 1508c2ecf20Sopenharmony_ci gpa_t addr, unsigned int len); 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ciunsigned long vgic_uaccess_read_pending(struct kvm_vcpu *vcpu, 1538c2ecf20Sopenharmony_ci gpa_t addr, unsigned int len); 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_civoid vgic_mmio_write_spending(struct kvm_vcpu *vcpu, 1568c2ecf20Sopenharmony_ci gpa_t addr, unsigned int len, 1578c2ecf20Sopenharmony_ci unsigned long val); 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_civoid vgic_mmio_write_cpending(struct kvm_vcpu *vcpu, 1608c2ecf20Sopenharmony_ci gpa_t addr, unsigned int len, 1618c2ecf20Sopenharmony_ci unsigned long val); 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ciint vgic_uaccess_write_spending(struct kvm_vcpu *vcpu, 1648c2ecf20Sopenharmony_ci gpa_t addr, unsigned int len, 1658c2ecf20Sopenharmony_ci unsigned long val); 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ciint vgic_uaccess_write_cpending(struct kvm_vcpu *vcpu, 1688c2ecf20Sopenharmony_ci gpa_t addr, unsigned int len, 1698c2ecf20Sopenharmony_ci unsigned long val); 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ciunsigned long vgic_mmio_read_active(struct kvm_vcpu *vcpu, 1728c2ecf20Sopenharmony_ci gpa_t addr, unsigned int len); 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ciunsigned long vgic_uaccess_read_active(struct kvm_vcpu *vcpu, 1758c2ecf20Sopenharmony_ci gpa_t addr, unsigned int len); 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_civoid vgic_mmio_write_cactive(struct kvm_vcpu *vcpu, 1788c2ecf20Sopenharmony_ci gpa_t addr, unsigned int len, 1798c2ecf20Sopenharmony_ci unsigned long val); 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_civoid vgic_mmio_write_sactive(struct kvm_vcpu *vcpu, 1828c2ecf20Sopenharmony_ci gpa_t addr, unsigned int len, 1838c2ecf20Sopenharmony_ci unsigned long val); 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ciint vgic_mmio_uaccess_write_cactive(struct kvm_vcpu *vcpu, 1868c2ecf20Sopenharmony_ci gpa_t addr, unsigned int len, 1878c2ecf20Sopenharmony_ci unsigned long val); 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ciint vgic_mmio_uaccess_write_sactive(struct kvm_vcpu *vcpu, 1908c2ecf20Sopenharmony_ci gpa_t addr, unsigned int len, 1918c2ecf20Sopenharmony_ci unsigned long val); 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ciunsigned long vgic_mmio_read_priority(struct kvm_vcpu *vcpu, 1948c2ecf20Sopenharmony_ci gpa_t addr, unsigned int len); 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_civoid vgic_mmio_write_priority(struct kvm_vcpu *vcpu, 1978c2ecf20Sopenharmony_ci gpa_t addr, unsigned int len, 1988c2ecf20Sopenharmony_ci unsigned long val); 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ciunsigned long vgic_mmio_read_config(struct kvm_vcpu *vcpu, 2018c2ecf20Sopenharmony_ci gpa_t addr, unsigned int len); 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_civoid vgic_mmio_write_config(struct kvm_vcpu *vcpu, 2048c2ecf20Sopenharmony_ci gpa_t addr, unsigned int len, 2058c2ecf20Sopenharmony_ci unsigned long val); 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ciint vgic_uaccess(struct kvm_vcpu *vcpu, struct vgic_io_device *dev, 2088c2ecf20Sopenharmony_ci bool is_write, int offset, u32 *val); 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_ciu64 vgic_read_irq_line_level_info(struct kvm_vcpu *vcpu, u32 intid); 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_civoid vgic_write_irq_line_level_info(struct kvm_vcpu *vcpu, u32 intid, 2138c2ecf20Sopenharmony_ci const u64 val); 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ciunsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev); 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ciunsigned int vgic_v3_init_dist_iodev(struct vgic_io_device *dev); 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ciu64 vgic_sanitise_outer_cacheability(u64 reg); 2208c2ecf20Sopenharmony_ciu64 vgic_sanitise_inner_cacheability(u64 reg); 2218c2ecf20Sopenharmony_ciu64 vgic_sanitise_shareability(u64 reg); 2228c2ecf20Sopenharmony_ciu64 vgic_sanitise_field(u64 reg, u64 field_mask, int field_shift, 2238c2ecf20Sopenharmony_ci u64 (*sanitise_fn)(u64)); 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ci/* Find the proper register handler entry given a certain address offset */ 2268c2ecf20Sopenharmony_ciconst struct vgic_register_region * 2278c2ecf20Sopenharmony_civgic_find_mmio_region(const struct vgic_register_region *regions, 2288c2ecf20Sopenharmony_ci int nr_regions, unsigned int offset); 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_ci#endif 231