1 /* 2 * PROJECT: ReactOS Kernel 3 * LICENSE: BSD - See COPYING.ARM in the top level directory 4 * FILE: ntoskrnl/mm/ARM3/ncache.c 5 * PURPOSE: ARM Memory Manager Noncached Memory Allocator 6 * PROGRAMMERS: ReactOS Portable Systems Group 7 */ 8 9 /* INCLUDES *******************************************************************/ 10 11 #include <ntoskrnl.h> 12 #define NDEBUG 13 #include <debug.h> 14 15 #define MODULE_INVOLVED_IN_ARM3 16 #include <mm/ARM3/miarm.h> 17 18 /* GLOBALS ********************************************************************/ 19 20 /* 21 * @implemented 22 */ 23 PVOID 24 NTAPI 25 MmAllocateNonCachedMemory(IN SIZE_T NumberOfBytes) 26 { 27 PFN_COUNT PageCount, MdlPageCount; 28 PFN_NUMBER PageFrameIndex; 29 PHYSICAL_ADDRESS LowAddress, HighAddress, SkipBytes; 30 MI_PFN_CACHE_ATTRIBUTE CacheAttribute; 31 PMDL Mdl; 32 PVOID BaseAddress; 33 PPFN_NUMBER MdlPages; 34 PMMPTE PointerPte; 35 MMPTE TempPte; 36 37 // 38 // Get the page count 39 // 40 ASSERT(NumberOfBytes != 0); 41 PageCount = (PFN_COUNT)BYTES_TO_PAGES(NumberOfBytes); 42 43 // 44 // Use the MDL allocator for simplicity, so setup the parameters 45 // 46 LowAddress.QuadPart = 0; 47 HighAddress.QuadPart = -1; 48 SkipBytes.QuadPart = 0; 49 CacheAttribute = MiPlatformCacheAttributes[0][MmNonCached]; 50 51 // 52 // Now call the MDL allocator 53 // 54 Mdl = MiAllocatePagesForMdl(LowAddress, 55 HighAddress, 56 SkipBytes, 57 NumberOfBytes, 58 CacheAttribute, 59 0); 60 if (!Mdl) return NULL; 61 62 // 63 // Get the MDL VA and check how many pages we got (could be partial) 64 // 65 BaseAddress = (PVOID)((ULONG_PTR)Mdl->StartVa + Mdl->ByteOffset); 66 MdlPageCount = ADDRESS_AND_SIZE_TO_SPAN_PAGES(BaseAddress, Mdl->ByteCount); 67 if (PageCount != MdlPageCount) 68 { 69 // 70 // Unlike MDLs, partial isn't okay for a noncached allocation, so fail 71 // 72 ASSERT(PageCount > MdlPageCount); 73 MmFreePagesFromMdl(Mdl); 74 ExFreePoolWithTag(Mdl, TAG_MDL); 75 return NULL; 76 } 77 78 // 79 // Allocate system PTEs for the base address 80 // We use an extra page to store the actual MDL pointer for the free later 81 // 82 PointerPte = MiReserveSystemPtes(PageCount + 1, SystemPteSpace); 83 if (!PointerPte) 84 { 85 // 86 // Out of memory... 87 // 88 MmFreePagesFromMdl(Mdl); 89 ExFreePoolWithTag(Mdl, TAG_MDL); 90 return NULL; 91 } 92 93 // 94 // Store the MDL pointer 95 // 96 *(PMDL*)PointerPte++ = Mdl; 97 98 // 99 // Okay, now see what range we got 100 // 101 BaseAddress = MiPteToAddress(PointerPte); 102 103 // 104 // This is our array of pages 105 // 106 MdlPages = (PPFN_NUMBER)(Mdl + 1); 107 108 // 109 // Setup the template PTE 110 // 111 TempPte = ValidKernelPte; 112 113 // 114 // Now check what kind of caching we should use 115 // 116 switch (CacheAttribute) 117 { 118 case MiNonCached: 119 120 // 121 // Disable caching 122 // 123 MI_PAGE_DISABLE_CACHE(&TempPte); 124 MI_PAGE_WRITE_THROUGH(&TempPte); 125 break; 126 127 case MiWriteCombined: 128 129 // 130 // Enable write combining 131 // 132 MI_PAGE_DISABLE_CACHE(&TempPte); 133 MI_PAGE_WRITE_COMBINED(&TempPte); 134 break; 135 136 default: 137 // 138 // Nothing to do 139 // 140 break; 141 } 142 143 // 144 // Now loop the MDL pages 145 // 146 do 147 { 148 // 149 // Get the PFN 150 // 151 PageFrameIndex = *MdlPages++; 152 153 // 154 // Set the PFN in the page and write it 155 // 156 TempPte.u.Hard.PageFrameNumber = PageFrameIndex; 157 MI_WRITE_VALID_PTE(PointerPte++, TempPte); 158 } while (--PageCount); 159 160 // 161 // Return the base address 162 // 163 return BaseAddress; 164 165 } 166 167 /* 168 * @implemented 169 */ 170 VOID 171 NTAPI 172 MmFreeNonCachedMemory(IN PVOID BaseAddress, 173 IN SIZE_T NumberOfBytes) 174 { 175 PMDL Mdl; 176 PMMPTE PointerPte; 177 PFN_COUNT PageCount; 178 179 // 180 // Sanity checks 181 // 182 ASSERT(NumberOfBytes != 0); 183 ASSERT(PAGE_ALIGN(BaseAddress) == BaseAddress); 184 185 // 186 // Get the page count 187 // 188 PageCount = (PFN_COUNT)BYTES_TO_PAGES(NumberOfBytes); 189 190 // 191 // Get the first PTE 192 // 193 PointerPte = MiAddressToPte(BaseAddress); 194 195 // 196 // Remember this is where we store the shadow MDL pointer 197 // 198 Mdl = *(PMDL*)(--PointerPte); 199 200 // 201 // Kill the MDL (and underlying pages) 202 // 203 MmFreePagesFromMdl(Mdl); 204 ExFreePoolWithTag(Mdl, TAG_MDL); 205 206 // 207 // Now free the system PTEs for the underlying VA 208 // 209 MiReleaseSystemPtes(PointerPte, PageCount + 1, SystemPteSpace); 210 } 211 212 /* EOF */ 213