diff --git a/headers/private/kernel/arch/arm/arm_mmu.h b/headers/private/kernel/arch/arm/arm_mmu.h index 730ebac43f..39abb00ddf 100644 --- a/headers/private/kernel/arch/arm/arm_mmu.h +++ b/headers/private/kernel/arch/arm/arm_mmu.h @@ -96,4 +96,7 @@ #define ARM_PTE_ADDRESS_MASK 0xfffff000 #define ARM_PTE_TYPE_MASK 0x00000003 +#define ARM_PTE_PROTECTION_MASK 0x00000231 // AP[2:0], XN +#define ARM_PTE_MEMORY_TYPE_MASK 0x000001cc // TEX, B, C + #endif /* _ARCH_ARM_ARM_MMU_H */ diff --git a/src/system/kernel/arch/arm/paging/32bit/ARMPagingMethod32Bit.cpp b/src/system/kernel/arch/arm/paging/32bit/ARMPagingMethod32Bit.cpp index 3b288d2c43..684ea41879 100644 --- a/src/system/kernel/arch/arm/paging/32bit/ARMPagingMethod32Bit.cpp +++ b/src/system/kernel/arch/arm/paging/32bit/ARMPagingMethod32Bit.cpp @@ -511,22 +511,10 @@ ARMPagingMethod32Bit::PutPageTableEntryInTable(page_table_entry* entry, { page_table_entry page = (physicalAddress & ARM_PTE_ADDRESS_MASK) | ARM_MMU_L2_TYPE_SMALLNEW - | ARM_MMU_L2_FLAG_B | ARM_MMU_L2_FLAG_C - | ARM_MMU_L2_FLAG_AP_RW; -#if 0 //IRA - | X86_PTE_PRESENT | (globalPage ? X86_PTE_GLOBAL : 0) - | MemoryTypeToPageTableEntryFlags(memoryType); + | MemoryTypeToPageTableEntryFlags(memoryType) + | AttributesToPageTableEntryFlags(attributes) + | (globalPage ? 0 : ARM_MMU_L2_FLAG_NG); - // if the page is user accessible, it's automatically - // accessible in kernel space, too (but with the same - // protection) - if ((attributes & B_USER_PROTECTION) != 0) { - page |= X86_PTE_USER; - if ((attributes & B_WRITE_AREA) != 0) - page |= X86_PTE_WRITABLE; - } else if ((attributes & B_KERNEL_WRITE_AREA) != 0) - page |= X86_PTE_WRITABLE; -#endif // put it in the page table *(volatile page_table_entry*)entry = page; } diff --git a/src/system/kernel/arch/arm/paging/32bit/ARMPagingMethod32Bit.h b/src/system/kernel/arch/arm/paging/32bit/ARMPagingMethod32Bit.h index 26a2c579dc..b36462be2c 100644 --- a/src/system/kernel/arch/arm/paging/32bit/ARMPagingMethod32Bit.h +++ b/src/system/kernel/arch/arm/paging/32bit/ARMPagingMethod32Bit.h @@ -69,6 +69,10 @@ public: static page_table_entry ClearPageTableEntryFlags( page_table_entry* entry, uint32 flags); + static uint32 AttributesToPageTableEntryFlags( + uint32 attributes); + static uint32 PageTableEntryFlagsToAttributes( + uint32 pageTableEntry); static uint32 MemoryTypeToPageTableEntryFlags( uint32 memoryType); @@ -139,37 +143,95 @@ ARMPagingMethod32Bit::ClearPageTableEntryFlags(page_table_entry* entry, uint32 f } +/*static*/ inline uint32 +ARMPagingMethod32Bit::AttributesToPageTableEntryFlags(uint32 attributes) +{ + int apFlags = 0; + + if ((attributes & B_WRITE_AREA) != 0) { + // kernel rw user rw + apFlags = ARM_MMU_L2_FLAG_AP1 | ARM_MMU_L2_FLAG_AP0; + } else if ((attributes & B_READ_AREA) != 0) { + if ((attributes & B_KERNEL_WRITE_AREA) != 0) { + // kernel rw user ro + apFlags = ARM_MMU_L2_FLAG_AP1; + } else { + // kernel ro user ro + apFlags = ARM_MMU_L2_FLAG_AP2 | ARM_MMU_L2_FLAG_AP1; + } + } else if ((attributes & B_KERNEL_WRITE_AREA) != 0) { + // kernel rw + apFlags = ARM_MMU_L2_FLAG_AP0; + } else { + // kernel ro + apFlags = ARM_MMU_L2_FLAG_AP2 | ARM_MMU_L2_FLAG_AP0; + } + + if (((attributes & B_KERNEL_EXECUTE_AREA) == 0) && + ((attributes & B_EXECUTE_AREA) == 0)) { + apFlags |= ARM_MMU_L2_FLAG_XN; + } + + return apFlags; +} + + +/*static*/ inline uint32 +ARMPagingMethod32Bit::PageTableEntryFlagsToAttributes(uint32 pageTableEntry) +{ + uint32 attributes; + + if ((pageTableEntry & ARM_MMU_L2_FLAG_AP2) == 0) { + if ((pageTableEntry & ARM_MMU_L2_FLAG_AP1) != 0) { + if ((pageTableEntry & ARM_MMU_L2_FLAG_AP0) != 0) + attributes = B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA | B_READ_AREA | B_WRITE_AREA; + else + attributes = B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA | B_READ_AREA; + } else { + if ((pageTableEntry & ARM_MMU_L2_FLAG_AP0) != 0) + attributes = B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA; + else + attributes = 0; + } + } else { + if ((pageTableEntry & ARM_MMU_L2_FLAG_AP1) != 0) + attributes = B_KERNEL_READ_AREA | B_READ_AREA; + else if ((pageTableEntry & ARM_MMU_L2_FLAG_AP0) != 0) + attributes = B_KERNEL_READ_AREA; + else + attributes = 0; + } + + if ((pageTableEntry & ARM_MMU_L2_FLAG_XN) == 0) { + if ((attributes & B_KERNEL_READ_AREA) != 0) + attributes |= B_KERNEL_EXECUTE_AREA; + if ((attributes & B_READ_AREA) != 0) + attributes |= B_EXECUTE_AREA; + } + + return attributes; +} + + /*static*/ inline uint32 ARMPagingMethod32Bit::MemoryTypeToPageTableEntryFlags(uint32 memoryType) { -#if 0 //IRA - // ATM we only handle the uncacheable and write-through type explicitly. For - // all other types we rely on the MTRRs to be set up correctly. Since we set - // the default memory type to write-back and since the uncacheable type in - // the PTE overrides any MTRR attribute (though, as per the specs, that is - // not recommended for performance reasons), this reduces the work we - // actually *have* to do with the MTRRs to setting the remaining types - // (usually only write-combining for the frame buffer). switch (memoryType) { case B_MTR_UC: - return X86_PTE_CACHING_DISABLED | X86_PTE_WRITE_THROUGH; - - case B_MTR_WC: - // ARM_PTE_WRITE_THROUGH would be closer, but the combination with - // MTRR WC is "implementation defined" for Pentium Pro/II. + // Strongly Ordered return 0; - + case B_MTR_WC: + // Shareable Device Memory + return ARM_MMU_L2_FLAG_B; case B_MTR_WT: - return X86_PTE_WRITE_THROUGH; - + // Outer and Inner Write-Through, no Write-Allocate + return ARM_MMU_L2_FLAG_C; case B_MTR_WP: case B_MTR_WB: default: - return 0; + // Outer and Inner Write-Back, no Write-Allocate + return ARM_MMU_L2_FLAG_B | ARM_MMU_L2_FLAG_C; } -#else - return 0; -#endif } diff --git a/src/system/kernel/arch/arm/paging/32bit/ARMVMTranslationMap32Bit.cpp b/src/system/kernel/arch/arm/paging/32bit/ARMVMTranslationMap32Bit.cpp index bcdea687ad..f872472473 100644 --- a/src/system/kernel/arch/arm/paging/32bit/ARMVMTranslationMap32Bit.cpp +++ b/src/system/kernel/arch/arm/paging/32bit/ARMVMTranslationMap32Bit.cpp @@ -638,23 +638,11 @@ ARMVMTranslationMap32Bit::Query(addr_t va, phys_addr_t *_physical, if ((entry & ARM_PTE_TYPE_MASK) != 0) *_physical = (entry & ARM_PTE_ADDRESS_MASK); -#if 0 //IRA - // read in the page state flags - if ((entry & X86_PTE_USER) != 0) { - *_flags |= ((entry & X86_PTE_WRITABLE) != 0 ? B_WRITE_AREA : 0) - | B_READ_AREA; - } - - *_flags |= ((entry & X86_PTE_WRITABLE) != 0 ? B_KERNEL_WRITE_AREA : 0) - | B_KERNEL_READ_AREA - | ((entry & ARM_PTE_DIRTY) != 0 ? PAGE_MODIFIED : 0) - | ((entry & ARM_PTE_ACCESSED) != 0 ? PAGE_ACCESSED : 0) - | ((entry & ARM_PTE_PRESENT) != 0 ? PAGE_PRESENT : 0); -#else - *_flags = B_KERNEL_WRITE_AREA | B_KERNEL_READ_AREA; + //TODO: read in the page state flags + *_flags = ARMPagingMethod32Bit::PageTableEntryFlagsToAttributes(entry); if (*_physical != 0) *_flags |= PAGE_PRESENT; -#endif + pinner.Unlock(); TRACE("query_tmap: returning pa 0x%lx for va 0x%lx\n", *_physical, va); @@ -686,23 +674,11 @@ ARMVMTranslationMap32Bit::QueryInterrupt(addr_t va, phys_addr_t *_physical, if ((entry & ARM_PTE_TYPE_MASK) != 0) *_physical = (entry & ARM_PTE_ADDRESS_MASK); -#if 0 - // read in the page state flags - if ((entry & X86_PTE_USER) != 0) { - *_flags |= ((entry & X86_PTE_WRITABLE) != 0 ? B_WRITE_AREA : 0) - | B_READ_AREA; - } - - *_flags |= ((entry & X86_PTE_WRITABLE) != 0 ? B_KERNEL_WRITE_AREA : 0) - | B_KERNEL_READ_AREA - | ((entry & X86_PTE_DIRTY) != 0 ? PAGE_MODIFIED : 0) - | ((entry & X86_PTE_ACCESSED) != 0 ? PAGE_ACCESSED : 0) - | ((entry & X86_PTE_PRESENT) != 0 ? PAGE_PRESENT : 0); -#else - *_flags = B_KERNEL_WRITE_AREA | B_KERNEL_READ_AREA; + //TODO: read in the page state flags + *_flags = ARMPagingMethod32Bit::PageTableEntryFlagsToAttributes(entry); if (*_physical != 0) *_flags |= PAGE_PRESENT; -#endif + return B_OK; } @@ -717,15 +693,9 @@ ARMVMTranslationMap32Bit::Protect(addr_t start, addr_t end, uint32 attributes, TRACE("protect_tmap: pages 0x%lx to 0x%lx, attributes %lx\n", start, end, attributes); -#if 0 //IRA - // compute protection flags - uint32 newProtectionFlags = 0; - if ((attributes & B_USER_PROTECTION) != 0) { - newProtectionFlags = ARM_PTE_USER; - if ((attributes & B_WRITE_AREA) != 0) - newProtectionFlags |= ARM_PTE_WRITABLE; - } else if ((attributes & B_KERNEL_WRITE_AREA) != 0) - newProtectionFlags = ARM_PTE_WRITABLE; + + uint32 newProtectionFlags = ARMPagingMethod32Bit::AttributesToPageTableEntryFlags(attributes); + uint32 newMemoryTypeFlags = ARMPagingMethod32Bit::MemoryTypeToPageTableEntryFlags(memoryType); page_directory_entry *pd = fPagingStructures->pgdir_virt; @@ -747,7 +717,7 @@ ARMVMTranslationMap32Bit::Protect(addr_t start, addr_t end, uint32 attributes, for (index = VADDR_TO_PTENT(start); index < 256 && start < end; index++, start += B_PAGE_SIZE) { page_table_entry entry = pt[index]; - if ((entry & ARM_PTE_PRESENT) == 0) { + if ((entry & ARM_PTE_TYPE_MASK) == 0) { // page mapping not valid continue; } @@ -762,24 +732,18 @@ ARMVMTranslationMap32Bit::Protect(addr_t start, addr_t end, uint32 attributes, &pt[index], (entry & ~(ARM_PTE_PROTECTION_MASK | ARM_PTE_MEMORY_TYPE_MASK)) - | newProtectionFlags - | ARMPagingMethod32Bit::MemoryTypeToPageTableEntryFlags( - memoryType), + | newProtectionFlags | newMemoryTypeFlags, entry); if (oldEntry == entry) break; entry = oldEntry; } - if ((oldEntry & ARM_PTE_ACCESSED) != 0) { - // Note, that we only need to invalidate the address, if the - // accessed flag was set, since only then the entry could have - // been in any TLB. - InvalidatePage(start); - } + //TODO: invalidate only if the Accessed flag is set + InvalidatePage(start); } } while (start != 0 && start < end); -#endif + return B_OK; }