/** @file | |
Copyright (c) 2008, Intel Corporation. All rights reserved.<BR> | |
(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR> | |
SPDX-License-Identifier: BSD-2-Clause-Patent | |
**/ | |
#include <Library/DebugLib.h> | |
#include <Library/BaseMemoryLib.h> | |
#include <Library/PcdLib.h> | |
#include <Library/CpuLib.h> | |
#include <Library/SynchronizationLib.h> | |
#include <Uefi/UefiBaseType.h> | |
#include <IndustryStandard/IntelTdx.h> | |
#include <IndustryStandard/Tdx.h> | |
#include <Library/TdxMailboxLib.h> | |
/** | |
This function will be called by BSP to get the CPU number. | |
@retval CPU number | |
**/ | |
UINT32 | |
EFIAPI | |
GetCpusNum ( | |
VOID | |
) | |
{ | |
UINT64 Status; | |
TD_RETURN_DATA TdReturnData; | |
Status = TdCall (TDCALL_TDINFO, 0, 0, 0, &TdReturnData); | |
if (Status == TDX_EXIT_REASON_SUCCESS) { | |
return TdReturnData.TdInfo.NumVcpus; | |
} else { | |
DEBUG ((DEBUG_ERROR, "Failed call TDCALL_TDINFO. %llx\n", Status)); | |
} | |
return 0; | |
} | |
/** | |
Get the address of Td mailbox. | |
**/ | |
volatile VOID * | |
EFIAPI | |
GetTdxMailBox ( | |
VOID | |
) | |
{ | |
return (VOID *)(UINTN)PcdGet32 (PcdOvmfSecGhcbBackupBase); | |
} | |
/** | |
This function will be called by BSP to wakeup APs the are spinning on mailbox | |
in protected mode | |
@param[in] Command Command to send APs | |
@param[in] WakeupVector If used, address for APs to start executing | |
@param[in] WakeArgsX Args to pass to APs for excuting commands | |
**/ | |
VOID | |
EFIAPI | |
MpSendWakeupCommand ( | |
IN UINT16 Command, | |
IN UINT64 WakeupVector, | |
IN UINT64 WakeupArgs1, | |
IN UINT64 WakeupArgs2, | |
IN UINT64 WakeupArgs3, | |
IN UINT64 WakeupArgs4 | |
) | |
{ | |
volatile MP_WAKEUP_MAILBOX *MailBox; | |
MailBox = (volatile MP_WAKEUP_MAILBOX *)GetTdxMailBox (); | |
MailBox->ApicId = MP_CPU_PROTECTED_MODE_MAILBOX_APICID_INVALID; | |
MailBox->WakeUpVector = 0; | |
MailBox->Command = MpProtectedModeWakeupCommandNoop; | |
MailBox->ApicId = MP_CPU_PROTECTED_MODE_MAILBOX_APICID_BROADCAST; | |
MailBox->WakeUpVector = WakeupVector; | |
MailBox->WakeUpArgs1 = WakeupArgs1; | |
MailBox->WakeUpArgs2 = WakeupArgs2; | |
MailBox->WakeUpArgs3 = WakeupArgs3; | |
MailBox->WakeUpArgs4 = WakeupArgs4; | |
AsmCpuid (0x01, NULL, NULL, NULL, NULL); | |
MailBox->Command = Command; | |
AsmCpuid (0x01, NULL, NULL, NULL, NULL); | |
return; | |
} | |
/** | |
BSP wait until all the APs arriving. It means the task triggered by BSP is started. | |
**/ | |
VOID | |
EFIAPI | |
MpSerializeStart ( | |
VOID | |
) | |
{ | |
volatile MP_WAKEUP_MAILBOX *MailBox; | |
UINT32 NumOfCpus; | |
NumOfCpus = GetCpusNum (); | |
MailBox = (volatile MP_WAKEUP_MAILBOX *)GetTdxMailBox (); | |
DEBUG ((DEBUG_VERBOSE, "Waiting for APs to arriving. NumOfCpus=%d, MailBox=%p\n", NumOfCpus, MailBox)); | |
while (MailBox->NumCpusArriving != (NumOfCpus -1)) { | |
CpuPause (); | |
} | |
DEBUG ((DEBUG_VERBOSE, "Releasing APs\n")); | |
MailBox->NumCpusExiting = NumOfCpus; | |
InterlockedIncrement ((UINT32 *)&MailBox->NumCpusArriving); | |
} | |
/** | |
BSP wait until all the APs arriving. It means the task triggered by BSP is ended. | |
**/ | |
VOID | |
EFIAPI | |
MpSerializeEnd ( | |
VOID | |
) | |
{ | |
volatile MP_WAKEUP_MAILBOX *MailBox; | |
MailBox = (volatile MP_WAKEUP_MAILBOX *)GetTdxMailBox (); | |
DEBUG ((DEBUG_VERBOSE, "Waiting for APs to finish\n")); | |
while (MailBox->NumCpusExiting != 1 ) { | |
CpuPause (); | |
} | |
DEBUG ((DEBUG_VERBOSE, "Restarting APs\n")); | |
MailBox->Command = MpProtectedModeWakeupCommandNoop; | |
MailBox->NumCpusArriving = 0; | |
InterlockedDecrement ((UINT32 *)&MailBox->NumCpusExiting); | |
} |