PIT and Keyboard causing crashes?

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
PearOs
Member
Member
Posts: 194
Joined: Mon Apr 08, 2013 3:03 pm
Location: Usually at my keyboard!

PIT and Keyboard causing crashes?

Post by PearOs »

Edit: Its PIT not PIC. Didn't get my coffee this morning :D

Hey guys, this is by far one of the most annoying and worst bugs I have ever encountered in my system. So I have a GDT setup, and a IDT, and Interrupts are enabled and working. Everything works. If I set the PIT to run super faster, no issues. My code gets called, nothing crashes, I can switch tasks, the works. But the second I pressed a ton of keyboard keys, Bochs prints out "fetch_raw_descriptor: LDTR.valid=0" and it doesn't always happen. I can press a ton and it never happens and then it does. But whats odd is if I set the PIT to a slower speed and do that it takes a much longer time to actually cause a crash. But here's the annoying part, the keyboard code is super basic. I pretty much wiped it to nothing thinking it was a issue with the stack. I don't think it is.

In my main interrupt function that gets called in my ISR is my keyboard code.

Code: Select all

push 0x60
call IOPort_Read_8
pop eax
That's all of it, IOPort_Read_8 looks like this

Code: Select all

;Input:
; - (int) Address
;Ouput:
; - (int) Data
;Description: Reads data from an ioport.
IOPort_Read_8_Return: db 0,0,0,0
IOPort_Read_8:
call Thread_Lock
pop dword[IOPort_Read_8_Return] ;Save the return address
pop edx ;Address
in al, dx
MOVZX eax, al
push eax
push dword[IOPort_Read_8_Return] ;Restore the return address
call Thread_Unlock
ret ;Return
There is no stack leaks anywhere. Any ideas as to whats going on here?

Thanks, Matt
Nable
Member
Member
Posts: 453
Joined: Tue Nov 08, 2011 11:35 am

Re: PIT and Keyboard causing crashes?

Post by Nable »

> Any ideas as to whats going on here?
Some race condition in your code (although there's a very little but non-zero probability of bug in Bochs, about 2 years ago I've found a reproducable bug^W strange behaviour on invalid code that nobody could debug).

> call Thread_Lock
> pop dword[IOPort_Read_8_Return] ;Save the return address
Why are you doing this? You have too little stack space? This is not ARM with its link-register, so you don't have to save return address before calling another routine.
So, just use [esp+4] memory access.

> push eax
So, you are replacing the argument on stack with return data. Why are you using such a strange calling convention?

