157 @param aPageTable Virtual address of the page table, |
163 @param aPageTable Virtual address of the page table, |
158 @param aPinArgs The resources to use for pinning. This must have |
164 @param aPinArgs The resources to use for pinning. This must have |
159 at least #KNumPagesToPinOnePageTable replacement |
165 at least #KNumPagesToPinOnePageTable replacement |
160 pages available. |
166 pages available. |
161 */ |
167 */ |
162 static void PinPageTable(TPte* aPageTable, TPinArgs& aPinArgs); |
168 TInt PinPageTable(TPte* aPageTable, TPinArgs& aPinArgs); |
163 |
169 |
164 /** |
170 /** |
165 Unpin the RAM page containing a page table, as well as the RAM page |
171 Unpin the RAM page containing a page table, as well as the RAM page |
166 containing its #SPageTableInfo structure. |
172 containing its #SPageTableInfo structure. |
167 This reverses the action of #PinPageTable. |
173 This reverses the action of #PinPageTable. |
170 @param aPinArgs The resources to use for pinning. The replacement |
176 @param aPinArgs The resources to use for pinning. The replacement |
171 pages count in this will be incremented for each |
177 pages count in this will be incremented for each |
172 completely unpinned, e.g. those which can be reused |
178 completely unpinned, e.g. those which can be reused |
173 as new replacement pages or freed. |
179 as new replacement pages or freed. |
174 */ |
180 */ |
175 static void UnpinPageTable(TPte* aPageTable, TPinArgs& aPinArgs); |
181 void UnpinPageTable(TPte* aPageTable, TPinArgs& aPinArgs); |
176 |
182 |
177 private: |
183 private: |
178 /** |
184 /** |
179 Sub-allocator used for managing page tables of a given 'pagedness' (paged/not-paged). |
185 Sub-allocator used for managing page tables of a given 'pagedness' (paged/not-paged). |
180 Each allocator maintains a list free page tables (#iFreeList) from which it can allocate. |
186 Each allocator maintains a list free page tables (#iFreeList) from which it can allocate. |
356 { |
362 { |
357 public: |
363 public: |
358 void Init2(TUint aNumInitPages); |
364 void Init2(TUint aNumInitPages); |
359 TInt Alloc(TBool aDemandPaged); |
365 TInt Alloc(TBool aDemandPaged); |
360 void Free(TUint aPageIndex, TBool aDemandPaged); |
366 void Free(TUint aPageIndex, TBool aDemandPaged); |
361 TBool IsDemandPaged(SPageInfo* aPageInfo) |
367 |
362 {// Is the highest page table index this page table info page can reference |
368 /** |
|
369 Determine if the page table info page is paged. |
|
370 |
|
371 @param aPageInfo Pointer to the SPageInfo of the page table info page. |
|
372 @return ETrue if the page table info page is paged, EFalse otherwise. |
|
373 @pre MmuLock is held. |
|
374 */ |
|
375 inline TBool IsDemandPagedPtInfo(SPageInfo* aPageInfo) |
|
376 { |
|
377 // Is the highest page table index this page table info page can reference |
363 // allocated within the demand paged region of the page table address space. |
378 // allocated within the demand paged region of the page table address space. |
364 TUint groupIndex = aPageInfo->Index(); |
379 TUint groupIndex = aPageInfo->Index(); |
365 return ((groupIndex+1) * KPageTableGroupSize)-1 >= iUpperWaterMark; |
380 return ((groupIndex+1) * KPageTableGroupSize)-1 >= iUpperWaterMark; |
366 } |
381 } |
|
382 |
|
383 /** |
|
384 Determine if the page table page is paged. |
|
385 |
|
386 @param aPageInfo Pointer to the SPageInfo of the page table info page. |
|
387 @return ETrue if the page table page is paged, EFalse otherwise. |
|
388 @pre MmuLock is held. |
|
389 */ |
|
390 inline TBool IsDemandPagedPt(SPageInfo* aPageInfo) |
|
391 { |
|
392 return aPageInfo->Index() >= iUpperWaterMark; |
|
393 } |
|
394 |
|
395 /** |
|
396 Get a random paged page table page. |
|
397 |
|
398 @return The index of a paged page table page. |
|
399 @pre All paged page table pages are allocated. |
|
400 @pre Page tables lock is held. |
|
401 */ |
|
402 TUint RandomPagedPtPage(); |
|
403 |
|
404 /** |
|
405 Increase the count of pinned paged page table pages. |
|
406 |
|
407 @return KErrNone on success, KErrNoMemory if too many pages are already pinned. |
|
408 @pre MmuLock is held |
|
409 */ |
|
410 inline TInt PtPagePinCountInc() |
|
411 { |
|
412 if (AtPinnedPagedPtsLimit(iUpperWaterMark, iLowerWaterMark, iPinnedPageTablePages + 1)) |
|
413 { |
|
414 return KErrNoMemory; |
|
415 } |
|
416 iPinnedPageTablePages++; |
|
417 return KErrNone; |
|
418 } |
|
419 |
|
420 /** |
|
421 Decrease the count of pinned paged page table pages. |
|
422 |
|
423 @pre MmuLock is held |
|
424 */ |
|
425 inline void PtPagePinCountDec() |
|
426 { |
|
427 __NK_ASSERT_DEBUG(iPinnedPageTablePages); // Can't be zero. |
|
428 iPinnedPageTablePages--; |
|
429 } |
|
430 |
|
431 private: |
|
432 /** |
|
433 Check whether it is safe to pin a paged page table or reduce the amount of |
|
434 virtual address space available to paged page tables. By checking that we |
|
435 either have spare virtual address space to increase the amount of paged page |
|
436 tables or that there are already enough unpinned paged page tables. |
|
437 |
|
438 @return ETrue if there isn't or EFalse if it is ok to pin more paged page |
|
439 tables or increase the number of unpaged page tables. |
|
440 */ |
|
441 TBool AtPinnedPagedPtsLimit(TUint aUpperWaterMark, TUint aLowerWaterMark, TUint aPinnedPtPages) |
|
442 { |
|
443 TUint adjustedUpperWaterMark = aUpperWaterMark & ~(KPageTableGroupSize - 1); |
|
444 TUint availPagedPtPages = KMaxPageTablePages - adjustedUpperWaterMark; |
|
445 TUint availUnpinnedPagedPtPages = availPagedPtPages - aPinnedPtPages; |
|
446 // This check is sufficient as we only increase the pinned paged page table |
|
447 // pages or unpaged page table pages one at a time. |
|
448 return (aLowerWaterMark + 1 == adjustedUpperWaterMark && |
|
449 availUnpinnedPagedPtPages < KMinUnpinnedPagedPtPages); |
|
450 } |
|
451 |
367 private: |
452 private: |
368 TBitMapAllocator* iLowerAllocator; ///< Allocator for unpaged page tables |
453 TBitMapAllocator* iLowerAllocator; ///< Allocator for unpaged page tables |
369 TUint iLowerWaterMark; ///< Highest page index allocated by iLowerAllocator |
454 TUint iLowerWaterMark; ///< Highest page index allocated by iLowerAllocator |
370 TBitMapAllocator* iUpperAllocator; ///< Allocator for demand paged page tables |
455 TBitMapAllocator* iUpperAllocator; ///< Allocator for demand paged page tables |
371 TUint iUpperWaterMark; ///< Lowest page index allocated by iUpperAllocator |
456 TUint iUpperWaterMark; ///< Lowest page index allocated by iUpperAllocator |
|
457 TUint iPinnedPageTablePages; ///< The number of pinned paged page table pages. |
372 }; |
458 }; |
373 |
459 |
374 /** |
460 /** |
375 Allocator for page indexes within #iPageTableMemory. |
461 Allocator for page indexes within #iPageTableMemory. |
376 */ |
462 */ |