Message ID | 20170519142750.18437-3-danielhb@linux.vnet.ibm.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Quoting Daniel Henrique Barboza (2017-05-19 09:27:50) > From: Jianjun Duan <duanj@linux.vnet.ibm.com> > > In racing situations between hotplug events and migration operation, > a rtas hotplug event could have not yet be delivered to the source > guest when migration is started. In this case the pending_events of > spapr state need be transmitted to the target so that the hotplug > event can be finished on the target. > > All the different fields of the events are encoded as defined by > PAPR. We can migrate them as a binary stream inside VBUFFER without > any concerns about data padding or endianess. > > pending_events is put in a subsection in the spapr state VMSD to make > sure migration across different versions is not broken. > > Signed-off-by: Jianjun Duan <duanj@linux.vnet.ibm.com> > Signed-off-by: Daniel Henrique Barboza <danielhb@linux.vnet.ibm.com> Reviewed-by: Michael Roth <mdroth@linux.vnet.ibm.com> > --- > hw/ppc/spapr.c | 32 ++++++++++++++++++++++++++++++++ > hw/ppc/spapr_events.c | 12 ++++++++++++ > include/hw/ppc/spapr.h | 3 ++- > 3 files changed, 46 insertions(+), 1 deletion(-) > > diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c > index 0980d73..5afd328 100644 > --- a/hw/ppc/spapr.c > +++ b/hw/ppc/spapr.c > @@ -1444,6 +1444,37 @@ static bool version_before_3(void *opaque, int version_id) > return version_id < 3; > } > > +static bool spapr_pending_events_needed(void *opaque) > +{ > + sPAPRMachineState *spapr = (sPAPRMachineState *)opaque; > + return !QTAILQ_EMPTY(&spapr->pending_events); > +} > + > +static const VMStateDescription vmstate_spapr_event_entry = { > + .name = "spapr_event_log_entry", > + .version_id = 1, > + .minimum_version_id = 1, > + .fields = (VMStateField[]) { > + VMSTATE_INT32(log_type, sPAPREventLogEntry), > + VMSTATE_UINT32(data_size, sPAPREventLogEntry), > + VMSTATE_VBUFFER_ALLOC_UINT32(data, sPAPREventLogEntry, 0, > + NULL, data_size), > + VMSTATE_END_OF_LIST() > + }, > +}; > + > +static const VMStateDescription vmstate_spapr_pending_events = { > + .name = "spapr_pending_events", > + .version_id = 1, > + .minimum_version_id = 1, > + .needed = spapr_pending_events_needed, > + .fields = (VMStateField[]) { > + VMSTATE_QTAILQ_V(pending_events, sPAPRMachineState, 1, > + vmstate_spapr_event_entry, sPAPREventLogEntry, next), > + VMSTATE_END_OF_LIST() > + }, > +}; > + > static bool spapr_ov5_cas_needed(void *opaque) > { > sPAPRMachineState *spapr = opaque; > @@ -1542,6 +1573,7 @@ static const VMStateDescription vmstate_spapr = { > .subsections = (const VMStateDescription*[]) { > &vmstate_spapr_ov5_cas, > &vmstate_spapr_patb_entry, > + &vmstate_spapr_pending_events, > NULL > } > }; > diff --git a/hw/ppc/spapr_events.c b/hw/ppc/spapr_events.c > index 73e2a18..a509c46 100644 > --- a/hw/ppc/spapr_events.c > +++ b/hw/ppc/spapr_events.c > @@ -350,6 +350,18 @@ static void rtas_event_log_queue(int log_type, void *data) > g_assert(data); > entry->log_type = log_type; > entry->data = data; > + > + switch (log_type) { > + case RTAS_LOG_TYPE_EPOW: > + entry->data_size = sizeof(struct epow_log_full); > + break; > + case RTAS_LOG_TYPE_HOTPLUG: > + entry->data_size = sizeof(struct hp_log_full); > + break; > + default: > + g_assert(false); > + } > + > QTAILQ_INSERT_TAIL(&spapr->pending_events, entry, next); > } > > diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h > index 02239a5..0554e11 100644 > --- a/include/hw/ppc/spapr.h > +++ b/include/hw/ppc/spapr.h > @@ -597,8 +597,9 @@ struct sPAPRTCETable { > sPAPRTCETable *spapr_tce_find_by_liobn(target_ulong liobn); > > struct sPAPREventLogEntry { > - int log_type; > + int32_t log_type; > void *data; > + uint32_t data_size; > QTAILQ_ENTRY(sPAPREventLogEntry) next; > }; > > -- > 2.9.4 >
On Fri, May 19, 2017 at 11:27:50AM -0300, Daniel Henrique Barboza wrote: > From: Jianjun Duan <duanj@linux.vnet.ibm.com> > > In racing situations between hotplug events and migration operation, > a rtas hotplug event could have not yet be delivered to the source > guest when migration is started. In this case the pending_events of > spapr state need be transmitted to the target so that the hotplug > event can be finished on the target. > > All the different fields of the events are encoded as defined by > PAPR. We can migrate them as a binary stream inside VBUFFER without > any concerns about data padding or endianess. > > pending_events is put in a subsection in the spapr state VMSD to make > sure migration across different versions is not broken. > > Signed-off-by: Jianjun Duan <duanj@linux.vnet.ibm.com> > Signed-off-by: Daniel Henrique Barboza <danielhb@linux.vnet.ibm.com> > --- > hw/ppc/spapr.c | 32 ++++++++++++++++++++++++++++++++ > hw/ppc/spapr_events.c | 12 ++++++++++++ > include/hw/ppc/spapr.h | 3 ++- > 3 files changed, 46 insertions(+), 1 deletion(-) > > diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c > index 0980d73..5afd328 100644 > --- a/hw/ppc/spapr.c > +++ b/hw/ppc/spapr.c > @@ -1444,6 +1444,37 @@ static bool version_before_3(void *opaque, int version_id) > return version_id < 3; > } > > +static bool spapr_pending_events_needed(void *opaque) > +{ > + sPAPRMachineState *spapr = (sPAPRMachineState *)opaque; > + return !QTAILQ_EMPTY(&spapr->pending_events); > +} > + > +static const VMStateDescription vmstate_spapr_event_entry = { > + .name = "spapr_event_log_entry", > + .version_id = 1, > + .minimum_version_id = 1, > + .fields = (VMStateField[]) { > + VMSTATE_INT32(log_type, sPAPREventLogEntry), > + VMSTATE_UINT32(data_size, sPAPREventLogEntry), > + VMSTATE_VBUFFER_ALLOC_UINT32(data, sPAPREventLogEntry, 0, > + NULL, data_size), > + VMSTATE_END_OF_LIST() > + }, > +}; > + > +static const VMStateDescription vmstate_spapr_pending_events = { > + .name = "spapr_pending_events", > + .version_id = 1, > + .minimum_version_id = 1, > + .needed = spapr_pending_events_needed, > + .fields = (VMStateField[]) { > + VMSTATE_QTAILQ_V(pending_events, sPAPRMachineState, 1, > + vmstate_spapr_event_entry, sPAPREventLogEntry, next), > + VMSTATE_END_OF_LIST() > + }, > +}; > + > static bool spapr_ov5_cas_needed(void *opaque) > { > sPAPRMachineState *spapr = opaque; > @@ -1542,6 +1573,7 @@ static const VMStateDescription vmstate_spapr = { > .subsections = (const VMStateDescription*[]) { > &vmstate_spapr_ov5_cas, > &vmstate_spapr_patb_entry, > + &vmstate_spapr_pending_events, > NULL > } > }; > diff --git a/hw/ppc/spapr_events.c b/hw/ppc/spapr_events.c > index 73e2a18..a509c46 100644 > --- a/hw/ppc/spapr_events.c > +++ b/hw/ppc/spapr_events.c > @@ -350,6 +350,18 @@ static void rtas_event_log_queue(int log_type, void *data) > g_assert(data); > entry->log_type = log_type; > entry->data = data; > + > + switch (log_type) { > + case RTAS_LOG_TYPE_EPOW: > + entry->data_size = sizeof(struct epow_log_full); > + break; > + case RTAS_LOG_TYPE_HOTPLUG: > + entry->data_size = sizeof(struct hp_log_full); > + break; > + default: > + g_assert(false); > + } You can do better than this. The header of the event has an 'extended_length' field which is set (correctly) by the existing functions creating the events. You'll need to add the base/common header size back in, but that's easy. That's how the guest determines the size of the events once they arrive, and that's what you should use here as well. > + > QTAILQ_INSERT_TAIL(&spapr->pending_events, entry, next); > } > > diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h > index 02239a5..0554e11 100644 > --- a/include/hw/ppc/spapr.h > +++ b/include/hw/ppc/spapr.h > @@ -597,8 +597,9 @@ struct sPAPRTCETable { > sPAPRTCETable *spapr_tce_find_by_liobn(target_ulong liobn); > > struct sPAPREventLogEntry { > - int log_type; > + int32_t log_type; > void *data; > + uint32_t data_size; > QTAILQ_ENTRY(sPAPREventLogEntry) next; > }; >
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 0980d73..5afd328 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -1444,6 +1444,37 @@ static bool version_before_3(void *opaque, int version_id) return version_id < 3; } +static bool spapr_pending_events_needed(void *opaque) +{ + sPAPRMachineState *spapr = (sPAPRMachineState *)opaque; + return !QTAILQ_EMPTY(&spapr->pending_events); +} + +static const VMStateDescription vmstate_spapr_event_entry = { + .name = "spapr_event_log_entry", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_INT32(log_type, sPAPREventLogEntry), + VMSTATE_UINT32(data_size, sPAPREventLogEntry), + VMSTATE_VBUFFER_ALLOC_UINT32(data, sPAPREventLogEntry, 0, + NULL, data_size), + VMSTATE_END_OF_LIST() + }, +}; + +static const VMStateDescription vmstate_spapr_pending_events = { + .name = "spapr_pending_events", + .version_id = 1, + .minimum_version_id = 1, + .needed = spapr_pending_events_needed, + .fields = (VMStateField[]) { + VMSTATE_QTAILQ_V(pending_events, sPAPRMachineState, 1, + vmstate_spapr_event_entry, sPAPREventLogEntry, next), + VMSTATE_END_OF_LIST() + }, +}; + static bool spapr_ov5_cas_needed(void *opaque) { sPAPRMachineState *spapr = opaque; @@ -1542,6 +1573,7 @@ static const VMStateDescription vmstate_spapr = { .subsections = (const VMStateDescription*[]) { &vmstate_spapr_ov5_cas, &vmstate_spapr_patb_entry, + &vmstate_spapr_pending_events, NULL } }; diff --git a/hw/ppc/spapr_events.c b/hw/ppc/spapr_events.c index 73e2a18..a509c46 100644 --- a/hw/ppc/spapr_events.c +++ b/hw/ppc/spapr_events.c @@ -350,6 +350,18 @@ static void rtas_event_log_queue(int log_type, void *data) g_assert(data); entry->log_type = log_type; entry->data = data; + + switch (log_type) { + case RTAS_LOG_TYPE_EPOW: + entry->data_size = sizeof(struct epow_log_full); + break; + case RTAS_LOG_TYPE_HOTPLUG: + entry->data_size = sizeof(struct hp_log_full); + break; + default: + g_assert(false); + } + QTAILQ_INSERT_TAIL(&spapr->pending_events, entry, next); } diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h index 02239a5..0554e11 100644 --- a/include/hw/ppc/spapr.h +++ b/include/hw/ppc/spapr.h @@ -597,8 +597,9 @@ struct sPAPRTCETable { sPAPRTCETable *spapr_tce_find_by_liobn(target_ulong liobn); struct sPAPREventLogEntry { - int log_type; + int32_t log_type; void *data; + uint32_t data_size; QTAILQ_ENTRY(sPAPREventLogEntry) next; };