Thread Scheduling, IRQLs and APIC

First, I apologize if this question has already been asked, but I couldn’t find any relevant information while searching the forum.

I know for a fact that anytime a hardware device interrupt occurs, CPU’s Task Priority Register is risen to a specific IRQ Level. In an APIC system, the higher nibble of the interrupt’s vector value is its IRQL. (For example, CR8=5 then any interrupt with the vector under 0x50 will stay pending when fired).
I’ve heard that Windows rises the IRQL based on that nibble when an IRQ gets handled (Windows is probably doing this in a common handler? Is this true?).

So the scheduling could occur, a timer interrupt has to be fired and Windows assumes that this interrupt’s IRQL is CLOCK_LEVEL which is 28 (0x1C in hex) I believe. This means that the timer interrupt vector is programmed to be anything between what interrupt vectors???

Whatever, now that we are in the timer interrupt handler, the code will check if the quantum of the current thread is 0 then use APIC to fire a dispatch interrupt to reschedule. Now here I have another two questions:

  1. The software interrupt that is asked by the Hal to be fired (mapped to DISPATCH_LEVEL) has to be any vector in the range 0x20-0x2F to respect the TPR logic, right, because when the IRQL is lowered the scheduler software interrupt can fire?
  2. I know that scheduling and context switching are two separate things, and that scheduling happens once the Timer interrupt handler requests a DISPATCH_LEVEL software interrupt as mentioned above, but what about context switch? When is the context switch done? Is it when the Hal requests APC_LEVEL software interrupt? When is this request done, is it done by the timer interrupt too?

Thank you for taking your time to read this.

This means that the timer interrupt vector is programmed to be anything between what interrupt vectors???

How is that possibly relevant to anything? It's purely implementation detail.

I know that scheduling and context switching are two separate things,

Sort of. A context switch can be one of the results of the scheduling process.

scheduling happens once the Timer interrupt handler requests a DISPATCH_LEVEL software interrupt

Scheduling happens when we have finished in the kernel and are about to switch back to user mode. There are no "software interrupts". The timer interrupt handler might queue up a task to be run at DISPATCH_LEVEL, using KeInsertQueueDpc, for example.

The context switch is clearly NOT done by the timer interrupt handler. Scheduling (and hence a context switch) can be triggered even without a timer interrupt.

My understanding is that thread scheduling can happen anytime a cpu transitions from >= DISPATCH_LEVEL to < DISPATCH_LEVEL. The operation is performed before lowering the IRQL.

Certainly it does not only happen when exiting kernel mode, as that would imply that kernel mode threads running at < DISPATCH_LEVEL are never context switched.

Also imposing a scheduling operation on kernel->user mode transitions would be costly and annoying. And the 'scheduler' would have to raise to DISPATCH_LEVEL anyway.

It was once written that a context switch can occur when a clock interrupt fires, a page-fault occurs, or when a thread calls into one of the Ke* routines. Perhaps these conditions have changed over time.

Context switches can only occur on the transition from >= dispatch_level to < dispatch_level. That transition can be caused by many sequences of events, for example a timer interrupt, or any other interrupt.