VirtualBox

Ignore:
Timestamp:
Feb 10, 2025 2:44:27 PM (12 days ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
167444
Message:

Devices/PC/DevACPI: Create the CPU hotplug variant SSDT on the fly and remove the static variant which got patched accordingly, bugref:10733

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/PC/ACPI/VBoxAcpi.cpp

    r108139 r108143  
    5151/* Statically compiled AML */
    5252#include <vboxaml.hex>
    53 #include <vboxssdt_cpuhotplug.hex>
    5453#ifdef VBOX_WITH_TPM
    5554# include <vboxssdt_tpm.hex>
     
    124123}
    125124
     125
    126126/**
    127  * Patch the CPU hot-plug SSDT version to
    128  * only contain the ACPI containers which may have a CPU
     127 * Creates the SSDT exposing configured CPUs as processor objects - hotplug variant.
     128 *
     129 * @returns VBox status code.
     130 * @param   pDevIns             The PDM device instance data.
     131 * @param   ppabAml             Where to store the pointer to the buffer containing the ACPI table on success.
     132 * @param   pcbAml              Where to store the size of the ACPI table in bytes on success.
     133 *
     134 * @note This replaces the old vbox-cpuhotplug.dsl which was patched accordingly.
    129135 */
    130 static int patchAmlCpuHotPlug(PPDMDEVINS pDevIns, uint8_t *pabAml, size_t cbAml)
     136static int acpiCreateCpuHotplugSsdt(PPDMDEVINS pDevIns, uint8_t **ppabAml, size_t *pcbAml)
    131137{
    132138    PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3;
     
    137143        return rc;
    138144
    139     /*
    140      * Now search AML for:
    141      *  AML_DEVICE_OP               (UINT16) 0x5b82
    142      * and replace whole block with
    143      *  AML_NOOP_OP                 (UINT16) 0xa3
    144      * for VCPU not configured
    145      */
    146     uint32_t idxAml = 0;
    147     while (idxAml < cbAml - 7)
    148     {
    149         /*
    150          * AML_DEVICE_OP
    151          *
    152          * DefDevice    := DeviceOp PkgLength NameString ObjectList
    153          * DeviceOp     := ExtOpPrefix 0x82
    154          */
    155         if (pabAml[idxAml] == 0x5b && pabAml[idxAml+1] == 0x82)
    156         {
    157             /* Check if the enclosed CPU device is configured. */
    158             uint8_t *pabAmlPkgLength = &pabAml[idxAml+2];
    159             uint32_t cBytes = 0;
    160             uint32_t cLengthBytesFollow = pabAmlPkgLength[0] >> 6;
    161 
    162             if (cLengthBytesFollow == 0)
    163             {
    164                 /* Simple package length */
    165                 cBytes = pabAmlPkgLength[0];
    166             }
    167             else
    168             {
    169                 unsigned idxLengthByte = 1;
    170 
    171                 cBytes = pabAmlPkgLength[0] & 0xF;
    172 
    173                 while (idxLengthByte <= cLengthBytesFollow)
    174                 {
    175                     cBytes |= pabAmlPkgLength[idxLengthByte] << (4*idxLengthByte);
    176                     idxLengthByte++;
    177                 }
    178             }
    179 
    180             uint8_t *pabAmlDevName = &pabAmlPkgLength[cLengthBytesFollow+1];
    181             uint8_t *pabAmlCpu     = &pabAmlDevName[4];
    182             bool fCpuConfigured = false;
    183 #ifdef RT_STRICT
    184             bool fCpuFound      = false;
    185 #endif
    186 
    187             if ((pabAmlDevName[0] != 'S') || (pabAmlDevName[1] != 'C') || (pabAmlDevName[2] != 'K'))
    188             {
    189                 /* false alarm, not named starting SCK */
    190                 idxAml++;
    191                 continue;
    192             }
    193 
    194             for (uint32_t idxAmlCpu = 0; idxAmlCpu < cBytes - 7; idxAmlCpu++)
    195             {
    196                 /*
    197                  * AML_PROCESSOR_OP
    198                  *
    199                  * DefProcessor := ProcessorOp PkgLength NameString ProcID
    200                                      PblkAddr PblkLen ObjectList
    201                  * ProcessorOp  := ExtOpPrefix 0x83
    202                  * ProcID       := ByteData
    203                  * PblkAddr     := DwordData
    204                  * PblkLen      := ByteData
    205                  */
    206                 if ((pabAmlCpu[idxAmlCpu] == 0x5b) && (pabAmlCpu[idxAmlCpu+1] == 0x83))
    207                 {
    208                     if ((pabAmlCpu[idxAmlCpu+4] != 'C') || (pabAmlCpu[idxAmlCpu+5] != 'P'))
    209                         /* false alarm, not named starting CP */
    210                         continue;
    211 
    212 #ifdef RT_STRICT
    213                     fCpuFound = true;
    214 #endif
    215 
    216                     /* Processor ID */
    217                     uint8_t const idAmlCpu = pabAmlCpu[idxAmlCpu + 8];
    218                     if (idAmlCpu < cCpus)
     145    RTACPITBL hAcpiTbl;
     146    rc = RTAcpiTblCreate(&hAcpiTbl, ACPI_TABLE_HDR_SIGNATURE_SSDT, 1, "VBOX  ", "VBOXCPUT", 2, "VBOX", RTBldCfgRevision());
     147    if (RT_SUCCESS(rc))
     148    {
     149        uint8_t const cCpuSuff = RT_ELEMENTS(g_achCpuSuff);
     150
     151        /* Declare externals */
     152        RTAcpiTblIfStart(hAcpiTbl);
     153            RTAcpiTblIntegerAppend(hAcpiTbl, 0);
     154
     155            RTAcpiTblExternalAppend(hAcpiTbl, "CPUC", kAcpiObjType_Unknown, 0 /*cArgs*/);
     156            RTAcpiTblExternalAppend(hAcpiTbl, "CPUL", kAcpiObjType_Unknown, 0 /*cArgs*/);
     157            RTAcpiTblExternalAppend(hAcpiTbl, "CPEV", kAcpiObjType_Unknown, 0 /*cArgs*/);
     158            RTAcpiTblExternalAppend(hAcpiTbl, "CPET", kAcpiObjType_Unknown, 0 /*cArgs*/);
     159
     160        RTAcpiTblIfFinalize(hAcpiTbl);
     161
     162        /* Define two helper methods. */
     163
     164        /* CPCK(Arg0) -> Boolean - Checks whether the CPU identified by the given indes is locked. */
     165        RTAcpiTblMethodStart(hAcpiTbl, "CPCK", 1 /*cArgs*/, RTACPI_METHOD_F_NOT_SERIALIZED, 0 /*uSyncLvl*/);
     166            RTAcpiTblStmtSimpleAppend(hAcpiTbl, kAcpiStmt_Store);
     167                RTAcpiTblArgOpAppend(hAcpiTbl, 0);
     168                RTAcpiTblNameStringAppend(hAcpiTbl, "CPUC");
     169
     170            RTAcpiTblStmtSimpleAppend(hAcpiTbl, kAcpiStmt_Return);
     171                    RTAcpiTblBinaryOpAppend(hAcpiTbl, kAcpiBinaryOp_LEqual);
     172                        RTAcpiTblNameStringAppend(hAcpiTbl, "CPUL");
     173                        RTAcpiTblIntegerAppend(hAcpiTbl, 1);
     174        RTAcpiTblMethodFinalize(hAcpiTbl);
     175
     176        /* CPLO(Arg0) -> Nothing - Unlocks the CPU identified by the given index. */
     177        RTAcpiTblMethodStart(hAcpiTbl, "CPLO", 1 /*cArgs*/, RTACPI_METHOD_F_NOT_SERIALIZED, 0 /*uSyncLvl*/);
     178            RTAcpiTblStmtSimpleAppend(hAcpiTbl, kAcpiStmt_Store);
     179                RTAcpiTblArgOpAppend(hAcpiTbl, 0);
     180                RTAcpiTblNameStringAppend(hAcpiTbl, "CPUL");
     181        RTAcpiTblMethodFinalize(hAcpiTbl);
     182
     183        /* Define all configured CPUs. */
     184        RTAcpiTblScopeStart(hAcpiTbl, "\\_SB");
     185        for (uint16_t i = 0; i < cCpus; i++)
     186        {
     187            RTAcpiTblDeviceStartF(hAcpiTbl, "SC%c%c", i < cCpuSuff ? 'K' : 'L', g_achCpuSuff[i % cCpuSuff]);
     188
     189                RTAcpiTblNameAppend(hAcpiTbl, "_HID");
     190                    RTAcpiTblStringAppend(hAcpiTbl, "ACPI0004");
     191                RTAcpiTblNameAppend(hAcpiTbl, "_UID");
     192                    RTAcpiTblStringAppendF(hAcpiTbl, "SCKCP%c%c", i < cCpuSuff ? 'U' : 'V', g_achCpuSuff[i % cCpuSuff]);
     193
     194                RTAcpiTblProcessorStartF(hAcpiTbl, i /*bProcId*/, 0 /*u32PBlkAddr*/, 0 /*cbPBlk*/, "CP%c%c",
     195                                         i < cCpuSuff ? 'U' : 'V',
     196                                         g_achCpuSuff[i % cCpuSuff]);
     197
     198                    RTAcpiTblNameAppend(hAcpiTbl, "_HID");
     199                        RTAcpiTblStringAppend(hAcpiTbl, "ACPI0007");
     200                    RTAcpiTblNameAppend(hAcpiTbl, "_UID");
     201                        RTAcpiTblIntegerAppend(hAcpiTbl, i);
     202                    RTAcpiTblNameAppend(hAcpiTbl, "_PXM");
     203                        RTAcpiTblIntegerAppend(hAcpiTbl, 0);
     204
     205                    uint8_t abBufApic[8] = { 0x00, 0x08, (uint8_t)i, (uint8_t)i, 0, 0, 0, 0};
     206                    RTAcpiTblNameAppend(hAcpiTbl, "APIC");
     207                        RTAcpiTblBufferAppend(hAcpiTbl, &abBufApic[0], sizeof(abBufApic));
     208
     209                    /* _MAT Method. */
     210                    RTAcpiTblMethodStart(hAcpiTbl, "_MAT", 0 /*cArgs*/, RTACPI_METHOD_F_SERIALIZED, 0 /*uSyncLvl*/);
     211                        RTAcpiTblIfStart(hAcpiTbl);
     212                            RTAcpiTblNameStringAppend(hAcpiTbl, "CPCK");
     213                                RTAcpiTblIntegerAppend(hAcpiTbl, i);
     214
     215                            RTAcpiTblStmtSimpleAppend(hAcpiTbl, kAcpiStmt_Store);
     216                                RTAcpiTblIntegerAppend(hAcpiTbl, 1);
     217                                RTAcpiTblStmtSimpleAppend(hAcpiTbl, kAcpiStmt_Index);
     218                                    RTAcpiTblNameStringAppend(hAcpiTbl, "APIC");
     219                                    RTAcpiTblIntegerAppend(hAcpiTbl, 4);
     220                                    RTAcpiTblNullNameAppend(hAcpiTbl);
     221 
     222                        RTAcpiTblIfFinalize(hAcpiTbl);
     223                        RTAcpiTblElseStart(hAcpiTbl);
     224                        RTAcpiTblElseFinalize(hAcpiTbl);
     225
     226                        RTAcpiTblStmtSimpleAppend(hAcpiTbl, kAcpiStmt_Return);
     227                            RTAcpiTblNameStringAppend(hAcpiTbl, "APIC");
     228                    RTAcpiTblMethodFinalize(hAcpiTbl);
     229
     230                    /* _STA Method. */
     231                    RTAcpiTblMethodStart(hAcpiTbl, "_STA", 0 /*cArgs*/, RTACPI_METHOD_F_NOT_SERIALIZED, 0 /*uSyncLvl*/);
     232                        RTAcpiTblIfStart(hAcpiTbl);
     233                            RTAcpiTblNameStringAppend(hAcpiTbl, "CPCK");
     234                                RTAcpiTblIntegerAppend(hAcpiTbl, i);
     235
     236                            RTAcpiTblStmtSimpleAppend(hAcpiTbl, kAcpiStmt_Return);
     237                                RTAcpiTblIntegerAppend(hAcpiTbl, 0xf);
     238                        RTAcpiTblIfFinalize(hAcpiTbl);
     239                        RTAcpiTblElseStart(hAcpiTbl);
     240                            RTAcpiTblStmtSimpleAppend(hAcpiTbl, kAcpiStmt_Return);
     241                                RTAcpiTblIntegerAppend(hAcpiTbl, 0x0);
     242                        RTAcpiTblElseFinalize(hAcpiTbl);
     243                    RTAcpiTblMethodFinalize(hAcpiTbl);
     244
     245                    /* _EJ0 Method. */
     246                    RTAcpiTblMethodStart(hAcpiTbl, "_EJ0", 1 /*cArgs*/, RTACPI_METHOD_F_NOT_SERIALIZED, 0 /*uSyncLvl*/);
     247                        RTAcpiTblNameStringAppend(hAcpiTbl, "CPLO");
     248                            RTAcpiTblIntegerAppend(hAcpiTbl, i);
     249                        RTAcpiTblStmtSimpleAppend(hAcpiTbl, kAcpiStmt_Return);
     250                    RTAcpiTblMethodFinalize(hAcpiTbl);
     251
     252                RTAcpiTblProcessorFinalize(hAcpiTbl);
     253
     254            rc = RTAcpiTblDeviceFinalize(hAcpiTbl);
     255            if (RT_FAILURE(rc))
     256                break;
     257        }
     258
     259        if (RT_SUCCESS(rc))
     260        {
     261            RTAcpiTblScopeFinalize(hAcpiTbl);
     262
     263            /* Now the _GPE scope where event processing takes place. */
     264            RTAcpiTblScopeStart(hAcpiTbl, "\\_GPE");
     265                RTAcpiTblMethodStart(hAcpiTbl, "_L01", 0 /*cArgs*/, RTACPI_METHOD_F_NOT_SERIALIZED, 0 /*uSyncLvl*/);
     266
     267                    RTAcpiTblStmtSimpleAppend(hAcpiTbl, kAcpiStmt_Store);
     268                        RTAcpiTblNameStringAppend(hAcpiTbl, "CPEV");
     269                        RTAcpiTblLocalOpAppend(hAcpiTbl, 0);
     270
     271                    RTAcpiTblStmtSimpleAppend(hAcpiTbl, kAcpiStmt_Store);
     272                        RTAcpiTblNameStringAppend(hAcpiTbl, "CPET");
     273                        RTAcpiTblLocalOpAppend(hAcpiTbl, 1);
     274
     275                    for (uint16_t i = 0; i < cCpus; i++)
    219276                    {
    220                         LogFlow(("CPU %u is configured\n", idAmlCpu));
    221                         fCpuConfigured = true;
     277                        RTAcpiTblIfStart(hAcpiTbl);
     278                            RTAcpiTblBinaryOpAppend(hAcpiTbl, kAcpiBinaryOp_LEqual);
     279                                RTAcpiTblLocalOpAppend(hAcpiTbl, 0);
     280                                RTAcpiTblIntegerAppend(hAcpiTbl, i);
     281
     282                            RTAcpiTblStmtSimpleAppend(hAcpiTbl, kAcpiStmt_Notify);
     283                                RTAcpiTblNameStringAppendF(hAcpiTbl, "\\_SB.SC%c%c.CP%c%c",
     284                                                           i < cCpuSuff ? 'K' : 'L',
     285                                                           g_achCpuSuff[i % cCpuSuff],
     286                                                           i < cCpuSuff ? 'U' : 'V',
     287                                                           g_achCpuSuff[i % cCpuSuff]);
     288                                RTAcpiTblLocalOpAppend(hAcpiTbl, 1);
     289                        rc = RTAcpiTblIfFinalize(hAcpiTbl);
     290                        if (RT_FAILURE(rc))
     291                            break;
    222292                    }
    223                     else
    224                     {
    225                         LogFlow(("CPU %u is not configured\n", idAmlCpu));
    226                         fCpuConfigured = false;
    227                     }
    228                     break;
    229                 }
    230             }
    231 
    232             Assert(fCpuFound);
    233 
    234             if (!fCpuConfigured)
    235             {
    236                 /* Will fill unwanted CPU block with NOOPs */
    237                 /*
    238                  * See 18.2.4 Package Length Encoding in ACPI spec
    239                  * for full format
    240                  */
    241 
    242                 /* including AML_DEVICE_OP itself */
    243                 for (uint32_t j = 0; j < cBytes + 2; j++)
    244                     pabAml[idxAml+j] = 0xa3;
    245             }
    246 
    247             idxAml++;
     293
     294                RTAcpiTblMethodFinalize(hAcpiTbl);
     295            RTAcpiTblScopeFinalize(hAcpiTbl);
     296        }
     297
     298        rc = RTAcpiTblFinalize(hAcpiTbl);
     299        if (RT_SUCCESS(rc))
     300        {
     301            rc = RTAcpiTblDumpToBufferA(hAcpiTbl, RTACPITBLTYPE_AML, ppabAml, pcbAml);
     302            if (RT_FAILURE(rc))
     303                rc = PDMDEV_SET_ERROR(pDevIns, rc, N_("ACPI error: Failed to dump CPU SSDT"));
    248304        }
    249305        else
    250             idxAml++;
    251     }
    252 
    253     /* now recompute checksum, whole file byte sum must be 0 */
    254     pabAml[9] = 0;
    255     uint8_t         bSum = 0;
    256     for (uint32_t i = 0; i < cbAml; i++)
    257       bSum = bSum + pabAml[i];
    258     pabAml[9] = (uint8_t)(0 - bSum);
    259 
    260     return VINF_SUCCESS;
     306            rc = PDMDEV_SET_ERROR(pDevIns, rc, N_("ACPI error: Failed to finalize CPU SSDT"));
     307
     308        RTAcpiTblDestroy(hAcpiTbl);
     309    }
     310    else
     311        rc = PDMDEV_SET_ERROR(pDevIns, rc, N_("ACPI error: Failed to create CPU SSDT"));
     312
     313    return rc;
    261314}
    262315
     
    390443        {
    391444            if (fCpuHotPlug)
    392             {
    393                 cbAmlCodeSsdt  = sizeof(AmlCodeSsdtCpuHotPlug);
    394                 pabAmlCodeSsdt = (uint8_t *)RTMemDup(AmlCodeSsdtCpuHotPlug, sizeof(AmlCodeSsdtCpuHotPlug));
    395                 if (pabAmlCodeSsdt)
    396                     patchAmlCpuHotPlug(pDevIns, pabAmlCodeSsdt, cbAmlCodeSsdt);
    397                 else
    398                     rc = VERR_NO_MEMORY;
    399             }
     445                rc = acpiCreateCpuHotplugSsdt(pDevIns, &pabAmlCodeSsdt, &cbAmlCodeSsdt);
    400446            else
    401447                rc = acpiCreateCpuSsdt(pDevIns, &pabAmlCodeSsdt, &cbAmlCodeSsdt);
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette