From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-wm1-f66.google.com (mail-wm1-f66.google.com [209.85.128.66]) by mx.groups.io with SMTP id smtpd.web11.14466.1583157927501306013 for ; Mon, 02 Mar 2020 06:05:28 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@linaro.org header.s=google header.b=UmU/3SfO; spf=pass (domain: linaro.org, ip: 209.85.128.66, mailfrom: ard.biesheuvel@linaro.org) Received: by mail-wm1-f66.google.com with SMTP id i10so14009797wmd.1 for ; Mon, 02 Mar 2020 06:05:27 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc:content-transfer-encoding; bh=tXIe5aodJMlW3CL+GpER+RRPDgEr+m8z5M5DJL/R1nk=; b=UmU/3SfOeR5uc9GorY0Co0C0ck8ce7zNXGUvs3/3mb3GZAwLx77l9PJ0UtXJmzptbi 6fIHeO2o3UyYqpGs2g2qiHAFl1hIqeA6znYssDY8fso2iH969DdP2xxlc5pNN855Ed8t I2tCrwWRnFVeA0jaG5DN35IMHaOuYN9iEhbgTfAsaKiNFaEsgK0gbtQIkXDP2F+jwJxq /thHXAHoq+BIKe+0xs3eUK8DVl88g4HkCYA7knfIvcUo1VwRfyZ3vEVytkSYejKZOsJ7 HGCgeSiYH53seomwk2mv/pv1wDWuOGs3pFemms/dPUuJRh1WeFgVx3Pf4LOFnD1mknMC ivVw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc:content-transfer-encoding; bh=tXIe5aodJMlW3CL+GpER+RRPDgEr+m8z5M5DJL/R1nk=; b=ETCNcsSPpP1N3PTYlS3N411YhCLQ3ubelLt00qTTzUX+8iix8TJw+07Shxrb7vHvmk FjXewqwVsyMQnvBfBapC6aLMFnTiIf+hibvt2rbXzyI5AA4EpLNBtiKkORPAeuvhw4SL O+K8G8i+AavveQqyDuPqug4AOGnCv61Ma7HDCcgXIl4Ye3QowuRkS28Q7yhn8DJlQJNR zy40hIMySoWiJUoVbGbcfeKMjf5PVHTO0C0KlbDLKokwkh+6fgRCp4q2hcqG+7xP0+Wc urBTUYC9NzDZP8Wh+i0OETq9DTg68i+PcnlP/NAyVkUyuDWmrYwKLkK9/+WLQ4d5zH6h 5Cxw== X-Gm-Message-State: APjAAAUqwdaUT76q9GzK8e19jwxmbHwf3vf0k6T3G+G7Pi6gygOItkRV /lpWL5X0HlU9j10VV4z+8lPGNL6w29JdS8QWpwOygA== X-Google-Smtp-Source: APXvYqzd7hCgJWR2CXaljfewtzIJn8/kKgbWr/s/3eHcAvb3rD+veBewbNggqkCsmSPkbwOYL6I0md3W+ERkdHaXJLs= X-Received: by 2002:a7b:cb93:: with SMTP id m19mr20955930wmi.133.1583157925939; Mon, 02 Mar 2020 06:05:25 -0800 (PST) MIME-Version: 1.0 References: <20200226221156.29589-1-lersek@redhat.com> <20200226221156.29589-14-lersek@redhat.com> In-Reply-To: <20200226221156.29589-14-lersek@redhat.com> From: "Ard Biesheuvel" Date: Mon, 2 Mar 2020 15:05:15 +0100 Message-ID: Subject: Re: [PATCH v2 13/16] OvmfPkg/CpuHotplugSmm: complete root MMI handler for CPU hotplug To: Laszlo Ersek Cc: edk2-devel-groups-io , Igor Mammedov , Jiewen Yao , Jordan Justen , Michael Kinney , =?UTF-8?Q?Philippe_Mathieu=2DDaud=C3=A9?= Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable On Wed, 26 Feb 2020 at 23:12, Laszlo Ersek wrote: > > With the help of the Post-SMM Pen and the SMBASE relocation functions > added in the previous patches, we can now complete the root MMI handler > for CPU hotplug. > > In the driver's entry point function: > > - allocate the pen (in a reserved page in normal RAM), > > - install the default ("first") SMI handler for hot-added CPUs (which > includes priming the exchange area between the MM Monarch and the > hot-added CPUs, i.e., shutting the APIC ID gate). > > In the root MMI handler, for each hot-added CPU: > > - record the APIC ID of the new CPU in CPU_HOT_PLUG_DATA, > > - relocate the SMBASE of the new CPU, > > - inform PiSmmCpuDxeSmm by calling > EFI_SMM_CPU_SERVICE_PROTOCOL.AddProcessor(). > > Cc: Ard Biesheuvel > Cc: Igor Mammedov > Cc: Jiewen Yao > Cc: Jordan Justen > Cc: Michael Kinney > Cc: Philippe Mathieu-Daud=C3=A9 > Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=3D1512 > Signed-off-by: Laszlo Ersek > Acked-by: Ard Biesheuvel Reviewed-by: Ard Biesheuvel > --- > > Notes: > v2: > > - Pick up Ard's Acked-by, which is conditional on approval from Intel > reviewers on Cc. (I'd like to save Ard the churn of re-acking > unmodified patches.) > > - repeat all the v1 tests > > v1: > > (1) At this stage, CPU hotplug with SMM works. > > Test CPU topology (libvirt domain XML snippet): > > > > > > > > > > > > > > > The firmware logs the following during normal boot: > > > SmbaseAllocatePostSmmPen: Post-SMM Pen at 0x9F000 > > CPU hotplug command on the host side: > > > virsh setvcpu ovmf.fedora.q35 1 --enable --live > > Firmware log in response: > > > QemuCpuhpCollectApicIds: CurrentSelector=3D1: insert > > QemuCpuhpCollectApicIds: ApicId=3D0x00000001 > > QemuCpuhpCollectApicIds: CurrentSelector=3D2 PendingSelector=3D1: > > wrap-around > > QemuCpuhpCollectApicIds: PluggedCount=3D1 ToUnplugCount=3D0 > > CpuHotplugMmi: hot-added APIC ID 0x00000001, SMBASE 0x7D082000, > > EFI_SMM_CPU_SERVICE_PROTOCOL assigned number 2 > > Query the CPU register state on the host side (without onlining the > hot-added CPU in the OS just yet): > > > virsh qemu-monitor-command ovmf.fedora.q35 --hmp 'info registers -a= ' > > Output, confirming penned status (pen at 0x9F000): > > > CPU#1 > > EAX=3D00009f00 EBX=3D00000000 ECX=3D00000000 EDX=3D00000600 > > ESI=3D00000000 EDI=3D00000000 EBP=3D00000000 ESP=3D00000000 > > EIP=3D0000000c EFL=3D00000002 [-------] CPL=3D0 II=3D0 A20=3D1 SMM= =3D0 HLT=3D1 > > ES =3D0000 00000000 0000ffff 00009300 > > CS =3D9f00 0009f000 0000ffff 00009b00 > > SS =3D0000 00000000 0000ffff 00009300 > > DS =3D9f00 0009f000 0000ffff 00009300 > > FS =3D0000 00000000 0000ffff 00009300 > > GS =3D0000 00000000 0000ffff 00009300 > > LDT=3D0000 00000000 0000ffff 00008200 > > TR =3D0000 00000000 0000ffff 00008b00 > > GDT=3D 00000000 0000ffff > > IDT=3D 00000000 0000ffff > > CR0=3D60000010 CR2=3D00000000 CR3=3D00000000 CR4=3D00000000 > > DR0=3D0000000000000000 DR1=3D0000000000000000 DR2=3D000000000000000= 0 > > DR3=3D0000000000000000 > > DR6=3D00000000ffff0ff0 DR7=3D0000000000000400 > > EFER=3D0000000000000000 > > FCW=3D037f FSW=3D0000 [ST=3D0] FTW=3D00 MXCSR=3D00001f80 > > FPR0=3D0000000000000000 0000 FPR1=3D0000000000000000 0000 > > FPR2=3D0000000000000000 0000 FPR3=3D0000000000000000 0000 > > FPR4=3D0000000000000000 0000 FPR5=3D0000000000000000 0000 > > FPR6=3D0000000000000000 0000 FPR7=3D0000000000000000 0000 > > XMM00=3D00000000000000000000000000000000 > > XMM01=3D00000000000000000000000000000000 > > XMM02=3D00000000000000000000000000000000 > > XMM03=3D00000000000000000000000000000000 > > XMM04=3D00000000000000000000000000000000 > > XMM05=3D00000000000000000000000000000000 > > XMM06=3D00000000000000000000000000000000 > > XMM07=3D00000000000000000000000000000000 > > Additionally, the dmesg in the Linux guest contains: > > > CPU2 has been hot-added > > We can now boot the hot-addad CPU in the Linux guest: > > > echo 1 > /sys/devices/system/cpu/cpu2/online > > Dmesg in response: > > > smpboot: Booting Node 0 Processor 2 APIC 0x1 > > kvm-clock: cpu 2, msr 6e01081, secondary cpu clock > > KVM setup async PF for cpu 2 > > kvm-stealtime: cpu 2, msr 7b52a040 > > Will online and init hotplugged CPU: 2 > > Still in the guest, call UEFI variable services on each CPU (includin= g > the hot-added one), per > : > > > taskset -c 0 efibootmgr > > taskset -c 1 efibootmgr > > taskset -c 2 efibootmgr > > No delays, no instability. > > Having booted the hot-added CPU in the Linux guest, the host-side > command > > > virsh qemu-monitor-command ovmf.fedora.q35 --hmp 'info registers -a= ' > > now shows: > > > CPU#1 > > RAX=3Dffffffffb39e4b50 RBX=3D0000000000000002 RCX=3D000000000000000= 0 > > RDX=3D0000000000000002 > > RSI=3D0000000000000002 RDI=3Dffff932cbb51c520 RBP=3D000000000000000= 2 > > RSP=3Dffffbc5bc0083eb0 > > R8 =3D000000cd42e4dffb R9 =3D0000005a22502599 R10=3D0000005a2250259= 9 > > R11=3D0000005a22502599 > > R12=3Dffff932cbae25dc0 R13=3D0000000000000000 R14=3D000000000000000= 0 > > R15=3Dffff932cbae25dc0 > > RIP=3Dffffffffb39e4f2e RFL=3D00000246 [---Z-P-] CPL=3D0 II=3D0 A20= =3D1 SMM=3D0 > > HLT=3D1 > > ES =3D0000 0000000000000000 ffffffff 00c00000 > > CS =3D0010 0000000000000000 ffffffff 00a09b00 DPL=3D0 CS64 [-RA] > > SS =3D0018 0000000000000000 ffffffff 00c09300 DPL=3D0 DS [-WA] > > DS =3D0000 0000000000000000 ffffffff 00c00000 > > FS =3D0000 0000000000000000 ffffffff 00c00000 > > GS =3D0000 ffff932cbb500000 ffffffff 00c00000 > > LDT=3D0000 0000000000000000 000fffff 00000000 > > TR =3D0040 fffffe0000069000 0000206f 00008b00 DPL=3D0 TSS64-busy > > GDT=3D fffffe0000067000 0000007f > > IDT=3D fffffe0000000000 00000fff > > CR0=3D80050033 CR2=3D00007f54893cbf20 CR3=3D0000000078418001 CR4=3D= 001606e0 > > DR0=3D0000000000000000 DR1=3D0000000000000000 DR2=3D000000000000000= 0 > > DR3=3D0000000000000000 > > DR6=3D00000000ffff0ff0 DR7=3D0000000000000400 > > EFER=3D0000000000000d01 > > FCW=3D037f FSW=3D0000 [ST=3D0] FTW=3D00 MXCSR=3D00001fa0 > > FPR0=3D0000000000000000 0000 FPR1=3D0000000000000000 0000 > > FPR2=3D0000000000000000 0000 FPR3=3D0000000000000000 0000 > > FPR4=3D0000000000000000 0000 FPR5=3D0000000000000000 0000 > > FPR6=3D0000000000000000 0000 FPR7=3D0000000000000000 0000 > > XMM00=3D000000000000000040ed2be000000000 > > XMM01=3D0000000000000000404ddf1a9fbe76c9 > > XMM02=3D00000000000000000000000000000000 > > XMM03=3D00000000000000000000000000000000 > > XMM04=3D00000000000000003ff0000000000000 > > XMM05=3D00000000000000000000000000000000 > > XMM06=3D00000000000000004078002d0ac487b7 > > XMM07=3D0000000000000000404ddf1a9fbe76c9 > > XMM08=3D72223d444955412022746f6f72223d44 > > XMM09=3D00000000000000000000000000000000 > > XMM10=3D00000000000000000000000000000000 > > XMM11=3D00000000000000000000000000000000 > > XMM12=3D00000000000000000000000000000000 > > XMM13=3D00000000000000000000000000000000 > > XMM14=3D00000000000000000000000000000000 > > XMM15=3D00000000000000000000000000000000 > > Hotplug another CPU: > > > virsh setvcpu ovmf.fedora.q35 3 --enable --live > > Firmware log in response: > > > QemuCpuhpCollectApicIds: CurrentSelector=3D3: insert > > QemuCpuhpCollectApicIds: ApicId=3D0x00000003 > > QemuCpuhpCollectApicIds: PluggedCount=3D1 ToUnplugCount=3D0 > > CpuHotplugMmi: hot-added APIC ID 0x00000003, SMBASE 0x7D084000, > > EFI_SMM_CPU_SERVICE_PROTOCOL assigned number 3 > > Online the hot-added CPU in the Linux guest: > > > echo 1 > /sys/devices/system/cpu/cpu3/online > > Guest dmesg in response: > > > smpboot: Booting Node 0 Processor 3 APIC 0x3 > > kvm-clock: cpu 3, msr 6e010c1, secondary cpu clock > > KVM setup async PF for cpu 3 > > kvm-stealtime: cpu 3, msr 7b5aa040 > > Will online and init hotplugged CPU: 3 > > (2) Alternative order of actions: > > Hotplug both CPUs first, on the host: > > > virsh setvcpu ovmf.fedora.q35 1 --enable --live > > virsh setvcpu ovmf.fedora.q35 3 --enable --live > > *then* online both hot-added CPUs in the Linux guest: > > > echo 1 > /sys/devices/system/cpu/cpu2/online > > echo 1 > /sys/devices/system/cpu/cpu3/online > > The only difference here is that the broadcast SMI for the second > hotplug finds the first hotplugged CPU still in the pen (i.e., not > onlined by Linux). There is no difference in observable behavior (bey= ond > the matching log messages and register dumps). > > (3) What doesn't work yet: > > - CPU hotplug w/ SMM in SEV guests. > > See . > > (NB. I'm uncertain if CPU hotplug works in SEV guests without > SMM_REQUIRE to begin with.) > > - S3 resume w/ SMM after hot-adding a CPU. > > The remaining patches in the series take care of that. (Only in the > absence of SEV; SEV+S3 looks broken regardless of hotplug.) > > - CPU hot-unplug w/ SMM. > > Needs separate investigation. EFI_SMM_REMOVE_PROCESSOR in > "UefiCpuPkg/Include/Protocol/SmmCpuService.h" is documented as > follows: "After this API is called, the removed processor must not > respond to SMIs in the coherence domain". This could raise challeng= ing > ordering questions between QEMU, the firmware, and the OS. > > OvmfPkg/CpuHotplugSmm/CpuHotplug.c | 97 +++++++++++++++++++- > 1 file changed, 95 insertions(+), 2 deletions(-) > > diff --git a/OvmfPkg/CpuHotplugSmm/CpuHotplug.c b/OvmfPkg/CpuHotplugSmm/C= puHotplug.c > index 42e023cb85c0..20e6bec04f41 100644 > --- a/OvmfPkg/CpuHotplugSmm/CpuHotplug.c > +++ b/OvmfPkg/CpuHotplugSmm/CpuHotplug.c > @@ -1,76 +1,82 @@ > /** @file > Root SMI handler for VCPU hotplug SMIs. > > Copyright (c) 2020, Red Hat, Inc. > > SPDX-License-Identifier: BSD-2-Clause-Patent > **/ > > #include // CPU_HOT_PLUG_DATA > #include // ICH9_APM_CNT > #include // QEMU_CPUHP_CMD_GET_PENDI= NG > #include // CpuDeadLoop() > #include // ASSERT() > #include // gMmst > #include // PcdGetBool() > #include // SafeUintnSub() > #include // EFI_MM_CPU_IO_PROTOCOL > #include // EFI_SMM_CPU_SERVICE_PROT= OCOL > #include // EFI_STATUS > > #include "ApicId.h" // APIC_ID > #include "QemuCpuhp.h" // QemuCpuhpWriteCpuSelecto= r() > +#include "Smbase.h" // SmbaseAllocatePostSmmPen= () > > // > // We use this protocol for accessing IO Ports. > // > STATIC EFI_MM_CPU_IO_PROTOCOL *mMmCpuIo; > // > // The following protocol is used to report the addition or removal of a= CPU to > // the SMM CPU driver (PiSmmCpuDxeSmm). > // > STATIC EFI_SMM_CPU_SERVICE_PROTOCOL *mMmCpuService; > // > // This structure is a communication side-channel between the > // EFI_SMM_CPU_SERVICE_PROTOCOL consumer (i.e., this driver) and provide= r > // (i.e., PiSmmCpuDxeSmm). > // > STATIC CPU_HOT_PLUG_DATA *mCpuHotPlugData; > // > // SMRAM arrays for fetching the APIC IDs of processors with pending eve= nts (of > // known event types), for the time of just one MMI. > // > // The lifetimes of these arrays match that of this driver only because = we > // don't want to allocate SMRAM at OS runtime, and potentially fail (or > // fragment the SMRAM map). > // > // These arrays provide room for ("possible CPU count" minus one) APIC I= Ds > // each, as we don't expect every possible CPU to appear, or disappear, = in a > // single MMI. The numbers of used (populated) elements in the arrays ar= e > // determined on every MMI separately. > // > STATIC APIC_ID *mPluggedApicIds; > STATIC APIC_ID *mToUnplugApicIds; > // > +// Address of the non-SMRAM reserved memory page that contains the Post-= SMM Pen > +// for hot-added CPUs. > +// > +STATIC UINT32 mPostSmmPenAddress; > +// > // Represents the registration of the CPU Hotplug MMI handler. > // > STATIC EFI_HANDLE mDispatchHandle; > > > /** > CPU Hotplug MMI handler function. > > This is a root MMI handler. > > @param[in] DispatchHandle The unique handle assigned to this hand= ler by > EFI_MM_SYSTEM_TABLE.MmiHandlerRegister(= ). > > @param[in] Context Context passed in by > EFI_MM_SYSTEM_TABLE.MmiManage(). Due to > CpuHotplugMmi() being a root MMI handle= r, > Context is ASSERT()ed to be NULL. > > @param[in,out] CommBuffer Ignored, due to CpuHotplugMmi() being a= root > MMI handler. > > @param[in,out] CommBufferSize Ignored, due to CpuHotplugMmi() being a= root > @@ -97,44 +103,46 @@ STATIC EFI_HANDLE mDispatchHandle; > > @retval EFI_WARN_INTERRUPT_SOURCE_PENDING The MMI source is still pe= nding, > and other handlers should = still > be called. > > @retval EFI_INTERRUPT_PENDING The MMI source could not b= e > quiesced. > **/ > STATIC > EFI_STATUS > EFIAPI > CpuHotplugMmi ( > IN EFI_HANDLE DispatchHandle, > IN CONST VOID *Context OPTIONAL, > IN OUT VOID *CommBuffer OPTIONAL, > IN OUT UINTN *CommBufferSize OPTIONAL > ) > { > EFI_STATUS Status; > UINT8 ApmControl; > UINT32 PluggedCount; > UINT32 ToUnplugCount; > + UINT32 PluggedIdx; > + UINT32 NewSlot; > > // > // Assert that we are entering this function due to our root MMI handl= er > // registration. > // > ASSERT (DispatchHandle =3D=3D mDispatchHandle); > // > // When MmiManage() is invoked to process root MMI handlers, the calle= r (the > // MM Core) is expected to pass in a NULL Context. MmiManage() then pa= sses > // the same NULL Context to individual handlers. > // > ASSERT (Context =3D=3D NULL); > // > // Read the MMI command value from the APM Control Port, to see if thi= s is an > // MMI we should care about. > // > Status =3D mMmCpuIo->Io.Read (mMmCpuIo, MM_IO_UINT8, ICH9_APM_CNT, 1, > &ApmControl); > if (EFI_ERROR (Status)) { > DEBUG ((DEBUG_ERROR, "%a: failed to read ICH9_APM_CNT: %r\n", __FUNC= TION__, > Status)); > // > @@ -152,49 +160,116 @@ CpuHotplugMmi ( > > // > // Collect the CPUs with pending events. > // > Status =3D QemuCpuhpCollectApicIds ( > mMmCpuIo, > mCpuHotPlugData->ArrayLength, // PossibleCpuCount > mCpuHotPlugData->ArrayLength - 1, // ApicIdCount > mPluggedApicIds, > &PluggedCount, > mToUnplugApicIds, > &ToUnplugCount > ); > if (EFI_ERROR (Status)) { > goto Fatal; > } > if (ToUnplugCount > 0) { > DEBUG ((DEBUG_ERROR, "%a: hot-unplug is not supported yet\n", > __FUNCTION__)); > goto Fatal; > } > > + // > + // Process hot-added CPUs. > + // > + // The Post-SMM Pen need not be reinstalled multiple times within a si= ngle > + // root MMI handling. Even reinstalling once per root MMI is only prud= ence; > + // in theory installing the pen in the driver's entry point function s= hould > + // suffice. > + // > + SmbaseReinstallPostSmmPen (mPostSmmPenAddress); > + > + PluggedIdx =3D 0; > + NewSlot =3D 0; > + while (PluggedIdx < PluggedCount) { > + APIC_ID NewApicId; > + UINTN NewProcessorNumberByProtocol; > + > + NewApicId =3D mPluggedApicIds[PluggedIdx]; > + // > + // Find the first empty slot in CPU_HOT_PLUG_DATA. > + // > + while (NewSlot < mCpuHotPlugData->ArrayLength && > + mCpuHotPlugData->ApicId[NewSlot] !=3D MAX_UINT64) { > + NewSlot++; > + } > + if (NewSlot =3D=3D mCpuHotPlugData->ArrayLength) { > + DEBUG ((DEBUG_ERROR, "%a: no room for APIC ID " FMT_APIC_ID "\n", > + __FUNCTION__, NewApicId)); > + goto Fatal; > + } > + > + // > + // Store the APIC ID of the new processor to the slot. > + // > + mCpuHotPlugData->ApicId[NewSlot] =3D NewApicId; > + > + // > + // Relocate the SMBASE of the new CPU. > + // > + Status =3D SmbaseRelocate (NewApicId, mCpuHotPlugData->SmBase[NewSlo= t], > + mPostSmmPenAddress); > + if (EFI_ERROR (Status)) { > + goto RevokeNewSlot; > + } > + > + // > + // Add the new CPU with EFI_SMM_CPU_SERVICE_PROTOCOL. > + // > + Status =3D mMmCpuService->AddProcessor (mMmCpuService, NewApicId, > + &NewProcessorNumberByProtocol); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a: AddProcessor(" FMT_APIC_ID "): %r\n", > + __FUNCTION__, NewApicId, Status)); > + goto RevokeNewSlot; > + } > + > + DEBUG ((DEBUG_INFO, "%a: hot-added APIC ID " FMT_APIC_ID ", SMBASE 0= x%Lx, " > + "EFI_SMM_CPU_SERVICE_PROTOCOL assigned number %Lu\n", __FUNCTION__= , > + NewApicId, (UINT64)mCpuHotPlugData->SmBase[NewSlot], > + (UINT64)NewProcessorNumberByProtocol)); > + > + NewSlot++; > + PluggedIdx++; > + } > + > // > // We've handled this MMI. > // > return EFI_SUCCESS; > > +RevokeNewSlot: > + mCpuHotPlugData->ApicId[NewSlot] =3D MAX_UINT64; > + > Fatal: > ASSERT (FALSE); > CpuDeadLoop (); > // > // We couldn't handle this MMI. > // > return EFI_INTERRUPT_PENDING; > } > > > // > // Entry point function of this driver. > // > EFI_STATUS > EFIAPI > CpuHotplugEntry ( > IN EFI_HANDLE ImageHandle, > IN EFI_SYSTEM_TABLE *SystemTable > ) > { > EFI_STATUS Status; > UINTN Size; > @@ -251,83 +326,101 @@ CpuHotplugEntry ( > // > // Allocate the data structures that depend on the possible CPU count. > // > if (RETURN_ERROR (SafeUintnSub (mCpuHotPlugData->ArrayLength, 1, &Size= )) || > RETURN_ERROR (SafeUintnMult (sizeof (APIC_ID), Size, &Size))) { > Status =3D EFI_ABORTED; > DEBUG ((DEBUG_ERROR, "%a: invalid CPU_HOT_PLUG_DATA\n", __FUNCTION__= )); > goto Fatal; > } > Status =3D gMmst->MmAllocatePool (EfiRuntimeServicesData, Size, > (VOID **)&mPluggedApicIds); > if (EFI_ERROR (Status)) { > DEBUG ((DEBUG_ERROR, "%a: MmAllocatePool(): %r\n", __FUNCTION__, Sta= tus)); > goto Fatal; > } > Status =3D gMmst->MmAllocatePool (EfiRuntimeServicesData, Size, > (VOID **)&mToUnplugApicIds); > if (EFI_ERROR (Status)) { > DEBUG ((DEBUG_ERROR, "%a: MmAllocatePool(): %r\n", __FUNCTION__, Sta= tus)); > goto ReleasePluggedApicIds; > } > > + // > + // Allocate the Post-SMM Pen for hot-added CPUs. > + // > + Status =3D SmbaseAllocatePostSmmPen (&mPostSmmPenAddress, > + SystemTable->BootServices); > + if (EFI_ERROR (Status)) { > + goto ReleaseToUnplugApicIds; > + } > + > // > // Sanity-check the CPU hotplug interface. > // > // Both of the following features are part of QEMU 5.0, introduced pri= marily > // in commit range 3e08b2b9cb64..3a61c8db9d25: > // > // (a) the QEMU_CPUHP_CMD_GET_ARCH_ID command of the modern CPU hotplu= g > // interface, > // > // (b) the "SMRAM at default SMBASE" feature. > // > // From these, (b) is restricted to 5.0+ machine type versions, while = (a) > // does not depend on machine type version. Because we ensured the str= icter > // condition (b) through PcdQ35SmramAtDefaultSmbase above, the (a) > // QEMU_CPUHP_CMD_GET_ARCH_ID command must now be available too. While= we > // can't verify the presence of precisely that command, we can still v= erify > // (sanity-check) that the modern interface is active, at least. > // > // Consult the "Typical usecases | Detecting and enabling modern CPU h= otplug > // interface" section in QEMU's "docs/specs/acpi_cpu_hotplug.txt", on = the > // following. > // > QemuCpuhpWriteCpuSelector (mMmCpuIo, 0); > QemuCpuhpWriteCpuSelector (mMmCpuIo, 0); > QemuCpuhpWriteCommand (mMmCpuIo, QEMU_CPUHP_CMD_GET_PENDING); > if (QemuCpuhpReadCommandData2 (mMmCpuIo) !=3D 0) { > Status =3D EFI_NOT_FOUND; > DEBUG ((DEBUG_ERROR, "%a: modern CPU hotplug interface: %r\n", > __FUNCTION__, Status)); > - goto ReleaseToUnplugApicIds; > + goto ReleasePostSmmPen; > } > > // > // Register the handler for the CPU Hotplug MMI. > // > Status =3D gMmst->MmiHandlerRegister ( > CpuHotplugMmi, > NULL, // HandlerType: root MMI handler > &mDispatchHandle > ); > if (EFI_ERROR (Status)) { > DEBUG ((DEBUG_ERROR, "%a: MmiHandlerRegister(): %r\n", __FUNCTION__, > Status)); > - goto ReleaseToUnplugApicIds; > + goto ReleasePostSmmPen; > } > > + // > + // Install the handler for the hot-added CPUs' first SMI. > + // > + SmbaseInstallFirstSmiHandler (); > + > return EFI_SUCCESS; > > +ReleasePostSmmPen: > + SmbaseReleasePostSmmPen (mPostSmmPenAddress, SystemTable->BootServices= ); > + mPostSmmPenAddress =3D 0; > + > ReleaseToUnplugApicIds: > gMmst->MmFreePool (mToUnplugApicIds); > mToUnplugApicIds =3D NULL; > > ReleasePluggedApicIds: > gMmst->MmFreePool (mPluggedApicIds); > mPluggedApicIds =3D NULL; > > Fatal: > ASSERT (FALSE); > CpuDeadLoop (); > return Status; > } > -- > 2.19.1.3.g30247aa5d201 > >