Re: [Qemu-devel] [PATCH 08/11] spapr_events: add support for dedicated hotplug event source

2016-10-16 Thread David Gibson
On Fri, Oct 14, 2016 at 01:44:17PM -0500, Michael Roth wrote:
> Quoting David Gibson (2016-10-13 23:56:43)
> > 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 
> > 
> > So.. are you saying that as well as allowing new event types, the new
> > special hotplug event souce effectively allows for a bigger queue?
> > 
> > Does that mean that we didn't even necessarily need the base+length
> > unplug events, because we could now have sent the many single-LMB
> > unplug requests that were necessary?  Or does it not increase the
> > effective queue enough for that?
> 
> I assume there are still some internal limits, but the events
> are now processed using a workqueue which should provide a bit more
> headroom than the RTAS event buffer used for EPOW events. Maybe
> John (on cc:) can provide more insight into what the actual limits
> 
> In either case, the possibility for huge memory hotplug/unplug
> situations still warrant the use of count+index I think, and since
> support for the new event delivery mechanism is negotiated using the
> same option bit as count+index, there's not really any reason not to
> use it when we can. For situations where we can't (CPU/PCI), it
> might give us a bit of breathing room there as well.

Ok, makes sense.  Thanks for the extra information.

> 
> > 
> > > ---
> > >  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 
> > >  
> > >  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   0x8000
> > > -#define EVENT_MASK_EPOW  0x4000
> > > -#define EVENT_MASK_HOTPLUG   0x1000
> > > 

Re: [Qemu-devel] [PATCH 08/11] spapr_events: add support for dedicated hotplug event source

2016-10-14 Thread Michael Roth
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 
> > ---
> >  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 
> > 
> >  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   0x8000
> > -#define EVENT_MASK_EPOW  0x4000
> > -#define EVENT_MASK_HOTPLUG   0x1000
> > -#define EVENT_MASK_IO0x0800
> > +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, 

Re: [Qemu-devel] [PATCH 08/11] spapr_events: add support for dedicated hotplug event source

2016-10-14 Thread Michael Roth
Quoting David Gibson (2016-10-13 23:56:43)
> 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 
> 
> So.. are you saying that as well as allowing new event types, the new
> special hotplug event souce effectively allows for a bigger queue?
> 
> Does that mean that we didn't even necessarily need the base+length
> unplug events, because we could now have sent the many single-LMB
> unplug requests that were necessary?  Or does it not increase the
> effective queue enough for that?

I assume there are still some internal limits, but the events
are now processed using a workqueue which should provide a bit more
headroom than the RTAS event buffer used for EPOW events. Maybe
John (on cc:) can provide more insight into what the actual limits

In either case, the possibility for huge memory hotplug/unplug
situations still warrant the use of count+index I think, and since
support for the new event delivery mechanism is negotiated using the
same option bit as count+index, there's not really any reason not to
use it when we can. For situations where we can't (CPU/PCI), it
might give us a bit of breathing room there as well.

> 
> > ---
> >  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 
> >  
> >  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   0x8000
> > -#define EVENT_MASK_EPOW  0x4000
> > -#define EVENT_MASK_HOTPLUG   0x1000
> > -#define EVENT_MASK_IO0x0800
> > +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,
> > +

Re: [Qemu-devel] [PATCH 08/11] spapr_events: add support for dedicated hotplug event source

2016-10-14 Thread Bharata B Rao
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 
> ---
>  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 
> 
>  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   0x8000
> -#define EVENT_MASK_EPOW  0x4000
> -#define EVENT_MASK_HOTPLUG   0x1000
> -#define EVENT_MASK_IO0x0800
> +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];
> +   

Re: [Qemu-devel] [PATCH 08/11] spapr_events: add support for dedicated hotplug event source

2016-10-13 Thread David Gibson
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 

So.. are you saying that as well as allowing new event types, the new
special hotplug event souce effectively allows for a bigger queue?

Does that mean that we didn't even necessarily need the base+length
unplug events, because we could now have sent the many single-LMB
unplug requests that were necessary?  Or does it not increase the
effective queue enough for that?

> ---
>  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 
>  
>  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   0x8000
> -#define EVENT_MASK_EPOW  0x4000
> -#define EVENT_MASK_HOTPLUG   0x1000
> -#define EVENT_MASK_IO0x0800
> +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 = 

[Qemu-devel] [PATCH 08/11] spapr_events: add support for dedicated hotplug event source

2016-10-12 Thread Michael Roth
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 
---
 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 
 
 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   0x8000
-#define EVENT_MASK_EPOW  0x4000
-#define EVENT_MASK_HOTPLUG   0x1000
-#define EVENT_MASK_IO0x0800
+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) {
+