diff -r 000000000000 -r 96e5fb8b040d kernel/eka/include/nkernsmp/arm/nk_plat.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kernel/eka/include/nkernsmp/arm/nk_plat.h Thu Dec 17 09:24:54 2009 +0200 @@ -0,0 +1,314 @@ +// 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: +// e32\include\nkernsmp\arm\nk_plat.h +// +// WARNING: This file contains some APIs which are internal and are subject +// to change without notice. Such APIs should therefore not be used +// outside the Kernel and Hardware Services package. +// + +/** + @file + @internalComponent +*/ + +#ifndef __NK_ARM_H__ +#define __NK_ARM_H__ +#include + +// These macros are intended for Symbian use only. +// It may not be possible to build the kernel if any of these macros are undefined +//#define __SCHEDULER_MACHINE_CODED__ +//#define __DFC_MACHINE_CODED__ +//#define __MSTIM_MACHINE_CODED__ +#define __PRI_LIST_MACHINE_CODED__ +#define __FAST_SEM_MACHINE_CODED__ +#define __FAST_MUTEX_MACHINE_CODED__ +#define __NTHREAD_WAITSTATE_MACHINE_CODED__ + +// TSubScheduler member data +#define i_ScuAddr iExtras[4] // Address of SCU (also in TScheduler) +#define i_GicDistAddr iExtras[5] // Address of GIC Distributor (also in TScheduler) +#define i_GicCpuIfcAddr iExtras[6] // Address of GIC CPU Interface (also in TScheduler) +#define i_LocalTimerAddr iExtras[7] // Address of local timer registers (also in TScheduler) +#define i_IrqCount iExtras[8] // count of interrupts handled +#define i_IrqNestCount iExtras[9] // IRQ nest count for this CPU (starts at -1) +#define i_ExcInfo iExtras[10] // pointer to exception info for crash debugger +#define i_CrashState iExtras[11] // 0=normal, 1=this CPU faulted, 2=this CPU has received an NMI and halted +#define i_AbtStackTop iExtras[12] // Top of ABT stack for this CPU, also used to point to SFullArmRegSet +#define i_UndStackTop iExtras[13] // Top of UND stack for this CPU +#define i_FiqStackTop iExtras[14] // Top of FIQ stack for this CPU +#define i_IrqStackTop iExtras[15] // Top of IRQ stack for this CPU +#define i_TimerMultF iExtras[16] // Timer frequency / Max Timer frequency * 2^32 +#define i_TimerMultI iExtras[17] // Max Timer frequency / Timer frequency * 2^24 +#define i_CpuMult iExtras[18] // CPU frequency / Max CPU frequency * 2^32 +#define i_LastTimerSet iExtras[20] // Value last written to local timer counter +#define i_TimestampError iExtras[21] // Current error in the timestamp +#define i_MaxCorrection iExtras[22] // Maximum correction to timestamp in one go +#define i_TimerGap iExtras[23] // Timestamp ticks taken to read and write local timer counter + +#define i_Regs iExtras[12] // Alias for i_AbtStackTop + +// TScheduler member data +#define i_TimerMax iExtras[16] // Maximum per-CPU timer frequency (after prescaling) + + +#define RESCHED_IPI_VECTOR 0x00 +#define GENERIC_IPI_VECTOR 0x01 +#define TRANSFERRED_IRQ_VECTOR 0x02 +#define CRASH_IPI_VECTOR 0x03 // would really like this to be a FIQ +#define BOOT_IPI_VECTOR 0x04 // used during boot to handshake with APs +#define RESERVED_IPI_VECTOR_1 0x05 // reserved for future kernel functionality +#define RESERVED_IPI_VECTOR_2 0x06 // reserved for future kernel functionality +#define RESERVED_IPI_VECTOR_3 0x07 // reserved for future kernel functionality + +#if defined(__CPU_ARM11MP__) +#define TIMESLICE_VECTOR 0x1D // vector 29 is per-CPU timer interrupt + // vector 30 is per-CPU Watchdog timer when not in watchdog mode + // vector 31 is external nIRQ local interrupt pin +#elif defined(__CPU_CORTEX_A9__) +#define TIMESLICE_VECTOR 0x1D // vector 29 is per-CPU timer interrupt + // vector 30 is per-CPU Watchdog timer when not in watchdog mode +#else +#error TIMESLICE_VECTOR not defined +#endif + + +//extern "C" TSubScheduler* SubSchedulerLookupTable[256]; // look up subscheduler from APIC ID + +const TUint32 KNThreadContextFlagThumbBit0=1; + +/** Registers saved by the scheduler + +Let's just have the same stack layout for all CPUs shall we? +TEEHBR, FpExc may not be used but leave space on the stack for them. + +@internalComponent +*/ +struct SThreadReschedStack + { + TUint32 iFpExc; // VFP enable + TUint32 iCar; // coprocessor access register + TUint32 iTEEHBR; // Thumb2-EE Handler Base + TUint32 iRWROTID; // User RO Thread ID + TUint32 iRWRWTID; // User RW Thread ID + TUint32 iDacr; // domain access control + TUint32 iSpare; + TUint32 iSpsrSvc; + TUint32 iSPRschdFlg; // Stack pointer plus flag indicating reschedule occurred + TUint32 iR15; // return address from Reschedule() + }; + +/** Registers saved on any exception, interrupt or system call + +@internalComponent +*/ +struct SThreadExcStack + { + enum TType + { + EPrefetch =0, // prefetch abort + EData =1, // data abort + EUndef =2, // undefined instruction + EIrq =3, // IRQ interrupt + EFiq =4, // FIQ interrupt + ESvc =5, // SWI + EInit =6, // Thread has never run + EStub =7, // Stub indicating parameter block still on stack + }; + + TUint32 iR0; + TUint32 iR1; + TUint32 iR2; + TUint32 iR3; + TUint32 iR4; + TUint32 iR5; + TUint32 iR6; + TUint32 iR7; + TUint32 iR8; + TUint32 iR9; + TUint32 iR10; + TUint32 iR11; + TUint32 iR12; + TUint32 iR13usr; // always user mode R13 + TUint32 iR14usr; // always user mode R14 + TUint32 iExcCode; + TUint32 iR15; // return address + TUint32 iCPSR; // return CPSR + }; + +/** +@internalComponent +*/ +struct SThreadStackStub + { + TLinAddr iPBlock; // pointer to parameter block + TUint32 iExcCode; // always EStub + TUint32 iR15; // unused + TUint32 iCPSR; // unused + }; + +/** +@internalComponent +*/ +struct SThreadInitStack + { + SThreadReschedStack iR; + SThreadExcStack iX; + }; + + +/** +@internalComponent +*/ +struct SThreadIrqStack + { + SThreadReschedStack iR; + TUint32 iUMGSave; // User memory guard state (if active) + TUint32 iR14svc; + SThreadExcStack iX; + }; + + +class TArmContextElement; +class TArmRegSet; + +/** ARM-specific part of the nano-thread abstraction. + @internalComponent + */ +class NThread : public NThreadBase + { +public: + TInt Create(SNThreadCreateInfo& aInfo, TBool aInitial); + inline void Stillborn() + {} + + /** Value indicating what event caused thread to enter privileged mode. + @publishedPartner + @released + */ + enum TUserContextType + { + EContextNone=0, /**< Thread has no user context */ + EContextException=1, /**< Hardware exception while in user mode */ + EContextUndefined, + EContextUserInterrupt, /**< Preempted by interrupt taken in user mode */ + EContextUserInterruptDied, /**< Killed while preempted by interrupt taken in user mode */ // NOT USED + EContextSvsrInterrupt1, /**< Preempted by interrupt taken in executive call handler */ + EContextSvsrInterrupt1Died, /**< Killed while preempted by interrupt taken in executive call handler */ // NOT USED + EContextSvsrInterrupt2, /**< Preempted by interrupt taken in executive call handler */ // NOT USED + EContextSvsrInterrupt2Died, /**< Killed while preempted by interrupt taken in executive call handler */ // NOT USED + EContextWFAR, /**< Blocked on User::WaitForAnyRequest() */ + EContextWFARDied, /**< Killed while blocked on User::WaitForAnyRequest() */ // NOT USED + EContextExec, /**< Slow executive call */ + EContextKernel, /**< Kernel side context (for kernel threads) */ + EContextKernel1, /**< Kernel side context (for kernel threads) (NKern::Unlock, NKern::PreemptionPoint) */ + EContextKernel2, /**< Kernel side context (for kernel threads) (NKern::FSWait, NKern::WaitForAnyRequest) */ + EContextKernel3, /**< Kernel side context (for kernel threads) (Interrupt) */ + EContextKernel4, /**< Kernel side context (for kernel threads) (Exec::WaitForAnyRequest) */ + }; + + IMPORT_C static const TArmContextElement* const* UserContextTables(); + IMPORT_C TUserContextType UserContextType(); + void GetUserContext(TArmRegSet& aContext, TUint32& aAvailRegistersMask); + void SetUserContext(const TArmRegSet& aContext, TUint32& aRegMask); + void GetSystemContext(TArmRegSet& aContext, TUint32& aAvailRegistersMask); + + TUint32 Dacr(); + void SetDacr(TUint32 aDacr); + TUint32 ModifyDacr(TUint32 aClearMask, TUint32 aSetMask); + + void SetCar(TUint32 aDacr); + IMPORT_C TUint32 Car(); + IMPORT_C TUint32 ModifyCar(TUint32 aClearMask, TUint32 aSetMask); + +#ifdef __CPU_HAS_VFP + void SetFpExc(TUint32 aDacr); +#endif + IMPORT_C TUint32 FpExc(); + IMPORT_C TUint32 ModifyFpExc(TUint32 aClearMask, TUint32 aSetMask); + + void CompleteContextSave(); + }; + + +struct SArmInterruptInfo + { + TLinAddr iIrqHandler; + TLinAddr iFiqHandler; + SCpuIdleHandler iCpuIdleHandler; + }; + +extern "C" SArmInterruptInfo ArmInterruptInfo; + +#if defined(__ARMCC__) +#ifndef __CIA__ +inline void mb() + { + TUint32 reg = 0; + asm("mcr p15, 0, reg, c7, c10, 5 "); + } + +inline void arm_dsb() + { + TUint32 reg = 0; + asm("mcr p15, 0, reg, c7, c10, 4 "); + } + +inline void arm_isb() + { + TUint32 reg = 0; + asm("mcr p15, 0, reg, c7, c5, 4 "); + } +#endif +#elif defined(__GNUC__) || defined(__GCC32__) +#define mb() \ + do { \ + TUint32 reg = 0; \ + __asm__ __volatile__("mcr p15, 0, %0, c7, c10, 5" : : "r"(reg) : "memory"); \ + } while(0) + +#define arm_dsb() \ + do { \ + TUint32 reg = 0; \ + __asm__ __volatile__("mcr p15, 0, %0, c7, c10, 4" : : "r"(reg) : "memory"); \ + } while(0) + +#define arm_isb() \ + do { \ + TUint32 reg = 0; \ + __asm__ __volatile__("mcr p15, 0, %0, c7, c5, 4" : : "r"(reg) : "memory"); \ + } while(0) +#else +#error Unknown ARM compiler +#endif + +#define smp_mb() mb() +#define wmb() mb() +#define smp_wmb() mb() + +#ifdef __IN_KERNEL__ +struct ArmScu; +struct GicDistributor; +struct GicCpuIfc; +struct ArmLocalTimer; +#define SCU (*(ArmScu*)TheScheduler.i_ScuAddr) +#define GIC_DIST (*(GicDistributor*)TheScheduler.i_GicDistAddr) +#define GIC_CPU_IFC (*(GicCpuIfc*)TheScheduler.i_GicCpuIfcAddr) +#define LOCAL_TIMER (*(ArmLocalTimer*)TheScheduler.i_LocalTimerAddr) +#endif + + +// End of file +#endif