[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 (KeGetCurrentPrcb()->BuildType & PRCB_BUILD_UNIPROCESSOR)
28 {
29 trace("This is a Uniprocessor kernel\n");
30 SynchIrql = DISPATCH_LEVEL;
31 }
32 else
33 {
34 trace("This is a Multiprocessor kernel\n");
35 SynchIrql = IPI_LEVEL - 2;
36 }
37
38 /* some Irqls MUST work */
39 {
40 const KIRQL Irqls[] = { LOW_LEVEL, PASSIVE_LEVEL, APC_LEVEL, DISPATCH_LEVEL,
41 CMCI_LEVEL, CLOCK1_LEVEL, CLOCK2_LEVEL, CLOCK_LEVEL,
42 PROFILE_LEVEL, IPI_LEVEL, /*POWER_LEVEL,*/ SynchIrql, HIGH_LEVEL };
43 int i;
44 for (i = 0; i < sizeof Irqls / sizeof Irqls[0]; ++i)
45 {
46 KeRaiseIrql(Irqls[i], &Irql2);
47 ok_eq_uint(Irql2, PrevIrql);
48 ok_irql(Irqls[i]);
49 KeLowerIrql(Irql2);
50 ok_irql(PrevIrql);
51 }
52 }
53
54 /* raising/lowering to the current level should have no effect */
55 ok_irql(PASSIVE_LEVEL);
56 KeRaiseIrql(PASSIVE_LEVEL, &Irql);
57 ok_eq_uint(Irql, PASSIVE_LEVEL);
58 KeLowerIrql(PASSIVE_LEVEL);
59 ok_irql(PASSIVE_LEVEL);
60
61 /* try to raise to each Irql and back */
62 for (Irql = PASSIVE_LEVEL; Irql <= HIGH_LEVEL; ++Irql)
63 {
64 DPRINT("Raising to %u\n", Irql);
65 KeRaiseIrql(Irql, &Irql2);
66 ok_eq_uint(Irql2, PrevIrql);
67 KeLowerIrql(Irql2);
68 ok_irql(PrevIrql);
69 }
70
71 /* go through all Irqls in order, skip the ones that the system doesn't accept */
72 for (Irql = PASSIVE_LEVEL; Irql <= HIGH_LEVEL; ++Irql)
73 {
74 DPRINT("Raising to %u\n", Irql);
75 KeRaiseIrql(Irql, &Irql2);
76 ok_eq_uint(Irql2, PrevIrql);
77 Irql2 = KeGetCurrentIrql();
78 ok(Irql2 <= Irql, "New Irql is %u, expected <= requested value of %u\n", Irql2, Irql);
79 PrevIrql = Irql2;
80 }
81
82 ok_irql(HIGH_LEVEL);
83
84 /* now go back again, skipping the ones that don't work */
85 for (Irql = HIGH_LEVEL; Irql > PASSIVE_LEVEL;)
86 {
87 DPRINT("Lowering to %u\n", Irql - 1);
88 KeLowerIrql(Irql - 1);
89 Irql2 = KeGetCurrentIrql();
90 ok(Irql2 < Irql, "New Irql is %u, expected <= requested value of %u\n", Irql2, Irql - 1);
91 if (Irql2 < Irql)
92 Irql = Irql2;
93 else
94 --Irql;
95 }
96
97 DPRINT("Alive!\n");
98 /* on x86, you can raise to _any_ possible KIRQL value */
99 /* on x64, anything with more than the least significant 4 bits set bugchecked, last time I tried */
100 /* TODO: other platforms? */
101 #if defined _M_X86
102 for (Irql = PASSIVE_LEVEL; Irql <= (KIRQL)-1; ++Irql)
103 {
104 DPRINT("Raising to %u\n", Irql);
105 KeRaiseIrql(Irql, &Irql2);
106 ok_eq_uint(Irql2, PrevIrql);
107 KeLowerIrql(Irql2);
108 ok_irql(PrevIrql);
109 }
110 #endif /* defined _M_X86 */
111
112 /* test KeRaiseIrqlToDpcLevel */
113 ok_irql(PASSIVE_LEVEL);
114 Irql = KeRaiseIrqlToDpcLevel();
115 ok_irql(DISPATCH_LEVEL);
116 ok_eq_uint(Irql, PASSIVE_LEVEL);
117 Irql = KeRaiseIrqlToDpcLevel();
118 ok_irql(DISPATCH_LEVEL);
119 ok_eq_uint(Irql, DISPATCH_LEVEL);
120 KeLowerIrql(PASSIVE_LEVEL);
121
122 /* test KeRaiseIrqlToSynchLevel */
123 ok_irql(PASSIVE_LEVEL);
124 Irql = KeRaiseIrqlToSynchLevel();
125 ok_irql(SynchIrql);
126 ok_eq_uint(Irql, PASSIVE_LEVEL);
127 Irql = KeRaiseIrqlToSynchLevel();
128 ok_irql(SynchIrql);
129 ok_eq_uint(Irql, SynchIrql);
130 KeLowerIrql(PASSIVE_LEVEL);
131
132 /* make sure we exit gracefully */
133 ok_irql(PASSIVE_LEVEL);
134 KeLowerIrql(PASSIVE_LEVEL);
135 }