Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does CR3 change when an interrupt is fired on x86 machines?

On x86 machines, does CR3 change (not just the value of EIP) when an interrupt is fired?

like image 700
Bill Maher Avatar asked Mar 14 '23 18:03

Bill Maher


1 Answers

The processor saves the following state when an interrupt or exception occurs (see Intel 64 and IA-32 Architectures Software Developer’s Manual Volume 3 (3A, 3B & 3C): System Programming Guide, 6.12.1.) :

  • If the DPL (destination privilege level) is equal to the CPL (current privilege level), then the following registers and possibly an error code is pushed to the current stack before control is handed to the interrupt handler:

    EFLAGS, CS, EIP
    
  • If on the other hand the DPL is lower than the CPL, then additionally to the above registers the SS and ESP registers are pushed onto another stack (specified in the TSS).

Since the processor must enable the operating system to restore the state of the interrupted process, it's impossible for the processor to change any other than the above registers on its own. Thus CR3 is not changed.

An implication of this is that the code for the interrupt handler must be accessible in every virtual address space in which an interrupt may occur. Because of that, and because such a handler usually calls additional code from the kernel, most kernels map a good portion of their own code and data into the address space of every process, reducing the available memory space for each process. Usually this mapping is established at the "upper end" of the addressable memory space, around 3GB.

In a hobby kernel I wrote long ago I took the approach of trying to keep the address space of the processes as large as possible, thus I only mapped the interrupt handler as well as some code and the required data to change to a dedicated kernel address space before actually handling the interrupt into the address space of the processes. This turned out to be rather difficult, with only a questionable benefit, which is why I guess most systems don't take this approach.


If there is a task gate descriptor in the interrupt descriptor table, then when that interrupt fires a hardware task switch will happen, saving the state of the processor into the current TSS and loading the state from the TSS referenced by the task gate. This includes loading the value of the CR3 register, thus changing the virtual address space (see 7.3. of above mentioned manual).

This is hardly done in practice, though, since hardware task switching is - as the name suggests - highly depended of the hardware and as such only supported on x86 CPUs. Because of the rare use of that feature, even the corresponding 64 bit CPUs no longer support it:

In 64-bit mode, task switching is not supported [..]

[Intel manual mentioned above, 7.2.3]

like image 128
Daniel Jour Avatar answered Apr 06 '23 22:04

Daniel Jour