Page 1 of 1

[Solved] RTC timer fails after reboot only in Bochs

Posted: Sun Feb 14, 2016 12:59 pm
by sleephacker
My OS is currently in Protected Mode and I have a basic CLI, and a reboot command that supports these methods:
1. Sending 0xfe to the PS/2 controller
2. Sending 0x02 and then 0x04 to port 0xcf9
3. Tripple fault

I tested rebooting using these methods as well as with the reset button both on bochs and my real machine.
But in Bochs it seems the RTC timer stops working after rebooting using either the PS/2 or the port 0xcf9 method but not after rebooting using any other method.
Also when the RTC stops working it won't work anymore even after I reboot using either the tripple fault method or the reset button.
I have also tested this on VirtualBox and my real machine, but the problem seems to be specific to Bochs so far.

This is the most important bit of the reboot code:

Code: Select all

	.ps2:
		mov esi, .ps2msg
		call boot_print_default
		mov byte [PS2.command], 0xfe		;pulse reset line
		call PS2_cscw
		jmp .fail
	.pci:					;TODO: according to linux source code I should check for the right PCI type to know if this is safe.
		mov esi, .pcimsg
		call boot_print_default
		mov dx, 0cf9h
		mov al, 02h
		out dx, al
		call .wait
		mov al, 04h
		out dx, al
		jmp .fail
	.tripple_fault:
		mov esi, .triflt
		call boot_print_default
		lidt [.BAD_IDTR]
		int 3	;debug interrupt
		jmp .fail
		.BAD_IDTR dw 0, 0, 0
Even though the PCI part needs some work I don't think that's the problem since PS/2 has the exact same issue.
Here is the part responsible for setting up the PIC and RTC:

Code: Select all

	;intialize PIC
	;ICW1
	mov al, 00010001b
	out 0020h, al
	out 00a0h, al
	;ICW 2
	mov al, 20h	;after reserved interrupts
	out 0021h, al
	mov al, 28h
	out 00a1h, al
	;ICW 3
	mov al, 4
	out 0021h, al
	mov al, 2
	out 00a1h, al
	;ICW 4
	mov al, 1
	out 0021h, al
	out 00a1h, al
	
	;enable IRQ 8
	in al, 0xa1
	and al, 11111110b
	out 0xa1, al
	;enable RTC
	mov al, 8bh
	out 70h, al
	in al, 71h
	or al, 01000000b
	and al, 11001111b
	xchg bl, al
	mov al, 8bh
	out 70h, al
	xchg bl, al
	out 71h, al
	;set RTC frequency
	mov al, 8ah
	out 70h, al
	in al, 71h
	and al, 0xf0
	or al, 08h	;256Hz
	xchg al, bl
	mov al, 8ah
	out 70h, al
	xchg al, bl
	out 71h, al
Could this be a bug in Bochs?

Re: RTC timer fails after reboot only in Bochs

Posted: Mon Feb 15, 2016 9:28 am
by Combuster
The master PIC doesn't have the slave unmasked.

Re: RTC timer fails after reboot only in Bochs

Posted: Mon Feb 15, 2016 12:32 pm
by sleephacker
I sort of figured it out.
I saved Bochs state before and after rebooting a couple of times, and noticed that in the PIC file slave.IRQ_in was always set to 0x01 after rebooting, which leads me to believe the IRQ 8 line got stuck high.
So I added an

Code: Select all

int 28h
after the PIC initialization which translates to IRQ 8, hoping that this would reset the IRQ 8 line, and it just worked!

I still don't know what caused this issue in the first place though...

[Solved] RTC timer fails after reboot only in Bochs

Posted: Fri Apr 28, 2017 1:27 pm
by sleephacker
More than a year later, the problem has been solved (credits to Octocontrabass who provided the solution in another thread).

It turns out the reason why doing 'int 28h' fixed it was because within the int 28h handler the status register C is read because that's needed to acknowledge pending RTC interrupts, which were apparently the cause of this bug. The problem was solved by removing the 'int 28h' and replacing it with the following code, at the end of the RTC initialisation:

Code: Select all

;read status register C to acknowledge pending RTC interrupts
mov al, 0ch
out 70h, al
in al, 71h
After coming back to this I've noticed an additional problem with my original RTC init code: NMIs were never enabled again. Instead normal interrupts were enabled, soon after which an IRQ 8 arrived causing NMIs to be enabled again while reading status register C, which is probably why I've never noticed this bug, even on real hardware. This problem has now also been fixed by sending 0x0C (select RTC status reg C, and enable NMIs) to port 0x70 instead of sending 0x8C (which would have left NMIs disabled).

I've added the solution to the original problem to the part about status reg C on the wiki:
On the wiki, I wrote:[...] If you're using Bochs, it is also recommended to read Status Register C after initialising the RTC, to make sure any RTC interrupts that were pending before/while the RTC was initialised are acknowledged (not doing this has lead to the RTC timer not sending any interrupts after rebooting in at least one case, observed on Bochs 2.6.6, see this thread)
But I'm not sure if I've worded it correctly, should it really just be a recommendation for bochs only (because it's only a problem on bochs, if that's even true) or is it actually a must (which seems unlikely because by default RTC interrupts are disabled, so there's no way there can be any interrupts pending before/while the RTC is initialised)? Or should this not be added to the wiki at all?