kernel/eka/memmodel/epoc/moving/mdefrag.cpp
changeset 0 a41df078684a
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     1 // Copyright (c) 2006-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 // e32\memmodel\epoc\moving\mdefrag.cpp
       
    15 // 
       
    16 //
       
    17 
       
    18 #include <memmodel.h>
       
    19 #include <defrag.h>
       
    20 #include "mmboot.h"
       
    21 #include <mmubase.inl>
       
    22 #include <ramalloc.h>
       
    23 #include "cache_maintenance.h"
       
    24 
       
    25 /*
       
    26  * Move a kernel page from aOld to aNew, updating the page table in aChunk.
       
    27  * Enter with system locked, exit with system unlocked (!!)
       
    28  * Must hold RAM alloc mutex.
       
    29  */
       
    30 TInt Mmu::MoveKernelPage(DChunk* aChunk, TUint32 aOffset, TPhysAddr aOld, TPhysAddr& aNew, TUint aBlockZoneId, TBool aBlockRest)
       
    31 	{
       
    32 	__KTRACE_OPT(KMMU,Kern::Printf("Mmu::MoveKernelPage() off=%08x old=%08x",aOffset,aOld));
       
    33 	Mmu& m=Mmu::Get();
       
    34 	
       
    35 	// Release the system lock - the kernel chunks can't ever be freed
       
    36 	// and the ramalloc mutex protects us from decommit.
       
    37 	NKern::UnlockSystem();
       
    38 
       
    39 	DMemModelChunk* chunk = (DMemModelChunk*)aChunk;
       
    40 
       
    41 	// Allocate new page, map it uncached but buffered, and find old mapping
       
    42 	TPhysAddr newPage;
       
    43 	if (m.AllocRamPages(&newPage, 1, EPageMovable, aBlockZoneId, aBlockRest) != KErrNone)
       
    44 		return KErrNoMemory;
       
    45 	TLinAddr vOld = (TLinAddr)chunk->iBase + aOffset;
       
    46 	TLinAddr vNew = m.MapTemp(newPage, EFalse);
       
    47 	
       
    48 	// Find page table for mapping
       
    49 	TInt ptid=m.GetPageTableId(vOld);
       
    50 	if(ptid<0)
       
    51 		Panic(EDefragKernelChunkNoPageTable);
       
    52 
       
    53 	// With the system lock, ask Mmu to remap the page.
       
    54 	// This will copy and remap it with interrupts disabled, while
       
    55 	// avoiding touching any cache lines on the heap.
       
    56 	NKern::LockSystem();
       
    57 	m.RemapKernelPage(ptid, vOld, vNew, newPage, chunk->iPtePermissions);
       
    58 
       
    59 	// update new pageinfo, clear old, then done with system lock.
       
    60 	SPageInfo* oldpi = SPageInfo::FromPhysAddr(aOld);
       
    61 	SPageInfo* pi = SPageInfo::FromPhysAddr(newPage);
       
    62 	pi->Set(oldpi->Type(),oldpi->Owner(),oldpi->Offset());
       
    63 	oldpi->SetUnused();
       
    64 	NKern::UnlockSystem();
       
    65 
       
    66 	// Remove temporary new page mapping
       
    67 	m.UnmapTemp();
       
    68 
       
    69 	// Remove old page from external cache - RemapKernelPage has already removed it from internal cache.
       
    70 	CacheMaintenance::PageToReusePhysicalCache(aOld);
       
    71 
       
    72 	// Free old page
       
    73 #ifdef _DEBUG
       
    74 	m.ClearPages(1, (TPhysAddr*)(aOld|1));
       
    75 #endif
       
    76 	m.iRamPageAllocator->FreeRamPage(aOld, EPageMovable);
       
    77 
       
    78 	aNew = newPage;
       
    79 	return KErrNone;
       
    80 	}
       
    81 
       
    82 /* 
       
    83  * These pages don't exist on moving memory model, no need to move them
       
    84  * but this function must exist to make the kernel link.
       
    85  */
       
    86 TInt Mmu::MoveCodeSegMemoryPage(DMemModelCodeSegMemory* /*aCodeSegMemory*/, TUint32 /*aOffset*/, TPhysAddr /*aOld*/,
       
    87 		TPhysAddr& /*aNew*/, TUint /*aBlockZoneId*/, TBool /*aBlockRest*/)
       
    88 	{
       
    89 	NKern::UnlockSystem();
       
    90 	return KErrNotSupported;
       
    91 	}
       
    92 
       
    93 /*
       
    94  * Move a code chunk page from aOld to aNew, updating the page table in aChunk.
       
    95  * Enter with system locked, exit with system unlocked (!!)
       
    96  * Must hold RAM alloc mutex.
       
    97  */
       
    98 TInt Mmu::MoveCodeChunkPage(DChunk* aChunk, TUint32 aOffset, TPhysAddr aOld, TPhysAddr& aNew, TUint aBlockZoneId, TBool aBlockRest)
       
    99 	{
       
   100 	__KTRACE_OPT(KMMU,Kern::Printf("Mmu::MoveCodeChunkPage() off=%08x old=%08x",aOffset,aOld));
       
   101 	Mmu& m=Mmu::Get();
       
   102 
       
   103 	// look up the code seg that corresponds to this page
       
   104 	TLinAddr aLinearAddress = (TLinAddr)(aChunk->Base() + aOffset);
       
   105 	DMemModelCodeSeg* codeseg = (DMemModelCodeSeg*)DCodeSeg::CodeSegsByAddress.Find(aLinearAddress);
       
   106 
       
   107 	// if the code seg is not done loading yet, we can't move it the easy way
       
   108 	// also, if it's being unloaded the codeseg will have gone.
       
   109 	if (!codeseg || !(codeseg->iMark & DCodeSeg::EMarkLoaded))
       
   110 		{
       
   111 		NKern::UnlockSystem();
       
   112 		return KErrInUse;
       
   113 		}
       
   114 
       
   115 	// Release system lock as page can't be decommitted while we hold ramalloc mutex
       
   116 	NKern::UnlockSystem();
       
   117 
       
   118 	// Allocate new page, map it uncached but buffered, and find old mapping
       
   119 	TPhysAddr newPage;
       
   120 	if (m.AllocRamPages(&newPage, 1, EPageMovable, aBlockZoneId, aBlockRest) != KErrNone)
       
   121 		return KErrNoMemory;
       
   122 	TLinAddr vOld = aLinearAddress;
       
   123 	TLinAddr vNew = m.MapTemp(newPage, EFalse);
       
   124 	
       
   125 	// Copy the page and remap it
       
   126 	pagecpy((TAny*)vNew, (TAny*)vOld);
       
   127 	NKern::LockSystem();
       
   128 	// Substitute drains the write buffer for us during the remap.
       
   129 	aChunk->Substitute(aOffset, aOld, newPage);
       
   130 	NKern::UnlockSystem();
       
   131 
       
   132 	// Remove temporary new page mapping
       
   133 	m.UnmapTemp();
       
   134 
       
   135 	// Remove old page from physical cache
       
   136 	CacheMaintenance::PageToReusePhysicalCache(aOld);
       
   137 
       
   138 	// Free old page
       
   139 #ifdef _DEBUG
       
   140 	m.ClearPages(1, (TPhysAddr*)(aOld|1));
       
   141 #endif
       
   142 	m.iRamPageAllocator->FreeRamPage(aOld, EPageMovable);
       
   143 
       
   144 	aNew = newPage;
       
   145 	return KErrNone;
       
   146 	}
       
   147 
       
   148 /*
       
   149  * Move a data chunk page from aOld to aNew, updating the page table in aChunk.
       
   150  * Enter with system locked, exit with system unlocked (!!)
       
   151  * Must hold RAM alloc mutex.
       
   152  */
       
   153 TInt Mmu::MoveDataChunkPage(DChunk* aChunk, TUint32 aOffset, TPhysAddr aOld, TPhysAddr& aNew, TUint aBlockZoneId, TBool aBlockRest)
       
   154 	{
       
   155 	__KTRACE_OPT(KMMU,Kern::Printf("Mmu::MoveDataChunkPage() off=%08x old=%08x",aOffset,aOld));
       
   156 	Mmu& m=Mmu::Get();
       
   157 	TInt r;
       
   158 
       
   159 	// Release system lock as page can't be decommitted while we hold ramalloc mutex
       
   160 	NKern::UnlockSystem();
       
   161 
       
   162 	// Allocate new page, map it uncached but buffered
       
   163 	TPhysAddr newPage;
       
   164 	if (m.AllocRamPages(&newPage, 1, EPageMovable, aBlockZoneId, aBlockRest) != KErrNone)
       
   165 		return KErrNoMemory;
       
   166 	TLinAddr vNew = m.MapTemp(newPage, EFalse);
       
   167 
       
   168 	// Mark the PTE as inaccessible to avoid the data being overwritten while we copy
       
   169 	// This also takes care of the cache requirements to alias the page elsewhere,
       
   170 	// since it can't be copied from an inaccessible PTE
       
   171 	DisablePageModification((DMemModelChunk*)aChunk, aOffset);
       
   172 	TLinAddr vOldAlias = m.MapSecondTemp(aOld, ETrue);
       
   173 
       
   174 	// Copy the page's contents and remap its PTE
       
   175 	pagecpy((TAny*)vNew, (TAny*)vOldAlias);
       
   176 	NKern::LockSystem();
       
   177 	if (iDisabledPte != NULL)
       
   178 		{
       
   179 		// Access wasn't reenabled, so we can continue
       
   180 		aChunk->Substitute(aOffset, aOld, newPage);
       
   181 		iDisabledAddr = 0;
       
   182 		iDisabledPte = NULL;
       
   183 		iDisabledOldVal = 0;
       
   184 		r = KErrNone;
       
   185 		}
       
   186 	else
       
   187 		r = KErrInUse;
       
   188 	NKern::UnlockSystem();
       
   189 
       
   190 	// Remove temporary page mappings
       
   191 	CacheMaintenance::PageToReuseVirtualCache(vOldAlias);
       
   192 	m.UnmapTemp();
       
   193 	m.UnmapSecondTemp();
       
   194 
       
   195 	if (r == KErrNone)
       
   196 		{
       
   197 		// Remove old page from physical cache - DisablePageModification removed it from L1 already
       
   198 		CacheMaintenance::PageToReusePhysicalCache(aOld);
       
   199 		}
       
   200 
       
   201 	if (r == KErrNone)
       
   202 		{
       
   203 		// Free old page
       
   204 #ifdef _DEBUG
       
   205 		m.ClearPages(1, (TPhysAddr*)(aOld|1));
       
   206 #endif
       
   207 		m.iRamPageAllocator->FreeRamPage(aOld, EPageMovable);
       
   208 		aNew = newPage;
       
   209 		}
       
   210 	else
       
   211 		{
       
   212 		// Free new page
       
   213 		m.iRamPageAllocator->FreeRamPage(newPage, EPageMovable);
       
   214 		}
       
   215 
       
   216 	return r;
       
   217 	}