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?
Modifying IDT
Re: Modifying IDT
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.
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
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.
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
Hi,
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
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").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.
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
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
Re: Modifying IDT
My bad! I forgot entries are twice the size of native machine words.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.
Re: Modifying IDT
You could use FISTP, FSTP or MOVNTQ.
Re: Modifying IDT
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?
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?
- Combuster
- Member
- Posts: 9301
- Joined: Wed Oct 18, 2006 3:45 am
- Libera.chat IRC: [com]buster
- Location: On the balcony, where I can actually keep 1½m distance
- Contact:
Re: Modifying IDT
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.mrstobbe wrote:disabling interrupts is problematic?
Re: Modifying IDT
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.Combuster wrote: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.mrstobbe wrote:disabling interrupts is problematic?