VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/Firmware/OvmfPkg/TdxDxe/TdxAcpiTable.c

最後變更 在這個檔案是 105670,由 vboxsync 提交於 7 月 前

Devices/EFI/FirmwareNew: Merge edk2-stable-202405 and make it build on aarch64, bugref:4643

  • 屬性 svn:eol-style 設為 native
檔案大小: 6.7 KB
 
1/** @file
2 OVMF ACPI QEMU support
3
4 Copyright (c) 2008 - 2014, Intel Corporation. All rights reserved.<BR>
5
6 Copyright (C) 2012-2014, Red Hat, Inc.
7
8 SPDX-License-Identifier: BSD-2-Clause-Patent
9
10**/
11
12#include <Library/DebugLib.h>
13#include <Library/BaseLib.h>
14#include <Library/BaseMemoryLib.h>
15#include <Library/MemoryAllocationLib.h>
16#include <Library/QemuFwCfgLib.h>
17#include <Library/DxeServicesTableLib.h>
18#include <Library/PcdLib.h>
19#include <Library/OrderedCollectionLib.h>
20#include <Library/TdxLib.h>
21#include <IndustryStandard/Acpi.h>
22#include <Protocol/AcpiSystemDescriptionTable.h>
23#include <Protocol/AcpiTable.h>
24#include <Library/UefiBootServicesTableLib.h>
25#include <Library/UefiLib.h>
26#include <Library/TdxMailboxLib.h>
27#include <Protocol/Cpu.h>
28#include <Uefi.h>
29#include <TdxAcpiTable.h>
30
31/**
32 At the beginning of system boot, a 4K-aligned, 4K-size memory (Td mailbox) is
33 pre-allocated by host VMM. BSP & APs do the page accept together in that memory
34 region.
35
36 After that TDVF is designed to relocate the mailbox to a 4K-aligned, 4K-size
37 memory block which is allocated in the ACPI Nvs memory. APs are waken up and
38 spin around the relocated mailbox for further command.
39
40 @return EFI_PHYSICAL_ADDRESS Address of the relocated mailbox
41**/
42EFI_PHYSICAL_ADDRESS
43EFIAPI
44RelocateMailbox (
45 VOID
46 )
47{
48 EFI_PHYSICAL_ADDRESS Address;
49 VOID *ApLoopFunc;
50 UINT32 RelocationPages;
51 MP_RELOCATION_MAP RelocationMap;
52 MP_WAKEUP_MAILBOX *RelocatedMailBox;
53 EFI_STATUS Status;
54
55 Address = 0;
56 ApLoopFunc = NULL;
57 ZeroMem (&RelocationMap, sizeof (RelocationMap));
58
59 //
60 // Get information needed to setup aps running in their
61 // run loop in allocated acpi reserved memory
62 // Add another page for mailbox
63 //
64 AsmGetRelocationMap (&RelocationMap);
65 if ((RelocationMap.RelocateApLoopFuncAddress == 0) || (RelocationMap.RelocateApLoopFuncSize == 0)) {
66 DEBUG ((DEBUG_ERROR, "Failed to get the RelocationMap.\n"));
67 return 0;
68 }
69
70 RelocationPages = EFI_SIZE_TO_PAGES ((UINT32)RelocationMap.RelocateApLoopFuncSize) + 1;
71
72 Status = gBS->AllocatePages (AllocateAnyPages, EfiACPIMemoryNVS, RelocationPages, &Address);
73 if (EFI_ERROR (Status)) {
74 DEBUG ((DEBUG_ERROR, "Failed to allocate pages for MailboxRelocation. %r\n", Status));
75 return 0;
76 }
77
78 ZeroMem ((VOID *)Address, EFI_PAGES_TO_SIZE (RelocationPages));
79
80 ApLoopFunc = (VOID *)((UINTN)Address + EFI_PAGE_SIZE);
81
82 CopyMem (
83 ApLoopFunc,
84 RelocationMap.RelocateApLoopFuncAddress,
85 RelocationMap.RelocateApLoopFuncSize
86 );
87
88 DEBUG ((
89 DEBUG_INFO,
90 "Ap Relocation: mailbox %llx, loop %p\n",
91 Address,
92 ApLoopFunc
93 ));
94
95 //
96 // Initialize mailbox
97 //
98 RelocatedMailBox = (MP_WAKEUP_MAILBOX *)Address;
99 RelocatedMailBox->Command = MpProtectedModeWakeupCommandNoop;
100 RelocatedMailBox->ApicId = MP_CPU_PROTECTED_MODE_MAILBOX_APICID_INVALID;
101 RelocatedMailBox->WakeUpVector = 0;
102
103 //
104 // Wakup APs and have been move to the finalized run loop
105 // They will spin until guest OS wakes them
106 //
107 MpSerializeStart ();
108
109 MpSendWakeupCommand (
110 MpProtectedModeWakeupCommandWakeup,
111 (UINT64)ApLoopFunc,
112 (UINT64)RelocatedMailBox,
113 0,
114 0,
115 0
116 );
117
118 return Address;
119}
120
121/**
122 Alter the MADT when ACPI Table from QEMU is available.
123
124 @param[in] Event Event whose notification function is being invoked
125 @param[in] Context Pointer to the notification function's context
126**/
127VOID
128EFIAPI
129AlterAcpiTable (
130 IN EFI_EVENT Event,
131 IN VOID *Context
132 )
133{
134 EFI_ACPI_SDT_PROTOCOL *AcpiSdtProtocol;
135 EFI_ACPI_TABLE_PROTOCOL *AcpiTableProtocol;
136 EFI_STATUS Status;
137 UINTN Index;
138 EFI_ACPI_SDT_HEADER *Table;
139 EFI_ACPI_TABLE_VERSION Version;
140 UINTN OriginalTableKey;
141 UINTN NewTableKey;
142 UINT8 *NewMadtTable;
143 UINTN NewMadtTableLength;
144 EFI_PHYSICAL_ADDRESS RelocateMailboxAddress;
145 EFI_ACPI_6_4_MULTIPROCESSOR_WAKEUP_STRUCTURE *MadtMpWk;
146 EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER *MadtHeader;
147
148 Index = 0;
149 NewMadtTable = NULL;
150 MadtHeader = NULL;
151
152 Status = gBS->LocateProtocol (&gEfiAcpiSdtProtocolGuid, NULL, (void **)&AcpiSdtProtocol);
153 if (EFI_ERROR (Status)) {
154 DEBUG ((DEBUG_ERROR, "Unable to locate ACPI SDT protocol.\n"));
155 return;
156 }
157
158 RelocateMailboxAddress = RelocateMailbox ();
159 if (RelocateMailboxAddress == 0) {
160 ASSERT (FALSE);
161 DEBUG ((DEBUG_ERROR, "Failed to relocate Td mailbox\n"));
162 return;
163 }
164
165 do {
166 Status = AcpiSdtProtocol->GetAcpiTable (Index, &Table, &Version, &OriginalTableKey);
167
168 if (!EFI_ERROR (Status) && (Table->Signature == EFI_ACPI_1_0_APIC_SIGNATURE)) {
169 Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (void **)&AcpiTableProtocol);
170 if (EFI_ERROR (Status)) {
171 DEBUG ((DEBUG_ERROR, "Unable to locate ACPI Table protocol.\n"));
172 break;
173 }
174
175 NewMadtTableLength = Table->Length + sizeof (EFI_ACPI_6_4_MULTIPROCESSOR_WAKEUP_STRUCTURE);
176 NewMadtTable = AllocatePool (NewMadtTableLength);
177 if (NewMadtTable == NULL) {
178 DEBUG ((DEBUG_ERROR, "%a: OUT_OF_SOURCES error.\n", __func__));
179 break;
180 }
181
182 CopyMem (NewMadtTable, (UINT8 *)Table, Table->Length);
183 MadtHeader = (EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER *)NewMadtTable;
184 MadtHeader->Header.Length = (UINT32)NewMadtTableLength;
185
186 MadtMpWk = (EFI_ACPI_6_4_MULTIPROCESSOR_WAKEUP_STRUCTURE *)(NewMadtTable + Table->Length);
187 MadtMpWk->Type = EFI_ACPI_6_4_MULTIPROCESSOR_WAKEUP;
188 MadtMpWk->Length = sizeof (EFI_ACPI_6_4_MULTIPROCESSOR_WAKEUP_STRUCTURE);
189 MadtMpWk->MailBoxVersion = 0;
190 MadtMpWk->Reserved = 0;
191 MadtMpWk->MailBoxAddress = RelocateMailboxAddress;
192
193 Status = AcpiTableProtocol->InstallAcpiTable (AcpiTableProtocol, NewMadtTable, NewMadtTableLength, &NewTableKey);
194 if (EFI_ERROR (Status)) {
195 DEBUG ((DEBUG_ERROR, "Failed to install new MADT table. %r\n", Status));
196 break;
197 }
198
199 Status = AcpiTableProtocol->UninstallAcpiTable (AcpiTableProtocol, OriginalTableKey);
200 if (EFI_ERROR (Status)) {
201 DEBUG ((DEBUG_ERROR, "Uninstall old MADT table error.\n"));
202 }
203
204 break;
205 }
206
207 Index++;
208 } while (!EFI_ERROR (Status));
209
210 if (NewMadtTable != NULL) {
211 FreePool (NewMadtTable);
212 }
213}
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette