From nobody Sat Feb 7 06:55:47 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+54957+1787277+3901457@groups.io; helo=web01.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+54957+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1582755161; cv=none; d=zohomail.com; s=zohoarc; b=CoBIQOEmZOJsg/PeWnZR/rcOOz/yA6hRboTtO8AISkfTEPdt8zARdgCs6AyKlWCOu34aYHoYgvZfwAoF39G0ZFZhOqXUCfw2AJDTRTLl4no+e48ymOiQU1J2Ltlkh4Hky20mMjh/NU7rbyfgxROMrS3ztKuLWR4Q77nCoi2zz+A= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1582755161; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Id:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=GOI9rcHom/b/xQX0iwyvd6JDjCHuhDmRrf42acWc6Pg=; b=f31KQ86K9ryyDcsGqM9tYvQAqcGFMGem0jR08zECY7vMK3dewNZJRKMMd9WTjzU/uSjVVFh2w9F16HLQtJrx3cytf1vzHx0oKp4fnv4WFO68xallMNSboVtgpD9rUnsLNWu09Y+Ksyf/bE6H9ui6wP9a8K6Ogu0SPjSrsv2nzhA= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+54957+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) header.from= Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1582755161404627.7794523427552; Wed, 26 Feb 2020 14:12:41 -0800 (PST) Return-Path: X-Received: by 127.0.0.2 with SMTP id jN8gYY1788612xoIqV3Uoly3; Wed, 26 Feb 2020 14:12:40 -0800 X-Received: from us-smtp-delivery-1.mimecast.com (us-smtp-delivery-1.mimecast.com [207.211.31.81]) by mx.groups.io with SMTP id smtpd.web12.233.1582755159672580431 for ; Wed, 26 Feb 2020 14:12:39 -0800 X-Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-161-4mSbdVDaPjSKG0wKMRU3bg-1; Wed, 26 Feb 2020 17:12:32 -0500 X-MC-Unique: 4mSbdVDaPjSKG0wKMRU3bg-1 X-Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id A6A79800D50; Wed, 26 Feb 2020 22:12:31 +0000 (UTC) X-Received: from lacos-laptop-7.usersys.redhat.com (ovpn-116-185.ams2.redhat.com [10.36.116.185]) by smtp.corp.redhat.com (Postfix) with ESMTP id EE74E909E9; Wed, 26 Feb 2020 22:12:29 +0000 (UTC) From: "Laszlo Ersek" To: edk2-devel-groups-io Cc: Ard Biesheuvel , Igor Mammedov , Jiewen Yao , Jordan Justen , Michael Kinney , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Subject: [edk2-devel] [PATCH v2 13/16] OvmfPkg/CpuHotplugSmm: complete root MMI handler for CPU hotplug Date: Wed, 26 Feb 2020 23:11:53 +0100 Message-Id: <20200226221156.29589-14-lersek@redhat.com> In-Reply-To: <20200226221156.29589-1-lersek@redhat.com> References: <20200226221156.29589-1-lersek@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,lersek@redhat.com X-Gm-Message-State: Xc9qr6ptHH3RhozEeFPKMnOLx1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1582755160; bh=GOI9rcHom/b/xQX0iwyvd6JDjCHuhDmRrf42acWc6Pg=; h=Cc:Content-Type:Date:From:Reply-To:Subject:To; b=iLVCXRzQeIYvbRWT9UdYkwzQyyxYL8vgxkFVz8DvLdw92rg9ZscNOnH1GAu6sS9p55k 03W1hF2nvtajAJiEVpL3RNsKXKpgdOz5S7TjztOmkoYLCwu3cuIphCK1wSkRJhcewtqXs WltVB+lGP6GEaAFv0juBX56ANpzWs6juKuU= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Type: text/plain; charset="utf-8" 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: =20 - 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.) =20 - repeat all the v1 tests =20 v1: =20 (1) At this stage, CPU hotplug with SMM works. =20 Test CPU topology (libvirt domain XML snippet): =20 > > > > > > =20 The firmware logs the following during normal boot: =20 > SmbaseAllocatePostSmmPen: Post-SMM Pen at 0x9F000 =20 CPU hotplug command on the host side: =20 > virsh setvcpu ovmf.fedora.q35 1 --enable --live =20 Firmware log in response: =20 > 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 =20 Query the CPU register state on the host side (without onlining the hot-added CPU in the OS just yet): =20 > virsh qemu-monitor-command ovmf.fedora.q35 --hmp 'info registers -a' =20 Output, confirming penned status (pen at 0x9F000): =20 > 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=3D= 0 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=3D0000000000000000 > 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 =20 Additionally, the dmesg in the Linux guest contains: =20 > CPU2 has been hot-added =20 We can now boot the hot-addad CPU in the Linux guest: =20 > echo 1 > /sys/devices/system/cpu/cpu2/online =20 Dmesg in response: =20 > 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 =20 Still in the guest, call UEFI variable services on each CPU (including the hot-added one), per : =20 > taskset -c 0 efibootmgr > taskset -c 1 efibootmgr > taskset -c 2 efibootmgr =20 No delays, no instability. =20 Having booted the hot-added CPU in the Linux guest, the host-side command =20 > virsh qemu-monitor-command ovmf.fedora.q35 --hmp 'info registers -a' =20 now shows: =20 > CPU#1 > RAX=3Dffffffffb39e4b50 RBX=3D0000000000000002 RCX=3D0000000000000000 > RDX=3D0000000000000002 > RSI=3D0000000000000002 RDI=3Dffff932cbb51c520 RBP=3D0000000000000002 > RSP=3Dffffbc5bc0083eb0 > R8 =3D000000cd42e4dffb R9 =3D0000005a22502599 R10=3D0000005a22502599 > R11=3D0000005a22502599 > R12=3Dffff932cbae25dc0 R13=3D0000000000000000 R14=3D0000000000000000 > R15=3Dffff932cbae25dc0 > RIP=3Dffffffffb39e4f2e RFL=3D00000246 [---Z-P-] CPL=3D0 II=3D0 A20=3D= 1 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=3D00= 1606e0 > DR0=3D0000000000000000 DR1=3D0000000000000000 DR2=3D0000000000000000 > 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 =20 Hotplug another CPU: =20 > virsh setvcpu ovmf.fedora.q35 3 --enable --live =20 Firmware log in response: =20 > 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 =20 Online the hot-added CPU in the Linux guest: =20 > echo 1 > /sys/devices/system/cpu/cpu3/online =20 Guest dmesg in response: =20 > 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 =20 (2) Alternative order of actions: =20 Hotplug both CPUs first, on the host: =20 > virsh setvcpu ovmf.fedora.q35 1 --enable --live > virsh setvcpu ovmf.fedora.q35 3 --enable --live =20 *then* online both hot-added CPUs in the Linux guest: =20 > echo 1 > /sys/devices/system/cpu/cpu2/online > echo 1 > /sys/devices/system/cpu/cpu3/online =20 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 (beyond the matching log messages and register dumps). =20 (3) What doesn't work yet: =20 - CPU hotplug w/ SMM in SEV guests. =20 See . =20 (NB. I'm uncertain if CPU hotplug works in SEV guests without SMM_REQUIRE to begin with.) =20 - S3 resume w/ SMM after hot-adding a CPU. =20 The remaining patches in the series take care of that. (Only in the absence of SEV; SEV+S3 looks broken regardless of hotplug.) =20 - CPU hot-unplug w/ SMM. =20 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 challenging 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/Cpu= Hotplug.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. =20 Copyright (c) 2020, Red Hat, Inc. =20 SPDX-License-Identifier: BSD-2-Clause-Patent **/ =20 #include // CPU_HOT_PLUG_DATA #include // ICH9_APM_CNT #include // QEMU_CPUHP_CMD_GET_PENDING #include // CpuDeadLoop() #include // ASSERT() #include // gMmst #include // PcdGetBool() #include // SafeUintnSub() #include // EFI_MM_CPU_IO_PROTOCOL #include // EFI_SMM_CPU_SERVICE_PROTOC= OL #include // EFI_STATUS =20 #include "ApicId.h" // APIC_ID #include "QemuCpuhp.h" // QemuCpuhpWriteCpuSelector() +#include "Smbase.h" // SmbaseAllocatePostSmmPen() =20 // // 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 C= PU 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 provider // (i.e., PiSmmCpuDxeSmm). // STATIC CPU_HOT_PLUG_DATA *mCpuHotPlugData; // // SMRAM arrays for fetching the APIC IDs of processors with pending event= s (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 IDs // 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 are // 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-SM= M Pen +// for hot-added CPUs. +// +STATIC UINT32 mPostSmmPenAddress; +// // Represents the registration of the CPU Hotplug MMI handler. // STATIC EFI_HANDLE mDispatchHandle; =20 =20 /** CPU Hotplug MMI handler function. =20 This is a root MMI handler. =20 @param[in] DispatchHandle The unique handle assigned to this handle= r by EFI_MM_SYSTEM_TABLE.MmiHandlerRegister(). =20 @param[in] Context Context passed in by EFI_MM_SYSTEM_TABLE.MmiManage(). Due to CpuHotplugMmi() being a root MMI handler, Context is ASSERT()ed to be NULL. =20 @param[in,out] CommBuffer Ignored, due to CpuHotplugMmi() being a r= oot MMI handler. =20 @param[in,out] CommBufferSize Ignored, due to CpuHotplugMmi() being a r= oot @@ -97,44 +103,46 @@ STATIC EFI_HANDLE mDispatchHandle; =20 @retval EFI_WARN_INTERRUPT_SOURCE_PENDING The MMI source is still pend= ing, and other handlers should st= ill be called. =20 @retval EFI_INTERRUPT_PENDING The MMI source could not be 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; =20 // // Assert that we are entering this function due to our root MMI handler // registration. // ASSERT (DispatchHandle =3D=3D mDispatchHandle); // // When MmiManage() is invoked to process root MMI handlers, the caller = (the // MM Core) is expected to pass in a NULL Context. MmiManage() then pass= es // 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 this = 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", __FUNCTI= ON__, Status)); // @@ -152,49 +160,116 @@ CpuHotplugMmi ( =20 // // 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; } =20 + // + // Process hot-added CPUs. + // + // The Post-SMM Pen need not be reinstalled multiple times within a sing= le + // root MMI handling. Even reinstalling once per root MMI is only pruden= ce; + // in theory installing the pen in the driver's entry point function sho= uld + // 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[NewSlot], + 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 0x%= 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; =20 +RevokeNewSlot: + mCpuHotPlugData->ApicId[NewSlot] =3D MAX_UINT64; + Fatal: ASSERT (FALSE); CpuDeadLoop (); // // We couldn't handle this MMI. // return EFI_INTERRUPT_PENDING; } =20 =20 // // 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__, Statu= s)); goto Fatal; } Status =3D gMmst->MmAllocatePool (EfiRuntimeServicesData, Size, (VOID **)&mToUnplugApicIds); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "%a: MmAllocatePool(): %r\n", __FUNCTION__, Statu= s)); goto ReleasePluggedApicIds; } =20 + // + // 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 prima= rily // in commit range 3e08b2b9cb64..3a61c8db9d25: // // (a) the QEMU_CPUHP_CMD_GET_ARCH_ID command of the modern CPU hotplug // 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 stric= ter // 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 ver= ify // (sanity-check) that the modern interface is active, at least. // // Consult the "Typical usecases | Detecting and enabling modern CPU hot= plug // 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; } =20 // // 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; } =20 + // + // Install the handler for the hot-added CPUs' first SMI. + // + SmbaseInstallFirstSmiHandler (); + return EFI_SUCCESS; =20 +ReleasePostSmmPen: + SmbaseReleasePostSmmPen (mPostSmmPenAddress, SystemTable->BootServices); + mPostSmmPenAddress =3D 0; + ReleaseToUnplugApicIds: gMmst->MmFreePool (mToUnplugApicIds); mToUnplugApicIds =3D NULL; =20 ReleasePluggedApicIds: gMmst->MmFreePool (mPluggedApicIds); mPluggedApicIds =3D NULL; =20 Fatal: ASSERT (FALSE); CpuDeadLoop (); return Status; } --=20 2.19.1.3.g30247aa5d201 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#54957): https://edk2.groups.io/g/devel/message/54957 Mute This Topic: https://groups.io/mt/71575191/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-