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