Interrupt Descriptor Table: Masking and shifting addresses

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
glauxosdever
Member
Member
Posts: 501
Joined: Wed Jun 17, 2015 9:40 am
Libera.chat IRC: glauxosdever
Location: Athens, Greece

Interrupt Descriptor Table: Masking and shifting addresses

Post by glauxosdever »

Hi all,


I want to make an Interrupt Descriptor Table, which needs to have the address of the interrupt handler for each entry. The problem is that there are two fields for the address: the one contains the lower 16 bits, the other contains the upper 16 bits. Like this (NASM):

Code: Select all

dw handler_addr & 0xFFFF
dw 0x08
db 0x00
db 0x8F
dw handler_addr >> 16
But these are not scalar values. I tried the solution provided on the wiki but doesn't work for elf32. I remember it worked fine for flat binary. Any ideas?

P.S. I'd prefer not having runtime initialisation code.


Regards,
glauxosdever
alexfru
Member
Member
Posts: 1112
Joined: Tue Mar 04, 2014 5:27 am

Re: Interrupt Descriptor Table: Masking and shifting address

Post by alexfru »

Change the order to concatenate the two address halves and pre-initialize like that. At run-time in a loop change the order to what the CPU wants. Unions might help.

Another option might be to recognize something here:

Code: Select all

...
dw handler_addr & 0xFFFF
dw 0x08
db 0x00
db 0x8F
dw handler_addr >> 16
dw handler_addr & 0xFFFF
dw 0x08
db 0x00
db 0x8F
dw handler_addr >> 16
...
But you'd still need to swap the address halves.
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: Interrupt Descriptor Table: Masking and shifting address

Post by Combuster »

The ELF object file contains relocations of a fixed format that correspond to the instruction set. The x86 architecture has no instruction that is in any tradition used to load the top 16 bits of an address into, therefore you can't express that in an object file. Several RISC processors do have an explicit load high with a 16-bit immediate where the fixed instruction width requires two instructions to load a 32-bit integer. When assembling directly to a flat binary you don't have the restrictions of an intermediate object file, and the assembler is often capable (or to some extent, if you look at the fix) of filling out the addresses on the spot.

If you want to use object files, you'll have to initialize the tables at runtime. The resulting code could well be cleaner for lack of pages worth of loop unrolling.
"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 ]
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: Interrupt Descriptor Table: Masking and shifting address

Post by Brendan »

Hi,
glauxosdever wrote:P.S. I'd prefer not having runtime initialisation code.
Realistically:
  • The first 32 entries are exceptions handlers that could be statically allocated, but they're also a perfect place to have different code for different systems. For example, maybe you want one page fault handler for "plain 32-bit paging" and a different page fault handler for "PAE"; and one "invalid opcode" exception handler for CPUs that support AVX and a different one for when the kernel emulates AVX instructions, etc.
  • The 15 interrupts used by the PIC chips depend on whether or not the OS decides to use PIC or IO APIC (if the OS uses IO APIC then you only need 2 "spurious IRQ from PIC chip" interrupt handlers because the PIC chips won't send normal IRQs)
  • The variable number of interrupts used by IO APIC is variable (and depend on whether the OS decides to use PIC or IO APIC)
  • Any interrupts used by the local APIC (spurious, timer, thermal status, performance monitoring) depend on whether or not the local APIC exists (and whether or not things like performance monitoring for the specific CPU is supported by the kernel)
  • The interrupt vectors the OS uses for IPIs (e.g. multi-CPU TLB shootdown, etc) mostly depend on whether the computer has 2 or more CPUs (but even for single-CPU some might be used for some sort of deferred procedure call thing, which would depend on the existence of the local APIC). This is another place where you might choose one of multiple interrupt handlers (e.g. one "multi-CPU TLB shootdown IPI" handler for SMP and another/different one for NUMA)
  • The vast majority of "otherwise unused" interrupts may or may not be used for PCI devices using MSI
Basically; you might only be able to setup less than 10% of IDT entries at compile time anyway.


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.
glauxosdever
Member
Member
Posts: 501
Joined: Wed Jun 17, 2015 9:40 am
Libera.chat IRC: glauxosdever
Location: Athens, Greece

Re: Interrupt Descriptor Table: Masking and shifting address

Post by glauxosdever »

Hi all,


Thank you kindly for your answers. Based on them I decided to initialise the Interrupt Descriptor Table at runtime.


Regards,
glauxosdever
Post Reply