Page 2 of 5

Posted: Fri Jun 01, 2007 4:52 pm
by xyjamepa
Hi...
Now I've changed my code a little bit my multitasking consists of two tasks
main() and task() and both they are PL0.
when I enabled the VM bit in EFLAGS I didn't get any exceptions, but
when I made a long call "lcall" to the selector of the virtual task
unfortunately I got general protection fault...
here's my code and an IMG, also please note paging isn't enabled.


Thanx.

Posted: Fri Jun 01, 2007 5:44 pm
by pcmattman
First of all - get a debugger.

Second - GPFs in Virtual Mode occur on privileged instructions. Read the intel manuals on virtual mode and you can see what you need to emulate as a virtual mode monitor.

Edit: Downloaded your image, running it works alright, apart from the GPF. I have a few questions: is your task under the 1MB mark? Do you have a mode monitor that emulates privileged instructions (read the Intel manual, and search Google). You can't expect us to upload fixed code. You have to do this yourself.

It took me a month. It's worth doing it yourself.

As I type, this is what I notice in my Bochs log:

Code: Select all

call_protected: EIP not within CS limits
You cannot switch tasks via a long call in virtual mode (read the manuals). Why can't you use preemptive tasking, whereby a timer tick allows a reschedule to occur. What you're doing now looks to me like cooperative tasking.

Posted: Sat Jun 02, 2007 12:47 pm
by xyjamepa
Hi...
is your task under the 1MB mark
how can I make sure that my task is 1MB mark?
You can't expect us to upload fixed code.
I'm not, I just need your opinion and experience to explain to me why
my virtual task doesn't work.

Thanx.

Posted: Sat Jun 02, 2007 4:36 pm
by pcmattman
When I was testing virtual mode, this is what I did:

Code: Select all

char* data = (char*) 0x1000; // pointer to location < 1MB
*dat++ = 0xCD;
*dat++ = 0x03; // int 0x03
*dat++ = 0xEB;
*dat++ = 0xFE; // jmp $
/** create task, set base to 0x1000 **/
If you are using a C function, you just need to get the pointer to the function and copy enough of it's code to a location under 1 MB to be able to have it run... something like

Code: Select all

memcpy( (void*) 0x1000, &task1, 1024 ); // you could also run until you found 'ret' (is it C3, or C9? keep getting Z80 opcodes mixed up...)
Good luck!

