From bb02cb8071e9df25cbcae15a9afa70d6387320cb Mon Sep 17 00:00:00 2001 From: andrewfish Date: Tue, 13 Apr 2010 19:27:03 +0000 Subject: [PATCH] Cleanup MMU code to do book required sync. Update exception handler to clear fault registers. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@10366 6f19259b-4bc3-4df7-8a09-765794883524 --- .../Drivers/CpuDxe/ExceptionSupport.ARMv6.S | 6 ++ .../Drivers/CpuDxe/ExceptionSupport.ARMv6.asm | 6 ++ ArmPkg/Drivers/CpuDxe/Mmu.c | 67 +++++++++++++------ ArmPkg/Include/Library/ArmLib.h | 4 +- ArmPkg/Library/ArmLib/ArmV7/ArmLibSupport.S | 38 +++++++++-- ArmPkg/Library/ArmLib/ArmV7/ArmLibSupport.asm | 61 ++++++++++++----- ArmPkg/Library/ArmLib/ArmV7/ArmV7Support.asm | 1 + .../DefaultExceptionHandler.c | 4 ++ 8 files changed, 141 insertions(+), 46 deletions(-) diff --git a/ArmPkg/Drivers/CpuDxe/ExceptionSupport.ARMv6.S b/ArmPkg/Drivers/CpuDxe/ExceptionSupport.ARMv6.S index 646aca76a4..bf9a4d4b76 100644 --- a/ArmPkg/Drivers/CpuDxe/ExceptionSupport.ARMv6.S +++ b/ArmPkg/Drivers/CpuDxe/ExceptionSupport.ARMv6.S @@ -256,6 +256,12 @@ CommonCExceptionHandler ( */ blx ASM_PFX(CommonCExceptionHandler) @ Call exception handler + + ldr R1, [SP, #0x4c] @ Restore EFI_SYSTEM_CONTEXT_ARM.IFSR + mcr p15, 0, R1, c5, c0, 1 @ Write IFSR + + ldr R1, [SP, #0x44] @ sRestore EFI_SYSTEM_CONTEXT_ARM.DFSR + mcr p15, 0, R1, c5, c0, 0 @ Write DFSR ldr R1,[SP,#0x3c] @ EFI_SYSTEM_CONTEXT_ARM.PC str R1,[SP,#0x58] @ Store it back to srsfd stack slot so it can be restored diff --git a/ArmPkg/Drivers/CpuDxe/ExceptionSupport.ARMv6.asm b/ArmPkg/Drivers/CpuDxe/ExceptionSupport.ARMv6.asm index 3bcca4d6aa..b45f6682a1 100644 --- a/ArmPkg/Drivers/CpuDxe/ExceptionSupport.ARMv6.asm +++ b/ArmPkg/Drivers/CpuDxe/ExceptionSupport.ARMv6.asm @@ -254,6 +254,12 @@ CommonCExceptionHandler ( */ blx CommonCExceptionHandler ; Call exception handler + ldr R1, [SP, #0x4c] ; Restore EFI_SYSTEM_CONTEXT_ARM.IFSR + mcr p15, 0, R1, c5, c0, 1 ; Write IFSR + + ldr R1, [SP, #0x44] ; sRestore EFI_SYSTEM_CONTEXT_ARM.DFSR + mcr p15, 0, R1, c5, c0, 0 ; Write DFSR + ldr R1,[SP,#0x3c] ; EFI_SYSTEM_CONTEXT_ARM.PC str R1,[SP,#0x58] ; Store it back to srsfd stack slot so it can be restored diff --git a/ArmPkg/Drivers/CpuDxe/Mmu.c b/ArmPkg/Drivers/CpuDxe/Mmu.c index e81e58a9b1..bcb66e5879 100644 --- a/ArmPkg/Drivers/CpuDxe/Mmu.c +++ b/ArmPkg/Drivers/CpuDxe/Mmu.c @@ -105,7 +105,7 @@ typedef UINT32 ARM_PAGE_TABLE_ENTRY; #define ARM_PAGE_TYPE_SMALL 0x2 #define ARM_PAGE_TYPE_SMALL_XN 0x3 -#define SMALL_PAGE_TABLE_ENTRY_COUNT (ARM_PAGE_DESC_ENTRY_MVA_SIZE / EFI_PAGE_SIZE) +#define SMALL_PAGE_TABLE_ENTRY_COUNT (ARM_PAGE_DESC_ENTRY_MVA_SIZE / SIZE_4KB) // Translation Table Base 0 fields @@ -434,6 +434,8 @@ UpdatePageEntries ( UINT32 p; UINT32 PageTableIndex; UINT32 PageTableEntry; + UINT32 CurrentPageTableEntry; + VOID *Mva; volatile ARM_FIRST_LEVEL_DESCRIPTOR *FirstLevelTable; volatile ARM_PAGE_TABLE_ENTRY *PageTable; @@ -492,7 +494,7 @@ UpdatePageEntries ( FirstLevelTable = (ARM_FIRST_LEVEL_DESCRIPTOR *)ArmGetTranslationTableBaseAddress (); // calculate number of 4KB page table entries to change - NumPageEntries = Length/EFI_PAGE_SIZE; + NumPageEntries = Length/SIZE_4KB; // iterate for the number of 4KB pages to change Offset = 0; @@ -525,10 +527,10 @@ UpdatePageEntries ( ASSERT (PageTableIndex < SMALL_PAGE_TABLE_ENTRY_COUNT); // get the entry - PageTableEntry = PageTable[PageTableIndex]; + CurrentPageTableEntry = PageTable[PageTableIndex]; // mask off appropriate fields - PageTableEntry &= ~EntryMask; + PageTableEntry = CurrentPageTableEntry & ~EntryMask; // mask in new attributes and/or permissions PageTableEntry |= EntryValue; @@ -537,13 +539,22 @@ UpdatePageEntries ( // Make this virtual address point at a physical page PageTableEntry &= ~VirtualMask; } - - // update the entry - PageTable[PageTableIndex] = PageTableEntry; + if (CurrentPageTableEntry != PageTableEntry) { + Mva = (VOID *)(UINTN)((((UINTN)FirstLevelIdx) << ARM_SECTION_BASE_SHIFT) + (PageTableIndex << ARM_SMALL_PAGE_BASE_SHIFT)); + if ((CurrentPageTableEntry & ARM_PAGE_C) == ARM_PAGE_C) { + // The current section mapping is cacheable so Clean/Invalidate the MVA of the page + // Note assumes switch(Attributes), not ARMv7 possibilities + WriteBackInvalidateDataCacheRange (Mva, SIZE_4KB); + } + + // Only need to update if we are changing the entry + PageTable[PageTableIndex] = PageTableEntry; + ArmUpdateTranslationTableEntry ((VOID *)&PageTable[PageTableIndex], Mva); + } Status = EFI_SUCCESS; - Offset += EFI_PAGE_SIZE; + Offset += SIZE_4KB; } // end first level translation table loop @@ -566,8 +577,9 @@ UpdateSectionEntries ( UINT32 FirstLevelIdx; UINT32 NumSections; UINT32 i; + UINT32 CurrentDescriptor; UINT32 Descriptor; - + VOID *Mva; volatile ARM_FIRST_LEVEL_DESCRIPTOR *FirstLevelTable; // EntryMask: bitmask of values to change (1 = change this value, 0 = leave alone) @@ -582,28 +594,28 @@ UpdateSectionEntries ( switch(Attributes) { case EFI_MEMORY_UC: // modify cacheability attributes - EntryMask |= ARM_SECTION_TEX_MASK | ARM_SECTION_C | ARM_SECTION_B; + EntryMask |= ARM_SECTION_CACHEABILITY_MASK; // map to strongly ordered EntryValue |= 0; // TEX[2:0] = 0, C=0, B=0 break; case EFI_MEMORY_WC: // modify cacheability attributes - EntryMask |= ARM_SECTION_TEX_MASK | ARM_SECTION_C | ARM_SECTION_B; + EntryMask |= ARM_SECTION_CACHEABILITY_MASK; // map to normal non-cachable EntryValue |= (0x1 << ARM_SECTION_TEX_SHIFT); // TEX [2:0]= 001 = 0x2, B=0, C=0 break; case EFI_MEMORY_WT: // modify cacheability attributes - EntryMask |= ARM_SECTION_TEX_MASK | ARM_SECTION_C | ARM_SECTION_B; + EntryMask |= ARM_SECTION_CACHEABILITY_MASK; // write through with no-allocate EntryValue |= ARM_SECTION_C; // TEX [2:0] = 0, C=1, B=0 break; case EFI_MEMORY_WB: // modify cacheability attributes - EntryMask |= ARM_SECTION_TEX_MASK | ARM_SECTION_C | ARM_SECTION_B; + EntryMask |= ARM_SECTION_CACHEABILITY_MASK; // write back (with allocate) EntryValue |= (0x1 << ARM_SECTION_TEX_SHIFT) | ARM_SECTION_C | ARM_SECTION_B; // TEX [2:0] = 001, C=1, B=1 break; @@ -635,17 +647,17 @@ UpdateSectionEntries ( // iterate through each descriptor for(i=0; iDFSR = 0; + SystemContext.SystemContextArm->IFSR = 0; + // If some one is stepping past the exception handler adjust the PC to point to the next instruction SystemContext.SystemContextArm->PC += PcAdjust; } -- 2.39.2