MmuLibCorePei.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. /** @file
  2. Platform PEI driver
  3. Copyright (c) 2022 Loongson Technology Corporation Limited. All rights reserved.<BR>
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. @par Glossary:
  6. - FwCfg - Firmeware Config
  7. - Tlb - Translation Lookaside Buffer
  8. **/
  9. #include <Uefi.h>
  10. #include <Library/BaseMemoryLib.h>
  11. #include <Library/MemoryAllocationLib.h>
  12. #include <Library/BaseLib.h>
  13. #include <Library/DebugLib.h>
  14. #include "Library/Cpu.h"
  15. #include "pte.h"
  16. #include "page.h"
  17. #include "mmu.h"
  18. #include <Library/QemuFwCfgLib.h>
  19. #include "MmuLibCore.h"
  20. #include <Library/CacheMaintenanceLib.h>
  21. #include <Library/MmuLib.h>
  22. /**
  23. Return the Virtual Memory Map of your platform
  24. This Virtual Memory Map is used by MemoryInitPei Module to initialize the MMU
  25. on your platform.
  26. @param[out] VirtualMemoryMap Array of MEMORY_REGION_DESCRIPTOR
  27. describing a Physical-to-Virtual Memory
  28. mapping. This array must be ended by a
  29. zero-filled entry. The allocated memory
  30. will not be freed.
  31. **/
  32. VOID
  33. GetMemoryMapFromFwCfg (
  34. OUT MEMORY_REGION_DESCRIPTOR **VirtualMemoryMap
  35. )
  36. {
  37. EFI_STATUS Status;
  38. FIRMWARE_CONFIG_ITEM FwCfgItem;
  39. UINTN FwCfgSize;
  40. LOONGARCH_MEMMAP_ENTRY MemoryMapEntry;
  41. LOONGARCH_MEMMAP_ENTRY *StartEntry;
  42. LOONGARCH_MEMMAP_ENTRY *pEntry;
  43. UINTN Processed;
  44. MEMORY_REGION_DESCRIPTOR *VirtualMemoryTable;
  45. UINTN Index = 0;
  46. ASSERT (VirtualMemoryMap != NULL);
  47. VirtualMemoryTable = AllocatePool (
  48. sizeof (MEMORY_REGION_DESCRIPTOR) *
  49. MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS
  50. );
  51. VirtualMemoryTable[Index].PhysicalBase = 0x10000000;
  52. VirtualMemoryTable[Index].VirtualBase = VirtualMemoryTable[Index].PhysicalBase;
  53. VirtualMemoryTable[Index].Length = 0x10000000;
  54. VirtualMemoryTable[Index].Attributes = PAGE_VALID | PLV_KERNEL | CACHE_SUC | PAGE_DIRTY | PAGE_GLOBAL;
  55. ++Index;
  56. Status = QemuFwCfgFindFile ("etc/memmap", &FwCfgItem, &FwCfgSize);
  57. if (EFI_ERROR (Status)) {
  58. DEBUG ((DEBUG_ERROR, "%a %d read etc/memmap error Status %d \n", __func__, __LINE__, Status));
  59. ZeroMem (&VirtualMemoryTable[Index], sizeof (MEMORY_REGION_DESCRIPTOR));
  60. *VirtualMemoryMap = VirtualMemoryTable;
  61. return ;
  62. }
  63. if (FwCfgSize % sizeof MemoryMapEntry != 0) {
  64. DEBUG ((DEBUG_ERROR, "no MemoryMapEntry FwCfgSize:%d\n", FwCfgSize));
  65. }
  66. QemuFwCfgSelectItem (FwCfgItem);
  67. StartEntry = AllocatePages (EFI_SIZE_TO_PAGES (FwCfgSize));
  68. QemuFwCfgReadBytes (FwCfgSize, StartEntry);
  69. for (Processed = 0; Processed < (FwCfgSize / sizeof MemoryMapEntry); Processed++) {
  70. pEntry = StartEntry + Processed;
  71. if (pEntry->Length == 0) {
  72. continue;
  73. }
  74. DEBUG ((DEBUG_INFO, "MemmapEntry Base %p length %p type %d\n", pEntry->BaseAddr, pEntry->Length, pEntry->Type));
  75. VirtualMemoryTable[Index].PhysicalBase = pEntry->BaseAddr;
  76. VirtualMemoryTable[Index].VirtualBase = VirtualMemoryTable[Index].PhysicalBase;
  77. VirtualMemoryTable[Index].Length = pEntry->Length;
  78. VirtualMemoryTable[Index].Attributes = PAGE_VALID | PLV_KERNEL | CACHE_CC | PAGE_DIRTY | PAGE_GLOBAL;
  79. ++Index;
  80. }
  81. FreePages (StartEntry, EFI_SIZE_TO_PAGES (FwCfgSize));
  82. // End of Table
  83. ZeroMem (&VirtualMemoryTable[Index], sizeof (MEMORY_REGION_DESCRIPTOR));
  84. *VirtualMemoryMap = VirtualMemoryTable;
  85. return ;
  86. }
  87. /**
  88. Create a page table and initialize the MMU.
  89. @param[] VOID
  90. @retval VOID
  91. **/
  92. EFIAPI
  93. VOID
  94. ConfigureMmu (VOID)
  95. {
  96. PGD *SwapperPageDir = NULL;
  97. PGD *InvalidPgd = NULL;
  98. PUD *InvalidPudTable = NULL;
  99. PMD *InvalidPmdTable = NULL;
  100. PTE *InvalidPteTable = NULL;
  101. MEMORY_REGION_DESCRIPTOR *MemoryTable = NULL;
  102. RETURN_STATUS PcdStatus;
  103. UINTN PgdShift = PGD_SHIFT;
  104. UINTN PgdWide = PGD_WIDE;
  105. UINTN PudShift = PUD_SHIFT;
  106. UINTN PudWide = PUD_WIDE;
  107. UINTN PmdShift = PMD_SHIFT;
  108. UINTN PmdWide = PMD_WIDE;
  109. UINTN PteShift = PTE_SHIFT;
  110. UINTN PteWide = PTE_WIDE;
  111. UINTN PageEnable = 1 << 4;
  112. VOID *TlbReEntry;
  113. SwapperPageDir = AllocatePages (EFI_SIZE_TO_PAGES (PGD_TABLE_SIZE));
  114. InvalidPgd = AllocatePages (EFI_SIZE_TO_PAGES (PGD_TABLE_SIZE));
  115. InvalidPudTable = AllocatePages (EFI_SIZE_TO_PAGES (PUD_TABLE_SIZE));
  116. InvalidPmdTable = AllocatePages (EFI_SIZE_TO_PAGES (PMD_TABLE_SIZE));
  117. InvalidPteTable = AllocatePages (EFI_SIZE_TO_PAGES (PTE_TABLE_SIZE));
  118. ZeroMem (InvalidPteTable, PTE_TABLE_SIZE);
  119. if ((!InvalidPgd) ||
  120. (!InvalidPudTable) ||
  121. (!InvalidPmdTable) ||
  122. (!InvalidPteTable))
  123. {
  124. goto FreeTranslationTable;
  125. }
  126. /*pgd init*/
  127. PageDirInit (SwapperPageDir , ENTRYS_PER_PGD, InvalidPudTable);
  128. /*pgd init*/
  129. PageDirInit (InvalidPgd, ENTRYS_PER_PGD, InvalidPudTable);
  130. /*pud init*/
  131. PageDirInit (InvalidPudTable, ENTRYS_PER_PUD, InvalidPmdTable);
  132. /*pmd init*/
  133. PageDirInit (InvalidPmdTable, ENTRYS_PER_PMD, InvalidPteTable);
  134. GetMemoryMapFromFwCfg (&MemoryTable);
  135. PcdStatus |= PcdSet64S (PcdSwapPageDir, (UINTN)SwapperPageDir);
  136. PcdStatus |= PcdSet64S (PcdInvalidPgd, (UINTN)InvalidPgd);
  137. PcdStatus |= PcdSet64S (PcdInvalidPud, (UINTN)InvalidPudTable);
  138. PcdStatus |= PcdSet64S (PcdInvalidPmd, (UINTN)InvalidPmdTable);
  139. PcdStatus |= PcdSet64S (PcdInvalidPte, (UINTN)InvalidPteTable);
  140. ASSERT_RETURN_ERROR (PcdStatus);
  141. while (MemoryTable->Length != 0) {
  142. DEBUG ((DEBUG_VERBOSE, "%a %d VirtualBase %p VirtualEnd %p Attributes %p .\n", __func__, __LINE__,
  143. MemoryTable->VirtualBase,
  144. (MemoryTable->Length + MemoryTable->VirtualBase),
  145. MemoryTable->Attributes));
  146. PcdStatus = FillTranslationTable (MemoryTable);
  147. if (EFI_ERROR (PcdStatus)) {
  148. goto FreeTranslationTable;
  149. }
  150. MemoryTable++;
  151. }
  152. if (PcdGet8 (PcdNullPointerDetectionPropertyMask) & BIT0) {
  153. LoongArchSetMemoryAttributes (0, EFI_PAGE_SIZE, EFI_MEMORY_RP | EFI_MEMORY_XP | EFI_MEMORY_WP);
  154. }
  155. TlbReEntry = AllocatePages (1);
  156. if (TlbReEntry == NULL) {
  157. goto FreeTranslationTable;
  158. }
  159. CopyMem ((char *)TlbReEntry, HandleTlbRefill, (HandleTlbRefillEnd - HandleTlbRefill));
  160. InvalidateInstructionCacheRange ((VOID *)(UINTN)HandleTlbRefill, (UINTN)(HandleTlbRefillEnd - HandleTlbRefill));
  161. DEBUG ((DEBUG_VERBOSE,
  162. "%a %d PteShift %d PteWide %d PmdShift %d PmdWide %d PudShift %d PudWide %d PgdShift %d PgdWide %d.\n",
  163. __func__, __LINE__,
  164. PteShift, PteWide, PmdShift, PmdWide,PudShift, PudWide, PgdShift, PgdWide));
  165. SetTlbRefillFuncBase ((UINTN)TlbReEntry);
  166. /*set page size*/
  167. WriteCsrPageSize (DEFAULT_PAGE_SIZE);
  168. WriteCsrStlbPageSize (DEFAULT_PAGE_SIZE);
  169. WriteCsrTlbRefillPageSize (DEFAULT_PAGE_SIZE);
  170. LoongArchWriteqCsrPwctl0 ((PteShift | PteWide << 5 | PmdShift << 10 | PmdWide << 15 | PudShift << 20 | PudWide << 25
  171. ));
  172. LoongArchWriteqCsrPwctl1 (PgdShift | PgdWide << 6);
  173. LoongArchWriteqCsrPgdl ((UINTN)SwapperPageDir);
  174. LoongArchWriteqCsrPgdh ((UINTN)InvalidPgd);
  175. DEBUG ((DEBUG_INFO, "%a %d Enable Mmu Start PageBassAddress %p.\n", __func__, __LINE__, SwapperPageDir));
  176. LoongArchXchgCsrCrmd ( PageEnable, 1 << 4);
  177. DEBUG ((DEBUG_INFO, "%a %d Enable Mmu End.\n", __func__, __LINE__));
  178. return ;
  179. FreeTranslationTable:
  180. if (SwapperPageDir) {
  181. FreePages (SwapperPageDir, EFI_SIZE_TO_PAGES (PGD_TABLE_SIZE));
  182. }
  183. if (InvalidPgd) {
  184. FreePages (InvalidPgd, EFI_SIZE_TO_PAGES (PGD_TABLE_SIZE));
  185. }
  186. if (InvalidPudTable) {
  187. FreePages (InvalidPudTable, EFI_SIZE_TO_PAGES (PUD_TABLE_SIZE));
  188. }
  189. if (InvalidPmdTable) {
  190. FreePages (InvalidPmdTable, EFI_SIZE_TO_PAGES (PMD_TABLE_SIZE));
  191. }
  192. if (InvalidPteTable) {
  193. FreePages (InvalidPteTable, EFI_SIZE_TO_PAGES (PTE_TABLE_SIZE));
  194. }
  195. PcdSet64S (PcdSwapPageDir, (UINTN)0);
  196. PcdSet64S (PcdInvalidPgd, (UINTN)0);
  197. PcdSet64S (PcdInvalidPud, (UINTN)0);
  198. PcdSet64S (PcdInvalidPmd, (UINTN)0);
  199. PcdSet64S (PcdInvalidPte, (UINTN)0);
  200. return ;
  201. }