2 UncachedMemoryAllocation lib that uses DXE Service to change cachability for
5 Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>
7 This program and the accompanying materials
8 are licensed and made available under the terms and conditions of the BSD License
9 which accompanies this distribution. The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 #include <Library/BaseLib.h>
19 #include <Library/BaseMemoryLib.h>
20 #include <Library/MemoryAllocationLib.h>
21 #include <Library/DebugLib.h>
22 #include <Library/UefiBootServicesTableLib.h>
23 #include <Library/UncachedMemoryAllocationLib.h>
24 #include <Library/PcdLib.h>
25 #include <Library/ArmLib.h>
26 #include <Library/DxeServicesTableLib.h>
28 #include <Protocol/Cpu.h>
31 UncachedInternalAllocatePages (
32 IN EFI_MEMORY_TYPE MemoryType
,
37 UncachedInternalAllocateAlignedPages (
38 IN EFI_MEMORY_TYPE MemoryType
,
46 // Assume all of memory has the same cache attributes, unless we do our magic
56 LIST_ENTRY mPageList
= INITIALIZE_LIST_HEAD_VARIABLE (mPageList
);
64 FREE_PAGE_NODE
*NewNode
;
66 NewNode
= AllocatePool (sizeof (LIST_ENTRY
));
67 if (NewNode
== NULL
) {
72 NewNode
->Allocation
= Allocation
;
73 NewNode
->Pages
= Pages
;
75 InsertTailList (&mPageList
, &NewNode
->Link
);
86 FREE_PAGE_NODE
*OldNode
;
90 for (Link
= mPageList
.ForwardLink
; Link
!= &mPageList
; Link
= Link
->ForwardLink
) {
91 OldNode
= BASE_CR (Link
, FREE_PAGE_NODE
, Link
);
92 if (OldNode
->Allocation
== Allocation
) {
93 *Pages
= OldNode
->Pages
;
95 RemoveEntryList (&OldNode
->Link
);
106 Converts a cached or uncached address to a physical address suitable for use in SoC registers.
108 @param VirtualAddress The pointer to convert.
110 @return The physical address of the supplied virtual pointer.
114 ConvertToPhysicalAddress (
115 IN VOID
*VirtualAddress
118 return (EFI_PHYSICAL_ADDRESS
)(UINTN
)VirtualAddress
;
123 UncachedInternalAllocatePages (
124 IN EFI_MEMORY_TYPE MemoryType
,
128 return UncachedInternalAllocateAlignedPages (MemoryType
, Pages
, EFI_PAGE_SIZE
);
134 UncachedAllocatePages (
138 return UncachedInternalAllocatePages (EfiBootServicesData
, Pages
);
143 UncachedAllocateRuntimePages (
147 return UncachedInternalAllocatePages (EfiRuntimeServicesData
, Pages
);
152 UncachedAllocateReservedPages (
156 return UncachedInternalAllocatePages (EfiReservedMemoryType
, Pages
);
168 UncachedFreeAlignedPages (Buffer
, Pages
);
174 UncachedInternalAllocateAlignedPages (
175 IN EFI_MEMORY_TYPE MemoryType
,
181 EFI_PHYSICAL_ADDRESS Memory
;
182 EFI_PHYSICAL_ADDRESS AlignedMemory
;
184 UINTN UnalignedPages
;
186 EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor
;
189 // Alignment must be a power of two or zero.
191 ASSERT ((Alignment
& (Alignment
- 1)) == 0);
196 if (Alignment
> EFI_PAGE_SIZE
) {
198 // Caculate the total number of pages since alignment is larger than page size.
200 AlignmentMask
= Alignment
- 1;
201 RealPages
= Pages
+ EFI_SIZE_TO_PAGES (Alignment
);
203 // Make sure that Pages plus EFI_SIZE_TO_PAGES (Alignment) does not overflow.
205 ASSERT (RealPages
> Pages
);
207 Status
= gBS
->AllocatePages (AllocateAnyPages
, MemoryType
, RealPages
, &Memory
);
208 if (EFI_ERROR (Status
)) {
211 AlignedMemory
= ((UINTN
) Memory
+ AlignmentMask
) & ~AlignmentMask
;
212 UnalignedPages
= EFI_SIZE_TO_PAGES (AlignedMemory
- (UINTN
) Memory
);
213 if (UnalignedPages
> 0) {
215 // Free first unaligned page(s).
217 Status
= gBS
->FreePages (Memory
, UnalignedPages
);
218 ASSERT_EFI_ERROR (Status
);
220 Memory
= (EFI_PHYSICAL_ADDRESS
) (AlignedMemory
+ EFI_PAGES_TO_SIZE (Pages
));
221 UnalignedPages
= RealPages
- Pages
- UnalignedPages
;
222 if (UnalignedPages
> 0) {
224 // Free last unaligned page(s).
226 Status
= gBS
->FreePages (Memory
, UnalignedPages
);
227 ASSERT_EFI_ERROR (Status
);
231 // Do not over-allocate pages in this case.
233 Status
= gBS
->AllocatePages (AllocateAnyPages
, MemoryType
, Pages
, &Memory
);
234 if (EFI_ERROR (Status
)) {
237 AlignedMemory
= (UINTN
) Memory
;
240 Status
= gDS
->GetMemorySpaceDescriptor (Memory
, &Descriptor
);
241 if (!EFI_ERROR (Status
)) {
242 // We are making an assumption that all of memory has the same default attributes
243 gAttributes
= Descriptor
.Attributes
;
246 Status
= gDS
->SetMemorySpaceAttributes (Memory
, EFI_PAGES_TO_SIZE (Pages
), EFI_MEMORY_WC
);
247 ASSERT_EFI_ERROR (Status
);
249 return (VOID
*)(UINTN
)Memory
;
255 UncachedFreeAlignedPages (
261 EFI_PHYSICAL_ADDRESS Memory
;
265 Memory
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) Buffer
;
266 Status
= gDS
->SetMemorySpaceAttributes (Memory
, EFI_PAGES_TO_SIZE (Pages
), gAttributes
);
268 Status
= gBS
->FreePages (Memory
, Pages
);
269 ASSERT_EFI_ERROR (Status
);
276 UncachedInternalAllocateAlignedPool (
277 IN EFI_MEMORY_TYPE PoolType
,
278 IN UINTN AllocationSize
,
282 VOID
*AlignedAddress
;
285 // Alignment must be a power of two or zero.
287 ASSERT ((Alignment
& (Alignment
- 1)) == 0);
289 if (Alignment
< EFI_PAGE_SIZE
) {
290 Alignment
= EFI_PAGE_SIZE
;
293 AlignedAddress
= UncachedInternalAllocateAlignedPages (PoolType
, EFI_SIZE_TO_PAGES (AllocationSize
), Alignment
);
294 if (AlignedAddress
== NULL
) {
298 AddPagesToList ((VOID
*)(UINTN
)AlignedAddress
, EFI_SIZE_TO_PAGES (AllocationSize
));
300 return (VOID
*) AlignedAddress
;
305 UncachedAllocateAlignedPool (
306 IN UINTN AllocationSize
,
310 return UncachedInternalAllocateAlignedPool (EfiBootServicesData
, AllocationSize
, Alignment
);
315 UncachedAllocateAlignedRuntimePool (
316 IN UINTN AllocationSize
,
320 return UncachedInternalAllocateAlignedPool (EfiRuntimeServicesData
, AllocationSize
, Alignment
);
325 UncachedAllocateAlignedReservedPool (
326 IN UINTN AllocationSize
,
330 return UncachedInternalAllocateAlignedPool (EfiReservedMemoryType
, AllocationSize
, Alignment
);
334 UncachedInternalAllocateAlignedZeroPool (
335 IN EFI_MEMORY_TYPE PoolType
,
336 IN UINTN AllocationSize
,
341 Memory
= UncachedInternalAllocateAlignedPool (PoolType
, AllocationSize
, Alignment
);
342 if (Memory
!= NULL
) {
343 Memory
= ZeroMem (Memory
, AllocationSize
);
350 UncachedAllocateAlignedZeroPool (
351 IN UINTN AllocationSize
,
355 return UncachedInternalAllocateAlignedZeroPool (EfiBootServicesData
, AllocationSize
, Alignment
);
360 UncachedAllocateAlignedRuntimeZeroPool (
361 IN UINTN AllocationSize
,
365 return UncachedInternalAllocateAlignedZeroPool (EfiRuntimeServicesData
, AllocationSize
, Alignment
);
370 UncachedAllocateAlignedReservedZeroPool (
371 IN UINTN AllocationSize
,
375 return UncachedInternalAllocateAlignedZeroPool (EfiReservedMemoryType
, AllocationSize
, Alignment
);
379 UncachedInternalAllocateAlignedCopyPool (
380 IN EFI_MEMORY_TYPE PoolType
,
381 IN UINTN AllocationSize
,
382 IN CONST VOID
*Buffer
,
388 ASSERT (Buffer
!= NULL
);
389 ASSERT (AllocationSize
<= (MAX_ADDRESS
- (UINTN
) Buffer
+ 1));
391 Memory
= UncachedInternalAllocateAlignedPool (PoolType
, AllocationSize
, Alignment
);
392 if (Memory
!= NULL
) {
393 Memory
= CopyMem (Memory
, Buffer
, AllocationSize
);
400 UncachedAllocateAlignedCopyPool (
401 IN UINTN AllocationSize
,
402 IN CONST VOID
*Buffer
,
406 return UncachedInternalAllocateAlignedCopyPool (EfiBootServicesData
, AllocationSize
, Buffer
, Alignment
);
411 UncachedAllocateAlignedRuntimeCopyPool (
412 IN UINTN AllocationSize
,
413 IN CONST VOID
*Buffer
,
417 return UncachedInternalAllocateAlignedCopyPool (EfiRuntimeServicesData
, AllocationSize
, Buffer
, Alignment
);
422 UncachedAllocateAlignedReservedCopyPool (
423 IN UINTN AllocationSize
,
424 IN CONST VOID
*Buffer
,
428 return UncachedInternalAllocateAlignedCopyPool (EfiReservedMemoryType
, AllocationSize
, Buffer
, Alignment
);
433 UncachedFreeAlignedPool (
439 RemovePagesFromList (Allocation
, &Pages
);
441 UncachedFreePages (Allocation
, Pages
);
445 UncachedInternalAllocatePool (
446 IN EFI_MEMORY_TYPE MemoryType
,
447 IN UINTN AllocationSize
450 UINTN CacheLineLength
= ArmDataCacheLineLength ();
451 return UncachedInternalAllocateAlignedPool (MemoryType
, AllocationSize
, CacheLineLength
);
456 UncachedAllocatePool (
457 IN UINTN AllocationSize
460 return UncachedInternalAllocatePool (EfiBootServicesData
, AllocationSize
);
465 UncachedAllocateRuntimePool (
466 IN UINTN AllocationSize
469 return UncachedInternalAllocatePool (EfiRuntimeServicesData
, AllocationSize
);
474 UncachedAllocateReservedPool (
475 IN UINTN AllocationSize
478 return UncachedInternalAllocatePool (EfiReservedMemoryType
, AllocationSize
);
482 UncachedInternalAllocateZeroPool (
483 IN EFI_MEMORY_TYPE PoolType
,
484 IN UINTN AllocationSize
489 Memory
= UncachedInternalAllocatePool (PoolType
, AllocationSize
);
490 if (Memory
!= NULL
) {
491 Memory
= ZeroMem (Memory
, AllocationSize
);
498 UncachedAllocateZeroPool (
499 IN UINTN AllocationSize
502 return UncachedInternalAllocateZeroPool (EfiBootServicesData
, AllocationSize
);
507 UncachedAllocateRuntimeZeroPool (
508 IN UINTN AllocationSize
511 return UncachedInternalAllocateZeroPool (EfiRuntimeServicesData
, AllocationSize
);
516 UncachedAllocateReservedZeroPool (
517 IN UINTN AllocationSize
520 return UncachedInternalAllocateZeroPool (EfiReservedMemoryType
, AllocationSize
);
524 UncachedInternalAllocateCopyPool (
525 IN EFI_MEMORY_TYPE PoolType
,
526 IN UINTN AllocationSize
,
527 IN CONST VOID
*Buffer
532 ASSERT (Buffer
!= NULL
);
533 ASSERT (AllocationSize
<= (MAX_ADDRESS
- (UINTN
) Buffer
+ 1));
535 Memory
= UncachedInternalAllocatePool (PoolType
, AllocationSize
);
536 if (Memory
!= NULL
) {
537 Memory
= CopyMem (Memory
, Buffer
, AllocationSize
);
544 UncachedAllocateCopyPool (
545 IN UINTN AllocationSize
,
546 IN CONST VOID
*Buffer
549 return UncachedInternalAllocateCopyPool (EfiBootServicesData
, AllocationSize
, Buffer
);
554 UncachedAllocateRuntimeCopyPool (
555 IN UINTN AllocationSize
,
556 IN CONST VOID
*Buffer
559 return UncachedInternalAllocateCopyPool (EfiRuntimeServicesData
, AllocationSize
, Buffer
);
564 UncachedAllocateReservedCopyPool (
565 IN UINTN AllocationSize
,
566 IN CONST VOID
*Buffer
569 return UncachedInternalAllocateCopyPool (EfiReservedMemoryType
, AllocationSize
, Buffer
);
578 UncachedFreeAlignedPool (Buffer
);
583 UncachedSafeFreePool (
587 if (Buffer
!= NULL
) {
588 UncachedFreePool (Buffer
);