software task switch

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
octavio

software task switch

Post by octavio »

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.
lode

Re:software task switch

Post by lode »

I think you need to do push user_stack_segment+3
Are you pushing eflags (4 bytes) and not flags (2 bytes) ?
OZ

Re:software task switch

Post by OZ »

I think you do need to set the rpl of all your segments you're going to pop to 3 or what you wanted.

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
this works for me with software switching.
hope it helps
octavio

Re:software task switch

Post by octavio »

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.
lode

Re:software task switch

Post by lode »

You said paging is enabled, have you checked that the pagetables indicate that the memory is accessible in ring 3 ?
octavio

Re:software task switch

Post by octavio »

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.

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
 }

octavio

Re:software task switch

Post by octavio »

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.

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
also don't understand why bochs says 'gate286' if descriptor types are 14 = interrupt 386
octavio

Re:software task switch

Post by octavio »

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.
Post Reply