[Android-virt] [PATCH 13/15] ARM: KVM: Make VGIC distributor MMIO table relative

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 22/06/12 22:55, Christoffer Dall wrote:
> On Mon, May 14, 2012 at 9:06 AM, Marc Zyngier <marc.zyngier at arm.com> wrote:
>> Change the vgic_ranges table to be relative to a per VM
>> vgic_dist_base. It makes it faster to bail out if the
>> access is out of range, and makes it possible to have multiple
>> VMs using different GIC base addresses.
>>
>> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
>> ---
>>  arch/arm/include/asm/kvm_vgic.h |    2 +
>>  arch/arm/kvm/vgic.c             |   49 +++++++++++++++++++++++---------------
>>  2 files changed, 32 insertions(+), 19 deletions(-)
>>
>> diff --git a/arch/arm/include/asm/kvm_vgic.h b/arch/arm/include/asm/kvm_vgic.h
>> index 354e528..4e7f6c3 100644
>> --- a/arch/arm/include/asm/kvm_vgic.h
>> +++ b/arch/arm/include/asm/kvm_vgic.h
>> @@ -85,6 +85,8 @@ struct vgic_dist {
>>        spinlock_t              lock;
>>
>>        void __iomem            *vctrl_base;
>> +       unsigned long           vgic_dist_base;
>> +       unsigned long           vgic_dist_size;
>>
>>        u32                     enabled;
>>
>> diff --git a/arch/arm/kvm/vgic.c b/arch/arm/kvm/vgic.c
>> index f26b091..1b4f6b7 100644
>> --- a/arch/arm/kvm/vgic.c
>> +++ b/arch/arm/kvm/vgic.c
>> @@ -290,62 +290,62 @@ struct mmio_range {
>>
>>  static const struct mmio_range vgic_ranges[] = {
>>        {                       /* CTRL, TYPER, IIDR */
>> -               .base           = VGIC_DIST_BASE,
>> +               .base           = 0,
> 
> nit: field could be named offset of base_offset instead

OK.

>>                .len            = 12,
>>                .handle_mmio    = handle_mmio_misc,
>>        },
>>        {                       /* IGROUPRn */
>> -               .base           = VGIC_DIST_BASE + 0x80,
>> +               .base           = 0x80,
>>                .len            = VGIC_NR_IRQS / 8,
>>                .handle_mmio    = handle_mmio_group_reg,
>>        },
>>        {                       /* ISENABLERn */
>> -               .base           = VGIC_DIST_BASE + 0x100,
>> +               .base           = 0x100,
>>                .len            = VGIC_NR_IRQS / 8,
>>                .handle_mmio    = handle_mmio_set_enable_reg,
>>        },
>>        {                       /* ICENABLERn */
>> -               .base           = VGIC_DIST_BASE + 0x180,
>> +               .base           = 0x180,
>>                .len            = VGIC_NR_IRQS / 8,
>>                .handle_mmio    = handle_mmio_clear_enable_reg,
>>        },
>>        {                       /* ISPENDRn */
>> -               .base           = VGIC_DIST_BASE + 0x200,
>> +               .base           = 0x200,
>>                .len            = VGIC_NR_IRQS / 8,
>>                .handle_mmio    = handle_mmio_set_pending_reg,
>>        },
>>        {                       /* ICPENDRn */
>> -               .base           = VGIC_DIST_BASE + 0x280,
>> +               .base           = 0x280,
>>                .len            = VGIC_NR_IRQS / 8,
>>                .handle_mmio    = handle_mmio_clear_pending_reg,
>>        },
>>        {                       /* ISACTIVERn */
>> -               .base           = VGIC_DIST_BASE + 0x300,
>> +               .base           = 0x300,
>>                .len            = VGIC_NR_IRQS / 8,
>>                .handle_mmio    = handle_mmio_set_active_reg,
>>        },
>>        {                       /* ICACTIVERn */
>> -               .base           = VGIC_DIST_BASE + 0x380,
>> +               .base           = 0x380,
>>                .len            = VGIC_NR_IRQS / 8,
>>                .handle_mmio    = handle_mmio_clear_active_reg,
>>        },
>>        {                       /* IPRIORITYRn */
>> -               .base           = VGIC_DIST_BASE + 0x400,
>> +               .base           = 0x400,
>>                .len            = VGIC_NR_IRQS,
>>                .handle_mmio    = handle_mmio_priority_reg,
>>        },
>>        {                       /* ITARGETSRn */
>> -               .base           = VGIC_DIST_BASE + 0x800,
>> +               .base           = 0x800,
>>                .len            = VGIC_NR_IRQS,
>>                .handle_mmio    = handle_mmio_target_reg,
>>        },
>>        {                       /* ICFGRn */
>> -               .base           = VGIC_DIST_BASE + 0xC00,
>> +               .base           = 0xC00,
>>                .len            = VGIC_NR_IRQS / 4,
>>                .handle_mmio    = handle_mmio_cfg_reg,
>>        },
>>        {                       /* SGIRn */
>> -               .base           = VGIC_DIST_BASE + 0xF00,
>> +               .base           = 0xF00,
>>                .len            = 4,
>>                .handle_mmio    = handle_mmio_sgi_reg,
>>        },
>> @@ -354,12 +354,14 @@ static const struct mmio_range vgic_ranges[] = {
>>
>>  static const
>>  struct mmio_range *find_matching_range(const struct mmio_range *ranges,
>> -                                      struct kvm_run *run)
>> +                                      struct kvm_run *run, unsigned long base)
>>  {
>>        const struct mmio_range *r = ranges;
>> +       unsigned long addr = run->mmio.phys_addr - base;
>> +
>>        while (r->len) {
>> -               if (run->mmio.phys_addr >= r->base &&
>> -                   (run->mmio.phys_addr + run->mmio.len) <= (r->base + r->len))
>> +               if (addr >= r->base &&
>> +                   (addr + run->mmio.len) <= (r->base + r->len))
>>                        return r;
>>                r++;
>>        }
>> @@ -370,18 +372,25 @@ struct mmio_range *find_matching_range(const struct mmio_range *ranges,
>>  int vgic_handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run *run)
>>  {
>>        const struct mmio_range *range;
>> +       struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
>> +       unsigned long base = dist->vgic_dist_base;
>>
>> -       if (!irqchip_in_kernel(vcpu->kvm))
>> +       if (!irqchip_in_kernel(vcpu->kvm) ||
>> +           run->mmio.phys_addr < base ||
>> +           (run->mmio.phys_addr + run->mmio.len) > (base + dist->vgic_dist_size))
> 
> the last line is unsafe in the very unlikely case that
> run->mmio.phys_addr + run->mmio.len overflows right?
> 
> but then again, it will be caught underneath from the missing range,
> so it's an optimization check.
> 
>>                return KVM_EXIT_MMIO;
>>
>> -       range = find_matching_range(vgic_ranges, run);
>> -       if (!range || !range->handle_mmio)
>> +       range = find_matching_range(vgic_ranges, run, base);
>> +       if (unlikely(!range || !range->handle_mmio)) {
>> +               pr_warn("Unhandled access %d %08llx %d\n",
>> +                       run->mmio.is_write, run->mmio.phys_addr, run->mmio.len);
> 
> add a kvm_warn to include/linux/kvm_host.h and call kvm_warn
> 
> it's not apparent that this comes from KVM by looking at the error message.

I was planning to remove that warning anyway. If you have a sparse IO
range and the access is in a hole, it is probably better to let it go
through the emulation code and probably die.

>>                return KVM_EXIT_MMIO;
>> +       }
>>
>>        spin_lock(&vcpu->kvm->arch.vgic.lock);
>>        pr_debug("emulating %d %08llx %d\n", run->mmio.is_write,
>>                 run->mmio.phys_addr, run->mmio.len);
>> -       range->handle_mmio(vcpu, run, run->mmio.phys_addr - range->base);
>> +       range->handle_mmio(vcpu, run, run->mmio.phys_addr - range->base - base);
> 
> nit: I prefer - (range->base + base) to not force people to think
> about the associativity

OK.

>>        kvm_handle_mmio_return(vcpu, run);
>>        spin_unlock(&vcpu->kvm->arch.vgic.lock);
>>
>> @@ -857,6 +866,8 @@ int kvm_vgic_init(struct kvm *kvm)
>>
>>        spin_lock_init(&kvm->arch.vgic.lock);
>>        kvm->arch.vgic.vctrl_base = vgic_vctrl_base;
>> +       kvm->arch.vgic.vgic_dist_base = VGIC_DIST_BASE;
>> +       kvm->arch.vgic.vgic_dist_size = VGIC_DIST_SIZE;
>>
>>        ret = kvm_phys_addr_ioremap(kvm, VGIC_CPU_BASE,
>>                                    vcpu_res.start, VGIC_CPU_SIZE);
>> --
>> 1.7.7.1
>>
> 
> Looks good (you could merge this down before releasing a new version
> of the patches).

That's the intention.

	M.
-- 
Jazz is not dead. It just smells funny...




[Index of Archives]     [Linux KVM]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux