Usermode GPF

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.
User avatar
Octacone
Member
Member
Posts: 1138
Joined: Fri Aug 07, 2015 6:13 am

Usermode GPF

Post by Octacone »

Hey everyone. I started entering ring 3 like 10 days ago and I am still not inside it.
BSOD-GPF.png
BSOD-GPF.png (7.25 KiB) Viewed 4925 times
I don't have a clue what is going on?

Assembly Related Code:

Code: Select all

	Enter_User_Mode:
	cli
	mov ax, 0x23
	mov ds, ax
	mov es, ax
	mov fs, ax
	mov gs, ax
	mov eax, esp
	push 0x23
	push eax
	pushf
	pop eax
	or eax, 0x200
	push eax
	push 0x1B
	iret
	ret
TSS Related Code:

Code: Select all

void TSS_Write(int32_t number, uint16_t ss0, uint32_t esp0)
{
	uint32_t base = (uint32_t) & TSS_Entry;
	uint32_t limit = base + sizeof(TSS_Entry);
	GDT_Set_Gate(number, base, limit, 0xE9, 0x00);
	Memory_Set(& TSS_Entry, 0x0, sizeof(TSS_Entry));
	TSS_Entry.ss0 = ss0;
	TSS_Entry.esp0 = esp0;
	TSS_Entry.cs = 0x0B;
	TSS_Entry.ss = 0x13;
	TSS_Entry.ds = 0x13;
	TSS_Entry.es = 0x13;
	TSS_Entry.fs = 0x13;
	TSS_Entry.gs = 0x13;
	TSS_Entry.iomap_base = sizeof(TSS_Entry);
}
Inside GDT_Install:
...
GDT_Set_Gate(3, 0, 0xFFFFFFFF, 0xFA, 0xCF);
GDT_Set_Gate(4, 0, 0xFFFFFFFF, 0xF2, 0xCF);
TSS_Write(5, 0x10, 0x0);
...
TSS_Flush();
...
I just can't figure it out. :|
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader
User avatar
BrightLight
Member
Member
Posts: 901
Joined: Sat Dec 27, 2014 9:11 am
Location: Maadi, Cairo, Egypt
Contact:

Re: Usermode GPF

Post by BrightLight »

If I were you, I'd try to enter usermode without the interrupt flag set, and the usermode code would be just a jmp $ or while(1) for testing.
The error code of the fault says the cause is descriptor 0x42 of the LDT, and I assume you don't have an LDT.
Have you tried running in Bochs? What does the log say? What does your usermode code do? Use Bochs' debugger to dump the GDT and take a look if your usermode descriptors contain what they should.
You know your OS is advanced when you stop using the Intel programming guide as a reference.
User avatar
Octacone
Member
Member
Posts: 1138
Joined: Fri Aug 07, 2015 6:13 am

Re: Usermode GPF

Post by Octacone »

omarrx024 wrote:If I were you, I'd try to enter usermode without the interrupt flag set, and the usermode code would be just a jmp $ or while(1) for testing.
The error code of the fault says the cause is descriptor 0x42 of the LDT, and I assume you don't have an LDT.
Have you tried running in Bochs? What does the log say? What does your usermode code do? Use Bochs' debugger to dump the GDT and take a look if your usermode descriptors contain what they should.
Okay I will remove the flag. My usermode code does not do anything it is just a while(1) loop that halts the CPU. I do not have an LDT. I have a problem with Bochs it uses my entire CPU power and makes my system unstable. It takes around 5-10 seconds for anything to draw, loading BIOS screen (Bochs default) takes around one minute to load.

Update: without that flag being set:
Attachments
NoFlagErrorGPF.png
NoFlagErrorGPF.png (7.19 KiB) Viewed 4914 times
Last edited by Octacone on Sat Nov 26, 2016 7:11 am, edited 2 times in total.
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader
User avatar
BrightLight
Member
Member
Posts: 901
Joined: Sat Dec 27, 2014 9:11 am
Location: Maadi, Cairo, Egypt
Contact:

Re: Usermode GPF

Post by BrightLight »

Bochs is easy to set up. Try using the default options; there shouldn't be anything CPU intensive to the degree you describe. It's the easiest way to debug such low-level code.
You know your OS is advanced when you stop using the Intel programming guide as a reference.
Gigasoft
Member
Member
Posts: 856
Joined: Sat Nov 21, 2009 5:11 pm

Re: Usermode GPF

Post by Gigasoft »

In Enter_User_Mode, you forget to push the actual address to jump to. There is also another problem: The user mode code is using the kernel mode stack.
User avatar
Octacone
Member
Member
Posts: 1138
Joined: Fri Aug 07, 2015 6:13 am

Re: Usermode GPF

Post by Octacone »

omarrx024 wrote:Bochs is easy to set up. Try using the default options; there shouldn't be anything CPU intensive to the degree you describe. It's the easiest way to debug such low-level code.
I am using default options. It is just like line by line, really really really slow. Can't debug with something that runs at 0.05 FPS.
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader
User avatar
Octacone
Member
Member
Posts: 1138
Joined: Fri Aug 07, 2015 6:13 am

Re: Usermode GPF

Post by Octacone »

