Message ID | 1462531568-9799-33-git-send-email-andre.przywara@arm.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On 06/05/16 11:45, Andre Przywara wrote: > Create a new file called vgic-mmio-v3.c and describe the GICv3 > distributor and redistributor registers there. > This adds a special macro to deal with the split of SGI/PPI in the > redistributor and SPIs in the distributor, which allows us to reuse > the existing GICv2 handlers for those registers which are compatible. > Also we provide a function to deal with the registration of the two > separate redistributor frames per VCPU. > > Signed-off-by: Andre Przywara <andre.przywara@arm.com> > Reviewed-by: Eric Auger <eric.auger@linaro.org> > --- > Changelog RFC..v1: > - adapt to new MMIO registration approach: > register one device for the distributor and two for each VCPU > - implement special handling for private interrupts > - remove empty stub functions > - make IGROUPR return RAO > > Changelog v1 .. v2: > - adapt to new framework, introduce vgic-mmio-v3.c > - remove userland register access functions (for now) > - precompute .len when describing a VGIC register > - add missed pointer incrementation on registering redist regions > - replace _nyi stub functions with raz/wi versions > > Changelog v2 .. v3: > - replace inclusion of kvm/vgic/vgic.h with kvm/arm_vgic.h > - add prototype and stub code for vgic_register_redist_iodevs > - rename register struct variables _rdbase_ and _sgibase_ > > virt/kvm/arm/vgic/vgic-mmio-v3.c | 191 +++++++++++++++++++++++++++++++++++++++ > virt/kvm/arm/vgic/vgic-mmio.c | 5 + > virt/kvm/arm/vgic/vgic-mmio.h | 2 + > virt/kvm/arm/vgic/vgic.h | 7 ++ > 4 files changed, 205 insertions(+) > create mode 100644 virt/kvm/arm/vgic/vgic-mmio-v3.c > > diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c > new file mode 100644 > index 0000000..06c7ec5 > --- /dev/null > +++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c > @@ -0,0 +1,191 @@ > +/* > + * VGICv3 MMIO handling functions > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License version 2 as > + * published by the Free Software Foundation. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + */ > + > +#include <linux/irqchip/arm-gic-v3.h> > +#include <linux/kvm.h> > +#include <linux/kvm_host.h> > +#include <kvm/iodev.h> > +#include <kvm/arm_vgic.h> > + > +#include <asm/kvm_emulate.h> > + > +#include "vgic.h" > +#include "vgic-mmio.h" > + > +/* > + * The GICv3 per-IRQ registers are split to control PPIs and SGIs in the > + * redistributors, while SPIs are covered by registers in the distributor > + * block. Trying to set private IRQs in this block gets ignored. > + * We take some special care here to fix the calculation of the register > + * offset. > + */ > +#define REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(off, read_ops, write_ops, bpi) \ > + { \ > + .reg_offset = off, \ > + .bits_per_irq = bpi, \ > + .len = (bpi * VGIC_NR_PRIVATE_IRQS) / 8, \ > + .read = vgic_mmio_read_raz, \ > + .write = vgic_mmio_write_wi, \ > + }, { \ > + .reg_offset = off + (bpi * VGIC_NR_PRIVATE_IRQS) / 8, \ > + .bits_per_irq = bpi, \ > + .len = (bpi * (1024 - VGIC_NR_PRIVATE_IRQS)) / 8, \ > + .read = read_ops, \ > + .write = write_ops, \ > + } > + > +static const struct vgic_register_region vgic_v3_dist_registers[] = { > + REGISTER_DESC_WITH_LENGTH(GICD_CTLR, > + vgic_mmio_read_raz, vgic_mmio_write_wi, 16), > + REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IGROUPR, > + vgic_mmio_read_rao, vgic_mmio_write_wi, 1), > + REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISENABLER, > + vgic_mmio_read_enable, vgic_mmio_write_senable, 1), > + REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICENABLER, > + vgic_mmio_read_enable, vgic_mmio_write_cenable, 1), > + REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISPENDR, > + vgic_mmio_read_pending, vgic_mmio_write_spending, 1), > + REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICPENDR, > + vgic_mmio_read_pending, vgic_mmio_write_cpending, 1), > + REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISACTIVER, > + vgic_mmio_read_active, vgic_mmio_write_sactive, 1), > + REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICACTIVER, > + vgic_mmio_read_active, vgic_mmio_write_cactive, 1), > + REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IPRIORITYR, > + vgic_mmio_read_priority, vgic_mmio_write_priority, 8), > + REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ITARGETSR, > + vgic_mmio_read_raz, vgic_mmio_write_wi, 8), > + REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICFGR, > + vgic_mmio_read_config, vgic_mmio_write_config, 2), > + REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IGRPMODR, > + vgic_mmio_read_raz, vgic_mmio_write_wi, 1), > + REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IROUTER, > + vgic_mmio_read_raz, vgic_mmio_write_wi, 64), > + REGISTER_DESC_WITH_LENGTH(GICD_IDREGS, > + vgic_mmio_read_raz, vgic_mmio_write_wi, 48), > +}; > + > +static const struct vgic_register_region vgic_v3_rdbase_registers[] = { > + REGISTER_DESC_WITH_LENGTH(GICR_CTLR, > + vgic_mmio_read_raz, vgic_mmio_write_wi, 4), > + REGISTER_DESC_WITH_LENGTH(GICR_IIDR, > + vgic_mmio_read_raz, vgic_mmio_write_wi, 4), > + REGISTER_DESC_WITH_LENGTH(GICR_TYPER, > + vgic_mmio_read_raz, vgic_mmio_write_wi, 8), > + REGISTER_DESC_WITH_LENGTH(GICR_PROPBASER, > + vgic_mmio_read_raz, vgic_mmio_write_wi, 8), > + REGISTER_DESC_WITH_LENGTH(GICR_PENDBASER, > + vgic_mmio_read_raz, vgic_mmio_write_wi, 8), > + REGISTER_DESC_WITH_LENGTH(GICR_IDREGS, > + vgic_mmio_read_raz, vgic_mmio_write_wi, 48), > +}; > + > +static const struct vgic_register_region vgic_v3_sgibase_registers[] = { > + REGISTER_DESC_WITH_LENGTH(GICR_IGROUPR0, > + vgic_mmio_read_rao, vgic_mmio_write_wi, 4), > + REGISTER_DESC_WITH_LENGTH(GICR_ISENABLER0, > + vgic_mmio_read_enable, vgic_mmio_write_senable, 4), > + REGISTER_DESC_WITH_LENGTH(GICR_ICENABLER0, > + vgic_mmio_read_enable, vgic_mmio_write_cenable, 4), > + REGISTER_DESC_WITH_LENGTH(GICR_ISPENDR0, > + vgic_mmio_read_pending, vgic_mmio_write_spending, 4), > + REGISTER_DESC_WITH_LENGTH(GICR_ICPENDR0, > + vgic_mmio_read_pending, vgic_mmio_write_cpending, 4), > + REGISTER_DESC_WITH_LENGTH(GICR_ISACTIVER0, > + vgic_mmio_read_active, vgic_mmio_write_sactive, 4), > + REGISTER_DESC_WITH_LENGTH(GICR_ICACTIVER0, > + vgic_mmio_read_active, vgic_mmio_write_cactive, 4), > + REGISTER_DESC_WITH_LENGTH(GICR_IPRIORITYR0, > + vgic_mmio_read_priority, vgic_mmio_write_priority, 32), > + REGISTER_DESC_WITH_LENGTH(GICR_ICFGR0, > + vgic_mmio_read_config, vgic_mmio_write_config, 8), > + REGISTER_DESC_WITH_LENGTH(GICR_IGRPMODR0, > + vgic_mmio_read_raz, vgic_mmio_write_wi, 4), > + REGISTER_DESC_WITH_LENGTH(GICR_NSACR, > + vgic_mmio_read_raz, vgic_mmio_write_wi, 4), > +}; > + > +unsigned int vgic_v3_init_dist_iodev(struct vgic_io_device *dev) > +{ > + dev->regions = vgic_v3_dist_registers; > + dev->nr_regions = ARRAY_SIZE(vgic_v3_dist_registers); > + > + kvm_iodevice_init(&dev->dev, &kvm_io_gic_ops); > + > + return SZ_64K; > +} > + > +int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t redist_base_address) > +{ > + int nr_vcpus = atomic_read(&kvm->online_vcpus); > + struct kvm_vcpu *vcpu; > + struct vgic_io_device *devices, *device; > + int c, ret = 0; > + > + devices = kmalloc(sizeof(struct vgic_io_device) * nr_vcpus * 2, > + GFP_KERNEL); > + if (!devices) > + return -ENOMEM; > + > + device = devices; > + kvm_for_each_vcpu(c, vcpu, kvm) { > + kvm_iodevice_init(&device->dev, &kvm_io_gic_ops); > + device->base_addr = redist_base_address; > + device->regions = vgic_v3_rdbase_registers; > + device->nr_regions = ARRAY_SIZE(vgic_v3_rdbase_registers); > + device->redist_vcpu = vcpu; > + > + mutex_lock(&kvm->slots_lock); > + ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, > + redist_base_address, > + SZ_64K, &device->dev); > + mutex_unlock(&kvm->slots_lock); > + > + if (ret) > + break; > + > + device++; > + kvm_iodevice_init(&device->dev, &kvm_io_gic_ops); > + device->base_addr = redist_base_address + SZ_64K; > + device->regions = vgic_v3_sgibase_registers; > + device->nr_regions = ARRAY_SIZE(vgic_v3_sgibase_registers); > + device->redist_vcpu = vcpu; > + > + mutex_lock(&kvm->slots_lock); > + ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, > + redist_base_address + SZ_64K, > + SZ_64K, &device->dev); > + mutex_unlock(&kvm->slots_lock); > + if (ret) { > + kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS, > + &devices[c * 2].dev); > + break; > + } > + device++; > + redist_base_address += 2 * SZ_64K; > + } What I fail to see here is what prevents the redistributor range from overlapping with the distributor (or any other device). The kvm IO bus is happy with overlapping addresses, but I'm not sure at all that this is safe. Care to shed some light on it? Thanks, M.
DQoNCg0KDQoNCk9uIDUvOS8xNiwgMTA6MTggQU0sICJrdm1hcm0tYm91bmNlc0BsaXN0cy5jcy5j b2x1bWJpYS5lZHUgb24gYmVoYWxmIG9mIE1hcmMgWnluZ2llciIgPGt2bWFybS1ib3VuY2VzQGxp c3RzLmNzLmNvbHVtYmlhLmVkdSBvbiBiZWhhbGYgb2YgbWFyYy56eW5naWVyQGFybS5jb20+IHdy b3RlOg0KDQo+T24gMDYvMDUvMTYgMTE6NDUsIEFuZHJlIFByenl3YXJhIHdyb3RlOg0KPj4gQ3Jl YXRlIGEgbmV3IGZpbGUgY2FsbGVkIHZnaWMtbW1pby12My5jIGFuZCBkZXNjcmliZSB0aGUgR0lD djMNCj4+IGRpc3RyaWJ1dG9yIGFuZCByZWRpc3RyaWJ1dG9yIHJlZ2lzdGVycyB0aGVyZS4NCj4+ IFRoaXMgYWRkcyBhIHNwZWNpYWwgbWFjcm8gdG8gZGVhbCB3aXRoIHRoZSBzcGxpdCBvZiBTR0kv UFBJIGluIHRoZQ0KPj4gcmVkaXN0cmlidXRvciBhbmQgU1BJcyBpbiB0aGUgZGlzdHJpYnV0b3Is IHdoaWNoIGFsbG93cyB1cyB0byByZXVzZQ0KPj4gdGhlIGV4aXN0aW5nIEdJQ3YyIGhhbmRsZXJz IGZvciB0aG9zZSByZWdpc3RlcnMgd2hpY2ggYXJlIGNvbXBhdGlibGUuDQo+PiBBbHNvIHdlIHBy b3ZpZGUgYSBmdW5jdGlvbiB0byBkZWFsIHdpdGggdGhlIHJlZ2lzdHJhdGlvbiBvZiB0aGUgdHdv DQo+PiBzZXBhcmF0ZSByZWRpc3RyaWJ1dG9yIGZyYW1lcyBwZXIgVkNQVS4NCj4+IA0KPj4gU2ln bmVkLW9mZi1ieTogQW5kcmUgUHJ6eXdhcmEgPGFuZHJlLnByenl3YXJhQGFybS5jb20+DQo+PiBS ZXZpZXdlZC1ieTogRXJpYyBBdWdlciA8ZXJpYy5hdWdlckBsaW5hcm8ub3JnPg0KPj4gLS0tDQo+ PiBDaGFuZ2Vsb2cgUkZDLi52MToNCj4+IC0gYWRhcHQgdG8gbmV3IE1NSU8gcmVnaXN0cmF0aW9u IGFwcHJvYWNoOg0KPj4gICByZWdpc3RlciBvbmUgZGV2aWNlIGZvciB0aGUgZGlzdHJpYnV0b3Ig YW5kIHR3byBmb3IgZWFjaCBWQ1BVDQo+PiAtIGltcGxlbWVudCBzcGVjaWFsIGhhbmRsaW5nIGZv ciBwcml2YXRlIGludGVycnVwdHMNCj4+IC0gcmVtb3ZlIGVtcHR5IHN0dWIgZnVuY3Rpb25zDQo+ PiAtIG1ha2UgSUdST1VQUiByZXR1cm4gUkFPDQo+PiANCj4+IENoYW5nZWxvZyB2MSAuLiB2MjoN Cj4+IC0gYWRhcHQgdG8gbmV3IGZyYW1ld29yaywgaW50cm9kdWNlIHZnaWMtbW1pby12My5jDQo+ PiAtIHJlbW92ZSB1c2VybGFuZCByZWdpc3RlciBhY2Nlc3MgZnVuY3Rpb25zIChmb3Igbm93KQ0K Pj4gLSBwcmVjb21wdXRlIC5sZW4gd2hlbiBkZXNjcmliaW5nIGEgVkdJQyByZWdpc3Rlcg0KPj4g LSBhZGQgbWlzc2VkIHBvaW50ZXIgaW5jcmVtZW50YXRpb24gb24gcmVnaXN0ZXJpbmcgcmVkaXN0 IHJlZ2lvbnMNCj4+IC0gcmVwbGFjZSBfbnlpIHN0dWIgZnVuY3Rpb25zIHdpdGggcmF6L3dpIHZl cnNpb25zDQo+PiANCj4+IENoYW5nZWxvZyB2MiAuLiB2MzoNCj4+IC0gcmVwbGFjZSBpbmNsdXNp b24gb2Yga3ZtL3ZnaWMvdmdpYy5oIHdpdGgga3ZtL2FybV92Z2ljLmgNCj4+IC0gYWRkIHByb3Rv dHlwZSBhbmQgc3R1YiBjb2RlIGZvciB2Z2ljX3JlZ2lzdGVyX3JlZGlzdF9pb2RldnMNCj4+IC0g cmVuYW1lIHJlZ2lzdGVyIHN0cnVjdCB2YXJpYWJsZXMgX3JkYmFzZV8gYW5kIF9zZ2liYXNlXw0K Pj4gDQo+PiAgdmlydC9rdm0vYXJtL3ZnaWMvdmdpYy1tbWlvLXYzLmMgfCAxOTEgKysrKysrKysr KysrKysrKysrKysrKysrKysrKysrKysrKysrKysrDQo+PiAgdmlydC9rdm0vYXJtL3ZnaWMvdmdp Yy1tbWlvLmMgICAgfCAgIDUgKw0KPj4gIHZpcnQva3ZtL2FybS92Z2ljL3ZnaWMtbW1pby5oICAg IHwgICAyICsNCj4+ICB2aXJ0L2t2bS9hcm0vdmdpYy92Z2ljLmggICAgICAgICB8ICAgNyArKw0K Pj4gIDQgZmlsZXMgY2hhbmdlZCwgMjA1IGluc2VydGlvbnMoKykNCj4+ICBjcmVhdGUgbW9kZSAx MDA2NDQgdmlydC9rdm0vYXJtL3ZnaWMvdmdpYy1tbWlvLXYzLmMNCj4+IA0KPj4gZGlmZiAtLWdp dCBhL3ZpcnQva3ZtL2FybS92Z2ljL3ZnaWMtbW1pby12My5jIGIvdmlydC9rdm0vYXJtL3ZnaWMv dmdpYy1tbWlvLXYzLmMNCj4+IG5ldyBmaWxlIG1vZGUgMTAwNjQ0DQo+PiBpbmRleCAwMDAwMDAw Li4wNmM3ZWM1DQo+PiAtLS0gL2Rldi9udWxsDQo+PiArKysgYi92aXJ0L2t2bS9hcm0vdmdpYy92 Z2ljLW1taW8tdjMuYw0KPj4gQEAgLTAsMCArMSwxOTEgQEANCj4+ICsvKg0KPj4gKyAqIFZHSUN2 MyBNTUlPIGhhbmRsaW5nIGZ1bmN0aW9ucw0KPj4gKyAqDQo+PiArICogVGhpcyBwcm9ncmFtIGlz IGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnkNCj4+ ICsgKiBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNl IHZlcnNpb24gMiBhcw0KPj4gKyAqIHB1Ymxpc2hlZCBieSB0aGUgRnJlZSBTb2Z0d2FyZSBGb3Vu ZGF0aW9uLg0KPj4gKyAqDQo+PiArICogVGhpcyBwcm9ncmFtIGlzIGRpc3RyaWJ1dGVkIGluIHRo ZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsDQo+PiArICogYnV0IFdJVEhPVVQgQU5ZIFdB UlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YNCj4+ICsgKiBNRVJD SEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhl DQo+PiArICogR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy4NCj4+ ICsgKi8NCj4+ICsNCj4+ICsjaW5jbHVkZSA8bGludXgvaXJxY2hpcC9hcm0tZ2ljLXYzLmg+DQo+ PiArI2luY2x1ZGUgPGxpbnV4L2t2bS5oPg0KPj4gKyNpbmNsdWRlIDxsaW51eC9rdm1faG9zdC5o Pg0KPj4gKyNpbmNsdWRlIDxrdm0vaW9kZXYuaD4NCj4+ICsjaW5jbHVkZSA8a3ZtL2FybV92Z2lj Lmg+DQo+PiArDQo+PiArI2luY2x1ZGUgPGFzbS9rdm1fZW11bGF0ZS5oPg0KPj4gKw0KPj4gKyNp bmNsdWRlICJ2Z2ljLmgiDQo+PiArI2luY2x1ZGUgInZnaWMtbW1pby5oIg0KPj4gKw0KPj4gKy8q DQo+PiArICogVGhlIEdJQ3YzIHBlci1JUlEgcmVnaXN0ZXJzIGFyZSBzcGxpdCB0byBjb250cm9s IFBQSXMgYW5kIFNHSXMgaW4gdGhlDQo+PiArICogcmVkaXN0cmlidXRvcnMsIHdoaWxlIFNQSXMg YXJlIGNvdmVyZWQgYnkgcmVnaXN0ZXJzIGluIHRoZSBkaXN0cmlidXRvcg0KPj4gKyAqIGJsb2Nr LiBUcnlpbmcgdG8gc2V0IHByaXZhdGUgSVJRcyBpbiB0aGlzIGJsb2NrIGdldHMgaWdub3JlZC4N Cj4+ICsgKiBXZSB0YWtlIHNvbWUgc3BlY2lhbCBjYXJlIGhlcmUgdG8gZml4IHRoZSBjYWxjdWxh dGlvbiBvZiB0aGUgcmVnaXN0ZXINCj4+ICsgKiBvZmZzZXQuDQo+PiArICovDQo+PiArI2RlZmlu ZSBSRUdJU1RFUl9ERVNDX1dJVEhfQklUU19QRVJfSVJRX1NIQVJFRChvZmYsIHJlYWRfb3BzLCB3 cml0ZV9vcHMsIGJwaSkgXA0KPj4gKwl7CQkJCQkJCQlcDQo+PiArCQkucmVnX29mZnNldCA9IG9m ZiwJCQkJCVwNCj4+ICsJCS5iaXRzX3Blcl9pcnEgPSBicGksCQkJCQlcDQo+PiArCQkubGVuID0g KGJwaSAqIFZHSUNfTlJfUFJJVkFURV9JUlFTKSAvIDgsCQlcDQo+PiArCQkucmVhZCA9IHZnaWNf bW1pb19yZWFkX3JheiwJCQkJXA0KPj4gKwkJLndyaXRlID0gdmdpY19tbWlvX3dyaXRlX3dpLAkJ CQlcDQo+PiArCX0sIHsJCQkJCQkJCVwNCj4+ICsJCS5yZWdfb2Zmc2V0ID0gb2ZmICsgKGJwaSAq IFZHSUNfTlJfUFJJVkFURV9JUlFTKSAvIDgsCVwNCj4+ICsJCS5iaXRzX3Blcl9pcnEgPSBicGks CQkJCQlcDQo+PiArCQkubGVuID0gKGJwaSAqICgxMDI0IC0gVkdJQ19OUl9QUklWQVRFX0lSUVMp KSAvIDgsCVwNCj4+ICsJCS5yZWFkID0gcmVhZF9vcHMsCQkJCQlcDQo+PiArCQkud3JpdGUgPSB3 cml0ZV9vcHMsCQkJCQlcDQo+PiArCX0NCj4+ICsNCj4+ICtzdGF0aWMgY29uc3Qgc3RydWN0IHZn aWNfcmVnaXN0ZXJfcmVnaW9uIHZnaWNfdjNfZGlzdF9yZWdpc3RlcnNbXSA9IHsNCj4+ICsJUkVH SVNURVJfREVTQ19XSVRIX0xFTkdUSChHSUNEX0NUTFIsDQo+PiArCQl2Z2ljX21taW9fcmVhZF9y YXosIHZnaWNfbW1pb193cml0ZV93aSwgMTYpLA0KPj4gKwlSRUdJU1RFUl9ERVNDX1dJVEhfQklU U19QRVJfSVJRX1NIQVJFRChHSUNEX0lHUk9VUFIsDQo+PiArCQl2Z2ljX21taW9fcmVhZF9yYW8s IHZnaWNfbW1pb193cml0ZV93aSwgMSksDQo+PiArCVJFR0lTVEVSX0RFU0NfV0lUSF9CSVRTX1BF Ul9JUlFfU0hBUkVEKEdJQ0RfSVNFTkFCTEVSLA0KPj4gKwkJdmdpY19tbWlvX3JlYWRfZW5hYmxl LCB2Z2ljX21taW9fd3JpdGVfc2VuYWJsZSwgMSksDQo+PiArCVJFR0lTVEVSX0RFU0NfV0lUSF9C SVRTX1BFUl9JUlFfU0hBUkVEKEdJQ0RfSUNFTkFCTEVSLA0KPj4gKwkJdmdpY19tbWlvX3JlYWRf ZW5hYmxlLCB2Z2ljX21taW9fd3JpdGVfY2VuYWJsZSwgMSksDQo+PiArCVJFR0lTVEVSX0RFU0Nf V0lUSF9CSVRTX1BFUl9JUlFfU0hBUkVEKEdJQ0RfSVNQRU5EUiwNCj4+ICsJCXZnaWNfbW1pb19y ZWFkX3BlbmRpbmcsIHZnaWNfbW1pb193cml0ZV9zcGVuZGluZywgMSksDQo+PiArCVJFR0lTVEVS X0RFU0NfV0lUSF9CSVRTX1BFUl9JUlFfU0hBUkVEKEdJQ0RfSUNQRU5EUiwNCj4+ICsJCXZnaWNf bW1pb19yZWFkX3BlbmRpbmcsIHZnaWNfbW1pb193cml0ZV9jcGVuZGluZywgMSksDQo+PiArCVJF R0lTVEVSX0RFU0NfV0lUSF9CSVRTX1BFUl9JUlFfU0hBUkVEKEdJQ0RfSVNBQ1RJVkVSLA0KPj4g KwkJdmdpY19tbWlvX3JlYWRfYWN0aXZlLCB2Z2ljX21taW9fd3JpdGVfc2FjdGl2ZSwgMSksDQo+ PiArCVJFR0lTVEVSX0RFU0NfV0lUSF9CSVRTX1BFUl9JUlFfU0hBUkVEKEdJQ0RfSUNBQ1RJVkVS LA0KPj4gKwkJdmdpY19tbWlvX3JlYWRfYWN0aXZlLCB2Z2ljX21taW9fd3JpdGVfY2FjdGl2ZSwg MSksDQo+PiArCVJFR0lTVEVSX0RFU0NfV0lUSF9CSVRTX1BFUl9JUlFfU0hBUkVEKEdJQ0RfSVBS SU9SSVRZUiwNCj4+ICsJCXZnaWNfbW1pb19yZWFkX3ByaW9yaXR5LCB2Z2ljX21taW9fd3JpdGVf cHJpb3JpdHksIDgpLA0KPj4gKwlSRUdJU1RFUl9ERVNDX1dJVEhfQklUU19QRVJfSVJRX1NIQVJF RChHSUNEX0lUQVJHRVRTUiwNCj4+ICsJCXZnaWNfbW1pb19yZWFkX3JheiwgdmdpY19tbWlvX3dy aXRlX3dpLCA4KSwNCj4+ICsJUkVHSVNURVJfREVTQ19XSVRIX0JJVFNfUEVSX0lSUV9TSEFSRUQo R0lDRF9JQ0ZHUiwNCj4+ICsJCXZnaWNfbW1pb19yZWFkX2NvbmZpZywgdmdpY19tbWlvX3dyaXRl X2NvbmZpZywgMiksDQo+PiArCVJFR0lTVEVSX0RFU0NfV0lUSF9CSVRTX1BFUl9JUlFfU0hBUkVE KEdJQ0RfSUdSUE1PRFIsDQo+PiArCQl2Z2ljX21taW9fcmVhZF9yYXosIHZnaWNfbW1pb193cml0 ZV93aSwgMSksDQo+PiArCVJFR0lTVEVSX0RFU0NfV0lUSF9CSVRTX1BFUl9JUlFfU0hBUkVEKEdJ Q0RfSVJPVVRFUiwNCj4+ICsJCXZnaWNfbW1pb19yZWFkX3JheiwgdmdpY19tbWlvX3dyaXRlX3dp LCA2NCksDQo+PiArCVJFR0lTVEVSX0RFU0NfV0lUSF9MRU5HVEgoR0lDRF9JRFJFR1MsDQo+PiAr CQl2Z2ljX21taW9fcmVhZF9yYXosIHZnaWNfbW1pb193cml0ZV93aSwgNDgpLA0KPj4gK307DQo+ PiArDQo+PiArc3RhdGljIGNvbnN0IHN0cnVjdCB2Z2ljX3JlZ2lzdGVyX3JlZ2lvbiB2Z2ljX3Yz X3JkYmFzZV9yZWdpc3RlcnNbXSA9IHsNCj4+ICsJUkVHSVNURVJfREVTQ19XSVRIX0xFTkdUSChH SUNSX0NUTFIsDQo+PiArCQl2Z2ljX21taW9fcmVhZF9yYXosIHZnaWNfbW1pb193cml0ZV93aSwg NCksDQo+PiArCVJFR0lTVEVSX0RFU0NfV0lUSF9MRU5HVEgoR0lDUl9JSURSLA0KPj4gKwkJdmdp Y19tbWlvX3JlYWRfcmF6LCB2Z2ljX21taW9fd3JpdGVfd2ksIDQpLA0KPj4gKwlSRUdJU1RFUl9E RVNDX1dJVEhfTEVOR1RIKEdJQ1JfVFlQRVIsDQo+PiArCQl2Z2ljX21taW9fcmVhZF9yYXosIHZn aWNfbW1pb193cml0ZV93aSwgOCksDQo+PiArCVJFR0lTVEVSX0RFU0NfV0lUSF9MRU5HVEgoR0lD Ul9QUk9QQkFTRVIsDQo+PiArCQl2Z2ljX21taW9fcmVhZF9yYXosIHZnaWNfbW1pb193cml0ZV93 aSwgOCksDQo+PiArCVJFR0lTVEVSX0RFU0NfV0lUSF9MRU5HVEgoR0lDUl9QRU5EQkFTRVIsDQo+ PiArCQl2Z2ljX21taW9fcmVhZF9yYXosIHZnaWNfbW1pb193cml0ZV93aSwgOCksDQo+PiArCVJF R0lTVEVSX0RFU0NfV0lUSF9MRU5HVEgoR0lDUl9JRFJFR1MsDQo+PiArCQl2Z2ljX21taW9fcmVh ZF9yYXosIHZnaWNfbW1pb193cml0ZV93aSwgNDgpLA0KPj4gK307DQo+PiArDQo+PiArc3RhdGlj IGNvbnN0IHN0cnVjdCB2Z2ljX3JlZ2lzdGVyX3JlZ2lvbiB2Z2ljX3YzX3NnaWJhc2VfcmVnaXN0 ZXJzW10gPSB7DQo+PiArCVJFR0lTVEVSX0RFU0NfV0lUSF9MRU5HVEgoR0lDUl9JR1JPVVBSMCwN Cj4+ICsJCXZnaWNfbW1pb19yZWFkX3JhbywgdmdpY19tbWlvX3dyaXRlX3dpLCA0KSwNCj4+ICsJ UkVHSVNURVJfREVTQ19XSVRIX0xFTkdUSChHSUNSX0lTRU5BQkxFUjAsDQo+PiArCQl2Z2ljX21t aW9fcmVhZF9lbmFibGUsIHZnaWNfbW1pb193cml0ZV9zZW5hYmxlLCA0KSwNCj4+ICsJUkVHSVNU RVJfREVTQ19XSVRIX0xFTkdUSChHSUNSX0lDRU5BQkxFUjAsDQo+PiArCQl2Z2ljX21taW9fcmVh ZF9lbmFibGUsIHZnaWNfbW1pb193cml0ZV9jZW5hYmxlLCA0KSwNCj4+ICsJUkVHSVNURVJfREVT Q19XSVRIX0xFTkdUSChHSUNSX0lTUEVORFIwLA0KPj4gKwkJdmdpY19tbWlvX3JlYWRfcGVuZGlu ZywgdmdpY19tbWlvX3dyaXRlX3NwZW5kaW5nLCA0KSwNCj4+ICsJUkVHSVNURVJfREVTQ19XSVRI X0xFTkdUSChHSUNSX0lDUEVORFIwLA0KPj4gKwkJdmdpY19tbWlvX3JlYWRfcGVuZGluZywgdmdp Y19tbWlvX3dyaXRlX2NwZW5kaW5nLCA0KSwNCj4+ICsJUkVHSVNURVJfREVTQ19XSVRIX0xFTkdU SChHSUNSX0lTQUNUSVZFUjAsDQo+PiArCQl2Z2ljX21taW9fcmVhZF9hY3RpdmUsIHZnaWNfbW1p b193cml0ZV9zYWN0aXZlLCA0KSwNCj4+ICsJUkVHSVNURVJfREVTQ19XSVRIX0xFTkdUSChHSUNS X0lDQUNUSVZFUjAsDQo+PiArCQl2Z2ljX21taW9fcmVhZF9hY3RpdmUsIHZnaWNfbW1pb193cml0 ZV9jYWN0aXZlLCA0KSwNCj4+ICsJUkVHSVNURVJfREVTQ19XSVRIX0xFTkdUSChHSUNSX0lQUklP UklUWVIwLA0KPj4gKwkJdmdpY19tbWlvX3JlYWRfcHJpb3JpdHksIHZnaWNfbW1pb193cml0ZV9w cmlvcml0eSwgMzIpLA0KPj4gKwlSRUdJU1RFUl9ERVNDX1dJVEhfTEVOR1RIKEdJQ1JfSUNGR1Iw LA0KPj4gKwkJdmdpY19tbWlvX3JlYWRfY29uZmlnLCB2Z2ljX21taW9fd3JpdGVfY29uZmlnLCA4 KSwNCj4+ICsJUkVHSVNURVJfREVTQ19XSVRIX0xFTkdUSChHSUNSX0lHUlBNT0RSMCwNCj4+ICsJ CXZnaWNfbW1pb19yZWFkX3JheiwgdmdpY19tbWlvX3dyaXRlX3dpLCA0KSwNCj4+ICsJUkVHSVNU RVJfREVTQ19XSVRIX0xFTkdUSChHSUNSX05TQUNSLA0KPj4gKwkJdmdpY19tbWlvX3JlYWRfcmF6 LCB2Z2ljX21taW9fd3JpdGVfd2ksIDQpLA0KPj4gK307DQo+PiArDQo+PiArdW5zaWduZWQgaW50 IHZnaWNfdjNfaW5pdF9kaXN0X2lvZGV2KHN0cnVjdCB2Z2ljX2lvX2RldmljZSAqZGV2KQ0KPj4g K3sNCj4+ICsJZGV2LT5yZWdpb25zID0gdmdpY192M19kaXN0X3JlZ2lzdGVyczsNCj4+ICsJZGV2 LT5ucl9yZWdpb25zID0gQVJSQVlfU0laRSh2Z2ljX3YzX2Rpc3RfcmVnaXN0ZXJzKTsNCj4+ICsN Cj4+ICsJa3ZtX2lvZGV2aWNlX2luaXQoJmRldi0+ZGV2LCAma3ZtX2lvX2dpY19vcHMpOw0KPj4g Kw0KPj4gKwlyZXR1cm4gU1pfNjRLOw0KPj4gK30NCj4+ICsNCj4+ICtpbnQgdmdpY19yZWdpc3Rl cl9yZWRpc3RfaW9kZXZzKHN0cnVjdCBrdm0gKmt2bSwgZ3BhX3QgcmVkaXN0X2Jhc2VfYWRkcmVz cykNCj4+ICt7DQo+PiArCWludCBucl92Y3B1cyA9IGF0b21pY19yZWFkKCZrdm0tPm9ubGluZV92 Y3B1cyk7DQo+PiArCXN0cnVjdCBrdm1fdmNwdSAqdmNwdTsNCj4+ICsJc3RydWN0IHZnaWNfaW9f ZGV2aWNlICpkZXZpY2VzLCAqZGV2aWNlOw0KPj4gKwlpbnQgYywgcmV0ID0gMDsNCj4+ICsNCj4+ ICsJZGV2aWNlcyA9IGttYWxsb2Moc2l6ZW9mKHN0cnVjdCB2Z2ljX2lvX2RldmljZSkgKiBucl92 Y3B1cyAqIDIsDQo+PiArCQkJICBHRlBfS0VSTkVMKTsNCj4+ICsJaWYgKCFkZXZpY2VzKQ0KPj4g KwkJcmV0dXJuIC1FTk9NRU07DQo+PiArDQo+PiArCWRldmljZSA9IGRldmljZXM7DQo+PiArCWt2 bV9mb3JfZWFjaF92Y3B1KGMsIHZjcHUsIGt2bSkgew0KPj4gKwkJa3ZtX2lvZGV2aWNlX2luaXQo JmRldmljZS0+ZGV2LCAma3ZtX2lvX2dpY19vcHMpOw0KPj4gKwkJZGV2aWNlLT5iYXNlX2FkZHIg PSByZWRpc3RfYmFzZV9hZGRyZXNzOw0KPj4gKwkJZGV2aWNlLT5yZWdpb25zID0gdmdpY192M19y ZGJhc2VfcmVnaXN0ZXJzOw0KPj4gKwkJZGV2aWNlLT5ucl9yZWdpb25zID0gQVJSQVlfU0laRSh2 Z2ljX3YzX3JkYmFzZV9yZWdpc3RlcnMpOw0KPj4gKwkJZGV2aWNlLT5yZWRpc3RfdmNwdSA9IHZj cHU7DQo+PiArDQo+PiArCQltdXRleF9sb2NrKCZrdm0tPnNsb3RzX2xvY2spOw0KPj4gKwkJcmV0 ID0ga3ZtX2lvX2J1c19yZWdpc3Rlcl9kZXYoa3ZtLCBLVk1fTU1JT19CVVMsDQo+PiArCQkJCQkg ICAgICByZWRpc3RfYmFzZV9hZGRyZXNzLA0KPj4gKwkJCQkJICAgICAgU1pfNjRLLCAmZGV2aWNl LT5kZXYpOw0KPj4gKwkJbXV0ZXhfdW5sb2NrKCZrdm0tPnNsb3RzX2xvY2spOw0KPj4gKw0KPj4g KwkJaWYgKHJldCkNCj4+ICsJCQlicmVhazsNCj4+ICsNCj4+ICsJCWRldmljZSsrOw0KPj4gKwkJ a3ZtX2lvZGV2aWNlX2luaXQoJmRldmljZS0+ZGV2LCAma3ZtX2lvX2dpY19vcHMpOw0KPj4gKwkJ ZGV2aWNlLT5iYXNlX2FkZHIgPSByZWRpc3RfYmFzZV9hZGRyZXNzICsgU1pfNjRLOw0KPj4gKwkJ ZGV2aWNlLT5yZWdpb25zID0gdmdpY192M19zZ2liYXNlX3JlZ2lzdGVyczsNCj4+ICsJCWRldmlj ZS0+bnJfcmVnaW9ucyA9IEFSUkFZX1NJWkUodmdpY192M19zZ2liYXNlX3JlZ2lzdGVycyk7DQo+ PiArCQlkZXZpY2UtPnJlZGlzdF92Y3B1ID0gdmNwdTsNCj4+ICsNCj4+ICsJCW11dGV4X2xvY2so Jmt2bS0+c2xvdHNfbG9jayk7DQo+PiArCQlyZXQgPSBrdm1faW9fYnVzX3JlZ2lzdGVyX2Rldihr dm0sIEtWTV9NTUlPX0JVUywNCj4+ICsJCQkJCSAgICAgIHJlZGlzdF9iYXNlX2FkZHJlc3MgKyBT Wl82NEssDQo+PiArCQkJCQkgICAgICBTWl82NEssICZkZXZpY2UtPmRldik7DQo+PiArCQltdXRl eF91bmxvY2soJmt2bS0+c2xvdHNfbG9jayk7DQo+PiArCQlpZiAocmV0KSB7DQo+PiArCQkJa3Zt X2lvX2J1c191bnJlZ2lzdGVyX2Rldihrdm0sIEtWTV9NTUlPX0JVUywNCj4+ICsJCQkJCQkgICZk ZXZpY2VzW2MgKiAyXS5kZXYpOw0KPj4gKwkJCWJyZWFrOw0KPj4gKwkJfQ0KPj4gKwkJZGV2aWNl Kys7DQo+PiArCQlyZWRpc3RfYmFzZV9hZGRyZXNzICs9IDIgKiBTWl82NEs7DQo+PiArCX0NCj4N Cj5XaGF0IEkgZmFpbCB0byBzZWUgaGVyZSBpcyB3aGF0IHByZXZlbnRzIHRoZSByZWRpc3RyaWJ1 dG9yIHJhbmdlIGZyb20NCj5vdmVybGFwcGluZyB3aXRoIHRoZSBkaXN0cmlidXRvciAob3IgYW55 IG90aGVyIGRldmljZSkuIFRoZSBrdm0gSU8gYnVzDQo+aXMgaGFwcHkgd2l0aCBvdmVybGFwcGlu ZyBhZGRyZXNzZXMsIGJ1dCBJJ20gbm90IHN1cmUgYXQgYWxsIHRoYXQgdGhpcw0KPmlzIHNhZmUu DQo+DQo+Q2FyZSB0byBzaGVkIHNvbWUgbGlnaHQgb24gaXQ/DQoNCkFkZGVkIHRoZSBzYW1lIHF1 ZXN0aW9uIG9uIHdyb25nIHBhdGNoIGxhc3Qgd2VlaywgdGhhbmtzIE1hcmMuIA0KPg0KPlRoYW5r cywNCj4NCj4JTS4NCj4tLSANCj5KYXp6IGlzIG5vdCBkZWFkLiBJdCBqdXN0IHNtZWxscyBmdW5u eS4uLg0KPl9fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fDQo+ a3ZtYXJtIG1haWxpbmcgbGlzdA0KPmt2bWFybUBsaXN0cy5jcy5jb2x1bWJpYS5lZHUNCj5odHRw czovL2xpc3RzLmNzLmNvbHVtYmlhLmVkdS9tYWlsbWFuL2xpc3RpbmZvL2t2bWFybQ0K -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Fri, May 06, 2016 at 11:45:45AM +0100, Andre Przywara wrote: > Create a new file called vgic-mmio-v3.c and describe the GICv3 > distributor and redistributor registers there. > This adds a special macro to deal with the split of SGI/PPI in the > redistributor and SPIs in the distributor, which allows us to reuse > the existing GICv2 handlers for those registers which are compatible. > Also we provide a function to deal with the registration of the two > separate redistributor frames per VCPU. > > Signed-off-by: Andre Przywara <andre.przywara@arm.com> > Reviewed-by: Eric Auger <eric.auger@linaro.org> > --- > Changelog RFC..v1: > - adapt to new MMIO registration approach: > register one device for the distributor and two for each VCPU > - implement special handling for private interrupts > - remove empty stub functions > - make IGROUPR return RAO > > Changelog v1 .. v2: > - adapt to new framework, introduce vgic-mmio-v3.c > - remove userland register access functions (for now) > - precompute .len when describing a VGIC register > - add missed pointer incrementation on registering redist regions > - replace _nyi stub functions with raz/wi versions > > Changelog v2 .. v3: > - replace inclusion of kvm/vgic/vgic.h with kvm/arm_vgic.h > - add prototype and stub code for vgic_register_redist_iodevs > - rename register struct variables _rdbase_ and _sgibase_ > > virt/kvm/arm/vgic/vgic-mmio-v3.c | 191 +++++++++++++++++++++++++++++++++++++++ > virt/kvm/arm/vgic/vgic-mmio.c | 5 + > virt/kvm/arm/vgic/vgic-mmio.h | 2 + > virt/kvm/arm/vgic/vgic.h | 7 ++ > 4 files changed, 205 insertions(+) > create mode 100644 virt/kvm/arm/vgic/vgic-mmio-v3.c > > diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c > new file mode 100644 > index 0000000..06c7ec5 > --- /dev/null > +++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c > @@ -0,0 +1,191 @@ > +/* > + * VGICv3 MMIO handling functions > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License version 2 as > + * published by the Free Software Foundation. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + */ > + > +#include <linux/irqchip/arm-gic-v3.h> > +#include <linux/kvm.h> > +#include <linux/kvm_host.h> > +#include <kvm/iodev.h> > +#include <kvm/arm_vgic.h> > + > +#include <asm/kvm_emulate.h> > + > +#include "vgic.h" > +#include "vgic-mmio.h" > + > +/* > + * The GICv3 per-IRQ registers are split to control PPIs and SGIs in the > + * redistributors, while SPIs are covered by registers in the distributor > + * block. Trying to set private IRQs in this block gets ignored. > + * We take some special care here to fix the calculation of the register > + * offset. > + */ > +#define REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(off, read_ops, write_ops, bpi) \ > + { \ > + .reg_offset = off, \ > + .bits_per_irq = bpi, \ > + .len = (bpi * VGIC_NR_PRIVATE_IRQS) / 8, \ > + .read = vgic_mmio_read_raz, \ > + .write = vgic_mmio_write_wi, \ > + }, { \ > + .reg_offset = off + (bpi * VGIC_NR_PRIVATE_IRQS) / 8, \ > + .bits_per_irq = bpi, \ > + .len = (bpi * (1024 - VGIC_NR_PRIVATE_IRQS)) / 8, \ > + .read = read_ops, \ > + .write = write_ops, \ > + } > + > +static const struct vgic_register_region vgic_v3_dist_registers[] = { > + REGISTER_DESC_WITH_LENGTH(GICD_CTLR, > + vgic_mmio_read_raz, vgic_mmio_write_wi, 16), > + REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IGROUPR, > + vgic_mmio_read_rao, vgic_mmio_write_wi, 1), > + REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISENABLER, > + vgic_mmio_read_enable, vgic_mmio_write_senable, 1), > + REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICENABLER, > + vgic_mmio_read_enable, vgic_mmio_write_cenable, 1), > + REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISPENDR, > + vgic_mmio_read_pending, vgic_mmio_write_spending, 1), > + REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICPENDR, > + vgic_mmio_read_pending, vgic_mmio_write_cpending, 1), > + REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISACTIVER, > + vgic_mmio_read_active, vgic_mmio_write_sactive, 1), > + REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICACTIVER, > + vgic_mmio_read_active, vgic_mmio_write_cactive, 1), > + REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IPRIORITYR, > + vgic_mmio_read_priority, vgic_mmio_write_priority, 8), > + REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ITARGETSR, > + vgic_mmio_read_raz, vgic_mmio_write_wi, 8), > + REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICFGR, > + vgic_mmio_read_config, vgic_mmio_write_config, 2), > + REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IGRPMODR, > + vgic_mmio_read_raz, vgic_mmio_write_wi, 1), > + REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IROUTER, > + vgic_mmio_read_raz, vgic_mmio_write_wi, 64), > + REGISTER_DESC_WITH_LENGTH(GICD_IDREGS, > + vgic_mmio_read_raz, vgic_mmio_write_wi, 48), > +}; > + > +static const struct vgic_register_region vgic_v3_rdbase_registers[] = { > + REGISTER_DESC_WITH_LENGTH(GICR_CTLR, > + vgic_mmio_read_raz, vgic_mmio_write_wi, 4), > + REGISTER_DESC_WITH_LENGTH(GICR_IIDR, > + vgic_mmio_read_raz, vgic_mmio_write_wi, 4), > + REGISTER_DESC_WITH_LENGTH(GICR_TYPER, > + vgic_mmio_read_raz, vgic_mmio_write_wi, 8), > + REGISTER_DESC_WITH_LENGTH(GICR_PROPBASER, > + vgic_mmio_read_raz, vgic_mmio_write_wi, 8), > + REGISTER_DESC_WITH_LENGTH(GICR_PENDBASER, > + vgic_mmio_read_raz, vgic_mmio_write_wi, 8), > + REGISTER_DESC_WITH_LENGTH(GICR_IDREGS, > + vgic_mmio_read_raz, vgic_mmio_write_wi, 48), > +}; > + > +static const struct vgic_register_region vgic_v3_sgibase_registers[] = { > + REGISTER_DESC_WITH_LENGTH(GICR_IGROUPR0, > + vgic_mmio_read_rao, vgic_mmio_write_wi, 4), > + REGISTER_DESC_WITH_LENGTH(GICR_ISENABLER0, > + vgic_mmio_read_enable, vgic_mmio_write_senable, 4), > + REGISTER_DESC_WITH_LENGTH(GICR_ICENABLER0, > + vgic_mmio_read_enable, vgic_mmio_write_cenable, 4), > + REGISTER_DESC_WITH_LENGTH(GICR_ISPENDR0, > + vgic_mmio_read_pending, vgic_mmio_write_spending, 4), > + REGISTER_DESC_WITH_LENGTH(GICR_ICPENDR0, > + vgic_mmio_read_pending, vgic_mmio_write_cpending, 4), > + REGISTER_DESC_WITH_LENGTH(GICR_ISACTIVER0, > + vgic_mmio_read_active, vgic_mmio_write_sactive, 4), > + REGISTER_DESC_WITH_LENGTH(GICR_ICACTIVER0, > + vgic_mmio_read_active, vgic_mmio_write_cactive, 4), > + REGISTER_DESC_WITH_LENGTH(GICR_IPRIORITYR0, > + vgic_mmio_read_priority, vgic_mmio_write_priority, 32), > + REGISTER_DESC_WITH_LENGTH(GICR_ICFGR0, > + vgic_mmio_read_config, vgic_mmio_write_config, 8), > + REGISTER_DESC_WITH_LENGTH(GICR_IGRPMODR0, > + vgic_mmio_read_raz, vgic_mmio_write_wi, 4), > + REGISTER_DESC_WITH_LENGTH(GICR_NSACR, > + vgic_mmio_read_raz, vgic_mmio_write_wi, 4), > +}; > + > +unsigned int vgic_v3_init_dist_iodev(struct vgic_io_device *dev) > +{ > + dev->regions = vgic_v3_dist_registers; > + dev->nr_regions = ARRAY_SIZE(vgic_v3_dist_registers); > + > + kvm_iodevice_init(&dev->dev, &kvm_io_gic_ops); > + > + return SZ_64K; > +} > + > +int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t redist_base_address) > +{ > + int nr_vcpus = atomic_read(&kvm->online_vcpus); > + struct kvm_vcpu *vcpu; > + struct vgic_io_device *devices, *device; > + int c, ret = 0; > + > + devices = kmalloc(sizeof(struct vgic_io_device) * nr_vcpus * 2, > + GFP_KERNEL); > + if (!devices) > + return -ENOMEM; > + > + device = devices; > + kvm_for_each_vcpu(c, vcpu, kvm) { > + kvm_iodevice_init(&device->dev, &kvm_io_gic_ops); > + device->base_addr = redist_base_address; > + device->regions = vgic_v3_rdbase_registers; > + device->nr_regions = ARRAY_SIZE(vgic_v3_rdbase_registers); > + device->redist_vcpu = vcpu; > + > + mutex_lock(&kvm->slots_lock); > + ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, > + redist_base_address, > + SZ_64K, &device->dev); > + mutex_unlock(&kvm->slots_lock); > + > + if (ret) > + break; > + > + device++; > + kvm_iodevice_init(&device->dev, &kvm_io_gic_ops); > + device->base_addr = redist_base_address + SZ_64K; > + device->regions = vgic_v3_sgibase_registers; > + device->nr_regions = ARRAY_SIZE(vgic_v3_sgibase_registers); > + device->redist_vcpu = vcpu; > + > + mutex_lock(&kvm->slots_lock); > + ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, > + redist_base_address + SZ_64K, > + SZ_64K, &device->dev); > + mutex_unlock(&kvm->slots_lock); > + if (ret) { > + kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS, > + &devices[c * 2].dev); > + break; > + } > + device++; > + redist_base_address += 2 * SZ_64K; while I think this whole thing is actually correct, I think it could have been much more clear by, in the beginning of the loop doing: gpa_t rd_base = redist_base_address + c * SZ_64K * 2; gpa_t sgi_base = rd_base + SZ_64K; struct vgic_io_device *rd_dev = &devices[c]; struct vgic_io_device *sgi_dev = &devices[c + 1]; and then referring directly to these variables. > + } > + > + if (ret) { > + for (c--; c >= 0; c--) { holy dark mother of all that's evil; I think this is correct. > + kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS, > + &devices[c * 2].dev); > + kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS, > + &devices[c * 2 + 1].dev); do we really need this though? Can't we just rely on KVM to tear down thew whole bus infrastructure as we're returning an error anyway? (have you looked at what the unregister_dev function does, it's full of kmallocs and other fun stuff). Thanks, -Christoffer > + } > + kfree(devices); > + } else { > + kvm->arch.vgic.redist_iodevs = devices; > + } > + > + return ret; > +} > diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c > index 19fed56..d1b88d2 100644 > --- a/virt/kvm/arm/vgic/vgic-mmio.c > +++ b/virt/kvm/arm/vgic/vgic-mmio.c > @@ -502,6 +502,11 @@ int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address, > case VGIC_V2: > len = vgic_v2_init_dist_iodev(io_device); > break; > +#ifdef CONFIG_KVM_ARM_VGIC_V3 > + case VGIC_V3: > + len = vgic_v3_init_dist_iodev(io_device); > + break; > +#endif > default: > BUG_ON(1); > } > diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h > index 884eb71..3585ac6 100644 > --- a/virt/kvm/arm/vgic/vgic-mmio.h > +++ b/virt/kvm/arm/vgic/vgic-mmio.h > @@ -123,4 +123,6 @@ void vgic_mmio_write_config(struct kvm_vcpu *vcpu, > > unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev); > > +unsigned int vgic_v3_init_dist_iodev(struct vgic_io_device *dev); > + > #endif > diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h > index cf62015..39a8a65 100644 > --- a/virt/kvm/arm/vgic/vgic.h > +++ b/virt/kvm/arm/vgic/vgic.h > @@ -40,6 +40,7 @@ void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu); > void vgic_v3_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr); > void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr); > void vgic_v3_set_underflow(struct kvm_vcpu *vcpu); > +int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t dist_base_address); > #else > static inline void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu) > { > @@ -61,6 +62,12 @@ static inline void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr) > static inline void vgic_v3_set_underflow(struct kvm_vcpu *vcpu) > { > } > + > +static inline int vgic_register_redist_iodevs(struct kvm *kvm, > + gpa_t dist_base_address) > +{ > + return -ENODEV; > +} > #endif > > #endif > -- > 2.7.3 > -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Hi, On 12/05/16 11:26, Christoffer Dall wrote: > On Fri, May 06, 2016 at 11:45:45AM +0100, Andre Przywara wrote: >> Create a new file called vgic-mmio-v3.c and describe the GICv3 >> distributor and redistributor registers there. >> This adds a special macro to deal with the split of SGI/PPI in the >> redistributor and SPIs in the distributor, which allows us to reuse >> the existing GICv2 handlers for those registers which are compatible. >> Also we provide a function to deal with the registration of the two >> separate redistributor frames per VCPU. >> >> Signed-off-by: Andre Przywara <andre.przywara@arm.com> >> Reviewed-by: Eric Auger <eric.auger@linaro.org> >> --- >> Changelog RFC..v1: >> - adapt to new MMIO registration approach: >> register one device for the distributor and two for each VCPU >> - implement special handling for private interrupts >> - remove empty stub functions >> - make IGROUPR return RAO >> >> Changelog v1 .. v2: >> - adapt to new framework, introduce vgic-mmio-v3.c >> - remove userland register access functions (for now) >> - precompute .len when describing a VGIC register >> - add missed pointer incrementation on registering redist regions >> - replace _nyi stub functions with raz/wi versions >> >> Changelog v2 .. v3: >> - replace inclusion of kvm/vgic/vgic.h with kvm/arm_vgic.h >> - add prototype and stub code for vgic_register_redist_iodevs >> - rename register struct variables _rdbase_ and _sgibase_ >> >> virt/kvm/arm/vgic/vgic-mmio-v3.c | 191 +++++++++++++++++++++++++++++++++++++++ >> virt/kvm/arm/vgic/vgic-mmio.c | 5 + >> virt/kvm/arm/vgic/vgic-mmio.h | 2 + >> virt/kvm/arm/vgic/vgic.h | 7 ++ >> 4 files changed, 205 insertions(+) >> create mode 100644 virt/kvm/arm/vgic/vgic-mmio-v3.c >> >> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c >> new file mode 100644 >> index 0000000..06c7ec5 >> --- /dev/null >> +++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c >> @@ -0,0 +1,191 @@ >> +/* >> + * VGICv3 MMIO handling functions >> + * >> + * This program is free software; you can redistribute it and/or modify >> + * it under the terms of the GNU General Public License version 2 as >> + * published by the Free Software Foundation. >> + * >> + * This program is distributed in the hope that it will be useful, >> + * but WITHOUT ANY WARRANTY; without even the implied warranty of >> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >> + * GNU General Public License for more details. >> + */ >> + >> +#include <linux/irqchip/arm-gic-v3.h> >> +#include <linux/kvm.h> >> +#include <linux/kvm_host.h> >> +#include <kvm/iodev.h> >> +#include <kvm/arm_vgic.h> >> + >> +#include <asm/kvm_emulate.h> >> + >> +#include "vgic.h" >> +#include "vgic-mmio.h" >> + >> +/* >> + * The GICv3 per-IRQ registers are split to control PPIs and SGIs in the >> + * redistributors, while SPIs are covered by registers in the distributor >> + * block. Trying to set private IRQs in this block gets ignored. >> + * We take some special care here to fix the calculation of the register >> + * offset. >> + */ >> +#define REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(off, read_ops, write_ops, bpi) \ >> + { \ >> + .reg_offset = off, \ >> + .bits_per_irq = bpi, \ >> + .len = (bpi * VGIC_NR_PRIVATE_IRQS) / 8, \ >> + .read = vgic_mmio_read_raz, \ >> + .write = vgic_mmio_write_wi, \ >> + }, { \ >> + .reg_offset = off + (bpi * VGIC_NR_PRIVATE_IRQS) / 8, \ >> + .bits_per_irq = bpi, \ >> + .len = (bpi * (1024 - VGIC_NR_PRIVATE_IRQS)) / 8, \ >> + .read = read_ops, \ >> + .write = write_ops, \ >> + } >> + >> +static const struct vgic_register_region vgic_v3_dist_registers[] = { >> + REGISTER_DESC_WITH_LENGTH(GICD_CTLR, >> + vgic_mmio_read_raz, vgic_mmio_write_wi, 16), >> + REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IGROUPR, >> + vgic_mmio_read_rao, vgic_mmio_write_wi, 1), >> + REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISENABLER, >> + vgic_mmio_read_enable, vgic_mmio_write_senable, 1), >> + REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICENABLER, >> + vgic_mmio_read_enable, vgic_mmio_write_cenable, 1), >> + REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISPENDR, >> + vgic_mmio_read_pending, vgic_mmio_write_spending, 1), >> + REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICPENDR, >> + vgic_mmio_read_pending, vgic_mmio_write_cpending, 1), >> + REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISACTIVER, >> + vgic_mmio_read_active, vgic_mmio_write_sactive, 1), >> + REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICACTIVER, >> + vgic_mmio_read_active, vgic_mmio_write_cactive, 1), >> + REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IPRIORITYR, >> + vgic_mmio_read_priority, vgic_mmio_write_priority, 8), >> + REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ITARGETSR, >> + vgic_mmio_read_raz, vgic_mmio_write_wi, 8), >> + REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICFGR, >> + vgic_mmio_read_config, vgic_mmio_write_config, 2), >> + REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IGRPMODR, >> + vgic_mmio_read_raz, vgic_mmio_write_wi, 1), >> + REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IROUTER, >> + vgic_mmio_read_raz, vgic_mmio_write_wi, 64), >> + REGISTER_DESC_WITH_LENGTH(GICD_IDREGS, >> + vgic_mmio_read_raz, vgic_mmio_write_wi, 48), >> +}; >> + >> +static const struct vgic_register_region vgic_v3_rdbase_registers[] = { >> + REGISTER_DESC_WITH_LENGTH(GICR_CTLR, >> + vgic_mmio_read_raz, vgic_mmio_write_wi, 4), >> + REGISTER_DESC_WITH_LENGTH(GICR_IIDR, >> + vgic_mmio_read_raz, vgic_mmio_write_wi, 4), >> + REGISTER_DESC_WITH_LENGTH(GICR_TYPER, >> + vgic_mmio_read_raz, vgic_mmio_write_wi, 8), >> + REGISTER_DESC_WITH_LENGTH(GICR_PROPBASER, >> + vgic_mmio_read_raz, vgic_mmio_write_wi, 8), >> + REGISTER_DESC_WITH_LENGTH(GICR_PENDBASER, >> + vgic_mmio_read_raz, vgic_mmio_write_wi, 8), >> + REGISTER_DESC_WITH_LENGTH(GICR_IDREGS, >> + vgic_mmio_read_raz, vgic_mmio_write_wi, 48), >> +}; >> + >> +static const struct vgic_register_region vgic_v3_sgibase_registers[] = { >> + REGISTER_DESC_WITH_LENGTH(GICR_IGROUPR0, >> + vgic_mmio_read_rao, vgic_mmio_write_wi, 4), >> + REGISTER_DESC_WITH_LENGTH(GICR_ISENABLER0, >> + vgic_mmio_read_enable, vgic_mmio_write_senable, 4), >> + REGISTER_DESC_WITH_LENGTH(GICR_ICENABLER0, >> + vgic_mmio_read_enable, vgic_mmio_write_cenable, 4), >> + REGISTER_DESC_WITH_LENGTH(GICR_ISPENDR0, >> + vgic_mmio_read_pending, vgic_mmio_write_spending, 4), >> + REGISTER_DESC_WITH_LENGTH(GICR_ICPENDR0, >> + vgic_mmio_read_pending, vgic_mmio_write_cpending, 4), >> + REGISTER_DESC_WITH_LENGTH(GICR_ISACTIVER0, >> + vgic_mmio_read_active, vgic_mmio_write_sactive, 4), >> + REGISTER_DESC_WITH_LENGTH(GICR_ICACTIVER0, >> + vgic_mmio_read_active, vgic_mmio_write_cactive, 4), >> + REGISTER_DESC_WITH_LENGTH(GICR_IPRIORITYR0, >> + vgic_mmio_read_priority, vgic_mmio_write_priority, 32), >> + REGISTER_DESC_WITH_LENGTH(GICR_ICFGR0, >> + vgic_mmio_read_config, vgic_mmio_write_config, 8), >> + REGISTER_DESC_WITH_LENGTH(GICR_IGRPMODR0, >> + vgic_mmio_read_raz, vgic_mmio_write_wi, 4), >> + REGISTER_DESC_WITH_LENGTH(GICR_NSACR, >> + vgic_mmio_read_raz, vgic_mmio_write_wi, 4), >> +}; >> + >> +unsigned int vgic_v3_init_dist_iodev(struct vgic_io_device *dev) >> +{ >> + dev->regions = vgic_v3_dist_registers; >> + dev->nr_regions = ARRAY_SIZE(vgic_v3_dist_registers); >> + >> + kvm_iodevice_init(&dev->dev, &kvm_io_gic_ops); >> + >> + return SZ_64K; >> +} >> + >> +int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t redist_base_address) >> +{ >> + int nr_vcpus = atomic_read(&kvm->online_vcpus); >> + struct kvm_vcpu *vcpu; >> + struct vgic_io_device *devices, *device; >> + int c, ret = 0; >> + >> + devices = kmalloc(sizeof(struct vgic_io_device) * nr_vcpus * 2, >> + GFP_KERNEL); >> + if (!devices) >> + return -ENOMEM; >> + >> + device = devices; >> + kvm_for_each_vcpu(c, vcpu, kvm) { >> + kvm_iodevice_init(&device->dev, &kvm_io_gic_ops); >> + device->base_addr = redist_base_address; >> + device->regions = vgic_v3_rdbase_registers; >> + device->nr_regions = ARRAY_SIZE(vgic_v3_rdbase_registers); >> + device->redist_vcpu = vcpu; >> + >> + mutex_lock(&kvm->slots_lock); >> + ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, >> + redist_base_address, >> + SZ_64K, &device->dev); >> + mutex_unlock(&kvm->slots_lock); >> + >> + if (ret) >> + break; >> + >> + device++; >> + kvm_iodevice_init(&device->dev, &kvm_io_gic_ops); >> + device->base_addr = redist_base_address + SZ_64K; >> + device->regions = vgic_v3_sgibase_registers; >> + device->nr_regions = ARRAY_SIZE(vgic_v3_sgibase_registers); >> + device->redist_vcpu = vcpu; >> + >> + mutex_lock(&kvm->slots_lock); >> + ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, >> + redist_base_address + SZ_64K, >> + SZ_64K, &device->dev); >> + mutex_unlock(&kvm->slots_lock); >> + if (ret) { >> + kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS, >> + &devices[c * 2].dev); >> + break; >> + } >> + device++; >> + redist_base_address += 2 * SZ_64K; > > while I think this whole thing is actually correct, I think it could > have been much more clear by, in the beginning of the loop doing: > > gpa_t rd_base = redist_base_address + c * SZ_64K * 2; > gpa_t sgi_base = rd_base + SZ_64K; > struct vgic_io_device *rd_dev = &devices[c]; > struct vgic_io_device *sgi_dev = &devices[c + 1]; > > and then referring directly to these variables. Yeah, looks useful, not sure we want to change it last minute though. >> + } >> + >> + if (ret) { >> + for (c--; c >= 0; c--) { > > holy dark mother of all that's evil; I think this is correct. > >> + kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS, >> + &devices[c * 2].dev); >> + kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS, >> + &devices[c * 2 + 1].dev); > > do we really need this though? Can't we just rely on KVM to tear down > thew whole bus infrastructure as we're returning an error anyway? I haven't checked if this is really necessary, but this missing teardown was mentioned multiple times in previous reviews, so I just did it. We can remove it once we have proven that it's pointless later. > (have you looked at what the unregister_dev function does, it's full of > kmallocs and other fun stuff). TBH, this whole kvm_io_bus framework is really weird (I think registering a new region copies every thing it had before) and designed for the x86 use case. But it shouldn't be this series which fixes this. Cheers, Andre. > > Thanks, > -Christoffer > >> + } >> + kfree(devices); >> + } else { >> + kvm->arch.vgic.redist_iodevs = devices; >> + } >> + >> + return ret; >> +} >> diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c >> index 19fed56..d1b88d2 100644 >> --- a/virt/kvm/arm/vgic/vgic-mmio.c >> +++ b/virt/kvm/arm/vgic/vgic-mmio.c >> @@ -502,6 +502,11 @@ int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address, >> case VGIC_V2: >> len = vgic_v2_init_dist_iodev(io_device); >> break; >> +#ifdef CONFIG_KVM_ARM_VGIC_V3 >> + case VGIC_V3: >> + len = vgic_v3_init_dist_iodev(io_device); >> + break; >> +#endif >> default: >> BUG_ON(1); >> } >> diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h >> index 884eb71..3585ac6 100644 >> --- a/virt/kvm/arm/vgic/vgic-mmio.h >> +++ b/virt/kvm/arm/vgic/vgic-mmio.h >> @@ -123,4 +123,6 @@ void vgic_mmio_write_config(struct kvm_vcpu *vcpu, >> >> unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev); >> >> +unsigned int vgic_v3_init_dist_iodev(struct vgic_io_device *dev); >> + >> #endif >> diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h >> index cf62015..39a8a65 100644 >> --- a/virt/kvm/arm/vgic/vgic.h >> +++ b/virt/kvm/arm/vgic/vgic.h >> @@ -40,6 +40,7 @@ void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu); >> void vgic_v3_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr); >> void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr); >> void vgic_v3_set_underflow(struct kvm_vcpu *vcpu); >> +int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t dist_base_address); >> #else >> static inline void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu) >> { >> @@ -61,6 +62,12 @@ static inline void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr) >> static inline void vgic_v3_set_underflow(struct kvm_vcpu *vcpu) >> { >> } >> + >> +static inline int vgic_register_redist_iodevs(struct kvm *kvm, >> + gpa_t dist_base_address) >> +{ >> + return -ENODEV; >> +} >> #endif >> >> #endif >> -- >> 2.7.3 >> > > -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On 12/05/16 11:52, Andre Przywara wrote: > Hi, > > On 12/05/16 11:26, Christoffer Dall wrote: >> On Fri, May 06, 2016 at 11:45:45AM +0100, Andre Przywara wrote: >>> Create a new file called vgic-mmio-v3.c and describe the GICv3 >>> distributor and redistributor registers there. >>> This adds a special macro to deal with the split of SGI/PPI in the >>> redistributor and SPIs in the distributor, which allows us to reuse >>> the existing GICv2 handlers for those registers which are compatible. >>> Also we provide a function to deal with the registration of the two >>> separate redistributor frames per VCPU. >>> >>> Signed-off-by: Andre Przywara <andre.przywara@arm.com> >>> Reviewed-by: Eric Auger <eric.auger@linaro.org> >>> --- >>> Changelog RFC..v1: >>> - adapt to new MMIO registration approach: >>> register one device for the distributor and two for each VCPU >>> - implement special handling for private interrupts >>> - remove empty stub functions >>> - make IGROUPR return RAO >>> >>> Changelog v1 .. v2: >>> - adapt to new framework, introduce vgic-mmio-v3.c >>> - remove userland register access functions (for now) >>> - precompute .len when describing a VGIC register >>> - add missed pointer incrementation on registering redist regions >>> - replace _nyi stub functions with raz/wi versions >>> >>> Changelog v2 .. v3: >>> - replace inclusion of kvm/vgic/vgic.h with kvm/arm_vgic.h >>> - add prototype and stub code for vgic_register_redist_iodevs >>> - rename register struct variables _rdbase_ and _sgibase_ >>> >>> virt/kvm/arm/vgic/vgic-mmio-v3.c | 191 +++++++++++++++++++++++++++++++++++++++ >>> virt/kvm/arm/vgic/vgic-mmio.c | 5 + >>> virt/kvm/arm/vgic/vgic-mmio.h | 2 + >>> virt/kvm/arm/vgic/vgic.h | 7 ++ >>> 4 files changed, 205 insertions(+) >>> create mode 100644 virt/kvm/arm/vgic/vgic-mmio-v3.c >>> >>> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c >>> new file mode 100644 >>> index 0000000..06c7ec5 >>> --- /dev/null >>> +++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c >>> @@ -0,0 +1,191 @@ >>> +/* >>> + * VGICv3 MMIO handling functions >>> + * >>> + * This program is free software; you can redistribute it and/or modify >>> + * it under the terms of the GNU General Public License version 2 as >>> + * published by the Free Software Foundation. >>> + * >>> + * This program is distributed in the hope that it will be useful, >>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of >>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >>> + * GNU General Public License for more details. >>> + */ >>> + >>> +#include <linux/irqchip/arm-gic-v3.h> >>> +#include <linux/kvm.h> >>> +#include <linux/kvm_host.h> >>> +#include <kvm/iodev.h> >>> +#include <kvm/arm_vgic.h> >>> + >>> +#include <asm/kvm_emulate.h> >>> + >>> +#include "vgic.h" >>> +#include "vgic-mmio.h" >>> + >>> +/* >>> + * The GICv3 per-IRQ registers are split to control PPIs and SGIs in the >>> + * redistributors, while SPIs are covered by registers in the distributor >>> + * block. Trying to set private IRQs in this block gets ignored. >>> + * We take some special care here to fix the calculation of the register >>> + * offset. >>> + */ >>> +#define REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(off, read_ops, write_ops, bpi) \ >>> + { \ >>> + .reg_offset = off, \ >>> + .bits_per_irq = bpi, \ >>> + .len = (bpi * VGIC_NR_PRIVATE_IRQS) / 8, \ >>> + .read = vgic_mmio_read_raz, \ >>> + .write = vgic_mmio_write_wi, \ >>> + }, { \ >>> + .reg_offset = off + (bpi * VGIC_NR_PRIVATE_IRQS) / 8, \ >>> + .bits_per_irq = bpi, \ >>> + .len = (bpi * (1024 - VGIC_NR_PRIVATE_IRQS)) / 8, \ >>> + .read = read_ops, \ >>> + .write = write_ops, \ >>> + } >>> + >>> +static const struct vgic_register_region vgic_v3_dist_registers[] = { >>> + REGISTER_DESC_WITH_LENGTH(GICD_CTLR, >>> + vgic_mmio_read_raz, vgic_mmio_write_wi, 16), >>> + REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IGROUPR, >>> + vgic_mmio_read_rao, vgic_mmio_write_wi, 1), >>> + REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISENABLER, >>> + vgic_mmio_read_enable, vgic_mmio_write_senable, 1), >>> + REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICENABLER, >>> + vgic_mmio_read_enable, vgic_mmio_write_cenable, 1), >>> + REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISPENDR, >>> + vgic_mmio_read_pending, vgic_mmio_write_spending, 1), >>> + REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICPENDR, >>> + vgic_mmio_read_pending, vgic_mmio_write_cpending, 1), >>> + REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISACTIVER, >>> + vgic_mmio_read_active, vgic_mmio_write_sactive, 1), >>> + REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICACTIVER, >>> + vgic_mmio_read_active, vgic_mmio_write_cactive, 1), >>> + REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IPRIORITYR, >>> + vgic_mmio_read_priority, vgic_mmio_write_priority, 8), >>> + REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ITARGETSR, >>> + vgic_mmio_read_raz, vgic_mmio_write_wi, 8), >>> + REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICFGR, >>> + vgic_mmio_read_config, vgic_mmio_write_config, 2), >>> + REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IGRPMODR, >>> + vgic_mmio_read_raz, vgic_mmio_write_wi, 1), >>> + REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IROUTER, >>> + vgic_mmio_read_raz, vgic_mmio_write_wi, 64), >>> + REGISTER_DESC_WITH_LENGTH(GICD_IDREGS, >>> + vgic_mmio_read_raz, vgic_mmio_write_wi, 48), >>> +}; >>> + >>> +static const struct vgic_register_region vgic_v3_rdbase_registers[] = { >>> + REGISTER_DESC_WITH_LENGTH(GICR_CTLR, >>> + vgic_mmio_read_raz, vgic_mmio_write_wi, 4), >>> + REGISTER_DESC_WITH_LENGTH(GICR_IIDR, >>> + vgic_mmio_read_raz, vgic_mmio_write_wi, 4), >>> + REGISTER_DESC_WITH_LENGTH(GICR_TYPER, >>> + vgic_mmio_read_raz, vgic_mmio_write_wi, 8), >>> + REGISTER_DESC_WITH_LENGTH(GICR_PROPBASER, >>> + vgic_mmio_read_raz, vgic_mmio_write_wi, 8), >>> + REGISTER_DESC_WITH_LENGTH(GICR_PENDBASER, >>> + vgic_mmio_read_raz, vgic_mmio_write_wi, 8), >>> + REGISTER_DESC_WITH_LENGTH(GICR_IDREGS, >>> + vgic_mmio_read_raz, vgic_mmio_write_wi, 48), >>> +}; >>> + >>> +static const struct vgic_register_region vgic_v3_sgibase_registers[] = { >>> + REGISTER_DESC_WITH_LENGTH(GICR_IGROUPR0, >>> + vgic_mmio_read_rao, vgic_mmio_write_wi, 4), >>> + REGISTER_DESC_WITH_LENGTH(GICR_ISENABLER0, >>> + vgic_mmio_read_enable, vgic_mmio_write_senable, 4), >>> + REGISTER_DESC_WITH_LENGTH(GICR_ICENABLER0, >>> + vgic_mmio_read_enable, vgic_mmio_write_cenable, 4), >>> + REGISTER_DESC_WITH_LENGTH(GICR_ISPENDR0, >>> + vgic_mmio_read_pending, vgic_mmio_write_spending, 4), >>> + REGISTER_DESC_WITH_LENGTH(GICR_ICPENDR0, >>> + vgic_mmio_read_pending, vgic_mmio_write_cpending, 4), >>> + REGISTER_DESC_WITH_LENGTH(GICR_ISACTIVER0, >>> + vgic_mmio_read_active, vgic_mmio_write_sactive, 4), >>> + REGISTER_DESC_WITH_LENGTH(GICR_ICACTIVER0, >>> + vgic_mmio_read_active, vgic_mmio_write_cactive, 4), >>> + REGISTER_DESC_WITH_LENGTH(GICR_IPRIORITYR0, >>> + vgic_mmio_read_priority, vgic_mmio_write_priority, 32), >>> + REGISTER_DESC_WITH_LENGTH(GICR_ICFGR0, >>> + vgic_mmio_read_config, vgic_mmio_write_config, 8), >>> + REGISTER_DESC_WITH_LENGTH(GICR_IGRPMODR0, >>> + vgic_mmio_read_raz, vgic_mmio_write_wi, 4), >>> + REGISTER_DESC_WITH_LENGTH(GICR_NSACR, >>> + vgic_mmio_read_raz, vgic_mmio_write_wi, 4), >>> +}; >>> + >>> +unsigned int vgic_v3_init_dist_iodev(struct vgic_io_device *dev) >>> +{ >>> + dev->regions = vgic_v3_dist_registers; >>> + dev->nr_regions = ARRAY_SIZE(vgic_v3_dist_registers); >>> + >>> + kvm_iodevice_init(&dev->dev, &kvm_io_gic_ops); >>> + >>> + return SZ_64K; >>> +} >>> + >>> +int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t redist_base_address) >>> +{ >>> + int nr_vcpus = atomic_read(&kvm->online_vcpus); >>> + struct kvm_vcpu *vcpu; >>> + struct vgic_io_device *devices, *device; >>> + int c, ret = 0; >>> + >>> + devices = kmalloc(sizeof(struct vgic_io_device) * nr_vcpus * 2, >>> + GFP_KERNEL); >>> + if (!devices) >>> + return -ENOMEM; >>> + >>> + device = devices; >>> + kvm_for_each_vcpu(c, vcpu, kvm) { >>> + kvm_iodevice_init(&device->dev, &kvm_io_gic_ops); >>> + device->base_addr = redist_base_address; >>> + device->regions = vgic_v3_rdbase_registers; >>> + device->nr_regions = ARRAY_SIZE(vgic_v3_rdbase_registers); >>> + device->redist_vcpu = vcpu; >>> + >>> + mutex_lock(&kvm->slots_lock); >>> + ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, >>> + redist_base_address, >>> + SZ_64K, &device->dev); >>> + mutex_unlock(&kvm->slots_lock); >>> + >>> + if (ret) >>> + break; >>> + >>> + device++; >>> + kvm_iodevice_init(&device->dev, &kvm_io_gic_ops); >>> + device->base_addr = redist_base_address + SZ_64K; >>> + device->regions = vgic_v3_sgibase_registers; >>> + device->nr_regions = ARRAY_SIZE(vgic_v3_sgibase_registers); >>> + device->redist_vcpu = vcpu; >>> + >>> + mutex_lock(&kvm->slots_lock); >>> + ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, >>> + redist_base_address + SZ_64K, >>> + SZ_64K, &device->dev); >>> + mutex_unlock(&kvm->slots_lock); >>> + if (ret) { >>> + kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS, >>> + &devices[c * 2].dev); >>> + break; >>> + } >>> + device++; >>> + redist_base_address += 2 * SZ_64K; >> >> while I think this whole thing is actually correct, I think it could >> have been much more clear by, in the beginning of the loop doing: >> >> gpa_t rd_base = redist_base_address + c * SZ_64K * 2; >> gpa_t sgi_base = rd_base + SZ_64K; >> struct vgic_io_device *rd_dev = &devices[c]; >> struct vgic_io_device *sgi_dev = &devices[c + 1]; >> >> and then referring directly to these variables. > > Yeah, looks useful, not sure we want to change it last minute though. Why not? We're changing much more fundamental things already. I'd rather have something that I can easily read and convince myself that it does the right thing rather than merge something that I'm suspicious of. In other words, we fix it. Thanks, M.
diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c new file mode 100644 index 0000000..06c7ec5 --- /dev/null +++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c @@ -0,0 +1,191 @@ +/* + * VGICv3 MMIO handling functions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/irqchip/arm-gic-v3.h> +#include <linux/kvm.h> +#include <linux/kvm_host.h> +#include <kvm/iodev.h> +#include <kvm/arm_vgic.h> + +#include <asm/kvm_emulate.h> + +#include "vgic.h" +#include "vgic-mmio.h" + +/* + * The GICv3 per-IRQ registers are split to control PPIs and SGIs in the + * redistributors, while SPIs are covered by registers in the distributor + * block. Trying to set private IRQs in this block gets ignored. + * We take some special care here to fix the calculation of the register + * offset. + */ +#define REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(off, read_ops, write_ops, bpi) \ + { \ + .reg_offset = off, \ + .bits_per_irq = bpi, \ + .len = (bpi * VGIC_NR_PRIVATE_IRQS) / 8, \ + .read = vgic_mmio_read_raz, \ + .write = vgic_mmio_write_wi, \ + }, { \ + .reg_offset = off + (bpi * VGIC_NR_PRIVATE_IRQS) / 8, \ + .bits_per_irq = bpi, \ + .len = (bpi * (1024 - VGIC_NR_PRIVATE_IRQS)) / 8, \ + .read = read_ops, \ + .write = write_ops, \ + } + +static const struct vgic_register_region vgic_v3_dist_registers[] = { + REGISTER_DESC_WITH_LENGTH(GICD_CTLR, + vgic_mmio_read_raz, vgic_mmio_write_wi, 16), + REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IGROUPR, + vgic_mmio_read_rao, vgic_mmio_write_wi, 1), + REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISENABLER, + vgic_mmio_read_enable, vgic_mmio_write_senable, 1), + REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICENABLER, + vgic_mmio_read_enable, vgic_mmio_write_cenable, 1), + REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISPENDR, + vgic_mmio_read_pending, vgic_mmio_write_spending, 1), + REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICPENDR, + vgic_mmio_read_pending, vgic_mmio_write_cpending, 1), + REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISACTIVER, + vgic_mmio_read_active, vgic_mmio_write_sactive, 1), + REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICACTIVER, + vgic_mmio_read_active, vgic_mmio_write_cactive, 1), + REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IPRIORITYR, + vgic_mmio_read_priority, vgic_mmio_write_priority, 8), + REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ITARGETSR, + vgic_mmio_read_raz, vgic_mmio_write_wi, 8), + REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICFGR, + vgic_mmio_read_config, vgic_mmio_write_config, 2), + REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IGRPMODR, + vgic_mmio_read_raz, vgic_mmio_write_wi, 1), + REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IROUTER, + vgic_mmio_read_raz, vgic_mmio_write_wi, 64), + REGISTER_DESC_WITH_LENGTH(GICD_IDREGS, + vgic_mmio_read_raz, vgic_mmio_write_wi, 48), +}; + +static const struct vgic_register_region vgic_v3_rdbase_registers[] = { + REGISTER_DESC_WITH_LENGTH(GICR_CTLR, + vgic_mmio_read_raz, vgic_mmio_write_wi, 4), + REGISTER_DESC_WITH_LENGTH(GICR_IIDR, + vgic_mmio_read_raz, vgic_mmio_write_wi, 4), + REGISTER_DESC_WITH_LENGTH(GICR_TYPER, + vgic_mmio_read_raz, vgic_mmio_write_wi, 8), + REGISTER_DESC_WITH_LENGTH(GICR_PROPBASER, + vgic_mmio_read_raz, vgic_mmio_write_wi, 8), + REGISTER_DESC_WITH_LENGTH(GICR_PENDBASER, + vgic_mmio_read_raz, vgic_mmio_write_wi, 8), + REGISTER_DESC_WITH_LENGTH(GICR_IDREGS, + vgic_mmio_read_raz, vgic_mmio_write_wi, 48), +}; + +static const struct vgic_register_region vgic_v3_sgibase_registers[] = { + REGISTER_DESC_WITH_LENGTH(GICR_IGROUPR0, + vgic_mmio_read_rao, vgic_mmio_write_wi, 4), + REGISTER_DESC_WITH_LENGTH(GICR_ISENABLER0, + vgic_mmio_read_enable, vgic_mmio_write_senable, 4), + REGISTER_DESC_WITH_LENGTH(GICR_ICENABLER0, + vgic_mmio_read_enable, vgic_mmio_write_cenable, 4), + REGISTER_DESC_WITH_LENGTH(GICR_ISPENDR0, + vgic_mmio_read_pending, vgic_mmio_write_spending, 4), + REGISTER_DESC_WITH_LENGTH(GICR_ICPENDR0, + vgic_mmio_read_pending, vgic_mmio_write_cpending, 4), + REGISTER_DESC_WITH_LENGTH(GICR_ISACTIVER0, + vgic_mmio_read_active, vgic_mmio_write_sactive, 4), + REGISTER_DESC_WITH_LENGTH(GICR_ICACTIVER0, + vgic_mmio_read_active, vgic_mmio_write_cactive, 4), + REGISTER_DESC_WITH_LENGTH(GICR_IPRIORITYR0, + vgic_mmio_read_priority, vgic_mmio_write_priority, 32), + REGISTER_DESC_WITH_LENGTH(GICR_ICFGR0, + vgic_mmio_read_config, vgic_mmio_write_config, 8), + REGISTER_DESC_WITH_LENGTH(GICR_IGRPMODR0, + vgic_mmio_read_raz, vgic_mmio_write_wi, 4), + REGISTER_DESC_WITH_LENGTH(GICR_NSACR, + vgic_mmio_read_raz, vgic_mmio_write_wi, 4), +}; + +unsigned int vgic_v3_init_dist_iodev(struct vgic_io_device *dev) +{ + dev->regions = vgic_v3_dist_registers; + dev->nr_regions = ARRAY_SIZE(vgic_v3_dist_registers); + + kvm_iodevice_init(&dev->dev, &kvm_io_gic_ops); + + return SZ_64K; +} + +int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t redist_base_address) +{ + int nr_vcpus = atomic_read(&kvm->online_vcpus); + struct kvm_vcpu *vcpu; + struct vgic_io_device *devices, *device; + int c, ret = 0; + + devices = kmalloc(sizeof(struct vgic_io_device) * nr_vcpus * 2, + GFP_KERNEL); + if (!devices) + return -ENOMEM; + + device = devices; + kvm_for_each_vcpu(c, vcpu, kvm) { + kvm_iodevice_init(&device->dev, &kvm_io_gic_ops); + device->base_addr = redist_base_address; + device->regions = vgic_v3_rdbase_registers; + device->nr_regions = ARRAY_SIZE(vgic_v3_rdbase_registers); + device->redist_vcpu = vcpu; + + mutex_lock(&kvm->slots_lock); + ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, + redist_base_address, + SZ_64K, &device->dev); + mutex_unlock(&kvm->slots_lock); + + if (ret) + break; + + device++; + kvm_iodevice_init(&device->dev, &kvm_io_gic_ops); + device->base_addr = redist_base_address + SZ_64K; + device->regions = vgic_v3_sgibase_registers; + device->nr_regions = ARRAY_SIZE(vgic_v3_sgibase_registers); + device->redist_vcpu = vcpu; + + mutex_lock(&kvm->slots_lock); + ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, + redist_base_address + SZ_64K, + SZ_64K, &device->dev); + mutex_unlock(&kvm->slots_lock); + if (ret) { + kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS, + &devices[c * 2].dev); + break; + } + device++; + redist_base_address += 2 * SZ_64K; + } + + if (ret) { + for (c--; c >= 0; c--) { + kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS, + &devices[c * 2].dev); + kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS, + &devices[c * 2 + 1].dev); + } + kfree(devices); + } else { + kvm->arch.vgic.redist_iodevs = devices; + } + + return ret; +} diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c index 19fed56..d1b88d2 100644 --- a/virt/kvm/arm/vgic/vgic-mmio.c +++ b/virt/kvm/arm/vgic/vgic-mmio.c @@ -502,6 +502,11 @@ int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address, case VGIC_V2: len = vgic_v2_init_dist_iodev(io_device); break; +#ifdef CONFIG_KVM_ARM_VGIC_V3 + case VGIC_V3: + len = vgic_v3_init_dist_iodev(io_device); + break; +#endif default: BUG_ON(1); } diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h index 884eb71..3585ac6 100644 --- a/virt/kvm/arm/vgic/vgic-mmio.h +++ b/virt/kvm/arm/vgic/vgic-mmio.h @@ -123,4 +123,6 @@ void vgic_mmio_write_config(struct kvm_vcpu *vcpu, unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev); +unsigned int vgic_v3_init_dist_iodev(struct vgic_io_device *dev); + #endif diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h index cf62015..39a8a65 100644 --- a/virt/kvm/arm/vgic/vgic.h +++ b/virt/kvm/arm/vgic/vgic.h @@ -40,6 +40,7 @@ void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu); void vgic_v3_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr); void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr); void vgic_v3_set_underflow(struct kvm_vcpu *vcpu); +int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t dist_base_address); #else static inline void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu) { @@ -61,6 +62,12 @@ static inline void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr) static inline void vgic_v3_set_underflow(struct kvm_vcpu *vcpu) { } + +static inline int vgic_register_redist_iodevs(struct kvm *kvm, + gpa_t dist_base_address) +{ + return -ENODEV; +} #endif #endif