TianoCore EDK2 master
Loading...
Searching...
No Matches
CpuMmuInit.c
Go to the documentation of this file.
1
10#include <Uefi.h>
11#include <Library/BaseLib.h>
13#include <Library/CpuMmuLib.h>
14#include <Library/DebugLib.h>
17
18//
19// Because the page size in edk2 is 4KB, the lowest level
20// page table is align to 12 bits, and the page table width
21// of other levels is set to 9 bits by default, which will
22// be 3 or 4 or 5 level page tables, and continuous.
23//
24// Correspondence between max virtual memory address width
25// and page table level:
26// 39 bit >= VA > 31 bit, 3 level page tables
27// 48 bit >= VA > 40 bit, 4 level page tables
28// 57 bit >= VA > 49 bit, 5 level page tables
29//
30#define DEFAULT_BIT_WIDTH_PER_LEVEL (EFI_PAGE_SHIFT - 3)
31
41UINT8
43 IN OUT UINT64 *PageWalkCfg OPTIONAL,
44 IN UINT8 BitWidth
45 )
46{
47 CPUCFG_REG1_INFO_DATA CpucfgReg1Data;
48 UINT8 CpuVirtMemAddressWidth;
49 UINT8 PageTableLevelNum;
50 UINT8 CurrentPageTableLevel;
51 UINT32 Pwcl0Value;
52 UINT32 Pwcl1Value;
53
54 //
55 // If BitWidth is 0, use the default bit width.
56 //
57 if (BitWidth == 0) {
58 BitWidth = DEFAULT_BIT_WIDTH_PER_LEVEL;
59 }
60
61 //
62 // Get the the CPU virtual memory address width.
63 //
64 AsmCpucfg (CPUCFG_REG1_INFO, &CpucfgReg1Data.Uint32);
65
66 CpuVirtMemAddressWidth = (UINT8)(CpucfgReg1Data.Bits.VALEN + 1);
67
68 //
69 // Statisitics the maximum page table level
70 //
71 PageTableLevelNum = 0x0;
72 if (((CpuVirtMemAddressWidth - EFI_PAGE_SHIFT) % BitWidth) > 0) {
73 PageTableLevelNum++;
74 }
75
76 PageTableLevelNum += (CpuVirtMemAddressWidth - EFI_PAGE_SHIFT) / BitWidth;
77
78 //
79 // Set page table level
80 //
81 Pwcl0Value = 0x0;
82 Pwcl1Value = 0x0;
83 for (CurrentPageTableLevel = 0x0; CurrentPageTableLevel < PageTableLevelNum; CurrentPageTableLevel++) {
84 if (CurrentPageTableLevel < 0x3) {
85 // Less then or equal to level 3
86 Pwcl0Value |= ((BitWidth * CurrentPageTableLevel + EFI_PAGE_SHIFT) << 10 * CurrentPageTableLevel) |
87 BitWidth << (10 * CurrentPageTableLevel + 5);
88 } else {
89 // Lager then level 3
90 Pwcl1Value |= ((BitWidth * CurrentPageTableLevel + EFI_PAGE_SHIFT) << 12 * (CurrentPageTableLevel - 3)) |
91 BitWidth << (12 * (CurrentPageTableLevel - 3) + 6);
92 }
93
94 DEBUG ((
95 DEBUG_INFO,
96 "%a %d Level %d DIR shift %d.\n",
97 __func__,
98 __LINE__,
99 (CurrentPageTableLevel + 1),
100 (BitWidth * CurrentPageTableLevel + EFI_PAGE_SHIFT)
101 ));
102 }
103
104 *PageWalkCfg = ((UINT64)Pwcl1Value << 32) | Pwcl0Value;
105
106 return PageTableLevelNum;
107}
108
120EFIAPI
122 IN EFI_MEMORY_DESCRIPTOR *MemoryTable
123 )
124{
125 EFI_STATUS Status;
126 UINTN PageTable;
127 UINT64 PageWalkCfg;
128 UINT8 MaxLevel;
129
130 if (MemoryTable == NULL) {
131 ASSERT (MemoryTable != NULL);
132 return EFI_INVALID_PARAMETER;
133 }
134
135 //
136 // Automatically obtain the current appropriate page walker configuration.
137 //
138 MaxLevel = DecidePageWalkConfiguration (&PageWalkCfg, 0);
139
140 if ((MaxLevel < 0) || (MaxLevel > 5)) {
141 return EFI_UNSUPPORTED;
142 }
143
144 //
145 // Clear PGD series registers.
146 //
147 CsrWrite (LOONGARCH_CSR_PGDL, 0x0);
148 CsrWrite (LOONGARCH_CSR_PGDH, 0x0);
149
150 PageTable = 0;
151 while (MemoryTable->NumberOfPages != 0) {
152 DEBUG ((
153 DEBUG_INFO,
154 "%a %d VirtualBase %p VirtualEnd %p Attributes %p .\n",
155 __func__,
156 __LINE__,
157 MemoryTable->VirtualStart,
158 (EFI_PAGES_TO_SIZE (MemoryTable->NumberOfPages) + MemoryTable->VirtualStart),
159 MemoryTable->Attribute
160 ));
161
162 Status = MemoryRegionMap (
163 &PageTable,
164 PageWalkCfg,
165 MemoryTable->VirtualStart,
166 EFI_PAGES_TO_SIZE (MemoryTable->NumberOfPages),
167 MemoryTable->Attribute,
168 0x0
169 );
170
171 if (EFI_ERROR (Status)) {
172 return EFI_UNSUPPORTED;
173 }
174
175 MemoryTable++;
176 }
177
178 //
179 // Configure page walker.
180 //
181 CsrWrite (LOONGARCH_CSR_PWCTL0, (UINT32)PageWalkCfg);
182 if ((PageWalkCfg >> 32) != 0x0) {
183 CsrWrite (LOONGARCH_CSR_PWCTL1, (UINT32)(PageWalkCfg >> 32));
184 }
185
186 //
187 // Set page size
188 //
189 CsrXChg (LOONGARCH_CSR_TLBIDX, (DEFAULT_PAGE_SIZE << CSR_TLBIDX_SIZE), CSR_TLBIDX_SIZE_MASK);
190 CsrWrite (LOONGARCH_CSR_STLBPGSIZE, DEFAULT_PAGE_SIZE);
191 CsrXChg (LOONGARCH_CSR_TLBREHI, (DEFAULT_PAGE_SIZE << CSR_TLBREHI_PS_SHIFT), CSR_TLBREHI_PS);
192
193 //
194 // Enable MMU
195 //
196 CsrWrite (LOONGARCH_CSR_PGDL, PageTable);
197
198 //
199 // Enable Paging
200 //
201 CsrXChg (LOONGARCH_CSR_CRMD, BIT4, BIT4|BIT3);
202
203 DEBUG ((DEBUG_INFO, "%a %d Enable MMU Start PageBassAddress %p.\n", __func__, __LINE__, PageTable));
204
205 return EFI_SUCCESS;
206}
UINT64 UINTN
STATIC UINT8 DecidePageWalkConfiguration(IN OUT UINT64 *PageWalkCfg OPTIONAL, IN UINT8 BitWidth)
Definition: CpuMmuInit.c:42
EFI_STATUS EFIAPI ConfigureMemoryManagementUnit(IN EFI_MEMORY_DESCRIPTOR *MemoryTable)
Definition: CpuMmuInit.c:121
EFI_STATUS EFIAPI MemoryRegionMap(IN OUT UINTN *PageTable OPTIONAL, IN UINT64 PageWalkCfg, IN EFI_PHYSICAL_ADDRESS BaseAddress, IN UINT64 Length, IN UINT64 Attributes, IN UINT64 AttributeMask)
Definition: CpuMmu.c:694
UINTN EFIAPI CsrXChg(IN UINT16 Select, IN OUT UINTN Value, IN UINTN Mask)
Definition: Csr.c:75
UINTN EFIAPI CsrWrite(IN UINT16 Select, IN OUT UINTN Value)
Definition: Csr.c:55
#define NULL
Definition: Base.h:319
#define STATIC
Definition: Base.h:264
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define DEBUG(Expression)
Definition: DebugLib.h:434
#define EFI_PAGES_TO_SIZE(Pages)
Definition: UefiBaseType.h:213
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SUCCESS
Definition: UefiBaseType.h:112