Regarding page fault

Hello Guys

I have a couple of questions regarding page fault handling mechanism. The
Windows Internals book says that the page fault trap dispatcher (ISR for
interrupt vector 0xe) dispatches page fault handling to memory managers
fault handler MmAccessFault for resolution that runs in the context of the
thread that caused the page fault. If MmAccessfault can’t resolve the the
fault then it raises an exception.

It further says that to satisfy the page fault an in-paging I/O is issued.
This in-paging I/O is synchronous and it waits for an event to be set when
this in paging request completes.

Questions:

  1. The trap handler for vector 0xe, at what IRQL does it run? is there a
    DIRQL associated or does it simply run at the IRQL of whatever thread that
    has caused the page fault.

  2. Another question stemming from the first one, does every interrupt
    handler need to run at some DIRQL level (as per me a DIRQL level is
    required only when you need to block some interrupts, otherwise an ISR can
    run at PASSIVE_LEVEL too…so just confirming). Is there any IRQL associated
    with Divide by Zero exception?

As I am writing these questions I am getting the answers myself. I know
that at dispatch level there shouldn’t be any page fault. If the page fault
trap dispatcher runs at a DIRQL level then above mentioned in-paging I/O
won’t be possible. The main reason of these doubts just before I started
writing this post was that whenever I thought of any entry in the IDR, an
interrupt vector, I subconsciously started to picture DIRQL associated
with it. Just got some clarity while writing this post. But I am going to
post it anyways. Please correct me if I am wrong anywhere or add something
if it’s missing : )

If you’re asking this just for curiosity, there is no fixed answer, and the answer won’t be of any use.

If you’re learning to write drivers, you don’t want to know every little detail of kernel itself. What you need to know are constraints and limitations what you can do in your ISR, DPC, etc. You don’t need to care about trap handlers, etc.

If you’re writing an ISR, you only needs to know it runs in arbitrary thread context on elevated IRQL >DISPATCH_LEVEL, and you cannot use regular spinlocks, and any other synchronization objects, other than interrupt spinlocks. You cannot access any pageable memory. You can queue a DPC from there.

If you’re writing a DPC, you need to know you cannot wait on synch objects. You can use spinlocks. You can signal events.

Okay. Atleast in case of handling page fault the page fault handler(ISR)
should run at an IRQL < DISPATCH_LEVEL in the context of the thread that
resulted in page fault for what Windows Internals says to hold true. If it
runs at an IRQL >= DISPATCH_LEVEL, it can’t wait for the synchronous IO to
complete. Synchronous handling of page fault also makes sense as it is a
fault type exception so the instruction that caused the exception would
re-execute expecting that the fault handler or ISR would have fixed the
problem (page fault handler would have adjusted the eip to the back to the
same instruction before returning i suppose). While it’s okay to say that
in general it’s safer to assume that the ISRs run at a DIRQL level but in
this case it doesn’t seem to hold true. Device interrupts handler run at
DIRQL level but that might not be the case with other system registered
exception handlers. Am I thinking on the right lines?

On Thu, Sep 20, 2012 at 8:25 PM, wrote:

> If you’re asking this just for curiosity, there is no fixed answer, and
> the answer won’t be of any use.
>
> If you’re learning to write drivers, you don’t want to know every little
> detail of kernel itself. What you need to know are constraints and
> limitations what you can do in your ISR, DPC, etc. You don’t need to care
> about trap handlers, etc.
>
> If you’re writing an ISR, you only needs to know it runs in arbitrary
> thread context on elevated IRQL >DISPATCH_LEVEL, and you cannot use regular
> spinlocks, and any other synchronization objects, other than interrupt
> spinlocks. You cannot access any pageable memory. You can queue a DPC from
> there.
>
> If you’re writing a DPC, you need to know you cannot wait on synch
> objects. You can use spinlocks. You can signal events.
>
>
> —
> NTDEV is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>

You’re thinking too much into it. A page fault happens in a non-arbitrary context. The only valid IRQL for it is <= APC_LEVEL. Thus, no matter what IRQL the exception handler may temporarily go in, it can always safely go back to the original IRQL, issue a page-in read and wait for the IO completion.

TL;DR: it doesn’t matter to what IRQL you might need to go up, it only matters to where it can go down.

I was trying to connect a few dots. But yea I guess I thought a bit too
much into it. Thanks for your helping comments.

On Thu, Sep 20, 2012 at 11:15 PM, wrote:

