Updating IDT without reloading IDTR

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
Ethin
Member
Member
Posts: 625
Joined: Sun Jun 23, 2019 5:36 pm
Location: North Dakota, United States

Updating IDT without reloading IDTR

Post by Ethin »

So I was wondering precisely how I might go about this. When my OS starts I load the IDT with the LIDT instruction. But when I scan the PCI bus, devices there have interrupt vectors that I don't know about. I was wondering how (say) mainstream OSes handle this? I can see three possible ways:
  1. Dynamically alter the IDT, and then, if required, reload it
  2. Have each device driver asynchronously poll the devices for responses/changes/etc
  3. Register all 256 interrupts and set up an "interrupt dispatch" mechanism for interrupts beyond 32 or 48
The first option is what this topic is about -- is something like this possible to do safely? If not, what is the best alternative for this?
Octocontrabass
Member
Member
Posts: 5575
Joined: Mon Mar 25, 2013 7:01 pm

Re: Updating IDT without reloading IDTR

Post by Octocontrabass »

Changes to the IDT apply immediately. There is no need to flush the IDT by rewriting the IDTR, but you need to take care to prevent any CPU from trying to use a partially-written IDT entry.
nullplan
Member
Member
Posts: 1792
Joined: Wed Aug 30, 2017 8:24 am

Re: Updating IDT without reloading IDTR

Post by nullplan »

Adding to Octocontrabass' answer, in a modern system, you need all entry points anyway. The IOAPIC can have a variable number of interrupts and then there are Message Signalled Interrupts, of which you can have a variable number.

So what I did is this: Of the first 32 entries, only those are set that correspond to exceptions I can handle. And they are set to assembly functions that save state and call a handler function directly. To save code, those functions are generated by a macro. Then I do have entry points for all 224 remaining interrupts, but each of them only pushes the interrupt number and jumps to a common handler. And the rest is handled with function pointers.

This also means I can abstract interrupt controllers away. The entry code jumps to the common interrupt handler, which jumps to the registered handler for the interrupt controller, which jumps to the handler registered in the IC code and then does the EOI for the controller.

What I'm getting at is: This way I have the entire IDT prepared before secondary processors can start. As for other updates being inconsistent: I mask out all interrupts on system start (in all interrupt controllers) and only unmask interrupts after a handler is registered. That means a partial update can never be used by any processor. In theory, anyway.
Carpe diem!
Post Reply