Page 1 of 1

Syscall causes triple fault.

Posted: Wed Jan 23, 2013 7:32 pm
by ablakely
Whenever I do a syscall, the system triple faults. I'm not sure what's causing it. Currently I'm using the code from JamesM's tutorial, but I eventually plan on writing my own code.

Code: Select all

00031052840i[GDBST] setting breakpoint at 103b48
00031052844i[CPU0 ] CPU is in protected mode (active)
00031052844i[CPU0 ] CS.d_b = 32 bit
00031052844i[CPU0 ] SS.d_b = 32 bit
00031052844i[CPU0 ] EFER   = 0x00000000
00031052844i[CPU0 ] | RAX=0000000000000000  RBX=0000000000105664
00031052844i[CPU0 ] | RCX=000000000000000a  RDX=00000000000b03d5
00031052844i[CPU0 ] | RSP=00000000dfffffb0  RBP=00000000e0000014
00031052844i[CPU0 ] | RSI=0000000000053c9d  RDI=0000000000053c9e
00031052844i[CPU0 ] |  R8=0000000000000000   R9=0000000000000000
00031052844i[CPU0 ] | R10=0000000000000000  R11=0000000000000000
00031052844i[CPU0 ] | R12=0000000000000000  R13=0000000000000000
00031052844i[CPU0 ] | R14=0000000000000000  R15=0000000000000000
00031052844i[CPU0 ] | IOPL=0 id vip vif ac vm RF nt of df if tf SF zf af pf cf
00031052844i[CPU0 ] | SEG selector     base    limit G D
00031052844i[CPU0 ] | SEG sltr(index|ti|rpl)     base    limit G D
00031052844i[CPU0 ] |  CS:001b( 0003| 0|  3) 00000000 ffffffff 1 1
00031052844i[CPU0 ] |  DS:0023( 0004| 0|  3) 00000000 ffffffff 1 1
00031052844i[CPU0 ] |  SS:0023( 0004| 0|  3) 00000000 ffffffff 1 1
00031052844i[CPU0 ] |  ES:0023( 0004| 0|  3) 00000000 ffffffff 1 1
00031052844i[CPU0 ] |  FS:0023( 0004| 0|  3) 00000000 ffffffff 1 1
00031052844i[CPU0 ] |  GS:0023( 0004| 0|  3) 00000000 ffffffff 1 1
00031052844i[CPU0 ] |  MSR_FS_BASE:0000000000000000
00031052844i[CPU0 ] |  MSR_GS_BASE:0000000000000000
00031052844i[CPU0 ] | RIP=0000000000103b55 (0000000000103b55)
00031052844i[CPU0 ] | CR0=0xe0000011 CR2=0x00000000fffffffc
00031052844i[CPU0 ] | CR3=0x001a3000 CR4=0x00000000
00031052844i[CPU0 ] 0x0000000000103b55>> int 0x80 : CD80
00031052844e[CPU0 ] exception(): 3rd (14) exception with no resolution, shutdown status is 00h, resetting
I can provide source code if needed. Any pointers as to what is happening would be appreciated.

Re: Syscall causes triple fault.

Posted: Wed Jan 23, 2013 7:40 pm
by BMW
If I understand that log correctly, CS = 0x1B... 0x1B is not a valid selector... it must be a multiple of 0x08 e.g. 0x08, 0x10 as it points to an entry in the GDT and entries in the GDT are 0x08 bytes in size.

Re: Syscall causes triple fault.

Posted: Wed Jan 23, 2013 8:08 pm
by linguofreak
BMW wrote:If I understand that log correctly, CS = 0x1B... 0x1B is not a valid selector... it must be a multiple of 0x08 e.g. 0x08, 0x10 as it points to an entry in the GDT and entries in the GDT are 0x08 bytes in size.
No. Descriptor table entries are 8 bytes in size, but the third from lowest bit of a selector selects whether the segment should be taken from the LDT or GDT, and the low two bits determine the requested privilege level.

0x1B is selector 0x18 with an RPL of 3.

Re: Syscall causes triple fault.

Posted: Wed Jan 23, 2013 8:19 pm
by ablakely
linguofreak wrote:
BMW wrote:If I understand that log correctly, CS = 0x1B... 0x1B is not a valid selector... it must be a multiple of 0x08 e.g. 0x08, 0x10 as it points to an entry in the GDT and entries in the GDT are 0x08 bytes in size.
No. Descriptor table entries are 8 bytes in size, but the third from lowest bit of a selector selects whether the segment should be taken from the LDT or GDT, and the low two bits determine the requested privilege level.

0x1B is selector 0x18 with an RPL of 3.
My GDT and such seem to be working correctly, but who knows it might be breaking whenever I write the TSS. I'm able to enter ring 3 fine, but the issue I'm having is that whenever I do any system call it triple faults.

If it'll help, my code can be found here: https://github.com/ablakely/xnix

Re: Syscall causes triple fault.

Posted: Wed Jan 23, 2013 10:29 pm
by thepowersgang
The original exception number is 14 (in brackets after '3rd'), this is a page fault. The address that caused the page fault is stored in CR2, and is 0xfffffffc.
This looks to me like your TSS's ESP0 field is currently set to 0, instead of the kernel stack's top.

Re: Syscall causes triple fault.

Posted: Thu Jan 24, 2013 6:19 pm
by ablakely
thepowersgang wrote:This looks to me like your TSS's ESP0 field is currently set to 0, instead of the kernel stack's top.
Oh, thanks! I forgot to update the ESP0 when I switched tasks. :oops:

It no longer crashes, but syscalls still seem to be broken, the handler doesn't seem to be called at all. I'll investigate this more.

Re: Syscall causes triple fault.

Posted: Thu Jan 24, 2013 8:28 pm
by ablakely
It seems that the interrupt 0x80 isn't being caught (as my handler is never called).

I don't think I'm disabling interrupts anywhere and forgetting to re-enable them. Could it be how I'm entering usermode?

Code: Select all

void switch_to_user_mode()
{
        set_kernel_stack(current_task->kernel_stack+KERNEL_STACK_SIZE);

        printf("Attempting to switch to user mode.\n");
        asm volatile("                  \
                mov $0x23, %ax;         \
                mov %ax, %ds;           \
                mov %ax, %es;           \
                mov %ax, %fs;           \
                mov %ax, %gs;           \
                                        \
                mov %esp, %eax;         \
                pushl $0x23;            \
                pushl %eax;             \
                pushf;                  \
                pushl $0x1B;            \
                push $1f;               \
                iret;                   \
        1:                              ");

}
Edit: It appears the interrupt being caught when I do a syscall is 0xF0.