Message ID | 20180521140402.23318-24-peter.maydell@linaro.org |
---|---|
State | Superseded |
Headers | show |
Series | iommu: support txattrs, support TCG execution, implement TZ MPC | expand |
On 21/05/2018 16:03, Peter Maydell wrote: > + * VMState array; devices with more inputs than this need to > + * migrate the extra lines via a subsection. > + * The subsection migrates as much of the levels[] array as is needed > + * (including repeating the first 16 elements), to avoid the awkwardness > + * of splitting it in two to meet the requirements of VMSTATE_VARRAY_UINT16. > + */ > +#define OLD_MAX_OR_LINES 16 > +#if MAX_OR_LINES < OLD_MAX_OR_LINES > +#error MAX_OR_LINES must be at least 16 for migration compatibility > +#endif > + > +static bool vmstate_extras_needed(void *opaque) > +{ > + qemu_or_irq *s = OR_IRQ(opaque); > + > + return s->num_lines >= OLD_MAX_OR_LINES; > +} > + > +static const VMStateDescription vmstate_or_irq_extras = { > + .name = "or-irq-extras", > + .version_id = 1, > + .minimum_version_id = 1, > + .needed = vmstate_extras_needed, > + .fields = (VMStateField[]) { > + VMSTATE_VARRAY_UINT16_UNSAFE(levels, qemu_or_irq, num_lines, 0, > + vmstate_info_bool, bool), > + VMSTATE_END_OF_LIST(), > + }, > +}; > + Why do the levels have to be migrated at all? It should be enough if the IRQ level is either migrated manually, or restored (e.g. in post_save callbacks) through other data that is migrated. Paolo
On 21 May 2018 at 15:34, Paolo Bonzini <pbonzini@redhat.com> wrote: > Why do the levels have to be migrated at all? It should be enough if > the IRQ level is either migrated manually, or restored (e.g. in > post_save callbacks) through other data that is migrated. This is standard behaviour for devices: they track their inbound irq/gpio lines, and then that becomes internal state for them that must be migrated. If we didn't migrate the input line state, then after a migration the levels[] array would be all zeroes, and the next time a connected device signalled a high-to-low transition we'd take the output line low even if it should not be (because we'd have forgotten that some other input lines were high). In a different world, the state would be in the qemu_irq line itself (in the same way that in hardware signal lines are their own state), but we can't get there from here. thanks -- PMM
On 21/05/2018 17:02, Peter Maydell wrote: > On 21 May 2018 at 15:34, Paolo Bonzini <pbonzini@redhat.com> wrote: >> Why do the levels have to be migrated at all? It should be enough if >> the IRQ level is either migrated manually, or restored (e.g. in >> post_save callbacks) through other data that is migrated. > This is standard behaviour for devices: they track their > inbound irq/gpio lines, and then that becomes internal state for > them that must be migrated. But or_irq's input are another device's outbound lines, so tracking them should not be necessary. The other device would do it for or_irq. Paolo > If we didn't migrate the input line state, then after a migration > the levels[] array would be all zeroes, and the next time a > connected device signalled a high-to-low transition we'd take > the output line low even if it should not be (because we'd have > forgotten that some other input lines were high). > > In a different world, the state would be in the qemu_irq line itself > (in the same way that in hardware signal lines are their own state), > but we can't get there from here.
On 30 May 2018 at 17:59, Paolo Bonzini <pbonzini@redhat.com> wrote: > On 21/05/2018 17:02, Peter Maydell wrote: >> On 21 May 2018 at 15:34, Paolo Bonzini <pbonzini@redhat.com> wrote: >>> Why do the levels have to be migrated at all? It should be enough if >>> the IRQ level is either migrated manually, or restored (e.g. in >>> post_save callbacks) through other data that is migrated. >> This is standard behaviour for devices: they track their >> inbound irq/gpio lines, and then that becomes internal state for >> them that must be migrated. > > But or_irq's input are another device's outbound lines, so tracking them > should not be necessary. The other device would do it for or_irq. There's no mechanism in qemu_irq for the destination end to ask the source end about its current value. The information flow is strictly one-way. thanks -- PMM
On 30/05/2018 19:35, Peter Maydell wrote: > On 30 May 2018 at 17:59, Paolo Bonzini <pbonzini@redhat.com> wrote: >> On 21/05/2018 17:02, Peter Maydell wrote: >>> On 21 May 2018 at 15:34, Paolo Bonzini <pbonzini@redhat.com> wrote: >>>> Why do the levels have to be migrated at all? It should be enough if >>>> the IRQ level is either migrated manually, or restored (e.g. in >>>> post_save callbacks) through other data that is migrated. >>> This is standard behaviour for devices: they track their >>> inbound irq/gpio lines, and then that becomes internal state for >>> them that must be migrated. >> >> But or_irq's input are another device's outbound lines, so tracking them >> should not be necessary. The other device would do it for or_irq. > > There's no mechanism in qemu_irq for the destination end to ask > the source end about its current value. The information flow > is strictly one-way. On postload, the source must call qemu_set_irq and that will cause an update of the or_irq, won't it? Paolo
On 31 May 2018 at 11:21, Paolo Bonzini <pbonzini@redhat.com> wrote: > On 30/05/2018 19:35, Peter Maydell wrote: >> On 30 May 2018 at 17:59, Paolo Bonzini <pbonzini@redhat.com> wrote: >>> On 21/05/2018 17:02, Peter Maydell wrote: >>>> On 21 May 2018 at 15:34, Paolo Bonzini <pbonzini@redhat.com> wrote: >>>>> Why do the levels have to be migrated at all? It should be enough if >>>>> the IRQ level is either migrated manually, or restored (e.g. in >>>>> post_save callbacks) through other data that is migrated. >>>> This is standard behaviour for devices: they track their >>>> inbound irq/gpio lines, and then that becomes internal state for >>>> them that must be migrated. >>> >>> But or_irq's input are another device's outbound lines, so tracking them >>> should not be necessary. The other device would do it for or_irq. >> >> There's no mechanism in qemu_irq for the destination end to ask >> the source end about its current value. The information flow >> is strictly one-way. > > On postload, the source must call qemu_set_irq and that will cause an > update of the or_irq, won't it? No, calling qemu_set_irq in postload is a bug. (You don't know which order the state of the source and destination devices is restored, so asserting a signal in postload would have different effects depending on whether the destination had already had its state restored or not.) The system design relies on each device keeping track of (and migrating) the state of the input lines it cares about. thanks -- PMM
On 31/05/2018 12:50, Peter Maydell wrote: > On 31 May 2018 at 11:21, Paolo Bonzini <pbonzini@redhat.com> wrote: >> On 30/05/2018 19:35, Peter Maydell wrote: >>> On 30 May 2018 at 17:59, Paolo Bonzini <pbonzini@redhat.com> wrote: >>>> On 21/05/2018 17:02, Peter Maydell wrote: >>>>> On 21 May 2018 at 15:34, Paolo Bonzini <pbonzini@redhat.com> wrote: >>>>>> Why do the levels have to be migrated at all? It should be enough if >>>>>> the IRQ level is either migrated manually, or restored (e.g. in >>>>>> post_save callbacks) through other data that is migrated. >>>>> This is standard behaviour for devices: they track their >>>>> inbound irq/gpio lines, and then that becomes internal state for >>>>> them that must be migrated. >>>> >>>> But or_irq's input are another device's outbound lines, so tracking them >>>> should not be necessary. The other device would do it for or_irq. >>> >>> There's no mechanism in qemu_irq for the destination end to ask >>> the source end about its current value. The information flow >>> is strictly one-way. >> >> On postload, the source must call qemu_set_irq and that will cause an >> update of the or_irq, won't it? > > No, calling qemu_set_irq in postload is a bug. (You don't know > which order the state of the source and destination devices is > restored, so asserting a signal in postload would have different > effects depending on whether the destination had already had > its state restored or not.) Hmm, I suppose the x86 world is a bit more "hierarchical" and you cannot create a qemu_irq loop - and creating the sink always before the source ensures that migration works fine with post_load. I'm pretty sure that there are devices that do that, and an interesting case (for the sake of this thread) is the IOMMU, which prompted the introduction of MigrationPriority. Thanks for the lesson! :) Maybe we should add your text to docs/devel/migration.rst, under "Device ordering", because it explicitly mentions interrupt controllers. Paolo
On 31 May 2018 at 12:50, Paolo Bonzini <pbonzini@redhat.com> wrote: > On 31/05/2018 12:50, Peter Maydell wrote: >> No, calling qemu_set_irq in postload is a bug. (You don't know >> which order the state of the source and destination devices is >> restored, so asserting a signal in postload would have different >> effects depending on whether the destination had already had >> its state restored or not.) > > Hmm, I suppose the x86 world is a bit more "hierarchical" and you cannot > create a qemu_irq loop - and creating the sink always before the source > ensures that migration works fine with post_load. I'm pretty sure that > there are devices that do that If there are then they are broken, because that's not how qemu_irqs work... (Similarly, you can't assert an irq in a reset method, because of ordering problems.) >, and an interesting case (for the sake of > this thread) is the IOMMU, which prompted the introduction of > MigrationPriority. Thanks for the lesson! :) This sounds like a workaround for a bug in the device implementation. Devices shouldn't care about which order they're restored in. thanks -- PMM
diff --git a/include/hw/or-irq.h b/include/hw/or-irq.h index 3f6fc1b58a..5a31e5a188 100644 --- a/include/hw/or-irq.h +++ b/include/hw/or-irq.h @@ -31,7 +31,10 @@ #define TYPE_OR_IRQ "or-irq" -#define MAX_OR_LINES 16 +/* This can safely be increased if necessary without breaking + * migration compatibility (as long as it remains greater than 15). + */ +#define MAX_OR_LINES 32 typedef struct OrIRQState qemu_or_irq; diff --git a/hw/core/or-irq.c b/hw/core/or-irq.c index f9d76c4641..a86901b673 100644 --- a/hw/core/or-irq.c +++ b/hw/core/or-irq.c @@ -66,14 +66,49 @@ static void or_irq_init(Object *obj) qdev_init_gpio_out(DEVICE(obj), &s->out_irq, 1); } +/* The original version of this device had a fixed 16 entries in its + * VMState array; devices with more inputs than this need to + * migrate the extra lines via a subsection. + * The subsection migrates as much of the levels[] array as is needed + * (including repeating the first 16 elements), to avoid the awkwardness + * of splitting it in two to meet the requirements of VMSTATE_VARRAY_UINT16. + */ +#define OLD_MAX_OR_LINES 16 +#if MAX_OR_LINES < OLD_MAX_OR_LINES +#error MAX_OR_LINES must be at least 16 for migration compatibility +#endif + +static bool vmstate_extras_needed(void *opaque) +{ + qemu_or_irq *s = OR_IRQ(opaque); + + return s->num_lines >= OLD_MAX_OR_LINES; +} + +static const VMStateDescription vmstate_or_irq_extras = { + .name = "or-irq-extras", + .version_id = 1, + .minimum_version_id = 1, + .needed = vmstate_extras_needed, + .fields = (VMStateField[]) { + VMSTATE_VARRAY_UINT16_UNSAFE(levels, qemu_or_irq, num_lines, 0, + vmstate_info_bool, bool), + VMSTATE_END_OF_LIST(), + }, +}; + static const VMStateDescription vmstate_or_irq = { .name = TYPE_OR_IRQ, .version_id = 1, .minimum_version_id = 1, .fields = (VMStateField[]) { - VMSTATE_BOOL_ARRAY(levels, qemu_or_irq, MAX_OR_LINES), + VMSTATE_BOOL_SUB_ARRAY(levels, qemu_or_irq, 0, OLD_MAX_OR_LINES), VMSTATE_END_OF_LIST(), - } + }, + .subsections = (const VMStateDescription*[]) { + &vmstate_or_irq_extras, + NULL + }, }; static Property or_irq_properties[] = {
For the IoTKit MPC support, we need to wire together the interrupt outputs of 17 MPCs; this exceeds the current value of MAX_OR_LINES. Increase MAX_OR_LINES to 32 (which should be enough for anyone). The tricky part is retaining the migration compatibility for existing OR gates; we add a subsection which is only used for larger OR gates, and define it such that we can freely increase MAX_OR_LINES in future (or even move to a dynamically allocated levels[] array without an upper size limit) without breaking compatibility. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- include/hw/or-irq.h | 5 ++++- hw/core/or-irq.c | 39 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 41 insertions(+), 3 deletions(-) -- 2.17.0