Page 1 of 1

Triple-faults on startup [SOLVED]

Posted: Tue Mar 13, 2007 1:44 am
by pcmattman
I keep getting triple faults on startup of my OS, and often it takes several restarts before the OS actually successfully boots.

Part of the Bochs log is below:

Code: Select all

00241772720e[CPU0 ] interrupt(): gate descriptor is not valid sys seg
00241772720e[CPU0 ] interrupt(): gate descriptor is not valid sys seg
00241772720e[CPU0 ] interrupt(): gate descriptor is not valid sys seg
00241772720i[CPU0 ] protected mode
00241772720i[CPU0 ] CS.d_b = 32 bit
00241772720i[CPU0 ] SS.d_b = 32 bit
00241772720i[CPU0 ] | EAX=0010c8a0  EBX=00108000  ECX=0019ae0f  EDX=00000000
00241772720i[CPU0 ] | ESP=0019ae08  EBP=0019ae18  ESI=0002be83  EDI=0002be88
00241772720i[CPU0 ] | IOPL=0 id vip vif ac vm RF nt of df IF tf sf ZF af PF cf
00241772720i[CPU0 ] | SEG selector     base    limit G D
00241772720i[CPU0 ] | SEG sltr(index|ti|rpl)     base    limit G D
00241772720i[CPU0 ] |  CS:0008( 0001| 0|  0) 00000000 000fffff 1 1
00241772720i[CPU0 ] |  DS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00241772720i[CPU0 ] |  SS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00241772720i[CPU0 ] |  ES:0010( 0002| 0|  0) 00000000 000fffff 1 1
00241772720i[CPU0 ] |  FS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00241772720i[CPU0 ] |  GS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00241772720i[CPU0 ] | EIP=00104d9a (00104d9a)
00241772720i[CPU0 ] | CR0=0x00000011 CR1=0 CR2=0x00000000
00241772720i[CPU0 ] | CR3=0x00000000 CR4=0x00000000
00241772720i[CPU0 ] >> leave  : C9
00241772720e[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting
I think it may be a problem in my GDT, but I haven't had any trouble up until now. The only reason I can think of that would have caused this is a recent modification to my multitasker, which I took out after this started appearing.

Posted: Tue Mar 13, 2007 3:44 am
by Combuster
Have you considered disabling interrupts when you don't have a functional IDT? :shock:

Posted: Tue Mar 13, 2007 4:17 am
by pcmattman
Interrupts are disabled at startup, then my kernel enables them after it finishes booting. I doubt that's the problem.

Re: Triple-faults on startup

Posted: Tue Mar 13, 2007 4:22 am
by pjt
pcmattman wrote:I think it may be a problem in my GDT, but I haven't had any trouble up until now. The only reason I can think of that would have caused this is a recent modification to my multitasker, which I took out after this started appearing.
This happened to me, when I added the system call interrupt, but the GDT wasn't big enough. :)

Posted: Tue Mar 13, 2007 4:53 am
by Combuster
The problem is that your IDT is bogus:
00241772720e[CPU0 ] interrupt(): gate descriptor is not valid sys seg
In itself this is not a problem. Enabling interrupts is on itself not a problem.
However, this combination of circumstances forces the processors to use a broken IDT which will obviously not work.

Posted: Tue Mar 13, 2007 3:38 pm
by pcmattman
The GDT is definitely big enough, I've removed the code that first caused this from the multitasker (and rebuilt the library).

It really started when I attempted to change the RTC clock speed using code like this:

Code: Select all

void SetClockRate( int hz )
{
	int divisor = 1193180 / hz;       /* Calculate our divisor */
	outportb(0x43, 0x36);             /* Set our command byte 0x36 */
	outportb(0x40, divisor & 0xFF);   /* Set low byte of divisor */
	outportb(0x40, divisor >> 8);     /* Set high byte of divisor */
}
I have no idea what went wrong there :(. Either way, I'm still really confused as to why this is happening. There's got to be a way of fixing this... and to think I was so close to beta testing :(.

Posted: Tue Mar 13, 2007 3:48 pm
by ~
At what rate is your RTC? I remember having a problem like that when I tried to get nanoseconds with the RTC and ended up with miliseconds, and I don't remember if the PC locked or it restarted, but it was giving problems, maybe was more than the RTC could handle.

Try commenting out that routine call or use a lower rate; if that doesn't work it should be some change you don't remember having done that you did to test code and was forgotten and now is giving problems.

Posted: Tue Mar 13, 2007 3:51 pm
by pcmattman
I commented out changing the clock rate, and I've checked over all of the code of my OS (that's not an easy task, either). All of the test code has been removed.

Hang on a second, I just figured it out! My memset, memcpy etc... functions disable interrupts before they start. Afterwards, they enable them again! I think I did this because my GUI was halting during mem* function calls, which may instead be a problem with the multitasker and not the calls.

Edit: fixed the problem, took out the interrupt stuff in mem* functions and replaced it with disabling and enabling multitasking. Everything works properly now...

Posted: Fri Mar 16, 2007 12:03 am
by pcmattman
I just found a good use for this: whenever I need to restart the computer, I just enable interrupts (just in case they weren't already) and then do this:

Code: Select all

while( true )
    idt_install();
// never get here
Because interrupts are enabled, it trashes the IDT and triple faults the CPU. I think it's pretty nifty :D.

Posted: Fri Mar 16, 2007 1:38 pm
by mystran
Suggestion for temporarily disabling interrupts:

Write a pair of functions, one of which disables interrupts, and returns 1 if interrupts where enabled, 0 if not. The other takes one arguments, and enables interrupts if the argument is true.

Basicly:

Code: Select all


int disable_interrupts() {
   int val = true_if_interrupts_enabled();
   if(val) disable_interrupts_real();
   return val;
}

void restore_interrupts(int state) {
  if(val) enable_interrupts();
}
You can then do stuff like:

Code: Select all

void non_reentrant_function() {

   int istate = disable_interrupts();

   /* do whatever needs interrupts disabled */

   restore_interrupts(istate);
}
Now you'll never accidentally enable interrupts unless you actually disabled them. :)

Posted: Fri Mar 16, 2007 1:49 pm
by ehird
pcmattman wrote: Because interrupts are enabled, it trashes the IDT and triple faults the CPU. I think it's pretty nifty :D.
Linux does that as a last resort. Presumably for a reason ;)