|
1 // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of the License "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // |
|
15 |
|
16 /** |
|
17 @file |
|
18 @internalComponent |
|
19 */ |
|
20 |
|
21 #ifndef MOBJECT_H |
|
22 #define MOBJECT_H |
|
23 |
|
24 #include "mrefcntobj.h" |
|
25 #include "mmappinglist.h" |
|
26 #include "mpagearray.h" |
|
27 |
|
28 class DMemoryManager; |
|
29 class DCoarseMapping; |
|
30 |
|
31 |
|
32 /** |
|
33 Base class for memory objects. |
|
34 |
|
35 A memory object is a sparse array of memory pages (#iPages) to which memory |
|
36 mappings may be attached (#iMappings). All pages in the array are managed |
|
37 in the same way (#iManager). |
|
38 */ |
|
39 class DMemoryObject : public DReferenceCountedObject |
|
40 { |
|
41 public: |
|
42 virtual ~DMemoryObject(); |
|
43 |
|
44 /** |
|
45 Claim ownership of memory originally allocated by the bootstrap. |
|
46 |
|
47 This is used during system boot to initialise this object's memory to contain |
|
48 the pages which are already mapped at a given region of virtual addresses. |
|
49 |
|
50 For coarse memory objects, this function also takes ownership of the page tables |
|
51 being used to map the memory. |
|
52 |
|
53 @param aBase Starting virtual address of memory to claim. |
|
54 |
|
55 @param aSize Size, in bytes, of memory region to claim. |
|
56 |
|
57 @param aPermissions The access permissions which the memory region |
|
58 is mapped. As well as being required for correct object |
|
59 initialisation this also enables the function to check |
|
60 that the bootstrap code mapped the memory in manner |
|
61 consistent with the flexible memory model implementation. |
|
62 |
|
63 @param aAllowGaps True if the memory region may have gaps (unmapped pages) in it. |
|
64 If false, the function faults if the region is not fully |
|
65 populated with mapped pages. |
|
66 |
|
67 @param aAllowNonRamPages True if the memory region contains memory pages which are |
|
68 not RAM pages known to the kernel. I.e. are not |
|
69 contained in the list of RAM banks supplied by the bootstrap. |
|
70 Any such memory cannot be never be subsequently freed from the |
|
71 memory object because the kernel can't handle this memory. |
|
72 |
|
73 @return KErrNone if successful, otherwise one of the system wide error codes. |
|
74 */ |
|
75 virtual TInt ClaimInitialPages(TLinAddr aBase, TUint aSize, TMappingPermissions aPermissions, TBool aAllowGaps=false, TBool aAllowNonRamPages=false) = 0; |
|
76 |
|
77 /** |
|
78 Update the page table entries for all attached mappings to add entries for |
|
79 a specified set of memory pages. |
|
80 |
|
81 This method is called by this object's manager whenever new pages of memory are added. |
|
82 |
|
83 @param aPages An RPageArray::TIter which refers to a range of pages |
|
84 in this memory object. |
|
85 Only array entries which have state RPageArray::ECommitted |
|
86 should be mapped into a mapping's page tables. |
|
87 |
|
88 @return KErrNone if successful, otherwise one of the system wide error codes. |
|
89 */ |
|
90 virtual TInt MapPages(RPageArray::TIter aPages); |
|
91 |
|
92 /** |
|
93 Update the page table entries for all attached mappings to add new entry for |
|
94 a specified memory page. |
|
95 |
|
96 This method is called by this object's manager whenever the page is moved. |
|
97 |
|
98 @param aPageArray The page array entry of the page in this memory object. |
|
99 Only array entries which have state RPageArray::ECommitted |
|
100 should be mapped into a mapping's page tables. |
|
101 |
|
102 @param aIndex The index of the page in this memory object. |
|
103 |
|
104 @param aInvalidateTLB Set to ETrue when the TLB entries associated with this page |
|
105 should be invalidated. This must be done when there is |
|
106 already a valid pte for this page, i.e. if the page is still |
|
107 mapped. |
|
108 |
|
109 @return KErrNone if successful, otherwise one of the system wide error codes. |
|
110 */ |
|
111 virtual void RemapPage(TPhysAddr& aPageArray, TUint aIndex, TBool aInvalidateTLB); |
|
112 |
|
113 /** |
|
114 Update the page table entries for all attached mappings to remove entries for |
|
115 a specified set of memory pages. |
|
116 |
|
117 This method is called this object's manager whenever pages of memory are removed. |
|
118 |
|
119 @param aPages An RPageArray::TIter which refers to a range of pages |
|
120 in this memory object. |
|
121 Only array entries which return true for |
|
122 RPageArray::TargetStateIsDecommitted should be unmapped |
|
123 from a mapping's page tables. |
|
124 |
|
125 @param aDecommitting True if memory is being permanently decommitted from |
|
126 the memory object. False if the memory pages are only |
|
127 temporarily being unmapped due to a demand paging 'page out' |
|
128 operation. |
|
129 */ |
|
130 virtual void UnmapPages(RPageArray::TIter aPages, TBool aDecommitting); |
|
131 |
|
132 /** |
|
133 Update the page table entries for all attached mappings to apply access restrictions |
|
134 to a specified set of memory pages. |
|
135 |
|
136 This method is called by this object's manager whenever pages of memory are restricted. |
|
137 |
|
138 @param aPages An RPageArray::TIter which refers to a range of pages |
|
139 in this memory object. |
|
140 Only array entries which return true for |
|
141 RPageArray::TargetStateIsDecommitted should be unmapped |
|
142 from a mapping's page tables. |
|
143 |
|
144 @param aRestriction A value from enum #TRestrictPagesType indicating the |
|
145 kind of restriction to apply. |
|
146 */ |
|
147 virtual void RestrictPages(RPageArray::TIter aPages, TRestrictPagesType aRestriction); |
|
148 |
|
149 /** |
|
150 Add a memory mapping to this memory object. |
|
151 |
|
152 This is only intended for use by #DMemoryMappingBase::Attach. |
|
153 |
|
154 After verifying that the mapping is permitted (using #CheckNewMapping) |
|
155 the mapping is linked into this objects list of mappings #iMappings. |
|
156 |
|
157 @param aMapping The mapping to add. |
|
158 |
|
159 @return KErrNone if successful, |
|
160 otherwise KErrAccessDenied to indicate that the mapping is not allowed. |
|
161 */ |
|
162 virtual TInt AddMapping(DMemoryMappingBase* aMapping); |
|
163 |
|
164 /** |
|
165 Remove a memory mapping from this memory object. |
|
166 |
|
167 This is only intended for use by #DMemoryMappingBase::Detach. |
|
168 |
|
169 This unlinks the mapping from the list of mappings #iMappings. |
|
170 |
|
171 @param aMapping The mapping to remove. |
|
172 */ |
|
173 virtual void RemoveMapping(DMemoryMappingBase* aMapping); |
|
174 |
|
175 /** |
|
176 Attempt to set the memory object read only. This will only succeed if |
|
177 there are no writable mappings to the memory object. |
|
178 |
|
179 NOTE - This can't be undone, page moving will break if a memory object |
|
180 is made writable again. |
|
181 |
|
182 @return KErrNone on success, KErrInUse if writable mappings are found. |
|
183 */ |
|
184 virtual TInt SetReadOnly(); |
|
185 |
|
186 /** |
|
187 Create a mapping object to map this memory. |
|
188 |
|
189 This is only intended for use by #MM::MappingNew. |
|
190 |
|
191 The base class creates a #DFineMapping object. It is overridden by #DCoarseMemory to create a |
|
192 #DCoarseMapping in appropriate circumstances. |
|
193 |
|
194 @param aIndex The index of the start of the mapping into this memory object. |
|
195 @oaram aCount The size in pages of the mapping. |
|
196 */ |
|
197 virtual DMemoryMapping* CreateMapping(TUint aIndex, TUint aCount); |
|
198 |
|
199 /** |
|
200 Get the physical address(es) for a region of pages in this memory object. |
|
201 |
|
202 Depending on how the memory is being managed the physical addresses returned |
|
203 may become invalid due to various reasons, e.g. |
|
204 |
|
205 - memory being decommitted from the memory object |
|
206 - ram defragmentation moving the memory contents to a different physical page |
|
207 - paging out of demand paged memory |
|
208 |
|
209 This function should therefore only be used where it is know that these |
|
210 possibilities can't occur, e.g. this is used safely by DPhysicalPinMapping::PhysAddr. |
|
211 |
|
212 @param aIndex Page index, within the memory, for the start of the region. |
|
213 @param aCount Number of pages in the region. |
|
214 @param aPhysicalAddress On success, this value is set to one of two values. |
|
215 If the specified region is physically contiguous, |
|
216 the value is the physical address of the first page |
|
217 in the region. If the region is discontiguous, the |
|
218 value is set to KPhysAddrInvalid. |
|
219 @param aPhysicalPageList If not zero, this points to an array of TPhysAddr |
|
220 objects. On success, this array will be filled |
|
221 with the addresses of the physical pages which |
|
222 contain the specified region. If aPageList is |
|
223 zero, then the function will fail with |
|
224 KErrNotFound if the specified region is not |
|
225 physically contiguous. |
|
226 |
|
227 @return 0 if successful and the whole region is physically contiguous. |
|
228 1 if successful but the region isn't physically contiguous. |
|
229 KErrNotFound, if any page in the region is not present, |
|
230 otherwise one of the system wide error codes. |
|
231 */ |
|
232 TInt PhysAddr(TUint aIndex, TUint aCount, TPhysAddr& aPhysicalAddress, TPhysAddr* aPhysicalPageList); |
|
233 |
|
234 /** |
|
235 Check specified region lies entirely within this memory object, and that it |
|
236 is page aligned. |
|
237 */ |
|
238 TBool CheckRegion(TUint aIndex, TUint aCount); |
|
239 |
|
240 /** |
|
241 Clip the specified region to lie within the memory object, |
|
242 */ |
|
243 void ClipRegion(TUint& aIndex, TUint& aCount); |
|
244 |
|
245 /** |
|
246 Set the mutex used to lock operations on this memory object |
|
247 */ |
|
248 void SetLock(DMutex* aLock); |
|
249 |
|
250 /** |
|
251 Prevents any further mappings being added to this memory object. |
|
252 */ |
|
253 void DenyMappings(); |
|
254 |
|
255 /** |
|
256 Return the memory attributes for this object's memory. |
|
257 */ |
|
258 FORCE_INLINE TMemoryAttributes Attributes() |
|
259 { |
|
260 return (TMemoryAttributes)iAttributes; |
|
261 } |
|
262 |
|
263 /** |
|
264 Value for initialising SPageInfo::iFlags when allocating pages. |
|
265 */ |
|
266 FORCE_INLINE TUint8 PageInfoFlags() |
|
267 { |
|
268 return iAttributes; |
|
269 } |
|
270 |
|
271 /** |
|
272 Value for #Mmu::TRamAllocFlags to use when allocating pages. |
|
273 */ |
|
274 FORCE_INLINE Mmu::TRamAllocFlags RamAllocFlags() |
|
275 { |
|
276 return (Mmu::TRamAllocFlags)iRamAllocFlags; |
|
277 } |
|
278 |
|
279 /** |
|
280 Return true if this object is an instance of #DCoarseMemory. |
|
281 */ |
|
282 FORCE_INLINE TBool IsCoarse() |
|
283 { |
|
284 return iFlags&ECoarseObject; |
|
285 } |
|
286 |
|
287 /** |
|
288 Return true if this object contains memory which is being demand paged. |
|
289 */ |
|
290 FORCE_INLINE TBool IsDemandPaged() |
|
291 { |
|
292 return iFlags&EDemandPaged; |
|
293 } |
|
294 |
|
295 /** |
|
296 Return true if writeable mappings of the memory are not allowed. |
|
297 */ |
|
298 FORCE_INLINE TBool IsReadOnly() |
|
299 { |
|
300 return iFlags&EDenyWriteMappings; |
|
301 } |
|
302 |
|
303 /** |
|
304 Return true if executable mappings allowed on this memory object. |
|
305 */ |
|
306 FORCE_INLINE TBool IsExecutable() |
|
307 { |
|
308 return !(iFlags&EDenyExecuteMappings); |
|
309 } |
|
310 |
|
311 /** |
|
312 Clear the flag that indicates that a mapping has been added. |
|
313 */ |
|
314 FORCE_INLINE void ClearMappingAddedFlag() |
|
315 { |
|
316 __NK_ASSERT_DEBUG(iMappings.LockIsHeld()); |
|
317 __e32_atomic_and_ord8(&iFlags, (TUint8)~EMappingAdded); |
|
318 } |
|
319 |
|
320 /** |
|
321 Set the flag to indicate that a mapping has been added. |
|
322 */ |
|
323 FORCE_INLINE void SetMappingAddedFlag() |
|
324 { |
|
325 __NK_ASSERT_DEBUG(iMappings.LockIsHeld()); |
|
326 __NK_ASSERT_DEBUG(MmuLock::IsHeld()); |
|
327 __e32_atomic_ior_ord8(&iFlags, (TUint8)EMappingAdded); |
|
328 } |
|
329 |
|
330 /** |
|
331 Get the value of the mappings added flags |
|
332 |
|
333 @return ETrue if a mapping has been added, EFalse otherwise. |
|
334 */ |
|
335 FORCE_INLINE TBool MappingAddedFlag() |
|
336 { |
|
337 __NK_ASSERT_DEBUG(MmuLock::IsHeld()); |
|
338 return iFlags & (TUint8)EMappingAdded; |
|
339 } |
|
340 |
|
341 enum |
|
342 { |
|
343 /** |
|
344 Maximum number of bits which can be stored in an array entry by SetPagingManagerData. |
|
345 */ |
|
346 KPagingManagerDataBits = RPageArray::KPagingManagerDataBits |
|
347 }; |
|
348 |
|
349 enum |
|
350 { |
|
351 /** |
|
352 Maximum value which can be stored in an array entry by SetPagingManagerData. |
|
353 */ |
|
354 KMaxPagingManagerData = RPageArray::KMaxPagingManagerData |
|
355 }; |
|
356 |
|
357 /** |
|
358 Write \a aValue to the paging manager data for page index \a aIndex. |
|
359 The value must not exceed KMaxPagingManagerData. |
|
360 This must only be used for demand paged memory objects. |
|
361 */ |
|
362 void SetPagingManagerData(TUint aIndex, TUint aValue); |
|
363 |
|
364 /** |
|
365 Return the paging manager data for page index \a aIndex. |
|
366 This must only be used for demand paged memory objects. |
|
367 @see SetPagingManagerData |
|
368 */ |
|
369 TUint PagingManagerData(TUint aIndex); |
|
370 |
|
371 /** |
|
372 Check that a given memory mapping is allowed to be attached to this memory object. |
|
373 |
|
374 @param aMapping The mapping to check. |
|
375 |
|
376 @return KErrNone if successful, |
|
377 otherwise KErrAccessDenied to indicate that the mapping is not allowed. |
|
378 */ |
|
379 TInt CheckNewMapping(DMemoryMappingBase* aMapping); |
|
380 |
|
381 /** |
|
382 Emit BTrace traces identifying the initial attributes of this object. |
|
383 */ |
|
384 void BTraceCreate(); |
|
385 |
|
386 protected: |
|
387 /** |
|
388 @param aManager The manager object for this memory. |
|
389 @param aFlags Initial value for #iFlags. |
|
390 @param aSizeInPages Size of the memory object, in number of pages. |
|
391 @param aAttributes Bitmask of values from enum #TMemoryAttributes. |
|
392 @param aCreateFlags Bitmask of option flags from enum #TMemoryCreateFlags. |
|
393 */ |
|
394 DMemoryObject(DMemoryManager* aManager, TUint aFlags, TUint aSizeInPages, TMemoryAttributes aAttributes, TMemoryCreateFlags aCreateFlags); |
|
395 |
|
396 /** |
|
397 Second phase constructor. |
|
398 |
|
399 @return KErrNone if successful, otherwise one of the system wide error codes. |
|
400 */ |
|
401 TInt Construct(); |
|
402 |
|
403 public: |
|
404 /** |
|
405 The manager of this memory object. |
|
406 */ |
|
407 DMemoryManager* iManager; |
|
408 |
|
409 /** |
|
410 For use by this object's manager (iManager) to store any memory objects specific state |
|
411 it requires to keep track of. |
|
412 */ |
|
413 TAny* iManagerData; |
|
414 |
|
415 /** |
|
416 For use by DMemoryManager::QueueCleanup to link objects which require a cleanup operation. |
|
417 Access to this is protected by #DMemoryManager::iCleanupLock. |
|
418 */ |
|
419 DMemoryObject* iCleanupNext; |
|
420 |
|
421 /** |
|
422 For use by DMemoryManager::QueueCleanup to store flags representing each pending cleanup operation. |
|
423 Access to this is protected by #DMemoryManager::iCleanupLock. |
|
424 */ |
|
425 TUint32 iCleanupFlags; |
|
426 |
|
427 /** |
|
428 Bit flags stored in #iFlags giving various state and attributes of the object. |
|
429 */ |
|
430 enum TFlags |
|
431 { |
|
432 /** |
|
433 Flag set during object construction to indicate that this mapping is of |
|
434 class #DCoarseMemory. |
|
435 */ |
|
436 ECoarseObject = 1<<0, |
|
437 |
|
438 /** |
|
439 Flag set during object construction to indicate that the memory for this object |
|
440 is being demand paged in some manner. |
|
441 */ |
|
442 EDemandPaged = 1<<1, |
|
443 |
|
444 /** |
|
445 Flag set during object construction to indicate that all resources for this |
|
446 object are to be reserved during construction; excluding memory pages owned by |
|
447 object. Objects constructed in this way will not require additional memory |
|
448 allocation when committing memory to them (other than allocating the memory |
|
449 pages being committed.) |
|
450 */ |
|
451 EReserveResources = 1<<2, |
|
452 |
|
453 /** |
|
454 Flag set during object construction to indicate that pinned memory mappings |
|
455 are not allowed to be attached to this object. |
|
456 */ |
|
457 EDenyPinning = 1<<3, |
|
458 |
|
459 /** |
|
460 Flag set by DenyMappings to indicate that no additional memory mappings |
|
461 are allowed to be attached to this object. |
|
462 */ |
|
463 EDenyMappings = 1<<4, |
|
464 |
|
465 /** |
|
466 Flag set during object construction, or by SetReadOnly, to indicate that |
|
467 the memory object is read-only and no writable mappings are allowed |
|
468 to be attached to this object. |
|
469 */ |
|
470 EDenyWriteMappings = 1<<5, |
|
471 |
|
472 /** |
|
473 Flag set during object construction to indicate that executable memory mappings |
|
474 are not allowed to be attached to this object. |
|
475 This is mainly an optimisation to allow demand paging to avoid instruction cache |
|
476 maintenance operations during page fault handling. |
|
477 */ |
|
478 EDenyExecuteMappings = 1<<6, |
|
479 |
|
480 /** |
|
481 Flag set whenever a new mapping is added to a memory object. |
|
482 The object's mappings lock and MmuLock protects this flag when it is set |
|
483 and the mappings lock protects when it is cleared. |
|
484 */ |
|
485 EMappingAdded = 1<<7, |
|
486 }; |
|
487 |
|
488 /** |
|
489 Bitmask of TFlags |
|
490 */ |
|
491 TUint8 iFlags; |
|
492 |
|
493 /** |
|
494 Value from TMemoryAttributes indicating type of memory in object. |
|
495 */ |
|
496 TUint8 iAttributes; |
|
497 |
|
498 /** |
|
499 #Mmu::TRamAllocFlags value to use when allocating RAM for this memory object. |
|
500 */ |
|
501 TUint16 iRamAllocFlags; |
|
502 |
|
503 /** |
|
504 List of mappings currently attached to this object. |
|
505 */ |
|
506 TMappingList iMappings; |
|
507 |
|
508 /** |
|
509 Size, in page units, of this memory object. |
|
510 */ |
|
511 TUint iSizeInPages; |
|
512 |
|
513 /** |
|
514 Lock currently being used to serialise explicit memory operations. |
|
515 This is assigned using #MemoryObjectLock. |
|
516 */ |
|
517 DMutex* iLock; |
|
518 |
|
519 /** |
|
520 The array of memory pages assigned to this memory object. |
|
521 */ |
|
522 RPageArray iPages; |
|
523 }; |
|
524 |
|
525 |
|
526 |
|
527 /** |
|
528 A memory object which has a size that is an exact multiple |
|
529 multiple of the region covered by a whole MMU page table; |
|
530 that is a 'chunk' size (#KChunkSize) bytes. |
|
531 |
|
532 When used in conjunction with DCoarseMapping this object |
|
533 allows RAM to be saved by sharing MMU page tables between multiple |
|
534 different mappings of the memory. |
|
535 |
|
536 Fine memory mappings (DFineMapping) may also be attached |
|
537 to this memory object but these won't benefit from page table |
|
538 sharing. |
|
539 */ |
|
540 class DCoarseMemory : public DMemoryObject |
|
541 { |
|
542 public: |
|
543 // from DMemoryObject... |
|
544 virtual ~DCoarseMemory(); |
|
545 virtual TInt ClaimInitialPages(TLinAddr aBase, TUint aSize, TMappingPermissions aPermissions, TBool aAllowGaps=false, TBool aAllowNonRamPages=false); |
|
546 virtual TInt MapPages(RPageArray::TIter aPages); |
|
547 virtual void RemapPage(TPhysAddr& aPageArray, TUint aIndex, TBool aInvalidateTLB); |
|
548 virtual void UnmapPages(RPageArray::TIter aPages, TBool aDecommitting); |
|
549 virtual void RestrictPages(RPageArray::TIter aPages, TRestrictPagesType aRestriction); |
|
550 virtual TInt AddMapping(DMemoryMappingBase* aMapping); |
|
551 virtual void RemoveMapping(DMemoryMappingBase* aMapping); |
|
552 virtual TInt SetReadOnly(); |
|
553 virtual DMemoryMapping* CreateMapping(TUint aIndex, TUint aCount); |
|
554 public: |
|
555 /** |
|
556 Create a new DCoarseMemory object. |
|
557 |
|
558 @param aManager The manager object for this memory. |
|
559 @param aSizeInPages Size of the memory object, in number of pages. |
|
560 (Must represent an exact 'chunk' size.) |
|
561 @param aAttributes Bitmask of values from enum #TMemoryAttributes. |
|
562 @param aCreateFlags Bitmask of option flags from enum #TMemoryCreateFlags. |
|
563 |
|
564 @return The newly created DCoarseMemory or the null pointer if there was |
|
565 insufficient memory. |
|
566 */ |
|
567 static DCoarseMemory* New(DMemoryManager* aManager, TUint aSizeInPages, TMemoryAttributes aAttributes, TMemoryCreateFlags aCreateFlags); |
|
568 |
|
569 /** |
|
570 Remove an mmu page table from this memory object's ownership. |
|
571 This is called when a RAM page containing the page table is paged out. |
|
572 This function delegates its action to DPageTables::StealPageTable. |
|
573 |
|
574 @param aChunkIndex The index of the page table, i.e. the offset, in 'chunks', |
|
575 into the object's memory that the page table is being used to map. |
|
576 (The index into DPageTables::iTables.) |
|
577 @param aPteType The #TPteType the page table is being used for. |
|
578 (The index into #iPageTables.) |
|
579 |
|
580 @pre #MmuLock is held. |
|
581 @pre #PageTablesLockIsHeld |
|
582 */ |
|
583 void StealPageTable(TUint aChunkIndex, TUint aPteType); |
|
584 |
|
585 public: |
|
586 // Interface for DCoarseMapping |
|
587 |
|
588 /** |
|
589 Get the page table to use for mapping a specified chunk if it exists. |
|
590 |
|
591 @param aPteType The #TPteType the page tables will be used for. |
|
592 @param aChunkIndex The index of the chunk. |
|
593 |
|
594 @return The virtual address of the page table, or NULL. |
|
595 |
|
596 @pre #MmuLock is held. |
|
597 */ |
|
598 TPte* GetPageTable(TUint aPteType , TUint aChunkIndex); |
|
599 |
|
600 /** |
|
601 Update the page tables to add entries for a specified set of demand paged memory |
|
602 pages following a 'page in' or memory pinning operation. |
|
603 |
|
604 @param aMapping The mapping the pages are being paged into. |
|
605 |
|
606 @param aPages An RPageArray::TIter which refers to a range of pages |
|
607 in the memory object #iMemory. |
|
608 Only array entries which have state RPageArray::ECommitted |
|
609 should be mapped into the page tables. |
|
610 |
|
611 @param aPinArgs The resources required to pin any page tables. |
|
612 Page table must be pinned if \a aPinArgs.iPinnedPageTables is |
|
613 not the null pointer, in which case this the virtual address |
|
614 of the pinned must be stored in the array this points to. |
|
615 \a aPinArgs.iReadOnly is true if write access permissions |
|
616 are not needed. |
|
617 |
|
618 @return KErrNone if successful, otherwise one of the system wide error codes. |
|
619 |
|
620 @pre #MmuLock is held. |
|
621 @post #MmuLock has been released. |
|
622 */ |
|
623 TInt PageIn(DCoarseMapping* aMapping, RPageArray::TIter aPages, TPinArgs& aPinArgs, TUint aMapInstanceCount); |
|
624 |
|
625 /** |
|
626 Update the page table entries to renable access to a specified memory page. |
|
627 |
|
628 This method is called by #DCoarseMapping::MovingPageIn |
|
629 |
|
630 @param aMapping The mapping which maps the page. |
|
631 @param aPageArrayPtr The page array entry of the page to map. |
|
632 Only array entries which have state RPageArray::ECommitted |
|
633 should be mapped into a mapping's page tables. |
|
634 |
|
635 @param aIndex The index of the memory page. |
|
636 */ |
|
637 TBool MovingPageIn(DCoarseMapping* aMapping, TPhysAddr& aPageArrayPtr, TUint aIndex); |
|
638 |
|
639 /** |
|
640 Function to return a page table pointer for the specified linear address and |
|
641 index to this mapping. |
|
642 |
|
643 This method is called by #DCoarseMapping::FindPageTable. |
|
644 |
|
645 @param aLinAddr The linear address to find the page table entry for. |
|
646 @param aMemoryIndex The memory object index of the page to find the page |
|
647 table entry for. |
|
648 |
|
649 @return A pointer to the page table entry, if the page table entry couldn't |
|
650 be found this will be NULL |
|
651 */ |
|
652 TPte* FindPageTable(DCoarseMapping* aMapping, TLinAddr aLinAddr, TUint aMemoryIndex); |
|
653 |
|
654 protected: |
|
655 /** |
|
656 For arguments, see #New. |
|
657 */ |
|
658 DCoarseMemory(DMemoryManager* aManager, TUint aSizeInPages, TMemoryAttributes aAttributes, TMemoryCreateFlags aCreateFlags); |
|
659 |
|
660 public: |
|
661 /** |
|
662 The object which manages the page tables owned by a #DCoarseMemory object |
|
663 and used by #DCoarseMapping objects. Each DPageTables is used for mappings |
|
664 with a specific #TPteType e.g. set of memory access permissions, and all these |
|
665 #DCoarseMapping objects are linked into this object whenever they are |
|
666 attached to a DCoarseMemory. |
|
667 */ |
|
668 class DPageTables : public DReferenceCountedObject |
|
669 { |
|
670 public: |
|
671 /** |
|
672 Create a new DPageTables. |
|
673 |
|
674 This object is added to DCoarseMemory::iPageTables and all of |
|
675 the mmu page tables will be initialised to map the memory currently |
|
676 owned by the memory object (unless memory is demand paged). |
|
677 |
|
678 |
|
679 @param aMemory The DCoarseMemory the new object is associated with. |
|
680 @param aNumPages Size of the memory object, in number of pages. |
|
681 (Must represent an exact 'chunk' size.) |
|
682 @param aPteType The #TPteType the page tables will be used for. |
|
683 |
|
684 @return The newly created DPageTables or the null pointer if there was |
|
685 insufficient memory. |
|
686 |
|
687 @pre The #MemoryObjectLock for the memory must be held by the current thread. |
|
688 */ |
|
689 static DPageTables* New(DCoarseMemory* aMemory, TUint aNumPages, TUint aPteType); |
|
690 |
|
691 virtual ~DPageTables(); |
|
692 |
|
693 /** |
|
694 Update the page tables to add entries for a specified set of memory pages. |
|
695 |
|
696 This method is called by #DCoarseMemory::MapPages. |
|
697 |
|
698 @param aPages An RPageArray::TIter which refers to a range of pages |
|
699 in the memory object #iMemory. |
|
700 Only array entries which have state RPageArray::ECommitted |
|
701 should be mapped into the page tables. |
|
702 |
|
703 @return KErrNone if successful, otherwise one of the system wide error codes. |
|
704 */ |
|
705 virtual TInt MapPages(RPageArray::TIter aPages); |
|
706 |
|
707 /** |
|
708 Update the page table entries for a specified memory page. |
|
709 |
|
710 This method is called by #DCoarseMemory::RemapPage |
|
711 |
|
712 @param aPageArray The page array entry of the page in this memory object. |
|
713 Only array entries which have state RPageArray::ECommitted |
|
714 should be mapped into a mapping's page tables. |
|
715 |
|
716 @param aIndex The index of the page in this memory object. |
|
717 |
|
718 @param aInvalidateTLB Set to ETrue when the TLB entries associated with this page |
|
719 should be invalidated. This must be done when there is |
|
720 already a valid pte for this page, i.e. if the page is still |
|
721 mapped. |
|
722 */ |
|
723 virtual void RemapPage(TPhysAddr& aPageArray, TUint aIndex, TBool aInvalidateTLB); |
|
724 |
|
725 /** |
|
726 Update the page table entries to renable access to a specified memory page. |
|
727 |
|
728 This method is called by #DCoarseMemory::MovingPageIn |
|
729 |
|
730 @param aPageArrayPtr The page array entry of the page to map. |
|
731 Only array entries which have state RPageArray::ECommitted |
|
732 should be mapped into a mapping's page tables. |
|
733 |
|
734 @param aIndex The index of the memory page. |
|
735 */ |
|
736 virtual TBool MovingPageIn(TPhysAddr& aPageArrayPtr, TUint aIndex); |
|
737 |
|
738 |
|
739 /** |
|
740 Update the page tables to remove entries for a specified set of memory pages. |
|
741 |
|
742 This method is called by #DCoarseMemory::UnmapPages. |
|
743 |
|
744 @param aPages An RPageArray::TIter which refers to a range of pages |
|
745 in the memory object #iMemory. |
|
746 Only array entries which return true for |
|
747 RPageArray::TargetStateIsDecommitted should be unmapped |
|
748 from the page tables. |
|
749 |
|
750 @param aDecommitting True if memory is being permanently decommitted from |
|
751 the memory object. False if the memory pages are only |
|
752 temporarily being unmapped due to a demand paging 'page out' |
|
753 operation. |
|
754 */ |
|
755 virtual void UnmapPages(RPageArray::TIter aPages, TBool aDecommitting); |
|
756 |
|
757 /** |
|
758 Update the page tables to apply access restrictions to a specified set of memory pages. |
|
759 |
|
760 This method is called by #DCoarseMemory::RestrictPagesNA. |
|
761 |
|
762 @param aPages An RPageArray::TIter which refers to a range of pages |
|
763 in the memory object #iMemory. |
|
764 Only array entries which return true for |
|
765 RPageArray::TargetStateIsDecommitted should be unmapped |
|
766 from the page tables. |
|
767 */ |
|
768 virtual void RestrictPagesNA(RPageArray::TIter aPages); |
|
769 |
|
770 /** |
|
771 Update the page tables to add entries for a specified set of demand paged memory |
|
772 pages following a 'page in' or memory pinning operation. |
|
773 |
|
774 @param aPages An RPageArray::TIter which refers to a range of pages |
|
775 in the memory object #iMemory. |
|
776 Only array entries which have state RPageArray::ECommitted |
|
777 should be mapped into the page tables. |
|
778 |
|
779 @param aPinArgs The resources required to pin any page tables. |
|
780 Page table must be pinned if \a aPinArgs.iPinnedPageTables is |
|
781 not the null pointer, in which case this the virtual address |
|
782 of the pinned must be stored in the array this points to. |
|
783 \a aPinArgs.iReadOnly is true if write access permissions |
|
784 are not needed. |
|
785 |
|
786 @param aMapping The mapping that took the page fault or is being pinned. |
|
787 |
|
788 @param aMapInstanceCount The instance count of the mapping. |
|
789 |
|
790 @return KErrNone if successful, otherwise one of the system wide error codes. |
|
791 */ |
|
792 virtual TInt PageIn(RPageArray::TIter aPages, TPinArgs& aPinArgs, |
|
793 DMemoryMappingBase* aMapping, TUint aMapInstanceCount); |
|
794 |
|
795 /** |
|
796 Flush the MMUs TLB entries associated with all attached memory mappings |
|
797 for a specified region of memory pages. |
|
798 |
|
799 This is used by UnmapPages and RestrictPages. |
|
800 |
|
801 @param aStartIndex Page index, within the memory, for start of the region. |
|
802 @param aEndIndex Page index, within the memory, for the first page after |
|
803 the end of the region. |
|
804 */ |
|
805 void FlushTLB(TUint aStartIndex, TUint aEndIndex); |
|
806 |
|
807 |
|
808 /** |
|
809 Get the page table being used for a specified chunk index if it exists. |
|
810 |
|
811 @param aChunkIndex The index into #iTables of the page table. |
|
812 |
|
813 @return The virtual address of the page table, |
|
814 or the null pointer if one wasn't found. |
|
815 */ |
|
816 inline TPte* GetPageTable(TUint aChunkIndex) |
|
817 { |
|
818 __NK_ASSERT_DEBUG(MmuLock::IsHeld()); |
|
819 return iTables[aChunkIndex]; |
|
820 } |
|
821 |
|
822 /** |
|
823 Get the page table being used for a specified chunk index; allocating |
|
824 a new one if it didn't previously exist. |
|
825 |
|
826 @param aChunkIndex The index into #iTables of the page table. |
|
827 |
|
828 @return The virtual address of the page table, |
|
829 or the null pointer if one wasn't found and couldn't be allocated. |
|
830 */ |
|
831 TPte* GetOrAllocatePageTable(TUint aChunkIndex); |
|
832 |
|
833 /** |
|
834 Get and pin the page table being for a specified chunk index; allocating |
|
835 a new one if it didn't previously exist. |
|
836 |
|
837 @param aChunkIndex The index into #iTables of the page table. |
|
838 @param aPinArgs The resources required to pin the page table. |
|
839 On success, the page table will have been appended to |
|
840 \a aPinArgs.iPinnedPageTables. |
|
841 |
|
842 @return The virtual address of the page table, |
|
843 or the null pointer if one wasn't found and couldn't be allocated. |
|
844 */ |
|
845 TPte* GetOrAllocatePageTable(TUint aChunkIndex, TPinArgs& aPinArgs); |
|
846 |
|
847 /** |
|
848 Allocate a single page table. |
|
849 |
|
850 @param aChunkIndex The index into #iTables of the page table. |
|
851 @param aDemandPaged True if the page table is for mapping demand paged memory. Most of the |
|
852 time this will be determined by the #EDemandPaged bit in #iFlags. |
|
853 @param aPermanent True, if the page table's permanence count is to be incremented. |
|
854 |
|
855 @return The virtual address of the page table, |
|
856 or the null pointer if one wasn't found and couldn't be allocated. |
|
857 */ |
|
858 TPte* AllocatePageTable(TUint aChunkIndex, TBool aDemandPaged, TBool aPermanent=false); |
|
859 |
|
860 /** |
|
861 Free a single page table if it is unused. |
|
862 |
|
863 @param aChunkIndex The index into #iTables of the page table. |
|
864 */ |
|
865 void FreePageTable(TUint aChunkIndex); |
|
866 |
|
867 /** |
|
868 Allocate all the mmu page tables for this object (iTables) and ensure that |
|
869 they are not freed even when they no longer map any pages. |
|
870 |
|
871 This method increments iPermanenceCount. |
|
872 |
|
873 This is called by DCoarseMemory::AddMapping when a memory mapping is |
|
874 added with the #DMemoryMappingBase::EPermanentPageTables attribute is set. |
|
875 This will also be true if the memory object has the #EReserveResources |
|
876 attribute. |
|
877 |
|
878 @pre The #MemoryObjectLock for the memory must be held by the current thread. |
|
879 |
|
880 @return KErrNone if successful, otherwise one of the system wide error codes. |
|
881 */ |
|
882 TInt AllocatePermanentPageTables(); |
|
883 |
|
884 /** |
|
885 Reverses the action of #AllocatePermanentPageTables. |
|
886 |
|
887 This method decrements iPermanenceCount and if this reaches zero, |
|
888 the mmu page tables for this object are freed if the are no longer in use. |
|
889 */ |
|
890 void FreePermanentPageTables(); |
|
891 |
|
892 /** |
|
893 This is called by DCoarseMemory::AddMapping when a coarse memory mapping is |
|
894 added. |
|
895 |
|
896 @param aMapping The coarse memory mapping to add. |
|
897 |
|
898 @return KErrNone if successful, otherwise one of the system wide error codes. |
|
899 */ |
|
900 TInt AddMapping(DCoarseMapping* aMapping); |
|
901 |
|
902 /** |
|
903 This is called by DCoarseMemory::RemoveMapping when a coarse memory mapping is |
|
904 removed. |
|
905 |
|
906 @param aMapping The coarse memory mapping to remove. |
|
907 */ |
|
908 void RemoveMapping(DCoarseMapping* aMapping); |
|
909 |
|
910 /** |
|
911 Overriding DReferenceCountedObject::Close. |
|
912 This removes the linkage with #iMemory if this object is deleted. |
|
913 */ |
|
914 void Close(); |
|
915 |
|
916 /** |
|
917 Overriding DReferenceCountedObject::AsyncClose. |
|
918 This removes the linkage with #iMemory if this object is deleted. |
|
919 */ |
|
920 void AsyncClose(); |
|
921 |
|
922 /** |
|
923 Remove an mmu page table from this object's ownership. |
|
924 This is called from DCoarseMemory::StealPageTable when a RAM page containing |
|
925 the page table is paged out. |
|
926 |
|
927 @param aChunkIndex The index into #iTables of the page table. |
|
928 |
|
929 @pre #MmuLock is held. |
|
930 @pre #PageTablesLockIsHeld |
|
931 */ |
|
932 void StealPageTable(TUint aChunkIndex); |
|
933 |
|
934 protected: |
|
935 /** |
|
936 For arguments, see #New. |
|
937 */ |
|
938 DPageTables(DCoarseMemory* aMemory, TInt aNumPts, TUint aPteType); |
|
939 |
|
940 /** |
|
941 Second phase constructor. |
|
942 |
|
943 This initialises all of the mmu page tables to map the memory currently owned |
|
944 by the memory object (#iMemory). |
|
945 |
|
946 @return KErrNone if successful, otherwise one of the system wide error codes. |
|
947 */ |
|
948 TInt Construct(); |
|
949 |
|
950 private: |
|
951 /** |
|
952 Reverses the action of #AllocatePermanentPageTables for a range of page tables. |
|
953 |
|
954 This is an implementation factor for #FreePermanentPageTables(). |
|
955 |
|
956 @param aChunkIndex The index into #iTables of the first page table. |
|
957 @param aChunkCount The number of page tables. |
|
958 */ |
|
959 void FreePermanentPageTables(TUint aChunkIndex, TUint aChunkCount); |
|
960 |
|
961 /** |
|
962 Assign a newly allocated page table to this object. |
|
963 |
|
964 This adds the page table to the page directory entries associated with |
|
965 all mappings attached to this object. |
|
966 |
|
967 @param aChunkIndex The index into #iTables of the page table. |
|
968 @param aPageTable The page table. |
|
969 |
|
970 @pre #PageTablesLockIsHeld. |
|
971 */ |
|
972 void AssignPageTable(TUint aChunkIndex, TPte* aPageTable); |
|
973 |
|
974 /** |
|
975 Unassign a page table to this object. |
|
976 |
|
977 This removes the page table from the page directory entries associated with |
|
978 all mappings attached to this object. |
|
979 |
|
980 This is called by FreePageTable and StealPageTable. |
|
981 |
|
982 @param aChunkIndex The index into #iTables of the page table. |
|
983 |
|
984 @pre #PageTablesLockIsHeld. |
|
985 */ |
|
986 void UnassignPageTable(TUint aChunkIndex); |
|
987 |
|
988 public: |
|
989 /** |
|
990 The coarse memory object which owns us. |
|
991 */ |
|
992 DCoarseMemory* iMemory; |
|
993 |
|
994 /** |
|
995 The #TPteType the page tables are being used for. |
|
996 (This object's index in #iMemory->iPageTables.) |
|
997 */ |
|
998 TUint iPteType; |
|
999 |
|
1000 /** |
|
1001 The list of coarse mappings attached to this object. |
|
1002 These mappings use the mmu page tables owned by us. |
|
1003 */ |
|
1004 TMappingList iMappings; |
|
1005 |
|
1006 /** |
|
1007 The page table entry (PTE) value for use when mapping pages into the page tables. |
|
1008 This value has the physical address component being zero, so a page's physical |
|
1009 address can be simply ORed in. |
|
1010 */ |
|
1011 TPte iBlankPte; |
|
1012 |
|
1013 /** |
|
1014 Reference count for the number of times #AllocatePermanentPageTables |
|
1015 has been called without #FreePermanentPageTables. |
|
1016 */ |
|
1017 TUint iPermanenceCount; |
|
1018 |
|
1019 /** |
|
1020 Number of entries in #iTables. |
|
1021 */ |
|
1022 TUint iNumPageTables; |
|
1023 |
|
1024 /** |
|
1025 Array of page tables owned by this object. This may extend into memory |
|
1026 beyond the end of this object and contains #iNumPageTables entries. |
|
1027 |
|
1028 Each entry in the array corresponds to a #KChunkSize sized region of #iMemory. |
|
1029 The null pointer indicating that no page table exists for the corresponding |
|
1030 region. |
|
1031 |
|
1032 The contents of the array are protected by the PageTableAllocator lock AND #MmuLock |
|
1033 */ |
|
1034 TPte* iTables[1]; |
|
1035 }; |
|
1036 |
|
1037 private: |
|
1038 /** |
|
1039 Get or allocate the page tables container for a given PTE type |
|
1040 |
|
1041 @pre #MemoryObjectLock for this object must be held. |
|
1042 */ |
|
1043 DPageTables* GetOrAllocatePageTables(TUint aPteType); |
|
1044 |
|
1045 protected: |
|
1046 /** |
|
1047 Array of #DPageTables objects owned by this memory object. |
|
1048 Updates to this array require the #MmuLock. |
|
1049 */ |
|
1050 DPageTables* iPageTables[ENumPteTypes]; |
|
1051 |
|
1052 friend class DCoarseMemory::DPageTables; // for DPageTables::Close() / AsyncClose() |
|
1053 }; |
|
1054 |
|
1055 |
|
1056 |
|
1057 /** |
|
1058 A memory object without the special case optimisations of DCoarseMemory. |
|
1059 */ |
|
1060 class DFineMemory : public DMemoryObject |
|
1061 { |
|
1062 public: |
|
1063 // from DMemoryObject... |
|
1064 virtual ~DFineMemory(); |
|
1065 virtual TInt ClaimInitialPages(TLinAddr aBase, TUint aSize, TMappingPermissions aPermissions, TBool aAllowGaps=false, TBool aAllowNonRamPages=false); |
|
1066 |
|
1067 public: |
|
1068 /** |
|
1069 Create a new DFineMemory object. |
|
1070 |
|
1071 @param aManager The manager object for this memory. |
|
1072 @param aSizeInPages Size of the memory object, in number of pages. |
|
1073 @param aAttributes Bitmask of values from enum #TMemoryAttributes. |
|
1074 @param aCreateFlags Bitmask of option flags from enum #TMemoryCreateFlags. |
|
1075 |
|
1076 @return The newly created DFineMemory or the null pointer if there was |
|
1077 insufficient memory. |
|
1078 */ |
|
1079 static DFineMemory* New(DMemoryManager* aManager, TUint aSizeInPages, TMemoryAttributes aAttributes, TMemoryCreateFlags aCreateFlags); |
|
1080 |
|
1081 private: |
|
1082 /** |
|
1083 For arguments, see #New. |
|
1084 */ |
|
1085 DFineMemory(DMemoryManager* aManager, TUint aSizeInPages, TMemoryAttributes aAttributes, TMemoryCreateFlags aCreateFlags); |
|
1086 }; |
|
1087 |
|
1088 |
|
1089 #endif |