The hardware notifies the
software via
a Page Fault Exception.
When an exception happens, the CPU
jumps to an address that the
OS had previously registered
as the fault handler. This is usually
done at boot
time by the
OS.
This could happen for example due to
a programming error:
int *is = malloc(1);
is[2] = 1;
but there are cases where it is not
a bug, for example in
Linux when:
the program wants to increase its stack.
It just tries to accesses
a certain
byte in
a given possible range, and if the
OS is happy it adds that page to the process address
space, otherwise, it sends
a signal to the process.
the page was swapped to disk.
The
OS will need to do some work behind the processes back to get the page back into RAM.
The
OS can discover that this is the case based on the contents of the rest of the page table entry, since if the
present flag is clear, the other entries of the page table entry are completely left for the
OS to to what it wants.
On
Linux for example, when
present =
0:
- if all the fields of the page table entry are 0, invalid address.
- else, the page has been swapped to disk, and the actual values of those fields encode the position of the page on the disk.
In any case, the
OS needs to know which address generated the Page Fault to be able to
deal with the problem. This is why the nice IA32 developers set the value of
cr2
to that address whenever
a Page Fault occurs. The exception handler can then just look into
cr2
to get the address.