os/kernelhwsrv/kernel/eka/memmodel/epoc/flexible/mmu/mdefrag.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 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 #include <memmodel.h>
    17 #include <ramalloc.h>
    18 #include "mm.h"
    19 #include "mmu.h"
    20 #include "mmanager.h"
    21 #include "mobject.h"
    22 #include "mpager.h"
    23 #include "mmapping.h"
    24 
    25 
    26 TInt M::RamDefragFault(TAny* /*aExceptionInfo*/)
    27 	{// Defag faults are handled by Mmu::HandlePageFault() on the flexible memory model.
    28 	return KErrAbort;
    29 	} 
    30 
    31 
    32 EXPORT_C TInt Epoc::MovePhysicalPage(TPhysAddr aOld, TPhysAddr& aNew, TRamDefragPageToMove aPageToMove)
    33 	{
    34 	CHECK_PRECONDITIONS(MASK_THREAD_CRITICAL,"Epoc::MovePhysicalPage");
    35 	__KTRACE_OPT(KMMU,Kern::Printf("Epoc::MovePhysicalPage() old=%08x pageToMove=%d",aOld,aPageToMove));
    36 	// Mark aNew as invalid if a page is moved then this will be updated.
    37 	// However, if the page couldn't be moved or is discarded then it must be invalid.
    38 	aNew = KPhysAddrInvalid;
    39 
    40 	TInt r = KErrNotFound;
    41 
    42 	switch (aPageToMove)
    43 		{
    44 		case ERamDefragPage_Physical :
    45 			break;
    46 
    47 		case ERamDefragPage_PageTable :
    48 			{
    49 			// Assume aOld is a linear address in current thread and get the physical
    50 			// address of the page table that maps it and move that.
    51 			TLinAddr linAddr = (TLinAddr) aOld;
    52 			DMemModelThread* thread = (DMemModelThread*)TheCurrentThread;
    53 			// Get the os asid of current thread's process so no need to open reference on it.
    54 			TUint osAsid = ((DMemModelProcess*)thread->iOwningProcess)->OsAsid();
    55 			TUint offsetInMapping;
    56 			TUint mapInstanceCount;
    57 			DMemoryMapping* mapping = MM::FindMappingInAddressSpace(osAsid,linAddr,1,offsetInMapping,mapInstanceCount);
    58 			if (!mapping)
    59 				return r;
    60 			MmuLock::Lock();
    61 			TUint memoryIndex = (offsetInMapping >> KPageShift)+ mapping->iStartIndex;
    62 			TPte* pte = mapping->FindPageTable(linAddr, memoryIndex);
    63 			if (mapInstanceCount != mapping->MapInstanceCount() || !pte)
    64 				{
    65 				MmuLock::Unlock();
    66 				mapping->Close();
    67 				return r;
    68 				}
    69 			TPhysAddr physAddr = TheMmu.LinearToPhysical((TLinAddr)pte, KKernelOsAsid);
    70 			__NK_ASSERT_DEBUG(physAddr != KPhysAddrInvalid);
    71 			aOld = physAddr;	// Have physical address of page table page so move it.
    72 			MmuLock::Unlock();
    73 			mapping->Close();
    74 			break;
    75 			}
    76 
    77 		case ERamDefragPage_PageTableInfo :
    78 			{
    79 			// Assume aOld is a linear address in current thread and get physical 
    80 			// address of the page table info of the page table that maps it 
    81 			// and move that.
    82 			TLinAddr linAddr = (TLinAddr) aOld;
    83 			DMemModelThread* thread = (DMemModelThread*)TheCurrentThread;
    84 			// Get the os asid of current thread's process so no need to open reference on it.
    85 			TUint osAsid = ((DMemModelProcess*)thread->iOwningProcess)->OsAsid();
    86 			TUint offsetInMapping;
    87 			TUint mapInstanceCount;
    88 			DMemoryMapping* mapping = MM::FindMappingInAddressSpace(osAsid,linAddr,1,offsetInMapping,mapInstanceCount);
    89 			if (!mapping)
    90 				return r;
    91 			MmuLock::Lock();
    92 			TUint memoryIndex = (offsetInMapping >> KPageShift)+ mapping->iStartIndex;
    93 			TPte* pte = mapping->FindPageTable(linAddr, memoryIndex);
    94 			if (mapInstanceCount != mapping->MapInstanceCount() || !pte)
    95 				{
    96 				MmuLock::Unlock();
    97 				mapping->Close();
    98 				return r;
    99 				}
   100 			
   101 			SPageTableInfo* pti = SPageTableInfo::FromPtPtr(pte);
   102 			TPhysAddr physAddr = TheMmu.LinearToPhysical((TLinAddr)pti, KKernelOsAsid);
   103 			__NK_ASSERT_DEBUG(physAddr != KPhysAddrInvalid);
   104 			aOld = physAddr;	// Have physical address of page table info page so move it.
   105 			MmuLock::Unlock();
   106 			mapping->Close();
   107 			break;
   108 			}
   109 
   110 		default :
   111 			r = KErrNotSupported;
   112 			return r;
   113 		}
   114 
   115 	RamAllocLock::Lock();
   116 
   117 	// Move the page to any RAM zone.
   118 	r = M::MovePage(aOld, aNew, KRamZoneInvalidId, EFalse);
   119 
   120 	RamAllocLock::Unlock();
   121 	return r;
   122 	}
   123 
   124 
   125 TInt M::MovePage(TPhysAddr aOld, TPhysAddr& aNew, TUint aBlockZoneId, TBool aBlockRest)
   126 	{
   127 	TInt r;
   128 
   129 	// get memory object corresponding to the page...
   130 	DMemoryObject* memory = 0;
   131 	MmuLock::Lock();
   132 	SPageInfo* pi = SPageInfo::SafeFromPhysAddr(aOld&~KPageMask);
   133 	if(pi)
   134 		{
   135 		if (pi->PagedState() != SPageInfo::EUnpaged)
   136 			{// The page is paged so let the pager handle it.
   137 			return ThePager.DiscardPage(pi, aBlockZoneId, aBlockRest);
   138 			}
   139 		if (pi->Type()==SPageInfo::EManaged)
   140 			memory = pi->Owner();
   141 		}
   142 	MmuLock::Unlock();
   143 
   144 	// Note, whilst we hold the RamAllocLock the page can't change it's use
   145 	// and we can safely assume that it still belongs to the memory object
   146 	// at a fixed page index.
   147 	// Also, as memory objects can't be destroyed whilst they still own pages
   148 	// we can safely access this object without taking an explicit referernce,
   149 	// i.e. we don't need to Open() the memory object.
   150 	if (!pi)
   151 		{// page info for aOld not found so aOld is not a RAM page...
   152 		r = KErrArgument;
   153 		}
   154 	else if(!memory)
   155 		{
   156 		// page does not have a memory manager, so we can't move it...
   157 		r = KErrNotSupported;
   158 		}
   159 	else
   160 		{
   161 		// move page...
   162 		r = memory->iManager->MovePage(memory, pi, aNew, aBlockZoneId, aBlockRest);
   163 		}
   164 	return r;
   165 	}