diff -r 000000000000 -r 96e5fb8b040d kernel/eka/memmodel/epoc/flexible/mmu/maddressspace.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kernel/eka/memmodel/epoc/flexible/mmu/maddressspace.h Thu Dec 17 09:24:54 2009 +0200 @@ -0,0 +1,311 @@ +// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of the License "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// + +/** +@file +@internalComponent +*/ + +#ifndef MADDRESSSPACE_H +#define MADDRESSSPACE_H + +#include "mrefcntobj.h" +#include "maddrcont.h" +#include "mvalloc.h" + + + +// +// DAddressSpace +// + +/** +Class representing the virtual address space used by a single process. + +Each address space has: +- An MMU page directory. +- An allocator for virtual addresses. +- A list of memory mappings currently mapped into it. + +Most other APIs in the kernel which make use of address spaces don't use pointers to +the address space object itself, instead they use an OS Address Space ID (OS ASID). +This is an integer less than KNumOsAsids and can be used to index into the array of +address space objects - #AddressSpace. +*/ +class DAddressSpace : public DReferenceCountedObject + { +public: + /** + Initialiser called during stage 2 of system boot. + This includes initialisation of the kernel's address space object. + */ + static void Init2(); + + /** + Create a new address space. + + This creates a DAddressSpace address space object and adds it to the array + of all address space objects - #AddressSpace. The function returns the objects + index into this array, this value is used as OS Address Space ID (OS ASID) + in most kernel APIs which refer to address spaces. + + @param[out] aPageDirectory Returns the physical address of the MMU page directory + which was created for the new address space. + + @return On success, the OS ASID value for the new address space; + otherwise one of the system wide error codes + */ + static TInt New(TPhysAddr& aPageDirectory); +public: + DAddressSpace(); + ~DAddressSpace(); + + /** + Allocate a region of virtual addresses within this address space. + + The returned region may have a start address and/or size which is different to + those requested due to various alignment requirements in the implementation. + However the returned region will always include all addresses requested. + + The range of virtual addresses available to a user-side address space is + #KUserLocalDataBase through to #KUserLocalDataEnd. + + The range of virtual addresses available to the kernel's address space (#KKernelOsAsid) + is #KKernelSectionBase though to #KKernelSectionEnd. + + @param[out] aAddr Returns the start address of the region which was allocated. + This will always be aligned to a multiple of the page colouring + size: #KPageColourCount*#KPageSize. + @param[out] aSize Returns the size, in bytes, of the region which was allocated. + @param aRequestedAddr The requested start address of the region to allocate, + or zero if no specific address is required. + @param aRequestedSize The requested size, in bytes, of the region to allocate. + @param aPdeType A value from #TPdeType ORed with flags from #TVirtualSlabType. + This is used to prevent incompatible memory uses (different + \a aPdeType values) from being allocated virtual addresses + which would share the same MMU page table. + + @return KErrNone if successful, otherwise one of the system wide error codes. + */ + TInt AllocateVirtualMemory(TLinAddr& aAddr, TUint& aSize, TLinAddr aRequestedAddr, TUint aRequestedSize, TUint aPdeType); + + /** + Allocate a region of virtual addresses within the global address region, for use by + user-side code. These global addresses are outside the range of addresses used + by any individual address space, and so are globally unique. They lie in the range + from #KGlobalMemoryBase through to #KUserMemoryLimit. + + The arguments for this function are of the same type and use as #AllocateVirtualMemory. + */ + static TInt AllocateUserGlobalVirtualMemory(TLinAddr& aAddr, TUint& aSize, TLinAddr aRequestedAddr, TUint aRequestedSize, TUint aPdeType); + + /** + Free a virtual addresses region which was allocated with #AllocateVirtualMemory + or #AllocateUserGlobalVirtualMemory. The region supplied to this function + must either be one supplied to a previous call to AllocateVirtualMemory or + be one returned by that function. + + @param aAddr Start address of the region to be freed. + @param aSize Size, in bytes, of the region to be freed. + */ + void FreeVirtualMemory(TLinAddr aAddr, TUint aSize); + + /** + Allocate a region of virtual addresses for use by memory which should appear at + the same address in all user-side processes which map it. E.g. for position dependant + memory like executable code. + + The region allocated lies in the range used by normal user-side address spaces + but there is no guarantee that the addresses are not already in use by any of them, + and there is nothing to prevent the allocated addresses from being returned by any + future call to #AllocateVirtualMemory. + + However, as the 'common' addresses are allocated from the top of memory downwards + and #AllocateVirtualMemory allocates upwards from the bottom of memory it XXX TODO + + The arguments for this function are of the same type and use as #AllocateVirtualMemory. + */ + static TInt AllocateUserCommonVirtualMemory(TLinAddr& aAddr, TUint& aSize, TLinAddr aRequestedAddr, TUint aRequestedSize, TUint aPdeType); + + /** + Free a virtual addresses region which was allocated with #AllocateUserCommonVirtualMemory. + The region supplied to this function must either be one supplied to a previous + call to AllocateVirtualMemory or be one returned by that function. + + @param aAddr Start address of the region to be freed. + @param aSize Size, in bytes, of the region to be freed. + */ + static void FreeUserCommonVirtualMemory(TLinAddr aAddr, TUint aSize); + + /** + Add a memory mapping to this address space's list of mappings. + + This is intended only for use by #DMemoryMapping. + + @param aAddr The address which is allocated to the mapping + (DMemoryMapping::iAllocatedLinAddrAndOsAsid&~KPageMask). + @param aMapping The mapping to add. + + @return KErrNone if successful, otherwise one of the system wide error codes. + */ + TInt AddMapping(TLinAddr aAddr, DMemoryMapping* aMapping); + + /** + Remove a memory mapping from this address space's list of mappings. + + This is intended only for use by #DMemoryMapping. + + @param aAddr The address which was used to add the mapping with AddMapping. + + @return Pointer to the removed mapping or the null pointer if no mapping + was found to match the specified address. + */ + DMemoryMapping* RemoveMapping(TLinAddr aAddr); + + /** + Get a pointer to a memory mapping which was previously added to this + address space's list of mappings. This function does not perform any additional + reference counting or locking to prevent the returned pointer becoming invalid, + therefore the caller must ensure that it is not possible for another thread to + destroy the mapping. + + The typical use case for this function is where the owner of the mapping has + not saved the pointer to the mapping object but has instead kept track of the + virtual address it uses. This function can then be used to retrieve the pointer + to the object again. + + If no mapping exists for the specified address the results are unpredictable. + + @param aAddr The address which was used to add the mapping with AddMapping. + + @return Pointer to the mapping. + */ + DMemoryMapping* GetMapping(TLinAddr aAddr); + + /** + Find the mapping within this address space which maps a specified region of + addresses. A mapping is only found if all of the bytes in the specified region + lie within it and it is current mapping a memory object (#DMemoryMapping::IsAttached + returns true). + + The returned mapping will have had its reference count incremented and it is + the callers responsibility to balance this with a #Close or #AsyncClose. + + @param aAddr The start address of the region. + @param aSize The size, in bytes, of the region. + @param[out] aOffsetInMapping Returns the byte address offset within the found + mapping which corresponds to \a aAddr. + @param[out] aInstanceCount The instance count of the found mapping. + + @return Pointer to the mapping which contains the specified region + or the null pointer if no mapping was found. + + @post The returned mapping will have had its reference count incremented. + */ + DMemoryMapping* FindMapping(TLinAddr aAddr, TUint aSize, TUint& aOffsetInMapping, TUint& aInstanceCount); + + /** + Check that the virtual addresses previously allocated with #AllocateVirtualMemory + or #AllocateUserGlobalVirtualMemory are compatible with the specified 'pde type'. + + This is only intended for used by error checking in debug builds. + + @param aAddr The start address of the region. + @param aSize The size, in bytes, of the region. + @param aPdeType See description in AllocateVirtualMemory. + */ + TBool CheckPdeType(TLinAddr aAddr, TUint aSize, TUint aPdeType); + +private: + /** + Second phase constructor. + + @param aOsAsid The OS ASID for the address space. + @param aStart The first virtual address available in the address space. + @param aEnd The last virtual address (plus one) available in the address space. + + @return KErrNone if successful, otherwise one of the system wide error codes. + */ + TInt Construct(TInt aOsAsid, TLinAddr aStart, TLinAddr aEnd); + + /** + Wait on the mutex used to protect virtual address allocation and the + addition/removal of memory mappings. This is only used internally by + the DAddressSpace methods. + */ + void Lock(); + + /** + Reverse the action of #Lock. + */ + void Unlock(); + + /** + In debug builds, dump information about each mapping in the address to the + kernel trace port. + */ + void Dump(); + +private: + /** + The OS ASID value for this address space. + This is its index in the array #AddressSpace. + */ + TInt iOsAsid; + + /** + Lock currently being used to protect virtual address allocation (#iVirtualAllocator) + and changes to the mapping container (#iMappings). + */ + DMutex* iLock; + + /** + Container containing all mappings added to this address space. + */ + RAddressedContainer iMappings; + + /** + Allocator object for virtual addresses within the address space. + */ + RVirtualAllocator iVirtualAllocator; + +private: + /** + Allocator for virtual addresses within the global address region for use by user-side code. + + This is used by #AllocateUserGlobalVirtualMemory and the lock mutex for the + kernel's address space is used to protect access. + */ + static RVirtualAllocator UserGlobalVirtualAllocator; + + /** + Allocator for virtual addresses for use by memory which should appear at + the same address in all user-side processes which map it. + + This is used by AllocateUserCommonVirtualMemory and the lock mutex for the + kernel's address space is used to protect access. + */ + static RBackwardsVirtualAllocator UserCommonVirtualAllocator; + }; + + +/** +Array of all address spaces. An OS Address Space ID (OS ASID) can be used to +index this array to find the corresponding DAddressSpace object. +*/ +extern DAddressSpace* AddressSpace[]; + + +#endif