> You’re thinking too much into it. A page fault happens in a non-arbitrary
> context. The only valid IRQL for it is <= APC_LEVEL. Thus, no matter what
> IRQL the exception handler may temporarily go in, it can always safely go
> back to the original IRQL, issue a page-in read and wait for the IO
> completion.
>
> TL;DR: it doesn’t matter to what IRQL you might need to go up, it only
> matters to where it can go down.
>
> —
> NTDEV is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>

Well, in general you understand handling of
page fault correctly. The delicate details of how
exactly it begins (as ISR or something else) are not
important and should not concern you.
More over, it may depend on the machine architecture
(now when Windows runs on different architectures again)
– pa

On 20-Sep-2012 20:27, sanjeev wrote:

Okay. Atleast in case of handling page fault the page fault handler(ISR)
should run at an IRQL < DISPATCH_LEVEL in the context of the thread that
resulted in page fault for what Windows Internals says to hold true. If
it runs at an IRQL >= DISPATCH_LEVEL, it can’t wait for the synchronous
IO to complete. Synchronous handling of page fault also makes sense as
it is a fault type exception so the instruction that caused the
exception would re-execute expecting that the fault handler or ISR would
have fixed the problem (page fault handler would have adjusted the eip
to the back to the same instruction before returning i suppose). While
it’s okay to say that in general it’s safer to assume that the ISRs run
at a DIRQL level but in this case it doesn’t seem to hold true. Device
interrupts handler run at DIRQL level but that might not be the case
with other system registered exception handlers. Am I thinking on the
right lines?

On Thu, Sep 20, 2012 at 8:25 PM, > mailto:xxxxx> wrote:
>
> If you’re asking this just for curiosity, there is no fixed answer,
> and the answer won’t be of any use.
>
> If you’re learning to write drivers, you don’t want to know every
> little detail of kernel itself. What you need to know are
> constraints and limitations what you can do in your ISR, DPC, etc.
> You don’t need to care about trap handlers, etc.
>
> If you’re writing an ISR, you only needs to know it runs in
> arbitrary thread context on elevated IRQL >DISPATCH_LEVEL, and you
> cannot use regular spinlocks, and any other synchronization objects,
> other than interrupt spinlocks. You cannot access any pageable
> memory. You can queue a DPC from there.
>
> If you’re writing a DPC, you need to know you cannot wait on synch
> objects. You can use spinlocks. You can signal events.
>
>
> —</mailto:xxxxx>

Well, it is obvious that you are trying to actually understand things, rather than getting enough with
the " as a driver writer, you don’t need to know it" - style answers and dumbly quoting MSDN. This is really good. Therefore, if you don’t mind, I will give you some search directions without immediately giving an explicit answer to your question - I will leave it for you to do a bit of investigation on your own (i.e. the kind of thing that I would certainly expect from someone who intends to become a competent system-level developer)

First of all, you should ask yourself a question “What is the purpose of the very concept of IRQL, in the first place”. After you have found an answer to it (it should not take your that long, don’t you think), you should take Intel or AMD manuals and read everything about interrupts and exceptions, and try to figure out what the main differences between them are. At this point you will be able to answer your own questions concerning IRQL that exception handler may run at. I will give you a hint - the concept of IRQL may be implemented (and is actually implemented this way on some HALs) as a write to the local APIC’s TPR. The rest is a combination of logical thinking and carefully reading manuals. Good luck…

Anton Bassov

Remember that “interrupt” comes asynchronously from outside the CPU, and
“exception” comes synchronously from the instruction execution engine.
While it is true that ISRs run at elevated IRQL, that’s because the
interrupt system is dealing with this. So, from a driver perspective, all
ISRs run at elevated IRQL level, > DISPATCH_LEVEL, and that is absolutely
true. But exception handlers, although they use (and share) the mechanism
of gates and dispatching, you have to think of them as basically unrelated
concepts. The Intel instruction manual, for every instruction, tells what
exceptions it can raise. Some exceptions (such as page fault) can only be
raised in certain modes (virtual memory enabled). So when you talk about
ISRs in the context of a driver development group, the standard answer is
“All ISRs run at DIRQL > DISPATCH_LEVEL”, because in the context of
external devices, this is true. As a programmer, unless you are writing
an operating system, you will never see these exceptions or have to worry
about handling them. So while innate curiosity is valuable, you have to
be willing to understand that generic responses to generic questions are
not going to cover ISRs that handle exceptions.

