1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
|
/** @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);
}
|