KeFlushQueuedDpcs is used by some drivers, when unloading or removing a device, to be sure no DPC is still running their code. On a UP system this can be done "inline", on an SMP system, it requires to send an IPI to each processor that has DPCs queued and also synchronize it with the calling thread, which is what KeSetSystemAffinityThread does implicitly: When a queued DPC was detected on a remote processor (implying that processor is currently running at DISPATCH_LEVEL or above), KeSetSystemAffinityThread will schedule the current thread on that processor and send a DPC interrupt. The remote processor will handle that DPC interrupt once it is back below DISPATCH_LEVEL. It will only run the current thread, after all queued DPCs (including threaded DPCs) have finished running.
Pass a proper write/execute flag in the ExceptionInformation[0] field of the exception record instead of the raw fault code. This fixes comdlg:filedlg wine test, which writes to a write protected resource section, which needs to be handled by kernel32 UnhandledExceptionFilter, which relies on this parameter to be correct.
- Fix annotations
- Don't use KiServiceExit to return to the caller with an error code, instead just return from the function, that is the same thing.
- Refactor failure path
- Add DPRINTs on failure
- Implement KiExceptionExit, which works like KiServiceExit2, but takes an exception frame as 2nd parameter
- Add a local exception frame to NtRaiseException and NtContinue, which is needed to exit with a full context on x64 and arm
- Use KeContextToTrapFrame again instead of KiSetTrapContext, since we have a proper exception frame now.
- Don't wait 1 second for each processor
- Use AFFINITY_MASK
- Use Prcb->Number, which is more future proof than KeGetCurrentProcessorNumber
- Improve for loop
The registers that are saved/restored in the trap / exception frame need to be consistent between all entry/exit points as well as the functions that convert between trap/exception frame and context. The trap frame contains only the non-volatile registers and rbp, the rest is saved in the exception frame.
The previous code didn't save rbp in the syscall handler, which led to it being clobbered when exiting though KiServiceExit2 rather than returning back to the syscall exit path. Also KeContextToTrapFrame would use rbx, rsi and rdi from the trap frame, which wouldn't be saved there by the syscall handler.
We need to save the missing registers in the trap frame before calling KiInitiateUserApc, because they will be used to create the CONTEXT that is saved on the user mode stack, where KiUserApcDispatcher returns back to using NtContinue. This fixes remaining failures in kernel32_apitest QueueUserAPC.
Both due-times and interrupt time are unsigned, but were treated as signed in KiInsertTimerTable, which led to very long (e.g. INFINITE) waits being interpreted as having a negative due-time and being completed instantly.
Mostly fixes kernel32_apitest QueueUserAPC
This is used in KiUserModeCallout instead of KiServiceExit2. The latter is broken, leaks non-volatile registers and will need to be modified to handle an exception frame, which we don't need/have here. It will also use sysret instead of iret and is generally simpler/faster.
Eventually it would be desirable to skip the entire trap frame setup and do everything in KiCallUserMode. This requires some cleanup and special handling for user APC delivery.
This also fixes delivering APCs from the system call handler, which previously would have clobbered rax. Also don't use the thread's TrapFrame member, which is not always set, when returning.
This is needed, because KiSystemCallHandler can be called multiple times for the same syscall entry, which would mess up the linkage. This replaces a previous hack and makes things cleaner.
- Use an index for the table instead of ugly pointer offset
- Invert the check for GUI calls
- Fail with proper status code on invalid win32k syscall ids
This is required since while interrupts are enabled, another user APC could get queued and we want to guarantee that those are all delivered before returning to user mode.
Fixed in x86 and ARM (this was already done in x64).
This is needed because thread preparation routine KxQueueReadyThread()
releases PRCB lock, but does not acquire it, so that the locking must
always be done outside the function, same as in all its other usage cases.
This fixes an assert from release PRCB routine, when booting x86 ReactOS
in SMP mode, because it attempts to release the lock when it is not
actually acquired.
Addendum to commit a011d19ed.
+ Add an assert in KxQueueReadyThread() to ensure the PRCB lock is actually acquired.
CORE-1697
Raise IRQL to SYNCH_LEVEL when exiting from the idle thread in the
idle loop, in case it is scheduled for execution. Then restore it
back to DISPATCH_LEVEL, after this is done.
This behaviour is a bit similar to the way it's done on x64.
This IRQL raise is necessary only in SMP builds.
Calls are placed in CONFIG_SMP ifdef: this avoids unnecessary IRQL
changes on UP, since SYNCH_LEVEL and DISPATCH_LEVEL are identical
there, unlike in MP, where SYNCH_LEVEL is IPI_LEVEL - 2 actually.
This prevents bugcheck DRIVER_IRQL_NOT_LESS_OR_EQUAL when booting
SMP x86 ReactOS, in KiTimerExpiration when calling it 2nd time.
The BSOD happened due to IRQL levels mismatch.