[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-ppc] [PATCH 08/11] spapr_events: add support for dedicated hot
From: |
Michael Roth |
Subject: |
Re: [Qemu-ppc] [PATCH 08/11] spapr_events: add support for dedicated hotplug event source |
Date: |
Fri, 14 Oct 2016 13:51:19 -0500 |
User-agent: |
alot/0.3.6 |
Quoting Bharata B Rao (2016-10-14 03:46:20)
> On Wed, Oct 12, 2016 at 06:13:56PM -0500, Michael Roth wrote:
> > Hotplug events were previously delivered using an EPOW interrupt
> > and were queued by linux guests into a circular buffer. For traditional
> > EPOW events like shutdown/resets, this isn't an issue, but for hotplug
> > events there are cases where this buffer can be exhausted, resulting
> > in the loss of hotplug events, resets, etc.
> >
> > Newer-style hotplug event are delivered using a dedicated event source.
> > We enable this in supported guests by adding standard an additional
> > event source in the guest device-tree via /event-sources, and, if
> > the guest advertises support for the newer-style hotplug events,
> > using the corresponding interrupt to signal the available of
> > hotplug/unplug events.
> >
> > Signed-off-by: Michael Roth <address@hidden>
> > ---
> > hw/ppc/spapr.c | 10 ++--
> > hw/ppc/spapr_events.c | 148
> > ++++++++++++++++++++++++++++++++++++++-----------
> > include/hw/ppc/spapr.h | 3 +-
> > 3 files changed, 120 insertions(+), 41 deletions(-)
> >
> > diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
> > index d80a6fa..2037222 100644
> > --- a/hw/ppc/spapr.c
> > +++ b/hw/ppc/spapr.c
> > @@ -275,8 +275,7 @@ static void *spapr_create_fdt_skel(hwaddr initrd_base,
> > hwaddr initrd_size,
> > hwaddr kernel_size,
> > bool little_endian,
> > - const char *kernel_cmdline,
> > - uint32_t epow_irq)
> > + const char *kernel_cmdline)
> > {
> > void *fdt;
> > uint32_t start_prop = cpu_to_be32(initrd_base);
> > @@ -437,7 +436,7 @@ static void *spapr_create_fdt_skel(hwaddr initrd_base,
> > _FDT((fdt_end_node(fdt)));
> >
> > /* event-sources */
> > - spapr_events_fdt_skel(fdt, epow_irq);
> > + spapr_events_fdt_skel(fdt);
> >
> > /* /hypervisor node */
> > if (kvm_enabled()) {
> > @@ -1944,7 +1943,7 @@ static void ppc_spapr_init(MachineState *machine)
> > }
> > g_free(filename);
> >
> > - /* Set up EPOW events infrastructure */
> > + /* Set up RTAS event infrastructure */
> > spapr_events_init(spapr);
> >
> > /* Set up the RTC RTAS interfaces */
> > @@ -2076,8 +2075,7 @@ static void ppc_spapr_init(MachineState *machine)
> > /* Prepare the device tree */
> > spapr->fdt_skel = spapr_create_fdt_skel(initrd_base, initrd_size,
> > kernel_size, kernel_le,
> > - kernel_cmdline,
> > - spapr->check_exception_irq);
> > + kernel_cmdline);
> > assert(spapr->fdt_skel != NULL);
> >
> > /* used by RTAS */
> > diff --git a/hw/ppc/spapr_events.c b/hw/ppc/spapr_events.c
> > index 4c7b6ae..f8bbec6 100644
> > --- a/hw/ppc/spapr_events.c
> > +++ b/hw/ppc/spapr_events.c
> > @@ -40,6 +40,7 @@
> > #include "hw/ppc/spapr_drc.h"
> > #include "qemu/help_option.h"
> > #include "qemu/bcd.h"
> > +#include "hw/ppc/spapr_ovec.h"
> > #include <libfdt.h>
> >
> > struct rtas_error_log {
> > @@ -206,28 +207,104 @@ struct hp_log_full {
> > struct rtas_event_log_v6_hp hp;
> > } QEMU_PACKED;
> >
> > -#define EVENT_MASK_INTERNAL_ERRORS 0x80000000
> > -#define EVENT_MASK_EPOW 0x40000000
> > -#define EVENT_MASK_HOTPLUG 0x10000000
> > -#define EVENT_MASK_IO 0x08000000
> > +typedef enum EventClassIndex {
> > + EVENT_CLASS_INTERNAL_ERRORS = 0,
> > + EVENT_CLASS_EPOW = 1,
> > + EVENT_CLASS_RESERVED = 2,
> > + EVENT_CLASS_HOT_PLUG = 3,
> > + EVENT_CLASS_IO = 4,
> > + EVENT_CLASS_MAX
> > +} EventClassIndex;
> > +
> > +#define EVENT_CLASS_MASK(index) (1 << (31 - index))
> > +
> > +typedef struct EventSource {
> > + const char *name;
> > + int irq;
> > + uint32_t mask;
> > + bool enabled;
> > +} EventSource;
> > +
> > +static EventSource event_source[EVENT_CLASS_MAX] = {
> > + [EVENT_CLASS_INTERNAL_ERRORS] = { .name = "internal-errors", },
> > + [EVENT_CLASS_EPOW] = { .name = "epow-events", },
> > + [EVENT_CLASS_HOT_PLUG] = { .name = "hot-plug-events", },
> > + [EVENT_CLASS_IO] = { .name = "ibm,io-events", },
> > +};
> > +
> > +static void rtas_event_source_register(EventClassIndex index, int irq)
> > +{
> > + /* we only support 1 irq per event class at the moment */
> > + g_assert(!event_source[index].enabled);
> > + event_source[index].irq = irq;
> > + event_source[index].mask = EVENT_CLASS_MASK(index);
> > + event_source[index].enabled = true;
> > +}
> >
> > -void spapr_events_fdt_skel(void *fdt, uint32_t check_exception_irq)
> > +void spapr_events_fdt_skel(void *fdt)
> > {
> > - uint32_t irq_ranges[] = {cpu_to_be32(check_exception_irq),
> > cpu_to_be32(1)};
> > - uint32_t interrupts[] = {cpu_to_be32(check_exception_irq), 0};
> > + uint32_t irq_ranges[EVENT_CLASS_MAX * 2];
> > + int i, count = 0;
> >
> > _FDT((fdt_begin_node(fdt, "event-sources")));
> >
> > + for (i = 0, count = 0; i < EVENT_CLASS_MAX; i++) {
> > + /* TODO: what does 0 entail? */
> > + uint32_t interrupts[] = { cpu_to_be32(event_source[i].irq), 0 };
> > +
> > + if (!event_source[i].enabled) {
> > + continue;
> > + }
> > +
> > + _FDT((fdt_begin_node(fdt, event_source[i].name)));
> > + _FDT((fdt_property(fdt, "interrupts", interrupts,
> > sizeof(interrupts))));
> > + _FDT((fdt_end_node(fdt)));
> > +
> > + irq_ranges[count++] = interrupts[0];
> > + irq_ranges[count++] = cpu_to_be32(1);
> > + }
> > +
> > + /* TODO: confirm the count is the last expected element */
> > + irq_ranges[count] = cpu_to_be32(count);
> > + count++;
> > +
> > _FDT((fdt_property(fdt, "interrupt-controller", NULL, 0)));
> > _FDT((fdt_property_cell(fdt, "#interrupt-cells", 2)));
> > _FDT((fdt_property(fdt, "interrupt-ranges",
> > - irq_ranges, sizeof(irq_ranges))));
> > + irq_ranges, count * sizeof(uint32_t))));
> >
> > - _FDT((fdt_begin_node(fdt, "epow-events")));
> > - _FDT((fdt_property(fdt, "interrupts", interrupts,
> > sizeof(interrupts))));
> > _FDT((fdt_end_node(fdt)));
> > +}
> >
> > - _FDT((fdt_end_node(fdt)));
> > +static const EventSource *rtas_event_log_to_source(int log_type)
> > +{
> > + const EventSource *source;
> > +
> > + switch (log_type) {
> > + case RTAS_LOG_TYPE_HOTPLUG:
> > + source = &event_source[EVENT_CLASS_HOT_PLUG];
> > + if (event_source[EVENT_CLASS_HOT_PLUG].enabled) {
> > + break;
> > + }
>
> In addition to the above .enabled check, shouldn't you be checking if
> the guest indeed supports the dedicated hotplug interrupt source before
> returning the source ?
Yes, I believe you're right. I'd been relying legacy-hotplug-events=true
to test the old signalling mechanism (which leaves this event source
disabled), but haven't tried PCI/CPU since adding the ovec stuff, so
didn't notice those were broken with legacy-hotplug-events=false.
Will fix it up in next submission.
>
> This I believe is the reason for the CPU hotplug failures I that mentioned
> in reply to your 11/11 thread. I am on 4.7.x kernel which probably doesn't
> support hotplug interrupt source, but QEMU ends up registering and raising
> such an interrupt.
>
> Regards,
> Bharata.
- Re: [Qemu-ppc] [PATCH 01/11] spapr_ovec: initial implementation of option vector helpers, (continued)
- [Qemu-ppc] [PATCH 04/11] spapr: improve ibm, architecture-vec-5 property handling, Michael Roth, 2016/10/12
- [Qemu-ppc] [PATCH 05/11] spapr: fix inheritance chain for default machine options, Michael Roth, 2016/10/12
- [Qemu-ppc] [PATCH 08/11] spapr_events: add support for dedicated hotplug event source, Michael Roth, 2016/10/12
- Re: [Qemu-ppc] [PATCH 08/11] spapr_events: add support for dedicated hotplug event source, Bharata B Rao, 2016/10/14
- Re: [Qemu-ppc] [PATCH 08/11] spapr_events: add support for dedicated hotplug event source,
Michael Roth <=
- Re: [Qemu-ppc] [Qemu-devel] [RFC PATCH 00/11] spapr: option vector re-work and memory unplug support, no-reply, 2016/10/14