diff -r 000000000000 -r a41df078684a kerneltest/e32test/mmu/t_btb.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kerneltest/e32test/mmu/t_btb.cpp Mon Oct 19 15:55:17 2009 +0100 @@ -0,0 +1,236 @@ +// Copyright (c) 1995-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: +// e32test\mmu\t_btb.cpp +// +// + +//! @SYMTestCaseID KBASE/T_BTB +//! @SYMTestType UT +//! @SYMTestCaseDesc Make sure processes can't interfere with each other via the BTB. Make sure the BTB is turned on. +//! @SYMREQ REQ4095 +//! @SYMTestActions Make concurent processes with code areas and thrash them. +//! @SYMTestExpectedResults They shouldn't interfere. The BTB should be enabled. +//! @SYMTestPriority Low +//! @SYMTestStatus Defined + +#include +#include "u32std.h" + +#ifdef __CPU_ARM + +extern TInt BranchTest1(); +extern TInt BranchTest2(); +extern TInt BranchTest3(); +void BranchTest4(TInt); +extern void BranchTest1End(); +extern void BranchTest2End(); +extern void BranchTest3End(); +extern void BranchTest4End(); + +typedef TInt (*PFI)(void); +typedef void (*PFV)(TInt); + +void SecondaryProcess(const TDesC& aCmd, RTest& test) + { + test.Start(_L("Secondary Process")); + TLex lex(aCmd); + TUint32 addr; + TInt r=lex.Val(addr,EHex); + test(r==KErrNone); + test.Printf(_L("Primary process says: RAM code at %08x\n"),addr); + TInt pageSize; + r=UserHal::PageSizeInBytes(pageSize); + test(r==KErrNone); + RChunk c; + r=c.CreateLocalCode(pageSize,0x100000); + test(r==KErrNone); + PFI pBranchTest2=(PFI)c.Base(); + test.Printf(_L("Secondary test loop function at %08x\n"),pBranchTest2); + + test((TUint32)pBranchTest2==addr); + + TInt fnLength = (TInt)&BranchTest2End-(TInt)&BranchTest2; + + test.Printf(_L("SecProc: Copying %d bytes from %08x...\n"), (TInt)&BranchTest2End-(TInt)&BranchTest2, (TAny*)&BranchTest2 ); + Mem::Copy((TAny*)pBranchTest2, (TAny*)&BranchTest2, fnLength); + User::IMB_Range((TAny*)pBranchTest2, fnLength+(TUint8*)pBranchTest2); + + TTime begin; + begin.HomeTime(); + + test.Printf(_L("Running secondary loop...\n")); + + TInt n=0; + FOREVER + { + n=pBranchTest2(); + + if (n) + break; + + TTime now; + now.HomeTime(); + if (now.MicroSecondsFrom(begin).Int64()>20000000) // ten seconds for each test ought to be long enough + break; + } + test.Printf(_L("Ending secondary loop.\n")); + test(n==0); + //test.End(); + } + + +GLREF_C TInt E32Main() + { + RTest test(_L("T_BTB")); + test.Title(); + + TBuf<16> cmd; + User::CommandLine(cmd); + if (cmd.Length()!=0) // if we get a command line, we're the secondary process + { + SecondaryProcess(cmd,test); + return 0; + } + + test.Start(_L("Create primary process code chunk")); + TInt pageSize; + TInt r=UserHal::PageSizeInBytes(pageSize); + test(r==KErrNone); + + RChunk c; + r=c.CreateLocalCode(pageSize,0x100000); + test(r==KErrNone); + TUint8* pCode=c.Base(); + test.Printf(_L("Primary process code chunk at %08x\n"),pCode); + + // Spawn a secondary process + RProcess p; + TRequestStatus s; + TBuf<16> codeBaseHex; + codeBaseHex.Format(_L("%08x"),pCode); + r=p.Create(RProcess().FileName(),codeBaseHex); + test(r==KErrNone); + p.Logon(s); + p.Resume(); + + + TTime begin, now; + TInt n=0, m=0, q=0, fnLength; + + PFI pBranchTest1=(PFI)pCode; + test.Printf(_L("Primary test loop function at %08x\n"),pBranchTest1); + + fnLength = (TInt)&BranchTest1End-(TInt)&BranchTest1; + + //test.Printf(_L("PriProc: Copying %d bytes from 0x%08x to 0x%08x for forward-branching test...\n"), fnLength, &BranchTest1, pBranchTest1); + Mem::Copy((TAny *)pBranchTest1, (const TAny*)&BranchTest1, fnLength); // copy in the asm test code + User::IMB_Range((TAny*)pBranchTest1, fnLength+(TUint8*)pBranchTest1); + + test.Printf(_L("Running primary loop...\n")); + begin.HomeTime(); + FOREVER + { + m++; + n=pBranchTest1(); + if (n) + break; + now.HomeTime(); + if (now.MicroSecondsFrom(begin).Int64()>10000000) // ten seconds ought to be long enough + break; + } + test(n==0); + test.Printf(_L("Ending primary loop. Ran %d times in 10s.\n"), m); + + // run the second test + + PFI pBranchTest3=(PFI)pCode; + + fnLength = (TInt)&BranchTest3End-(TInt)&BranchTest3; + //test.Printf(_L("PriProc: Copying %d bytes from 0x%08x to 0x%08x for back-branching test...\n"), fnLength, &BranchTest3, pBranchTest3); + Mem::Copy((TAny *)pBranchTest3, (const TAny*)&BranchTest3, fnLength); // copy in the asm test code + User::IMB_Range((TAny*)pBranchTest3, fnLength+(TUint8*)pBranchTest3); + + test.Printf(_L("PriProc: Starting back-branch test loop.\n")); + m=0; + begin.HomeTime(); + FOREVER + { + m++; + n=pBranchTest3(); + if (n) + break; + now.HomeTime(); + if (now.MicroSecondsFrom(begin).Int64()>10000000) // ten seconds ought to be long enough + break; + } + test(n==0); + test.Printf(_L("Ending primary back-branching loop. Ran %d times in 10s.\n"), m); + + p.Kill(0); + User::WaitForRequest(s); + TInt exitType=p.ExitType(); + TInt exitReason=p.ExitReason(); + TExitCategoryName exitCat=p.ExitCategory(); + CLOSE_AND_WAIT(p); + test.Printf(_L("SecProc: %d,%d,%S\n"),exitType,exitReason,&exitCat); + test(exitType==EExitKill); + test(exitReason==KErrNone); + + // speed test + + PFV pBranchTest4 = (PFV)pCode; + fnLength = (TInt)&BranchTest4End-(TInt)&BranchTest4; + //test.Printf(_L("PriProc: Copying %d bytes from 0x%08x to 0x%08x for forward-branching speed test...\n"), fnLength, &BranchTest4, pBranchTest1); + Mem::Copy((TAny *)pBranchTest4, (const TAny*)&BranchTest4, fnLength); // copy in the asm test code + User::IMB_Range((TAny*)pBranchTest4, fnLength+(TUint8*)pBranchTest4); + + test.Printf(_L("Speed test running with f(0)...\n")); + m=0; + begin.HomeTime(); + FOREVER + { + m++; + pBranchTest4(0); + now.HomeTime(); + if (now.MicroSecondsFrom(begin).Int64()>10000000) // ten seconds ought to be long enough + break; + } + test.Printf(_L("Ending f(0) test. Ran %d times in 10s.\n"), m); + + test.Printf(_L("PriProc: Starting f(1) run.\n")); + q=0; + begin.HomeTime(); + FOREVER + { + q++; + pBranchTest4(1); + now.HomeTime(); + if (now.MicroSecondsFrom(begin).Int64()>10000000) // ten seconds ought to be long enough + break; + } + test.Printf(_L("Ending test loop with f(1). Ran %d times in 10s.\n"), q); + + test(m-q>m/4); // the difference between m and q should be large, indicating successful prediction + + c.Close(); + + test.End(); + return 0; + } +#else +GLREF_C TInt E32Main() + { + return 0; + } +#endif