qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [Bug 1297651] [NEW] KVM create a win7 guest with Qemu,


From: Hu, Robert
Subject: Re: [Qemu-devel] [Bug 1297651] [NEW] KVM create a win7 guest with Qemu, it boots up fail
Date: Thu, 27 Mar 2014 05:19:15 +0000


Best Regards,
Robert Ho

> -----Original Message-----
> From: Laszlo Ersek [mailto:address@hidden
> Sent: Wednesday, March 26, 2014 9:57 PM
> To: Michael S. Tsirkin
> Cc: Bug 1297651; address@hidden; address@hidden; Hu, Robert
> Subject: Re: [Bug 1297651] [NEW] KVM create a win7 guest with Qemu, it boots
> up fail
> 
> On 03/26/14 13:58, Michael S. Tsirkin wrote:
> > On Wed, Mar 26, 2014 at 01:28:02PM +0100, Laszlo Ersek wrote:
> >> On 03/26/14 11:31, Michael S. Tsirkin wrote:
> >>
> >>> On Wed, Mar 26, 2014 at 06:45:10AM -0000, Robert Hu wrote:
> >>
> >>>> Date:   Mon Mar 17 17:05:16 2014 +0100
> >>>>
> >>>>     i386/acpi-build: allow more than 255 elements in CPON
> >>>>
> >>>>     The build_ssdt() function builds a number of AML objects that are
> related
> >>>>     to CPU hotplug, and whose IDs form a contiguous sequence of APIC
> IDs.
> >>>>     (APIC IDs are in fact discontiguous, but this is the traditional
> >>>>     interface: build a contiguous sequence from zero up that covers all
> >>>>     possible APIC IDs.) These objects are:
> >>>>
> >>>>     - a Processor() object for each VCPU,
> >>>>     - a NTFY method, with one branch for each VCPU,
> >>>>     - a CPON package with one element (hotplug status byte) for each
> VCPU.
> >>>>
> >>>>     The build_ssdt() function currently limits the *count* of processor
> >>>>     objects, and NTFY branches, and CPON elements, in 0xFF (see the
> assignment
> >>>>     to "acpi_cpus"). This allows for an inclusive APIC ID range of 
> >>>> [0..254].
> >>>>     This is incorrect, because the highest APIC ID that we otherwise 
> >>>> allow
> a
> >>>>     VCPU to take is 255.
> >>>>
> >>>>     In order to extend the maximum count to 256, and the traversed APIC
> ID
> >>>>     range correspondingly to [0..255]:
> >>>>     - the Processor() objects need no change,
> >>>>     - the NTFY method also needs no change,
> >>>>     - the CPON package must be updated, because it is defined with a
> >>>>       DefPackage, and the number of elements in such a package can be
> at most
> >>>>       255. We pick a DefVarPackage instead.
> >>>>
> >>>>     We replace the Op byte, and the encoding of the number of
> elements.
> >>>>     Compare:
> >>>>
> >>>>     DefPackage     := PackageOp    PkgLength NumElements
> PackageElementList
> >>>>     DefVarPackage  := VarPackageOp PkgLength VarNumElements
> PackageElementList
> >>>>
> >>>>     PackageOp      := 0x12
> >>>>     VarPackageOp   := 0x13
> >>>
> >>>
> >>> I think I know what's going on here: the specification says:
> >>>
> >>> The ASL compiler can emit two different AML opcodes for a Package
> >>> declaration, either PackageOp or VarPackageOp. For small,
> >>> fixed-length packages, the PackageOp is used and this
> >>>
> >>> opcode is compatible with ACPI 1.0. A VarPackageOp will be emitted
> >>> if any of the following conditions are true:
> >>> *
> >>>  The NumElements argument is a TermArg that can only be resolved at
> >>> runtime.
> >>> *
> >>>  At compile time, NumElements resolves to a constant that is larger
> >>>  than 55.
> >>> *
> >>>  The PackageList contains more than 255 initializer elements.
> >>>
> >>>
> >>> So we clearly violate this rule.
> >>
> >> I did see this passage of the spec, but it is not relevant. It is
> >> about what the ASL compiler does. It comes from:
> >>
> >> 19      ACPI Source Language (ASL)Reference
> >> 19.5    ASL Operator Reference
> >> 19.5.98 Package (Declare Package Object)
> >>
> >> We do not have an ASL compiler at hand.
> >
> > True. But I think the spec and guests simply didn't envision writing
> > AML by hand :)
> 
> I sort of disagree. The spec has an entire chapter dedicated to AML. If
> the restriction were mentioned in the AML chapter, I'd agree. (Of course
> it *could* be in fact mentioned there, just with me not knowing!)
> 
> >
> >> The specification nowhere restricts VarPackageOp to > 255.
> >>
> >> However, what I *did* mess up is compatibility with ACPI 1.0. Just
> >> below the quoted part, there's also this:
> >>
> >>   Note: The ability to create variable-sized packages was first
> >>         introduced in ACPI 2.0. ACPI 1.0 only allowed fixed-size
> >>         packages with up to 255 elements.
> >>
> >> I forgot that the header of the containing table stated the ACPI
> >> version:
> >>
> >>     /* Copy header and patch values in the S3_ / S4_ / S5_ packages */
> >>     ssdt_ptr = acpi_data_push(table_data, sizeof(ssdp_misc_aml));
> >>
> >> and
> >>
> >>   DefinitionBlock ("ssdt-misc.aml",  "SSDT", 0x01, "BXPC", "BXSSDTSUSP",
> 0x1)
> >>                                              ^^^^
> >>                                         ComplianceRevision
> >>
> >> So my patch generates ACPI 2.0+ contents for an 1.0 table.
> >>
> >>> The following seems to fix the issue - still testing. Can you
> >>> confirm please?
> >>
> >> This patch only restricts the bug to a subset of cases, but it
> >> doesn't fix it.
> >>
> >>> However the question we should ask is whether
> >>> it's a good idea to allow hotplug ID values that might
> >>> make guests fail to boot.
> >>>
> >>> How about limiting ACPI_CPU_HOTPLUG_ID_LIMIT to 255?
> >>
> >> I think it's not the package size / APIC ID value per se that breaks
> >> the boot, but the incompatibility between the ACPI revision stated in
> >> the SSDT header, and the construct in the table.
> >
> >
> > It would be interesting to try tweaking the table version and seeing
> > what happens. Does it help any guests?
> 
> Maybe Robert can try this patch:
> 
> ------------[snip]------------
> diff --git a/hw/i386/acpi-dsdt.dsl b/hw/i386/acpi-dsdt.dsl
> index 0a1e252..6294da5 100644
> --- a/hw/i386/acpi-dsdt.dsl
> +++ b/hw/i386/acpi-dsdt.dsl
> @@ -22,7 +22,7 @@ ACPI_EXTRACT_ALL_CODE AcpiDsdtAmlCode
>  DefinitionBlock (
>      "acpi-dsdt.aml",    // Output Filename
>      "DSDT",             // Signature
> -    0x01,               // DSDT Compliance Revision
> +    0x02,               // DSDT Compliance Revision
>      "BXPC",             // OEMID
>      "BXDSDT",           // TABLE ID
>      0x1                 // OEM Revision
> diff --git a/hw/i386/q35-acpi-dsdt.dsl b/hw/i386/q35-acpi-dsdt.dsl
> index f4d2a2d..a728e7f 100644
> --- a/hw/i386/q35-acpi-dsdt.dsl
> +++ b/hw/i386/q35-acpi-dsdt.dsl
> @@ -27,7 +27,7 @@ ACPI_EXTRACT_ALL_CODE Q35AcpiDsdtAmlCode
>  DefinitionBlock (
>      "q35-acpi-dsdt.aml",// Output Filename
>      "DSDT",             // Signature
> -    0x01,               // DSDT Compliance Revision
> +    0x02,               // DSDT Compliance Revision
>      "BXPC",             // OEMID
>      "BXDSDT",           // TABLE ID
>      0x2                 // OEM Revision
> diff --git a/hw/i386/ssdt-misc.dsl b/hw/i386/ssdt-misc.dsl
> index a4484b8..f284f34 100644
> --- a/hw/i386/ssdt-misc.dsl
> +++ b/hw/i386/ssdt-misc.dsl
> @@ -15,7 +15,7 @@
> 
>  ACPI_EXTRACT_ALL_CODE ssdp_misc_aml
> 
> -DefinitionBlock ("ssdt-misc.aml", "SSDT", 0x01, "BXPC", "BXSSDTSUSP", 0x1)
> +DefinitionBlock ("ssdt-misc.aml", "SSDT", 0x02, "BXPC", "BXSSDTSUSP", 0x1)
>  {
> 
> 
> /*************************************************************
> ***
> diff --git a/hw/i386/ssdt-pcihp.dsl b/hw/i386/ssdt-pcihp.dsl
> index ac91c05..80d4b9a 100644
> --- a/hw/i386/ssdt-pcihp.dsl
> +++ b/hw/i386/ssdt-pcihp.dsl
> @@ -15,7 +15,7 @@
> 
>  ACPI_EXTRACT_ALL_CODE ssdp_pcihp_aml
> 
> -DefinitionBlock ("ssdt-pcihp.aml", "SSDT", 0x01, "BXPC", "BXSSDTPCIHP", 0x1)
> +DefinitionBlock ("ssdt-pcihp.aml", "SSDT", 0x02, "BXPC", "BXSSDTPCIHP", 0x1)
>  {
> 
> 
> /*************************************************************
> ***
> diff --git a/hw/i386/ssdt-proc.dsl b/hw/i386/ssdt-proc.dsl
> index 8229bfd..e8a43d6 100644
> --- a/hw/i386/ssdt-proc.dsl
> +++ b/hw/i386/ssdt-proc.dsl
> @@ -32,7 +32,7 @@
> 
>  ACPI_EXTRACT_ALL_CODE ssdp_proc_aml
> 
> -DefinitionBlock ("ssdt-proc.aml", "SSDT", 0x01, "BXPC", "BXSSDT", 0x1)
> +DefinitionBlock ("ssdt-proc.aml", "SSDT", 0x02, "BXPC", "BXSSDT", 0x1)
>  {
>      ACPI_EXTRACT_PROCESSOR_START ssdt_proc_start
>      ACPI_EXTRACT_PROCESSOR_END ssdt_proc_end
> ------------[snip]------------
> 
[Hu, Robert] Tried the above patch, guest still fail to boot up.
> >>>
> >>> We never allowed > 255 in the past, is it worth the
> >>> maintainance headaches?
> >>>
> >>>
> >>> diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
> >>> index f1054dd..7597517 100644
> >>> --- a/hw/i386/acpi-build.c
> >>> +++ b/hw/i386/acpi-build.c
> >>> @@ -1055,9 +1055,21 @@ build_ssdt(GArray *table_data, GArray *linker,
> >>>
> >>>          {
> >>>              GArray *package = build_alloc_array();
> >>> -            uint8_t op = 0x13; /* VarPackageOp */
> >>> +            uint8_t op;
> >>> +
> >>> +            /*
> >>> +             * Note: The ability to create variable-sized packages was 
> >>> first
> introduced in ACPI 2.0. ACPI 1.0 only
> >>> +             * allowed fixed-size packages with up to 255 elements.
> >>> +             * Windows guests up to win2k8 fail when VarPackageOp is
> used.
> >>> +             */
> >>> +            if (acpi_cpus <= 255) {
> >>> +                op = 0x12; /* PackageOp */
> >>> +                build_append_byte(package, acpi_cpus); /*
> NumElements */
> >>> +            } else {
> >>> +                op = 0x13; /* VarPackageOp */
> >>> +                build_append_int(package, acpi_cpus); /*
> VarNumElements */
> >>> +            }
> >>>
> >>> -            build_append_int(package, acpi_cpus); /* VarNumElements
> */
> >>>              for (i = 0; i < acpi_cpus; i++) {
> >>>                  uint8_t b = test_bit(i, cpu->found_cpus) ? 0x01 : 0x00;
> >>>                  build_append_byte(package, b);
> >>>
> >>
> >> The patch will mask the problem for most of the cases, but when
> >> VarPackageOp is used, it will be broken just the same (because the
> >> ACPI revision in the SSDT header will still mismatch).
> >
> > yes but modern guests don't seem to care,
> 
> I disagree. I think this is exactly what causes the Windows boot
> problem.
> 
> > and it was already broken in
> > 1.7, wasn't it?
> 
> No, I don't think so. The ACPI revision in the SSDT table header stated
> ACPI 1.0 just the same, and the PackageOp + NumElements AML code was
> fully compliant with that ACPI spec revision.
> 
> (Or else I'm not getting what you're getting at.)
> 
> >
> >> Here's my proposal:
> >> - I can post a patch that changes the SSDT DSL files, *and* the DSDT
> >>   files (q35-acpi-dsdt.dsl acpi-dsdt.dsl), to state an ACPI revision
> >>   of 2.0. (The ACPI revision of the DSDT file determines integer
> >>   sizes for SSDTs too, so we can't just bump the SSDTs to 2.0)
> >
> > It should not be a problem but I'm not sure I get this comment. Can
> > you explain?
> 
> See
> 
>   19.5.28 DefinitionBlock (Declare Definition Block)
> 
> in the DSL chapter:
> 
>   Note: For compatibility with ACPI versions before ACPI 2.0, the bit
>   width of Integer objects is dependent on the ComplianceRevision of the
>   DSDT. If the ComplianceRevision is less than 2, all integers are
>   restricted to 32 bits. Otherwise, full 64-bit integers are used. The
>   version of the DSDT sets the global integer width for all integers,
>   including integers in SSDTs.
> 
> So, the ACPI revision in the DefinitionBlock()s must be kept in sync
> between DSDT and SSDT.
> 
> >
> >> - Or I suggest to revert my patches for 2.0.
> >>
> >> You probably won't like bumping the ACPI rev in DSDT/SSDT, for
> >> various compatibility reasons, so I think I suggest to revert these
> >> two patches of mine. It's now clear to me that this VCPU hotplug
> >> limit cannot be lifted without much more intrusive (and guest
> >> visible) changes. Sorry about missing this fact in my original
> >> submission.
> >>
> >> Thanks,
> >> Laszlo
> >
> > I have a problem with both approaches :)
> >
> > If we want to change ACPI rev, I think we should do this
> > conditionally when max_cpus > 255.
> > Would be worth it if this fixes some guests.
> 
> Two problems, one small, one bigger:
> - small: you'd have to patch the table header dynamically
> - bigger: ACPI revision stated in the DefinitionBlock() operator of the
>   DSL (ie. human readable source) might have an effect on the AML
>   generated by iasl. So if you compile the DSL for ACPI 1.0 with iasl,
>   then hot-patch the ACPI revision to 2.0 in the AML, some ACPI parsers
>   might find problems with the AML that has been compiled for 1.0, but
>   now has to be interpreted for 2.0.
> 
> >
> > As for reverting, I think it's a problem that we seem to
> > allow max_cpus = 256 but then it doesn't really work.
> 
> It's not about max_cpus. Let me rephrase your statement:
> 
>   As for reverting, I think it's a problem that we seem to allow a VCPU
>   with an APIC ID of 255 (which can occur dependent on VCPU topology,
>   and is only indirectly related to max_vcpus), but then hotplugging the
>   VCPU with APIC ID == 255 doesn't really work.
> 
> And yes, this is exactly the bug that my patches tried to fix.
> 
> >
> >
> >
> > I think the patch I posted might be good enough for 2.0.
> > It seems to make things work for new guests, and old guests
> > work as long as you don't specify max_cpus = 255.
> > The config with a high max_cpus value never really worked so
> > not a big deal.
> >
> >
> > Alternatively limit max_cpus to 255, to make it fail cleanly.
> >
> 
> Again, it's not about max_cpus (it's more about topology). But, you
> could be right; your patch would work as a stop-gap.
> 
> Thanks,
> Laszlo

reply via email to

[Prev in Thread] Current Thread [Next in Thread]