Gigasoft wrote:In Enter_User_Mode, you forget to push the actual address to jump to. There is also another problem: The user mode code is using the kernel mode stack.
Now I am getting a triple fault.

Code: Select all

Enter_User_Mode:
	cli
	mov ax, 0x23
	mov ds, ax
	mov es, ax
	mov fs, ax
	mov gs, ax
	mov eax, esp
	push 0x23
	push eax
	pushf
	pop eax
	;or eax, 0x200
	push eax
	push 0x1B
	push LoopOn
	iret
LoopOn:
	hlt
	jmp LoopOn
Bochs reports: (unk. ctxt): hlt ; f4

Update:
after removing "LoopOn" code I am getting this: (unk. ctxt): mov ax, 0x002b
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader
User avatar
crunch
Member
Member
Posts: 81
Joined: Wed Aug 31, 2016 9:53 pm
Libera.chat IRC: crunch
Location: San Diego, CA

Re: Usermode GPF

Post by crunch »

Try using a separate stack for the ring 3 code. Make sure that the ring 3 stack and code pages are marked as user accessible.
Kevin
Member
Member
Posts: 1071
Joined: Sun Feb 01, 2009 6:11 am
Location: Germany
Contact:

Re: Usermode GPF

Post by Kevin »

Enough people have already mentioned that trying to get into userspace without doing a context switch (i.e. staying on the kernel stack and continue using the kernel state of the registers) is unlikely to result in anything useful, but it shouldn't be in the way of getting into usermode and crashing or hanging there.

The problem with hlt is probably that it's a privileged instruction. So you were in usermode, but the transition back to kernel mode to handle the GPF didn't work.
Developer of tyndur - community OS of Lowlevel (German)
User avatar
Octacone
Member
Member
Posts: 1138
Joined: Fri Aug 07, 2015 6:13 am

Re: Usermode GPF

Post by Octacone »

crunch wrote:Try using a separate stack for the ring 3 code. Make sure that the ring 3 stack and code pages are marked as user accessible.
How am I supposed to use a separate stack? I am not running any code at all (except while(1)).
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader
User avatar
Octacone
Member
Member
Posts: 1138
Joined: Fri Aug 07, 2015 6:13 am

Re: Usermode GPF

Post by Octacone »

(unk. ctxt): ltr ax

TSS seems to be a problem?
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader
User avatar
Octacone
Member
Member
Posts: 1138
Joined: Fri Aug 07, 2015 6:13 am

Re: Usermode Triple Fault

Post by Octacone »

I have no idea what is going on. I checked everything twice. I just don't get it. Other people have entered user mode without any problem, every tutorial I've ever seen just magically works.
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader
User avatar
crunch
Member
Member
Posts: 81
Joined: Wed Aug 31, 2016 9:53 pm
Libera.chat IRC: crunch
Location: San Diego, CA

Re: Usermode Triple Fault

Post by crunch »

octacone wrote:I have no idea what is going on. I checked everything twice. I just don't get it. Other people have entered user mode without any problem, every tutorial I've ever seen just magically works.
I understand the feeling. Took me about 5 days of banging my head on the wall to get it working. And it was because I wasn't using a separate user-access paged stack.

Code: Select all

enter_usermode:
	;push ebp
	mov ebp, esp
	cli

	mov ax, 0x20 | 3
	mov ds, ax
	mov es, ax
	mov fs, ax
	mov gs, ax

	push 0x20 | 3	; push ss3

	mov ecx, [ebp+8]
	push ecx ; push esp3

	pushf  ; push flags onto stack
	pop eax ; pop into eax
	or eax, 0x200 ; set IF (enable interrupts)
	push eax ; push eflags
	push 0x18 | 3 ; push CS, requested priv. level = 3

	xor eax, eax  ; Clear eax
	mov eax, [ebp+4] ; Load new IP into eax
	push eax ; Push EIP onto stack

	iret

To use this, allocate a new physical page for the user-level stack. Map that physical page to some address and make sure that you set the user-accessible flag in the page table entry. enter_usermode(address_of_function, user_stack). Remember that the stack grows down, so if for instance, you chose to map 0x0-0x1000 for your user stack, pass the function 0xF00 as a test.
Boris
Member
Member
Posts: 145
Joined: Sat Nov 07, 2015 3:12 pm

Re: Usermode GPF

Post by Boris »

if you read what's inside your instruction pointer you will see that it is set jusy after some instruction it was normal to do.. But in user land, it is not!

HLT is a ring0 only instruction.
You should for now do nothing, then later call a yield syscall of sorts.

The reason HLT is privileged is because you can lock a CPU if interrupts are disabled ( which can happen sometimes right after context switch, because sti takes some times before action )
User avatar
Octacone
Member
Member
Posts: 1138
Joined: Fri Aug 07, 2015 6:13 am

Re: Usermode GPF

Post by Octacone »

Boris wrote:if you read what's inside your instruction pointer you will see that it is set jusy after some instruction it was normal to do.. But in user land, it is not!

HLT is a ring0 only instruction.
You should for now do nothing, then later call a yield syscall of sorts.

The reason HLT is privileged is because you can lock a CPU if interrupts are disabled ( which can happen sometimes right after context switch, because sti takes some times before action )
I figured as much. Forgot that "hlt" was privileged instruction. #-o
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader
Post Reply