GPF when seting tss and entring to usermode

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
sajadbanooie
Posts: 8
Joined: Mon Jun 06, 2016 2:04 am

GPF when seting tss and entring to usermode

Post by sajadbanooie »

When I tried to enter ring 3 I got GPF first I thought that I't because that I don't have a working tss. when I tried to set tss I got GPF again. this is the code which I use to enter user mode:

Code: Select all

global switch_to_usermode
extern Ring3_EIP
extern Ring3_ESP
switch_to_usermode:
    cli
    mov ax, 0x23
    mov ds, ax
    mov es, ax
    mov fs, ax
    mov gs, ax
    push  dword 0x23
    push  dword Ring3_ESP
    pushfd
    push  dword 0x1B
    push  dword Ring3_EIP
    iretd
this is the code I used to set tss:

Code: Select all

settss:
	cli
	mov eax, 0x2b
	ltr ax
	sti
	ret

Code: Select all

void install_tss(void){
	memset ((void*) &TSS, 0, sizeof (struct tss_entry));

	TSS.ss0 = 0x10;
	TSS.esp0 = stack_top;
	
	//! flush tss
	settss ();
}
GPF err_code when tried to switch to user mode is 0x20 which is my PL3 data segment selector
GPF err_code when tried to switch to user mode is 0x28 which is tss selector
heat
Member
Member
Posts: 103
Joined: Sat Mar 28, 2015 11:23 am
Libera.chat IRC: heat

Re: GPF when seting tss and entring to usermode

Post by heat »

We can't do much with not a lot of info. Show us your GDT, your TSS and check if it's valid.
Your TSS loading code looks ok, and the switch_to_usermode looks alright too.
Also, do you make an entry in the GDT for the TSS?
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
sajadbanooie
Posts: 8
Joined: Mon Jun 06, 2016 2:04 am

Re: GPF when seting tss and entring to usermode

Post by sajadbanooie »

yes I do here's my code:

Code: Select all

void init_gdt(void){
	gp.limit = (sizeof(struct gdt_entry) * 3) - 1;
    	gp.base = &gdt;
// null
	add_gdt_entry(0, 0, 0, 0, 0);
	// kernel cs
	add_gdt_entry(1, 0, 0xFFFFFFFF, 0xCF, 0x9A);

	// kernel ds
	add_gdt_entry(2,0, 0xFFFFFFFFF, 0xCF, 0x92);
	
	// user cs
	add_gdt_entry(3, 0, 0xFFFFFFFF, 0xCF, 0xFA);
	
	// user ds
	
	add_gdt_entry(4,0, 0xFFFFFFFFF, 0xCF, 0xF2);
	
	// tss
	add_gdt_entry(5,&TSS,sizeof(TSS), 0xCF, 0xE9);
	
	setgdt();
	reloadseg();

Code: Select all

extern gp
setgdt:
   LGDT  [gp]
   RET


reloadseg:
   JMP   0x08:.reload_CS 
   
.reload_CS:

   MOV   AX, 0x10 
   MOV   DS, AX
   MOV   ES, AX
   MOV   FS, AX
   MOV   GS, AX
   MOV   SS, AX
   RET
heat
Member
Member
Posts: 103
Joined: Sat Mar 28, 2015 11:23 am
Libera.chat IRC: heat

Re: GPF when seting tss and entring to usermode

Post by heat »

sajadbanooie wrote:yes I do here's my code:

Code: Select all

void init_gdt(void){
	gp.limit = (sizeof(struct gdt_entry) * 3) - 1;
    	gp.base = &gdt;
// null
	add_gdt_entry(0, 0, 0, 0, 0);
	// kernel cs
	add_gdt_entry(1, 0, 0xFFFFFFFF, 0xCF, 0x9A);

	// kernel ds
	add_gdt_entry(2,0, 0xFFFFFFFFF, 0xCF, 0x92);
	
	// user cs
	add_gdt_entry(3, 0, 0xFFFFFFFF, 0xCF, 0xFA);
	
	// user ds
	
	add_gdt_entry(4,0, 0xFFFFFFFFF, 0xCF, 0xF2);
	
	// tss
	add_gdt_entry(5,&TSS,sizeof(TSS), 0xCF, 0xE9);
	
	setgdt();
	reloadseg();

Code: Select all

extern gp
setgdt:
   LGDT  [gp]
   RET


reloadseg:
   JMP   0x08:.reload_CS 
   
.reload_CS:

   MOV   AX, 0x10 
   MOV   DS, AX
   MOV   ES, AX
   MOV   FS, AX
   MOV   GS, AX
   MOV   SS, AX
   RET
Try doing this when creating the TSS gdt entry

Code: Select all

add_gdt_entry(5,&TSS,sizeof(TSS), 0, 0xE9);
Also show us the output bochs gives with

Code: Select all

info gdt
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
sajadbanooie
Posts: 8
Joined: Mon Jun 06, 2016 2:04 am

Re: GPF when seting tss and entring to usermode

Post by sajadbanooie »

thanks for your help the problem is fixed.when I installed bochs and used its internal debugger it showed that my gdt has only 3 entries then I realized that the problem is with gdt limit.
the problem was this line:

Code: Select all

gp.limit = (sizeof(struct gdt_entry) * 3) - 1;
I changed it to:

Code: Select all

gp.limit = (sizeof(struct gdt_entry) * 6) - 1;
now every thing is working right
heat
Member
Member
Posts: 103
Joined: Sat Mar 28, 2015 11:23 am
Libera.chat IRC: heat

Re: GPF when seting tss and entring to usermode

Post by heat »

Oh yes, I didn't see that error in your code. Anyways, have fun!
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