41 if (
CsrRead (LOONGARCH_CSR_PGDL) != 0) {
62 if ((
CsrRead (LOONGARCH_CSR_CRMD) & BIT4) != 0) {
84 if (Entry != INVALID_PAGE) {
106 if ((Entry & (PAGE_HGLOBAL | PAGE_HUGE)) == (PAGE_HGLOBAL | PAGE_HUGE)) {
144 IN UINT64 PageWalkCfg
150 Pwctl0 = PageWalkCfg & MAX_UINT32;
151 Pwctl1 = (PageWalkCfg >> 32) & MAX_UINT32;
153 if (((Pwctl1 >> 18) & 0x3F) != 0x0) {
155 }
else if (((Pwctl1 >> 6) & 0x3F) != 0x0) {
157 }
else if (((Pwctl0 >> 25) & 0x3F) != 0x0) {
177 IN UINT64 PageWalkCfg
183 return ((PageWalkCfg >> 5) & 0x1F);
202 IN UINT64 PageWalkCfg
228 IN UINT64 PageWalkCfg
259 IN BOOLEAN IsLiveBlockMapping
264 if (IsLiveBlockMapping &&
MmuIsInit ()) {
283 return ((Entry & PTE_PPN_MASK) >> PTE_PPN_SHIFT);
304 Ppn = ((Address >> LOONGARCH_MMU_PAGE_SHIFT) << PTE_PPN_SHIFT);
305 ASSERT (~(Ppn & ~PTE_PPN_MASK));
306 Entry &= ~PTE_PPN_MASK;
322 IN UINT64 PageWalkCfg,
332 for (Index = 0; Index < TableEntryNum; Index++) {
333 if (
IsTableEntry (TranslationTable[Index], Level, PageWalkCfg)) {
336 LOONGARCH_MMU_PAGE_SHIFT),
372 IN UINT64 PageWalkCfg,
373 IN BOOLEAN TableIsLive
382 UINTN *TranslationTable;
385 BOOLEAN NextTableIsLive;
388 ASSERT (((RegionStart | RegionEnd) & EFI_PAGE_MASK) == 0);
391 BlockShift = (
ParseMaxPageTableLevel (PageWalkCfg) - Level - 1) * TableBitWidth + LOONGARCH_MMU_PAGE_SHIFT;
397 "%a(%d): %llx - %llx set %lx clr %lx\n",
407 TableEntryNum = (1 << TableBitWidth);
408 for ( ; RegionStart < RegionEnd; RegionStart = BlockEnd) {
409 BlockEnd =
MIN (RegionEnd, (RegionStart | BlockMask) + 1);
410 Entry = &PageTable[(RegionStart >> BlockShift) & (TableEntryNum - 1)];
420 (((RegionStart | BlockEnd) & BlockMask) != 0) ||
IsTableEntry (*Entry, Level, PageWalkCfg))
429 if (TranslationTable ==
NULL) {
430 return EFI_OUT_OF_RESOURCES;
433 ZeroMem (TranslationTable, EFI_PAGE_SIZE);
441 RegionStart & ~BlockMask,
442 (RegionStart | BlockMask) + 1,
443 *Entry & PTE_ATTRIBUTES_MASK,
450 if (EFI_ERROR (Status)) {
461 NextTableIsLive =
FALSE;
464 NextTableIsLive = TableIsLive;
480 if (EFI_ERROR (Status)) {
505 EntryValue = (*Entry & ~AttributeClearMask) | AttributeSetMask;
507 EntryValue =
SetPpnToPte (EntryValue, RegionStart);
511 EntryValue |= (PAGE_HGLOBAL | PAGE_HUGE |
PAGE_VALID);
543 IN UINT64 PageWalkCfg,
547 IN BOOLEAN TableIsLive
550 if (((RegionStart | RegionLength) & EFI_PAGE_MASK) != 0) {
551 return EFI_INVALID_PARAMETER;
556 RegionStart + RegionLength,
576 IN UINT64 EfiAttributes
579 UINT64 LoongArchAttributes;
581 LoongArchAttributes =
PAGE_VALID | PAGE_DIRTY | PLV_KERNEL | PAGE_GLOBAL;
583 switch (EfiAttributes & EFI_CACHE_ATTRIBUTE_MASK) {
585 LoongArchAttributes |= CACHE_SUC;
588 LoongArchAttributes |= CACHE_WUC;
592 LoongArchAttributes |= CACHE_CC;
595 LoongArchAttributes &= ~PAGE_DIRTY;
602 switch (EfiAttributes & EFI_MEMORY_ACCESS_MASK) {
604 LoongArchAttributes |= PAGE_NO_READ;
607 LoongArchAttributes |= PAGE_NO_EXEC;
610 LoongArchAttributes &= ~PAGE_DIRTY;
616 return LoongArchAttributes;
634 UINTN TlbReEntryOffset;
647 TlbReEntryOffset = (MAX_LOONGARCH_EXCEPTION + MAX_LOONGARCH_INTERRUPT) * 512;
648 Remaining = TlbReEntryOffset % SIZE_4KB;
649 if (Remaining != 0x0) {
650 TlbReEntryOffset += (SIZE_4KB - Remaining);
653 TlbReEntry =
PcdGet64 (PcdLoongArchExceptionVectorBaseAddress) + TlbReEntryOffset;
654 if ((TlbReEntryOffset + Length) > SIZE_64KB) {
655 return EFI_UNSUPPORTED;
661 if (TlbReEntry & (SIZE_4KB - 1)) {
662 return EFI_UNSUPPORTED;
671 SetTlbRebaseAddress ((
UINTN)TlbReEntry);
696 IN UINT64 PageWalkCfg,
699 IN UINT64 Attributes,
700 IN UINT64 AttributeMask
704 UINT64 LoongArchAttributes;
705 BOOLEAN Initialization;
707 UINTN PageTableBitWidth;
711 if ((PageTable ==
NULL) || (PageWalkCfg == 0)) {
712 return EFI_INVALID_PARAMETER;
718 if ((!PageTableBitWidth && !MaxLevel) || (PageTableBitWidth > 0x1F) || (MaxLevel > LEVEL5)) {
719 return EFI_INVALID_PARAMETER;
722 Initialization =
FALSE;
728 if (*PageTable == 0) {
734 Initialization =
TRUE;
742 if (Initialization ==
TRUE) {
747 if (CreateNew ==
TRUE) {
751 PgdSize = (1 << PageTableBitWidth) *
sizeof (
UINTN);
753 ZeroMem ((VOID *)*PageTable, PgdSize);
755 if ((VOID *)*PageTable ==
NULL) {
756 return EFI_UNSUPPORTED;
777 (
UINTN *)(*PageTable),
VOID *EFIAPI InvalidateInstructionCacheRange(IN VOID *Address, IN UINTN Length)
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
EFI_STATUS TlbRefillHandlerConfigure(VOID)
STATIC BOOLEAN MmuIsInit(VOID)
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)
UINT64 EFIAPI EfiAttributeConverse(IN UINT64 EfiAttributes)
STATIC EFI_STATUS UpdateRegionMappingRecursive(IN UINTN RegionStart, IN UINTN RegionEnd, IN UINTN AttributeSetMask, IN UINTN AttributeClearMask, IN UINTN *PageTable, IN UINTN Level, IN UINT64 PageWalkCfg, IN BOOLEAN TableIsLive)
STATIC BOOLEAN IsBlockEntry(IN UINTN Entry, IN UINTN Level, IN UINT64 PageWalkCfg)
STATIC BOOLEAN IsValidPte(IN UINTN Entry)
STATIC UINTN SetPpnToPte(UINTN Entry, UINTN Address)
STATIC UINTN GetPpnfromPte(IN UINTN Entry)
STATIC BOOLEAN IsValidHugePage(IN UINTN Entry)
STATIC UINTN SetValidPte(IN UINTN Entry)
STATIC VOID FreePageTablesRecursive(IN UINTN *TranslationTable, IN UINT64 PageWalkCfg, IN UINTN Level)
STATIC UINTN ParseMaxPageTableLevel(IN UINT64 PageWalkCfg)
STATIC BOOLEAN IsTableEntry(IN UINTN Entry, IN UINTN Level, IN UINT64 PageWalkCfg)
EFI_STATUS UpdateRegionMapping(IN UINTN RegionStart, IN UINTN RegionLength, IN UINT64 PageWalkCfg, IN UINTN AttributeSetMask, IN UINTN AttributeClearMask, IN UINTN *RootTable, IN BOOLEAN TableIsLive)
STATIC VOID ReplaceTableEntry(IN UINTN *Entry, IN UINTN Value, IN UINTN RegionStart, IN BOOLEAN IsLiveBlockMapping)
STATIC BOOLEAN MmuIsEnabled(VOID)
STATIC UINTN ParsePageTableBitWidth(IN UINT64 PageWalkCfg)
UINTN EFIAPI CsrRead(IN UINT16 Select)
VOID EFIAPI FreePages(IN VOID *Buffer, IN UINTN Pages)
#define ASSERT_EFI_ERROR(StatusParameter)
#define DEBUG(Expression)
#define PcdGet64(TokenName)
VOID *EFIAPI AllocatePages(IN UINTN Pages)
VOID HandleTlbRefillEnd(VOID)
VOID HandleTlbRefillStart(VOID)
VOID InvalidTlb(UINTN Address)
UINT64 EFI_PHYSICAL_ADDRESS
#define EFI_SIZE_TO_PAGES(Size)