Author: tfaber Date: Fri Jul 8 06:38:01 2011 New Revision: 52567
URL: http://svn.reactos.org/svn/reactos?rev=52567&view=rev Log: [KMTESTS/KE] - add a test for DPCs - add a test for IRQ levels
Added: branches/GSoC_2011/KMTestSuite/kmtests/ntos_ke/KeDpc.c (with props) branches/GSoC_2011/KMTestSuite/kmtests/ntos_ke/KeIrql.c (with props) Modified: branches/GSoC_2011/KMTestSuite/kmtests/CMakeLists.txt branches/GSoC_2011/KMTestSuite/kmtests/kmtest_drv.rbuild branches/GSoC_2011/KMTestSuite/kmtests/kmtest_drv/testlist.c
Modified: branches/GSoC_2011/KMTestSuite/kmtests/CMakeLists.txt URL: http://svn.reactos.org/svn/reactos/branches/GSoC_2011/KMTestSuite/kmtests/CM... ============================================================================== --- branches/GSoC_2011/KMTestSuite/kmtests/CMakeLists.txt [iso-8859-1] (original) +++ branches/GSoC_2011/KMTestSuite/kmtests/CMakeLists.txt [iso-8859-1] Fri Jul 8 06:38:01 2011 @@ -4,7 +4,7 @@ # # subdirectories containing special-purpose drivers # -add_subdirectory(Example) +add_subdirectory(example)
# # kmtest_drv.sys driver @@ -20,6 +20,8 @@ ntos_io/IoDeviceInterface.c ntos_io/IoIrp.c ntos_io/IoMdl.c + ntos_ke/KeDpc.c + ntos_ke/KeIrql.c ntos_ke/KeProcessor.c ntos_ob/ObCreate.c
Modified: branches/GSoC_2011/KMTestSuite/kmtests/kmtest_drv.rbuild URL: http://svn.reactos.org/svn/reactos/branches/GSoC_2011/KMTestSuite/kmtests/km... ============================================================================== --- branches/GSoC_2011/KMTestSuite/kmtests/kmtest_drv.rbuild [iso-8859-1] (original) +++ branches/GSoC_2011/KMTestSuite/kmtests/kmtest_drv.rbuild [iso-8859-1] Fri Jul 8 06:38:01 2011 @@ -25,6 +25,8 @@ <file>IoMdl.c</file> </directory> <directory name="ntos_ke"> + <file>KeDpc.c</file> + <file>KeIrql.c</file> <file>KeProcessor.c</file> </directory> <directory name="ntos_ob">
Modified: branches/GSoC_2011/KMTestSuite/kmtests/kmtest_drv/testlist.c URL: http://svn.reactos.org/svn/reactos/branches/GSoC_2011/KMTestSuite/kmtests/km... ============================================================================== --- branches/GSoC_2011/KMTestSuite/kmtests/kmtest_drv/testlist.c [iso-8859-1] (original) +++ branches/GSoC_2011/KMTestSuite/kmtests/kmtest_drv/testlist.c [iso-8859-1] Fri Jul 8 06:38:01 2011 @@ -15,6 +15,8 @@ KMT_TESTFUNC Test_IoDeviceInterface; KMT_TESTFUNC Test_IoIrp; KMT_TESTFUNC Test_IoMdl; +KMT_TESTFUNC Test_KeDpc; +KMT_TESTFUNC Test_KeIrql; KMT_TESTFUNC Test_KeProcessor; KMT_TESTFUNC Test_ObCreate;
@@ -27,6 +29,8 @@ { "IoDeviceInterface", Test_IoDeviceInterface }, { "IoIrp", Test_IoIrp }, { "IoMdl", Test_IoMdl }, + { "KeDpc", Test_KeDpc }, + { "KeIrql", Test_KeIrql }, { "KeProcessor", Test_KeProcessor }, { "ObCreate", Test_ObCreate }, { NULL, NULL }
Added: branches/GSoC_2011/KMTestSuite/kmtests/ntos_ke/KeDpc.c URL: http://svn.reactos.org/svn/reactos/branches/GSoC_2011/KMTestSuite/kmtests/nt... ============================================================================== --- branches/GSoC_2011/KMTestSuite/kmtests/ntos_ke/KeDpc.c (added) +++ branches/GSoC_2011/KMTestSuite/kmtests/ntos_ke/KeDpc.c [iso-8859-1] Fri Jul 8 06:38:01 2011 @@ -1,0 +1,185 @@ +/* + * PROJECT: ReactOS kernel-mode tests + * LICENSE: GPLv2+ - See COPYING in the top level directory + * PURPOSE: Kernel-Mode Test Suite Deferred Procedure Call test + * PROGRAMMER: Thomas Faber thfabba@gmx.de + */ + +#include <ntddk.h> +#include <ntifs.h> +#include <ndk/ketypes.h> +#include <kmt_test.h> +#include <pseh/pseh2.h> + +//#define NDEBUG +#include <debug.h> + +/* TODO: DPC importance */ + +static volatile LONG DpcCount = 0; +static volatile UCHAR DpcImportance = MediumImportance; + +static KDEFERRED_ROUTINE DpcHandler; + +static +VOID +NTAPI +DpcHandler( + IN PRKDPC Dpc, + IN PVOID DeferredContext, + IN PVOID SystemArgument1, + IN PVOID SystemArgument2) +{ + PKPCR Pcr = KeGetPcr(); + PKPRCB Prcb = Pcr->Prcb; + + ok_irql(DISPATCH_LEVEL); + InterlockedIncrement(&DpcCount); + ok(DeferredContext == Dpc, "DeferredContext = %p, Dpc = %p, expected equal\n", DeferredContext, Dpc); + ok_eq_pointer(SystemArgument1, (PVOID)0xabc123); + ok_eq_pointer(SystemArgument2, (PVOID)0x5678); + + /* KDPC object contents */ + ok_eq_uint(Dpc->Type, DpcObject); + ok_eq_uint(Dpc->Importance, DpcImportance); + ok_eq_uint(Dpc->Number, 0); + ok(Dpc->DpcListEntry.Blink != NULL, "\n"); + ok(Dpc->DpcListEntry.Blink != &Dpc->DpcListEntry, "\n"); + if (!skip(Dpc->DpcListEntry.Blink != NULL, "DpcListEntry.Blink == NULL\n")) + ok_eq_pointer(Dpc->DpcListEntry.Flink, Dpc->DpcListEntry.Blink->Flink); + + ok(Dpc->DpcListEntry.Flink != NULL, "\n"); + ok(Dpc->DpcListEntry.Flink != &Dpc->DpcListEntry, "\n"); + if (!skip(Dpc->DpcListEntry.Flink != NULL, "DpcListEntry.Flink == NULL\n")) + ok_eq_pointer(Dpc->DpcListEntry.Blink, Dpc->DpcListEntry.Flink->Blink); + + ok_eq_pointer(Dpc->DeferredRoutine, DpcHandler); + ok_eq_pointer(Dpc->DeferredContext, DeferredContext); + ok_eq_pointer(Dpc->SystemArgument1, SystemArgument1); + ok_eq_pointer(Dpc->SystemArgument2, SystemArgument2); + ok_eq_pointer(Dpc->DpcData, NULL); + + ok_eq_uint(Prcb->DpcRoutineActive, 1); + /* this DPC is not in the list anymore, but it was at the head! */ + ok_eq_pointer(Prcb->DpcData[DPC_NORMAL].DpcListHead.Flink, Dpc->DpcListEntry.Flink); + ok_eq_pointer(Prcb->DpcData[DPC_NORMAL].DpcListHead.Blink, Dpc->DpcListEntry.Blink); +} + +START_TEST(KeDpc) +{ + NTSTATUS Status = STATUS_SUCCESS; + KDPC Dpc; + KIRQL Irql, Irql2, Irql3; + LONG ExpectedDpcCount = 0; + BOOLEAN Ret; + int i; + +#define ok_dpccount() ok(DpcCount == ExpectedDpcCount, "DpcCount = %ld, expected %ld\n", DpcCount, ExpectedDpcCount); + trace("Dpc = %p\n", &Dpc); + memset(&Dpc, 0x55, sizeof Dpc); + KeInitializeDpc(&Dpc, DpcHandler, &Dpc); + /* check the Dpc object's fields */ + ok_eq_uint(Dpc.Type, DpcObject); + ok_eq_uint(Dpc.Importance, DpcImportance); + ok_eq_uint(Dpc.Number, 0); + ok_eq_pointer(Dpc.DpcListEntry.Flink, (LIST_ENTRY *)0x5555555555555555); + ok_eq_pointer(Dpc.DpcListEntry.Blink, (LIST_ENTRY *)0x5555555555555555); + ok_eq_pointer(Dpc.DeferredRoutine, DpcHandler); + ok_eq_pointer(Dpc.DeferredContext, &Dpc); + ok_eq_pointer(Dpc.SystemArgument1, (PVOID)0x5555555555555555); + ok_eq_pointer(Dpc.SystemArgument2, (PVOID)0x5555555555555555); + ok_eq_pointer(Dpc.DpcData, NULL); + + /* simply run the Dpc a few times */ + for (i = 0; i < 5; ++i) + { + ok_dpccount(); + Ret = KeInsertQueueDpc(&Dpc, (PVOID)0xabc123, (PVOID)0x5678); + ok_bool_true(Ret, "KeInsertQueueDpc returned"); + ++ExpectedDpcCount; + ok_dpccount(); + } + + /* insert into queue at high irql + * -> should only run when lowered to APC_LEVEL, + * inserting a second time should fail + */ + KeRaiseIrql(APC_LEVEL, &Irql); + for (i = 0; i < 5; ++i) + { + KeRaiseIrql(DISPATCH_LEVEL, &Irql2); + ok_dpccount(); + Ret = KeInsertQueueDpc(&Dpc, (PVOID)0xabc123, (PVOID)0x5678); + ok_bool_true(Ret, "KeInsertQueueDpc returned"); + Ret = KeInsertQueueDpc(&Dpc, (PVOID)0xdef, (PVOID)0x123); + ok_bool_false(Ret, "KeInsertQueueDpc returned"); + ok_dpccount(); + KeRaiseIrql(HIGH_LEVEL, &Irql3); + ok_dpccount(); + KeLowerIrql(Irql3); + ok_dpccount(); + DPRINT1("This is a debug print\n"); + ok_dpccount(); + KeLowerIrql(Irql2); + ++ExpectedDpcCount; + ok_dpccount(); + } + KeLowerIrql(Irql); + + /* now test removing from the queue */ + KeRaiseIrql(APC_LEVEL, &Irql); + for (i = 0; i < 5; ++i) + { + KeRaiseIrql(DISPATCH_LEVEL, &Irql2); + ok_dpccount(); + Ret = KeRemoveQueueDpc(&Dpc); + ok_bool_false(Ret, "KeRemoveQueueDpc returned"); + Ret = KeInsertQueueDpc(&Dpc, (PVOID)0xabc123, (PVOID)0x5678); + ok_bool_true(Ret, "KeInsertQueueDpc returned"); + ok_dpccount(); + KeRaiseIrql(HIGH_LEVEL, &Irql3); + ok_dpccount(); + KeLowerIrql(Irql3); + ok_dpccount(); + Ret = KeRemoveQueueDpc(&Dpc); + ok_bool_true(Ret, "KeRemoveQueueDpc returned"); + KeLowerIrql(Irql2); + ok_dpccount(); + } + KeLowerIrql(Irql); + + /* parameter checks */ + Status = STATUS_SUCCESS; + _SEH2_TRY { + KeInitializeDpc(&Dpc, NULL, NULL); + } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { + Status = _SEH2_GetExceptionCode(); + } _SEH2_END; + ok_eq_hex(Status, STATUS_SUCCESS); + + if (!skip(Status == STATUS_SUCCESS, "KeInitializeDpc failed\n")) + { + KeRaiseIrql(HIGH_LEVEL, &Irql); + Ret = KeInsertQueueDpc(&Dpc, NULL, NULL); + ok_bool_true(Ret, "KeInsertQueueDpc returned"); + Ret = KeRemoveQueueDpc(&Dpc); + ok_bool_true(Ret, "KeRemoveQueueDpc returned"); + KeLowerIrql(Irql); + } + + Status = STATUS_SUCCESS; + _SEH2_TRY { + KeInitializeDpc(NULL, NULL, NULL); + } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { + Status = _SEH2_GetExceptionCode(); + } _SEH2_END; + ok_eq_hex(Status, STATUS_ACCESS_VIOLATION); + + /* These result in IRQL_NOT_LESS_OR_EQUAL on 2k3 -- IRQLs 0x1f and 0xff (?) + Ret = KeInsertQueueDpc(NULL, NULL, NULL); + Ret = KeRemoveQueueDpc(NULL);*/ + + ok_dpccount(); + ok_irql(PASSIVE_LEVEL); + trace("Final Dpc count: %ld, expected %ld\n", DpcCount, ExpectedDpcCount); +}
Propchange: branches/GSoC_2011/KMTestSuite/kmtests/ntos_ke/KeDpc.c ------------------------------------------------------------------------------ svn:eol-style = native
Added: branches/GSoC_2011/KMTestSuite/kmtests/ntos_ke/KeIrql.c URL: http://svn.reactos.org/svn/reactos/branches/GSoC_2011/KMTestSuite/kmtests/nt... ============================================================================== --- branches/GSoC_2011/KMTestSuite/kmtests/ntos_ke/KeIrql.c (added) +++ branches/GSoC_2011/KMTestSuite/kmtests/ntos_ke/KeIrql.c [iso-8859-1] Fri Jul 8 06:38:01 2011 @@ -1,0 +1,135 @@ +/* + * PROJECT: ReactOS kernel-mode tests + * LICENSE: GPLv2+ - See COPYING in the top level directory + * PURPOSE: Kernel-Mode Test Suite Interrupt Request Level test + * PROGRAMMER: Thomas Faber thfabba@gmx.de + */ + +#include <ntddk.h> +#include <ntifs.h> +#include <ndk/ntndk.h> +#include <kmt_test.h> +#include <pseh/pseh2.h> + +#define NDEBUG +#include <debug.h> + +START_TEST(KeIrql) +{ + KIRQL Irql, Irql2, PrevIrql, SynchIrql; + + /* we should be called at PASSIVE_LEVEL */ + ok_irql(PASSIVE_LEVEL); + + PrevIrql = KeGetCurrentIrql(); + + // SYNCH_LEVEL is different for UP/MP + if (KeGetCurrentPrcb()->BuildType & PRCB_BUILD_UNIPROCESSOR) + { + trace("This is a Uniprocessor kernel\n"); + SynchIrql = DISPATCH_LEVEL; + } + else + { + trace("This is a Multiprocessor kernel\n"); + SynchIrql = IPI_LEVEL - 2; + } + + /* some Irqls MUST work */ + { + const KIRQL Irqls[] = { LOW_LEVEL, PASSIVE_LEVEL, APC_LEVEL, DISPATCH_LEVEL, + CMCI_LEVEL, CLOCK1_LEVEL, CLOCK2_LEVEL, CLOCK_LEVEL, + PROFILE_LEVEL, IPI_LEVEL, /*POWER_LEVEL,*/ SynchIrql, HIGH_LEVEL }; + int i; + for (i = 0; i < sizeof Irqls / sizeof Irqls[0]; ++i) + { + KeRaiseIrql(Irqls[i], &Irql2); + ok_eq_uint(Irql2, PrevIrql); + ok_irql(Irqls[i]); + KeLowerIrql(Irql2); + ok_irql(PrevIrql); + } + } + + /* raising/lowering to the current level should have no effect */ + ok_irql(PASSIVE_LEVEL); + KeRaiseIrql(PASSIVE_LEVEL, &Irql); + ok_eq_uint(Irql, PASSIVE_LEVEL); + KeLowerIrql(PASSIVE_LEVEL); + ok_irql(PASSIVE_LEVEL); + + /* try to raise to each Irql and back */ + for (Irql = PASSIVE_LEVEL; Irql <= HIGH_LEVEL; ++Irql) + { + DPRINT("Raising to %u\n", Irql); + KeRaiseIrql(Irql, &Irql2); + ok_eq_uint(Irql2, PrevIrql); + KeLowerIrql(Irql2); + ok_irql(PrevIrql); + } + + /* go through all Irqls in order, skip the ones that the system doesn't accept */ + for (Irql = PASSIVE_LEVEL; Irql <= HIGH_LEVEL; ++Irql) + { + DPRINT("Raising to %u\n", Irql); + KeRaiseIrql(Irql, &Irql2); + ok_eq_uint(Irql2, PrevIrql); + Irql2 = KeGetCurrentIrql(); + ok(Irql2 <= Irql, "New Irql is %u, expected <= requested value of %u\n", Irql2, Irql); + PrevIrql = Irql2; + } + + ok_irql(HIGH_LEVEL); + + /* now go back again, skipping the ones that don't work */ + for (Irql = HIGH_LEVEL; Irql > PASSIVE_LEVEL;) + { + DPRINT("Lowering to %u\n", Irql - 1); + KeLowerIrql(Irql - 1); + Irql2 = KeGetCurrentIrql(); + ok(Irql2 < Irql, "New Irql is %u, expected <= requested value of %u\n", Irql2, Irql - 1); + if (Irql2 < Irql) + Irql = Irql2; + else + --Irql; + } + + DPRINT("Alive!\n"); + /* on x86, you can raise to _any_ possible KIRQL value */ + /* on x64, anything with more than the least significant 4 bits set bugchecked, last time I tried */ + /* TODO: other platforms? */ +#if defined _M_X86 + for (Irql = PASSIVE_LEVEL; Irql <= (KIRQL)-1; ++Irql) + { + DPRINT("Raising to %u\n", Irql); + KeRaiseIrql(Irql, &Irql2); + ok_eq_uint(Irql2, PrevIrql); + KeLowerIrql(Irql2); + ok_irql(PrevIrql); + } +#endif /* defined _M_X86 */ + + /* test KeRaiseIrqlToDpcLevel */ + ok_irql(PASSIVE_LEVEL); + Irql = KeRaiseIrqlToDpcLevel(); + ok_irql(DISPATCH_LEVEL); + ok_eq_uint(Irql, PASSIVE_LEVEL); + Irql = KeRaiseIrqlToDpcLevel(); + ok_irql(DISPATCH_LEVEL); + ok_eq_uint(Irql, DISPATCH_LEVEL); + KeLowerIrql(PASSIVE_LEVEL); + + /* test KeRaiseIrqlToSynchLevel */ + ok_irql(PASSIVE_LEVEL); + Irql = KeRaiseIrqlToSynchLevel(); + ok_irql(SynchIrql); + ok_eq_uint(Irql, PASSIVE_LEVEL); + Irql = KeRaiseIrqlToSynchLevel(); + ok_irql(SynchIrql); + ok_eq_uint(Irql, SynchIrql); + KeLowerIrql(PASSIVE_LEVEL); + + /* make sure we exit gracefully */ + ok_irql(PASSIVE_LEVEL); + KeLowerIrql(PASSIVE_LEVEL); +}
Propchange: branches/GSoC_2011/KMTestSuite/kmtests/ntos_ke/KeIrql.c ------------------------------------------------------------------------------ svn:eol-style = native