Syscall causes triple fault.

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
ablakely
Posts: 11
Joined: Wed Jan 23, 2013 9:01 am

Syscall causes triple fault.

Post 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.
User avatar
BMW
Member
Member
Posts: 286
Joined: Mon Nov 05, 2012 8:31 pm
Location: New Zealand

Re: Syscall causes triple fault.

Post 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.
Currently developing Lithium OS (LiOS).

Recursive paging saves lives.
"I want to change the world, but they won't give me the source code."
linguofreak
Member
Member
Posts: 510
Joined: Wed Mar 09, 2011 3:55 am

Re: Syscall causes triple fault.

Post 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.
ablakely
Posts: 11
Joined: Wed Jan 23, 2013 9:01 am

Re: Syscall causes triple fault.

Post 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
User avatar
thepowersgang
Member
Member
Posts: 734
Joined: Tue Dec 25, 2007 6:03 am
Libera.chat IRC: thePowersGang
Location: Perth, Western Australia
Contact:

Re: Syscall causes triple fault.

Post 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.
Kernel Development, It's the brain surgery of programming.
Acess2 OS (c) | Tifflin OS (rust) | mrustc - Rust compiler
Currently Working on: mrustc
ablakely
Posts: 11
Joined: Wed Jan 23, 2013 9:01 am

Re: Syscall causes triple fault.

Post 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.
ablakely
Posts: 11
Joined: Wed Jan 23, 2013 9:01 am

Re: Syscall causes triple fault.

Post 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.
Post Reply