/** @file
Copyright (c) 2008, Intel Corporation. All rights reserved.
(C) Copyright 2016 Hewlett Packard Enterprise Development LP
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include
#include
#include
#include
#include
#include
#include
#include
#include
/**
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);
}