sl@0: // Copyright (c) 1994-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of the License "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // e32\nkern\arm\ncutils.cpp sl@0: // sl@0: // sl@0: sl@0: #include sl@0: #include "../../include/kernel/kernboot.h" sl@0: sl@0: extern "C" { sl@0: SFullArmRegSet ArmRegs; sl@0: } sl@0: sl@0: #ifdef _DEBUG sl@0: void FastMutexNestAttempt() sl@0: { sl@0: FAULT(); sl@0: } sl@0: sl@0: void FastMutexSignalError() sl@0: { sl@0: FAULT(); sl@0: } sl@0: #endif sl@0: sl@0: void NKern::Init0(TAny*) sl@0: { sl@0: ArmRegs.iExcCode = -1; sl@0: TheScheduler.i_Regs = &ArmRegs; sl@0: } sl@0: sl@0: GLDEF_C TUint32 IrqReturnAddress() sl@0: { sl@0: TStackInfo& stackInfo = ((SSuperPageBase*)::SuperPageAddress)->iStackInfo; sl@0: return ((TUint32)stackInfo.iIrqStackBase) + stackInfo.iIrqStackSize - sizeof(TUint32); sl@0: } sl@0: sl@0: /** Register the global IRQ handler sl@0: Called by the base port at boot time to bind the top level IRQ dispatcher sl@0: to the ARM IRQ vector. Should not be called at any other time. sl@0: sl@0: The handler specified will be called in mode_irq with IRQs disabled and sl@0: FIQs enabled. R0-R3, R12 and the return address from the interrupt will sl@0: be on the top of the mode_irq stack. R14_irq will point to the kernel's sl@0: IRQ postamble routine, which will run IDFCs and reschedule if necessary. sl@0: R13_irq will point to the top of the mode_irq stack and will be 8-byte aligned. sl@0: The handler should preserve all registers other than R0-R3, R12, R14_irq sl@0: and should return to the address in R14_irq. sl@0: sl@0: @param aHandler The address of the top level IRQ dispatcher routine sl@0: */ sl@0: EXPORT_C void Arm::SetIrqHandler(TLinAddr aHandler) sl@0: { sl@0: ArmInterruptInfo.iIrqHandler=aHandler; sl@0: } sl@0: sl@0: /** Register the global FIQ handler sl@0: Called by the base port at boot time to bind the top level FIQ dispatcher sl@0: to the ARM FIQ vector. Should not be called at any other time. sl@0: sl@0: The handler specified will be called in mode_fiq with both IRQs and FIQs sl@0: disabled. The return address from the interrupt will be on the top of the sl@0: mode_fiq stack. R14_fiq will point to the kernel's FIQ postamble routine, sl@0: which will run IDFCs and reschedule if necessary. sl@0: R13_fiq will point to the top of the mode_fiq stack and will be 4 modulo 8. sl@0: The handler should preserve all registers other than R8_fiq-R12_fiq and sl@0: R14_fiq and should return to the address in R14_fiq. sl@0: sl@0: @param aHandler The address of the top level FIQ dispatcher routine sl@0: */ sl@0: EXPORT_C void Arm::SetFiqHandler(TLinAddr aHandler) sl@0: { sl@0: ArmInterruptInfo.iFiqHandler=aHandler; sl@0: } sl@0: sl@0: extern void initialiseState(); sl@0: void Arm::Init1Interrupts() sl@0: // sl@0: // Initialise the interrupt and exception vector handlers. sl@0: // sl@0: { sl@0: // TheIrqHandler=0; // done by placing TheIrqHandler, TheFiqHandler in .bss sl@0: // TheFiqHandler=0; sl@0: sl@0: initialiseState(); sl@0: } sl@0: sl@0: extern "C" void __ArmVectorReset() sl@0: // sl@0: // Reset sl@0: // sl@0: { sl@0: sl@0: FAULT(); sl@0: } sl@0: sl@0: extern "C" void __ArmVectorReserved() sl@0: // sl@0: // Reserved sl@0: // sl@0: { sl@0: sl@0: FAULT(); sl@0: } sl@0: sl@0: sl@0: TInt BTraceDefaultControl(BTrace::TControl /*aFunction*/, TAny* /*aArg1*/, TAny* /*aArg2*/) sl@0: { sl@0: return KErrNotSupported; sl@0: } sl@0: sl@0: sl@0: EXPORT_C void BTrace::SetHandlers(BTrace::THandler aNewHandler, BTrace::TControlFunction aNewControl, BTrace::THandler& aOldHandler, BTrace::TControlFunction& aOldControl) sl@0: { sl@0: TUint irq = NKern::DisableAllInterrupts(); sl@0: sl@0: aOldHandler = BTraceData.iHandler; sl@0: BTraceData.iHandler = aNewHandler; sl@0: ArmInterruptInfo.iBTraceHandler = aNewHandler; sl@0: TheScheduler.iBTraceHandler = aNewHandler; sl@0: sl@0: aOldControl = BTraceData.iControl; sl@0: BTraceData.iControl = aNewControl ? aNewControl : BTraceDefaultControl; sl@0: sl@0: NKern::RestoreInterrupts(irq); sl@0: } sl@0: sl@0: sl@0: EXPORT_C TInt BTrace::SetFilter(TUint aCategory, TInt aValue) sl@0: { sl@0: if(!IsSupported(aCategory)) sl@0: return KErrNotSupported; sl@0: TUint irq = NKern::DisableAllInterrupts(); sl@0: TUint8* filter = BTraceData.iFilter+aCategory; sl@0: TUint oldValue = *filter; sl@0: if(TUint(aValue)<=1u) sl@0: { sl@0: *filter = (TUint8)aValue; sl@0: BTraceContext4(BTrace::EMetaTrace, BTrace::EMetaTraceFilterChange, (TUint8)aCategory | (aValue<<8)); sl@0: if(aCategory==ECpuUsage) sl@0: { sl@0: ArmInterruptInfo.iCpuUsageFilter = aValue; sl@0: TheScheduler.iCpuUsageFilter = aValue; sl@0: } sl@0: if (aCategory == EFastMutex) sl@0: { sl@0: // This is done because of the optimization in ncsched.cia for sl@0: // ARMv5 (check if lock is free (cmp) && filter is enabled (cmpeq)) sl@0: TheScheduler.iFastMutexFilter = aValue ? 1 : 0; sl@0: } sl@0: } sl@0: NKern::RestoreInterrupts(irq); sl@0: return oldValue; sl@0: } sl@0: sl@0: EXPORT_C SCpuIdleHandler* NKern::CpuIdleHandler() sl@0: { sl@0: return &ArmInterruptInfo.iCpuIdleHandler; sl@0: } sl@0: sl@0: EXPORT_C TUint32 NKern::CpuTimeMeasFreq() sl@0: { sl@0: #ifdef MONITOR_THREAD_CPU_TIME sl@0: return NKern::FastCounterFrequency(); sl@0: #else sl@0: return 0; sl@0: #endif sl@0: }