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