virtual mode...

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.
User avatar
xyjamepa
Member
Member
Posts: 397
Joined: Fri Sep 29, 2006 8:59 am

Post 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.
Attachments
knl.tar.gz
kernel
(15.03 KiB) Downloaded 71 times
a.tar.gz
IMG
(46.97 KiB) Downloaded 70 times
pcmattman
Member
Member
Posts: 2566
Joined: Sun Jan 14, 2007 9:15 pm
Libera.chat IRC: miselin
Location: Sydney, Australia (I come from a land down under!)
Contact:

Post 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.
User avatar
xyjamepa
Member
Member
Posts: 397
Joined: Fri Sep 29, 2006 8:59 am

Post 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.
pcmattman
Member
Member
Posts: 2566
Joined: Sun Jan 14, 2007 9:15 pm
Libera.chat IRC: miselin
Location: Sydney, Australia (I come from a land down under!)
Contact:

Post 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!
User avatar
xyjamepa
Member
Member
Posts: 397
Joined: Fri Sep 29, 2006 8:59 am

Post 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.
pcmattman
Member
Member
Posts: 2566
Joined: Sun Jan 14, 2007 9:15 pm
Libera.chat IRC: miselin
Location: Sydney, Australia (I come from a land down under!)
Contact:

Post 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.
User avatar
xyjamepa
Member
Member
Posts: 397
Joined: Fri Sep 29, 2006 8:59 am

Post 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.
frank
Member
Member
Posts: 729
Joined: Sat Dec 30, 2006 2:31 pm
Location: East Coast, USA

Post 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?
User avatar
xyjamepa
Member
Member
Posts: 397
Joined: Fri Sep 29, 2006 8:59 am

Post 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.
jnc100
Member
Member
Posts: 775
Joined: Mon Apr 09, 2007 12:10 pm
Location: London, UK
Contact:

Post 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.
User avatar
xyjamepa
Member
Member
Posts: 397
Joined: Fri Sep 29, 2006 8:59 am

Post 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.
Attachments
a.tar.gz
IMG
(47.49 KiB) Downloaded 126 times
jnc100
Member
Member
Posts: 775
Joined: Mon Apr 09, 2007 12:10 pm
Location: London, UK
Contact:

Post 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.
User avatar
xyjamepa
Member
Member
Posts: 397
Joined: Fri Sep 29, 2006 8:59 am

Post 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
frank
Member
Member
Posts: 729
Joined: Sat Dec 30, 2006 2:31 pm
Location: East Coast, USA

Post 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.
User avatar
xyjamepa
Member
Member
Posts: 397
Joined: Fri Sep 29, 2006 8:59 am

Post 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.
Attachments
a.tar.gz
IMG
(47.48 KiB) Downloaded 95 times
Post Reply