Modifying IDT

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
Alpha
Posts: 15
Joined: Fri Apr 10, 2009 7:04 am
Location: The Netherlands

Modifying IDT

Post 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?
User avatar
sortie
Member
Member
Posts: 931
Joined: Wed Mar 21, 2012 3:01 pm
Libera.chat IRC: sortie

Re: Modifying IDT

Post 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.
Antti
Member
Member
Posts: 923
Joined: Thu Jul 05, 2012 5:12 am
Location: Finland

Re: Modifying IDT

Post 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.
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: Modifying IDT

Post 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
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.
User avatar
sortie
Member
Member
Posts: 931
Joined: Wed Mar 21, 2012 3:01 pm
Libera.chat IRC: sortie

Re: Modifying IDT

Post 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.
Gigasoft
Member
Member
Posts: 856
Joined: Sat Nov 21, 2009 5:11 pm

Re: Modifying IDT

Post by Gigasoft »

You could use FISTP, FSTP or MOVNTQ.
mrstobbe
Member
Member
Posts: 62
Joined: Fri Nov 08, 2013 7:40 pm

Re: Modifying IDT

Post 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?
User avatar
Combuster
Member
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

Post 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.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
mrstobbe
Member
Member
Posts: 62
Joined: Fri Nov 08, 2013 7:40 pm

Re: Modifying IDT

Post 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.
Post Reply