I don't know how good is your implementation of Thread_Lock but you are definitely doing things in a strange way.
(btw: avoid pop'ing return address, each 'call' should have its 'ret', else processor's call trace optimizations won't work)
PearOs
Member
Member
Posts: 194
Joined: Mon Apr 08, 2013 3:03 pm
Location: Usually at my keyboard!

Re: PIT and Keyboard causing crashes?

Post by PearOs »

Nable wrote:> Any ideas as to whats going on here?
Some race condition in your code (although there's a very little but non-zero probability of bug in Bochs, about 2 years ago I've found a reproducable bug^W strange behaviour on invalid code that nobody could debug).

> call Thread_Lock
> pop dword[IOPort_Read_8_Return] ;Save the return address
Why are you doing this? You have too little stack space? This is not ARM with its link-register, so you don't have to save return address before calling another routine.
So, just use [esp+4] memory access.

> push eax
So, you are replacing the argument on stack with return data. Why are you using such a strange calling convention?

I don't know how good is your implementation of Thread_Lock but you are definitely doing things in a strange way.
(btw: avoid pop'ing return address, each 'call' should have its 'ret', else processor's call trace optimizations won't work)

Ok so that is the backend code to my system. The rest is in C#. I use pop dword[return address] to get them off the stack so I can
access the parameter. Thread_Lock prevents interrupts from happening so that I can do such a thing. This is so that I can write easy code
without having to think and functions like IOPort_Read_8 don't need to have local variables and such. So that's why. There's no problem doing it that way as my whole Os was once 100% assembly and written that way and worked just fine.
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: PIT and Keyboard causing crashes?

Post by Brendan »

Hi,
PearOs wrote:If I set the PIT to run super faster, no issues. My code gets called, nothing crashes, I can switch tasks, the works. But the second I pressed a ton of keyboard keys, Bochs prints out "fetch_raw_descriptor: LDTR.valid=0" and it doesn't always happen. I can press a ton and it never happens and then it does. But whats odd is if I set the PIT to a slower speed and do that it takes a much longer time to actually cause a crash. But here's the annoying part, the keyboard code is super basic. I pretty much wiped it to nothing thinking it was a issue with the stack. I don't think it is.
I'd be tempted to assume that your PIT IRQ handler trashes some registers. When not much is happening the PIT interrupts "not much" and trashes a register that wasn't being used anyway; but when PIT interrupts the keyboard's IRQ handler the register is being used and causes the keyboard's IRQ handler to crash in some strange (potentially "random" way).


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.
PearOs
Member
Member
Posts: 194
Joined: Mon Apr 08, 2013 3:03 pm
Location: Usually at my keyboard!

Re: PIT and Keyboard causing crashes?

Post by PearOs »

Brendan wrote:Hi,
PearOs wrote:If I set the PIT to run super faster, no issues. My code gets called, nothing crashes, I can switch tasks, the works. But the second I pressed a ton of keyboard keys, Bochs prints out "fetch_raw_descriptor: LDTR.valid=0" and it doesn't always happen. I can press a ton and it never happens and then it does. But whats odd is if I set the PIT to a slower speed and do that it takes a much longer time to actually cause a crash. But here's the annoying part, the keyboard code is super basic. I pretty much wiped it to nothing thinking it was a issue with the stack. I don't think it is.
I'd be tempted to assume that your PIT IRQ handler trashes some registers. When not much is happening the PIT interrupts "not much" and trashes a register that wasn't being used anyway; but when PIT interrupts the keyboard's IRQ handler the register is being used and causes the keyboard's IRQ handler to crash in some strange (potentially "random" way).


Cheers,

Brendan
Huh. But lets say a Keyboard IRQ raises and calls my ISR code which then goes to handle the keyboard code, a PIT interrupt can't be fired until the ISR finishes right? Here's my current ISR code.

Code: Select all

irq_int: dd 0
irq_common_stub:
pop dword[irq_int]

mov byte[0xB8000], '0'

;Save all the registers
;to the stack
;pushad
push eax
push ebx
push ecx
push edx
push ebp
push edi
push esi
push esp
;Prevent interrupts from being
;started again
call Thread_Ignore
;Try to save the current stack
;to the thread running
;mov eax, esp
;push eax
;call iPear.Multitasking.Core.SaveStack_U32
;Now try to run Masked IRQ's
push dword[irq_int]
call iPear.Hardware.IRQ.Invoke_U32

.skip:
;Now attempt to switch threads
;if we can.
;call iPear.Multitasking.Core.Switch
;pop eax
;cmp eax, 0
;je .end ;Not a valid stack
;Otherwise set our new stack
;mov esp, eax

.end:
;Now send our end of interrupt
mov eax, dword[irq_int]
add eax, 32
push eax
call PIC_EOI
;Now unignore threads
call Thread_UnIgnore
;Ok now we have to restore all the registers.
;popad
pop esp
pop esi
pop edi
pop ebp
pop edx
pop ecx
pop ebx
pop eax
;Restore interrupts.
sti
;Now just return.
iret
The moving 0 to the screen was a test for me to be able to tell that the IRQ handler is still being called. Oddly that runs fine in VMWare so far as I can tell, but in Bochs, the second I press a key the whole thing crashes. Sometimes VMWare would crash if I pressed a lot of keys quickly, but with the current code that isn't happening as far as I can tell. Any idea?

Thanks, Matt
PearOs
Member
Member
Posts: 194
Joined: Mon Apr 08, 2013 3:03 pm
Location: Usually at my keyboard!

Re: PIT and Keyboard causing crashes?

Post by PearOs »

I fixed it! My Thread_Lock and Thread_Unlock code were flawed! Yay! So basically what was happening was one interrupt would run, then while were processing that one, another would run! Major problem.

- Matt
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: PIT and Keyboard causing crashes?

Post by Combuster »

Code: Select all

;Restore interrupts.
sti
;Now just return.
iret
You realize what IRET does to IF? :wink:
"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 ]
Antti
Member
Member
Posts: 923
Joined: Thu Jul 05, 2012 5:12 am
Location: Finland

Re: PIT and Keyboard causing crashes?

Post by Antti »

Combuster wrote:You realize what IRET does to IF?
If interrupts are disabled before executing an interrupt handler (e.g. software interrupt triggered) and we want to enable them, executing "sti" before "iret" could actually make sense. I have not tested it but "interrupts are enabled at the end of the next instruction".
brighteningeyes
Member
Member
Posts: 45
Joined: Sat Sep 07, 2013 8:26 am
Contact:

Re: PIT and Keyboard causing crashes?

Post by brighteningeyes »

when you write iret in the asm code, it enable's interrupt again
you must not write sti before iret
testing the operating system is very hard when your eyes can't see well
like me and many others
jnc100
Member
Member
Posts: 775
Joined: Mon Apr 09, 2007 12:10 pm
Location: London, UK
Contact:

Re: PIT and Keyboard causing crashes?

Post by jnc100 »

Antti wrote:If interrupts are disabled before executing an interrupt handler (e.g. software interrupt triggered) and we want to enable them, executing "sti" before "iret" could actually make sense. I have not tested it but "interrupts are enabled at the end of the next instruction".
From the docs, IF is set immediately. The response to IF being set (i.e. enabling interrupts) is what is delayed until after the next instruction. If iret clears IF, I'd imagine there is no time for an interrupt to occur as the docs for CLI do not suggest that clearing IF also incorporates a delay before allowing interrupts. Again though, I haven't tested this.

Code: Select all

or [esp + 8], 0x200
iret
may be a more reliable way to achieve this effect.

Regards,
John.
Post Reply