Register a device for the virtual interface control block(GICH) access from the guest hypervisor. TODO: Get GICH address from DT, which is hardcoded now. Signed-off-by: Jintack Lim <jintack@xxxxxxxxxxxxxxx> --- arch/arm64/include/uapi/asm/kvm.h | 6 ++++++ include/kvm/arm_vgic.h | 5 ++++- virt/kvm/arm/vgic/vgic-mmio.c | 6 ++++++ virt/kvm/arm/vgic/vgic-v2-nested.c | 24 ++++++++++++++++++++++++ virt/kvm/arm/vgic/vgic-v2.c | 7 +++++++ virt/kvm/arm/vgic/vgic.h | 6 ++++++ 6 files changed, 53 insertions(+), 1 deletion(-) diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h index 78117bf..3995d3d 100644 --- a/arch/arm64/include/uapi/asm/kvm.h +++ b/arch/arm64/include/uapi/asm/kvm.h @@ -99,6 +99,12 @@ struct kvm_regs { #define KVM_ARM_VCPU_PMU_V3 3 /* Support guest PMUv3 */ #define KVM_ARM_VCPU_NESTED_VIRT 4 /* Support nested virtual EL2 */ +/* FIXME: This should come from DT */ +#ifdef CONFIG_KVM_ARM_NESTED_HYP +#define KVM_VGIC_V2_GICH_BASE 0x08030000 +#define KVM_VGIC_V2_GICH_SIZE 0x2000 +#endif + struct kvm_vcpu_init { __u32 target; __u32 features[7]; diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h index fc882d6..5bda20c 100644 --- a/include/kvm/arm_vgic.h +++ b/include/kvm/arm_vgic.h @@ -125,7 +125,8 @@ enum iodev_type { IODEV_CPUIF, IODEV_DIST, IODEV_REDIST, - IODEV_ITS + IODEV_ITS, + IODEV_GICH, }; struct vgic_io_device { @@ -198,6 +199,8 @@ struct vgic_dist { struct vgic_io_device dist_iodev; + struct vgic_io_device hyp_iodev; + bool has_its; /* diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c index 049c570..2e4097d 100644 --- a/virt/kvm/arm/vgic/vgic-mmio.c +++ b/virt/kvm/arm/vgic/vgic-mmio.c @@ -512,6 +512,9 @@ static int dispatch_mmio_read(struct kvm_vcpu *vcpu, struct kvm_io_device *dev, case IODEV_ITS: data = region->its_read(vcpu->kvm, iodev->its, addr, len); break; + case IODEV_GICH: + data = region->read(vcpu, addr, len); + break; } vgic_data_host_to_mmio_bus(val, len, data); @@ -543,6 +546,9 @@ static int dispatch_mmio_write(struct kvm_vcpu *vcpu, struct kvm_io_device *dev, case IODEV_ITS: region->its_write(vcpu->kvm, iodev->its, addr, len, data); break; + case IODEV_GICH: + region->write(vcpu, addr, len, data); + break; } return 0; diff --git a/virt/kvm/arm/vgic/vgic-v2-nested.c b/virt/kvm/arm/vgic/vgic-v2-nested.c index 85f646b..cb55324 100644 --- a/virt/kvm/arm/vgic/vgic-v2-nested.c +++ b/virt/kvm/arm/vgic/vgic-v2-nested.c @@ -206,6 +206,30 @@ static void vgic_mmio_write_v2_gich(struct kvm_vcpu *vcpu, 4 * VGIC_V2_MAX_LRS, VGIC_ACCESS_32bit), }; +int vgic_register_gich_iodev(struct kvm *kvm, struct vgic_dist *dist) +{ + struct vgic_io_device *io_device = &kvm->arch.vgic.hyp_iodev; + int ret = 0; + unsigned int len; + + len = KVM_VGIC_V2_GICH_SIZE; + + io_device->regions = vgic_v2_gich_registers; + io_device->nr_regions = ARRAY_SIZE(vgic_v2_gich_registers); + kvm_iodevice_init(&io_device->dev, &kvm_io_gic_ops); + + io_device->base_addr = KVM_VGIC_V2_GICH_BASE; + io_device->iodev_type = IODEV_GICH; + io_device->redist_vcpu = NULL; + + mutex_lock(&kvm->slots_lock); + ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, KVM_VGIC_V2_GICH_BASE, + len, &io_device->dev); + mutex_unlock(&kvm->slots_lock); + + return ret; +} + /* * For LRs which have HW bit set such as timer interrupts, we modify them to * have the host hardware interrupt number instead of the virtual one programmed diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c index 9bab867..b8b73fd 100644 --- a/virt/kvm/arm/vgic/vgic-v2.c +++ b/virt/kvm/arm/vgic/vgic-v2.c @@ -280,6 +280,13 @@ int vgic_v2_map_resources(struct kvm *kvm) goto out; } + /* Register virtual GICH interface to kvm io bus */ + ret = vgic_register_gich_iodev(kvm, dist); + if (ret) { + kvm_err("Unable to register VGIC GICH regions\n"); + goto out; + } + if (!static_branch_unlikely(&vgic_v2_cpuif_trap)) { ret = kvm_phys_addr_ioremap(kvm, dist->vgic_cpu_base, kvm_vgic_global_state.vcpu_base, diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h index 2aef680..11d61a7 100644 --- a/virt/kvm/arm/vgic/vgic.h +++ b/virt/kvm/arm/vgic/vgic.h @@ -121,8 +121,14 @@ static inline int vgic_its_inject_msi(struct kvm *kvm, struct kvm_msi *msi) int vgic_init(struct kvm *kvm); #ifdef CONFIG_KVM_ARM_NESTED_HYP +int vgic_register_gich_iodev(struct kvm *kvm, struct vgic_dist *dist); void vgic_init_nested(struct kvm_vcpu *vcpu); #else +static inline int vgic_register_gich_iodev(struct kvm *kvm, + struct vgic_dist *dist) +{ + return 0; +} static inline void vgic_init_nested(struct kvm_vcpu *vcpu) { struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu; -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html