162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (C) 2015, 2016 ARM Ltd. 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci#ifndef __KVM_ARM_VGIC_MMIO_H__ 662306a36Sopenharmony_ci#define __KVM_ARM_VGIC_MMIO_H__ 762306a36Sopenharmony_ci 862306a36Sopenharmony_cistruct vgic_register_region { 962306a36Sopenharmony_ci unsigned int reg_offset; 1062306a36Sopenharmony_ci unsigned int len; 1162306a36Sopenharmony_ci unsigned int bits_per_irq; 1262306a36Sopenharmony_ci unsigned int access_flags; 1362306a36Sopenharmony_ci union { 1462306a36Sopenharmony_ci unsigned long (*read)(struct kvm_vcpu *vcpu, gpa_t addr, 1562306a36Sopenharmony_ci unsigned int len); 1662306a36Sopenharmony_ci unsigned long (*its_read)(struct kvm *kvm, struct vgic_its *its, 1762306a36Sopenharmony_ci gpa_t addr, unsigned int len); 1862306a36Sopenharmony_ci }; 1962306a36Sopenharmony_ci union { 2062306a36Sopenharmony_ci void (*write)(struct kvm_vcpu *vcpu, gpa_t addr, 2162306a36Sopenharmony_ci unsigned int len, unsigned long val); 2262306a36Sopenharmony_ci void (*its_write)(struct kvm *kvm, struct vgic_its *its, 2362306a36Sopenharmony_ci gpa_t addr, unsigned int len, 2462306a36Sopenharmony_ci unsigned long val); 2562306a36Sopenharmony_ci }; 2662306a36Sopenharmony_ci unsigned long (*uaccess_read)(struct kvm_vcpu *vcpu, gpa_t addr, 2762306a36Sopenharmony_ci unsigned int len); 2862306a36Sopenharmony_ci union { 2962306a36Sopenharmony_ci int (*uaccess_write)(struct kvm_vcpu *vcpu, gpa_t addr, 3062306a36Sopenharmony_ci unsigned int len, unsigned long val); 3162306a36Sopenharmony_ci int (*uaccess_its_write)(struct kvm *kvm, struct vgic_its *its, 3262306a36Sopenharmony_ci gpa_t addr, unsigned int len, 3362306a36Sopenharmony_ci unsigned long val); 3462306a36Sopenharmony_ci }; 3562306a36Sopenharmony_ci}; 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ciextern const struct kvm_io_device_ops kvm_io_gic_ops; 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci#define VGIC_ACCESS_8bit 1 4062306a36Sopenharmony_ci#define VGIC_ACCESS_32bit 2 4162306a36Sopenharmony_ci#define VGIC_ACCESS_64bit 4 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci/* 4462306a36Sopenharmony_ci * Generate a mask that covers the number of bytes required to address 4562306a36Sopenharmony_ci * up to 1024 interrupts, each represented by <bits> bits. This assumes 4662306a36Sopenharmony_ci * that <bits> is a power of two. 4762306a36Sopenharmony_ci */ 4862306a36Sopenharmony_ci#define VGIC_ADDR_IRQ_MASK(bits) (((bits) * 1024 / 8) - 1) 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci/* 5162306a36Sopenharmony_ci * (addr & mask) gives us the _byte_ offset for the INT ID. 5262306a36Sopenharmony_ci * We multiply this by 8 the get the _bit_ offset, then divide this by 5362306a36Sopenharmony_ci * the number of bits to learn the actual INT ID. 5462306a36Sopenharmony_ci * But instead of a division (which requires a "long long div" implementation), 5562306a36Sopenharmony_ci * we shift by the binary logarithm of <bits>. 5662306a36Sopenharmony_ci * This assumes that <bits> is a power of two. 5762306a36Sopenharmony_ci */ 5862306a36Sopenharmony_ci#define VGIC_ADDR_TO_INTID(addr, bits) (((addr) & VGIC_ADDR_IRQ_MASK(bits)) * \ 5962306a36Sopenharmony_ci 8 >> ilog2(bits)) 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci/* 6262306a36Sopenharmony_ci * Some VGIC registers store per-IRQ information, with a different number 6362306a36Sopenharmony_ci * of bits per IRQ. For those registers this macro is used. 6462306a36Sopenharmony_ci * The _WITH_LENGTH version instantiates registers with a fixed length 6562306a36Sopenharmony_ci * and is mutually exclusive with the _PER_IRQ version. 6662306a36Sopenharmony_ci */ 6762306a36Sopenharmony_ci#define REGISTER_DESC_WITH_BITS_PER_IRQ(off, rd, wr, ur, uw, bpi, acc) \ 6862306a36Sopenharmony_ci { \ 6962306a36Sopenharmony_ci .reg_offset = off, \ 7062306a36Sopenharmony_ci .bits_per_irq = bpi, \ 7162306a36Sopenharmony_ci .len = bpi * 1024 / 8, \ 7262306a36Sopenharmony_ci .access_flags = acc, \ 7362306a36Sopenharmony_ci .read = rd, \ 7462306a36Sopenharmony_ci .write = wr, \ 7562306a36Sopenharmony_ci .uaccess_read = ur, \ 7662306a36Sopenharmony_ci .uaccess_write = uw, \ 7762306a36Sopenharmony_ci } 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci#define REGISTER_DESC_WITH_LENGTH(off, rd, wr, length, acc) \ 8062306a36Sopenharmony_ci { \ 8162306a36Sopenharmony_ci .reg_offset = off, \ 8262306a36Sopenharmony_ci .bits_per_irq = 0, \ 8362306a36Sopenharmony_ci .len = length, \ 8462306a36Sopenharmony_ci .access_flags = acc, \ 8562306a36Sopenharmony_ci .read = rd, \ 8662306a36Sopenharmony_ci .write = wr, \ 8762306a36Sopenharmony_ci } 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci#define REGISTER_DESC_WITH_LENGTH_UACCESS(off, rd, wr, urd, uwr, length, acc) \ 9062306a36Sopenharmony_ci { \ 9162306a36Sopenharmony_ci .reg_offset = off, \ 9262306a36Sopenharmony_ci .bits_per_irq = 0, \ 9362306a36Sopenharmony_ci .len = length, \ 9462306a36Sopenharmony_ci .access_flags = acc, \ 9562306a36Sopenharmony_ci .read = rd, \ 9662306a36Sopenharmony_ci .write = wr, \ 9762306a36Sopenharmony_ci .uaccess_read = urd, \ 9862306a36Sopenharmony_ci .uaccess_write = uwr, \ 9962306a36Sopenharmony_ci } 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ciunsigned long vgic_data_mmio_bus_to_host(const void *val, unsigned int len); 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_civoid vgic_data_host_to_mmio_bus(void *buf, unsigned int len, 10462306a36Sopenharmony_ci unsigned long data); 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ciunsigned long extract_bytes(u64 data, unsigned int offset, 10762306a36Sopenharmony_ci unsigned int num); 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ciu64 update_64bit_reg(u64 reg, unsigned int offset, unsigned int len, 11062306a36Sopenharmony_ci unsigned long val); 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ciunsigned long vgic_mmio_read_raz(struct kvm_vcpu *vcpu, 11362306a36Sopenharmony_ci gpa_t addr, unsigned int len); 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ciunsigned long vgic_mmio_read_rao(struct kvm_vcpu *vcpu, 11662306a36Sopenharmony_ci gpa_t addr, unsigned int len); 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_civoid vgic_mmio_write_wi(struct kvm_vcpu *vcpu, gpa_t addr, 11962306a36Sopenharmony_ci unsigned int len, unsigned long val); 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ciint vgic_mmio_uaccess_write_wi(struct kvm_vcpu *vcpu, gpa_t addr, 12262306a36Sopenharmony_ci unsigned int len, unsigned long val); 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ciunsigned long vgic_mmio_read_group(struct kvm_vcpu *vcpu, gpa_t addr, 12562306a36Sopenharmony_ci unsigned int len); 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_civoid vgic_mmio_write_group(struct kvm_vcpu *vcpu, gpa_t addr, 12862306a36Sopenharmony_ci unsigned int len, unsigned long val); 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ciunsigned long vgic_mmio_read_enable(struct kvm_vcpu *vcpu, 13162306a36Sopenharmony_ci gpa_t addr, unsigned int len); 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_civoid vgic_mmio_write_senable(struct kvm_vcpu *vcpu, 13462306a36Sopenharmony_ci gpa_t addr, unsigned int len, 13562306a36Sopenharmony_ci unsigned long val); 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_civoid vgic_mmio_write_cenable(struct kvm_vcpu *vcpu, 13862306a36Sopenharmony_ci gpa_t addr, unsigned int len, 13962306a36Sopenharmony_ci unsigned long val); 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ciint vgic_uaccess_write_senable(struct kvm_vcpu *vcpu, 14262306a36Sopenharmony_ci gpa_t addr, unsigned int len, 14362306a36Sopenharmony_ci unsigned long val); 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ciint vgic_uaccess_write_cenable(struct kvm_vcpu *vcpu, 14662306a36Sopenharmony_ci gpa_t addr, unsigned int len, 14762306a36Sopenharmony_ci unsigned long val); 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ciunsigned long vgic_mmio_read_pending(struct kvm_vcpu *vcpu, 15062306a36Sopenharmony_ci gpa_t addr, unsigned int len); 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ciunsigned long vgic_uaccess_read_pending(struct kvm_vcpu *vcpu, 15362306a36Sopenharmony_ci gpa_t addr, unsigned int len); 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_civoid vgic_mmio_write_spending(struct kvm_vcpu *vcpu, 15662306a36Sopenharmony_ci gpa_t addr, unsigned int len, 15762306a36Sopenharmony_ci unsigned long val); 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_civoid vgic_mmio_write_cpending(struct kvm_vcpu *vcpu, 16062306a36Sopenharmony_ci gpa_t addr, unsigned int len, 16162306a36Sopenharmony_ci unsigned long val); 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ciint vgic_uaccess_write_spending(struct kvm_vcpu *vcpu, 16462306a36Sopenharmony_ci gpa_t addr, unsigned int len, 16562306a36Sopenharmony_ci unsigned long val); 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ciint vgic_uaccess_write_cpending(struct kvm_vcpu *vcpu, 16862306a36Sopenharmony_ci gpa_t addr, unsigned int len, 16962306a36Sopenharmony_ci unsigned long val); 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ciunsigned long vgic_mmio_read_active(struct kvm_vcpu *vcpu, 17262306a36Sopenharmony_ci gpa_t addr, unsigned int len); 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ciunsigned long vgic_uaccess_read_active(struct kvm_vcpu *vcpu, 17562306a36Sopenharmony_ci gpa_t addr, unsigned int len); 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_civoid vgic_mmio_write_cactive(struct kvm_vcpu *vcpu, 17862306a36Sopenharmony_ci gpa_t addr, unsigned int len, 17962306a36Sopenharmony_ci unsigned long val); 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_civoid vgic_mmio_write_sactive(struct kvm_vcpu *vcpu, 18262306a36Sopenharmony_ci gpa_t addr, unsigned int len, 18362306a36Sopenharmony_ci unsigned long val); 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ciint vgic_mmio_uaccess_write_cactive(struct kvm_vcpu *vcpu, 18662306a36Sopenharmony_ci gpa_t addr, unsigned int len, 18762306a36Sopenharmony_ci unsigned long val); 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ciint vgic_mmio_uaccess_write_sactive(struct kvm_vcpu *vcpu, 19062306a36Sopenharmony_ci gpa_t addr, unsigned int len, 19162306a36Sopenharmony_ci unsigned long val); 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ciunsigned long vgic_mmio_read_priority(struct kvm_vcpu *vcpu, 19462306a36Sopenharmony_ci gpa_t addr, unsigned int len); 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_civoid vgic_mmio_write_priority(struct kvm_vcpu *vcpu, 19762306a36Sopenharmony_ci gpa_t addr, unsigned int len, 19862306a36Sopenharmony_ci unsigned long val); 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ciunsigned long vgic_mmio_read_config(struct kvm_vcpu *vcpu, 20162306a36Sopenharmony_ci gpa_t addr, unsigned int len); 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_civoid vgic_mmio_write_config(struct kvm_vcpu *vcpu, 20462306a36Sopenharmony_ci gpa_t addr, unsigned int len, 20562306a36Sopenharmony_ci unsigned long val); 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ciint vgic_uaccess(struct kvm_vcpu *vcpu, struct vgic_io_device *dev, 20862306a36Sopenharmony_ci bool is_write, int offset, u32 *val); 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ciu32 vgic_read_irq_line_level_info(struct kvm_vcpu *vcpu, u32 intid); 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_civoid vgic_write_irq_line_level_info(struct kvm_vcpu *vcpu, u32 intid, 21362306a36Sopenharmony_ci const u32 val); 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ciunsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev); 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ciunsigned int vgic_v3_init_dist_iodev(struct vgic_io_device *dev); 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ciu64 vgic_sanitise_outer_cacheability(u64 reg); 22062306a36Sopenharmony_ciu64 vgic_sanitise_inner_cacheability(u64 reg); 22162306a36Sopenharmony_ciu64 vgic_sanitise_shareability(u64 reg); 22262306a36Sopenharmony_ciu64 vgic_sanitise_field(u64 reg, u64 field_mask, int field_shift, 22362306a36Sopenharmony_ci u64 (*sanitise_fn)(u64)); 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci/* Find the proper register handler entry given a certain address offset */ 22662306a36Sopenharmony_ciconst struct vgic_register_region * 22762306a36Sopenharmony_civgic_find_mmio_region(const struct vgic_register_region *regions, 22862306a36Sopenharmony_ci int nr_regions, unsigned int offset); 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci#endif 231