Posted: Sat Jun 02, 2007 5:22 pm
by xyjamepa
Hi...
unfortunately it didn't work I got general protection fault again.
I'm starting to pull my hair up......I'm so confused,I don't know
what the wrong I'm doing?????? now I believe enabling virtual mode
harder than brain surgery. :( :( :(
So now I'm sure that my virtual task is marked 1MB,what else should
I take care of?
guys I really need your help.

Thanx.

Posted: Sat Jun 02, 2007 6:58 pm
by pcmattman
As I've said so many times, GPF comes from a privileged instruction!

Find out whether you're in virtual mode on a GPF, then read in the opcode from the CS:EIP that the fault occurred at. Handle the opcodes that Intel says are privileged. Return (after incrementing EIP).

In the least, make your GPF handler print out CPU state before the crash and the opcodes at the last executed location.

Posted: Sun Jun 03, 2007 4:37 am
by xyjamepa
Hi...
First of all @pcmattman thank you for your help.
Now my task doesn't have any instructions just an infinit loop.
but as soon as I make the call to the selector of the virtual task
I get general protection fault.
Also Intel manual says:
Task switch when the VM flag is set to 1 in the EFLAGS register image stored in the TSS
for the task. Here the task switch can be initiated in either of two ways:
— A CALL or JMP instruction.
— An IRET instruction, where the NT flag in the EFLAGS image is set to 1.
I'm using CALL instruction so this should be fine,my EFLAGS value is 0x23202L
so the VM bit is set,my task is 1MB marked,Also I'm sure about my multitasking.
what's wrong with my code....

Thanx.

Posted: Sun Jun 03, 2007 7:00 am
by frank
While debugging your code in bochs I have noticed that it throws the gpf right at the switch to the task, not after trying to execute any code. So the problem must be in the values that you are putting in the tss. Also, all code that is going to be run in virtual mode must be below the 1mb mark. Not at it not above it. Since your whole kernel is at the 1mb mark the function you are trying to call must be above the 1mb mark. Have you tried what pcmattman says about using memcpy to get the code below the 1mb mark?

Question for someone who knows, Aren't the values entered into the TSS for segment descriptors supposed to be real mode values and not segment descriptors?

Posted: Sun Jun 03, 2007 8:42 am
by xyjamepa
Hi...
I have noticed that it throws the gpf right at the switch to the task
This means it throws the gpf when I do the long call "lcall" to the
selector of my virtual task
So the problem must be in the values that you are putting in the tss.
here are my values:

Code: Select all

i=0;
for(i;i<max_tasks;i++)
  {
   tss[i].trace=0;
   tss[i].io_map_addr=sizeof(TSS);
   tss[i].ldtr=0;
   if (i) {
   tss[i].fs=tss[i].gs=0;
   tss[i].ds=tss[i].es=tss[i].ss=0x10;
   tss[i].cs=0x8;
   tss[i].eflags=0x23202L ;		//VM=1 ,IOPL=3, interrupts are enabled
   tss[i].esp=(dword)&task_stack[i];	// sp points to task stack top /
   tss[i].ss0=0x10;
   tss[i].esp0=(dword)&pl0_stack[i];	//stack for kernel
   }
  }
 tss[1].eip=(dword)&task;		//my virtual task

 memcpy( (void*) 0x1000, &task, 1024 ); 

 ltr(0x28);				//selector of the main()
Have you tried what pcmattman says about using memcpy to get the code below the 1mb mark?
Yes,I did.

Thanx.

Posted: Sun Jun 03, 2007 9:50 am
by jnc100
abuashraf wrote:

Code: Select all

tss[1].eip=(dword)&task;      //my virtual task

 memcpy( (void*) 0x1000, &task, 1024 );
frank wrote:Have you tried what pcmattman says about using memcpy to get the code below the 1mb mark?
Yes,I did.
I think he also meant: copy it there _and_ set the eip in the task structure to point to the new address of the task's code.

Code: Select all

tss[1].eip = 0x1000;
and link your 'task' program to run at 0x1000?

Regards,
John.

Posted: Sun Jun 03, 2007 10:38 am
by xyjamepa
Hi...

I tried tss[1].eip = 0x1000;
but this time I got Invalid opcode exception. :( :( :( :(
I'm so grateful for your help guys,
this my EIP=00100fc2 after the exception , using QEMU monitor.
here's an updated IMG file it might help,I don't know

:?: :?: :?: :?:

Thanx.

Posted: Sun Jun 03, 2007 11:16 am
by jnc100
Okay, so I just tested it.

Your code successfully jumps to 0x1000 with VM set.

Unfortunately, the contents at 0x1000 are a NOP followed by lots of zeros? Does your memcpy work? Is the location you're copying from correct?

Regards,
John.

Posted: Sun Jun 03, 2007 12:37 pm
by xyjamepa
Hi...
Does your memcpy work?
Here's my memcpy:

Code: Select all

unsigned char *memcpy(unsigned char *dest,unsigned char *src,int count)
{
 const char *s = (const char *)src;
 char *d = (char *)dest;
 for(; count!=0; count--) *d++ = *s++;
 return dest;
}
Is the location you're copying from correct?
Yes,I think so,the *src is &task "address of my virtual task"
Would you please take a look at init_task it may has some bugs

Code: Select all

void init_task()
{
 disable();
 unsigned int i=0;
 for(i;i<max_tasks;i++)
  {
   tss[i].trace=0;
   tss[i].io_map_addr=sizeof(TSS);
   tss[i].ldtr=0;
   if (i) {
   tss[i].fs=tss[i].gs=0;
   tss[i].ds=tss[i].es=tss[i].ss=0x10;
   tss[i].cs=0x8;
   tss[i].eflags=0x23202L ;		//VM=1,IOPL=3,interrupts are enabled
   tss[i].esp=(dword)&task_stack[i];	//points to task() stack top
   tss[i].ss0=0x10;
   tss[i].esp0=(dword)&pl0_stack[i];	//stack for kernel
   }
  }
 memcpy( (void*) 0x1000, &task, 1024 ); 
 tss[1].eip=0x1000;
 ltr(0x28);
 enable();
}
Thanx

Posted: Sun Jun 03, 2007 2:48 pm
by frank
You are supposed to use real mode values for the segment descriptors. Right now you are using 0x8 for cs. When you do real mode addressing the final address ends up being 0x1080 (0x8 * 16 + 0x1000). Try it with 0 as the value you enter for all of the segment registers cs, ds, es, fs, gs, and ss. That will fix the problem.

Posted: Sun Jun 03, 2007 3:53 pm
by xyjamepa
Hi...

Once again it didn't work Bochs gave me a panic message:
interrupt(): SS selector null
Also QEMU just halt, I couldn't dump any values ... :( :(
so here's another updated IMG ,guys we are so close
I'm really grateful for your help.


Thanx.