From: eric.auger@redhat.com (Auger Eric)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH] KVM: arm64: ITS: move ITS registration into first VCPU run
Date: Wed, 3 Aug 2016 19:56:38 +0200 [thread overview]
Message-ID: <05b33a03-8bcd-4fde-c81b-6af02b66e365@redhat.com> (raw)
In-Reply-To: <e508c027-229d-5c3b-cc45-dc27953b8526@redhat.com>
Hi
On 03/08/2016 19:48, Auger Eric wrote:
> Hi Andre, Christoffer,
>
> On 03/08/2016 19:18, Andre Przywara wrote:
>> Hi,
>>
>> On 03/08/16 18:11, Christoffer Dall wrote:
>>> On Wed, Aug 03, 2016 at 03:57:45PM +0100, Andre Przywara wrote:
>>>> Currently we register ITS devices upon userland issuing the CTRL_INIT
>>>> ioctl to mark initialization of the ITS as done.
>>>> This deviates from the initialization sequence of the existing GIC
>>>> devices and does not play well with the way QEMU handles things.
>>>> To be more in line with what we are used to, register the ITS(es) just
>>>> before the first VCPU is about to run, so in the map_resources() call.
>>>> This involves iterating through the list of KVM devices and handle each
>>>> ITS that we find.
>>>>
>>>> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
>>>> ---
>>>> Hi,
>>>>
>>>> this is based upon next-20160728 plus Christoffer's kvm_device locking
>>>> fix from today. Please let me know what tree I should base upon and I
>>>> will rebase.
>>>> Eric, Christoffer: does that do what you expect? Can QEMU live with that?
>>>>
>>>> Cheers,
>>>> Andre.
>>>>
>>>> virt/kvm/arm/vgic/vgic-its.c | 56 ++++++++++++++++++++++++++++++++++++--------
>>>> virt/kvm/arm/vgic/vgic-v3.c | 6 +++++
>>>> virt/kvm/arm/vgic/vgic.h | 6 +++++
>>>> 3 files changed, 58 insertions(+), 10 deletions(-)
>>>>
>>>> diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
>>>> index 07411cf..e677a60 100644
>>>> --- a/virt/kvm/arm/vgic/vgic-its.c
>>>> +++ b/virt/kvm/arm/vgic/vgic-its.c
>>>> @@ -1288,13 +1288,13 @@ void vgic_enable_lpis(struct kvm_vcpu *vcpu)
>>>> its_sync_lpi_pending_table(vcpu);
>>>> }
>>>>
>>>> -static int vgic_its_init_its(struct kvm *kvm, struct vgic_its *its)
>>>> +static int vgic_register_its_iodev(struct kvm *kvm, struct vgic_its *its)
>>>> {
>>>> struct vgic_io_device *iodev = &its->iodev;
>>>> int ret;
>>>>
>>>> - if (its->initialized)
>>>> - return 0;
>>>> + if (!its->initialized)
>>>> + return -EBUSY;
>>>>
>>>> if (IS_VGIC_ADDR_UNDEF(its->vgic_its_base))
>>>> return -ENXIO;
>>>> @@ -1311,9 +1311,6 @@ static int vgic_its_init_its(struct kvm *kvm, struct vgic_its *its)
>>>> KVM_VGIC_V3_ITS_SIZE, &iodev->dev);
>>>> mutex_unlock(&kvm->slots_lock);
>>>>
>>>> - if (!ret)
>>>> - its->initialized = true;
>>>> -
>>>> return ret;
>>>> }
>>>>
>>>> @@ -1435,9 +1432,6 @@ static int vgic_its_set_attr(struct kvm_device *dev,
>>>> if (type != KVM_VGIC_ITS_ADDR_TYPE)
>>>> return -ENODEV;
>>>>
>>>> - if (its->initialized)
>>>> - return -EBUSY;
>>>> -
>>>> if (copy_from_user(&addr, uaddr, sizeof(addr)))
>>>> return -EFAULT;
>>>>
>>>> @@ -1453,7 +1447,9 @@ static int vgic_its_set_attr(struct kvm_device *dev,
>>>> case KVM_DEV_ARM_VGIC_GRP_CTRL:
>>>> switch (attr->attr) {
>>>> case KVM_DEV_ARM_VGIC_CTRL_INIT:
>>>> - return vgic_its_init_its(dev->kvm, its);
>>>> + its->initialized = true;
>>>> +
>>>> + return 0;
>>>> }
>>>> break;
>>>> }
>>>> @@ -1498,3 +1494,43 @@ int kvm_vgic_register_its_device(void)
>>>> return kvm_register_device_ops(&kvm_arm_vgic_its_ops,
>>>> KVM_DEV_TYPE_ARM_VGIC_ITS);
>>>> }
>>>> +
>>>> +/*
>>>> + * Registers all ITSes with the kvm_io_bus framework.
>>>> + * To follow the existing VGIC initialization sequence, this has to be
>>>> + * done as late as possible, just before the first VCPU runs.
>>>> + */
>>>> +int vgic_register_its_iodevs(struct kvm *kvm)
>>>> +{
>>>> + struct kvm_device *dev;
>>>> + int ret = 0;
>>>> +
>>>> + mutex_lock(&kvm->devices_lock);
>>>> +
>>>> + list_for_each_entry(dev, &kvm->devices, vm_node) {
>>>> + if (dev->ops != &kvm_arm_vgic_its_ops)
>>>> + continue;
>>>> +
>>>> + ret = vgic_register_its_iodev(kvm, dev->private);
>>>> + if (ret)
>>>> + break;
>>>> + }
>>>> +
>>>> + if (ret) {
>>>> + /* Iterate backwards to roll back previous registrations. */
>>>> + for (dev = list_prev_entry(dev, vm_node);
>>>> + &dev->vm_node != &kvm->devices;
>>>> + dev = list_prev_entry(dev, vm_node)) {
>>>> + struct vgic_its *its = dev->private;
>>>> +
>>>> + if (dev->ops != &kvm_arm_vgic_its_ops)
>>>> + continue;
>>>> +
>>>> + kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS,
>>>> + &its->iodev.dev);
>>>> + }
>>>> + }
>>>
>>> is the unregister really necessary?
>>
>> I was wondering the same, but we do it for the GICv3 redistributors as
>> well (though that was introduced by the same stupid author).
>> That being said I would be too happy to remove both these dodgy routines
>> if we agree that a failure will ultimately lead to a VM teardown and is
>> thus not needed.
>
> Well to me this will lead to a kvm_vcpu_ioctl/KVM_RUN failure. Then the
> unregistration only happens in kvm_destroy_vm/kvm_io_bus_destroy and
> this calls iodevice destructor ops which is not implemented for our
> device so I don't think this can be removed right now.
hum no I mixed things I think: The destructor is needed if we want to
remove our io-dev explicit deallocation in vgic and vits. Anyway this
could be more elegant than what we have now. I can take this in charge
if confirmed.
sorry for the noise
Eric
>
> We shall implement this destructor ops first. In the past I attempted to
> use the destructor (early ages of new vgic) but this crashed. I think
> this crash should not happen anymore after:
> e6e3b5a64e5f15ebd569118a9af16bd4165cbd1a
>
> I tested the new version with a qemu integration looking similar to
> other vgic init:
>
> Tested-by: Eric Auger <eric.auger@redhat.com>
>
> Cheers
>
> Eric
>
>
>>
>> Cheers,
>> Andre.
>>
>>>
>>>> +
>>>> + mutex_unlock(&kvm->devices_lock);
>>>> + return ret;
>>>> +}
>>>> diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
>>>> index 0506543..f0d9b2b 100644
>>>> --- a/virt/kvm/arm/vgic/vgic-v3.c
>>>> +++ b/virt/kvm/arm/vgic/vgic-v3.c
>>>> @@ -289,6 +289,12 @@ int vgic_v3_map_resources(struct kvm *kvm)
>>>> goto out;
>>>> }
>>>>
>>>> + ret = vgic_register_its_iodevs(kvm);
>>>> + if (ret) {
>>>> + kvm_err("Unable to register VGIC ITS MMIO regions\n");
>>>> + goto out;
>>>> + }
>>>> +
>>>> dist->ready = true;
>>>>
>>>> out:
>>>> diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
>>>> index 1d8e21d..6c4625c 100644
>>>> --- a/virt/kvm/arm/vgic/vgic.h
>>>> +++ b/virt/kvm/arm/vgic/vgic.h
>>>> @@ -84,6 +84,7 @@ void vgic_v3_enable(struct kvm_vcpu *vcpu);
>>>> int vgic_v3_probe(const struct gic_kvm_info *info);
>>>> int vgic_v3_map_resources(struct kvm *kvm);
>>>> int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t dist_base_address);
>>>> +int vgic_register_its_iodevs(struct kvm *kvm);
>>>> bool vgic_has_its(struct kvm *kvm);
>>>> int kvm_vgic_register_its_device(void);
>>>> void vgic_enable_lpis(struct kvm_vcpu *vcpu);
>>>> @@ -140,6 +141,11 @@ static inline int vgic_register_redist_iodevs(struct kvm *kvm,
>>>> return -ENODEV;
>>>> }
>>>>
>>>> +static inline int vgic_register_its_iodevs(struct kvm *kvm)
>>>> +{
>>>> + return -ENODEV;
>>>> +}
>>>> +
>>>> static inline bool vgic_has_its(struct kvm *kvm)
>>>> {
>>>> return false;
>>>> --
>>>> 2.9.0
>>>>
>>>
>>> Otherwise this looks good to me.
>>>
>>> Can someone provide a tested-by ?
>>>
>>> Thanks,
>>> -Christoffer
>>>
>>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel at lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>>
next prev parent reply other threads:[~2016-08-03 17:56 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-08-03 14:57 [PATCH] KVM: arm64: ITS: move ITS registration into first VCPU run Andre Przywara
2016-08-03 17:11 ` Christoffer Dall
2016-08-03 17:18 ` Andre Przywara
2016-08-03 17:48 ` Auger Eric
2016-08-03 17:56 ` Auger Eric [this message]
2016-08-03 18:11 ` Auger Eric
2016-08-03 17:56 ` Christoffer Dall
2016-08-03 17:48 ` Christoffer Dall
2016-08-03 17:13 ` Christoffer Dall
2016-08-03 18:15 ` kbuild test robot
2016-08-04 10:11 ` Auger Eric
2016-08-04 10:17 ` Andre Przywara
2016-08-04 10:26 ` Auger Eric
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=05b33a03-8bcd-4fde-c81b-6af02b66e365@redhat.com \
--to=eric.auger@redhat.com \
--cc=linux-arm-kernel@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox