Page 1 of 1

Task & DPL3

Posted: Tue Mar 29, 2005 6:04 am
by Guest
Hello, i have problems running a task within ring3.

Code: Select all

           
   SetGdtEntry(0,0,0,0,0);                            // 0x00
   SetGdtEntry(1, 0, 0xFFFFFFFF, 0x9A, 0xCF);             // 0x08
   SetGdtEntry(2, 0, 0xFFFFFFFF, 0x92, 0xCF);             // 0x10
   SetGdtEntry(3, 0x0B8000, 0x0FFFFF, 0x92, 0xCF);          // 0x18
    SetGdtEntry(4, &tss[0], sizeof(struct TSS), 0x89, 0x5F); // 0x20
    SetGdtEntry(5, &tss[1], sizeof(struct TSS), 0x89, 0x5F); // 0x28
    SetGdtEntry(6, &tss[2], sizeof(struct TSS), 0x89, 0x5F); // 0x30
    SetGdtEntry(7, 0, 0xFFFFFFFF, 0xFA, 0xCF);               // 0x38  code / dpl3
    SetGdtEntry(8, 0, 0xFFFFFFFF, 0xF2, 0xCF);             // 0x40  data / dpl3

   tss[[0]].EFlags = 0x202;
   tss[[0]].Cs = 0x38;
   tss[[0]].Ss = 0x40;
   tss[[0]].Esp = 0x95000;
   tss[[0]].Ds = 0x40;
   tss[[0]].Eip = &task;
   tss[[0]].Trace = 0;
   tss[[0]].IoMap = sizeof(struct TSS);


             
             void task()
             {
         for (;;);
             }



void main()
{
   ReprogramPics();
   SetupGdt();

   asm("ljmp 0x20,0\n");

   for (;;);
}
When i jump in segment 0x20 i get exception 0.
But when i change the descriptor 0x38 & 0x40 to dpl0 i dont get an exeption. Pls Help !

Re:Task & DPL3

Posted: Tue Mar 29, 2005 6:20 am
by AR
I can't remember with any certainty but I think CPL0 code cannot jump/call DPL3, people usually use an IRET hack (push CS,EIP,SS[IIRC] and execute IRET)

Re:Task & DPL3

Posted: Tue Mar 29, 2005 6:58 am
by Pype.Clicker
the 'no call to DPL3' code restriction does not apply when you perform a hardware-assisted task switch. However, as soon as you enter level 3 code, you *need* a valid stack pointer in SS0:ESP0 to handle exception.

You should also load a proper TSS selector in TR register *prior* you jump/call another TSS so that the current state of the processor can be saved somewhere. If you're not concerned about being able to *return* to that state, just use a "dummy" TSS that you'll never jump to (also known as "trash" TSS)

Re:Task & DPL3

Posted: Tue Mar 29, 2005 7:23 am
by Guest
Hi, it still doesnt work.

Code: Select all

   tss[0].EFlags = 0x202;
   tss[0].Cs = 0x38;
   tss[0].Ss = 0x40;
   tss[0].Esp = 0x95000;
   tss[0].Ds = 0x40;
   tss[0].Eip = &task;
   tss[0].Trace = 0;
   tss[0].IoMap = sizeof(struct TSS);
   tss[0].Ss0 = 0x10;
   tss[0].Esp0 = 0x90000;


void main()
{
   ReprogramPics();
   SetupGdt();

   asm("ltr ax\n"::"a"(0x30));
   asm("ljmp 0x20,0\n");

   for (;;);
}
[edit by candy] Use the code tags [/edit]

Re:Task & DPL3

Posted: Tue Mar 29, 2005 7:41 pm
by proxy
do you have the access level of the tasks pages accessible to ring3 code?

if not, i imagine that's part of the problem

proxy

Re:Task & DPL3

Posted: Thu Mar 31, 2005 2:54 am
by Pype.Clicker
do you have paging enabled ? if yes, you're not filling the "CR3" value of the TSS, which may explain why it works so bad.

Also, i'm not sure i got right what that "5F" argument means, but it looks weird to me (bits 16..19 of TSS limit set ??? and 'AVL' bit set ??? what's the point ... )

Re:Task & DPL3

Posted: Thu Mar 31, 2005 6:44 am
by Guest
Hello, oh yes 5F is wrong. I changed to 4F but i still get the exception. Paging is disabled. With DPL0 code & data segment all work fine. But i want DPL3 :-\

Help!

Re:Task & DPL3

Posted: Thu Mar 31, 2005 6:56 am
by mystran
They way I've always done the switch to userspace is to setup everything, have a kernel-level task, then build a "fake" interrupt stack (that is, have the stuff in stack that you would have if you were serving an interrupt request) and then simply "restore" all registers and finally "IRET" to userspace, like if you were coming from a system call.

I like the method because I can use the same code for going into userspace whether or not we've actually ever been there. Another nice thing is that it handles loading SS automatically at the same time with CS, so userspace has a valid stack from the start.

Oh, and if you are using GCC for your inline assembly, you realize that you need % before registers, and $ before immediates.

So, basicly, what you probably want is (IIRC, didn't test):

Code: Select all

asm("ltr %ax;"::"a"(0x30));
asm("ljmp $0x20, $0");

Re:Task & DPL3

Posted: Thu Mar 31, 2005 7:33 am
by Guest
Hi, i am using the -masm=intel option to use intel syntax.

Re:Task & DPL3

Posted: Thu Mar 31, 2005 9:30 am
by Guest
Heya, i have it ! I forgot to set the RPL bits in the selector to 3 ;D

Code: Select all

tss[0].EFlags = 0x202;
tss[0].Cs = 0x38|3;
tss[0].Ss = 0x40|3;
tss[0].Esp = 0x95000;
tss[0].Ds = 0x40|3;