--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/eka/memmodel/epoc/flexible/mmu/mmappinglist.cpp Mon Oct 19 15:55:17 2009 +0100
@@ -0,0 +1,209 @@
+// 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:
+//
+
+#include <plat_priv.h>
+#include "mm.h"
+#include "mmu.h"
+
+#include "mmappinglist.h"
+#include "mmapping.h"
+
+
+TSpinLock TMappingListBase::iSpinLock(TSpinLock::EOrderGenericIrqHigh3);
+
+
+//
+// TMappingList
+//
+
+void TMappingList::Add(DMemoryMappingBase* aMapping)
+ {
+ __NK_ASSERT_DEBUG(LockIsHeld());
+ aMapping->iLink.InsertBefore(this);
+ }
+
+
+void TMappingList::Remove(DMemoryMappingBase* aMapping)
+ {
+ __NK_ASSERT_DEBUG(LockIsHeld());
+ aMapping->iLink.Remove();
+ }
+
+
+// Utility methods
+
+void TMappingList::RemapPage(TPhysAddr& aPageArray, TUint aIndex, TBool aInvalidateTLB)
+ {
+ Lock();
+ TMappingListIter iter;
+ DMemoryMappingBase* mapping = iter.Start(*this);
+ while(mapping)
+ {
+ TUint start = aIndex-mapping->iStartIndex;
+ if(start < mapping->iSizeInPages && !mapping->IsPinned())
+ {
+ // remap the page in the mapping...
+ mapping->Open();
+ TUint mapInstanceCount = mapping->MapInstanceCount();
+ Unlock();
+ mapping->RemapPage(aPageArray, aIndex, mapInstanceCount, aInvalidateTLB);
+ mapping->AsyncClose();
+ }
+ else
+ {
+ // the mapping doesn't contain the page or is a pinned mapping and therefore doesn't own
+ // any page tables...
+ Unlock();
+ }
+ Lock();
+ mapping = iter.Next();
+ }
+ iter.Finish();
+ Unlock();
+ }
+
+
+//
+// TMappingListIter
+//
+
+DMemoryMappingBase* TMappingListIter::Start(TMappingList& aList)
+ {
+ TRACE2(("TMappingListIter::Start"));
+ __NK_ASSERT_DEBUG(LockIsHeld());
+ return Next(&aList);
+ }
+
+
+void TMappingListIter::Finish()
+ {
+ TRACE2(("TMappingListIter::Finish"));
+ __NK_ASSERT_DEBUG(LockIsHeld());
+ Remove();
+ }
+
+
+DMemoryMappingBase* TMappingListIter::Next(TMappingListBase* aPrev)
+ {
+ // avoid live-lock by only flashing iSpinLock after a number of attempts greater
+ // than the number of CPU cores, that way each core is guaranteed to make some headway...
+ const TUint KFlashPeriod = KMaxCpus+1;
+ __ASSERT_COMPILE(KFlashPeriod<10); // make sure limit is sensible, if not, will need more complex live-lock avoidance
+ TUint flash = 0;
+
+ TMappingListBase* prev = aPrev;
+ TMappingListBase* next = prev->iNext;
+ for(;;)
+ {
+ TUint type = next->iType;
+
+ // at end of list?
+ if(type==EHead)
+ {
+ // yes, so put iterator back at end...
+ prev->iNext = this;
+ next->iPrev = this;
+ iNext = next;
+ iPrev = prev;
+ // return NULL...
+ TRACE2(("TMappingListIter::Next returns 0"));
+ return 0;
+ }
+
+ // move past next...
+ prev = next;
+ next = next->iNext;
+
+ // have we found a mapping?
+ if(type==ELink)
+ {
+ // yes, so insert iterator after it...
+ prev->iNext = this;
+ next->iPrev = this;
+ iNext = next;
+ iPrev = prev;
+ // return mapping...
+ DMemoryMappingBase* mapping = (DMemoryMappingBase*)((TLinAddr)prev-_FOFF(DMemoryMappingBase,iLink));
+ TRACE2(("TMappingListIter::Next returns 0x%08x",mapping));
+ return mapping;
+ }
+
+ // move on to next...
+ TRACE2(("TMappingListIter::Next skip %d",next->iType));
+
+ // but first see if we need to flash lock...
+ if(++flash>=KFlashPeriod)
+ {
+ // we need to flash the lock, but first put iterator back in list so we don't loose our place...
+ prev->iNext = this;
+ next->iPrev = this;
+ iNext = next;
+ iPrev = prev;
+ // flash lock...
+ __SPIN_FLASH_IRQ(iSpinLock);
+ // remove iterator again...
+ next = iNext;
+ prev = iPrev;
+ prev->iNext = next;
+ next->iPrev = prev;
+ }
+
+ // loop back and try next
+ }
+ }
+
+
+DMemoryMappingBase* TMappingListIter::Next()
+ {
+ __NK_ASSERT_DEBUG(LockIsHeld());
+
+ TMappingListBase* next = iNext;
+ TMappingListBase* prev = iPrev;
+ TUint type = next->iType;
+
+ // at end of list?
+ if(type==EHead)
+ {
+ // yes, return NULL...
+ TRACE2(("TMappingListIter::Next returns 0"));
+ return 0;
+ }
+
+ // unlink iterator...
+ prev->iNext = next;
+ next->iPrev = prev;
+
+ // have we found a mapping?
+ if(type==ELink)
+ {
+ // yes, so insert iterator after it...
+ prev = next;
+ next = next->iNext;
+ prev->iNext = this;
+ next->iPrev = this;
+ iNext = next;
+ iPrev = prev;
+ // return mapping...
+ DMemoryMappingBase* mapping = (DMemoryMappingBase*)((TLinAddr)prev-_FOFF(DMemoryMappingBase,iLink));
+ TRACE2(("TMappingListIter::Next returns 0x%08x",mapping));
+ return mapping;
+ }
+
+ // handle more complicated situations...
+ return Next(next);
+ }
+
+
+