public inbox for kvm@vger.kernel.org
 help / color / mirror / Atom feed
From: Marc Zyngier <maz@kernel.org>
To: Peter Xu <peterx@redhat.com>
Cc: Zenghui Yu <yuzenghui@huawei.com>,
	kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu,
	pbonzini@redhat.com
Subject: Re: BUG: using __this_cpu_read() in preemptible [00000000] code
Date: Fri, 07 Feb 2020 16:25:37 +0000	[thread overview]
Message-ID: <5a132e2ca9918b1b2c3d2f146ab44311@kernel.org> (raw)
In-Reply-To: <20200207161845.GB707371@xz-x1>

On 2020-02-07 16:18, Peter Xu wrote:
> On Fri, Feb 07, 2020 at 10:25:23AM +0000, Marc Zyngier wrote:
>> On 2020-02-07 10:19, Zenghui Yu wrote:
>> > Hi Marc,
>> >
>> > On 2020/2/7 17:19, Marc Zyngier wrote:
>> > > Hi Zenghui,
>> > >
>> > > On 2020-02-07 09:00, Zenghui Yu wrote:
>> > > > Hi,
>> > > >
>> > > > Running a latest preemptible kernel and some guests on it,
>> > > > I got the following message,
>> > > >
>> > > > ---8<---
>> > > >
>> > > > [  630.031870] BUG: using __this_cpu_read() in preemptible [00000000]
>> > > > code: qemu-system-aar/37270
>> > > > [  630.031872] caller is kvm_get_running_vcpu+0x1c/0x38
>> > > > [  630.031874] CPU: 32 PID: 37270 Comm: qemu-system-aar Kdump: loaded
>> > > > Not tainted 5.5.0+
>> > > > [  630.031876] Hardware name: Huawei TaiShan 2280 /BC11SPCD,
>> > > > BIOS 1.58
>> > > > 10/29/2018
>> > > > [  630.031876] Call trace:
>> > > > [  630.031878]  dump_backtrace+0x0/0x200
>> > > > [  630.031880]  show_stack+0x24/0x30
>> > > > [  630.031882]  dump_stack+0xb0/0xf4
>> > > > [  630.031884]  __this_cpu_preempt_check+0xc8/0xd0
>> > > > [  630.031886]  kvm_get_running_vcpu+0x1c/0x38
>> > > > [  630.031888]  vgic_mmio_change_active.isra.4+0x2c/0xe0
>> > > > [  630.031890]  __vgic_mmio_write_cactive+0x80/0xc8
>> > > > [  630.031892]  vgic_mmio_uaccess_write_cactive+0x3c/0x50
>> > > > [  630.031894]  vgic_uaccess+0xcc/0x138
>> > > > [  630.031896]  vgic_v3_redist_uaccess+0x7c/0xa8
>> > > > [  630.031898]  vgic_v3_attr_regs_access+0x1a8/0x230
>> > > > [  630.031901]  vgic_v3_set_attr+0x1b4/0x290
>> > > > [  630.031903]  kvm_device_ioctl_attr+0xbc/0x110
>> > > > [  630.031905]  kvm_device_ioctl+0xc4/0x108
>> > > > [  630.031907]  ksys_ioctl+0xb4/0xd0
>> > > > [  630.031909]  __arm64_sys_ioctl+0x28/0x38
>> > > > [  630.031911]  el0_svc_common.constprop.1+0x7c/0x1a0
>> > > > [  630.031913]  do_el0_svc+0x34/0xa0
>> > > > [  630.031915]  el0_sync_handler+0x124/0x274
>> > > > [  630.031916]  el0_sync+0x140/0x180
>> > > >
>> > > > ---8<---
>> > > >
>> > > > I'm now at commit 90568ecf561540fa330511e21fcd823b0c3829c6.
>> > > >
>> > > > And it looks like vgic_get_mmio_requester_vcpu() was broken by
>> > > > 7495e22bb165 ("KVM: Move running VCPU from ARM to common code").
>> > > >
>> > > > Could anyone please have a look?
>> > >
>> > > Here you go:
>> > >
>> > > diff --git a/virt/kvm/arm/vgic/vgic-mmio.c
>> > > b/virt/kvm/arm/vgic/vgic-mmio.c
>> > > index d656ebd5f9d4..e1735f19c924 100644
>> > > --- a/virt/kvm/arm/vgic/vgic-mmio.c
>> > > +++ b/virt/kvm/arm/vgic/vgic-mmio.c
>> > > @@ -190,6 +190,15 @@ unsigned long vgic_mmio_read_pending(struct
>> > > kvm_vcpu *vcpu,
>> > >    * value later will give us the same value as we update the
>> > > per-CPU variable
>> > >    * in the preempt notifier handlers.
>> > >    */
>> > > +static struct kvm_vcpu *vgic_get_mmio_requester_vcpu(void)
>> > > +{
>> > > +    struct kvm_vcpu *vcpu;
>> > > +
>> > > +    preempt_disable();
>> > > +    vcpu = kvm_get_running_vcpu();
>> > > +    preempt_enable();
>> > > +    return vcpu;
>> > > +}
>> > >
>> > >   /* Must be called with irq->irq_lock held */
>> > >   static void vgic_hw_irq_spending(struct kvm_vcpu *vcpu, struct
>> > > vgic_irq *irq,
>> > > @@ -212,7 +221,7 @@ void vgic_mmio_write_spending(struct kvm_vcpu
>> > > *vcpu,
>> > >                     gpa_t addr, unsigned int len,
>> > >                     unsigned long val)
>> > >   {
>> > > -    bool is_uaccess = !kvm_get_running_vcpu();
>> > > +    bool is_uaccess = !vgic_get_mmio_requester_vcpu();
>> > >       u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
>> > >       int i;
>> > >       unsigned long flags;
>> > > @@ -265,7 +274,7 @@ void vgic_mmio_write_cpending(struct kvm_vcpu
>> > > *vcpu,
>> > >                     gpa_t addr, unsigned int len,
>> > >                     unsigned long val)
>> > >   {
>> > > -    bool is_uaccess = !kvm_get_running_vcpu();
>> > > +    bool is_uaccess = !vgic_get_mmio_requester_vcpu();
>> > >       u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
>> > >       int i;
>> > >       unsigned long flags;
>> > > @@ -326,7 +335,7 @@ static void vgic_mmio_change_active(struct
>> > > kvm_vcpu *vcpu, struct vgic_irq *irq,
>> > >                       bool active)
>> > >   {
>> > >       unsigned long flags;
>> > > -    struct kvm_vcpu *requester_vcpu = kvm_get_running_vcpu();
>> > > +    struct kvm_vcpu *requester_vcpu = vgic_get_mmio_requester_vcpu();
>> > >
>> > >       raw_spin_lock_irqsave(&irq->irq_lock, flags);
>> > >
>> > >
>> > > That's basically a revert of the offending code. The comment right
>> > > above
>> > > vgic_get_mmio_requester_vcpu() explains *why* this is valid, and why
>> > > preempt_disable() is needed.
> 
> Sorry for not noticing this before.
> 
>> >
>> > I see, thanks!
>> >
>> > >
>> > > Can you please give it a shot?
>> >
>> > Yes, it works for me:
>> >
>> > Tested-by: Zenghui Yu <yuzenghui@huawei.com>
>> 
>> Actually, maybe a better/simpler fix would be this:
>> 
>> diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
>> index 67ae2d5c37b2..3cf7719d3177 100644
>> --- a/virt/kvm/kvm_main.c
>> +++ b/virt/kvm/kvm_main.c
>> @@ -4414,7 +4414,13 @@ static void kvm_sched_out(struct 
>> preempt_notifier
>> *pn,
>>   */
>>  struct kvm_vcpu *kvm_get_running_vcpu(void)
>>  {
>> -        return __this_cpu_read(kvm_running_vcpu);
>> +	struct kvm_vcpu *vcpu;
>> +
>> +	preempt_disable();
>> +	vcpu = __this_cpu_read(kvm_running_vcpu);
>> +	preempt_enable();
>> +
>> +	return vcpu;
>>  }
>> 
>>  /**
>> 
>> which matches the comment that comes with the function.
>> 
>> Paolo, which one do you prefer? It seems to me that the intent of 
>> moving
>> this to core code was to provide a high level API that works at all 
>> times.
> 
> Not sure about Paolo, but this looks better at least to me.  Shall we
> also move the comment from vgic-mmio.c to here?  And we can remove the
> 1st paragraph:
> 
> /*
>  * We can disable preemption locally around accessing the per-CPU 
> variable,
>  * and use the resolved vcpu pointer after enabling preemption again, 
> because
>  * even if the current thread is migrated to another CPU, reading the 
> per-CPU
>  * value later will give us the same value as we update the per-CPU 
> variable
>  * in the preempt notifier handlers.
>  */

Sure. I'll add it and post an actual patch in a moment.

Thanks,

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

      reply	other threads:[~2020-02-07 16:25 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-02-07  9:00 BUG: using __this_cpu_read() in preemptible [00000000] code Zenghui Yu
2020-02-07  9:19 ` Marc Zyngier
2020-02-07 10:19   ` Zenghui Yu
2020-02-07 10:25     ` Marc Zyngier
2020-02-07 16:18       ` Peter Xu
2020-02-07 16:25         ` Marc Zyngier [this message]

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=5a132e2ca9918b1b2c3d2f146ab44311@kernel.org \
    --to=maz@kernel.org \
    --cc=kvm@vger.kernel.org \
    --cc=kvmarm@lists.cs.columbia.edu \
    --cc=pbonzini@redhat.com \
    --cc=peterx@redhat.com \
    --cc=yuzenghui@huawei.com \
    /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