[PATCH v4 18/19] arm/arm64: KVM: enable kernel side of GICv3 emulation
Christoffer Dall
christoffer.dall at linaro.org
Mon Nov 24 01:09:27 PST 2014
On Fri, Nov 14, 2014 at 10:08:02AM +0000, Andre Przywara wrote:
> With all the necessary GICv3 emulation code in place, we can now
> connect the code to the GICv3 backend in the kernel.
> The LR register handling is different depending on the emulated GIC
> model, so provide different implementations for each.
> Also allow non-v2-compatible GICv3 implementations (which don't
> provide MMIO regions for the virtual CPU interface in the DT), but
> restrict those hosts to support GICv3 guests only.
>
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
> Changelog v3...v4:
> - handle differences between GICv2-on-v3 and GICv3-on-v3 in existing functions
> - remove init_*_emul() functions
> - remove max_vcpus setting (done in earlier patches now)
> - adapt to new vgic_v<n>_init_emulation behaviour
>
> virt/kvm/arm/vgic-v3.c | 83 ++++++++++++++++++++++++++++++++----------------
> virt/kvm/arm/vgic.c | 5 +++
> 2 files changed, 60 insertions(+), 28 deletions(-)
>
> diff --git a/virt/kvm/arm/vgic-v3.c b/virt/kvm/arm/vgic-v3.c
> index a04d208..4894c59 100644
> --- a/virt/kvm/arm/vgic-v3.c
> +++ b/virt/kvm/arm/vgic-v3.c
> @@ -34,6 +34,7 @@
> #define GICH_LR_VIRTUALID (0x3ffUL << 0)
> #define GICH_LR_PHYSID_CPUID_SHIFT (10)
> #define GICH_LR_PHYSID_CPUID (7UL << GICH_LR_PHYSID_CPUID_SHIFT)
> +#define ICH_LR_VIRTUALID_MASK (BIT_ULL(32) - 1)
>
> /*
> * LRs are stored in reverse order in memory. make sure we index them
> @@ -48,12 +49,17 @@ static struct vgic_lr vgic_v3_get_lr(const struct kvm_vcpu *vcpu, int lr)
> struct vgic_lr lr_desc;
> u64 val = vcpu->arch.vgic_cpu.vgic_v3.vgic_lr[LR_INDEX(lr)];
>
> - lr_desc.irq = val & GICH_LR_VIRTUALID;
> - if (lr_desc.irq <= 15)
> - lr_desc.source = (val >> GICH_LR_PHYSID_CPUID_SHIFT) & 0x7;
> + if (vcpu->kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3)
> + lr_desc.irq = val & ICH_LR_VIRTUALID_MASK;
> else
> - lr_desc.source = 0;
> - lr_desc.state = 0;
> + lr_desc.irq = val & GICH_LR_VIRTUALID;
> +
> + lr_desc.source = 0;
> + if (lr_desc.irq <= 15 &&
> + vcpu->kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V2)
> + lr_desc.source = (val >> GICH_LR_PHYSID_CPUID_SHIFT) & 0x7;
> +
> + lr_desc.state = 0;
super-nit-only-if-you-respin: you have a couple of tabs and extra spaces
in the two lines above that need to just be a single space before the
assignment operator on each line.
>
> if (val & ICH_LR_PENDING_BIT)
> lr_desc.state |= LR_STATE_PENDING;
> @@ -68,8 +74,20 @@ static struct vgic_lr vgic_v3_get_lr(const struct kvm_vcpu *vcpu, int lr)
> static void vgic_v3_set_lr(struct kvm_vcpu *vcpu, int lr,
> struct vgic_lr lr_desc)
> {
> - u64 lr_val = (((u32)lr_desc.source << GICH_LR_PHYSID_CPUID_SHIFT) |
> - lr_desc.irq);
> + u64 lr_val;
> +
> + lr_val = lr_desc.irq;
> +
> + /*
> + * currently all guest IRQs are Group1, as Group0 would result
I guess you couldn't guess my comment, from last time, can you please
begin sentences with upper-case? (only if you re-spin).
> + * in a FIQ in the guest, which it wouldn't expect.
> + * Eventually we want to make this configurable, so we may revisit
> + * this in the future.
> + */
> + if (vcpu->kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3)
> + lr_val |= ICH_LR_GROUP;
> + else
> + lr_val |= (u32)lr_desc.source << GICH_LR_PHYSID_CPUID_SHIFT;
>
> if (lr_desc.state & LR_STATE_PENDING)
> lr_val |= ICH_LR_PENDING_BIT;
> @@ -154,7 +172,14 @@ static void vgic_v3_enable(struct kvm_vcpu *vcpu)
> */
> vgic_v3->vgic_vmcr = 0;
>
> - vgic_v3->vgic_sre = 0;
> + /*
> + * Set the SRE_EL1 value depending on the configured
> + * emulated vGIC model.
> + */
> + if (vcpu->kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3)
> + vgic_v3->vgic_sre = ICC_SRE_EL1_SRE;
I think we left some of my questions from last round unanswered here
(you said you needed to go and think about it). If the guest sets SRE=0
we will not currently preserve this value I think.
The comment should clearly indicate that we're choosing a reset value
of the register for our implementation of the gic.
I'm fine with this change, but would like to know what the rationale
behind it is; wouldn't guests always initialize this value?
> + else
> + vgic_v3->vgic_sre = 0;
>
> /* Get the show on the road... */
> vgic_v3->vgic_hcr = ICH_HCR_EN;
> @@ -215,28 +240,30 @@ int vgic_v3_probe(struct device_node *vgic_node,
>
> gicv_idx += 3; /* Also skip GICD, GICC, GICH */
> if (of_address_to_resource(vgic_node, gicv_idx, &vcpu_res)) {
> - kvm_err("Cannot obtain GICV region\n");
> - ret = -ENXIO;
> - goto out;
> - }
> -
> - if (!PAGE_ALIGNED(vcpu_res.start)) {
> - kvm_err("GICV physical address 0x%llx not page aligned\n",
> - (unsigned long long)vcpu_res.start);
> - ret = -ENXIO;
> - goto out;
> - }
> -
> - if (!PAGE_ALIGNED(resource_size(&vcpu_res))) {
> - kvm_err("GICV size 0x%llx not a multiple of page size 0x%lx\n",
> - (unsigned long long)resource_size(&vcpu_res),
> - PAGE_SIZE);
> - ret = -ENXIO;
> - goto out;
> + kvm_info("GICv3: GICv2 emulation not available\n");
> + vgic->vcpu_base = 0;
> + } else {
> + if (!PAGE_ALIGNED(vcpu_res.start)) {
> + kvm_err("GICV physical address 0x%llx not page aligned\n",
> + (unsigned long long)vcpu_res.start);
> + ret = -ENXIO;
> + goto out;
shouldn't we be allowing an emulated gicv3 using the system registers in
this case then?
> + }
> +
> + if (!PAGE_ALIGNED(resource_size(&vcpu_res))) {
> + kvm_err("GICV size 0x%llx not a multiple of page size 0x%lx\n",
> + (unsigned long long)resource_size(&vcpu_res),
> + PAGE_SIZE);
> + ret = -ENXIO;
> + goto out;
ditto?
> + }
> +
> + vgic->vcpu_base = vcpu_res.start;
> + kvm_register_device_ops(&kvm_arm_vgic_v2_ops,
> + KVM_DEV_TYPE_ARM_VGIC_V2);
> }
> - kvm_register_device_ops(&kvm_arm_vgic_v2_ops, KVM_DEV_TYPE_ARM_VGIC_V2);
> + kvm_register_device_ops(&kvm_arm_vgic_v3_ops, KVM_DEV_TYPE_ARM_VGIC_V3);
>
> - vgic->vcpu_base = vcpu_res.start;
> vgic->vctrl_base = NULL;
> vgic->type = VGIC_V3;
> vgic->max_hw_vcpus = KVM_MAX_VCPUS;
> diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
> index b7de0f8..1dbaeb5 100644
> --- a/virt/kvm/arm/vgic.c
> +++ b/virt/kvm/arm/vgic.c
> @@ -1577,6 +1577,11 @@ static int init_vgic_model(struct kvm *kvm, int type)
> case KVM_DEV_TYPE_ARM_VGIC_V2:
> ret = vgic_v2_init_emulation(kvm);
> break;
> +#ifdef CONFIG_ARM_GIC_V3
> + case KVM_DEV_TYPE_ARM_VGIC_V3:
> + ret = vgic_v3_init_emulation(kvm);
> + break;
> +#endif
> default:
> ret = -ENODEV;
> break;
> --
> 1.7.9.5
>
Thanks,
-Christoffer
More information about the linux-arm-kernel
mailing list