[RESOLVED] IDT doesn't work when linking above 0xa0000

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
pm
Posts: 2
Joined: Sat Jun 29, 2019 3:19 pm

[RESOLVED] IDT doesn't work when linking above 0xa0000

Post by pm »

IDT doesn't work when part of the .data section gets loaded above 0xa0000. I am using GRUB. I have set up my own GDT. Source code here.

Changing line 6 of kernel.ld from 0x80000 to anything above 0x9c160 will cause the CPU to jump to 0xe05b on "int $3" instead of the correct interrupt handler. I tried linking the kernel way higher (at 4M and 100M) and it doesn't work as well.

Code: Select all

OUTPUT_ARCH(i386)
ENTRY(_start)

SECTIONS
{
  . = 0x80000; // Changing to anything above 0x9c160 will cause part of the .data section to go above 0xa0000.

  .text : { *(.multiboot) *(.text) }
  .data ALIGN(4096) : { *(.data .rodata*) }
  .bss ALIGN(4096) : { *(.bss) }
}
I imagine 0xe05b is a GRUB interrupt handler. I want to know if that is an issue with my linker script, or if I am missing something with the GRUB setup. Also, I would like to know where I can learn more about linking the kernel/linkers in general.

My environment:

Code: Select all

i386-elf-gcc (GCC) 9.1.0
GNU i386-elf-ld (GNU Binutils) 2.32
qemu-system-i386 version 4.0.0
grub-mkrescue (GRUB) 2.03.6~manjaro
xorriso 1.5.0
Last edited by pm on Sat Jun 29, 2019 7:39 pm, edited 2 times in total.
MichaelPetch
Member
Member
Posts: 798
Joined: Fri Aug 26, 2016 1:41 pm
Libera.chat IRC: mpetch

Re: IDT doesn't work when linking above 0xa0000

Post by MichaelPetch »

f000:e05b is indicative your kernel triple faulted and returned back to real mode. You should be using . = 0x100000; in your linker script as the multiboot spec doesn't actually say it will support loading anywhere else except at 0x100000 .
MichaelPetch
Member
Member
Posts: 798
Joined: Fri Aug 26, 2016 1:41 pm
Libera.chat IRC: mpetch

Re: IDT doesn't work when linking above 0xa0000

Post by MichaelPetch »

I had a chance to look at the code. It will fault on your interrupts because the IDT descriptors have been built incorrectly in make_interrupt_gate. You have:

Code: Select all

static inline uint64_t make_interrupt_gate(const uintptr_t interrupt) {
  const uint64_t interrupt_low = interrupt;
  const uint64_t interrupt_high = interrupt >> 16;

  uint64_t idt_entry = 0;
  idt_entry |= interrupt_low;
  idt_entry |= interrupt_high << 48;
  idt_entry |= KERNEL_CODE_SELECTOR << 16;
  // Interrupt type and attributes.
  idt_entry |= (uint64_t)0x8e << 40;
  return idt_entry;
}
I think it should be more like:

Code: Select all

static inline uint64_t make_interrupt_gate(const uint64_t interrupt) {
  uint64_t idt_entry = 0;
  idt_entry |= (interrupt & 0xffff);
  idt_entry |= (interrupt & 0xffff0000) << 32;
  idt_entry |= (uint64_t)KERNEL_CODE_SELECTOR << 16;
  // Interrupt type and attributes.
  idt_entry |= (uint64_t)0x8e << 40;
  return idt_entry;
}
pm
Posts: 2
Joined: Sat Jun 29, 2019 3:19 pm

Re: IDT doesn't work when linking above 0xa0000

Post by pm »

MichaelPetch wrote:I had a chance to look at the code. It will fault on your interrupts because the IDT descriptors have been built incorrectly in make_interrupt_gate.
Indeed, that was the case. Thank you very much for this and the previous reply.
Post Reply