Problems while switching to user-mode (x86_64)

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
heat
Member
Member
Posts: 103
Joined: Sat Mar 28, 2015 11:23 am
Libera.chat IRC: heat

Problems while switching to user-mode (x86_64)

Post by heat »

Hello,

I've depared myself with a problem while switching to user-mode in my x86_64 kernel. If I try to execute an ELF file with my TSS register loaded, it triple faults with the CR2 set to 0xfffff79ffffffff8. If I don't, the program never gets executed.

I'm sure that the task switching part of my code is correct, or at least the kernel thread part, as I have to start using some features like the gs and fs segment registers.
I'm sure the addresses of the executable are mapped correctly, with the user-bit set and everything. The user-space code doesn't even do anything special, it's just a while(1) loop, without C library initialization or anything.

Qemu's register dump of the triple fault:

Code: Select all

CPU Reset (CPU 0)
RAX=0000000000000000 RBX=0000000000000000 RCX=0000000000000000 RDX=0000000000000000
RSI=0000000000000000 RDI=0000000000000000 RBP=0000000000000000 RSP=00007a0000002000
R8 =0000000000000000 R9 =0000000000000000 R10=0000000000000000 R11=0000000000000000
R12=0000000000000000 R13=0000000000000000 R14=0000000000000000 R15=0000000000000000
RIP=0000000008048080 RFL=00010002 [-------] CPL=3 II=0 A20=1 SMM=0 HLT=0
ES =0023 0000000000000000 00000fff 00a0f300 DPL=3 DS   [-WA]
CS =001b 0000000000000000 00000fff 00a0fb00 DPL=3 CS64 [-RA]
SS =0023 0000000000000000 00000fff 00a0f300 DPL=3 DS   [-WA]
DS =0023 0000000000000000 00000fff 00a0f300 DPL=3 DS   [-WA]
FS =0023 0000000000000000 00000fff 00a0f300 DPL=3 DS   [-WA]
GS =0023 0000000000000000 00000fff 00a0f300 DPL=3 DS   [-WA]
LDT=0000 0000000000000000 0000ffff 00008200 DPL=0 LDT
TR =002b ffffffff8010c000 00000067 0000eb00 DPL=3 TSS64-busy
GDT=     ffffffff80100131 00000038
IDT=     ffffffff801199e0 00000fff
CR0=80000013 CR2=fffff79ffffffff8 CR3=0000000000101000 CR4=00000620
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000 
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=0000000000000000 CCD=0000000000000000 CCO=DYNAMIC 
EFER=0000000000000d01
FCW=037f FSW=0000 [ST=0] FTW=00 MXCSR=00001f80
FPR0=0000000000000000 0000 FPR1=0000000000000000 0000
FPR2=0000000000000000 0000 FPR3=0000000000000000 0000
FPR4=0000000000000000 0000 FPR5=0000000000000000 0000
FPR6=0000000000000000 0000 FPR7=0000000000000000 0000
XMM00=00000000000000000000000000000000 XMM01=00000000000000000000000000000000
XMM02=00000000000000000000000000000000 XMM03=00000000000000000000000000000000
XMM04=00000000000000000000000000000000 XMM05=00000000000000000000000000000000
XMM06=00000000000000000000000000000000 XMM07=00000000000000000000000000000000
XMM08=00000000000000000000000000000000 XMM09=00000000000000000000000000000000
XMM10=00000000000000000000000000000000 XMM11=00000000000000000000000000000000
XMM12=00000000000000000000000000000000 XMM13=00000000000000000000000000000000
XMM14=00000000000000000000000000000000 XMM15=00000000000000000000000000000000
As I can see below, I know I technically switched to ring 3, but it faults on the very first instruction.

Thanks for the help
If some of you people keep insisting on having backwards compatibitity with the stone age, we'll have stone tools forever.
My Hobby OS: https://github.com/heatd/Onyx
User avatar
BrightLight
Member
Member
Posts: 901
Joined: Sat Dec 27, 2014 9:11 am
Location: Maadi, Cairo, Egypt
Contact:

Re: Problems while switching to user-mode (x86_64)

Post by BrightLight »

I'm assuming your page fault handler didn't get called, so it's likely your TSS has an error, your IDT has an error, or the pages are not user-accessible.
You know your OS is advanced when you stop using the Intel programming guide as a reference.
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: Problems while switching to user-mode (x86_64)

Post by Combuster »

First reaction: why does the task register have bits 0-1 set?
"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 ]
heat
Member
Member
Posts: 103
Joined: Sat Mar 28, 2015 11:23 am
Libera.chat IRC: heat

Re: Problems while switching to user-mode (x86_64)

Post by heat »

This is my GDT:

Code: Select all

tmp_gdt:
	DQ	0x0000000000000000
	DQ	0x00A09A0000000000
	DQ	0x00A0920000000000
	DQ	0x00A0FA0000000000
	DQ	0x00A0F20000000000
	DW	0x67,0xc000
	DB	0x10, 0xE9, 0
	DB	0x80
	DD	0xffffffff
With the reply above, I assume something is wrong with it?
TSS code:

Code: Select all

extern tss_entry_t tss;
extern void tss_flush();
void init_tss()
{
	printf("tss: %x\n",&tss);
	memset(&tss, 0, sizeof(tss_entry_t));
	tss.stack0 = (uint64_t)vmm_allocate_virt_address(VM_KERNEL, 2, VMM_TYPE_STACK);
	vmm_map_range((void*)tss.stack0, 2, 0x3);
	tss.ist[0] = tss.stack0;
	tss_flush();
}
tss is a label I define in the linker script.
TSS struct:

Code: Select all

typedef struct tss_entry
{
	uint32_t reserved0;
	uint64_t stack0;
	uint64_t stack1;
	uint64_t stack2;
	uint64_t reserved1;
	uint64_t ist[7];
	uint64_t reserved2;
	uint16_t reserved3;
	uint16_t iomap_base;
} __attribute__((packed)) tss_entry_t;
Also, if the TSS is invalid, why would that contribute to having a #PF? Especially in a such high address.
Last edited by heat on Sun Jun 12, 2016 6:59 am, edited 1 time in total.
If some of you people keep insisting on having backwards compatibitity with the stone age, we'll have stone tools forever.
My Hobby OS: https://github.com/heatd/Onyx
User avatar
iansjack
Member
Member
Posts: 4706
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: Problems while switching to user-mode (x86_64)

Post by iansjack »

The GDT entry for your user mode code segment seems to be all zeros. That doesn't look right.
heat
Member
Member
Posts: 103
Joined: Sat Mar 28, 2015 11:23 am
Libera.chat IRC: heat

Re: Problems while switching to user-mode (x86_64)

Post by heat »

iansjack wrote:The GDT entry for your user mode code segment seems to be all zeros. That doesn't look right.
Oh, yeah I forgot to explain that it contains the 32-bit GDT segments it uses to bootstrap itself to 64-bit. Let me edit that out.
If some of you people keep insisting on having backwards compatibitity with the stone age, we'll have stone tools forever.
My Hobby OS: https://github.com/heatd/Onyx
Post Reply