Hello ,i want to test some code on my OS with cpl=3
i have setup one tss and loaded with 'ltr' instruction.
one data segment for all tasks with dpl=3
and two code segments not conforming with dpl=0 and dpl=3
paging is enabled but virtual address=physical
i tested this code from a privilege level 0
push user stack segment ;dpl=3
push user stack pointer
push flags
push user_code_segment ;dpl=3
push user_code_offset
iret ;cpl=0
and cpl not changed ,also the user stack was not loaded
then i try this:
push user stack pointer and segment
push flags
push user_code_segment+3 ;dpl=3 rpl=3
push user_code_offset
iret
the result is a GPF related to code segment, i read again the
Intel docs but don?t understand the problem, and all the samples i have seen use hardware task switch.
Can somebody explain how to jmp to a task with
different privilege level.
software task switch
Re:software task switch
I think you need to do push user_stack_segment+3
Are you pushing eflags (4 bytes) and not flags (2 bytes) ?
Are you pushing eflags (4 bytes) and not flags (2 bytes) ?
Re:software task switch
I think you do need to set the rpl of all your segments you're going to pop to 3 or what you wanted.
this works for me with software switching.
hope it helps
Code: Select all
kstack[0]=0x20 | 3; //gs
kstack[1]=0x20 | 3; //fs
kstack[2]=0x20 | 3; //es
kstack[3]=0x20 | 3; //ds
kstack[4]=0; //edi
kstack[5]=0; //esi
kstack[6]=0; //ebp
kstack[7]=0; //esp
kstack[8]=0; //ebx
kstack[9]=0; //edx
kstack[10]=0; //ecx
kstack[11]=0; //eax
kstack[12]=(uint)0x40800000; //entry point (eip)
kstack[13]=0x18 | 0x03; //cs
kstack[14]=0x0202;
kstack[15]=(uint)(ustack);//ustack; // ring 3 esp
kstack[16]=0x20 | 0x03; // ss
hope it helps
Re:software task switch
Yes,i push eflags and use a new data segment with dpl=3 and rpl=3 for the test.
I did a mistake, all segments have dpl=0, now i have corrected
this and try again with and without paging ,when i try with
rpl=0 i get a GPF as expected because the segment descriptor has dpl=3, but if i try with rpl=3 then the computer
resets.
I did a mistake, all segments have dpl=0, now i have corrected
this and try again with and without paging ,when i try with
rpl=0 i get a GPF as expected because the segment descriptor has dpl=3, but if i try with rpl=3 then the computer
resets.
Re:software task switch
You said paging is enabled, have you checked that the pagetables indicate that the memory is accessible in ring 3 ?
Re:software task switch
I did another test with interrupts disabled and the test program has a delay loop, now the computer resets after
a few seconds,so the problem is not on the 'iret' instruction,
the transition to privilege level 3 seems to work.But after
the delay loop a 'hlt' instruction should generate a int 13(gpf)
and then the computer resets.Perhaps there is something wrong with descriptors or tss, because interrupts work well
without privilege level changes.
a few seconds,so the problem is not on the 'iret' instruction,
the transition to privilege level 3 seems to work.But after
the delay loop a 'hlt' instruction should generate a int 13(gpf)
and then the computer resets.Perhaps there is something wrong with descriptors or tss, because interrupts work well
without privilege level changes.
Code: Select all
#GDT_START {
;base bytes 2,3,4,7
;limit bytes 0,1,6(bits 0-3)
executable=8 ;offset 5 del descriptor
aplication=16 ;data o code
writable=2 ;data descriptor (aplication)
readable=2 ;executable code (aplication+executable)
accessed=1
expand_down=4 ;data
conforming=4 ;code permite el acceso con nivel de privilegio
;igual o superior, sin cambiar el nivel de privelegio y sin usar call gates
;cuando se usa como datos el dpl se ignora
present=128
dpl=32 ;dpl*nivel_privilegio
granularity_4k=8000h
default=4000h ;code
big=4000h ;data
avl=1000h ;available for programmers use
;system segments types ,aplication bit=0
;descripcion nl
available_286_tss=1
_ldt=2
busy_286_tss=3
call_gate=4
task_gate=5 ;7988 ;como interrupt_386 sin el offset
interrupt_286=6
trap_286=7
available_386_tss=9
busy_386_tss=11
call_gate_386=12
interrupt_386=14 ;7996 dw offset0-15,cs(selector en gdt o ldt)
; db 0
; db interrupt_386+segment_present+dpl*0
; dw offset16-31
trap_386=15 ;8004 como interrupt_386
dq 0
;code16 base cs
dw -1,0 db 0
dw aplication+executable+readable+granularity_4k+present+0f00h
db 0
;code32 base ds
dw -1,0 db 0
dw aplication+executable+readable+granularity_4k+present+0f00h+default
db 0
;data32 base ds
dw -1,0 db 0
dw aplication+writable+granularity_4k+present+0f00h+dpl*0
db 0
;code32u base ds
dw -1,0 db 0
dw aplication+executable+readable+granularity_4k+present+0f00h+default+dpl*3
db 0
;data32u base ds
dw -1,0 db 0
dw aplication+writable+granularity_4k+present+0f00h+dpl*3
db 0
;tss0
dw 128,TSS1 db 0
dw 089h ;after 'ltr' busy bit is set.
db 0
}
#GDT_END
#TSS1{
dd 0 ;previous tss
#stacks
dd 1000H,selector\data32 ; only this data is used,i think
;next is irrelevant because there are no hardware task switch
rb 8 ;stack1
rb 8 ;stack2
dd first_page ;cr3 pdpr
#regs
dd 0 ;eip
dd 246h ;eflags
rb 20h ;regs
dd selector\data32 ;es
dd selector\code32 ;cs
dd selector\data32 ;ss
dd selector\data32 ;ds
dd 0 ;fs
dd 0 ;gs
dd 0 ;ldt
dd 0 ;io map base
#size
}
Re:software task switch
And here is the bochs output,int 13 works well without privilege level transitions but here something fails and a lot of int13 happens until the stack is overflow.
also don't understand why bochs says 'gate286' if descriptor types are 14 = interrupt 386
Code: Select all
exception(0d h)
00056452514d[CPU0 ] interrupt(): vector = 13, INT = 0, EXT = 1
00056452514d[CPU0 ] interrupt(): INTERRUPT TO INNER PRIVILEGE
00056452519d[CPU0 ] exception(0d h)
00056452519d[CPU0 ] interrupt(): vector = 13, INT = 0, EXT = 1
00056452519d[CPU0 ] int_trap_gate286(): INTERRUPT TO SAME PRIVILEGE
00056452524d[CPU0 ] exception(0d h)
00056452524d[CPU0 ] interrupt(): vector = 13, INT = 0, EXT = 1
00056452524d[CPU0 ] int_trap_gate286(): INTERRUPT TO SAME PRIVILEGE
00056452529d[CPU0 ] exception(0d h)
00056452529d[C
Re:software task switch
Mystery resolved: if cpl=3 all segments must have dpl=rpl=3 even if not
used, my mistake was to change only ss and cs. The curious think is
that the checks are not done on the iret instruction but when the first
interrupt happens.
>Your data segment descriptors don't have the BIG bit set
My stack uses only the first 32k ,but this could be a problem later
,thanks.
used, my mistake was to change only ss and cs. The curious think is
that the checks are not done on the iret instruction but when the first
interrupt happens.
>Your data segment descriptors don't have the BIG bit set
My stack uses only the first 32k ,but this could be a problem later
,thanks.