1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/kernelhwsrv/kernel/eka/include/nkernsmp/arm/nk_plat.h Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,314 @@
1.4 +// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of the License "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +// e32\include\nkernsmp\arm\nk_plat.h
1.18 +//
1.19 +// WARNING: This file contains some APIs which are internal and are subject
1.20 +// to change without notice. Such APIs should therefore not be used
1.21 +// outside the Kernel and Hardware Services package.
1.22 +//
1.23 +
1.24 +/**
1.25 + @file
1.26 + @internalComponent
1.27 +*/
1.28 +
1.29 +#ifndef __NK_ARM_H__
1.30 +#define __NK_ARM_H__
1.31 +#include <nk_cpu.h>
1.32 +
1.33 +// These macros are intended for Symbian use only.
1.34 +// It may not be possible to build the kernel if any of these macros are undefined
1.35 +//#define __SCHEDULER_MACHINE_CODED__
1.36 +//#define __DFC_MACHINE_CODED__
1.37 +//#define __MSTIM_MACHINE_CODED__
1.38 +#define __PRI_LIST_MACHINE_CODED__
1.39 +#define __FAST_SEM_MACHINE_CODED__
1.40 +#define __FAST_MUTEX_MACHINE_CODED__
1.41 +#define __NTHREAD_WAITSTATE_MACHINE_CODED__
1.42 +
1.43 +// TSubScheduler member data
1.44 +#define i_ScuAddr iExtras[4] // Address of SCU (also in TScheduler)
1.45 +#define i_GicDistAddr iExtras[5] // Address of GIC Distributor (also in TScheduler)
1.46 +#define i_GicCpuIfcAddr iExtras[6] // Address of GIC CPU Interface (also in TScheduler)
1.47 +#define i_LocalTimerAddr iExtras[7] // Address of local timer registers (also in TScheduler)
1.48 +#define i_IrqCount iExtras[8] // count of interrupts handled
1.49 +#define i_IrqNestCount iExtras[9] // IRQ nest count for this CPU (starts at -1)
1.50 +#define i_ExcInfo iExtras[10] // pointer to exception info for crash debugger
1.51 +#define i_CrashState iExtras[11] // 0=normal, 1=this CPU faulted, 2=this CPU has received an NMI and halted
1.52 +#define i_AbtStackTop iExtras[12] // Top of ABT stack for this CPU, also used to point to SFullArmRegSet
1.53 +#define i_UndStackTop iExtras[13] // Top of UND stack for this CPU
1.54 +#define i_FiqStackTop iExtras[14] // Top of FIQ stack for this CPU
1.55 +#define i_IrqStackTop iExtras[15] // Top of IRQ stack for this CPU
1.56 +#define i_TimerMultF iExtras[16] // Timer frequency / Max Timer frequency * 2^32
1.57 +#define i_TimerMultI iExtras[17] // Max Timer frequency / Timer frequency * 2^24
1.58 +#define i_CpuMult iExtras[18] // CPU frequency / Max CPU frequency * 2^32
1.59 +#define i_LastTimerSet iExtras[20] // Value last written to local timer counter
1.60 +#define i_TimestampError iExtras[21] // Current error in the timestamp
1.61 +#define i_MaxCorrection iExtras[22] // Maximum correction to timestamp in one go
1.62 +#define i_TimerGap iExtras[23] // Timestamp ticks taken to read and write local timer counter
1.63 +
1.64 +#define i_Regs iExtras[12] // Alias for i_AbtStackTop
1.65 +
1.66 +// TScheduler member data
1.67 +#define i_TimerMax iExtras[16] // Maximum per-CPU timer frequency (after prescaling)
1.68 +
1.69 +
1.70 +#define RESCHED_IPI_VECTOR 0x00
1.71 +#define GENERIC_IPI_VECTOR 0x01
1.72 +#define TRANSFERRED_IRQ_VECTOR 0x02
1.73 +#define CRASH_IPI_VECTOR 0x03 // would really like this to be a FIQ
1.74 +#define BOOT_IPI_VECTOR 0x04 // used during boot to handshake with APs
1.75 +#define RESERVED_IPI_VECTOR_1 0x05 // reserved for future kernel functionality
1.76 +#define RESERVED_IPI_VECTOR_2 0x06 // reserved for future kernel functionality
1.77 +#define RESERVED_IPI_VECTOR_3 0x07 // reserved for future kernel functionality
1.78 +
1.79 +#if defined(__CPU_ARM11MP__)
1.80 +#define TIMESLICE_VECTOR 0x1D // vector 29 is per-CPU timer interrupt
1.81 + // vector 30 is per-CPU Watchdog timer when not in watchdog mode
1.82 + // vector 31 is external nIRQ local interrupt pin
1.83 +#elif defined(__CPU_CORTEX_A9__)
1.84 +#define TIMESLICE_VECTOR 0x1D // vector 29 is per-CPU timer interrupt
1.85 + // vector 30 is per-CPU Watchdog timer when not in watchdog mode
1.86 +#else
1.87 +#error TIMESLICE_VECTOR not defined
1.88 +#endif
1.89 +
1.90 +
1.91 +//extern "C" TSubScheduler* SubSchedulerLookupTable[256]; // look up subscheduler from APIC ID
1.92 +
1.93 +const TUint32 KNThreadContextFlagThumbBit0=1;
1.94 +
1.95 +/** Registers saved by the scheduler
1.96 +
1.97 +Let's just have the same stack layout for all CPUs shall we?
1.98 +TEEHBR, FpExc may not be used but leave space on the stack for them.
1.99 +
1.100 +@internalComponent
1.101 +*/
1.102 +struct SThreadReschedStack
1.103 + {
1.104 + TUint32 iFpExc; // VFP enable
1.105 + TUint32 iCar; // coprocessor access register
1.106 + TUint32 iTEEHBR; // Thumb2-EE Handler Base
1.107 + TUint32 iRWROTID; // User RO Thread ID
1.108 + TUint32 iRWRWTID; // User RW Thread ID
1.109 + TUint32 iDacr; // domain access control
1.110 + TUint32 iSpare;
1.111 + TUint32 iSpsrSvc;
1.112 + TUint32 iSPRschdFlg; // Stack pointer plus flag indicating reschedule occurred
1.113 + TUint32 iR15; // return address from Reschedule()
1.114 + };
1.115 +
1.116 +/** Registers saved on any exception, interrupt or system call
1.117 +
1.118 +@internalComponent
1.119 +*/
1.120 +struct SThreadExcStack
1.121 + {
1.122 + enum TType
1.123 + {
1.124 + EPrefetch =0, // prefetch abort
1.125 + EData =1, // data abort
1.126 + EUndef =2, // undefined instruction
1.127 + EIrq =3, // IRQ interrupt
1.128 + EFiq =4, // FIQ interrupt
1.129 + ESvc =5, // SWI
1.130 + EInit =6, // Thread has never run
1.131 + EStub =7, // Stub indicating parameter block still on stack
1.132 + };
1.133 +
1.134 + TUint32 iR0;
1.135 + TUint32 iR1;
1.136 + TUint32 iR2;
1.137 + TUint32 iR3;
1.138 + TUint32 iR4;
1.139 + TUint32 iR5;
1.140 + TUint32 iR6;
1.141 + TUint32 iR7;
1.142 + TUint32 iR8;
1.143 + TUint32 iR9;
1.144 + TUint32 iR10;
1.145 + TUint32 iR11;
1.146 + TUint32 iR12;
1.147 + TUint32 iR13usr; // always user mode R13
1.148 + TUint32 iR14usr; // always user mode R14
1.149 + TUint32 iExcCode;
1.150 + TUint32 iR15; // return address
1.151 + TUint32 iCPSR; // return CPSR
1.152 + };
1.153 +
1.154 +/**
1.155 +@internalComponent
1.156 +*/
1.157 +struct SThreadStackStub
1.158 + {
1.159 + TLinAddr iPBlock; // pointer to parameter block
1.160 + TUint32 iExcCode; // always EStub
1.161 + TUint32 iR15; // unused
1.162 + TUint32 iCPSR; // unused
1.163 + };
1.164 +
1.165 +/**
1.166 +@internalComponent
1.167 +*/
1.168 +struct SThreadInitStack
1.169 + {
1.170 + SThreadReschedStack iR;
1.171 + SThreadExcStack iX;
1.172 + };
1.173 +
1.174 +
1.175 +/**
1.176 +@internalComponent
1.177 +*/
1.178 +struct SThreadIrqStack
1.179 + {
1.180 + SThreadReschedStack iR;
1.181 + TUint32 iUMGSave; // User memory guard state (if active)
1.182 + TUint32 iR14svc;
1.183 + SThreadExcStack iX;
1.184 + };
1.185 +
1.186 +
1.187 +class TArmContextElement;
1.188 +class TArmRegSet;
1.189 +
1.190 +/** ARM-specific part of the nano-thread abstraction.
1.191 + @internalComponent
1.192 + */
1.193 +class NThread : public NThreadBase
1.194 + {
1.195 +public:
1.196 + TInt Create(SNThreadCreateInfo& aInfo, TBool aInitial);
1.197 + inline void Stillborn()
1.198 + {}
1.199 +
1.200 + /** Value indicating what event caused thread to enter privileged mode.
1.201 + @publishedPartner
1.202 + @released
1.203 + */
1.204 + enum TUserContextType
1.205 + {
1.206 + EContextNone=0, /**< Thread has no user context */
1.207 + EContextException=1, /**< Hardware exception while in user mode */
1.208 + EContextUndefined,
1.209 + EContextUserInterrupt, /**< Preempted by interrupt taken in user mode */
1.210 + EContextUserInterruptDied, /**< Killed while preempted by interrupt taken in user mode */ // NOT USED
1.211 + EContextSvsrInterrupt1, /**< Preempted by interrupt taken in executive call handler */
1.212 + EContextSvsrInterrupt1Died, /**< Killed while preempted by interrupt taken in executive call handler */ // NOT USED
1.213 + EContextSvsrInterrupt2, /**< Preempted by interrupt taken in executive call handler */ // NOT USED
1.214 + EContextSvsrInterrupt2Died, /**< Killed while preempted by interrupt taken in executive call handler */ // NOT USED
1.215 + EContextWFAR, /**< Blocked on User::WaitForAnyRequest() */
1.216 + EContextWFARDied, /**< Killed while blocked on User::WaitForAnyRequest() */ // NOT USED
1.217 + EContextExec, /**< Slow executive call */
1.218 + EContextKernel, /**< Kernel side context (for kernel threads) */
1.219 + EContextKernel1, /**< Kernel side context (for kernel threads) (NKern::Unlock, NKern::PreemptionPoint) */
1.220 + EContextKernel2, /**< Kernel side context (for kernel threads) (NKern::FSWait, NKern::WaitForAnyRequest) */
1.221 + EContextKernel3, /**< Kernel side context (for kernel threads) (Interrupt) */
1.222 + EContextKernel4, /**< Kernel side context (for kernel threads) (Exec::WaitForAnyRequest) */
1.223 + };
1.224 +
1.225 + IMPORT_C static const TArmContextElement* const* UserContextTables();
1.226 + IMPORT_C TUserContextType UserContextType();
1.227 + void GetUserContext(TArmRegSet& aContext, TUint32& aAvailRegistersMask);
1.228 + void SetUserContext(const TArmRegSet& aContext, TUint32& aRegMask);
1.229 + void GetSystemContext(TArmRegSet& aContext, TUint32& aAvailRegistersMask);
1.230 +
1.231 + TUint32 Dacr();
1.232 + void SetDacr(TUint32 aDacr);
1.233 + TUint32 ModifyDacr(TUint32 aClearMask, TUint32 aSetMask);
1.234 +
1.235 + void SetCar(TUint32 aDacr);
1.236 + IMPORT_C TUint32 Car();
1.237 + IMPORT_C TUint32 ModifyCar(TUint32 aClearMask, TUint32 aSetMask);
1.238 +
1.239 +#ifdef __CPU_HAS_VFP
1.240 + void SetFpExc(TUint32 aDacr);
1.241 +#endif
1.242 + IMPORT_C TUint32 FpExc();
1.243 + IMPORT_C TUint32 ModifyFpExc(TUint32 aClearMask, TUint32 aSetMask);
1.244 +
1.245 + void CompleteContextSave();
1.246 + };
1.247 +
1.248 +
1.249 +struct SArmInterruptInfo
1.250 + {
1.251 + TLinAddr iIrqHandler;
1.252 + TLinAddr iFiqHandler;
1.253 + SCpuIdleHandler iCpuIdleHandler;
1.254 + };
1.255 +
1.256 +extern "C" SArmInterruptInfo ArmInterruptInfo;
1.257 +
1.258 +#if defined(__ARMCC__)
1.259 +#ifndef __CIA__
1.260 +inline void mb()
1.261 + {
1.262 + TUint32 reg = 0;
1.263 + asm("mcr p15, 0, reg, c7, c10, 5 ");
1.264 + }
1.265 +
1.266 +inline void arm_dsb()
1.267 + {
1.268 + TUint32 reg = 0;
1.269 + asm("mcr p15, 0, reg, c7, c10, 4 ");
1.270 + }
1.271 +
1.272 +inline void arm_isb()
1.273 + {
1.274 + TUint32 reg = 0;
1.275 + asm("mcr p15, 0, reg, c7, c5, 4 ");
1.276 + }
1.277 +#endif
1.278 +#elif defined(__GNUC__) || defined(__GCC32__)
1.279 +#define mb() \
1.280 + do { \
1.281 + TUint32 reg = 0; \
1.282 + __asm__ __volatile__("mcr p15, 0, %0, c7, c10, 5" : : "r"(reg) : "memory"); \
1.283 + } while(0)
1.284 +
1.285 +#define arm_dsb() \
1.286 + do { \
1.287 + TUint32 reg = 0; \
1.288 + __asm__ __volatile__("mcr p15, 0, %0, c7, c10, 4" : : "r"(reg) : "memory"); \
1.289 + } while(0)
1.290 +
1.291 +#define arm_isb() \
1.292 + do { \
1.293 + TUint32 reg = 0; \
1.294 + __asm__ __volatile__("mcr p15, 0, %0, c7, c5, 4" : : "r"(reg) : "memory"); \
1.295 + } while(0)
1.296 +#else
1.297 +#error Unknown ARM compiler
1.298 +#endif
1.299 +
1.300 +#define smp_mb() mb()
1.301 +#define wmb() mb()
1.302 +#define smp_wmb() mb()
1.303 +
1.304 +#ifdef __IN_KERNEL__
1.305 +struct ArmScu;
1.306 +struct GicDistributor;
1.307 +struct GicCpuIfc;
1.308 +struct ArmLocalTimer;
1.309 +#define SCU (*(ArmScu*)TheScheduler.i_ScuAddr)
1.310 +#define GIC_DIST (*(GicDistributor*)TheScheduler.i_GicDistAddr)
1.311 +#define GIC_CPU_IFC (*(GicCpuIfc*)TheScheduler.i_GicCpuIfcAddr)
1.312 +#define LOCAL_TIMER (*(ArmLocalTimer*)TheScheduler.i_LocalTimerAddr)
1.313 +#endif
1.314 +
1.315 +
1.316 +// End of file
1.317 +#endif