Page 1 of 1

Modifying IDT

Posted: Fri Nov 22, 2013 7:04 am
by Alpha
Hello everyone,

I was reading some tutorials about interrupt and the idt. I was wondering if you need to disable interrupts when you want to modify the idt.
For example when you want to change an interrupt handler. I have seen a lot of tutorials modifying the idt after interrupts are turned on. Does this have consequences? I could imagine that things go wrong when an interrupt occurs while you are busy altering the table.

Could someone explain this to me?

Re: Modifying IDT

Posted: Fri Nov 22, 2013 7:11 am
by sortie
I believe it should be safe to modify the IDT (I am not certain, however) while interrupts are enabled. After all, if you do aligned writes to it, then the entries should be updated atomically. Since the CPU ensures that interrupts happen at a consistent boundary, such writes will have completed when the interrupt happens. Indeed, the probability that an interrupt happens during this write is very, very low in the first place. I think the real key information is that the CPU only remembers the IDT pointer, but not the contents of the array itself. This means that the array is accessed during all interrupts, so you can just atomically change it.

Nonetheless, it's perhaps a sign of bad design if you need to modify the interrupt table while interrupts are enabled. You ought to prepare the IDT for use before enabling interrupts.

Re: Modifying IDT

Posted: Fri Nov 22, 2013 7:51 am
by Antti
How do you change the entry atomically? It is an 8-byte entry on x86-32 and a 16-byte entry on x86-64. However, you could first write 0 to the part where the present bit is. Then update the other part and then the part where the present bit is. This would make sure a partially updated entry is not used. Of course, you will get an exception if the interrupt is triggered at the wrong time but it is better than any undefined behaviour caused by the partially updated entry. Of course, this should be just for extra safety. It should be guaranteed by using other methods that the interrupt is not triggered at that time.

EDIT: On x86-64 it is quite common that you do not have to change the upper part. So yes, practically is possible to update the entry atomically.

Re: Modifying IDT

Posted: Fri Nov 22, 2013 8:27 am
by Brendan
Hi,
Antti wrote:How do you change the entry atomically? It is an 8-byte entry on x86-32 and a 16-byte entry on x86-64. However, you could first write 0 to the part where the present bit is. Then update the other part and then the part where the present bit is. This would make sure a partially updated entry is not used. Of course, you will get an exception if the interrupt is triggered at the wrong time but it is better than any undefined behaviour caused by the partially updated entry. Of course, this should be just for extra safety. It should be guaranteed by using other methods that the interrupt is not triggered at that time.

EDIT: On x86-64 it is quite common that you do not have to change the upper part. So yes, practically is possible to update the entry atomically.
For 32-bit protected mode you can use the "CMPXCHG8B" instruction and for 64-bit you can use "CMPXCHG16B". Sadly these instructions are both optional extras (there are older 32-bit CPUs that don't support "CMPXCHG8B", and older 64-bit CPUs that don't support "CMPXCHG16B"). :)

The alternative is to clone the entire IDT, make modifications to the copy, then do an atomic "LIDT".

Note: I think Alpha is more worried about modifying an IDT entry for an interrupt that can't occur, while other IDT entries are being used. This is perfectly safe without atomic updates.


Cheers,

Brendan

Re: Modifying IDT

Posted: Fri Nov 22, 2013 7:58 pm
by sortie
Antti wrote:How do you change the entry atomically? It is an 8-byte entry on x86-32 and a 16-byte entry on x86-64.
My bad! I forgot entries are twice the size of native machine words.

Re: Modifying IDT

Posted: Sat Nov 23, 2013 8:32 am
by Gigasoft
You could use FISTP, FSTP or MOVNTQ.

Re: Modifying IDT

Posted: Sat Nov 23, 2013 10:11 pm
by mrstobbe
Good advice about atomic operations all around (I'm seconding it).

I'm just wondering (purely for the sake of conversion/random interest here), how often are you actually modifying your IDT that disabling interrupts is problematic?

Re: Modifying IDT

Posted: Sun Nov 24, 2013 2:20 am
by Combuster
mrstobbe wrote:disabling interrupts is problematic?
Disabling interrupts of its own is already a significant pain if you're sharing the IDT with several processor cores - if not the biggest pain in doing it properly. Otherwise the trivial cli; mov; mov; sti would have been sufficient as it has neglegible impact on your interrupt latency.

Re: Modifying IDT

Posted: Mon Nov 25, 2013 12:33 am
by mrstobbe
Combuster wrote:
mrstobbe wrote:disabling interrupts is problematic?
Disabling interrupts of its own is already a significant pain if you're sharing the IDT with several processor cores - if not the biggest pain in doing it properly. Otherwise the trivial cli; mov; mov; sti would have been sufficient as it has neglegible impact on your interrupt latency.
Yes, of course, I was asking why the basic ISR chain setup wan't set in stone by the time the initial kernel setup was done. I was wondering what they were up to.