/*++ BUILD Version: 0018 // Increment this if a change has global effects Copyright (c) 1993 IBM Corporation Module Name: ppc.h Abstract: This module contains the PowerPC hardware specific header file. Author: Rick Simpson 9-Jul-1993 Based on mips.h, by David N. Cutler (davec) 31-Mar-1990 Revision History: --*/ #ifndef _PPCH_ #define _PPCH_ // begin_ntddk begin_nthal begin_ntndis #if defined(_PPC_) // // Define maximum size of flush multple TB request. // #define FLUSH_MULTIPLE_MAXIMUM 48 // // Indicate that the compiler (with MIPS front-end) supports // the pragma textout construct. // #define ALLOC_PRAGMA 1 // // Define function decoration depending on whether a driver, a file system, // or a kernel component is being built. // #if defined(_NTDRIVER_) || defined(_NTDDK_) || defined(_NTIFS_) || defined(_NTHAL_) #define NTKERNELAPI DECLSPEC_IMPORT #else #define NTKERNELAPI #endif // // Define function decoration depending on whether the HAL or other kernel // component is being build. // #if !defined(_NTHAL_) #define NTHALAPI DECLSPEC_IMPORT #else #define NTHALAPI #endif // end_ntndis // // Define macro to generate import names. // #define IMPORT_NAME(name) __imp_##name // // PowerPC specific interlocked operation result values. // // These are the values used on MIPS; there appears to be no // need to change them for PowerPC. // #define RESULT_ZERO 0 #define RESULT_NEGATIVE -2 #define RESULT_POSITIVE -1 // // Interlocked result type is portable, but its values are machine specific. // Constants for value are in i386.h, mips.h, ppc.h, etc. // typedef enum _INTERLOCKED_RESULT { ResultNegative = RESULT_NEGATIVE, ResultZero = RESULT_ZERO, ResultPositive = RESULT_POSITIVE } INTERLOCKED_RESULT; // // Convert portable interlock interfaces to architecure specific interfaces. // #define ExInterlockedIncrementLong(Addend, Lock) \ ExPpcInterlockedIncrementLong(Addend) #define ExInterlockedDecrementLong(Addend, Lock) \ ExPpcInterlockedDecrementLong(Addend) #define ExInterlockedExchangeUlong(Target, Value, Lock) \ ExPpcInterlockedExchangeUlong(Target, Value) NTKERNELAPI INTERLOCKED_RESULT ExPpcInterlockedIncrementLong ( IN PLONG Addend ); NTKERNELAPI INTERLOCKED_RESULT ExPpcInterlockedDecrementLong ( IN PLONG Addend ); NTKERNELAPI LARGE_INTEGER ExInterlockedExchangeAddLargeInteger ( IN PLARGE_INTEGER Addend, IN LARGE_INTEGER Increment, IN PKSPIN_LOCK Lock ); NTKERNELAPI ULONG ExPpcInterlockedExchangeUlong ( IN PULONG Target, IN ULONG Value ); // // Intrinsic interlocked functions // #if defined(_M_PPC) && defined(_MSC_VER) && (_MSC_VER>=1000) && !defined(RC_INVOKED) #define InterlockedIncrement _InterlockedIncrement #define InterlockedDecrement _InterlockedDecrement #define InterlockedExchange _InterlockedExchange #define InterlockedExchangeAdd _InterlockedExchangeAdd #define InterlockedCompareExchange _InterlockedCompareExchange LONG InterlockedIncrement( IN OUT PLONG Addend ); LONG InterlockedDecrement( IN OUT PLONG Addend ); LONG InterlockedExchange( IN OUT PLONG Target, IN LONG Increment ); LONG InterlockedExchangeAdd( IN OUT PLONG Addend, IN LONG Value ); PVOID InterlockedCompareExchange ( IN OUT PVOID *Destination, IN PVOID Exchange, IN PVOID Comperand ); #pragma intrinsic(_InterlockedIncrement) #pragma intrinsic(_InterlockedDecrement) #pragma intrinsic(_InterlockedExchange) #pragma intrinsic(_InterlockedExchangeAdd) #pragma intrinsic(_InterlockedCompareExchange) #else NTKERNELAPI LONG InterlockedIncrement( IN OUT PLONG Addend ); NTKERNELAPI LONG InterlockedDecrement( IN OUT PLONG Addend ); NTKERNELAPI LONG InterlockedExchange( IN OUT PLONG Target, IN LONG Increment ); NTKERNELAPI LONG InterlockedExchangeAdd( IN OUT PLONG Addend, IN LONG Value ); NTKERNELAPI PVOID InterlockedCompareExchange ( IN OUT PVOID *Destination, IN PVOID Exchange, IN PVOID Comperand ); #endif // // PowerPC Interrupt Definitions. // // Define length of interupt object dispatch code in 32-bit words. // #define DISPATCH_LENGTH 4 // Length of dispatch code in instructions // // Define Interrupt Request Levels. // #define PASSIVE_LEVEL 0 // Passive release level #define LOW_LEVEL 0 // Lowest interrupt level #define APC_LEVEL 1 // APC interrupt level #define DISPATCH_LEVEL 2 // Dispatcher level #define PROFILE_LEVEL 27 // Profiling level #define IPI_LEVEL 29 // Interprocessor interrupt level #define POWER_LEVEL 30 // Power failure level #define FLOAT_LEVEL 31 // Floating interrupt level #define HIGH_LEVEL 31 // Highest interrupt level #define SYNCH_LEVEL DISPATCH_LEVEL // Synchronization level // // Define profile intervals. // // **FINISH** These are the MIPS R4000 values; investigate for PPC #define DEFAULT_PROFILE_COUNT 0x40000000 // ~= 20 seconds @50mhz #define DEFAULT_PROFILE_INTERVAL (10 * 500) // 500 microseconds #define MAXIMUM_PROFILE_INTERVAL (10 * 1000 * 1000) // 1 second #define MINIMUM_PROFILE_INTERVAL (10 * 40) // 40 microseconds // end_ntddk end_nthal #define KiSynchIrql SYNCH_LEVEL // enable portable code #define KiProfileIrql PROFILE_LEVEL // enable portable code // // Define machine specific external references. // // **FINISH** On MIPS, this is defined in ...\ntos\ke\mips\xxintsup.s // For PPC, ensure that there is a C-referencable label // on the list of instructions (the ordinary entry point // name won't be, because it will start with '.'). extern ULONG KiInterruptTemplate[]; // // Sanitize FPSCR and MSR based on processor mode. // By analogy with MIPS "Sanitize FSR" and "Sanitize PSR" // // General form: #define SANTIZE_(reg, mode) // ((mode) == KernelMode ? // ((0x00000000L) | ((reg) & 0xFFFFFFFF)) : // ((0x00000000L) | ((reg) & 0xFFFFFFFF))) // Where 0x00000000L represents bits that are forced on, and // 0xFFFFFFFF represents bits that are forced off. // // We will optimize this expression right here in the macro, because // the initial PPC compiler cannot be expected to do so itself. // // FPSCR -- Floating Point Status and Control Register // // We turn off the various exception enable bits so that loading // the FPSCR cannot cause an exception. // Force to 0: VE (24), OE (25), UE (26), ZE (27), XE (28) // Force to 1: -none- // Let caller specify: All others // **FINISH** -- Set this macro back to do something; leave as a no-op for now #define SANITIZE_FPSCR(fpscr, mode) (fpscr) //#define SANITIZE_FPSCR(fpscr, mode) (fpscr & 0xFFFFFF07L) // // MSR -- Machine State Register // // If kernel mode, then // Force to 0: reserved (0..12, 24, 28) // Force to 1: ILE (15), LE (31) // Let caller specify: // POW (13), implementation-dependent (14), // EE (16), PR (17), FP (18), ME (19), // FE0 (20), SE (21), BE (22), FE1 (23), // IP (25), IR (26), DR (27), PM (29), RI (30) // // If user mode, then // Force to 0: POW (13), implementation-dependent (14), IP (25), // reserved (0..12, 24, 28) // Force to 1: ILE (15), EE (16), PR (17), FPE (18), ME (19), // IR (26), DR (27), RI (30), LE (31) // Let caller specify: // FE0 (20), SE (21), BE (22), FE1 (23), PM (29) // #define SANITIZE_MSR(msr, mode) \ ((mode) == KernelMode ? \ ((0x00010001L) | ((msr) & 0x0007FF77L)) : \ ((0x0001F033L) | ((msr) & 0x0001FF37L))) // begin_ntddk begin_nthal // // Define length of interrupt vector table. // #define MAXIMUM_VECTOR 256 // // Processor Control Region // // On PowerPC, this cannot be at a fixed virtual address; // it must be at a different address on each processor of an MP. // #define PCR_MINOR_VERSION 1 #define PCR_MAJOR_VERSION 1 typedef struct _KPCR { // // Major and minor version numbers of the PCR. // USHORT MinorVersion; USHORT MajorVersion; // // Start of the architecturally defined section of the PCR. This section // may be directly addressed by vendor/platform specific HAL code and will // not change from version to version of NT. // // Interrupt and error exception vectors. // PKINTERRUPT_ROUTINE InterruptRoutine[MAXIMUM_VECTOR]; ULONG PcrPage2; ULONG Kseg0Top; ULONG Spare7[30]; // // First and second level cache parameters. // ULONG FirstLevelDcacheSize; ULONG FirstLevelDcacheFillSize; ULONG FirstLevelIcacheSize; ULONG FirstLevelIcacheFillSize; ULONG SecondLevelDcacheSize; ULONG SecondLevelDcacheFillSize; ULONG SecondLevelIcacheSize; ULONG SecondLevelIcacheFillSize; // // Pointer to processor control block. // struct _KPRCB *Prcb; // // Pointer to the thread environment block. A fast-path system call // is provided that will return this value to user-mode code. // PVOID Teb; // // Data cache alignment and fill size used for cache flushing and alignment. // These fields are set to the larger of the first and second level data // cache fill sizes. // ULONG DcacheAlignment; ULONG DcacheFillSize; // // Instruction cache alignment and fill size used for cache flushing and // alignment. These fields are set to the larger of the first and second // level data cache fill sizes. // ULONG IcacheAlignment; ULONG IcacheFillSize; // // Processor identification information from PVR. // ULONG ProcessorVersion; ULONG ProcessorRevision; // // Profiling data. // ULONG ProfileInterval; ULONG ProfileCount; // // Stall execution count and scale factor. // ULONG StallExecutionCount; ULONG StallScaleFactor; // // Spare cell. // ULONG Spare; // // Cache policy, right justified, as read from the processor configuration // register at startup. // union { ULONG CachePolicy; struct { UCHAR IcacheMode; // Dynamic cache mode for PPC UCHAR DcacheMode; // Dynamic cache mode for PPC USHORT ModeSpare; }; }; // // IRQL mapping tables. // UCHAR IrqlMask[32]; UCHAR IrqlTable[9]; // // Current IRQL. // UCHAR CurrentIrql; // // Processor identification // CCHAR Number; KAFFINITY SetMember; // // Reserved interrupt vector mask. // ULONG ReservedVectors; // // Current state parameters. // struct _KTHREAD *CurrentThread; // // Cache policy, PTE field aligned, as read from the processor configuration // register at startup. // ULONG AlignedCachePolicy; // // Flag for determining pending software interrupts // union { ULONG SoftwareInterrupt; // any bit 1 => some s/w interrupt pending struct { UCHAR ApcInterrupt; // 0x01 if APC int pending UCHAR DispatchInterrupt; // 0x01 if dispatch int pending UCHAR Spare4; UCHAR Spare5; }; }; // // Complement of the processor affinity mask. // KAFFINITY NotMember; // // Space reserved for the system. // ULONG SystemReserved[16]; // // Space reserved for the HAL // ULONG HalReserved[16]; // // End of the architecturally defined section of the PCR. This section // may be directly addressed by vendor/platform specific HAL code and will // not change from version to version of NT. // // end_ntddk end_nthal // // Start of the operating system release dependent section of the PCR. // This section may change from release to release and should not be // addressed by vendor/platform specific HAL code. // // Function active flags. // ULONG FirstLevelActive; // // System service dispatch start and end address used by get/set context. // ULONG SystemServiceDispatchStart; ULONG SystemServiceDispatchEnd; // // Interrupt stack. // ULONG InterruptStack; // // Quantum end flag. // ULONG QuantumEnd; // // Exception handler values. // PVOID InitialStack; PVOID PanicStack; ULONG BadVaddr; PVOID StackLimit; PVOID SavedStackLimit; ULONG SavedV0; ULONG SavedV1; UCHAR DebugActive; UCHAR Spare6[3]; // // Save area for 6 GPRs on interrupt other than Storage interrupt. // ULONG GprSave[6]; // // Save area for Instruction Storage and Data Storage interrupts. // ULONG SiR0; ULONG SiR2; ULONG SiR3; ULONG SiR4; ULONG SiR5; ULONG Spare0; ULONG Spare8; // // Real address of current process's Page Directory Page, // changed when process (address space) changes, // for use by Instruction Storage and Data Storage interrupts. // ULONG PgDirRa; // // On interrupt stack indicator and saved initial stack. // ULONG OnInterruptStack; ULONG SavedInitialStack; } KPCR, *PKPCR; // ntddk nthal // // The PCR address on a particular processor is contained in // SPRG 0 and 1. // SPRG 0 -- Real address of PCR (used only by interrupt code) // SPRG 1 -- Virtual address of PCR (used by kernel generally) // These SPRGs are not accessable to user-mode code. // // Get Pointer to Processor Control Region // // KiGetPcr() is a two-instruction routine that just reads SPRG 1 // into reg 3 and returns. Eventually this should be expanded in-line. KPCR * KiGetPcr(VOID); #define KIPCR2 0xffffe000 // kernel address of second PCR #define KI_USER_SHARED_DATA KIPCR2 #define SharedUserData ((KUSER_SHARED_DATA * const)KIPCR2) // begin_ntddk begin_nthal #define KIPCR 0xffffd000 // kernel address of first PCR #define PCR ((volatile KPCR * const)KIPCR) #if defined(_M_PPC) && defined(_MSC_VER) && (_MSC_VER>=1000) unsigned __sregister_get( unsigned const regnum ); #define _PPC_SPRG1_ 273 #define PCRsprg1 ((volatile KPCR * volatile)__sregister_get(_PPC_SPRG1_)) #else KPCR * __builtin_get_sprg1(VOID); #define PCRsprg1 ((volatile KPCR * volatile)__builtin_get_sprg1()) #endif // // Macros for enabling and disabling system interrupts. // //BUGBUG - work around 603e/ev errata #15 // The instructions __emit'ed in these macros are "cror 0,0,0" instructions // that force the mtmsr to complete before allowing any subsequent loads to // issue. The condition register no-op is executed in the system unit on // the 603. This will not dispatch until the mtmsr completes and will halt // further dispatch. On a 601 or 604 this instruction executes in the // branch unit and will run in parallel (i.e., no performance penalty except // for code bloat). // #if defined(_M_PPC) && defined(_MSC_VER) && (_MSC_VER>=1000) unsigned __sregister_get( unsigned const regnum ); void __sregister_set( unsigned const regnum, unsigned value ); #define _PPC_MSR_ (unsigned)(~0x0) #define _enable() (__sregister_set(_PPC_MSR_, __sregister_get(_PPC_MSR_) | 0x00008000), __emit(0x4C000382)) #define _disable() (__sregister_set(_PPC_MSR_, __sregister_get(_PPC_MSR_) & 0xffff7fff), __emit(0x4C000382)) #define __builtin_get_msr() __sregister_get(_PPC_MSR_) #else ULONG __builtin_get_msr(VOID); VOID __builtin_set_msr(ULONG); #define _enable() (__builtin_set_msr(__builtin_get_msr() | 0x00008000), __builtin_isync()) #define _disable() (__builtin_set_msr(__builtin_get_msr() & 0xffff7fff), __builtin_isync()) #endif // // Get current IRQL. // #define KeGetCurrentIrql() PCR->CurrentIrql // // Get address of current processor block. // #define KeGetCurrentPrcb() PCR->Prcb // // Get address of processor control region. // #define KeGetPcr() PCR // // Get address of current kernel thread object. // #define KeGetCurrentThread() PCR->CurrentThread // // Get Processor Version Register // #if defined(_M_PPC) && defined(_MSC_VER) && (_MSC_VER>=1000) unsigned __sregister_get( unsigned const regnum ); #define _PPC_PVR_ 287 #define KeGetPvr() __sregister_get(_PPC_PVR_) #else ULONG __builtin_get_pvr(VOID); #define KeGetPvr() __builtin_get_pvr() #endif // begin_ntddk // // Get current processor number. // #define KeGetCurrentProcessorNumber() PCR->Number // // Get data cache fill size. // // **FINISH** See that proper PowerPC parameter is accessed here #define KeGetDcacheFillSize() PCR->DcacheFillSize // end_ntddk end_nthal // // Get previous processor mode. // #define KeGetPreviousMode() (KPROCESSOR_MODE)PCR->CurrentThread->PreviousMode // // Test if executing a DPC. // BOOLEAN KeIsExecutingDpc ( VOID ); // // Save & Restore floating point state // #define KeSaveFloatingPointState(a) STATUS_SUCCESS #define KeRestoreFloatingPointState(a) STATUS_SUCCESS // begin_nthal // // Fill TB random entry // NTKERNELAPI VOID KeFillEntryTb ( IN HARDWARE_PTE Pte[2], IN PVOID Virtual, IN BOOLEAN Invalid ); // // Data cache, instruction cache, I/O buffer, and write buffer flush routine // prototypes. // NTKERNELAPI VOID KeChangeColorPage ( IN PVOID NewColor, IN PVOID OldColor, IN ULONG PageFrame ); NTKERNELAPI VOID KeSweepDcache ( IN BOOLEAN AllProcessors ); #define KeSweepCurrentDcache() \ HalSweepDcache(); NTKERNELAPI VOID KeSweepIcache ( IN BOOLEAN AllProcessors ); #define KeSweepCurrentIcache() \ HalSweepIcache(); \ HalSweepDcache(); NTKERNELAPI VOID KeSweepIcacheRange ( IN BOOLEAN AllProcessors, IN PVOID BaseAddress, IN ULONG Length ); // begin_ntddk begin_ntndis // // Cache and write buffer flush functions. // NTKERNELAPI VOID KeFlushIoBuffers ( IN PMDL Mdl, IN BOOLEAN ReadOperation, IN BOOLEAN DmaOperation ); // end_ntddk end_ntndis // // Clock, profile, and interprocessor interrupt functions. // struct _KEXCEPTION_FRAME; struct _KTRAP_FRAME; NTKERNELAPI VOID KeIpiInterrupt ( IN struct _KTRAP_FRAME *TrapFrame ); NTKERNELAPI VOID KeProfileInterrupt ( IN struct _KTRAP_FRAME *TrapFrame ); NTKERNELAPI VOID KeProfileInterruptWithSource ( IN struct _KTRAP_FRAME *TrapFrame, IN KPROFILE_SOURCE ProfileSource ); NTKERNELAPI VOID KeUpdateRunTime ( IN struct _KTRAP_FRAME *TrapFrame ); NTKERNELAPI VOID KeUpdateSystemTime ( IN struct _KTRAP_FRAME *TrapFrame, IN ULONG TimeIncrement ); // // Spin lock function prototypes (empty for uniprocessor). // Exported for use in MP HALs. // #if defined(NT_UP) #define KiAcquireSpinLock(SpinLock) #else NTKERNELAPI VOID KiAcquireSpinLock ( IN PKSPIN_LOCK SpinLock ); #endif #if defined(NT_UP) #define KiReleaseSpinLock(SpinLock) #else NTKERNELAPI VOID KiReleaseSpinLock ( IN PKSPIN_LOCK SpinLock ); #endif // end_nthal // // Define executive macros for acquiring and releasing executive spinlocks. // These macros can ONLY be used by executive components and NOT by drivers. // Drivers MUST use the kernel interfaces since they must be MP enabled on // all systems. // // On PPC, raise/lower IRQL are in the HAL, but KeRaiseIrqlToDpcLevel (raising to a // software level) is in the kernel. // // begin_ntddk begin_ntifs begin_nthal NTKERNELAPI KIRQL KfRaiseIrqlToDpcLevel ( VOID ); #define KeRaiseIrqlToDpcLevel(OldIrql) (*(OldIrql) = KfRaiseIrqlToDpcLevel()) NTKERNELAPI KIRQL KeRaiseIrqlToSynchLevel ( VOID ); // end_nthal #if defined(NT_UP) && !defined(_NTDDK_) && !defined(_NTIFS_) #define ExAcquireSpinLock(Lock, OldIrql) KeRaiseIrqlToDpcLevel((OldIrql)) #define ExReleaseSpinLock(Lock, OldIrql) KeLowerIrql((OldIrql)) #define ExAcquireSpinLockAtDpcLevel(Lock) #define ExReleaseSpinLockFromDpcLevel(Lock) #else #define ExAcquireSpinLock(Lock, OldIrql) KeAcquireSpinLock((Lock), (OldIrql)) #define ExReleaseSpinLock(Lock, OldIrql) KeReleaseSpinLock((Lock), (OldIrql)) #define ExAcquireSpinLockAtDpcLevel(Lock) KeAcquireSpinLockAtDpcLevel(Lock) #define ExReleaseSpinLockFromDpcLevel(Lock) KeReleaseSpinLockFromDpcLevel(Lock) #endif // end_ntddk end_ntifs // // The acquire and release fast lock macros disable and enable interrupts // on UP nondebug systems. On MP or debug systems, the spinlock routines // are used. // // N.B. Extreme caution should be observed when using these routines. // #if defined(NT_UP) && !DBG #define ExAcquireFastLock(Lock, OldIrql) _disable() #else #define ExAcquireFastLock(Lock, OldIrql) \ ExAcquireSpinLock(Lock, OldIrql) #endif #if defined(NT_UP) && !DBG #define ExReleaseFastLock(Lock, OldIrql) _enable() #else #define ExReleaseFastLock(Lock, OldIrql) \ ExReleaseSpinLock(Lock, OldIrql) #endif // // Define query system time macro. // #define KiQuerySystemTime(CurrentTime) \ do { \ (CurrentTime)->HighPart = SharedUserData->SystemTime.High1Time; \ (CurrentTime)->LowPart = SharedUserData->SystemTime.LowPart; \ } while ((CurrentTime)->HighPart != SharedUserData->SystemTime.High2Time) // // Define query tick count macro. // // begin_ntddk begin_nthal #if defined(_NTDRIVER_) || defined(_NTDDK_) || defined(_NTIFS_) #define KeQueryTickCount(CurrentCount) { \ PKSYSTEM_TIME _TickCount = *((PKSYSTEM_TIME *)(&KeTickCount)); \ do { \ (CurrentCount)->HighPart = _TickCount->High1Time; \ (CurrentCount)->LowPart = _TickCount->LowPart; \ } while ((CurrentCount)->HighPart != _TickCount->High2Time); \ } #else #define KiQueryTickCount(CurrentCount) \ do { \ (CurrentCount)->HighPart = KeTickCount.High1Time; \ (CurrentCount)->LowPart = KeTickCount.LowPart; \ } while ((CurrentCount)->HighPart != KeTickCount.High2Time) NTKERNELAPI VOID KeQueryTickCount ( OUT PLARGE_INTEGER CurrentCount ); #endif // end_ntddk end_nthal #define KiQueryLowTickCount() KeTickCount.LowPart // // Define query interrupt time macro. // #define KiQueryInterruptTime(CurrentTime) \ do { \ (CurrentTime)->HighPart = SharedUserData->InterruptTime.High1Time; \ (CurrentTime)->LowPart = SharedUserData->InterruptTime.LowPart; \ } while ((CurrentTime)->HighPart != SharedUserData->InterruptTime.High2Time) // // The following function prototypes must be in the module since they are // machine dependent. // // // Raise and lower IRQL // ULONG KiEmulateBranch ( IN struct _KEXCEPTION_FRAME *ExceptionFrame, IN struct _KTRAP_FRAME *TrapFrame ); BOOLEAN KiEmulateFloating ( IN OUT PEXCEPTION_RECORD ExceptionRecord, IN OUT struct _KEXCEPTION_FRAME *ExceptionFrame, IN OUT struct _KTRAP_FRAME *TrapFrame ); BOOLEAN KiEmulateReference ( IN OUT PEXCEPTION_RECORD ExceptionRecord, IN OUT struct _KEXCEPTION_FRAME *ExceptionFrame, IN OUT struct _KTRAP_FRAME *TrapFrame ); ULONG KiGetRegisterValue ( IN ULONG Register, IN struct _KEXCEPTION_FRAME *ExceptionFrame, IN struct _KTRAP_FRAME *TrapFrame ); VOID KiSetRegisterValue ( IN ULONG Register, IN ULONG Value, OUT struct _KEXCEPTION_FRAME *ExceptionFrame, OUT struct _KTRAP_FRAME *TrapFrame ); VOID KiRequestSoftwareInterrupt ( ULONG RequestIrql ); // begin_ntddk begin_nthal begin_ntndis // // I/O space read and write macros. // // **FINISH** Ensure that these are appropriate for PowerPC #define READ_REGISTER_UCHAR(x) \ *(volatile UCHAR * const)(x) #define READ_REGISTER_USHORT(x) \ *(volatile USHORT * const)(x) #define READ_REGISTER_ULONG(x) \ *(volatile ULONG * const)(x) #define READ_REGISTER_BUFFER_UCHAR(x, y, z) { \ PUCHAR registerBuffer = x; \ PUCHAR readBuffer = y; \ ULONG readCount; \ for (readCount = z; readCount--; readBuffer++, registerBuffer++) { \ *readBuffer = *(volatile UCHAR * const)(registerBuffer); \ } \ } #define READ_REGISTER_BUFFER_USHORT(x, y, z) { \ PUSHORT registerBuffer = x; \ PUSHORT readBuffer = y; \ ULONG readCount; \ for (readCount = z; readCount--; readBuffer++, registerBuffer++) { \ *readBuffer = *(volatile USHORT * const)(registerBuffer); \ } \ } #define READ_REGISTER_BUFFER_ULONG(x, y, z) { \ PULONG registerBuffer = x; \ PULONG readBuffer = y; \ ULONG readCount; \ for (readCount = z; readCount--; readBuffer++, registerBuffer++) { \ *readBuffer = *(volatile ULONG * const)(registerBuffer); \ } \ } #define WRITE_REGISTER_UCHAR(x, y) { \ *(volatile UCHAR * const)(x) = y; \ KeFlushWriteBuffer(); \ } #define WRITE_REGISTER_USHORT(x, y) { \ *(volatile USHORT * const)(x) = y; \ KeFlushWriteBuffer(); \ } #define WRITE_REGISTER_ULONG(x, y) { \ *(volatile ULONG * const)(x) = y; \ KeFlushWriteBuffer(); \ } #define WRITE_REGISTER_BUFFER_UCHAR(x, y, z) { \ PUCHAR registerBuffer = x; \ PUCHAR writeBuffer = y; \ ULONG writeCount; \ for (writeCount = z; writeCount--; writeBuffer++, registerBuffer++) { \ *(volatile UCHAR * const)(registerBuffer) = *writeBuffer; \ } \ KeFlushWriteBuffer(); \ } #define WRITE_REGISTER_BUFFER_USHORT(x, y, z) { \ PUSHORT registerBuffer = x; \ PUSHORT writeBuffer = y; \ ULONG writeCount; \ for (writeCount = z; writeCount--; writeBuffer++, registerBuffer++) { \ *(volatile USHORT * const)(registerBuffer) = *writeBuffer; \ } \ KeFlushWriteBuffer(); \ } #define WRITE_REGISTER_BUFFER_ULONG(x, y, z) { \ PULONG registerBuffer = x; \ PULONG writeBuffer = y; \ ULONG writeCount; \ for (writeCount = z; writeCount--; writeBuffer++, registerBuffer++) { \ *(volatile ULONG * const)(registerBuffer) = *writeBuffer; \ } \ KeFlushWriteBuffer(); \ } #define READ_PORT_UCHAR(x) \ *(volatile UCHAR * const)(x) #define READ_PORT_USHORT(x) \ *(volatile USHORT * const)(x) #define READ_PORT_ULONG(x) \ *(volatile ULONG * const)(x) #define READ_PORT_BUFFER_UCHAR(x, y, z) { \ PUCHAR readBuffer = y; \ ULONG readCount; \ for (readCount = 0; readCount < z; readCount++, readBuffer++) { \ *readBuffer = *(volatile UCHAR * const)(x); \ } \ } #define READ_PORT_BUFFER_USHORT(x, y, z) { \ PUSHORT readBuffer = y; \ ULONG readCount; \ for (readCount = 0; readCount < z; readCount++, readBuffer++) { \ *readBuffer = *(volatile USHORT * const)(x); \ } \ } #define READ_PORT_BUFFER_ULONG(x, y, z) { \ PULONG readBuffer = y; \ ULONG readCount; \ for (readCount = 0; readCount < z; readCount++, readBuffer++) { \ *readBuffer = *(volatile ULONG * const)(x); \ } \ } #define WRITE_PORT_UCHAR(x, y) { \ *(volatile UCHAR * const)(x) = y; \ KeFlushWriteBuffer(); \ } #define WRITE_PORT_USHORT(x, y) { \ *(volatile USHORT * const)(x) = y; \ KeFlushWriteBuffer(); \ } #define WRITE_PORT_ULONG(x, y) { \ *(volatile ULONG * const)(x) = y; \ KeFlushWriteBuffer(); \ } #define WRITE_PORT_BUFFER_UCHAR(x, y, z) { \ PUCHAR writeBuffer = y; \ ULONG writeCount; \ for (writeCount = 0; writeCount < z; writeCount++, writeBuffer++) { \ *(volatile UCHAR * const)(x) = *writeBuffer; \ KeFlushWriteBuffer(); \ } \ } #define WRITE_PORT_BUFFER_USHORT(x, y, z) { \ PUSHORT writeBuffer = y; \ ULONG writeCount; \ for (writeCount = 0; writeCount < z; writeCount++, writeBuffer++) { \ *(volatile USHORT * const)(x) = *writeBuffer; \ KeFlushWriteBuffer(); \ } \ } #define WRITE_PORT_BUFFER_ULONG(x, y, z) { \ PULONG writeBuffer = y; \ ULONG writeCount; \ for (writeCount = 0; writeCount < z; writeCount++, writeBuffer++) { \ *(volatile ULONG * const)(x) = *writeBuffer; \ KeFlushWriteBuffer(); \ } \ } // end_ntddk end_nthal end_ntndis // // Masks for Dr7 and sanitize macros for various debug registers. // #define DR6_LEGAL 0x0000e00f #define DR7_LEGAL 0xffff0155 #define DR7_ACTIVE 0x00000055 // If any of these bits are set a debug // register is active providing Dr6 // indicates DR available #define SANITIZE_DR6(Dr6, mode) ((Dr6 & DR6_LEGAL)); #define SANITIZE_DR7(Dr7, mode) ((Dr7 & DR7_LEGAL)); #define SANITIZE_DRADDR(DrReg, mode) ( \ (mode) == KernelMode ? \ (DrReg): \ (((PVOID)DrReg <= MM_HIGHEST_USER_ADDRESS) ? \ (DrReg): \ (0) \ ) \ ) // // Trap Frame -- Volatile state // // N.B. This frame must be a multiple of 8 bytes in length, as the // Stack Frame header (see ntppc.h), Trap Frame and Exception Frame // together must make up a valid call stack frame. // // CR fields 0, 1, 5..7 are volatile and appear here // CR fields 2..4 are non-volatile and appear in the Exception Frame #define CR_VOLATILE_FIELDS 0xFF000FFFL typedef struct _KTRAP_FRAME { PVOID TrapFrame; // previous trap frame address UCHAR OldIrql; UCHAR PreviousMode; UCHAR SavedApcStateIndex; UCHAR SavedKernelApcDisable; // Exception Record embedded in the Trap Frame, on 8-byte boundary, // padded to multiple of 8 bytes UCHAR ExceptionRecord[(sizeof(EXCEPTION_RECORD) + 7) & (~7)]; ULONG FILL2; // General registers 0 thru 12 ULONG Gpr0; ULONG Gpr1; ULONG Gpr2; ULONG Gpr3; ULONG Gpr4; ULONG Gpr5; ULONG Gpr6; ULONG Gpr7; ULONG Gpr8; ULONG Gpr9; ULONG Gpr10; ULONG Gpr11; ULONG Gpr12; // Floating point registers 0 thru 13 DOUBLE Fpr0; // 8-byte boundary required here DOUBLE Fpr1; DOUBLE Fpr2; DOUBLE Fpr3; DOUBLE Fpr4; DOUBLE Fpr5; DOUBLE Fpr6; DOUBLE Fpr7; DOUBLE Fpr8; DOUBLE Fpr9; DOUBLE Fpr10; DOUBLE Fpr11; DOUBLE Fpr12; DOUBLE Fpr13; // Floating Point Status and Control Register DOUBLE Fpscr; // Other volatile control registers ULONG Cr; // Only CR fields 0, 1, 5..7 are volatile, but the // entire CR is saved here on interrupt ULONG Xer; ULONG Msr; ULONG Iar; ULONG Lr; ULONG Ctr; // Debug Registers ULONG Dr0; ULONG Dr1; ULONG Dr2; ULONG Dr3; ULONG Dr4; ULONG Dr5; ULONG Dr6; ULONG Dr7; } KTRAP_FRAME, *PKTRAP_FRAME; #define KTRAP_FRAME_LENGTH ((sizeof(KTRAP_FRAME) + 7) & (~7)) #define KTRAP_FRAME_ALIGN (sizeof(DOUBLE)) #define KTRAP_FRAME_ROUND (KTRAP_FRAME_ALIGN - 1) // // The frame saved by KiCallUserMode is defined here to allow // the kernel debugger to trace the entire kernel stack // when usermode callouts are pending. // typedef struct _KCALLOUT_FRAME { STACK_FRAME_HEADER Frame; ULONG CbStk; // saved callback stack address ULONG TrFr; // saved callback trap frame address ULONG InStk; // saved initial stack address ULONG TrIar; // saved trap IAR ULONG TrToc; // saved trap TOC ULONG R3; // saved R3 (OutputBuffer) ULONG R4; // saved R4 (OutputLength) ULONG Lr; // saved LR ULONG Gpr[18]; // all nonvolatile GPRs DOUBLE Fpr[18]; // all nonvolatile FPRs } KCALLOUT_FRAME, *PKCALLOUT_FRAME; typedef struct _UCALLOUT_FRAME { STACK_FRAME_HEADER Frame; PVOID Buffer; ULONG Length; ULONG ApiNumber; ULONG Lr; ULONG Toc; ULONG Pad; } UCALLOUT_FRAME, *PUCALLOUT_FRAME; // // Exception frame -- NON-VOLATILE state // // This structure's layout matches that of the registers as saved // in a call/return stack frame, where the called program has saved // all the non-volatile registers. // // N.B. This frame must be a multiple of 8 bytes in length, as the // Stack Frame header (see ntppc.h), Trap Frame and the Exception // Frame together must make up a valid call stack frame. // typedef struct _KEXCEPTION_FRAME { ULONG Fill1; // padding ULONG Gpr13; ULONG Gpr14; ULONG Gpr15; ULONG Gpr16; ULONG Gpr17; ULONG Gpr18; ULONG Gpr19; ULONG Gpr20; ULONG Gpr21; ULONG Gpr22; ULONG Gpr23; ULONG Gpr24; ULONG Gpr25; ULONG Gpr26; ULONG Gpr27; ULONG Gpr28; ULONG Gpr29; ULONG Gpr30; ULONG Gpr31; DOUBLE Fpr14; // 8-byte boundary required here DOUBLE Fpr15; DOUBLE Fpr16; DOUBLE Fpr17; DOUBLE Fpr18; DOUBLE Fpr19; DOUBLE Fpr20; DOUBLE Fpr21; DOUBLE Fpr22; DOUBLE Fpr23; DOUBLE Fpr24; DOUBLE Fpr25; DOUBLE Fpr26; DOUBLE Fpr27; DOUBLE Fpr28; DOUBLE Fpr29; DOUBLE Fpr30; DOUBLE Fpr31; } KEXCEPTION_FRAME, *PKEXCEPTION_FRAME; // // Special version of exception frame for use by SwapContext and // KiInitializeContextThread. // typedef struct _KSWAP_FRAME { KEXCEPTION_FRAME ExceptionFrame; ULONG ConditionRegister; ULONG SwapReturn; } KSWAP_FRAME, *PKSWAP_FRAME; // // Non-volatile floating point state // typedef struct _KFLOATING_SAVE { ULONG Reserved; } KFLOATING_SAVE, *PKFLOATING_SAVE; // // Format of stack frame during exceptions. // #define STK_SLACK_SPACE 232 typedef struct _KEXCEPTION_STACK_FRAME { STACK_FRAME_HEADER Header; ULONG AdditionalParameters[8]; KTRAP_FRAME TrapFrame; KEXCEPTION_FRAME ExceptionFrame; PVOID Lr; PVOID Cr; UCHAR SlackSpace[STK_SLACK_SPACE]; } KEXCEPTION_STACK_FRAME, *PKEXCEPTION_STACK_FRAME; // begin_nthal // begin_windbgkd #ifdef _PPC_ // // Special Registers for PowerPC // typedef struct _KSPECIAL_REGISTERS { ULONG KernelDr0; ULONG KernelDr1; ULONG KernelDr2; ULONG KernelDr3; ULONG KernelDr4; ULONG KernelDr5; ULONG KernelDr6; ULONG KernelDr7; ULONG Sprg0; ULONG Sprg1; ULONG Sr0; ULONG Sr1; ULONG Sr2; ULONG Sr3; ULONG Sr4; ULONG Sr5; ULONG Sr6; ULONG Sr7; ULONG Sr8; ULONG Sr9; ULONG Sr10; ULONG Sr11; ULONG Sr12; ULONG Sr13; ULONG Sr14; ULONG Sr15; ULONG DBAT0L; ULONG DBAT0U; ULONG DBAT1L; ULONG DBAT1U; ULONG DBAT2L; ULONG DBAT2U; ULONG DBAT3L; ULONG DBAT3U; ULONG IBAT0L; ULONG IBAT0U; ULONG IBAT1L; ULONG IBAT1U; ULONG IBAT2L; ULONG IBAT2U; ULONG IBAT3L; ULONG IBAT3U; ULONG Sdr1; ULONG Reserved[9]; } KSPECIAL_REGISTERS, *PKSPECIAL_REGISTERS; // // Processor State structure. // typedef struct _KPROCESSOR_STATE { struct _CONTEXT ContextFrame; struct _KSPECIAL_REGISTERS SpecialRegisters; } KPROCESSOR_STATE, *PKPROCESSOR_STATE; #endif // _PPC_ // end_windbgkd // // Processor Control Block (PRCB) // #define PRCB_MINOR_VERSION 1 #define PRCB_MAJOR_VERSION 1 #define PRCB_BUILD_DEBUG 0x0001 #define PRCB_BUILD_UNIPROCESSOR 0x0002 struct _RESTART_BLOCK; typedef struct _KPRCB { // // Major and minor version numbers of the PCR. // USHORT MinorVersion; USHORT MajorVersion; // // Start of the architecturally defined section of the PRCB. This section // may be directly addressed by vendor/platform specific HAL code and will // not change from version to version of NT. // struct _KTHREAD *CurrentThread; struct _KTHREAD *RESTRICTED_POINTER NextThread; struct _KTHREAD *IdleThread; CCHAR Number; CCHAR Reserved; USHORT BuildType; KAFFINITY SetMember; struct _RESTART_BLOCK *RestartBlock; ULONG PcrPage; ULONG PcrPage2; // // Space reserved for the system. // ULONG SystemReserved[15]; // // Space reserved for the HAL. // ULONG HalReserved[16]; // End of the architecturally defined section of the PRCB. // end_nthal // ULONG DpcTime; ULONG InterruptTime; ULONG KernelTime; ULONG UserTime; ULONG AdjustDpcThreshold; ULONG InterruptCount; ULONG ApcBypassCount; ULONG DpcBypassCount; ULONG Spare6[5]; // // MP information. // PVOID Spare1; PVOID Spare2; volatile ULONG IpiFrozen; struct _KPROCESSOR_STATE ProcessorState; // // Per-processor data for various hot code which resides in the // kernel image. Each processor is given its own copy of the data // to lessen the cache impact of sharing the data between multiple // processors. // // // File system runtime variables. // SINGLE_LIST_ENTRY FsRtlFreeSharedLockList; SINGLE_LIST_ENTRY FsRtlFreeExclusiveLockList; // // Cache manager performance counters. // ULONG CcFastReadNoWait; ULONG CcFastReadWait; ULONG CcFastReadNotPossible; ULONG CcCopyReadNoWait; ULONG CcCopyReadWait; ULONG CcCopyReadNoWaitMiss; // // Kernel performance counters. // ULONG KeAlignmentFixupCount; ULONG KeContextSwitches; ULONG KeDcacheFlushCount; ULONG KeExceptionDispatchCount; ULONG KeFirstLevelTbFills; ULONG KeFloatingEmulationCount; ULONG KeIcacheFlushCount; ULONG KeSecondLevelTbFills; ULONG KeSystemCalls; ULONG PagedPoolLookasideHits; // // More filesystem runtime // SINGLE_LIST_ENTRY FsRtlFreeWaitingLockList; SINGLE_LIST_ENTRY FsRtlFreeLockTreeNodeList; // // Reserved for future counters. // ULONG ReservedCounter[12]; // // Reserved pad. // union { ULONG ReservedPad[16 * 8]; PVOID PagedFreeEntry[POOL_SMALL_LISTS]; }; // // MP interprocessor request packet and summary. // // N.B. This is carefully aligned to be on a cache line boundary. // volatile PVOID CurrentPacket[3]; volatile KAFFINITY TargetSet; volatile PKIPI_WORKER WorkerRoutine; ULONG CachePad1[3]; // // N.B. These two longwords must be on a quadword boundary and adjacent. // volatile ULONG RequestSummary; volatile struct _KPRCB *SignalDone; ULONG CachePad2[6]; // // DPC interrupt requested. // ULONG DpcInterruptRequested; ULONG CachePad3[7]; // // DPC batching parameters. // ULONG MaximumDpcQueueDepth; ULONG MinimumDpcRate; // // Spare counters. // ULONG Spare4[2]; // // I/O system per processor single entry lookaside lists. // PVOID SmallIrpFreeEntry; PVOID LargeIrpFreeEntry; PVOID MdlFreeEntry; // // Object manager per processor single entry lookaside lists. // PVOID CreateInfoFreeEntry; PVOID NameBufferFreeEntry; // // Cache manager per processor single entry lookaside lists. // PVOID SharedCacheMapEntry; // // Spares. // ULONG Spare5[2]; // // Address of MP interprocessor operation counters. // PKIPI_COUNTS IpiCounts; LARGE_INTEGER StartCount; // // DPC list head, spinlock, and count. // KSPIN_LOCK DpcLock; LIST_ENTRY DpcListHead; ULONG DpcQueueDepth; ULONG DpcCount; ULONG DpcLastCount; ULONG DpcRequestRate; ULONG DpcRoutineActive; BOOLEAN SkipTick; ULONG CachePad4[5]; } KPRCB, *PKPRCB, *RESTRICTED_POINTER PRKPRCB; // nthal // begin_ntddk begin_nthal begin_ntndis // // PowerPC page size = 4 KB // #define PAGE_SIZE (ULONG)0x1000 // // Define the number of trailing zeroes in a page aligned virtual address. // This is used as the shift count when shifting virtual addresses to // virtual page numbers. // #define PAGE_SHIFT 12L // end_ntddk end_ntndis // // Define the number of bits to shift to right justify the Page Directory Index // field of a PTE. // #define PDI_SHIFT 22 // // Define the number of bits to shift to right justify the Page Table Index // field of a PTE. // #define PTI_SHIFT 12 // begin_ntddk // // The highest user address reserves 64K bytes for a guard page. This // the probing of address from kernel mode to only have to check the // starting address for structures of 64k bytes or less. // #define MM_HIGHEST_USER_ADDRESS (PVOID)0x7FFEFFFF // highest user address #define MM_USER_PROBE_ADDRESS 0x7FFF0000 // starting address of guard page // // The lowest user address reserves the low 64k. // #define MM_LOWEST_USER_ADDRESS (PVOID)0x00010000 #define MmGetProcedureAddress(Address) *((PVOID *)(Address)) #define MmLockPagableCodeSection(Address) MmLockPagableDataSection(*((PVOID *)(Address))) // end_ntddk // // Define the page table and the page directory base for // memory management. // #define PDE_BASE (ULONG)0xC0300000 #define PTE_BASE (ULONG)0xC0000000 // begin_ntddk // // The lowest address for system space. // #define MM_LOWEST_SYSTEM_ADDRESS (PVOID)0x80000000 #define SYSTEM_BASE 0x80000000 // start of system space (no typecast) // begin_ntndis #endif // defined(_PPC_) // end_ntddk end_nthal end_ntndis // Special comment moved for hal.h since mips.h defines UNCACHED_POLICY // in unconditional code which is placed in the hal header file. // // Define uncache policies. // // **FINISH** Check that these values are even needed for PPC. // #define UNCACHED_POLICY 2 // uncached // // Registers visible only to the operating system // // // Define Data Storage Interrupt Status Register (DSISR) // typedef struct _DSISR { ULONG UpdateReg : 5; // RA field for update-form instrs ULONG DataReg : 5; // RA, RS, FRA, or FRT field of instr ULONG Index : 7; // Index into table to distinguish instrs ULONG Fill2 : 1; ULONG XO : 2; // Extended op-code for DS-form instrs ULONG Fill1 : 12; } DSISR, *PDSISR; DSISR KiGetDsisr (); // Function to read the DSISR void KiSetDsisr (DSISR Value); // Function to write the DSISR // // PowerPC function definitions // //++ // // BOOLEAN // KiIsThreadNumericStateSaved( // IN PKTHREAD Address // ) // // This call is used on a not running thread to see if its numeric // state has been saved in its context information. // // **FINISH** PowerPC is eventually to use lazy FP state-save, // but for now we'll always save the FP state. // //-- #define KiIsThreadNumericStateSaved(a) TRUE //++ // // VOID // KiRundownThread( // IN PKTHREAD Address // ) // //-- #define KiRundownThread(a) // // Define macro to test if x86 feature is present. // // N.B. All x86 features test TRUE on PPC systems. // #define Isx86FeaturePresent(_f_) TRUE // // Symbolic values for exception entry // #define ppc_machine_check 1 #define ppc_data_storage 2 #define ppc_instruction_storage 3 #define ppc_external 4 #define ppc_alignment 5 #define ppc_program 6 #define ppc_fp_unavailable 7 #define ppc_decrementer 8 #define ppc_direct_store_error 9 #define ppc_syscall 10 #define ppc_trace 11 #define ppc_fp_assist 12 #define ppc_run_mode 13 #endif // _PPCH_