1 /* 2 * Copyright 2022 Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 */ 5 #ifndef VMSA_V8_TRANSLATION_MAP_H 6 #define VMSA_V8_TRANSLATION_MAP_H 7 8 9 #include <arch_cpu_defs.h> 10 #include <vm/VMTranslationMap.h> 11 12 13 static constexpr uint64_t kPteAddrMask = (((1UL << 36) - 1) << 12); 14 static constexpr uint64_t kPteAttrMask = ~(kPteAddrMask | 0x3); 15 static constexpr uint64_t kPteTLBCompatMask = (kPteAddrMask | (0x3 << 2) | (0x3 << 8)); 16 17 static constexpr uint64_t kPteValidMask = 0x1; 18 static constexpr uint64_t kPteTypeMask = 0x3; 19 static constexpr uint64_t kPteTypeL012Table = 0x3; 20 static constexpr uint64_t kPteTypeL12Block = 0x1; 21 static constexpr uint64_t kPteTypeL3Page = 0x3; 22 23 static constexpr uint64_t kAttrSWDIRTY = (1UL << 56); 24 static constexpr uint64_t kAttrSWDBM = (1UL << 55); 25 static constexpr uint64_t kAttrUXN = (1UL << 54); 26 static constexpr uint64_t kAttrPXN = (1UL << 53); 27 static constexpr uint64_t kAttrDBM = (1UL << 51); 28 static constexpr uint64_t kAttrNG = (1UL << 11); 29 static constexpr uint64_t kAttrAF = (1UL << 10); 30 static constexpr uint64_t kAttrShareability = (3UL << 8); 31 static constexpr uint64_t kAttrSHInnerShareable = (3UL << 8); 32 static constexpr uint64_t kAttrAPReadOnly = (1UL << 7); 33 static constexpr uint64_t kAttrAPUserAccess = (1UL << 6); 34 static constexpr uint64_t kAttrMemoryAttrIdx = (3UL << 2); 35 36 static constexpr uint64_t kTLBIMask = ((1UL << 44) - 1); 37 static constexpr uint64_t kASIDMask = 0xFF00000000000000UL; 38 39 40 struct VMSAv8TranslationMap : public VMTranslationMap { 41 public: 42 VMSAv8TranslationMap( 43 bool kernel, phys_addr_t pageTable, int pageBits, int vaBits, int minBlockLevel); 44 ~VMSAv8TranslationMap(); 45 46 virtual bool Lock(); 47 virtual void Unlock(); 48 49 virtual addr_t MappedSize() const; 50 virtual size_t MaxPagesNeededToMap(addr_t start, 51 addr_t end) const; 52 53 virtual status_t Map(addr_t virtualAddress, 54 phys_addr_t physicalAddress, 55 uint32 attributes, uint32 memoryType, 56 vm_page_reservation* reservation); 57 virtual status_t Unmap(addr_t start, addr_t end); 58 59 virtual status_t UnmapPage(VMArea* area, addr_t address, 60 bool updatePageQueue); 61 virtual void UnmapPages(VMArea* area, addr_t base, 62 size_t size, bool updatePageQueue); 63 virtual void UnmapArea(VMArea* area, 64 bool deletingAddressSpace, 65 bool ignoreTopCachePageFlags); 66 67 virtual status_t Query(addr_t virtualAddress, 68 phys_addr_t* _physicalAddress, 69 uint32* _flags); 70 virtual status_t QueryInterrupt(addr_t virtualAddress, 71 phys_addr_t* _physicalAddress, 72 uint32* _flags); 73 74 virtual status_t Protect(addr_t base, addr_t top, 75 uint32 attributes, uint32 memoryType); 76 77 virtual status_t ClearFlags(addr_t virtualAddress, 78 uint32 flags); 79 80 virtual bool ClearAccessedAndModified( 81 VMArea* area, addr_t address, 82 bool unmapIfUnaccessed, 83 bool& _modified); 84 85 virtual void Flush(); 86 87 enum HWFeature { 88 // Can HW update Access and Dirty flags, respectively? 89 HW_ACCESS = 0x1, 90 HW_DIRTY = 0x2, 91 92 // Can we use the CNP bit to indicate that ASIDs are consistent across cores? 93 HW_COMMON_NOT_PRIVATE = 0x4 94 }; 95 96 static uint32_t fHwFeature; 97 static uint64_t fMair; 98 99 static uint64_t GetMemoryAttr(uint32 attributes, uint32 memoryType, bool isKernel); 100 static int CalcStartLevel(int vaBits, int pageBits); 101 102 static void SwitchUserMap(VMSAv8TranslationMap *from, VMSAv8TranslationMap *to); 103 104 private: 105 bool fIsKernel; 106 phys_addr_t fPageTable; 107 int fPageBits; 108 int fVaBits; 109 int fMinBlockLevel; 110 int fInitialLevel; 111 int fASID; 112 int fRefcount; 113 114 private: 115 static uint8_t MairIndex(uint8_t type); 116 bool ValidateVa(addr_t va); 117 uint64_t* TableFromPa(phys_addr_t pa); 118 template<typename EntryRemoved> 119 void FreeTable(phys_addr_t ptPa, uint64_t va, int level, EntryRemoved &&entryRemoved); 120 phys_addr_t GetOrMakeTable(phys_addr_t ptPa, int level, int index, vm_page_reservation* reservation); 121 template<typename UpdatePte> 122 void ProcessRange(phys_addr_t ptPa, int level, addr_t va, size_t size, 123 vm_page_reservation* reservation, UpdatePte &&updatePte); 124 bool AttemptPteBreakBeforeMake(uint64_t* ptePtr, uint64_t oldPte, addr_t va); 125 bool FlushVAIfAccessed(uint64_t pte, addr_t va); 126 }; 127 128 129 #endif 130