From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from userp2130.oracle.com (userp2130.oracle.com [156.151.31.86]) by mx.groups.io with SMTP id smtpd.web08.30320.1610951712361140290 for ; Sun, 17 Jan 2021 22:35:12 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@oracle.com header.s=corp-2020-01-29 header.b=lReKly9r; spf=pass (domain: oracle.com, ip: 156.151.31.86, mailfrom: ankur.a.arora@oracle.com) Received: from pps.filterd (userp2130.oracle.com [127.0.0.1]) by userp2130.oracle.com (8.16.0.42/8.16.0.42) with SMTP id 10I6XPDb007140; Mon, 18 Jan 2021 06:35:09 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oracle.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding; s=corp-2020-01-29; bh=hTT+DiQ1DZJSBn4cwupFyJ0UG0SlPIG5Om+mLLJdVss=; b=lReKly9rc1VQjfFYvGxicD44qQVXDDlBXTCd0oiDNk/MH5kFZCNALf/20M9S/p6IUY4C yTG5a43Q7sNoQ1yDArQfvFA9dSFhkhIQJKnE0yQC0OmPxpsWiVKguwnfMnn5hF7q5KZy nIAgPgiK3KsTm94OWuZjOuIgQrm8X4ghE6ePWavXdvnpEKy3hvsQQh2XfSCoHeZ0R5us 7lK9ahQ//tQqkrHmisW+0DpwNi8GBxP/stx+iye7UW/dpIyg4A87ReI+FufuIEXEtArG 8Xg/ph9Yh+zMZN8h0Aa/qSAXa0bla1bxo/x+/3RzthTHpGyxR7mDefgVpsUvQnifYGJF 4g== Received: from userp3020.oracle.com (userp3020.oracle.com [156.151.31.79]) by userp2130.oracle.com with ESMTP id 363xyhk085-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Mon, 18 Jan 2021 06:35:09 +0000 Received: from pps.filterd (userp3020.oracle.com [127.0.0.1]) by userp3020.oracle.com (8.16.0.42/8.16.0.42) with SMTP id 10I6Upos031699; Mon, 18 Jan 2021 06:35:09 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by userp3020.oracle.com with ESMTP id 3649wpejpy-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Mon, 18 Jan 2021 06:35:09 +0000 Received: from abhmp0016.oracle.com (abhmp0016.oracle.com [141.146.116.22]) by userv0121.oracle.com (8.14.4/8.13.8) with ESMTP id 10I6Z8TE010379; Mon, 18 Jan 2021 06:35:08 GMT Received: from prion.us.oracle.com (/10.159.226.191) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Sun, 17 Jan 2021 22:35:07 -0800 From: "Ankur Arora" To: devel@edk2.groups.io Cc: lersek@redhat.com, imammedo@redhat.com, boris.ostrovsky@oracle.com, Ankur Arora , Jordan Justen , Ard Biesheuvel , Aaron Young Subject: [PATCH v4 7/9] OvmfPkg/CpuHotplugSmm: add CpuEject() Date: Sun, 17 Jan 2021 22:34:55 -0800 Message-Id: <20210118063457.358581-8-ankur.a.arora@oracle.com> X-Mailer: git-send-email 2.25.4 In-Reply-To: <20210118063457.358581-1-ankur.a.arora@oracle.com> References: <20210118063457.358581-1-ankur.a.arora@oracle.com> MIME-Version: 1.0 X-Proofpoint-Virus-Version: vendor=nai engine=6000 definitions=9867 signatures=668683 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 mlxscore=0 mlxlogscore=999 bulkscore=0 spamscore=0 phishscore=0 malwarescore=0 adultscore=0 suspectscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2009150000 definitions=main-2101180038 X-Proofpoint-Virus-Version: vendor=nai engine=6000 definitions=9867 signatures=668683 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 adultscore=0 phishscore=0 malwarescore=0 mlxlogscore=999 bulkscore=0 priorityscore=1501 spamscore=0 mlxscore=0 impostorscore=0 lowpriorityscore=0 suspectscore=0 clxscore=1015 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2009150000 definitions=main-2101180038 Content-Transfer-Encoding: quoted-printable Add CpuEject(), which handles the CPU ejection, and provides a holding area for said CPUs. It is called via SmmCpuFeaturesRendezvousExit(), at the tail end of the SMI handling. Also UnplugCpus() now stashes APIC IDs of CPUs which need to be ejected in CPU_HOT_EJECT_DATA.ApicIdMap. These are used by CpuEject() to identify such CPUs. Cc: Laszlo Ersek Cc: Jordan Justen Cc: Ard Biesheuvel Cc: Igor Mammedov Cc: Boris Ostrovsky Cc: Aaron Young Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=3D3132 Signed-off-by: Ankur Arora --- OvmfPkg/CpuHotplugSmm/CpuHotplug.c | 84 ++++++++++++++++++++++++++++++++++= +++- 1 file changed, 83 insertions(+), 1 deletion(-) diff --git a/OvmfPkg/CpuHotplugSmm/CpuHotplug.c b/OvmfPkg/CpuHotplugSmm/Cpu= Hotplug.c index ccd5787b7327..e8ba9ae59e69 100644 --- a/OvmfPkg/CpuHotplugSmm/CpuHotplug.c +++ b/OvmfPkg/CpuHotplugSmm/CpuHotplug.c @@ -14,6 +14,7 @@ #include // gMmst=0D #include // PcdGetBool()=0D #include // SafeUintnSub()=0D +#include // CPU_HOT_EJECT_DATA #include // EFI_MM_CPU_IO_PROTOCOL=0D #include // EFI_SMM_CPU_SERVICE_PROTOC= OL=0D #include // EFI_STATUS=0D @@ -32,11 +33,12 @@ STATIC EFI_MM_CPU_IO_PROTOCOL *mMmCpuIo; //=0D STATIC EFI_SMM_CPU_SERVICE_PROTOCOL *mMmCpuService;=0D //=0D -// This structure is a communication side-channel between the=0D +// These structures serve as communication side-channels between the=0D // EFI_SMM_CPU_SERVICE_PROTOCOL consumer (i.e., this driver) and provider= =0D // (i.e., PiSmmCpuDxeSmm).=0D //=0D STATIC CPU_HOT_PLUG_DATA *mCpuHotPlugData;=0D +STATIC CPU_HOT_EJECT_DATA *mCpuHotEjectData; //=0D // SMRAM arrays for fetching the APIC IDs of processors with pending event= s (of=0D // known event types), for the time of just one MMI.=0D @@ -181,6 +183,34 @@ Fatal: return EFI_INTERRUPT_PENDING; } =0D +VOID +EFIAPI +CpuEject( + IN UINTN ProcessorNum + ) +{ + // + // APIC ID is UINT32, but mCpuHotEjectData->ApicIdMap[] is UINT64 + // so use UINT64 throughout. + // + UINT64 ApicId; + + ApicId =3D mCpuHotEjectData->ApicIdMap[ProcessorNum]; + if (ApicId =3D=3D CPU_EJECT_INVALID) { + return; + } + + // + // CPU(s) being unplugged get here from SmmCpuFeaturesSmiRendezvousExit() + // after having been cleared to exit the SMI by the monarch and thus have + // no SMM processing remaining. + // + // Given that we cannot allow them to escape to the guest, we pen them + // here until the SMM monarch tells the HW to unplug them. + // + CpuDeadLoop (); +} + /**=0D CPU Hot-unplug MMI handler function. =20 @@ -203,6 +233,7 @@ UnplugCpus( { EFI_STATUS Status =3D EFI_SUCCESS; UINT32 ToUnplugIdx; + UINT32 EjectCount =3D 0; UINTN ProcessorNum; =20 ToUnplugIdx =3D 0; @@ -242,11 +273,35 @@ UnplugCpus( DEBUG ((DEBUG_ERROR, "%a: RemoveProcessor(" FMT_APIC_ID "): %r\n", __FUNCTION__, RemoveApicId, Status)); goto Fatal; + } else { + // + // Stash the APIC IDs so we can do the actual unplug later. + // + if (mCpuHotEjectData->ApicIdMap[ProcessorNum] !=3D CPU_EJECT_INVALID= ) { + // + // Since ProcessorNum and APIC-ID map 1-1, so a valid + // mCpuHotEjectData->ApicIdMap[ProcessorNum] means something + // is horribly wrong. + // + DEBUG ((DEBUG_ERROR, "%a: ProcessorNum %u maps to %llx, cannot map= to " FMT_APIC_ID "\n", + __FUNCTION__, ProcessorNum, mCpuHotEjectData->ApicIdMap[Processo= rNum], RemoveApicId)); + goto Fatal; + } + + mCpuHotEjectData->ApicIdMap[ProcessorNum] =3D (UINT64)RemoveApicId; + EjectCount++; } =20 ToUnplugIdx++; } =20 + if (EjectCount) { + // + // We have processors to be ejected; install the handler. + // + mCpuHotEjectData->Handler =3D CpuEject; + } + // // We've handled this unplug. // @@ -445,7 +500,13 @@ CpuHotplugEntry ( // Our DEPEX on EFI_SMM_CPU_SERVICE_PROTOCOL guarantees that PiSmmCpuDxe= Smm=0D // has pointed PcdCpuHotPlugDataAddress to CPU_HOT_PLUG_DATA in SMRAM.=0D //=0D + // Additionally, CPU Hot-unplug is available only if CPU Hotplug is, so= =0D + // the same DEPEX also guarantees that PcdCpuHotEjectDataAddress points= =0D + // to CPU_HOT_EJECT_DATA in SMRAM.=0D + // mCpuHotPlugData =3D (VOID *)(UINTN)PcdGet64 (PcdCpuHotPlugDataAddress);= =0D + mCpuHotEjectData =3D (VOID *)(UINTN)PcdGet64 (PcdCpuHotEjectDataAddress); + if (mCpuHotPlugData =3D=3D NULL) {=0D Status =3D EFI_NOT_FOUND;=0D DEBUG ((DEBUG_ERROR, "%a: CPU_HOT_PLUG_DATA: %r\n", __FUNCTION__, Stat= us));=0D @@ -457,6 +518,9 @@ CpuHotplugEntry ( if (mCpuHotPlugData->ArrayLength =3D=3D 1) {=0D return EFI_UNSUPPORTED;=0D }=0D + ASSERT (mCpuHotEjectData && + (mCpuHotPlugData->ArrayLength =3D=3D mCpuHotEjectData->ArrayLeng= th)); + //=0D // Allocate the data structures that depend on the possible CPU count.=0D //=0D @@ -539,6 +603,24 @@ CpuHotplugEntry ( //=0D SmbaseInstallFirstSmiHandler ();=0D =0D + if (mCpuHotEjectData) { + UINT32 Idx; + // + // For CPU ejection we need to map ProcessorNum -> APIC_ID. By the time + // we do that, however, the Processor's APIC ID has already been remov= ed + // from SMM data structures. So we will use mCpuHotEjectData->ApicIdMap + // to map from ProcessorNum -> APIC_ID. + // + for (Idx =3D 0; Idx < mCpuHotEjectData->ArrayLength; Idx++) { + mCpuHotEjectData->ApicIdMap[Idx] =3D CPU_EJECT_INVALID; + } + + // + // Wait to init the handler until an ejection is warranted + // + mCpuHotEjectData->Handler =3D NULL; + } + return EFI_SUCCESS;=0D =0D ReleasePostSmmPen:=0D --=20 2.9.3