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