Merge 36852, 37322, 37333, 37334, 43428, 43451, 44259, 46404 from amd64 branch.
[reactos.git] / reactos / ntoskrnl / mm / ARM3 / ncache.c
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 #line 15 "ARMĀ³::NCACHE"
16 #define MODULE_INVOLVED_IN_ARM3
17 #include "../ARM3/miarm.h"
18
19 /* GLOBALS ********************************************************************/
20
21 /*
22 * @implemented
23 */
24 PVOID
25 NTAPI
26 MmAllocateNonCachedMemory(IN SIZE_T NumberOfBytes)
27 {
28 PFN_NUMBER PageCount, MdlPageCount, 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 = 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 ExFreePool(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 ExFreePool(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 ULONG NumberOfBytes)
174 {
175 PMDL Mdl;
176 PMMPTE PointerPte;
177 PFN_NUMBER 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 = 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 ExFreePool(Mdl);
205
206 //
207 // Now free the system PTEs for the underlying VA
208 //
209 MiReleaseSystemPtes(PointerPte, PageCount + 1, SystemPteSpace);
210 }
211
212 /* EOF */