VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/DynamicTablesScmiInfoLib/DynamicTablesScmiInfoLib.c

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

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

  • 屬性 svn:eol-style 設為 native
檔案大小: 10.0 KB
 
1/** @file
2 Arm SCMI Info Library.
3
4 Copyright (c) 2022 - 2023, Arm Limited. All rights reserved.<BR>
5
6 Arm Functional Fixed Hardware Specification:
7 - https://developer.arm.com/documentation/den0048/latest/
8
9 SPDX-License-Identifier: BSD-2-Clause-Patent
10**/
11
12#include <Library/AcpiLib.h>
13#include <Library/DynamicTablesScmiInfoLib.h>
14#include <Library/DebugLib.h>
15#include <Library/MemoryAllocationLib.h>
16#include <Library/UefiBootServicesTableLib.h>
17#include <Protocol/ArmScmi.h>
18#include <Protocol/ArmScmiPerformanceProtocol.h>
19
20/** Arm FFH registers
21
22 Cf. Arm Functional Fixed Hardware Specification
23 s3.2 Performance management and Collaborative Processor Performance Control
24*/
25#define ARM_FFH_DELIVERED_PERF_COUNTER_REGISTER 0x0
26#define ARM_FFH_REFERENCE_PERF_COUNTER_REGISTER 0x1
27
28/// Arm SCMI performance protocol.
29STATIC SCMI_PERFORMANCE_PROTOCOL *ScmiPerfProtocol;
30
31/** Arm SCMI Info Library constructor.
32
33 @param ImageHandle Image of the loaded driver.
34 @param SystemTable Pointer to the System Table.
35
36 @retval EFI_SUCCESS Success.
37 @retval EFI_DEVICE_ERROR Device error.
38 @retval EFI_INVALID_PARAMETER Invalid parameter.
39 @retval EFI_NOT_FOUND Not Found
40 @retval EFI_TIMEOUT Timeout.
41 @retval EFI_UNSUPPORTED Unsupported.
42**/
43EFI_STATUS
44EFIAPI
45DynamicTablesScmiInfoLibConstructor (
46 IN EFI_HANDLE ImageHandle,
47 IN EFI_SYSTEM_TABLE *SystemTable
48 )
49{
50 EFI_STATUS Status;
51 UINT32 Version;
52
53 Status = gBS->LocateProtocol (
54 &gArmScmiPerformanceProtocolGuid,
55 NULL,
56 (VOID **)&ScmiPerfProtocol
57 );
58 if (EFI_ERROR (Status)) {
59 return Status;
60 }
61
62 Status = ScmiPerfProtocol->GetVersion (ScmiPerfProtocol, &Version);
63 if (EFI_ERROR (Status)) {
64 return Status;
65 }
66
67 // FastChannels were added in SCMI v2.0 spec.
68 if (Version < PERFORMANCE_PROTOCOL_VERSION_V2) {
69 DEBUG ((
70 DEBUG_ERROR,
71 "DynamicTablesScmiInfoLib requires SCMI version > 2.0\n"
72 ));
73 return EFI_UNSUPPORTED;
74 }
75
76 return Status;
77}
78
79/** Get the OPPs/performance states of a power domain.
80
81 This function is a wrapper around the SCMI PERFORMANCE_DESCRIBE_LEVELS
82 command. The list of discrete performance states is returned in a buffer
83 that must be freed by the caller.
84
85 @param[in] DomainId Identifier for the performance domain.
86 @param[out] LevelArray If success, pointer to the list of list of
87 performance state. This memory must be freed by
88 the caller.
89 @param[out] LevelArrayCount If success, contains the number of states in
90 LevelArray.
91
92 @retval EFI_SUCCESS Success.
93 @retval EFI_DEVICE_ERROR Device error.
94 @retval EFI_INVALID_PARAMETER Invalid parameter.
95 @retval EFI_TIMEOUT Time out.
96 @retval EFI_UNSUPPORTED Unsupported.
97**/
98STATIC
99EFI_STATUS
100EFIAPI
101DynamicTablesScmiInfoDescribeLevels (
102 IN UINT32 DomainId,
103 OUT SCMI_PERFORMANCE_LEVEL **LevelArray,
104 OUT UINT32 *LevelArrayCount
105 )
106{
107 EFI_STATUS Status;
108 SCMI_PERFORMANCE_LEVEL *Array;
109 UINT32 Count;
110 UINT32 Size;
111
112 if ((ScmiPerfProtocol == NULL) ||
113 (LevelArray == NULL) ||
114 (LevelArrayCount == NULL))
115 {
116 return EFI_INVALID_PARAMETER;
117 }
118
119 // First call to get the number of levels.
120 Size = 0;
121 Status = ScmiPerfProtocol->DescribeLevels (
122 ScmiPerfProtocol,
123 DomainId,
124 &Count,
125 &Size,
126 NULL
127 );
128 if (Status != EFI_BUFFER_TOO_SMALL) {
129 // EFI_SUCCESS is not a valid option.
130 if (Status == EFI_SUCCESS) {
131 return EFI_INVALID_PARAMETER;
132 } else {
133 return Status;
134 }
135 }
136
137 Array = AllocateZeroPool (Size);
138 if (Array == NULL) {
139 return EFI_OUT_OF_RESOURCES;
140 }
141
142 // Second call to get the descriptions of the levels.
143 Status = ScmiPerfProtocol->DescribeLevels (
144 ScmiPerfProtocol,
145 DomainId,
146 &Count,
147 &Size,
148 Array
149 );
150 if (EFI_ERROR (Status)) {
151 return Status;
152 }
153
154 *LevelArray = Array;
155 *LevelArrayCount = Count;
156
157 return Status;
158}
159
160/** Populate a AML_CPC_INFO object based on SCMI information.
161
162 @param[in] DomainId Identifier for the performance domain.
163 @param[out] CpcInfo If success, this structure was populated from
164 information queried to the SCP.
165
166 @retval EFI_SUCCESS Success.
167 @retval EFI_DEVICE_ERROR Device error.
168 @retval EFI_INVALID_PARAMETER Invalid parameter.
169 @retval EFI_TIMEOUT Time out.
170 @retval EFI_UNSUPPORTED Unsupported.
171**/
172EFI_STATUS
173EFIAPI
174DynamicTablesScmiInfoGetFastChannel (
175 IN UINT32 DomainId,
176 OUT AML_CPC_INFO *CpcInfo
177 )
178{
179 EFI_STATUS Status;
180 SCMI_PERFORMANCE_FASTCHANNEL FcLevelGet;
181 SCMI_PERFORMANCE_FASTCHANNEL FcLimitsSet;
182 SCMI_PERFORMANCE_DOMAIN_ATTRIBUTES DomainAttributes;
183
184 SCMI_PERFORMANCE_LEVEL *LevelArray;
185 UINT32 LevelCount;
186
187 UINT64 FcLevelGetAddr;
188 UINT64 FcLimitsMaxSetAddr;
189 UINT64 FcLimitsMinSetAddr;
190
191 if ((ScmiPerfProtocol == NULL) ||
192 (CpcInfo == NULL))
193 {
194 return EFI_INVALID_PARAMETER;
195 }
196
197 Status = ScmiPerfProtocol->DescribeFastchannel (
198 ScmiPerfProtocol,
199 DomainId,
200 ScmiMessageIdPerformanceLevelSet,
201 &FcLevelGet
202 );
203 if (EFI_ERROR (Status)) {
204 return Status;
205 }
206
207 Status = ScmiPerfProtocol->DescribeFastchannel (
208 ScmiPerfProtocol,
209 DomainId,
210 ScmiMessageIdPerformanceLimitsSet,
211 &FcLimitsSet
212 );
213 if (EFI_ERROR (Status)) {
214 return Status;
215 }
216
217 Status = ScmiPerfProtocol->GetDomainAttributes (
218 ScmiPerfProtocol,
219 DomainId,
220 &DomainAttributes
221 );
222 if (EFI_ERROR (Status)) {
223 return Status;
224 }
225
226 Status = DynamicTablesScmiInfoDescribeLevels (DomainId, &LevelArray, &LevelCount);
227 if (EFI_ERROR (Status)) {
228 return Status;
229 }
230
231 /* Do some safety checks.
232 Only support FastChannels (and not doorbells) as this is
233 the only mechanism supported by SCP.
234 FcLimits[Get|Set] require 2 UINT32 values (max, then min) and
235 FcLimits[Get|Set] require 1 UINT32 value (level).
236 */
237 if ((FcLevelGet.ChanSize != sizeof (UINT32)) ||
238 ((FcLevelGet.Attributes & SCMI_PERF_FC_ATTRIB_HAS_DOORBELL) ==
239 SCMI_PERF_FC_ATTRIB_HAS_DOORBELL) ||
240 (FcLimitsSet.ChanSize != 2 * sizeof (UINT32)) ||
241 ((FcLimitsSet.Attributes & SCMI_PERF_FC_ATTRIB_HAS_DOORBELL) ==
242 SCMI_PERF_FC_ATTRIB_HAS_DOORBELL))
243 {
244 Status = EFI_INVALID_PARAMETER;
245 goto exit_handler;
246 }
247
248 FcLevelGetAddr = ((UINT64)FcLevelGet.ChanAddrHigh << 32) |
249 FcLevelGet.ChanAddrLow;
250 FcLimitsMaxSetAddr = ((UINT64)FcLimitsSet.ChanAddrHigh << 32) |
251 FcLimitsSet.ChanAddrLow;
252 FcLimitsMinSetAddr = FcLimitsMaxSetAddr + 0x4;
253
254 CpcInfo->Revision = EFI_ACPI_6_5_AML_CPC_REVISION;
255 CpcInfo->HighestPerformanceInteger = LevelArray[LevelCount - 1].Level;
256 CpcInfo->NominalPerformanceInteger = DomainAttributes.SustainedPerfLevel;
257 CpcInfo->LowestNonlinearPerformanceInteger = LevelArray[0].Level;
258 CpcInfo->LowestPerformanceInteger = LevelArray[0].Level;
259
260 CpcInfo->DesiredPerformanceRegister.AddressSpaceId = EFI_ACPI_6_5_SYSTEM_MEMORY;
261 CpcInfo->DesiredPerformanceRegister.RegisterBitWidth = 32;
262 CpcInfo->DesiredPerformanceRegister.RegisterBitOffset = 0;
263 CpcInfo->DesiredPerformanceRegister.AccessSize = EFI_ACPI_6_5_DWORD;
264 CpcInfo->DesiredPerformanceRegister.Address = FcLevelGetAddr;
265
266 CpcInfo->MinimumPerformanceRegister.AddressSpaceId = EFI_ACPI_6_5_SYSTEM_MEMORY;
267 CpcInfo->MinimumPerformanceRegister.RegisterBitWidth = 32;
268 CpcInfo->MinimumPerformanceRegister.RegisterBitOffset = 0;
269 CpcInfo->MinimumPerformanceRegister.AccessSize = EFI_ACPI_6_5_DWORD;
270 CpcInfo->MinimumPerformanceRegister.Address = FcLimitsMinSetAddr;
271
272 CpcInfo->MaximumPerformanceRegister.AddressSpaceId = EFI_ACPI_6_5_SYSTEM_MEMORY;
273 CpcInfo->MaximumPerformanceRegister.RegisterBitWidth = 32;
274 CpcInfo->MaximumPerformanceRegister.RegisterBitOffset = 0;
275 CpcInfo->MaximumPerformanceRegister.AccessSize = EFI_ACPI_6_5_DWORD;
276 CpcInfo->MaximumPerformanceRegister.Address = FcLimitsMaxSetAddr;
277
278 CpcInfo->ReferencePerformanceCounterRegister.AddressSpaceId = EFI_ACPI_6_5_FUNCTIONAL_FIXED_HARDWARE;
279 CpcInfo->ReferencePerformanceCounterRegister.RegisterBitWidth = 0x40;
280 CpcInfo->ReferencePerformanceCounterRegister.RegisterBitOffset = 0;
281 CpcInfo->ReferencePerformanceCounterRegister.AccessSize = ARM_FFH_REFERENCE_PERF_COUNTER_REGISTER;
282 CpcInfo->ReferencePerformanceCounterRegister.Address = 0x4;
283
284 CpcInfo->DeliveredPerformanceCounterRegister.AddressSpaceId = EFI_ACPI_6_5_FUNCTIONAL_FIXED_HARDWARE;
285 CpcInfo->DeliveredPerformanceCounterRegister.RegisterBitWidth = 0x40;
286 CpcInfo->DeliveredPerformanceCounterRegister.RegisterBitOffset = 0;
287 CpcInfo->DeliveredPerformanceCounterRegister.AccessSize = ARM_FFH_DELIVERED_PERF_COUNTER_REGISTER;
288 CpcInfo->DeliveredPerformanceCounterRegister.Address = 0x4;
289
290 // SCMI should advertise performance values on a unified scale. So frequency
291 // values are not available. LowestFrequencyInteger and
292 // NominalFrequencyInteger are populated in the ConfigurationManager.
293
294exit_handler:
295 FreePool (LevelArray);
296 return Status;
297}
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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