Skip to content

Commit dba7976

Browse files
jongwumergify[bot]
authored andcommitted
CloudHv/arm: add PeiMemInfoLib
Memory layout in CLoud Hypervisor for arm is changed and is different with Qemu, thus we should build its own PeiMemInfoLib. The main change in the memory layout is that normal ram may not contiguous under 4G. The top 64M under 4G is reserved for 32bit device. What this patch does: 1. get all of the memory node from DT; 2. Init page table for each memory node; 3. Add all of the memory nodes to Hob; Reviewed-by: Sami Mujawar <sami.mujawar@arm.com> Signed-off-by: Jianyong Wu <jianyong.wu@arm.com>
1 parent 520ba8e commit dba7976

File tree

3 files changed

+332
-0
lines changed

3 files changed

+332
-0
lines changed
Lines changed: 243 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,243 @@
1+
/** @file
2+
3+
Copyright (c) 2022, Arm Limited. All rights reserved.
4+
5+
SPDX-License-Identifier: BSD-2-Clause-Patent
6+
7+
**/
8+
9+
#include <PiPei.h>
10+
11+
#include <Base.h>
12+
#include <libfdt.h>
13+
#include <Library/ArmLib.h>
14+
#include <Library/BaseMemoryLib.h>
15+
#include <Library/DebugLib.h>
16+
#include <Library/MemoryAllocationLib.h>
17+
#include <Library/PcdLib.h>
18+
19+
#include <Library/PrePiLib.h>
20+
21+
#include "CloudHvVirtMemInfoLib.h"
22+
23+
CLOUDHV_MEM_NODE_INFO CloudHvMemNode[CLOUDHV_MAX_MEM_NODE_NUM];
24+
25+
/**
26+
Get all of memory nodes info from DT. Store all of them into
27+
CloudHvMemNode which will be consumed by ArmVirtGetMemoryMap.
28+
29+
@retval RETURN_SUCCESS Success.
30+
@retval EFI_NOT_FOUND DT or the first memory node not found.
31+
32+
**/
33+
RETURN_STATUS
34+
EFIAPI
35+
CloudHvVirtMemInfoPeiLibConstructor (
36+
VOID
37+
)
38+
{
39+
VOID *DeviceTreeBase;
40+
EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttributes;
41+
INT32 Node, Prev;
42+
UINT64 FirMemNodeBase, FirMemNodeSize;
43+
UINT64 CurBase, MemBase;
44+
UINT64 CurSize;
45+
CONST CHAR8 *Type;
46+
INT32 Len;
47+
CONST UINT64 *RegProp;
48+
RETURN_STATUS PcdStatus;
49+
UINT8 Index;
50+
51+
ZeroMem (CloudHvMemNode, sizeof (CloudHvMemNode));
52+
53+
FirMemNodeBase = 0;
54+
FirMemNodeSize = 0;
55+
Index = 0;
56+
MemBase = FixedPcdGet64 (PcdSystemMemoryBase);
57+
ResourceAttributes = (
58+
EFI_RESOURCE_ATTRIBUTE_PRESENT |
59+
EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
60+
EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE |
61+
EFI_RESOURCE_ATTRIBUTE_TESTED
62+
);
63+
DeviceTreeBase = (VOID *)(UINTN)PcdGet64 (PcdDeviceTreeInitialBaseAddress);
64+
if (DeviceTreeBase == NULL) {
65+
return EFI_NOT_FOUND;
66+
}
67+
68+
//
69+
// Make sure we have a valid device tree blob
70+
//
71+
if (fdt_check_header (DeviceTreeBase) != 0) {
72+
return EFI_NOT_FOUND;
73+
}
74+
75+
//
76+
// Look for the lowest memory node
77+
//
78+
for (Prev = 0; ; Prev = Node) {
79+
Node = fdt_next_node (DeviceTreeBase, Prev, NULL);
80+
if (Node < 0) {
81+
break;
82+
}
83+
84+
//
85+
// Check for memory node
86+
//
87+
Type = fdt_getprop (DeviceTreeBase, Node, "device_type", &Len);
88+
if ((Type != 0) && (AsciiStrnCmp (Type, "memory", Len) == 0)) {
89+
//
90+
// Get the 'reg' property of this node. For now, we will assume
91+
// two 8 byte quantities for base and size, respectively.
92+
//
93+
RegProp = fdt_getprop (DeviceTreeBase, Node, "reg", &Len);
94+
if ((RegProp != 0) && (Len == (2 * sizeof (UINT64)))) {
95+
CurBase = fdt64_to_cpu (ReadUnaligned64 (RegProp));
96+
CurSize = fdt64_to_cpu (ReadUnaligned64 (RegProp + 1));
97+
98+
DEBUG ((
99+
DEBUG_INFO,
100+
"%a: System RAM @ 0x%lx - 0x%lx\n",
101+
__FUNCTION__,
102+
CurBase,
103+
CurBase + CurSize - 1
104+
));
105+
106+
// We should build Hob seperately for the memory node except the first one
107+
if (CurBase != MemBase) {
108+
BuildResourceDescriptorHob (
109+
EFI_RESOURCE_SYSTEM_MEMORY,
110+
ResourceAttributes,
111+
CurBase,
112+
CurSize
113+
);
114+
} else {
115+
FirMemNodeBase = CurBase;
116+
FirMemNodeSize = CurSize;
117+
}
118+
119+
CloudHvMemNode[Index].Base = CurBase;
120+
CloudHvMemNode[Index].Size = CurSize;
121+
Index++;
122+
123+
if (Index >= CLOUDHV_MAX_MEM_NODE_NUM) {
124+
DEBUG ((
125+
DEBUG_WARN,
126+
"%a: memory node larger than %d will not be included into Memory System\n",
127+
__FUNCTION__,
128+
CLOUDHV_MAX_MEM_NODE_NUM
129+
));
130+
break;
131+
}
132+
} else {
133+
DEBUG ((
134+
DEBUG_ERROR,
135+
"%a: Failed to parse FDT memory node\n",
136+
__FUNCTION__
137+
));
138+
}
139+
}
140+
}
141+
142+
//
143+
// Make sure the start of DRAM matches our expectation
144+
//
145+
if (FixedPcdGet64 (PcdSystemMemoryBase) != FirMemNodeBase) {
146+
return EFI_NOT_FOUND;
147+
}
148+
149+
PcdStatus = PcdSet64S (PcdSystemMemorySize, FirMemNodeSize);
150+
ASSERT_RETURN_ERROR (PcdStatus);
151+
ASSERT (
152+
(((UINT64)PcdGet64 (PcdFdBaseAddress) +
153+
(UINT64)PcdGet32 (PcdFdSize)) <= FirMemNodeBase) ||
154+
((UINT64)PcdGet64 (PcdFdBaseAddress) >= (FirMemNodeBase + FirMemNodeSize))
155+
);
156+
157+
return RETURN_SUCCESS;
158+
}
159+
160+
/**
161+
Return the Virtual Memory Map of your platform
162+
163+
This Virtual Memory Map is used by MemoryInitPei Module to initialize the MMU
164+
on your platform.
165+
166+
@param[out] VirtualMemoryMap Array of ARM_MEMORY_REGION_DESCRIPTOR
167+
describing a Physical-to-Virtual Memory
168+
mapping. This array must be ended by a
169+
zero-filled entry. The allocated memory
170+
will not be freed.
171+
172+
**/
173+
VOID
174+
ArmVirtGetMemoryMap (
175+
OUT ARM_MEMORY_REGION_DESCRIPTOR **VirtualMemoryMap
176+
)
177+
{
178+
ARM_MEMORY_REGION_DESCRIPTOR *VirtualMemoryTable;
179+
UINT8 Index, MemNodeIndex;
180+
181+
ASSERT (VirtualMemoryMap != NULL);
182+
183+
VirtualMemoryTable = AllocatePool (
184+
sizeof (ARM_MEMORY_REGION_DESCRIPTOR) *
185+
MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS
186+
);
187+
188+
if (VirtualMemoryTable == NULL) {
189+
DEBUG ((DEBUG_ERROR, "%a: Error: Failed AllocatePool()\n", __FUNCTION__));
190+
return;
191+
}
192+
193+
Index = 0;
194+
MemNodeIndex = 0;
195+
// System DRAM
196+
while ((MemNodeIndex < CLOUDHV_MAX_MEM_NODE_NUM) && (CloudHvMemNode[MemNodeIndex].Size != 0)) {
197+
VirtualMemoryTable[Index].PhysicalBase = CloudHvMemNode[MemNodeIndex].Base;
198+
VirtualMemoryTable[Index].VirtualBase = CloudHvMemNode[MemNodeIndex].Base;
199+
VirtualMemoryTable[Index].Length = CloudHvMemNode[MemNodeIndex].Size;
200+
VirtualMemoryTable[Index].Attributes = ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK;
201+
202+
DEBUG ((
203+
DEBUG_INFO,
204+
"%a: Dumping System DRAM Memory Node%d Map:\n"
205+
"\tPhysicalBase: 0x%lX\n"
206+
"\tVirtualBase: 0x%lX\n"
207+
"\tLength: 0x%lX\n",
208+
__FUNCTION__,
209+
MemNodeIndex,
210+
VirtualMemoryTable[Index].PhysicalBase,
211+
VirtualMemoryTable[Index].VirtualBase,
212+
VirtualMemoryTable[Index].Length
213+
));
214+
Index++;
215+
MemNodeIndex++;
216+
}
217+
218+
// Memory mapped peripherals (UART, RTC, GIC, virtio-mmio, etc)
219+
VirtualMemoryTable[Index].PhysicalBase = MACH_VIRT_PERIPH_BASE;
220+
VirtualMemoryTable[Index].VirtualBase = MACH_VIRT_PERIPH_BASE;
221+
VirtualMemoryTable[Index].Length = MACH_VIRT_PERIPH_SIZE;
222+
VirtualMemoryTable[Index].Attributes = ARM_MEMORY_REGION_ATTRIBUTE_DEVICE;
223+
Index++;
224+
225+
// Map the FV region as normal executable memory
226+
VirtualMemoryTable[Index].PhysicalBase = PcdGet64 (PcdFvBaseAddress);
227+
VirtualMemoryTable[Index].VirtualBase = VirtualMemoryTable[Index].PhysicalBase;
228+
VirtualMemoryTable[Index].Length = FixedPcdGet32 (PcdFvSize);
229+
VirtualMemoryTable[Index].Attributes = ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK;
230+
Index++;
231+
232+
// Memory mapped for 32bit device (like TPM)
233+
VirtualMemoryTable[Index].PhysicalBase = TOP_32BIT_DEVICE_BASE;
234+
VirtualMemoryTable[Index].VirtualBase = TOP_32BIT_DEVICE_BASE;
235+
VirtualMemoryTable[Index].Length = TOP_32BIT_DEVICE_SIZE;
236+
VirtualMemoryTable[Index].Attributes = ARM_MEMORY_REGION_ATTRIBUTE_DEVICE;
237+
Index++;
238+
239+
// End of Table
240+
ZeroMem (&VirtualMemoryTable[Index], sizeof (ARM_MEMORY_REGION_DESCRIPTOR));
241+
242+
*VirtualMemoryMap = VirtualMemoryTable;
243+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/** @file
2+
3+
Copyright (c) 2022, Arm Limited. All rights reserved.
4+
5+
SPDX-License-Identifier: BSD-2-Clause-Patent
6+
7+
**/
8+
9+
#ifndef CLOUDHV_VIRT_MEM_INFO_LIB_H_
10+
#define CLOUDHV_VIRT_MEM_INFO_LIB_H_
11+
12+
//
13+
// Cloud Hypervisor may have more than one memory nodes. Even there is no limit for that,
14+
// I think 10 is enough in general.
15+
//
16+
#define CLOUDHV_MAX_MEM_NODE_NUM 10
17+
18+
// Record memory node info (base address and size)
19+
typedef struct {
20+
UINT64 Base;
21+
UINT64 Size;
22+
} CLOUDHV_MEM_NODE_INFO;
23+
24+
// Number of Virtual Memory Map Descriptors
25+
#define MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS (4 + CLOUDHV_MAX_MEM_NODE_NUM)
26+
27+
//
28+
// Core peripherals such as the UART, the GIC and the RTC are
29+
// all mapped in the 'miscellaneous device I/O' region, which we just map
30+
// in its entirety rather than device by device. Note that it does not
31+
// cover any of the NOR flash banks or PCI resource windows.
32+
//
33+
#define MACH_VIRT_PERIPH_BASE 0x00400000
34+
#define MACH_VIRT_PERIPH_SIZE 0x0FC00000
35+
36+
//
37+
// The top of the 64M memory region under 4GB reserved for device
38+
//
39+
#define TOP_32BIT_DEVICE_BASE 0xFC000000
40+
#define TOP_32BIT_DEVICE_SIZE 0x04000000
41+
42+
#endif // CLOUDHV_VIRT_MEM_INFO_LIB_H_
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
## @file
2+
# Cloud Hypervisor virtual memory map library.
3+
#
4+
# Copyright (c) 2022, Arm Limited. All rights reserved.
5+
#
6+
# SPDX-License-Identifier: BSD-2-Clause-Patent
7+
#
8+
##
9+
10+
[Defines]
11+
INF_VERSION = 0x0001001B
12+
BASE_NAME = CloudHvVirtMemInfoPeiLib
13+
FILE_GUID = c7ada233-d35b-49c3-aa51-e2b5cd80c910
14+
MODULE_TYPE = BASE
15+
VERSION_STRING = 1.0
16+
LIBRARY_CLASS = ArmVirtMemInfoLib|PEIM
17+
CONSTRUCTOR = CloudHvVirtMemInfoPeiLibConstructor
18+
19+
[Sources]
20+
CloudHvVirtMemInfoLib.c
21+
CloudHvVirtMemInfoLib.h
22+
23+
[Packages]
24+
ArmPkg/ArmPkg.dec
25+
ArmVirtPkg/ArmVirtPkg.dec
26+
EmbeddedPkg/EmbeddedPkg.dec
27+
MdeModulePkg/MdeModulePkg.dec
28+
MdePkg/MdePkg.dec
29+
30+
[LibraryClasses]
31+
ArmLib
32+
BaseMemoryLib
33+
DebugLib
34+
FdtLib
35+
MemoryAllocationLib
36+
PcdLib
37+
38+
[Pcd]
39+
gArmTokenSpaceGuid.PcdFdBaseAddress
40+
gArmTokenSpaceGuid.PcdFvBaseAddress
41+
gArmTokenSpaceGuid.PcdSystemMemoryBase
42+
gArmTokenSpaceGuid.PcdSystemMemorySize
43+
44+
[FixedPcd]
45+
gArmTokenSpaceGuid.PcdFdSize
46+
gArmTokenSpaceGuid.PcdFvSize
47+
gArmVirtTokenSpaceGuid.PcdDeviceTreeInitialBaseAddress

0 commit comments

Comments
 (0)