Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3004 lines
64 KiB

  1. /*++ BUILD Version: 0014 // Increment this if a change has global effects
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. i386.h
  5. Abstract:
  6. This module contains the i386 hardware specific header file.
  7. Author:
  8. David N. Cutler (davec) 2-Aug-1989
  9. Revision History:
  10. 25-Jan-1990 shielint
  11. Added definitions for 8259 ports and commands and
  12. macros for 8259 irq# and system irql conversion.
  13. --*/
  14. #ifndef _i386_
  15. #define _i386_
  16. // begin_ntddk begin_wdm begin_nthal begin_ntndis begin_ntosp
  17. #if defined(_X86_)
  18. //
  19. // Types to use to contain PFNs and their counts.
  20. //
  21. typedef ULONG PFN_COUNT;
  22. typedef LONG SPFN_NUMBER, *PSPFN_NUMBER;
  23. typedef ULONG PFN_NUMBER, *PPFN_NUMBER;
  24. //
  25. // Define maximum size of flush multiple TB request.
  26. //
  27. #define FLUSH_MULTIPLE_MAXIMUM 16
  28. //
  29. // Indicate that the i386 compiler supports the pragma textout construct.
  30. //
  31. #define ALLOC_PRAGMA 1
  32. //
  33. // Indicate that the i386 compiler supports the DATA_SEG("INIT") and
  34. // DATA_SEG("PAGE") pragmas
  35. //
  36. #define ALLOC_DATA_PRAGMA 1
  37. // end_ntddk end_nthal end_ntndis end_wdm end_ntosp
  38. // NOTE - KiPcr is only useful for PCR references where we know we
  39. // won't get context switched between the call to it and the
  40. // variable reference, OR, were we don't care, (ie TEB pointer)
  41. // NOTE - bryanwi 11 june 90 - we must not macro out things we export
  42. // Things like KeFlushIcache and KeFlushDcache cannot be macroed
  43. // out because external code (like drivers) will want to import
  44. // them by name. Therefore, the defines below that turn them into
  45. // nothing are inappropriate. But this isn't going to hurt us right
  46. // now.
  47. //
  48. // Length on interrupt object dispatch code in longwords.
  49. // (shielint) Reserve 9*4 space for ABIOS stack mapping. If NO
  50. // ABIOS support the size of DISPATCH_LENGTH should be 74.
  51. //
  52. // begin_nthal
  53. #define NORMAL_DISPATCH_LENGTH 106 // ntddk wdm
  54. #define DISPATCH_LENGTH NORMAL_DISPATCH_LENGTH // ntddk wdm
  55. //
  56. // Define constants to access the bits in CR0.
  57. //
  58. #define CR0_PG 0x80000000 // paging
  59. #define CR0_ET 0x00000010 // extension type (80387)
  60. #define CR0_TS 0x00000008 // task switched
  61. #define CR0_EM 0x00000004 // emulate math coprocessor
  62. #define CR0_MP 0x00000002 // math present
  63. #define CR0_PE 0x00000001 // protection enable
  64. //
  65. // More CR0 bits; these only apply to the 80486.
  66. //
  67. #define CR0_CD 0x40000000 // cache disable
  68. #define CR0_NW 0x20000000 // not write-through
  69. #define CR0_AM 0x00040000 // alignment mask
  70. #define CR0_WP 0x00010000 // write protect
  71. #define CR0_NE 0x00000020 // numeric error
  72. //
  73. // CR4 bits; These only apply to Pentium
  74. //
  75. #define CR4_VME 0x00000001 // V86 mode extensions
  76. #define CR4_PVI 0x00000002 // Protected mode virtual interrupts
  77. #define CR4_TSD 0x00000004 // Time stamp disable
  78. #define CR4_DE 0x00000008 // Debugging Extensions
  79. #define CR4_PSE 0x00000010 // Page size extensions
  80. #define CR4_PAE 0x00000020 // Physical address extensions
  81. #define CR4_MCE 0x00000040 // Machine check enable
  82. #define CR4_PGE 0x00000080 // Page global enable
  83. #define CR4_FXSR 0x00000200 // FXSR used by OS
  84. #define CR4_XMMEXCPT 0x00000400 // XMMI used by OS
  85. // end_nthal
  86. //
  87. // Define constants to access ThNpxState
  88. //
  89. #define NPX_STATE_NOT_LOADED (CR0_TS | CR0_MP)
  90. #define NPX_STATE_LOADED 0
  91. //
  92. // External references to the labels defined in int.asm
  93. //
  94. extern ULONG KiInterruptTemplate[NORMAL_DISPATCH_LENGTH];
  95. extern PULONG KiInterruptTemplateObject;
  96. extern PULONG KiInterruptTemplateDispatch;
  97. extern PULONG KiInterruptTemplate2ndDispatch;
  98. // begin_ntddk begin_wdm begin_nthal begin_ntosp
  99. //
  100. // Interrupt Request Level definitions
  101. //
  102. #define PASSIVE_LEVEL 0 // Passive release level
  103. #define LOW_LEVEL 0 // Lowest interrupt level
  104. #define APC_LEVEL 1 // APC interrupt level
  105. #define DISPATCH_LEVEL 2 // Dispatcher level
  106. #define PROFILE_LEVEL 27 // timer used for profiling.
  107. #define CLOCK1_LEVEL 28 // Interval clock 1 level - Not used on x86
  108. #define CLOCK2_LEVEL 28 // Interval clock 2 level
  109. #define IPI_LEVEL 29 // Interprocessor interrupt level
  110. #define POWER_LEVEL 30 // Power failure level
  111. #define HIGH_LEVEL 31 // Highest interrupt level
  112. #if defined(NT_UP)
  113. #define SYNCH_LEVEL DISPATCH_LEVEL // synchronization level - UP system
  114. #else
  115. #define SYNCH_LEVEL (IPI_LEVEL-1) // synchronization level - MP system
  116. #endif
  117. // end_ntddk end_wdm end_ntosp
  118. #define KiSynchIrql SYNCH_LEVEL // enable portable code
  119. //
  120. // Machine type definitions
  121. //
  122. #define MACHINE_TYPE_ISA 0
  123. #define MACHINE_TYPE_EISA 1
  124. #define MACHINE_TYPE_MCA 2
  125. // end_nthal
  126. //
  127. // The previous values are or'ed into KeI386MachineType.
  128. //
  129. extern ULONG KeI386MachineType;
  130. // begin_nthal
  131. //
  132. // Define constants used in selector tests.
  133. //
  134. // RPL_MASK is the real value for extracting RPL values. IT IS THE WRONG
  135. // CONSTANT TO USE FOR MODE TESTING.
  136. //
  137. // MODE_MASK is the value for deciding the current mode.
  138. // WARNING: MODE_MASK assumes that all code runs at either ring-0
  139. // or ring-3. Ring-1 or Ring-2 support will require changing
  140. // this value and all of the code that refers to it.
  141. #define MODE_MASK 1 // ntosp
  142. #define RPL_MASK 3
  143. //
  144. // SEGMENT_MASK is used to throw away trash part of segment. Part always
  145. // pushes or pops 32 bits to/from stack, but if it's a segment value,
  146. // high order 16 bits are trash.
  147. //
  148. #define SEGMENT_MASK 0xffff
  149. //
  150. // Startup count value for KeStallExecution. This value is used
  151. // until KiInitializeStallExecution can compute the real one.
  152. // Pick a value long enough for very fast processors.
  153. //
  154. #define INITIAL_STALL_COUNT 100
  155. // end_nthal
  156. //
  157. // begin_nthal
  158. //
  159. // Macro to extract the high word of a long offset
  160. //
  161. #define HIGHWORD(l) \
  162. ((USHORT)(((ULONG)(l)>>16) & 0xffff))
  163. //
  164. // Macro to extract the low word of a long offset
  165. //
  166. #define LOWWORD(l) \
  167. ((USHORT)((ULONG)l & 0x0000ffff))
  168. //
  169. // Macro to combine two USHORT offsets into a long offset
  170. //
  171. #if !defined(MAKEULONG)
  172. #define MAKEULONG(x, y) \
  173. (((((ULONG)(x))<<16) & 0xffff0000) | \
  174. ((ULONG)(y) & 0xffff))
  175. #endif
  176. // end_nthal
  177. //
  178. // Request a software interrupt.
  179. //
  180. #define KiRequestSoftwareInterrupt(RequestIrql) \
  181. HalRequestSoftwareInterrupt( RequestIrql )
  182. // begin_ntddk begin_wdm begin_nthal begin_ntndis begin_ntosp
  183. //
  184. // I/O space read and write macros.
  185. //
  186. // These have to be actual functions on the 386, because we need
  187. // to use assembler, but cannot return a value if we inline it.
  188. //
  189. // The READ/WRITE_REGISTER_* calls manipulate I/O registers in MEMORY space.
  190. // (Use x86 move instructions, with LOCK prefix to force correct behavior
  191. // w.r.t. caches and write buffers.)
  192. //
  193. // The READ/WRITE_PORT_* calls manipulate I/O registers in PORT space.
  194. // (Use x86 in/out instructions.)
  195. //
  196. NTKERNELAPI
  197. UCHAR
  198. NTAPI
  199. READ_REGISTER_UCHAR(
  200. PUCHAR Register
  201. );
  202. NTKERNELAPI
  203. USHORT
  204. NTAPI
  205. READ_REGISTER_USHORT(
  206. PUSHORT Register
  207. );
  208. NTKERNELAPI
  209. ULONG
  210. NTAPI
  211. READ_REGISTER_ULONG(
  212. PULONG Register
  213. );
  214. NTKERNELAPI
  215. VOID
  216. NTAPI
  217. READ_REGISTER_BUFFER_UCHAR(
  218. PUCHAR Register,
  219. PUCHAR Buffer,
  220. ULONG Count
  221. );
  222. NTKERNELAPI
  223. VOID
  224. NTAPI
  225. READ_REGISTER_BUFFER_USHORT(
  226. PUSHORT Register,
  227. PUSHORT Buffer,
  228. ULONG Count
  229. );
  230. NTKERNELAPI
  231. VOID
  232. NTAPI
  233. READ_REGISTER_BUFFER_ULONG(
  234. PULONG Register,
  235. PULONG Buffer,
  236. ULONG Count
  237. );
  238. NTKERNELAPI
  239. VOID
  240. NTAPI
  241. WRITE_REGISTER_UCHAR(
  242. PUCHAR Register,
  243. UCHAR Value
  244. );
  245. NTKERNELAPI
  246. VOID
  247. NTAPI
  248. WRITE_REGISTER_USHORT(
  249. PUSHORT Register,
  250. USHORT Value
  251. );
  252. NTKERNELAPI
  253. VOID
  254. NTAPI
  255. WRITE_REGISTER_ULONG(
  256. PULONG Register,
  257. ULONG Value
  258. );
  259. NTKERNELAPI
  260. VOID
  261. NTAPI
  262. WRITE_REGISTER_BUFFER_UCHAR(
  263. PUCHAR Register,
  264. PUCHAR Buffer,
  265. ULONG Count
  266. );
  267. NTKERNELAPI
  268. VOID
  269. NTAPI
  270. WRITE_REGISTER_BUFFER_USHORT(
  271. PUSHORT Register,
  272. PUSHORT Buffer,
  273. ULONG Count
  274. );
  275. NTKERNELAPI
  276. VOID
  277. NTAPI
  278. WRITE_REGISTER_BUFFER_ULONG(
  279. PULONG Register,
  280. PULONG Buffer,
  281. ULONG Count
  282. );
  283. NTHALAPI
  284. UCHAR
  285. NTAPI
  286. READ_PORT_UCHAR(
  287. PUCHAR Port
  288. );
  289. NTHALAPI
  290. USHORT
  291. NTAPI
  292. READ_PORT_USHORT(
  293. PUSHORT Port
  294. );
  295. NTHALAPI
  296. ULONG
  297. NTAPI
  298. READ_PORT_ULONG(
  299. PULONG Port
  300. );
  301. NTHALAPI
  302. VOID
  303. NTAPI
  304. READ_PORT_BUFFER_UCHAR(
  305. PUCHAR Port,
  306. PUCHAR Buffer,
  307. ULONG Count
  308. );
  309. NTHALAPI
  310. VOID
  311. NTAPI
  312. READ_PORT_BUFFER_USHORT(
  313. PUSHORT Port,
  314. PUSHORT Buffer,
  315. ULONG Count
  316. );
  317. NTHALAPI
  318. VOID
  319. NTAPI
  320. READ_PORT_BUFFER_ULONG(
  321. PULONG Port,
  322. PULONG Buffer,
  323. ULONG Count
  324. );
  325. NTHALAPI
  326. VOID
  327. NTAPI
  328. WRITE_PORT_UCHAR(
  329. PUCHAR Port,
  330. UCHAR Value
  331. );
  332. NTHALAPI
  333. VOID
  334. NTAPI
  335. WRITE_PORT_USHORT(
  336. PUSHORT Port,
  337. USHORT Value
  338. );
  339. NTHALAPI
  340. VOID
  341. NTAPI
  342. WRITE_PORT_ULONG(
  343. PULONG Port,
  344. ULONG Value
  345. );
  346. NTHALAPI
  347. VOID
  348. NTAPI
  349. WRITE_PORT_BUFFER_UCHAR(
  350. PUCHAR Port,
  351. PUCHAR Buffer,
  352. ULONG Count
  353. );
  354. NTHALAPI
  355. VOID
  356. NTAPI
  357. WRITE_PORT_BUFFER_USHORT(
  358. PUSHORT Port,
  359. PUSHORT Buffer,
  360. ULONG Count
  361. );
  362. NTHALAPI
  363. VOID
  364. NTAPI
  365. WRITE_PORT_BUFFER_ULONG(
  366. PULONG Port,
  367. PULONG Buffer,
  368. ULONG Count
  369. );
  370. // end_ntndis
  371. //
  372. // Get data cache fill size.
  373. //
  374. #if PRAGMA_DEPRECATED_DDK
  375. #pragma deprecated(KeGetDcacheFillSize) // Use GetDmaAlignment
  376. #endif
  377. #define KeGetDcacheFillSize() 1L
  378. // end_ntddk end_wdm end_nthal end_ntosp
  379. //
  380. // Fill TB entry.
  381. //
  382. #define KeFillEntryTb(Pte, Virtual, Invalid) \
  383. if (Invalid != FALSE) { \
  384. Ke386InvalidateTb (Virtual); \
  385. }
  386. #if !defined(MIDL_PASS) && defined(_M_IX86) && !defined(_CROSS_PLATFORM_)
  387. FORCEINLINE
  388. VOID
  389. NTAPI
  390. Ke386InvalidateTb (
  391. IN PVOID Virtual
  392. )
  393. {
  394. __asm {
  395. mov eax, Virtual
  396. invlpg [eax]
  397. }
  398. }
  399. #endif
  400. NTKERNELAPI // nthal
  401. VOID // nthal
  402. KeFlushCurrentTb ( // nthal
  403. VOID // nthal
  404. ); // nthal
  405. // nthal
  406. //
  407. // Data cache, instruction cache, I/O buffer, and write buffer flush routine
  408. // prototypes.
  409. //
  410. // 386 and 486 have transparent caches, so these are noops.
  411. #define KeSweepDcache(AllProcessors)
  412. #define KeSweepCurrentDcache()
  413. #define KeSweepIcache(AllProcessors)
  414. #define KeSweepCurrentIcache()
  415. #define KeSweepIcacheRange(AllProcessors, BaseAddress, Length)
  416. // begin_ntddk begin_wdm begin_nthal begin_ntndis begin_ntosp
  417. #define KeFlushIoBuffers(Mdl, ReadOperation, DmaOperation)
  418. // end_ntddk end_wdm end_ntndis end_ntosp
  419. #define KeYieldProcessor() __asm { rep nop }
  420. // end_nthal
  421. //
  422. // Define executive macros for acquiring and releasing executive spinlocks.
  423. // These macros can ONLY be used by executive components and NOT by drivers.
  424. // Drivers MUST use the kernel interfaces since they must be MP enabled on
  425. // all systems.
  426. //
  427. // KeRaiseIrql is one instruction longer than KeAcquireSpinLock on x86 UP.
  428. // KeLowerIrql and KeReleaseSpinLock are the same.
  429. //
  430. #if defined(NT_UP) && !DBG && !defined(_NTDDK_) && !defined(_NTIFS_)
  431. #if !defined(_NTDRIVER_)
  432. #define ExAcquireSpinLock(Lock, OldIrql) (*OldIrql) = KeRaiseIrqlToDpcLevel();
  433. #define ExReleaseSpinLock(Lock, OldIrql) KeLowerIrql((OldIrql))
  434. #else
  435. #define ExAcquireSpinLock(Lock, OldIrql) KeAcquireSpinLock((Lock), (OldIrql))
  436. #define ExReleaseSpinLock(Lock, OldIrql) KeReleaseSpinLock((Lock), (OldIrql))
  437. #endif
  438. #define ExAcquireSpinLockAtDpcLevel(Lock)
  439. #define ExReleaseSpinLockFromDpcLevel(Lock)
  440. #else
  441. // begin_wdm begin_ntddk begin_ntosp
  442. #define ExAcquireSpinLock(Lock, OldIrql) KeAcquireSpinLock((Lock), (OldIrql))
  443. #define ExReleaseSpinLock(Lock, OldIrql) KeReleaseSpinLock((Lock), (OldIrql))
  444. #define ExAcquireSpinLockAtDpcLevel(Lock) KeAcquireSpinLockAtDpcLevel(Lock)
  445. #define ExReleaseSpinLockFromDpcLevel(Lock) KeReleaseSpinLockFromDpcLevel(Lock)
  446. // end_wdm end_ntddk end_ntosp
  447. #endif
  448. //
  449. // The acquire and release fast lock macros disable and enable interrupts
  450. // on UP nondebug systems. On MP or debug systems, the spinlock routines
  451. // are used.
  452. //
  453. // N.B. Extreme caution should be observed when using these routines.
  454. //
  455. #if defined(_M_IX86) && !defined(USER_MODE_CODE)
  456. #pragma warning(disable:4164)
  457. #pragma intrinsic(_disable)
  458. #pragma intrinsic(_enable)
  459. #pragma warning(default:4164)
  460. #endif
  461. #if defined(NT_UP) && !DBG && !defined(USER_MODE_CODE)
  462. #define ExAcquireFastLock(Lock, OldIrql) _disable()
  463. #else
  464. #define ExAcquireFastLock(Lock, OldIrql) \
  465. ExAcquireSpinLock(Lock, OldIrql)
  466. #endif
  467. #if defined(NT_UP) && !DBG && !defined(USER_MODE_CODE)
  468. #define ExReleaseFastLock(Lock, OldIrql) _enable()
  469. #else
  470. #define ExReleaseFastLock(Lock, OldIrql) \
  471. ExReleaseSpinLock(Lock, OldIrql)
  472. #endif
  473. //
  474. // The following function prototypes must be in this module so that the
  475. // above macros can call them directly.
  476. //
  477. // begin_nthal
  478. VOID
  479. FASTCALL
  480. KiAcquireSpinLock (
  481. IN PKSPIN_LOCK SpinLock
  482. );
  483. VOID
  484. FASTCALL
  485. KiReleaseSpinLock (
  486. IN PKSPIN_LOCK SpinLock
  487. );
  488. // end_nthal
  489. //
  490. // KeTestSpinLock may be used to spin at low IRQL until the lock is
  491. // available. The IRQL must then be raised and the lock acquired with
  492. // KeTryToAcquireSpinLock. If that fails, lower the IRQL and start again.
  493. //
  494. #if defined(NT_UP)
  495. #define KeTestSpinLock(SpinLock) (TRUE)
  496. #else
  497. BOOLEAN
  498. FASTCALL
  499. KeTestSpinLock (
  500. IN PKSPIN_LOCK SpinLock
  501. );
  502. #endif
  503. //
  504. // Define query tick count macro.
  505. //
  506. // begin_ntddk begin_nthal begin_ntosp
  507. #if defined(_NTDRIVER_) || defined(_NTDDK_) || defined(_NTIFS_)
  508. // begin_wdm
  509. #define KeQueryTickCount(CurrentCount ) { \
  510. volatile PKSYSTEM_TIME _TickCount = *((PKSYSTEM_TIME *)(&KeTickCount)); \
  511. while (TRUE) { \
  512. (CurrentCount)->HighPart = _TickCount->High1Time; \
  513. (CurrentCount)->LowPart = _TickCount->LowPart; \
  514. if ((CurrentCount)->HighPart == _TickCount->High2Time) break; \
  515. _asm { rep nop } \
  516. } \
  517. }
  518. // end_wdm
  519. #else
  520. // end_ntddk end_nthal end_ntosp
  521. #define KiQueryTickCount(CurrentCount) \
  522. while (TRUE) { \
  523. (CurrentCount)->HighPart = KeTickCount.High1Time; \
  524. (CurrentCount)->LowPart = KeTickCount.LowPart; \
  525. if ((CurrentCount)->HighPart == KeTickCount.High2Time) break; \
  526. _asm { rep nop } \
  527. }
  528. // begin_ntddk begin_nthal begin_ntosp
  529. VOID
  530. NTAPI
  531. KeQueryTickCount (
  532. OUT PLARGE_INTEGER CurrentCount
  533. );
  534. #endif // defined(_NTDRIVER_) || defined(_NTDDK_) || defined(_NTIFS_)
  535. // end_ntddk end_nthal end_ntosp
  536. // begin_nthal begin_ntosp
  537. //
  538. // 386 hardware structures
  539. //
  540. //
  541. // A Page Table Entry on an Intel 386/486 has the following definition.
  542. //
  543. // **** NOTE A PRIVATE COPY OF THIS EXISTS IN THE MM\I386 DIRECTORY! ****
  544. // **** ANY CHANGES NEED TO BE MADE TO BOTH HEADER FILES. ****
  545. //
  546. typedef struct _HARDWARE_PTE_X86 {
  547. ULONG Valid : 1;
  548. ULONG Write : 1;
  549. ULONG Owner : 1;
  550. ULONG WriteThrough : 1;
  551. ULONG CacheDisable : 1;
  552. ULONG Accessed : 1;
  553. ULONG Dirty : 1;
  554. ULONG LargePage : 1;
  555. ULONG Global : 1;
  556. ULONG CopyOnWrite : 1; // software field
  557. ULONG Prototype : 1; // software field
  558. ULONG reserved : 1; // software field
  559. ULONG PageFrameNumber : 20;
  560. } HARDWARE_PTE_X86, *PHARDWARE_PTE_X86;
  561. typedef struct _HARDWARE_PTE_X86PAE {
  562. union {
  563. struct {
  564. ULONGLONG Valid : 1;
  565. ULONGLONG Write : 1;
  566. ULONGLONG Owner : 1;
  567. ULONGLONG WriteThrough : 1;
  568. ULONGLONG CacheDisable : 1;
  569. ULONGLONG Accessed : 1;
  570. ULONGLONG Dirty : 1;
  571. ULONGLONG LargePage : 1;
  572. ULONGLONG Global : 1;
  573. ULONGLONG CopyOnWrite : 1; // software field
  574. ULONGLONG Prototype : 1; // software field
  575. ULONGLONG reserved0 : 1; // software field
  576. ULONGLONG PageFrameNumber : 26;
  577. ULONGLONG reserved1 : 26; // software field
  578. };
  579. struct {
  580. ULONG LowPart;
  581. ULONG HighPart;
  582. };
  583. };
  584. } HARDWARE_PTE_X86PAE, *PHARDWARE_PTE_X86PAE;
  585. //
  586. // Special check to work around mspdb limitation
  587. //
  588. #if defined (_NTSYM_HARDWARE_PTE_SYMBOL_)
  589. #if !defined (_X86PAE_)
  590. typedef struct _HARDWARE_PTE {
  591. ULONG Valid : 1;
  592. ULONG Write : 1;
  593. ULONG Owner : 1;
  594. ULONG WriteThrough : 1;
  595. ULONG CacheDisable : 1;
  596. ULONG Accessed : 1;
  597. ULONG Dirty : 1;
  598. ULONG LargePage : 1;
  599. ULONG Global : 1;
  600. ULONG CopyOnWrite : 1; // software field
  601. ULONG Prototype : 1; // software field
  602. ULONG reserved : 1; // software field
  603. ULONG PageFrameNumber : 20;
  604. } HARDWARE_PTE, *PHARDWARE_PTE;
  605. #else
  606. typedef struct _HARDWARE_PTE {
  607. union {
  608. struct {
  609. ULONGLONG Valid : 1;
  610. ULONGLONG Write : 1;
  611. ULONGLONG Owner : 1;
  612. ULONGLONG WriteThrough : 1;
  613. ULONGLONG CacheDisable : 1;
  614. ULONGLONG Accessed : 1;
  615. ULONGLONG Dirty : 1;
  616. ULONGLONG LargePage : 1;
  617. ULONGLONG Global : 1;
  618. ULONGLONG CopyOnWrite : 1; // software field
  619. ULONGLONG Prototype : 1; // software field
  620. ULONGLONG reserved0 : 1; // software field
  621. ULONGLONG PageFrameNumber : 26;
  622. ULONGLONG reserved1 : 26; // software field
  623. };
  624. struct {
  625. ULONG LowPart;
  626. ULONG HighPart;
  627. };
  628. };
  629. } HARDWARE_PTE, *PHARDWARE_PTE;
  630. #endif
  631. #else
  632. #if !defined (_X86PAE_)
  633. typedef HARDWARE_PTE_X86 HARDWARE_PTE;
  634. typedef PHARDWARE_PTE_X86 PHARDWARE_PTE;
  635. #else
  636. typedef HARDWARE_PTE_X86PAE HARDWARE_PTE;
  637. typedef PHARDWARE_PTE_X86PAE PHARDWARE_PTE;
  638. #endif
  639. #endif
  640. //
  641. // GDT Entry
  642. //
  643. typedef struct _KGDTENTRY {
  644. USHORT LimitLow;
  645. USHORT BaseLow;
  646. union {
  647. struct {
  648. UCHAR BaseMid;
  649. UCHAR Flags1; // Declare as bytes to avoid alignment
  650. UCHAR Flags2; // Problems.
  651. UCHAR BaseHi;
  652. } Bytes;
  653. struct {
  654. ULONG BaseMid : 8;
  655. ULONG Type : 5;
  656. ULONG Dpl : 2;
  657. ULONG Pres : 1;
  658. ULONG LimitHi : 4;
  659. ULONG Sys : 1;
  660. ULONG Reserved_0 : 1;
  661. ULONG Default_Big : 1;
  662. ULONG Granularity : 1;
  663. ULONG BaseHi : 8;
  664. } Bits;
  665. } HighWord;
  666. } KGDTENTRY, *PKGDTENTRY;
  667. #define TYPE_CODE 0x10 // 11010 = Code, Readable, NOT Conforming, Accessed
  668. #define TYPE_DATA 0x12 // 10010 = Data, ReadWrite, NOT Expanddown, Accessed
  669. #define TYPE_TSS 0x01 // 01001 = NonBusy TSS
  670. #define TYPE_LDT 0x02 // 00010 = LDT
  671. #define DPL_USER 3
  672. #define DPL_SYSTEM 0
  673. #define GRAN_BYTE 0
  674. #define GRAN_PAGE 1
  675. #define SELECTOR_TABLE_INDEX 0x04
  676. //
  677. // Entry of Interrupt Descriptor Table (IDTENTRY)
  678. //
  679. typedef struct _KIDTENTRY {
  680. USHORT Offset;
  681. USHORT Selector;
  682. USHORT Access;
  683. USHORT ExtendedOffset;
  684. } KIDTENTRY;
  685. typedef KIDTENTRY *PKIDTENTRY;
  686. //
  687. // TSS (Task switch segment) NT only uses to control stack switches.
  688. //
  689. // The only fields we actually care about are Esp0, Ss0, the IoMapBase
  690. // and the IoAccessMaps themselves.
  691. //
  692. //
  693. // N.B. Size of TSS must be <= 0xDFFF
  694. //
  695. //
  696. // The interrupt direction bitmap is used on Pentium to allow
  697. // the processor to emulate V86 mode software interrupts for us.
  698. // There is one for each IOPM. It is located by subtracting
  699. // 32 from the IOPM base in the Tss.
  700. //
  701. #define INT_DIRECTION_MAP_SIZE 32
  702. typedef UCHAR KINT_DIRECTION_MAP[INT_DIRECTION_MAP_SIZE];
  703. #define IOPM_COUNT 1 // Number of i/o access maps that
  704. // exist (in addition to
  705. // IO_ACCESS_MAP_NONE)
  706. #define IO_ACCESS_MAP_NONE 0
  707. #define IOPM_SIZE 8192 // Size of map callers can set.
  708. #define PIOPM_SIZE 8196 // Size of structure we must allocate
  709. // to hold it.
  710. typedef UCHAR KIO_ACCESS_MAP[IOPM_SIZE];
  711. typedef KIO_ACCESS_MAP *PKIO_ACCESS_MAP;
  712. typedef struct _KiIoAccessMap {
  713. KINT_DIRECTION_MAP DirectionMap;
  714. UCHAR IoMap[PIOPM_SIZE];
  715. } KIIO_ACCESS_MAP;
  716. typedef struct _KTSS {
  717. USHORT Backlink;
  718. USHORT Reserved0;
  719. ULONG Esp0;
  720. USHORT Ss0;
  721. USHORT Reserved1;
  722. ULONG NotUsed1[4];
  723. ULONG CR3;
  724. ULONG Eip;
  725. ULONG EFlags;
  726. ULONG Eax;
  727. ULONG Ecx;
  728. ULONG Edx;
  729. ULONG Ebx;
  730. ULONG Esp;
  731. ULONG Ebp;
  732. ULONG Esi;
  733. ULONG Edi;
  734. USHORT Es;
  735. USHORT Reserved2;
  736. USHORT Cs;
  737. USHORT Reserved3;
  738. USHORT Ss;
  739. USHORT Reserved4;
  740. USHORT Ds;
  741. USHORT Reserved5;
  742. USHORT Fs;
  743. USHORT Reserved6;
  744. USHORT Gs;
  745. USHORT Reserved7;
  746. USHORT LDT;
  747. USHORT Reserved8;
  748. USHORT Flags;
  749. USHORT IoMapBase;
  750. KIIO_ACCESS_MAP IoMaps[IOPM_COUNT];
  751. //
  752. // This is the Software interrupt direction bitmap associated with
  753. // IO_ACCESS_MAP_NONE
  754. //
  755. KINT_DIRECTION_MAP IntDirectionMap;
  756. } KTSS, *PKTSS;
  757. #define KiComputeIopmOffset(MapNumber) \
  758. (MapNumber == IO_ACCESS_MAP_NONE) ? \
  759. (USHORT)(sizeof(KTSS)) : \
  760. (USHORT)(FIELD_OFFSET(KTSS, IoMaps[MapNumber-1].IoMap))
  761. // begin_windbgkd
  762. //
  763. // Special Registers for i386
  764. //
  765. #ifdef _X86_
  766. typedef struct _DESCRIPTOR {
  767. USHORT Pad;
  768. USHORT Limit;
  769. ULONG Base;
  770. } KDESCRIPTOR, *PKDESCRIPTOR;
  771. typedef struct _KSPECIAL_REGISTERS {
  772. ULONG Cr0;
  773. ULONG Cr2;
  774. ULONG Cr3;
  775. ULONG Cr4;
  776. ULONG KernelDr0;
  777. ULONG KernelDr1;
  778. ULONG KernelDr2;
  779. ULONG KernelDr3;
  780. ULONG KernelDr6;
  781. ULONG KernelDr7;
  782. KDESCRIPTOR Gdtr;
  783. KDESCRIPTOR Idtr;
  784. USHORT Tr;
  785. USHORT Ldtr;
  786. ULONG Reserved[6];
  787. } KSPECIAL_REGISTERS, *PKSPECIAL_REGISTERS;
  788. //
  789. // Processor State frame: Before a processor freezes itself, it
  790. // dumps the processor state to the processor state frame for
  791. // debugger to examine.
  792. //
  793. typedef struct _KPROCESSOR_STATE {
  794. struct _CONTEXT ContextFrame;
  795. struct _KSPECIAL_REGISTERS SpecialRegisters;
  796. } KPROCESSOR_STATE, *PKPROCESSOR_STATE;
  797. #endif // _X86_
  798. // end_windbgkd
  799. //
  800. // Processor Control Block (PRCB)
  801. //
  802. #define PRCB_MAJOR_VERSION 1
  803. #define PRCB_MINOR_VERSION 1
  804. #define PRCB_BUILD_DEBUG 0x0001
  805. #define PRCB_BUILD_UNIPROCESSOR 0x0002
  806. typedef struct _KPRCB {
  807. //
  808. // Start of the architecturally defined section of the PRCB. This section
  809. // may be directly addressed by vendor/platform specific HAL code and will
  810. // not change from version to version of NT.
  811. //
  812. USHORT MinorVersion;
  813. USHORT MajorVersion;
  814. struct _KTHREAD *CurrentThread;
  815. struct _KTHREAD *NextThread;
  816. struct _KTHREAD *IdleThread;
  817. CCHAR Number;
  818. CCHAR Reserved;
  819. USHORT BuildType;
  820. KAFFINITY SetMember;
  821. CCHAR CpuType;
  822. CCHAR CpuID;
  823. USHORT CpuStep;
  824. struct _KPROCESSOR_STATE ProcessorState;
  825. ULONG KernelReserved[16]; // For use by the kernel
  826. ULONG HalReserved[16]; // For use by Hal
  827. //
  828. // Per processor lock queue entries.
  829. //
  830. // N.B. The following padding is such that the first lock entry falls in the
  831. // last eight bytes of a cache line. This makes the dispatcher lock and
  832. // the context swap lock lie in separate cache lines.
  833. //
  834. UCHAR PrcbPad0[28 + 64];
  835. KSPIN_LOCK_QUEUE LockQueue[16];
  836. UCHAR PrcbPad1[8];
  837. // End of the architecturally defined section of the PRCB.
  838. // end_nthal end_ntosp
  839. //
  840. // Micellaneous counters - 64-byte aligned.
  841. //
  842. struct _KTHREAD *NpxThread;
  843. ULONG InterruptCount;
  844. ULONG KernelTime;
  845. ULONG UserTime;
  846. ULONG DpcTime;
  847. ULONG DebugDpcTime;
  848. ULONG InterruptTime;
  849. ULONG AdjustDpcThreshold;
  850. ULONG PageColor;
  851. LOGICAL SkipTick;
  852. //
  853. // MultiThreadSetBusy is TRUE is all the processors in the set are
  854. // not idle. This field is only updated in the PRCB of the first
  855. // member of the SMT set and only by members of the same set.
  856. //
  857. BOOLEAN MultiThreadSetBusy;
  858. UCHAR Spare2[3];
  859. struct _KNODE * ParentNode; // Node this processor is a member of
  860. KAFFINITY MultiThreadProcessorSet; // Processors in SMT set
  861. struct _KPRCB * MultiThreadSetMaster;// Pointer to first proc in SMT set
  862. ULONG ThreadStartCount[2]; // perf data
  863. //
  864. // Performance counters - 64-byte aligned.
  865. //
  866. // Cache manager performance counters.
  867. //
  868. ULONG CcFastReadNoWait;
  869. ULONG CcFastReadWait;
  870. ULONG CcFastReadNotPossible;
  871. ULONG CcCopyReadNoWait;
  872. ULONG CcCopyReadWait;
  873. ULONG CcCopyReadNoWaitMiss;
  874. //
  875. // Kernel performance counters.
  876. //
  877. ULONG KeAlignmentFixupCount;
  878. ULONG KeContextSwitches;
  879. ULONG KeDcacheFlushCount;
  880. ULONG KeExceptionDispatchCount;
  881. ULONG KeFirstLevelTbFills;
  882. ULONG KeFloatingEmulationCount;
  883. ULONG KeIcacheFlushCount;
  884. ULONG KeSecondLevelTbFills;
  885. ULONG KeSystemCalls;
  886. ULONG SpareCounter0[1];
  887. //
  888. // Nonpaged per processor lookaside lists - 64-byte aligned.
  889. //
  890. PP_LOOKASIDE_LIST PPLookasideList[16];
  891. //
  892. // Nonpaged per processor small pool lookaside lists - 64-byte aligned.
  893. //
  894. PP_LOOKASIDE_LIST PPNPagedLookasideList[POOL_SMALL_LISTS];
  895. //
  896. // Paged per processor small pool lookaside lists - 64-byte aligned.
  897. //
  898. PP_LOOKASIDE_LIST PPPagedLookasideList[POOL_SMALL_LISTS];
  899. //
  900. // MP interprocessor request packet barrier - 64-byte aligned.
  901. //
  902. volatile ULONG PacketBarrier;
  903. volatile ULONG ReverseStall;
  904. PVOID IpiFrame;
  905. UCHAR PrcbPad2[52];
  906. //
  907. // MP interprocessor request packet and summary - 64-byte aligned.
  908. //
  909. volatile PVOID CurrentPacket[3];
  910. volatile KAFFINITY TargetSet;
  911. volatile PKIPI_WORKER WorkerRoutine;
  912. volatile ULONG IpiFrozen;
  913. UCHAR PrcbPad3[40];
  914. //
  915. // MP interprocessor request summary and packet address - 64-byte aligned.
  916. //
  917. volatile ULONG RequestSummary;
  918. volatile struct _KPRCB *SignalDone;
  919. UCHAR PrcbPad4[56];
  920. //
  921. // DPC listhead, counts, and batching parameters - 64-byte aligned.
  922. //
  923. LIST_ENTRY DpcListHead;
  924. PVOID DpcStack;
  925. ULONG DpcCount;
  926. volatile ULONG DpcQueueDepth;
  927. volatile ULONG DpcRoutineActive;
  928. volatile ULONG DpcInterruptRequested;
  929. ULONG DpcLastCount;
  930. ULONG DpcRequestRate;
  931. ULONG MaximumDpcQueueDepth;
  932. ULONG MinimumDpcRate;
  933. ULONG QuantumEnd;
  934. UCHAR PrcbPad5[16];
  935. //
  936. // DPC list lock - 64-byte aligned.
  937. //
  938. KSPIN_LOCK DpcLock;
  939. UCHAR PrcbPad6[60];
  940. //
  941. // Per processor chained interrupt list.
  942. //
  943. PVOID ChainedInterruptList;
  944. //
  945. // I/O IRP float.
  946. //
  947. LONG LookasideIrpFloat;
  948. //
  949. // Spare fields.
  950. //
  951. ULONG SpareFields0[6];
  952. //
  953. // Processor information.
  954. //
  955. UCHAR VendorString[13];
  956. UCHAR InitialApicId;
  957. UCHAR LogicalProcessorsPerPhysicalProcessor;
  958. ULONG MHz;
  959. ULONG FeatureBits;
  960. LARGE_INTEGER UpdateSignature;
  961. //
  962. // Npx save area - 16-byte aligned.
  963. //
  964. FX_SAVE_AREA NpxSaveArea;
  965. //
  966. // Processors power state
  967. //
  968. PROCESSOR_POWER_STATE PowerState;
  969. // begin_nthal begin_ntosp
  970. } KPRCB, *PKPRCB, *RESTRICTED_POINTER PRKPRCB;
  971. // end_nthal end_ntosp
  972. //
  973. // The offset of the PRCB in the PCR is 32 mod 64.
  974. //
  975. // The offset of the following structure must be 0 mod 64 except for the
  976. // lock queue array which straddles two cache lines.
  977. //
  978. C_ASSERT(((FIELD_OFFSET(KPRCB, LockQueue) + sizeof(KSPIN_LOCK_QUEUE) + 32) & (64 - 1)) == 0);
  979. C_ASSERT(((FIELD_OFFSET(KPRCB, NpxThread) + 32) & (64 - 1)) == 0);
  980. C_ASSERT(((FIELD_OFFSET(KPRCB, CcFastReadNoWait) + 32) & (64 - 1)) == 0);
  981. C_ASSERT(((FIELD_OFFSET(KPRCB, PPLookasideList) + 32) & (64 - 1)) == 0);
  982. C_ASSERT(((FIELD_OFFSET(KPRCB, PPNPagedLookasideList) + 32) & (64 - 1)) == 0);
  983. C_ASSERT(((FIELD_OFFSET(KPRCB, PPPagedLookasideList) + 32) & (64 - 1)) == 0);
  984. C_ASSERT(((FIELD_OFFSET(KPRCB, PacketBarrier) + 32) & (64 - 1)) == 0);
  985. C_ASSERT(((FIELD_OFFSET(KPRCB, CurrentPacket) + 32) & (64 - 1)) == 0);
  986. C_ASSERT(((FIELD_OFFSET(KPRCB, DpcListHead) + 32) & (64 - 1)) == 0);
  987. C_ASSERT(((FIELD_OFFSET(KPRCB, DpcLock) + 32) & (64 - 1)) == 0);
  988. C_ASSERT(((FIELD_OFFSET(KPRCB, ChainedInterruptList) + 32) & (64 - 1)) == 0);
  989. C_ASSERT(((FIELD_OFFSET(KPRCB, NpxSaveArea) + 32) & (16 - 1)) == 0);
  990. // begin_nthal begin_ntddk begin_ntosp
  991. //
  992. // Processor Control Region Structure Definition
  993. //
  994. #define PCR_MINOR_VERSION 1
  995. #define PCR_MAJOR_VERSION 1
  996. typedef struct _KPCR {
  997. //
  998. // Start of the architecturally defined section of the PCR. This section
  999. // may be directly addressed by vendor/platform specific HAL code and will
  1000. // not change from version to version of NT.
  1001. //
  1002. NT_TIB NtTib;
  1003. struct _KPCR *SelfPcr; // flat address of this PCR
  1004. struct _KPRCB *Prcb; // pointer to Prcb
  1005. KIRQL Irql;
  1006. ULONG IRR;
  1007. ULONG IrrActive;
  1008. ULONG IDR;
  1009. PVOID KdVersionBlock;
  1010. struct _KIDTENTRY *IDT;
  1011. struct _KGDTENTRY *GDT;
  1012. struct _KTSS *TSS;
  1013. USHORT MajorVersion;
  1014. USHORT MinorVersion;
  1015. KAFFINITY SetMember;
  1016. ULONG StallScaleFactor;
  1017. UCHAR DebugActive;
  1018. UCHAR Number;
  1019. // end_ntddk end_ntosp
  1020. UCHAR Spare0;
  1021. UCHAR SecondLevelCacheAssociativity;
  1022. ULONG VdmAlert;
  1023. ULONG KernelReserved[14]; // For use by the kernel
  1024. ULONG SecondLevelCacheSize;
  1025. ULONG HalReserved[16]; // For use by Hal
  1026. // End of the architecturally defined section of the PCR.
  1027. // end_nthal
  1028. ULONG InterruptMode;
  1029. UCHAR Spare1;
  1030. ULONG KernelReserved2[17];
  1031. struct _KPRCB PrcbData;
  1032. // begin_nthal begin_ntddk begin_ntosp
  1033. } KPCR, *PKPCR;
  1034. // end_nthal end_ntddk end_ntosp
  1035. C_ASSERT((FIELD_OFFSET(KPCR, PrcbData) & (64 - 1)) == 32);
  1036. // begin_nthal begin_ntosp
  1037. #define EFLAGS_TF 0x00000100L
  1038. #define EFLAGS_INTERRUPT_MASK 0x00000200L
  1039. #define EFLAGS_DF_MASK 0x00000400L
  1040. #define EFLAGS_V86_MASK 0x00020000L
  1041. #define EFLAGS_ALIGN_CHECK 0x00040000L
  1042. #define EFLAGS_IOPL_MASK 0x00003000L
  1043. #define EFLAGS_VIF 0x00080000L
  1044. #define EFLAGS_VIP 0x00100000L
  1045. #define EFLAGS_USER_SANITIZE 0x003e0dd7L
  1046. // end_nthal
  1047. //
  1048. // Sanitize segCS and eFlags based on a processor mode.
  1049. //
  1050. // If kernel mode,
  1051. // force CPL == 0
  1052. //
  1053. // If user mode,
  1054. // force CPL == 3
  1055. //
  1056. #define SANITIZE_SEG(segCS, mode) (\
  1057. ((mode) == KernelMode ? \
  1058. ((0x00000000L) | ((segCS) & 0xfffc)) : \
  1059. ((0x00000003L) | ((segCS) & 0xffff))))
  1060. //
  1061. // If kernel mode, then
  1062. // let caller specify Carry, Parity, AuxCarry, Zero, Sign, Trap,
  1063. // Direction, Overflow, Interrupt, AlignCheck.
  1064. //
  1065. // If user mode, then
  1066. // let caller specify Carry, Parity, AuxCarry, Zero, Sign, Trap,
  1067. // Direction, Overflow, AlignCheck.
  1068. // force Interrupts on.
  1069. //
  1070. #define SANITIZE_FLAGS(eFlags, mode) (\
  1071. ((mode) == KernelMode ? \
  1072. ((0x00000000L) | ((eFlags) & 0x003e0fd7)) : \
  1073. ((((eFlags) & EFLAGS_V86_MASK) && KeI386VdmIoplAllowed) ? \
  1074. (((eFlags) & KeI386EFlagsAndMaskV86) | KeI386EFlagsOrMaskV86) : \
  1075. ((EFLAGS_INTERRUPT_MASK) | ((eFlags) & EFLAGS_USER_SANITIZE)))))
  1076. //
  1077. // Masks for Dr7 and sanitize macros for various Dr registers.
  1078. //
  1079. #define DR6_LEGAL 0x0000e00f
  1080. #define DR7_LEGAL 0xffff0155 // R/W, LEN for Dr0-Dr4,
  1081. // Local enable for Dr0-Dr4,
  1082. // Le for "perfect" trapping
  1083. #define DR7_ACTIVE 0x00000055 // If any of these bits are set, a Dr is active
  1084. #define SANITIZE_DR6(Dr6, mode) ((Dr6 & DR6_LEGAL));
  1085. #define SANITIZE_DR7(Dr7, mode) ((Dr7 & DR7_LEGAL));
  1086. #define SANITIZE_DRADDR(DrReg, mode) ( \
  1087. (mode) == KernelMode ? \
  1088. (DrReg) : \
  1089. (((PVOID)DrReg <= MM_HIGHEST_USER_ADDRESS) ? \
  1090. (DrReg) : \
  1091. (0) \
  1092. ) \
  1093. )
  1094. //
  1095. // Define macro to clear reserved bits from MXCSR so that we don't
  1096. // GP fault when doing an FRSTOR
  1097. //
  1098. extern ULONG KiMXCsrMask;
  1099. #define SANITIZE_MXCSR(_mxcsr_) ((_mxcsr_) & KiMXCsrMask)
  1100. //
  1101. // Nonvolatile context pointers
  1102. //
  1103. // bryanwi 21 feb 90 - This is bogus. The 386 doesn't have
  1104. // enough nonvolatile context to make this
  1105. // structure worthwhile. Can't declare a
  1106. // field to be void, so declare a Junk structure
  1107. // instead.
  1108. typedef struct _KNONVOLATILE_CONTEXT_POINTERS {
  1109. ULONG Junk;
  1110. } KNONVOLATILE_CONTEXT_POINTERS, *PKNONVOLATILE_CONTEXT_POINTERS;
  1111. // begin_nthal
  1112. //
  1113. // Trap frame
  1114. //
  1115. // NOTE - We deal only with 32bit registers, so the assembler equivalents
  1116. // are always the extended forms.
  1117. //
  1118. // NOTE - Unless you want to run like slow molasses everywhere in the
  1119. // the system, this structure must be of DWORD length, DWORD
  1120. // aligned, and its elements must all be DWORD aligned.
  1121. //
  1122. // NOTE WELL -
  1123. //
  1124. // The i386 does not build stack frames in a consistent format, the
  1125. // frames vary depending on whether or not a privilege transition
  1126. // was involved.
  1127. //
  1128. // In order to make NtContinue work for both user mode and kernel
  1129. // mode callers, we must force a canonical stack.
  1130. //
  1131. // If we're called from kernel mode, this structure is 8 bytes longer
  1132. // than the actual frame!
  1133. //
  1134. // WARNING:
  1135. //
  1136. // KTRAP_FRAME_LENGTH needs to be 16byte integral (at present.)
  1137. //
  1138. typedef struct _KTRAP_FRAME {
  1139. //
  1140. // Following 4 values are only used and defined for DBG systems,
  1141. // but are always allocated to make switching from DBG to non-DBG
  1142. // and back quicker. They are not DEVL because they have a non-0
  1143. // performance impact.
  1144. //
  1145. ULONG DbgEbp; // Copy of User EBP set up so KB will work.
  1146. ULONG DbgEip; // EIP of caller to system call, again, for KB.
  1147. ULONG DbgArgMark; // Marker to show no args here.
  1148. ULONG DbgArgPointer; // Pointer to the actual args
  1149. //
  1150. // Temporary values used when frames are edited.
  1151. //
  1152. //
  1153. // NOTE: Any code that want's ESP must materialize it, since it
  1154. // is not stored in the frame for kernel mode callers.
  1155. //
  1156. // And code that sets ESP in a KERNEL mode frame, must put
  1157. // the new value in TempEsp, make sure that TempSegCs holds
  1158. // the real SegCs value, and put a special marker value into SegCs.
  1159. //
  1160. ULONG TempSegCs;
  1161. ULONG TempEsp;
  1162. //
  1163. // Debug registers.
  1164. //
  1165. ULONG Dr0;
  1166. ULONG Dr1;
  1167. ULONG Dr2;
  1168. ULONG Dr3;
  1169. ULONG Dr6;
  1170. ULONG Dr7;
  1171. //
  1172. // Segment registers
  1173. //
  1174. ULONG SegGs;
  1175. ULONG SegEs;
  1176. ULONG SegDs;
  1177. //
  1178. // Volatile registers
  1179. //
  1180. ULONG Edx;
  1181. ULONG Ecx;
  1182. ULONG Eax;
  1183. //
  1184. // Nesting state, not part of context record
  1185. //
  1186. ULONG PreviousPreviousMode;
  1187. PEXCEPTION_REGISTRATION_RECORD ExceptionList;
  1188. // Trash if caller was user mode.
  1189. // Saved exception list if caller
  1190. // was kernel mode or we're in
  1191. // an interrupt.
  1192. //
  1193. // FS is TIB/PCR pointer, is here to make save sequence easy
  1194. //
  1195. ULONG SegFs;
  1196. //
  1197. // Non-volatile registers
  1198. //
  1199. ULONG Edi;
  1200. ULONG Esi;
  1201. ULONG Ebx;
  1202. ULONG Ebp;
  1203. //
  1204. // Control registers
  1205. //
  1206. ULONG ErrCode;
  1207. ULONG Eip;
  1208. ULONG SegCs;
  1209. ULONG EFlags;
  1210. ULONG HardwareEsp; // WARNING - segSS:esp are only here for stacks
  1211. ULONG HardwareSegSs; // that involve a ring transition.
  1212. ULONG V86Es; // these will be present for all transitions from
  1213. ULONG V86Ds; // V86 mode
  1214. ULONG V86Fs;
  1215. ULONG V86Gs;
  1216. } KTRAP_FRAME;
  1217. typedef KTRAP_FRAME *PKTRAP_FRAME;
  1218. typedef KTRAP_FRAME *PKEXCEPTION_FRAME;
  1219. #define KTRAP_FRAME_LENGTH (sizeof(KTRAP_FRAME))
  1220. #define KTRAP_FRAME_ALIGN (sizeof(ULONG))
  1221. #define KTRAP_FRAME_ROUND (KTRAP_FRAME_ALIGN-1)
  1222. //
  1223. // Bits forced to 0 in SegCs if Esp has been edited.
  1224. //
  1225. #define FRAME_EDITED 0xfff8
  1226. // end_nthal
  1227. //
  1228. // The frame saved by KiCallUserMode is defined here to allow
  1229. // the kernel debugger to trace the entire kernel stack
  1230. // when usermode callouts are pending.
  1231. //
  1232. typedef struct _KCALLOUT_FRAME {
  1233. ULONG InStk; // saved initial stack address
  1234. ULONG TrFr; // saved callback trap frame
  1235. ULONG CbStk; // saved callback stack address
  1236. ULONG Edi; // saved nonvolatile registers
  1237. ULONG Esi; //
  1238. ULONG Ebx; //
  1239. ULONG Ebp; //
  1240. ULONG Ret; // saved return address
  1241. ULONG OutBf; // address to store output buffer
  1242. ULONG OutLn; // address to store output length
  1243. } KCALLOUT_FRAME;
  1244. typedef KCALLOUT_FRAME *PKCALLOUT_FRAME;
  1245. //
  1246. // Switch Frame
  1247. //
  1248. // 386 doesn't have an "exception frame", and doesn't normally make
  1249. // any use of nonvolatile context register structures.
  1250. //
  1251. // However, swapcontext in ctxswap.c and KeInitializeThread in
  1252. // thredini.c need to share common stack structure used at thread
  1253. // startup and switch time.
  1254. //
  1255. // This is that structure.
  1256. //
  1257. typedef struct _KSWITCHFRAME {
  1258. ULONG ExceptionList;
  1259. ULONG Eflags;
  1260. ULONG RetAddr;
  1261. } KSWITCHFRAME, *PKSWITCHFRAME;
  1262. //
  1263. // Various 387 defines
  1264. //
  1265. #define I386_80387_NP_VECTOR 0x07 // trap 7 when hardware not present
  1266. // begin_ntddk begin_wdm
  1267. //
  1268. // The non-volatile 387 state
  1269. //
  1270. typedef struct _KFLOATING_SAVE {
  1271. ULONG ControlWord;
  1272. ULONG StatusWord;
  1273. ULONG ErrorOffset;
  1274. ULONG ErrorSelector;
  1275. ULONG DataOffset; // Not used in wdm
  1276. ULONG DataSelector;
  1277. ULONG Cr0NpxState;
  1278. ULONG Spare1; // Not used in wdm
  1279. } KFLOATING_SAVE, *PKFLOATING_SAVE;
  1280. // end_ntddk end_wdm end_ntosp
  1281. //
  1282. // i386 Profile values
  1283. //
  1284. #define DEFAULT_PROFILE_INTERVAL 39063
  1285. //
  1286. // The minimum acceptable profiling interval is set to 1221 which is the
  1287. // fast RTC clock rate we can get. If this
  1288. // value is too small, the system will run very slowly.
  1289. //
  1290. #define MINIMUM_PROFILE_INTERVAL 1221
  1291. // begin_ntddk begin_wdm begin_nthal begin_ntndis begin_ntosp
  1292. //
  1293. // i386 Specific portions of mm component
  1294. //
  1295. //
  1296. // Define the page size for the Intel 386 as 4096 (0x1000).
  1297. //
  1298. #define PAGE_SIZE 0x1000
  1299. //
  1300. // Define the number of trailing zeroes in a page aligned virtual address.
  1301. // This is used as the shift count when shifting virtual addresses to
  1302. // virtual page numbers.
  1303. //
  1304. #define PAGE_SHIFT 12L
  1305. // end_ntndis end_wdm
  1306. //
  1307. // Define the number of bits to shift to right justify the Page Directory Index
  1308. // field of a PTE.
  1309. //
  1310. #define PDI_SHIFT_X86 22
  1311. #define PDI_SHIFT_X86PAE 21
  1312. #if !defined (_X86PAE_)
  1313. #define PDI_SHIFT PDI_SHIFT_X86
  1314. #else
  1315. #define PDI_SHIFT PDI_SHIFT_X86PAE
  1316. #define PPI_SHIFT 30
  1317. #endif
  1318. //
  1319. // Define the number of bits to shift to right justify the Page Table Index
  1320. // field of a PTE.
  1321. //
  1322. #define PTI_SHIFT 12
  1323. //
  1324. // Define the highest user address and user probe address.
  1325. //
  1326. // end_ntddk end_nthal end_ntosp
  1327. #if defined(_NTDRIVER_) || defined(_NTDDK_) || defined(_NTIFS_) || defined(_NTHAL_)
  1328. // begin_ntddk begin_nthal begin_ntosp
  1329. extern PVOID *MmHighestUserAddress;
  1330. extern PVOID *MmSystemRangeStart;
  1331. extern ULONG *MmUserProbeAddress;
  1332. #define MM_HIGHEST_USER_ADDRESS *MmHighestUserAddress
  1333. #define MM_SYSTEM_RANGE_START *MmSystemRangeStart
  1334. #define MM_USER_PROBE_ADDRESS *MmUserProbeAddress
  1335. // end_ntddk end_nthal end_ntosp
  1336. #else
  1337. extern PVOID MmHighestUserAddress;
  1338. extern PVOID MmSystemRangeStart;
  1339. extern ULONG MmUserProbeAddress;
  1340. #define MM_HIGHEST_USER_ADDRESS MmHighestUserAddress
  1341. #define MM_SYSTEM_RANGE_START MmSystemRangeStart
  1342. #define MM_USER_PROBE_ADDRESS MmUserProbeAddress
  1343. #endif
  1344. // begin_ntddk begin_nthal begin_ntosp
  1345. //
  1346. // The lowest user address reserves the low 64k.
  1347. //
  1348. #define MM_LOWEST_USER_ADDRESS (PVOID)0x10000
  1349. //
  1350. // The lowest address for system space.
  1351. //
  1352. #if !defined (_X86PAE_)
  1353. #define MM_LOWEST_SYSTEM_ADDRESS (PVOID)0xC0800000
  1354. #else
  1355. #define MM_LOWEST_SYSTEM_ADDRESS (PVOID)0xC0C00000
  1356. #endif
  1357. // begin_wdm
  1358. #define MmGetProcedureAddress(Address) (Address)
  1359. #define MmLockPagableCodeSection(Address) MmLockPagableDataSection(Address)
  1360. // end_ntddk end_wdm
  1361. //
  1362. // Define the number of bits to shift to right justify the Page Directory Index
  1363. // field of a PTE.
  1364. //
  1365. #define PDI_SHIFT_X86 22
  1366. #define PDI_SHIFT_X86PAE 21
  1367. #if !defined (_X86PAE_)
  1368. #define PDI_SHIFT PDI_SHIFT_X86
  1369. #else
  1370. #define PDI_SHIFT PDI_SHIFT_X86PAE
  1371. #define PPI_SHIFT 30
  1372. #endif
  1373. //
  1374. // Define the number of bits to shift to right justify the Page Table Index
  1375. // field of a PTE.
  1376. //
  1377. #define PTI_SHIFT 12
  1378. //
  1379. // Define page directory and page base addresses.
  1380. //
  1381. #define PDE_BASE_X86 0xc0300000
  1382. #define PDE_BASE_X86PAE 0xc0600000
  1383. #define PTE_TOP_X86 0xC03FFFFF
  1384. #define PDE_TOP_X86 0xC0300FFF
  1385. #define PTE_TOP_X86PAE 0xC07FFFFF
  1386. #define PDE_TOP_X86PAE 0xC0603FFF
  1387. #if !defined (_X86PAE_)
  1388. #define PDE_BASE PDE_BASE_X86
  1389. #define PTE_TOP PTE_TOP_X86
  1390. #define PDE_TOP PDE_TOP_X86
  1391. #else
  1392. #define PDE_BASE PDE_BASE_X86PAE
  1393. #define PTE_TOP PTE_TOP_X86PAE
  1394. #define PDE_TOP PDE_TOP_X86PAE
  1395. #endif
  1396. #define PTE_BASE 0xc0000000
  1397. // end_nthal end_ntosp
  1398. //
  1399. // Define virtual base and alternate virtual base of kernel.
  1400. //
  1401. #define KSEG0_BASE 0x80000000
  1402. #define ALTERNATE_BASE (0xe1000000 - 16 * 1024 * 1024)
  1403. //
  1404. // Define macro to initialize directory table base.
  1405. //
  1406. #define INITIALIZE_DIRECTORY_TABLE_BASE(dirbase,pfn) \
  1407. *((PULONG)(dirbase)) = ((pfn) << PAGE_SHIFT)
  1408. // begin_nthal
  1409. //
  1410. // Location of primary PCR (used only for UP kernel & hal code)
  1411. //
  1412. // addressed from 0xffdf0000 - 0xffdfffff are reserved for the system
  1413. // (ie, not for use by the hal)
  1414. #define KI_BEGIN_KERNEL_RESERVED 0xffdf0000
  1415. #define KIP0PCRADDRESS 0xffdff000 // ntddk wdm ntosp
  1416. // begin_ntddk begin_ntosp
  1417. #define KI_USER_SHARED_DATA 0xffdf0000
  1418. #define SharedUserData ((KUSER_SHARED_DATA * const) KI_USER_SHARED_DATA)
  1419. //
  1420. // Result type definition for i386. (Machine specific enumerate type
  1421. // which is return type for portable exinterlockedincrement/decrement
  1422. // procedures.) In general, you should use the enumerated type defined
  1423. // in ex.h instead of directly referencing these constants.
  1424. //
  1425. // Flags loaded into AH by LAHF instruction
  1426. #define EFLAG_SIGN 0x8000
  1427. #define EFLAG_ZERO 0x4000
  1428. #define EFLAG_SELECT (EFLAG_SIGN | EFLAG_ZERO)
  1429. #define RESULT_NEGATIVE ((EFLAG_SIGN & ~EFLAG_ZERO) & EFLAG_SELECT)
  1430. #define RESULT_ZERO ((~EFLAG_SIGN & EFLAG_ZERO) & EFLAG_SELECT)
  1431. #define RESULT_POSITIVE ((~EFLAG_SIGN & ~EFLAG_ZERO) & EFLAG_SELECT)
  1432. //
  1433. // Convert various portable ExInterlock APIs into their architectural
  1434. // equivalents.
  1435. //
  1436. #if PRAGMA_DEPRECATED_DDK
  1437. #pragma deprecated(ExInterlockedIncrementLong) // Use InterlockedIncrement
  1438. #pragma deprecated(ExInterlockedDecrementLong) // Use InterlockedDecrement
  1439. #pragma deprecated(ExInterlockedExchangeUlong) // Use InterlockedExchange
  1440. #endif
  1441. #define ExInterlockedIncrementLong(Addend,Lock) \
  1442. Exfi386InterlockedIncrementLong(Addend)
  1443. #define ExInterlockedDecrementLong(Addend,Lock) \
  1444. Exfi386InterlockedDecrementLong(Addend)
  1445. #define ExInterlockedExchangeUlong(Target,Value,Lock) \
  1446. Exfi386InterlockedExchangeUlong(Target,Value)
  1447. // begin_wdm
  1448. #define ExInterlockedAddUlong ExfInterlockedAddUlong
  1449. #define ExInterlockedInsertHeadList ExfInterlockedInsertHeadList
  1450. #define ExInterlockedInsertTailList ExfInterlockedInsertTailList
  1451. #define ExInterlockedRemoveHeadList ExfInterlockedRemoveHeadList
  1452. #define ExInterlockedPopEntryList ExfInterlockedPopEntryList
  1453. #define ExInterlockedPushEntryList ExfInterlockedPushEntryList
  1454. // end_wdm
  1455. //
  1456. // Prototypes for architectural specific versions of Exi386 Api
  1457. //
  1458. //
  1459. // Interlocked result type is portable, but its values are machine specific.
  1460. // Constants for value are in i386.h, mips.h, etc.
  1461. //
  1462. typedef enum _INTERLOCKED_RESULT {
  1463. ResultNegative = RESULT_NEGATIVE,
  1464. ResultZero = RESULT_ZERO,
  1465. ResultPositive = RESULT_POSITIVE
  1466. } INTERLOCKED_RESULT;
  1467. NTKERNELAPI
  1468. INTERLOCKED_RESULT
  1469. FASTCALL
  1470. Exfi386InterlockedIncrementLong (
  1471. IN PLONG Addend
  1472. );
  1473. NTKERNELAPI
  1474. INTERLOCKED_RESULT
  1475. FASTCALL
  1476. Exfi386InterlockedDecrementLong (
  1477. IN PLONG Addend
  1478. );
  1479. NTKERNELAPI
  1480. ULONG
  1481. FASTCALL
  1482. Exfi386InterlockedExchangeUlong (
  1483. IN PULONG Target,
  1484. IN ULONG Value
  1485. );
  1486. // end_ntddk end_nthal end_ntosp
  1487. //
  1488. // UP/MP versions of interlocked intrinsics
  1489. //
  1490. // N.B. FASTCALL does NOT work with inline functions.
  1491. //
  1492. #if !defined(_WINBASE_) && !defined(NONTOSPINTERLOCK) // ntosp ntddk nthal
  1493. #if defined(_M_IX86)
  1494. #pragma warning(disable:4035) // wdm re-enable below
  1495. // begin_ntddk begin_nthal begin_ntosp
  1496. #if !defined(MIDL_PASS) // wdm
  1497. #if defined(NO_INTERLOCKED_INTRINSICS) || defined(_CROSS_PLATFORM_)
  1498. // begin_wdm
  1499. NTKERNELAPI
  1500. LONG
  1501. FASTCALL
  1502. InterlockedIncrement(
  1503. IN LONG volatile *Addend
  1504. );
  1505. NTKERNELAPI
  1506. LONG
  1507. FASTCALL
  1508. InterlockedDecrement(
  1509. IN LONG volatile *Addend
  1510. );
  1511. NTKERNELAPI
  1512. LONG
  1513. FASTCALL
  1514. InterlockedExchange(
  1515. IN OUT LONG volatile *Target,
  1516. IN LONG Value
  1517. );
  1518. #define InterlockedExchangePointer(Target, Value) \
  1519. (PVOID)InterlockedExchange((PLONG)(Target), (LONG)(Value))
  1520. LONG
  1521. FASTCALL
  1522. InterlockedExchangeAdd(
  1523. IN OUT LONG volatile *Addend,
  1524. IN LONG Increment
  1525. );
  1526. NTKERNELAPI
  1527. LONG
  1528. FASTCALL
  1529. InterlockedCompareExchange(
  1530. IN OUT LONG volatile *Destination,
  1531. IN LONG ExChange,
  1532. IN LONG Comperand
  1533. );
  1534. #define InterlockedCompareExchangePointer(Destination, ExChange, Comperand) \
  1535. (PVOID)InterlockedCompareExchange((PLONG)Destination, (LONG)ExChange, (LONG)Comperand)
  1536. #define InterlockedCompareExchange64(Destination, ExChange, Comperand) \
  1537. ExfInterlockedCompareExchange64(Destination, &(ExChange), &(Comperand))
  1538. NTKERNELAPI
  1539. LONGLONG
  1540. FASTCALL
  1541. ExfInterlockedCompareExchange64(
  1542. IN OUT LONGLONG volatile *Destination,
  1543. IN PLONGLONG ExChange,
  1544. IN PLONGLONG Comperand
  1545. );
  1546. // end_wdm
  1547. #else // NO_INTERLOCKED_INCREMENTS || _CROSS_PLATFORM_
  1548. #define InterlockedExchangePointer(Target, Value) \
  1549. (PVOID)InterlockedExchange((PLONG)Target, (LONG)Value)
  1550. // end_ntddk end_nthal end_ntosp
  1551. #if defined(NT_UP) && !defined (_NTDDK_) && !defined(_NTIFS_)
  1552. #define InterlockedIncrement(Addend) (InterlockedExchangeAdd (Addend, 1)+1)
  1553. #define InterlockedDecrement(Addend) (InterlockedExchangeAdd (Addend, -1)-1)
  1554. //FORCEINLINE
  1555. //LONG
  1556. //FASTCALL
  1557. //InterlockedIncrement(
  1558. // IN PLONG Addend
  1559. // )
  1560. //{
  1561. // __asm {
  1562. // mov eax, 1
  1563. // mov ecx, Addend
  1564. // xadd [ecx], eax
  1565. // inc eax
  1566. // }
  1567. //}
  1568. //FORCEINLINE
  1569. //LONG
  1570. //FASTCALL
  1571. //InterlockedDecrement(
  1572. // IN PLONG Addend
  1573. // )
  1574. //{
  1575. // __asm {
  1576. // mov eax, -1
  1577. // mov ecx, Addend
  1578. // xadd [ecx], eax
  1579. // dec eax
  1580. // }
  1581. //}
  1582. FORCEINLINE
  1583. LONG
  1584. FASTCALL
  1585. InterlockedExchange(
  1586. IN OUT LONG volatile *Target,
  1587. IN LONG Value
  1588. )
  1589. {
  1590. __asm {
  1591. mov eax, Value
  1592. mov ecx, Target
  1593. xchg [ecx], eax
  1594. }
  1595. }
  1596. FORCEINLINE
  1597. LONG
  1598. FASTCALL
  1599. InterlockedExchangeAdd(
  1600. IN OUT LONG volatile *Addend,
  1601. IN LONG Increment
  1602. )
  1603. {
  1604. __asm {
  1605. mov eax, Increment
  1606. mov ecx, Addend
  1607. xadd [ecx], eax
  1608. }
  1609. }
  1610. FORCEINLINE
  1611. LONG
  1612. FASTCALL
  1613. InterlockedCompareExchange(
  1614. IN OUT LONG volatile *Destination,
  1615. IN LONG Exchange,
  1616. IN LONG Comperand
  1617. )
  1618. {
  1619. __asm {
  1620. mov eax, Comperand
  1621. mov ecx, Destination
  1622. mov edx, Exchange
  1623. cmpxchg [ecx], edx
  1624. }
  1625. }
  1626. #define InterlockedCompareExchangePointer(Destination, ExChange, Comperand) \
  1627. (PVOID)InterlockedCompareExchange((PLONG)Destination, (LONG)ExChange, (LONG)Comperand)
  1628. #define InterlockedCompareExchange64(Destination, ExChange, Comperand) \
  1629. ExfInterlockedCompareExchange64(Destination, &(ExChange), &(Comperand))
  1630. LONGLONG
  1631. FASTCALL
  1632. ExfInterlockedCompareExchange64(
  1633. IN OUT LONGLONG volatile *Destination,
  1634. IN PLONGLONG ExChange,
  1635. IN PLONGLONG Comperand
  1636. );
  1637. #else // NT_UP
  1638. // begin_ntosp begin_ntddk begin_nthal
  1639. #if (_MSC_FULL_VER > 13009037)
  1640. LONG
  1641. __cdecl
  1642. _InterlockedExchange(
  1643. IN OUT LONG volatile *Target,
  1644. IN LONG Value
  1645. );
  1646. #pragma intrinsic (_InterlockedExchange)
  1647. #define InterlockedExchange _InterlockedExchange
  1648. #else
  1649. FORCEINLINE
  1650. LONG
  1651. FASTCALL
  1652. InterlockedExchange(
  1653. IN OUT LONG volatile *Target,
  1654. IN LONG Value
  1655. )
  1656. {
  1657. __asm {
  1658. mov eax, Value
  1659. mov ecx, Target
  1660. xchg [ecx], eax
  1661. }
  1662. }
  1663. #endif
  1664. #if (_MSC_FULL_VER > 13009037)
  1665. LONG
  1666. __cdecl
  1667. _InterlockedIncrement(
  1668. IN LONG volatile *Addend
  1669. );
  1670. #pragma intrinsic (_InterlockedIncrement)
  1671. #define InterlockedIncrement _InterlockedIncrement
  1672. #else
  1673. #define InterlockedIncrement(Addend) (InterlockedExchangeAdd (Addend, 1)+1)
  1674. #endif
  1675. #if (_MSC_FULL_VER > 13009037)
  1676. LONG
  1677. __cdecl
  1678. _InterlockedDecrement(
  1679. IN LONG volatile *Addend
  1680. );
  1681. #pragma intrinsic (_InterlockedDecrement)
  1682. #define InterlockedDecrement _InterlockedDecrement
  1683. #else
  1684. #define InterlockedDecrement(Addend) (InterlockedExchangeAdd (Addend, -1)-1)
  1685. #endif
  1686. #if (_MSC_FULL_VER > 13009037)
  1687. LONG
  1688. __cdecl
  1689. _InterlockedExchangeAdd(
  1690. IN OUT LONG volatile *Addend,
  1691. IN LONG Increment
  1692. );
  1693. #pragma intrinsic (_InterlockedExchangeAdd)
  1694. #define InterlockedExchangeAdd _InterlockedExchangeAdd
  1695. #else
  1696. // begin_wdm
  1697. FORCEINLINE
  1698. LONG
  1699. FASTCALL
  1700. InterlockedExchangeAdd(
  1701. IN OUT LONG volatile *Addend,
  1702. IN LONG Increment
  1703. )
  1704. {
  1705. __asm {
  1706. mov eax, Increment
  1707. mov ecx, Addend
  1708. lock xadd [ecx], eax
  1709. }
  1710. }
  1711. // end_wdm
  1712. #endif
  1713. #if (_MSC_FULL_VER > 13009037)
  1714. LONG
  1715. __cdecl
  1716. _InterlockedCompareExchange (
  1717. IN OUT LONG volatile *Destination,
  1718. IN LONG ExChange,
  1719. IN LONG Comperand
  1720. );
  1721. #pragma intrinsic (_InterlockedCompareExchange)
  1722. #define InterlockedCompareExchange (LONG)_InterlockedCompareExchange
  1723. #else
  1724. FORCEINLINE
  1725. LONG
  1726. FASTCALL
  1727. InterlockedCompareExchange(
  1728. IN OUT LONG volatile *Destination,
  1729. IN LONG Exchange,
  1730. IN LONG Comperand
  1731. )
  1732. {
  1733. __asm {
  1734. mov eax, Comperand
  1735. mov ecx, Destination
  1736. mov edx, Exchange
  1737. lock cmpxchg [ecx], edx
  1738. }
  1739. }
  1740. #endif
  1741. #define InterlockedCompareExchangePointer(Destination, ExChange, Comperand) \
  1742. (PVOID)InterlockedCompareExchange((PLONG)Destination, (LONG)ExChange, (LONG)Comperand)
  1743. #define InterlockedCompareExchange64(Destination, ExChange, Comperand) \
  1744. ExfInterlockedCompareExchange64(Destination, &(ExChange), &(Comperand))
  1745. NTKERNELAPI
  1746. LONGLONG
  1747. FASTCALL
  1748. ExfInterlockedCompareExchange64(
  1749. IN OUT LONGLONG volatile *Destination,
  1750. IN PLONGLONG ExChange,
  1751. IN PLONGLONG Comperand
  1752. );
  1753. // end_ntosp end_ntddk end_nthal
  1754. #endif // NT_UP
  1755. // begin_ntddk begin_nthal begin_ntosp
  1756. #endif // INTERLOCKED_INTRINSICS || _CROSS_PLATFORM_
  1757. // begin_wdm
  1758. #endif // MIDL_PASS
  1759. // end_ntosp end_ntddk end_nthal
  1760. #pragma warning(default:4035)
  1761. // end_wdm
  1762. #endif // _M_IX86 && !CROSS_PLATFORM
  1763. // begin_ntddk begin_nthal begin_ntosp
  1764. #endif // __WINBASE__ && !NONTOSPINTERLOCK
  1765. // end_ntosp end_ntddk end_nthal
  1766. // begin_nthal begin_ntddk
  1767. //
  1768. // Turn these instrinsics off until the compiler can handle them
  1769. //
  1770. #if (_MSC_FULL_VER > 13009037)
  1771. LONG
  1772. _InterlockedOr (
  1773. IN OUT PLONG Target,
  1774. IN LONG Set
  1775. );
  1776. #pragma intrinsic (_InterlockedOr)
  1777. #define InterlockedOr _InterlockedOr
  1778. LONG
  1779. _InterlockedAnd (
  1780. IN OUT LONG volatile *Target,
  1781. IN LONG Set
  1782. );
  1783. #pragma intrinsic (_InterlockedAnd)
  1784. #define InterlockedAnd _InterlockedAnd
  1785. LONG
  1786. _InterlockedXor (
  1787. IN OUT LONG volatile Target,
  1788. IN LONG Set
  1789. );
  1790. #pragma intrinsic (_InterlockedXor)
  1791. #define InterlockedXor _InterlockedXor
  1792. #else // compiler version
  1793. FORCEINLINE
  1794. LONG
  1795. InterlockedAnd (
  1796. IN OUT LONG volatile *Target,
  1797. LONG Set
  1798. )
  1799. {
  1800. LONG i;
  1801. LONG j;
  1802. j = *Target;
  1803. do {
  1804. i = j;
  1805. j = InterlockedCompareExchange(Target,
  1806. i & Set,
  1807. i);
  1808. } while (i != j);
  1809. return j;
  1810. }
  1811. FORCEINLINE
  1812. LONG
  1813. InterlockedOr (
  1814. IN OUT LONG volatile *Target,
  1815. IN LONG Set
  1816. )
  1817. {
  1818. LONG i;
  1819. LONG j;
  1820. j = *Target;
  1821. do {
  1822. i = j;
  1823. j = InterlockedCompareExchange(Target,
  1824. i | Set,
  1825. i);
  1826. } while (i != j);
  1827. return j;
  1828. }
  1829. #endif // compiler version
  1830. // end_nthal end_ntddk
  1831. //
  1832. // Structure for Ldt information in x86 processes
  1833. //
  1834. typedef struct _LDTINFORMATION {
  1835. ULONG Size;
  1836. ULONG AllocatedSize;
  1837. PLDT_ENTRY Ldt;
  1838. } LDTINFORMATION, *PLDTINFORMATION;
  1839. //
  1840. // SetProcessInformation Structure for ProcessSetIoHandlers info class
  1841. //
  1842. // begin_ntosp
  1843. typedef struct _PROCESS_IO_PORT_HANDLER_INFORMATION {
  1844. BOOLEAN Install; // true if handlers to be installed
  1845. ULONG NumEntries;
  1846. ULONG Context;
  1847. PEMULATOR_ACCESS_ENTRY EmulatorAccessEntries;
  1848. } PROCESS_IO_PORT_HANDLER_INFORMATION, *PPROCESS_IO_PORT_HANDLER_INFORMATION;
  1849. //
  1850. // Vdm Objects and Io handling structure
  1851. //
  1852. typedef struct _VDM_IO_HANDLER_FUNCTIONS {
  1853. PDRIVER_IO_PORT_ULONG UlongIo;
  1854. PDRIVER_IO_PORT_ULONG_STRING UlongStringIo;
  1855. PDRIVER_IO_PORT_USHORT UshortIo[2];
  1856. PDRIVER_IO_PORT_USHORT_STRING UshortStringIo[2];
  1857. PDRIVER_IO_PORT_UCHAR UcharIo[4];
  1858. PDRIVER_IO_PORT_UCHAR_STRING UcharStringIo[4];
  1859. } VDM_IO_HANDLER_FUNCTIONS, *PVDM_IO_HANDLER_FUNCTIONS;
  1860. typedef struct _VDM_IO_HANDLER {
  1861. struct _VDM_IO_HANDLER *Next;
  1862. ULONG PortNumber;
  1863. VDM_IO_HANDLER_FUNCTIONS IoFunctions[2];
  1864. } VDM_IO_HANDLER, *PVDM_IO_HANDLER;
  1865. // begin_nthal begin_ntddk begin_wdm
  1866. #if !defined(MIDL_PASS) && defined(_M_IX86)
  1867. //
  1868. // i386 function definitions
  1869. //
  1870. #pragma warning(disable:4035) // re-enable below
  1871. // end_wdm
  1872. #if NT_UP
  1873. #define _PCR ds:[KIP0PCRADDRESS]
  1874. #else
  1875. #define _PCR fs:[0]
  1876. #endif
  1877. // end_ntddk end_ntosp
  1878. //
  1879. // Get address of current processor block.
  1880. //
  1881. // WARNING: This inline macro can only be used by the kernel or hal
  1882. //
  1883. #define KiPcr() KeGetPcr()
  1884. FORCEINLINE
  1885. PKPCR
  1886. NTAPI
  1887. KeGetPcr(VOID)
  1888. {
  1889. #if NT_UP
  1890. __asm { mov eax, KIP0PCRADDRESS }
  1891. #else
  1892. __asm { mov eax, _PCR KPCR.SelfPcr }
  1893. #endif
  1894. }
  1895. // begin_ntosp
  1896. //
  1897. // Get address of current processor block.
  1898. //
  1899. // WARNING: This inline macro can only be used by the kernel or hal
  1900. //
  1901. FORCEINLINE
  1902. PKPRCB
  1903. NTAPI
  1904. KeGetCurrentPrcb (VOID)
  1905. {
  1906. __asm { mov eax, _PCR KPCR.Prcb }
  1907. }
  1908. // begin_ntddk begin_wdm
  1909. //
  1910. // Get current IRQL.
  1911. //
  1912. // On x86 this function resides in the HAL
  1913. //
  1914. NTHALAPI
  1915. KIRQL
  1916. NTAPI
  1917. KeGetCurrentIrql();
  1918. // end_wdm
  1919. //
  1920. // Get the current processor number
  1921. //
  1922. FORCEINLINE
  1923. ULONG
  1924. NTAPI
  1925. KeGetCurrentProcessorNumber(VOID)
  1926. {
  1927. __asm { movzx eax, _PCR KPCR.Number }
  1928. }
  1929. // end_nthal end_ntddk end_ntosp
  1930. //
  1931. // Get address of current kernel thread object.
  1932. //
  1933. // WARNING: This inline macro can not be used for device drivers or HALs
  1934. // they must call the kernel function KeGetCurrentThread.
  1935. // WARNING: This inline macro is always MP enabled because filesystems
  1936. // utilize it
  1937. //
  1938. //
  1939. FORCEINLINE
  1940. struct _KTHREAD *
  1941. NTAPI KeGetCurrentThread (VOID)
  1942. {
  1943. __asm { mov eax, fs:[0] KPCR.PrcbData.CurrentThread }
  1944. }
  1945. //
  1946. // If processor executing DPC?
  1947. // WARNING: This inline macro is always MP enabled because filesystems
  1948. // utilize it
  1949. //
  1950. FORCEINLINE
  1951. ULONG
  1952. NTAPI
  1953. KeIsExecutingDpc(VOID)
  1954. {
  1955. __asm { mov eax, fs:[0] KPCR.PrcbData.DpcRoutineActive }
  1956. }
  1957. // begin_nthal begin_ntddk begin_ntosp
  1958. #pragma warning(default:4035)
  1959. // begin_wdm
  1960. #endif // !defined(MIDL_PASS) && defined(_M_IX86)
  1961. // end_nthal end_ntddk end_wdm end_ntosp
  1962. //++
  1963. //
  1964. //
  1965. // VOID
  1966. // KeMemoryBarrier (
  1967. // VOID
  1968. // )
  1969. //
  1970. //
  1971. // Routine Description:
  1972. //
  1973. // This function cases ordering of memory acceses as seen by other processors.
  1974. // Memory ordering isn't an issue on x86.
  1975. //
  1976. //
  1977. // Arguments:
  1978. //
  1979. // None.
  1980. //
  1981. // Return Value:
  1982. //
  1983. // None.
  1984. //--
  1985. #define KeMemoryBarrier()
  1986. // begin_nthal
  1987. //
  1988. // Macro to set address of a trap/interrupt handler to IDT
  1989. //
  1990. #define KiSetHandlerAddressToIDT(Vector, HandlerAddress) {\
  1991. UCHAR IDTEntry = HalVectorToIDTEntry(Vector); \
  1992. ULONG Ha = (ULONG)HandlerAddress; \
  1993. KeGetPcr()->IDT[IDTEntry].ExtendedOffset = HIGHWORD(Ha); \
  1994. KeGetPcr()->IDT[IDTEntry].Offset = LOWWORD(Ha); \
  1995. }
  1996. //
  1997. // Macro to return address of a trap/interrupt handler in IDT
  1998. //
  1999. #define KiReturnHandlerAddressFromIDT(Vector) \
  2000. MAKEULONG(KiPcr()->IDT[HalVectorToIDTEntry(Vector)].ExtendedOffset, KiPcr()->IDT[HalVectorToIDTEntry(Vector)].Offset)
  2001. // end_nthal
  2002. //++
  2003. //
  2004. // BOOLEAN
  2005. // KiIsThreadNumericStateSaved(
  2006. // IN PKTHREAD Address
  2007. // )
  2008. //
  2009. //--
  2010. #define KiIsThreadNumericStateSaved(a) \
  2011. (a->NpxState != NPX_STATE_LOADED)
  2012. //++
  2013. //
  2014. // VOID
  2015. // KiRundownThread(
  2016. // IN PKTHREAD Address
  2017. // )
  2018. //
  2019. //--
  2020. #if defined(NT_UP)
  2021. //
  2022. // On UP x86 systems, FP state is lazy saved and loaded. If this
  2023. // thread owns the current FP context, clear the ownership field
  2024. // so we will not try to save to this thread after it has been
  2025. // terminated.
  2026. //
  2027. #define KiRundownThread(a) \
  2028. if (KeGetCurrentPrcb()->NpxThread == (a)) { \
  2029. KeGetCurrentPrcb()->NpxThread = NULL; \
  2030. }
  2031. #else
  2032. #define KiRundownThread(a)
  2033. #endif
  2034. //
  2035. // functions specific to 386 structure
  2036. //
  2037. VOID
  2038. NTAPI
  2039. KiSetIRR (
  2040. IN ULONG SWInterruptMask
  2041. );
  2042. //
  2043. // Procedures to support frame manipulation
  2044. //
  2045. ULONG
  2046. NTAPI
  2047. KiEspFromTrapFrame(
  2048. IN PKTRAP_FRAME TrapFrame
  2049. );
  2050. VOID
  2051. NTAPI
  2052. KiEspToTrapFrame(
  2053. IN PKTRAP_FRAME TrapFrame,
  2054. IN ULONG Esp
  2055. );
  2056. ULONG
  2057. NTAPI
  2058. KiSegSsFromTrapFrame(
  2059. IN PKTRAP_FRAME TrapFrame
  2060. );
  2061. VOID
  2062. NTAPI
  2063. KiSegSsToTrapFrame(
  2064. IN PKTRAP_FRAME TrapFrame,
  2065. IN ULONG SegSs
  2066. );
  2067. //
  2068. // Define prototypes for i386 specific clock and profile interrupt routines.
  2069. //
  2070. VOID
  2071. NTAPI
  2072. KiUpdateRunTime (
  2073. VOID
  2074. );
  2075. VOID
  2076. NTAPI
  2077. KiUpdateSystemTime (
  2078. VOID
  2079. );
  2080. // begin_ntddk begin_wdm begin_ntosp
  2081. NTKERNELAPI
  2082. NTSTATUS
  2083. NTAPI
  2084. KeSaveFloatingPointState (
  2085. OUT PKFLOATING_SAVE FloatSave
  2086. );
  2087. NTKERNELAPI
  2088. NTSTATUS
  2089. NTAPI
  2090. KeRestoreFloatingPointState (
  2091. IN PKFLOATING_SAVE FloatSave
  2092. );
  2093. // end_ntddk end_wdm
  2094. // begin_nthal
  2095. NTKERNELAPI
  2096. VOID
  2097. NTAPI
  2098. KeProfileInterruptWithSource (
  2099. IN struct _KTRAP_FRAME *TrapFrame,
  2100. IN KPROFILE_SOURCE ProfileSource
  2101. );
  2102. // end_ntosp
  2103. VOID
  2104. NTAPI
  2105. KeProfileInterrupt (
  2106. IN KIRQL OldIrql,
  2107. IN KTRAP_FRAME TrapFrame
  2108. );
  2109. VOID
  2110. NTAPI
  2111. KeUpdateRuntime (
  2112. IN KIRQL OldIrql,
  2113. IN KTRAP_FRAME TrapFrame
  2114. );
  2115. VOID
  2116. NTAPI
  2117. KeUpdateSystemTime (
  2118. IN KIRQL OldIrql,
  2119. IN KTRAP_FRAME TrapFrame
  2120. );
  2121. // begin_ntddk begin_wdm begin_ntndis begin_ntosp
  2122. #endif // defined(_X86_)
  2123. // end_nthal end_ntddk end_wdm end_ntndis end_ntosp
  2124. // begin_nthal begin_ntddk
  2125. // Use the following for kernel mode runtime checks of X86 system architecture
  2126. #ifdef _X86_
  2127. #ifdef IsNEC_98
  2128. #undef IsNEC_98
  2129. #endif
  2130. #ifdef IsNotNEC_98
  2131. #undef IsNotNEC_98
  2132. #endif
  2133. #ifdef SetNEC_98
  2134. #undef SetNEC_98
  2135. #endif
  2136. #ifdef SetNotNEC_98
  2137. #undef SetNotNEC_98
  2138. #endif
  2139. #define IsNEC_98 (SharedUserData->AlternativeArchitecture == NEC98x86)
  2140. #define IsNotNEC_98 (SharedUserData->AlternativeArchitecture != NEC98x86)
  2141. #define SetNEC_98 SharedUserData->AlternativeArchitecture = NEC98x86
  2142. #define SetNotNEC_98 SharedUserData->AlternativeArchitecture = StandardDesign
  2143. #endif
  2144. // end_nthal end_ntddk
  2145. //
  2146. // i386 arch. specific kernel functions.
  2147. //
  2148. // begin_ntosp
  2149. #ifdef _X86_
  2150. VOID
  2151. NTAPI
  2152. Ke386SetLdtProcess (
  2153. struct _KPROCESS *Process,
  2154. PLDT_ENTRY Ldt,
  2155. ULONG Limit
  2156. );
  2157. VOID
  2158. NTAPI
  2159. Ke386SetDescriptorProcess (
  2160. struct _KPROCESS *Process,
  2161. ULONG Offset,
  2162. LDT_ENTRY LdtEntry
  2163. );
  2164. VOID
  2165. NTAPI
  2166. Ke386GetGdtEntryThread (
  2167. struct _KTHREAD *Thread,
  2168. ULONG Offset,
  2169. PKGDTENTRY Descriptor
  2170. );
  2171. BOOLEAN
  2172. NTAPI
  2173. Ke386SetIoAccessMap (
  2174. ULONG MapNumber,
  2175. PKIO_ACCESS_MAP IoAccessMap
  2176. );
  2177. BOOLEAN
  2178. NTAPI
  2179. Ke386QueryIoAccessMap (
  2180. ULONG MapNumber,
  2181. PKIO_ACCESS_MAP IoAccessMap
  2182. );
  2183. BOOLEAN
  2184. NTAPI
  2185. Ke386IoSetAccessProcess (
  2186. struct _KPROCESS *Process,
  2187. ULONG MapNumber
  2188. );
  2189. VOID
  2190. NTAPI
  2191. Ke386SetIOPL(
  2192. struct _KPROCESS *Process
  2193. );
  2194. NTSTATUS
  2195. NTAPI
  2196. Ke386CallBios (
  2197. IN ULONG BiosCommand,
  2198. IN OUT PCONTEXT BiosArguments
  2199. );
  2200. VOID
  2201. NTAPI
  2202. KiEditIopmDpc (
  2203. IN struct _KDPC *Dpc,
  2204. IN PVOID DeferredContext,
  2205. IN PVOID SystemArgument1,
  2206. IN PVOID SystemArgument2
  2207. );
  2208. BOOLEAN
  2209. NTAPI
  2210. Ki386GetSelectorParameters(
  2211. IN USHORT Selector,
  2212. OUT PULONG Flags,
  2213. OUT PULONG Base,
  2214. OUT PULONG Limit
  2215. );
  2216. ULONG
  2217. Ki386DispatchOpcodeV86 (
  2218. IN PKTRAP_FRAME TrapFrame
  2219. );
  2220. NTSTATUS
  2221. NTAPI
  2222. Ke386SetVdmInterruptHandler (
  2223. IN struct _KPROCESS *Process,
  2224. IN ULONG Interrupt,
  2225. IN USHORT Selector,
  2226. IN ULONG Offset,
  2227. IN BOOLEAN Gate32
  2228. );
  2229. #endif //_X86_
  2230. // end_ntosp
  2231. //
  2232. // i386 ABIOS specific routines.
  2233. //
  2234. NTSTATUS
  2235. NTAPI
  2236. KeI386GetLid(
  2237. IN USHORT DeviceId,
  2238. IN USHORT RelativeLid,
  2239. IN BOOLEAN SharedLid,
  2240. IN struct _DRIVER_OBJECT *DeviceObject,
  2241. OUT PUSHORT LogicalId
  2242. );
  2243. NTSTATUS
  2244. NTAPI
  2245. KeI386ReleaseLid(
  2246. IN USHORT LogicalId,
  2247. IN struct _DRIVER_OBJECT *DeviceObject
  2248. );
  2249. NTSTATUS
  2250. NTAPI
  2251. KeI386AbiosCall(
  2252. IN USHORT LogicalId,
  2253. IN struct _DRIVER_OBJECT *DriverObject,
  2254. IN PUCHAR RequestBlock,
  2255. IN USHORT EntryPoint
  2256. );
  2257. //
  2258. // i386 misc routines
  2259. //
  2260. NTSTATUS
  2261. NTAPI
  2262. KeI386AllocateGdtSelectors(
  2263. OUT PUSHORT SelectorArray,
  2264. IN USHORT NumberOfSelectors
  2265. );
  2266. VOID
  2267. NTAPI
  2268. KeI386Call16BitFunction (
  2269. IN OUT PCONTEXT Regs
  2270. );
  2271. USHORT
  2272. NTAPI
  2273. KeI386Call16BitCStyleFunction (
  2274. IN ULONG EntryOffset,
  2275. IN ULONG EntrySelector,
  2276. IN PUCHAR Parameters,
  2277. IN ULONG Size
  2278. );
  2279. NTSTATUS
  2280. NTAPI
  2281. KeI386FlatToGdtSelector(
  2282. IN ULONG SelectorBase,
  2283. IN USHORT Length,
  2284. IN USHORT Selector
  2285. );
  2286. NTSTATUS
  2287. NTAPI
  2288. KeI386ReleaseGdtSelectors(
  2289. OUT PUSHORT SelectorArray,
  2290. IN USHORT NumberOfSelectors
  2291. );
  2292. NTSTATUS
  2293. NTAPI
  2294. KeI386SetGdtSelector (
  2295. ULONG Selector,
  2296. PKGDTENTRY GdtValue
  2297. );
  2298. VOID
  2299. NTAPI
  2300. KeOptimizeProcessorControlState (
  2301. VOID
  2302. );
  2303. //
  2304. // Vdm specific functions.
  2305. //
  2306. BOOLEAN
  2307. NTAPI
  2308. KeVdmInsertQueueApc (
  2309. IN PKAPC Apc,
  2310. IN struct _KTHREAD *Thread,
  2311. IN KPROCESSOR_MODE ApcMode,
  2312. IN PKKERNEL_ROUTINE KernelRoutine,
  2313. IN PKRUNDOWN_ROUTINE RundownRoutine OPTIONAL,
  2314. IN PKNORMAL_ROUTINE NormalRoutine OPTIONAL,
  2315. IN PVOID NormalContext OPTIONAL,
  2316. IN KPRIORITY Increment
  2317. );
  2318. FORCEINLINE
  2319. VOID
  2320. NTAPI
  2321. KeVdmClearApcThreadAddress (
  2322. IN PKAPC Apc
  2323. )
  2324. {
  2325. if (Apc->Inserted == FALSE) {
  2326. Apc->Thread = NULL;
  2327. }
  2328. }
  2329. VOID
  2330. NTAPI
  2331. KeI386VdmInitialize (
  2332. VOID
  2333. );
  2334. //
  2335. // x86 functions for special instructions
  2336. //
  2337. VOID
  2338. NTAPI
  2339. CPUID (
  2340. ULONG InEax,
  2341. PULONG OutEax,
  2342. PULONG OutEbx,
  2343. PULONG OutEcx,
  2344. PULONG OutEdx
  2345. );
  2346. LONGLONG
  2347. NTAPI
  2348. RDTSC (
  2349. VOID
  2350. );
  2351. ULONGLONG
  2352. FASTCALL
  2353. RDMSR (
  2354. IN ULONG MsrRegister
  2355. );
  2356. VOID
  2357. NTAPI
  2358. WRMSR (
  2359. IN ULONG MsrRegister,
  2360. IN ULONGLONG MsrValue
  2361. );
  2362. //
  2363. // i386 Vdm specific data
  2364. //
  2365. extern ULONG KeI386EFlagsAndMaskV86;
  2366. extern ULONG KeI386EFlagsOrMaskV86;
  2367. extern BOOLEAN KeI386VdmIoplAllowed;
  2368. extern ULONG KeI386VirtualIntExtensions;
  2369. extern ULONG KeI386CpuType;
  2370. extern ULONG KeI386CpuStep;
  2371. extern BOOLEAN KeI386NpxPresent;
  2372. extern BOOLEAN KeI386FxsrPresent;
  2373. //
  2374. // i386 Feature bit definitions
  2375. //
  2376. #define KF_V86_VIS 0x00000001
  2377. #define KF_RDTSC 0x00000002
  2378. #define KF_CR4 0x00000004
  2379. #define KF_CMOV 0x00000008
  2380. #define KF_GLOBAL_PAGE 0x00000010
  2381. #define KF_LARGE_PAGE 0x00000020
  2382. #define KF_MTRR 0x00000040
  2383. #define KF_CMPXCHG8B 0x00000080
  2384. #define KF_MMX 0x00000100
  2385. #define KF_WORKING_PTE 0x00000200
  2386. #define KF_PAT 0x00000400
  2387. #define KF_FXSR 0x00000800
  2388. #define KF_FAST_SYSCALL 0x00001000
  2389. #define KF_XMMI 0x00002000
  2390. #define KF_3DNOW 0x00004000
  2391. #define KF_AMDK6MTRR 0x00008000
  2392. #define KF_XMMI64 0x00010000
  2393. #define KF_DTS 0x00020000
  2394. #define KF_SMT 0x00040000
  2395. //
  2396. // Define macro to test if x86 feature is present.
  2397. //
  2398. extern ULONG KiBootFeatureBits;
  2399. #define Isx86FeaturePresent(_f_) ((KiBootFeatureBits & (_f_)) != 0)
  2400. #endif // _i386_