Page 1 of 1
GPF when seting tss and entring to usermode
Posted: Mon Jun 06, 2016 6:13 am
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
Re: GPF when seting tss and entring to usermode
Posted: Mon Jun 06, 2016 9:51 am
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?
Re: GPF when seting tss and entring to usermode
Posted: Mon Jun 06, 2016 10:51 am
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
Re: GPF when seting tss and entring to usermode
Posted: Mon Jun 06, 2016 11:04 am
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
Re: GPF when seting tss and entring to usermode
Posted: Mon Jun 06, 2016 11:19 pm
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
Re: GPF when seting tss and entring to usermode
Posted: Tue Jun 07, 2016 6:16 pm
by heat
Oh yes, I didn't see that error in your code. Anyways, have fun!