Update contrib.
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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
16 #include <plat_priv.h>
20 #include "maddressspace.h"
27 Allocator for OS Address Space IDs (OS ASIDs).
28 This is a simple bitmap allocator for KNumOsAsids integers with an
29 associated mutex to guard against concurrency when allocating and
37 iAllocator = TBitMapAllocator::New(KNumOsAsids,ETrue);
38 __NK_ASSERT_ALWAYS(iAllocator);
39 iAllocator->Alloc(KKernelOsAsid,1); // make kernel OS ASID already allocated
44 NKern::FMWait(&iLock);
45 TInt osAsid = iAllocator->Alloc();
46 NKern::FMSignal(&iLock);
52 void Free(TInt aOsAsid)
54 NKern::FMWait(&iLock);
55 iAllocator->Free(aOsAsid);
56 NKern::FMSignal(&iLock);
60 TBitMapAllocator* iAllocator;
70 DAddressSpace KernelAddressSpace; ///< The kernel's address space object.
72 __ASSERT_COMPILE(KKernelOsAsid==0);
73 DAddressSpace* AddressSpace[KNumOsAsids] = { &KernelAddressSpace };
75 RVirtualAllocator DAddressSpace::UserGlobalVirtualAllocator;
76 RBackwardsVirtualAllocator DAddressSpace::UserCommonVirtualAllocator;
79 The read lock used for protecting the mappings container in address spaces (DAddressSpace::iMappings).
80 A single global lock is used for all processes - this isn't required but it is the simplest
81 implementation if we want to avoid the memory overhead of allocating a mutex per address space.
83 NFastMutex TheAddressSpaceMappingLock;
87 A pool of mutexes which are used to protect an address space's virtual address allocation
88 and acts as a write lock for the mappings container (DAddressSpace::iMappings).
90 DMutexPool AddressSpaceMutexPool;
93 void DAddressSpace::Init2()
95 // create allocator for ASIDs...
96 OsAsidAllocator.Init2();
98 // construct the kernel's address space...
99 TInt r = KernelAddressSpace.Construct(0, KKernelSectionBase, KKernelSectionEnd);
100 __NK_ASSERT_ALWAYS(r==KErrNone);
102 // mark primary i/o region as already allocated...
103 __ASSERT_COMPILE(((KPrimaryIOBase|KPrimaryIOEnd)&KChunkMask)==0); // region must be chunk aligned to avoid PDE type conflicts with any new allocations
106 r = KernelAddressSpace.AllocateVirtualMemory(addr,size,KPrimaryIOBase,KPrimaryIOEnd-KPrimaryIOBase,0);
107 __NK_ASSERT_ALWAYS(r==KErrNone);
109 // construct user global memory allocator...
110 r = UserGlobalVirtualAllocator.Construct(KGlobalMemoryBase,KUserMemoryLimit,ENumVirtualAllocTypes,AddressSpace[KKernelOsAsid]->iLock);
111 __NK_ASSERT_ALWAYS(r==KErrNone);
113 // construct user common memory allocator (two slab types, one each for paged and unpaged memory)...
114 r = UserCommonVirtualAllocator.Construct(KUserLocalDataBase,KUserLocalDataEnd,ENumVirtualAllocTypes,AddressSpace[KKernelOsAsid]->iLock);
115 __NK_ASSERT_ALWAYS(r==KErrNone);
117 // reserve virtual memory for XIP user code...
118 TUint romDataSize = TheRomHeader().iTotalUserDataSize;
119 TLinAddr romDataBase = TheRomHeader().iUserDataAddress-romDataSize;
120 __NK_ASSERT_DEBUG(TheRomHeader().iUserDataAddress==KUserLocalDataEnd);
123 r = UserCommonVirtualAllocator.Alloc(addr,size,romDataBase,romDataSize,0);
124 __NK_ASSERT_ALWAYS(r==KErrNone);
129 DAddressSpace::DAddressSpace()
130 : iMappings(&TheAddressSpaceMappingLock,iLock)
135 TInt DAddressSpace::New(TPhysAddr& aPageDirectory)
137 TRACE(("DAddressSpace::New(?)"));
139 TInt osAsid = OsAsidAllocator.Alloc();
144 r = PageDirectories.Alloc(osAsid,aPageDirectory);
146 OsAsidAllocator.Free(osAsid);
149 DAddressSpace*& info = AddressSpace[osAsid];
150 __NK_ASSERT_DEBUG(!info);
151 info = new DAddressSpace();
154 PageDirectories.Free(osAsid);
155 OsAsidAllocator.Free(osAsid);
160 r = info->Construct(osAsid,KUserLocalDataBase,KUserLocalDataEnd);
173 aPageDirectory = KPhysAddrInvalid;
175 TRACE(("DAddressSpace::New returns %d",r));
181 DAddressSpace::~DAddressSpace()
183 TRACE(("DAddressSpace[0x%08x]::~DAddressSpace() osAsid = %d",this,iOsAsid));
185 if(iMappings.Count())
188 __NK_ASSERT_DEBUG(iMappings.Count()==0);
190 TInt osAsid = iOsAsid;
191 AddressSpace[osAsid] = 0;
192 PageDirectories.Free(osAsid);
193 InvalidateTLBForAsid(osAsid);
194 OsAsidAllocator.Free(osAsid);
198 TInt DAddressSpace::Construct(TInt aOsAsid, TLinAddr aStart, TLinAddr aEnd)
200 TRACE(("DAddressSpace::Construct(%d,0x%08x,0x%08x)",aOsAsid,aStart,aEnd));
202 return iVirtualAllocator.Construct(aStart,aEnd,ENumVirtualAllocTypes,iLock);
206 void DAddressSpace::Lock()
208 AddressSpaceMutexPool.Wait(iLock);
212 void DAddressSpace::Unlock()
214 AddressSpaceMutexPool.Signal(iLock);
218 TInt DAddressSpace::AllocateVirtualMemory(TLinAddr& aAddr, TUint& aSize, TLinAddr aRequestedAddr, TUint aRequestedSize, TUint aPdeType)
220 TRACE(("DAddressSpace::AllocateVirtualMemory(?,?,0x%08x,0x%08x,%d) osAsid=%d",aRequestedAddr,aRequestedSize,aPdeType,iOsAsid));
221 __NK_ASSERT_DEBUG(aPdeType<ENumVirtualAllocTypes);
223 TInt r = iVirtualAllocator.Alloc(aAddr,aSize,aRequestedAddr,aRequestedSize,aPdeType);
227 TRACE(("DAddressSpace::AllocateVirtualMemory returns %d region=0x%08x+0x%08x",r,aAddr,aSize));
232 TInt DAddressSpace::AllocateUserGlobalVirtualMemory(TLinAddr& aAddr, TUint& aSize, TLinAddr aRequestedAddr, TUint aRequestedSize, TUint aPdeType)
234 TRACE(("DAddressSpace::AllocateUserGlobalVirtualMemory(?,?,0x%08x,0x%08x,%d)",aRequestedAddr,aRequestedSize,aPdeType));
235 __NK_ASSERT_DEBUG(aPdeType<ENumVirtualAllocTypes);
236 KernelAddressSpace.Lock();
237 TInt r = UserGlobalVirtualAllocator.Alloc(aAddr,aSize,aRequestedAddr,aRequestedSize,aPdeType);
238 KernelAddressSpace.Unlock();
239 TRACE(("DAddressSpace::AllocateUserGlobalVirtualMemory returns %d region=0x%08x+0x%08x",r,aAddr,aSize));
244 void DAddressSpace::FreeVirtualMemory(TLinAddr aAddr, TUint aSize)
246 TRACE(("DAddressSpace::FreeVirtualMemory(0x%08x,0x%08x) osAsid=%d",aAddr, aSize, iOsAsid));
248 if(iOsAsid==(TInt)KKernelOsAsid && UserGlobalVirtualAllocator.InRange(aAddr,aSize))
249 UserGlobalVirtualAllocator.Free(aAddr,aSize);
252 iVirtualAllocator.Free(aAddr,aSize);
259 TInt DAddressSpace::AllocateUserCommonVirtualMemory(TLinAddr& aAddr, TUint& aSize, TLinAddr aRequestedAddr, TUint aRequestedSize, TUint aPdeType)
261 TRACE(("DAddressSpace::AllocateUserCommonVirtualMemory(?,?,0x%08x,0x%08x,%d)",aRequestedAddr,aRequestedSize,aPdeType));
262 __NK_ASSERT_DEBUG(aPdeType<ENumVirtualAllocTypes);
263 KernelAddressSpace.Lock();
264 TInt r = UserCommonVirtualAllocator.Alloc(aAddr,aSize,aRequestedAddr,aRequestedSize,aPdeType);
265 KernelAddressSpace.Unlock();
266 TRACE(("DAddressSpace::AllocateUserCommonVirtualMemory returns %d region=0x%08x+0x%08x",r,aAddr,aSize));
271 void DAddressSpace::FreeUserCommonVirtualMemory(TLinAddr aAddr, TUint aSize)
273 TRACE(("DAddressSpace::FreeUserCommonVirtualMemory(0x%08x,0x%08x)",aAddr,aSize));
274 KernelAddressSpace.Lock();
275 UserCommonVirtualAllocator.Free(aAddr,aSize);
276 KernelAddressSpace.Unlock();
280 TInt DAddressSpace::AddMapping(TLinAddr aAddr, DMemoryMapping* aMapping)
283 TRACE(("DAddressSpace::AddMapping(0x%08x,0x%08x) osAsid=%d",aAddr, aMapping, iOsAsid));
284 TInt r = iMappings.Add(aAddr,aMapping);
285 TRACE(("DAddressSpace::AddMapping osAsid=%d returns %d",iOsAsid, r));
291 DMemoryMapping* DAddressSpace::RemoveMapping(TLinAddr aAddr)
294 DMemoryMapping* removed = (DMemoryMapping*)iMappings.Remove(aAddr);
295 TRACE(("DAddressSpace::RemoveMapping(0x%08x) osAsid=%d returns 0x%08x",aAddr, iOsAsid, removed));
301 DMemoryMapping* DAddressSpace::GetMapping(TLinAddr aAddr)
303 iMappings.ReadLock();
304 DMemoryMapping* mapping = (DMemoryMapping*)iMappings.Find(aAddr);
305 TRACE(("DAddressSpace::GetMapping(0x%08x) osAsid=%d returns 0x%08x",aAddr, iOsAsid, mapping));
306 __NK_ASSERT_DEBUG(mapping); // caller must know there is a mapping
307 iMappings.ReadUnlock();
312 DMemoryMapping* DAddressSpace::FindMapping(TLinAddr aAddr, TUint aSize, TUint& aOffsetInMapping, TUint& aInstanceCount)
316 DMemoryMapping* result = NULL;
319 iMappings.ReadLock();
321 DMemoryMapping* mapping = (DMemoryMapping*)iMappings.Find(aAddr,dummy);
322 if(mapping && mapping->IsAttached())
324 // found mapping, check addresses are in range...
325 TUint offset = aAddr-mapping->Base();
326 TUint end = offset+aSize;
327 if(offset<end && end<=mapping->iSizeInPages<<KPageShift)
329 // addresses OK, get a reference on the mapping before releasing list lock...
330 aOffsetInMapping = offset;
331 aInstanceCount = mapping->MapInstanceCount();
332 mapping->Open(); // can't fail because mapping IsAttached
336 iMappings.ReadUnlock();
342 TBool DAddressSpace::CheckPdeType(TLinAddr aAddr, TUint aSize, TUint aPdeType)
344 TRACE(("DAddressSpace::CheckPdeType(0x%08x,0x%08x,%d) osAsid=%d",aAddr, aSize, aPdeType, iOsAsid));
347 if(iOsAsid==(TInt)KKernelOsAsid && UserGlobalVirtualAllocator.InRange(aAddr,aSize))
348 r = UserGlobalVirtualAllocator.CheckSlabType(aAddr,aSize,aPdeType);
350 r = iVirtualAllocator.CheckSlabType(aAddr,aSize,aPdeType);
351 TRACE(("DAddressSpace::CheckPdeType returns %d",r));
364 void DAddressSpace::Dump()
366 Kern::Printf("DAddressSpace[0x%08x]::Dump() osAsid = %d",this,iOsAsid);
371 iMappings.ReadLock();
372 TUint offsetInMapping = 0;
373 DMemoryMapping* mapping = (DMemoryMapping*)iMappings.Find(virt,offsetInMapping);
376 if(!mapping->TryOpen())
378 virt -= offsetInMapping;
380 iMappings.ReadUnlock();