[KMTESTS]
[reactos.git] / kmtests / ntos_ke / KeIrql.c
1 /*
2 * PROJECT: ReactOS kernel-mode tests
3 * LICENSE: GPLv2+ - See COPYING in the top level directory
4 * PURPOSE: Kernel-Mode Test Suite Interrupt Request Level test
5 * PROGRAMMER: Thomas Faber <thfabba@gmx.de>
6 */
7
8 __declspec(dllimport) void __stdcall KeRaiseIrql(unsigned char, unsigned char *);
9 __declspec(dllimport) void __stdcall KeLowerIrql(unsigned char);
10
11 #include <ntddk.h>
12 #include <ntifs.h>
13 #include <ndk/ntndk.h>
14 #include <kmt_test.h>
15 #include <pseh/pseh2.h>
16
17 #define NDEBUG
18 #include <debug.h>
19
20 START_TEST(KeIrql)
21 {
22 KIRQL Irql, Irql2, PrevIrql, SynchIrql;
23
24 /* we should be called at PASSIVE_LEVEL */
25 ok_irql(PASSIVE_LEVEL);
26
27 PrevIrql = KeGetCurrentIrql();
28
29 /* SYNCH_LEVEL is different for UP/MP */
30 if (KmtIsMultiProcessorBuild)
31 SynchIrql = IPI_LEVEL - 2;
32 else
33 SynchIrql = DISPATCH_LEVEL;
34
35 /* some Irqls MUST work */
36 {
37 const KIRQL Irqls[] = { LOW_LEVEL, PASSIVE_LEVEL, APC_LEVEL, DISPATCH_LEVEL,
38 CMCI_LEVEL, CLOCK1_LEVEL, CLOCK2_LEVEL, CLOCK_LEVEL,
39 PROFILE_LEVEL, IPI_LEVEL, /*POWER_LEVEL,*/ SynchIrql, HIGH_LEVEL };
40 int i;
41 for (i = 0; i < sizeof Irqls / sizeof Irqls[0]; ++i)
42 {
43 KeRaiseIrql(Irqls[i], &Irql2);
44 ok_eq_uint(Irql2, PrevIrql);
45 ok_irql(Irqls[i]);
46 KeLowerIrql(Irql2);
47 ok_irql(PrevIrql);
48 }
49 }
50
51 /* raising/lowering to the current level should have no effect */
52 ok_irql(PASSIVE_LEVEL);
53 KeRaiseIrql(PASSIVE_LEVEL, &Irql);
54 ok_eq_uint(Irql, PASSIVE_LEVEL);
55 KeLowerIrql(PASSIVE_LEVEL);
56 ok_irql(PASSIVE_LEVEL);
57
58 /* try to raise to each Irql and back */
59 for (Irql = PASSIVE_LEVEL; Irql <= HIGH_LEVEL; ++Irql)
60 {
61 DPRINT("Raising to %u\n", Irql);
62 KeRaiseIrql(Irql, &Irql2);
63 ok_eq_uint(Irql2, PrevIrql);
64 KeLowerIrql(Irql2);
65 ok_irql(PrevIrql);
66 }
67
68 /* go through all Irqls in order, skip the ones that the system doesn't accept */
69 for (Irql = PASSIVE_LEVEL; Irql <= HIGH_LEVEL; ++Irql)
70 {
71 DPRINT("Raising to %u\n", Irql);
72 KeRaiseIrql(Irql, &Irql2);
73 ok_eq_uint(Irql2, PrevIrql);
74 Irql2 = KeGetCurrentIrql();
75 ok(Irql2 <= Irql, "New Irql is %u, expected <= requested value of %u\n", Irql2, Irql);
76 PrevIrql = Irql2;
77 }
78
79 ok_irql(HIGH_LEVEL);
80
81 /* now go back again, skipping the ones that don't work */
82 for (Irql = HIGH_LEVEL; Irql > PASSIVE_LEVEL;)
83 {
84 DPRINT("Lowering to %u\n", Irql - 1);
85 KeLowerIrql(Irql - 1);
86 Irql2 = KeGetCurrentIrql();
87 ok(Irql2 < Irql, "New Irql is %u, expected <= requested value of %u\n", Irql2, Irql - 1);
88 if (Irql2 < Irql)
89 Irql = Irql2;
90 else
91 --Irql;
92 }
93
94 DPRINT("Alive!\n");
95 /* on x86, you can raise to _any_ possible KIRQL value */
96 /* on x64, anything with more than the least significant 4 bits set bugchecked, last time I tried */
97 /* TODO: other platforms? */
98 #if defined _M_X86
99 for (Irql = PASSIVE_LEVEL; Irql <= (KIRQL)-1; ++Irql)
100 {
101 DPRINT("Raising to %u\n", Irql);
102 KeRaiseIrql(Irql, &Irql2);
103 ok_eq_uint(Irql2, PrevIrql);
104 KeLowerIrql(Irql2);
105 ok_irql(PrevIrql);
106 }
107 #endif /* defined _M_X86 */
108
109 /* test KeRaiseIrqlToDpcLevel */
110 ok_irql(PASSIVE_LEVEL);
111 Irql = KeRaiseIrqlToDpcLevel();
112 ok_irql(DISPATCH_LEVEL);
113 ok_eq_uint(Irql, PASSIVE_LEVEL);
114 Irql = KeRaiseIrqlToDpcLevel();
115 ok_irql(DISPATCH_LEVEL);
116 ok_eq_uint(Irql, DISPATCH_LEVEL);
117 KeLowerIrql(PASSIVE_LEVEL);
118
119 /* test KeRaiseIrqlToSynchLevel */
120 ok_irql(PASSIVE_LEVEL);
121 Irql = KeRaiseIrqlToSynchLevel();
122 ok_irql(SynchIrql);
123 ok_eq_uint(Irql, PASSIVE_LEVEL);
124 Irql = KeRaiseIrqlToSynchLevel();
125 ok_irql(SynchIrql);
126 ok_eq_uint(Irql, SynchIrql);
127 KeLowerIrql(PASSIVE_LEVEL);
128
129 /* these bugcheck on a checked build but run fine on free! */
130 if (!KmtIsCheckedBuild)
131 {
132 KeRaiseIrql(HIGH_LEVEL, &Irql);
133 KeRaiseIrql(APC_LEVEL, &Irql);
134 ok_irql(APC_LEVEL);
135 KeLowerIrql(HIGH_LEVEL);
136 ok_irql(HIGH_LEVEL);
137 KeLowerIrql(PASSIVE_LEVEL);
138 }
139
140 /* try the actual exports, not only the fastcall versions */
141 ok_irql(PASSIVE_LEVEL);
142 (KeRaiseIrql)(HIGH_LEVEL, &Irql);
143 ok_irql(HIGH_LEVEL);
144 ok_eq_uint(Irql, PASSIVE_LEVEL);
145 (KeLowerIrql)(Irql);
146 ok_irql(PASSIVE_LEVEL);
147
148 /* make sure we exit gracefully */
149 ok_irql(PASSIVE_LEVEL);
150 KeLowerIrql(PASSIVE_LEVEL);
151 }