All of lore.kernel.org
 help / color / mirror / Atom feed
From: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
To: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Cc: Ian Jackson <Ian.Jackson@eu.citrix.com>,
	"xen-devel@lists.xen.org" <xen-devel@lists.xen.org>
Subject: Re: [PATCH 3/3] piix4acpi, xen, hotplug: Fix race with ACPI AML code and hotplug.
Date: Mon, 13 May 2013 14:20:00 -0400	[thread overview]
Message-ID: <20130513182000.GB14177@phenom.dumpdata.com> (raw)
In-Reply-To: <alpine.DEB.2.02.1305131811330.4799@kaball.uk.xensource.com>

On Mon, May 13, 2013 at 06:17:50PM +0100, Stefano Stabellini wrote:
> On Mon, 13 May 2013, Konrad Rzeszutek Wilk wrote:
> > This is a race so the amount varies but on a 4PCPU box
> > I seem to get only ~14 out of 16 vCPUs I want to online.
> > 
> > The issue at hand is that QEMU xenstore.c hotplug code changes
> > the vCPU array and triggers an ACPI SCI for each vCPU
> > online/offline change. That means we modify the array of vCPUs
> > as the guests ACPI AML code is reading it - resulting in
> > the guest reading the data only once and not changing the
> > CPU states appropiately.
> > 
> > The fix is to seperate the vCPU array changes from the ACPI SCI
> > notification. The code now will enumerate all of the vCPUs
> > and change the vCPU array if there is a need for a change.
> > If a change did occur then only _one_ ACPI SCI pulse is sent
> > to the guest. The vCPU array at that point has the online/offline
> > modified to what the user wanted to have.
> > 
> > Specifically, if a user provided this command:
> >  xl vcpu-set latest 16
> > 
> > (guest config has vcpus=1, maxvcpus=32) QEMU and the guest
> > (in this case Linux) would do:
> > 
> > QEMU:                                           Guest OS:
> > -xenstore_process_vcpu_set_event
> >  -> Gets an XenBus notification for CPU1
> >  -> Updates the gpe_state.cpus_state bitfield.
> >         -> Pulses the ACPI SCI
> >                                                 - ACPI SCI kicks in
> > 
> >  -> Gets an XenBus notification for CPU2
> >  -> Updates the gpe_state.cpus_state bitfield.
> >         -> Pulses the ACPI SCI
> > 
> >  -> Gets an XenBus notification for CPU3
> >  -> Updates the gpe_state.cpus_state bitfield.
> >         -> Pulses the ACPI SCI
> >    ...
> >                                                  - Method(PRST) invoked
> > 
> >  -> Gets an XenBus notification for CPU12
> >  -> Updates the gpe_state.cpus_state bitfield.
> >         -> Pulses the ACPI SCI
> >                                                   - reads AF00 for CPU state
> >                                                     [gets 0xff]
> >                                                   - reads AF02 [gets 0x7f]
> > 
> >  -> Gets an XenBus notification for CPU13
> >  -> Updates the gpe_state.cpus_state bitfield.
> >         -> Pulses the ACPI SCI
> > 
> >         .. until VCPU 16
> >                                                  - Method PRST updates
> >                                                    PR01 through 13 FLG
> >                                                    entry.
> >                                                  - PR01->PR13 _MAD
> >                                                    invoked.
> > 
> >                                                  - Brings up 13 CPUs.
> > 
> > While QEMU updates the rest of the cpus_state bitfields the ACPI AML
> > only does the CPU hotplug on those it had read.
> > 
> > Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
> > ---
> >  xenstore.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
> >  1 file changed, 62 insertions(+), 6 deletions(-)
> > 
> > diff --git a/xenstore.c b/xenstore.c
> > index c861d36..31dbbe5 100644
> > --- a/xenstore.c
> > +++ b/xenstore.c
> > @@ -999,25 +999,24 @@ void xenstore_record_dm_state(const char *state)
> >  {
> >      xenstore_record_dm("state", state);
> >  }
> > -
> > -static void xenstore_process_vcpu_set_event(char **vec)
> > +static int xenstore_process_one_vcpu_set_event(char *node)
> >  {
> >      char *act = NULL;
> > -    char *vcpustr, *node = vec[XS_WATCH_PATH];
> > +    char *vcpustr;
> >      unsigned int vcpu, len;
> >      int changed = -EINVAL;
> >  
> >      vcpustr = strstr(node, "cpu/");
> >      if (!vcpustr) {
> >          fprintf(stderr, "vcpu-set: watch node error.\n");
> > -        return;
> > +        return changed;
> >      }
> >      sscanf(vcpustr, "cpu/%u", &vcpu);
> >  
> >      act = xs_read(xsh, XBT_NULL, node, &len);
> >      if (!act) {
> >          fprintf(stderr, "vcpu-set: no command yet.\n");
> > -        return;
> > +        return changed;
> >      }
> >  
> >      if (!strncmp(act, "online", len))
> > @@ -1028,8 +1027,65 @@ static void xenstore_process_vcpu_set_event(char **vec)
> >          fprintf(stderr, "vcpu-set: command error.\n");
> >  
> >      free(act);
> > -    if (changed > 0)
> > +    return changed;
> > +}
> > +static void xenstore_process_vcpu_set_event(char **vec)
> > +{
> > +    int changed = 0, rc, i, num = 0;
> > +    char *vcpu, **dir;
> > +    char *path = vec[XS_WATCH_PATH];
> > +
> > +    /*
> > +     * Process the event right away in case the loop below fails
> > +     * to enumerate the correct vCPU.
> > +     */
> > +    rc = xenstore_process_one_vcpu_set_event(path);
> > +    if (rc > 0)
> > +        changed = 1;
> 
> I am not sure I follow you here: why the loop below would fail?

If there is an error (for example the xs_read fails), then the loop
below would stop as rc == -EINVAL.

> 
> > +    /*
> > +     * We get: /local/domain/<domid>/cpu/<vcpu>/availability or
> > +     * (at init) /local/domain/<domid>/cpu [ignore it] and need to
> > +     * iterate over /local/domain/<domid>/cpu/ directory.
> > +     */
> > +    vcpu = strstr(path, "cpu/");
> > +    if (!vcpu) {
> > +        fprintf(stderr,"[%s]: %s has no CPU!\n", __func__, path);
> > +        return;
> > +    }
> > +    /* Eliminate '/availability' */
> > +    vcpu[3] = '\0';
> > +    dir = xs_directory(xsh, XBT_NULL, path, &num);
> > +
> > +    if (!dir) {
> > +        fprintf(stderr, "[%s]: directory %s has no dirs!\n", __func__, path);
> > +        return;
> > +    }
> > +    if (num != vcpus)
> > +        fprintf(stderr, "[%s]: %d (number of vcpu entries) != %d (maxvcpus)! "\
> > +                "Continuing on..\n", __func__, num, vcpus);
> > +
> > +    for (i = 0; i < num; i++) {
> > +        char *attr;
> > +        ssize_t len = strlen(path) + strlen(dir[i]) + strlen("availability") +
> > +                      3 /* account for two '/' and '\0'*/;
> > +        attr = malloc(len);
> 
> just use XEN_BUFSIZE and put in on the stack

OK.
> 
> 
> > +
> > +        /* Construct "/local/domain/<domid>/cpu" (path) with <vcpu> (attr),
> > +         * and "availability" with '/' sprinkled around. */
> > +        snprintf(attr, len, "%s/%s/%s", path, dir[i],  "availability");
> > +        rc = xenstore_process_one_vcpu_set_event(attr);
> > +
> > +        free(attr);
> > +        if (rc > 0)
> > +            changed = 1;
> > +        if (rc < 0)
> > +            break;
> 
> Given that the user could provide a mask of vcpus to enable/disable,
> shouldn't we just process them all anyway?

rc < 0 is if an error occurs. 0 is if there are no changes.

And xenstore_process_one_vcpu_set_event could fail (say xs_read). The top
of the function would process the vCPU for which the event occured. Please
keep in mind that this function is called for _each_ vCPU that has changed.

> > +    free (dir);
> > +    if (changed > 0) {
> > +        fprintf(stderr, "Notifying OS about CPU hotplug changes.\n");
> >          qemu_cpu_notify();
> > +    }
> >      return;
> >  }
> >  
> > -- 
> > 1.8.1.4
> > 

  reply	other threads:[~2013-05-13 18:20 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-05-13 16:56 [PATCH] Fix QEMU HVM hotplug race in QEMU traditional (Xen 4.1, Xen 4.2, and Xen 4.3) (v1) Konrad Rzeszutek Wilk
2013-05-13 16:56 ` [PATCH 1/3] piix4acpi, xen, vcpu hotplug: Split the notification from the changes Konrad Rzeszutek Wilk
2013-05-13 17:01   ` Stefano Stabellini
2013-05-14  9:14     ` George Dunlap
2013-05-14 13:22       ` Konrad Rzeszutek Wilk
2013-05-13 16:56 ` [PATCH 2/3] piix4acpi, xen: Clarify that the qemu_set_irq calls just do an IRQ pulse Konrad Rzeszutek Wilk
2013-05-13 17:01   ` Stefano Stabellini
2013-05-13 16:56 ` [PATCH 3/3] piix4acpi, xen, hotplug: Fix race with ACPI AML code and hotplug Konrad Rzeszutek Wilk
2013-05-13 17:17   ` Stefano Stabellini
2013-05-13 18:20     ` Konrad Rzeszutek Wilk [this message]
2013-05-13 19:28       ` Konrad Rzeszutek Wilk
2013-05-14 13:55         ` Stefano Stabellini
  -- strict thread matches above, loose matches on Subject: below --
2013-05-14 17:48 [PATCH] qemu-traditional - ACPI vCPU hotplug fixes for Xen 4.3 (v2) Konrad Rzeszutek Wilk
2013-05-14 17:48 ` [PATCH 3/3] piix4acpi, xen, hotplug: Fix race with ACPI AML code and hotplug Konrad Rzeszutek Wilk

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=20130513182000.GB14177@phenom.dumpdata.com \
    --to=konrad.wilk@oracle.com \
    --cc=Ian.Jackson@eu.citrix.com \
    --cc=stefano.stabellini@eu.citrix.com \
    --cc=xen-devel@lists.xen.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.