I’ve written several operating system-like components that had to respond
to address errors, divide-by-zero, alignment, and similar errors. It’s
really hairy when you have to respond to stack overflow errors.
Page-faults are complex, but generally formulaic solutions are provided by
the computer vendor. A misaligned stack was a seriously bizarre problem
on a machine that insisted that pointers be aligned on pointer-sized
boundaries, because the exception handler couldn’t be transferred to,
since the push of the IP took an alignment fault. We ultimately solved
this one with a wire-cutter, and clipped the lead to the low-order bit of
the register and soldering a jumper to lock it to 0. Then the new model
came out, and it was all done in microcode, and you ain’t seen nothin’
until you’ve seen a piece of hardware that monitors the CPU board and
“hooks” access to low-level registers by the microcode! (They were called
“procmod” boards).
joe

Okay. Atleast in case of handling page fault the page fault handler(ISR)
should run at an IRQL < DISPATCH_LEVEL in the context of the thread that
resulted in page fault for what Windows Internals says to hold true. If it
runs at an IRQL >= DISPATCH_LEVEL, it can’t wait for the synchronous IO to
complete. Synchronous handling of page fault also makes sense as it is a
fault type exception so the instruction that caused the exception would
re-execute expecting that the fault handler or ISR would have fixed the
problem (page fault handler would have adjusted the eip to the back to the
same instruction before returning i suppose). While it’s okay to say that
in general it’s safer to assume that the ISRs run at a DIRQL level but in
this case it doesn’t seem to hold true. Device interrupts handler run at
DIRQL level but that might not be the case with other system registered
exception handlers. Am I thinking on the right lines?

On Thu, Sep 20, 2012 at 8:25 PM, wrote:
>
>> If you’re asking this just for curiosity, there is no fixed answer, and
>> the answer won’t be of any use.
>>
>> If you’re learning to write drivers, you don’t want to know every little
>> detail of kernel itself. What you need to know are constraints and
>> limitations what you can do in your ISR, DPC, etc. You don’t need to
>> care
>> about trap handlers, etc.
>>
>> If you’re writing an ISR, you only needs to know it runs in arbitrary
>> thread context on elevated IRQL >DISPATCH_LEVEL, and you cannot use
>> regular
>> spinlocks, and any other synchronization objects, other than interrupt
>> spinlocks. You cannot access any pageable memory. You can queue a DPC
>> from
>> there.
>>
>> If you’re writing a DPC, you need to know you cannot wait on synch
>> objects. You can use spinlocks. You can signal events.
>>
>>
>> —
>> NTDEV is sponsored by OSR
>>
>> For our schedule of WDF, WDM, debugging and other seminars visit:
>> http://www.osr.com/seminars
>>
>> To unsubscribe, visit the List Server section of OSR Online at
>> http://www.osronline.com/page.cfm?name=ListServer
>>
>
> —
> NTDEV is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer

> Remember that “interrupt” comes asynchronously from outside the CPU, and “exception”

comes synchronously from the instruction execution engine.

Duh, Joe - this is exactly what I wanted the OP to realize. However, you gave him a ready answer…

Anton Bassov

>Then the new model came out, and it was all done in microcode, and you ain’t seen nothin’ until you’ve seen a piece of hardware that monitors the CPU board and “hooks” access to low-level registers by the microcode!

Did you design…this:

http://en.wikipedia.org/wiki/File:Picard_as_Locutus.jpg

Does shool still cover this topic in computer arch 101?

A fundamental problem a computer system needs to solve is prioritizing
interrupts from external devices. An intel 8086 system solves it by
programming the 8259 chip (actual discrete one on motherboard) in certain
mode. A 80386 with APIC, a Pentium with local APIC can do the same
thing differently if they choose to. Alpha, Itanium all needs to solve the
same problem.

IRQL, is a Microsoft SW abstraction on NT operating system of how external
interrupts are prioritized so that most programmers don’t need to know how
to program a 8259 or apic. OS does all work to make sure interrupts are
correctly prioritized should they arrive concurrently. They don’t worry
about if they have a 8259, and enhanced 8259, an i/o apic, a local apic
unless he write that part of code.

Exceptions, on intel 80386 compatible system, use the first 0x20 vectors to
transfer program execution flow. They are synchronous INTERNAL events which
interrupt prioritization (IRQL on NTOS) does not apply.