#NP only on real hardware under specific circumstances

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
seantavius
Posts: 2
Joined: Sat Apr 04, 2026 2:07 pm

#NP only on real hardware under specific circumstances

Post by seantavius »

Hi,

I am in the process of writing an x86_64 BIOS/UEFI kernelin rust, loosely using Philipp Oppermann's websiteas a guide. I am currently using the 8259 PIC to manage interrupts (planning to switch to APIC soon), and I have a basic PS/2 controller/keyboard driver.

My kernel works perfectly fine on BIOS and UEFI builds on QEMU. However, on real hardware, when utilising the keyboard at a high rate, a Segment Not Present exception occurs, with error code 0x13B. This doesn't seem to make any sense to me however, as the instruction causing this exception is RET, which does not alter segment registers (at least to my understanding). I have included an image of the exception and a video of the process leading to its occurrence in my github repository, as I do not seem able to attach files that large here for now.

Stranger still is that the presence of the error code means that this can't be due to a mismapped PIC, as otherwise the given interrupt stack frame would display nonsense values, which it doesn't.

Exception trace:

Code: Select all

I: CCCCCCCCCCCCCCCC3
S: 80000009EFF
PANIC: panicked at kernel/src/interrupts.rs:149:5:
EXCEPTION: SEGMENT NOT PRESENT
InterruptStackFrame {
    instruction_pointer: VirtAddr(
        0x80000009e11,
    ),
    code_segment: SegmentSelector {
        index: 1,
        rpl: Ring0,
    },
    cpu_flags: RFlags(
        RESUME_FLAG | INTERRUPT_FLAG | 0x2,
    ),
    stack_pointer: VirtAddr(
        0x10000014f98,
    ),
    stack_segment: SegmentSelector {
        index: 2,
        rpl: Ring0,
    },
}
Error: 0x13b
I is a dump of memory at the instruction pointer, confirming that it is indeed ret
S is the top of the stack, aka the address that would have been returned to

Code: Select all

addr2line
on the rip gives

Code: Select all

x86_64-0.15.4/src/instructions/mod.rs:21
, which is the end of the

Code: Select all

hlt()
function, confirmed to be ret by objdump.

The address on the stack likewise is

Code: Select all

kernel/src/main.rs:31
, which is what is expected, so it doesn't seem as if my stack or execution context is corrupted in any way.

I am lost at how to proceed from here given the infancy of my kernel - I have little to mess up and little to debug with.

FWIW, my older, messier C++ 32-bit BIOS kernel does work on my test machine.

My test machine is a HP Notebook from 2017 with a Insyde BIOS (v F.21).
Octocontrabass
Member
Member
Posts: 6249
Joined: Mon Mar 25, 2013 7:01 pm

Re: #NP only on real hardware under specific circumstances

Post by Octocontrabass »

seantavius wrote: Tue Apr 14, 2026 1:04 pmwhen utilising the keyboard at a high rate,
Are you updating the screen inside your keyboard interrupt handler while interrupts are disabled? Does updating the screen take long enough that you might completely miss a timer IRQ?
seantavius wrote: Tue Apr 14, 2026 1:04 pmerror code 0x13B.
According to this error code, the missing descriptor is index 0x27 of the IDT, and the CPU tried to use that descriptor in response to an external event - such as a spurious IRQ7 caused by missing a timer IRQ - instead of a faulting instruction.
seantavius
Posts: 2
Joined: Sat Apr 04, 2026 2:07 pm

Re: #NP only on real hardware under specific circumstances

Post by seantavius »

Octocontrabass wrote: Tue Apr 14, 2026 1:41 pm Are you updating the screen inside your keyboard interrupt handler while interrupts are disabled? Does updating the screen take long enough that you might completely miss a timer IRQ?
Yes, and yes - that explains why the exception only occurs when I reach the bottom of the screen and it scrolls, and additionally why I never faced that problem in my old OS (screen not updated inside IRQ handler), and I presume QEMU runs the timer at a different rate to my hardware.
Octocontrabass wrote: Tue Apr 14, 2026 1:41 pm According to this error code, the missing descriptor is index 0x27 of the IDT, and the CPU tried to use that descriptor in response to an external event - such as a spurious IRQ7 caused by missing a timer IRQ - instead of a faulting instruction.
That is precisely the course of the exception; indeed now I remember that with the timer disabled the exception did not occur (I had completely forgotten this when writing the original post). I had misread the documentation, and not realised that #NP can be caused by a missing gate, so I thought it was only for loading a segment.

Thanks a lot
Post Reply