Re: [Qemu-devel] [PATCH 08/11] spapr_events: add support for dedicated hotplug event source
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
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
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
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
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 RothSo.. 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
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) { +