OSDev.org

The Place to Start for Operating System Developers
It is currently Mon Apr 12, 2021 10:37 am

All times are UTC - 6 hours




Post new topic Reply to topic  [ 67 posts ]  Go to page Previous  1, 2, 3, 4, 5  Next
Author Message
 Post subject:
PostPosted: Tue Jun 05, 2007 2:04 pm 
Offline
Member
Member
User avatar

Joined: Fri Sep 29, 2006 8:59 am
Posts: 397
Hi...
I'm so sorry because I didn't get you right from the first time.
so here's my registers values:

Code:
eax:0x00100f88, ebx:0x00000000, ecx:0x00000000, edx:0x00100f87
ebp:0x001078e8, esp:0x001078e0, esi:0x0000000a, edi:0x00000000
eip:0x00100fc2, eflags:0x00003002, inhibit_mask:0
cs:s=0x0008, dl=0x0000ffff, dh=0x00c09a00, valid=1
ss:s=0x0010, dl=0x0000ffff, dh=0x00c09300, valid=7
ds:s=0x0010, dl=0x0000ffff, dh=0x00c09300, valid=7
es:s=0x0010, dl=0x0000ffff, dh=0x00c09300, valid=1
fs:s=0x0010, dl=0x0000ffff, dh=0x00c09300, valid=1
gs:s=0x0010, dl=0x0000ffff, dh=0x00c09300, valid=1
ldtr:s=0x0000, dl=0x00000000, dh=0x00000000, valid=0
tr:s=0x0030, dl=0x68e80068, dh=0x00808910, valid=1
gdtr:base=0x00106820, limit=0x37
idtr:base=0x00106020, limit=0x7ff
dr0:0x00000000, dr1:0x00000000, dr2:0x00000000
dr3:0x00000000, dr6:0xffff0ff0, dr7:0x00000400
cr0:0x00000019, cr1:0x00000000, cr2:0x00000000
cr3:0x00000000, cr4:0x00000000


All this values after the exception.
Also here's an IMG file it might help if you want more information.
I'm grateful for your help guys.

Thanx.


Attachments:
File comment: IMg
a.tar.gz [47.52 KiB]
Downloaded 30 times
Top
 Profile  
 
 Post subject:
PostPosted: Tue Jun 05, 2007 2:54 pm 
Offline
Member
Member
User avatar

Joined: Wed Oct 18, 2006 3:45 am
Posts: 9289
Location: On the balcony, where I can actually keep 1½m distance
The switch to v8086 mode seems to work ok.

However, there is nothing meaningful at 0000:1000 - only garbage is being executed which will at some point cause an random exception.

_________________
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jun 05, 2007 3:05 pm 
Offline
Member
Member

Joined: Sun Jan 14, 2007 9:15 pm
Posts: 2566
Location: Sydney, Australia (I come from a land down under!)
@abuashraf: try it without using a C function for the task. Do this, for instance:

Code:
char* dat = (char*) 0x1000;
/* comment out until you need to test your virtual mode monitor
*dat++ = 0xCD;
*dat++ = 0x03;
*/
*dat++ = 0xEB;
*dat++ = 0xFE;


If that doesn't work, I don't know what will!

_________________
Pedigree | GitHub | Twitter | LinkedIn


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jun 06, 2007 2:30 am 
Offline
Member
Member
User avatar

Joined: Fri Sep 29, 2006 8:59 am
Posts: 397
Hi...

I tried this:
Code:
char* dat = (char*) 0x1000;
/* comment out until you need to test your virtual mode monitor
*dat++ = 0xCD;
*dat++ = 0x03;
*/
*dat++ = 0xEB;
*dat++ = 0xFE;


Now bochs didn't gave me any exception :) :) :) :) ,If we wrote our virtual task usign assembly will this work fine?
If yes would you give me very very simple function written in assembly
and pointed to 0x1000,I'm soooo bad in assembly stuff.

Thanx.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jun 06, 2007 2:34 am 
Offline
Member
Member

Joined: Sun Jan 14, 2007 9:15 pm
Posts: 2566
Location: Sydney, Australia (I come from a land down under!)
No, not yet.

First, uncomment my comments, and write a virtual mode monitor. If you need help, post here.

_________________
Pedigree | GitHub | Twitter | LinkedIn


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jun 06, 2007 5:48 am 
Offline
Member
Member
User avatar

Joined: Fri Sep 29, 2006 8:59 am
Posts: 397
Hi...

:oops:

Okay I uncommented your comments but I got general protection faults.
So to be clear my registers values are:
Code:
void init_task()
{
disable();
for(i=0;i<max_tasks;i++)
  {

   tss[i].trace=0;
   tss[i].io_map_addr=sizeof(TSS);
   tss[i].ldtr=0;

   tss[i].fs=tss[i].gs=0;
   tss[i].ds=tss[i].es=tss[i].ss=0x0;
   tss[i].cs=0x0;
   tss[i].eflags=0x23202L;      //0x23202L VM=1 ,IOPL=3
   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

  }

char* dat = (char*)0x1000;
*dat++ = 0xCD;
*dat++ = 0x03;
*dat++ = 0xEB;
*dat++ = 0xFE;

tss[1].eip=(dword *)0x1000;

ltr(0x28);   //selector of main()

enable();
}


So now my virtual task became what you wrote,I commented
the old task(),do you see any wrong with reg values? eip,ss,ss0,esp...?

Also I found pcmattman values 0xfeeb03cd at 0x1000
and Combuster already said switching to virtual mode seems to work ok.
so now I think the problem with wrong reg values,to be more specific
the regs are esp,eip,sep0,ss0 but not quite sure.

Thanx


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jun 06, 2007 9:42 am 
Offline
Member
Member
User avatar

Joined: Wed Oct 18, 2006 3:45 am
Posts: 9289
Location: On the balcony, where I can actually keep 1½m distance
abuashraf wrote:
Okay I uncommented your comments but I got general protection faults.

Security test passed :D - the code tries to call an interrupt handler that it isnt supposed to call.

_________________
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jun 06, 2007 11:01 am 
Offline
Member
Member
User avatar

Joined: Fri Sep 29, 2006 8:59 am
Posts: 397
Hi...

It's been a week and we still tring to enable virtual mode.
Could someone guide me please I'm kind of lost here.
*switching to virtual mode is working.
*values that pcmattman wrote saved at 0x1000 successfuly,but
what should I do with this values.
*I pointed eip of the virtual task to 0x1000
like this tss[1].eip=(dword *)0x1000
Even with all this stuff I'm still getting gpf. :(
I'm afraid that some of my regs loaded with wrong values.
would you please take a look at the code above and see
if there is any thing wrong,and what else should I do?
I'm grateful for your help.


Thanx.


Last edited by abuashraf on Wed Jun 06, 2007 11:03 am, edited 1 time in total.

Top
 Profile  
 
 Post subject:
PostPosted: Wed Jun 06, 2007 11:03 am 
Offline
Member
Member
User avatar

Joined: Wed Oct 18, 2006 3:45 am
Posts: 9289
Location: On the balcony, where I can actually keep 1½m distance
Everything is working as it should.

The only thing you need to is to write the vmm. In the meantime anything interesting the v8086 task tries to do will result in a gpf or the like.

_________________
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jun 06, 2007 1:08 pm 
Offline
Member
Member
User avatar

Joined: Fri Sep 29, 2006 8:59 am
Posts: 397
Hi...

Quote:
Everything is working as it should.


This means I can't even print a message without implementing virtual mode
monitor,am I right?
I'm confused little bit now,my EFLAGS after the exception equal to 0x00003002
would someone please explain to me what does this mean?
If I want to enable virtual mode and not to do any thing,let's
say I don't want to print any message,but also I don't want to get a gpf,
are this the right steps:
*Enabling VM bit in EFLAGS.
*virtual task should be 1MB mark.
*pointing the eip field of the virtual task tss to virtual task address.
like this tss[1].eip=(dword *)0x1000.
*virtual task is emptylike this:
void task()
{
//no thing
}

*Is there any thing else?

One last thing and I already said that,my virtual task works in PL0,
what about the vmm,what kind of PL does it work in?PL0 or PL3?

Thanx.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jun 06, 2007 2:19 pm 
Offline
Member
Member
User avatar

Joined: Wed Oct 18, 2006 3:45 am
Posts: 9289
Location: On the balcony, where I can actually keep 1½m distance
abuashraf wrote:
Quote:
Everything is working as it should.

This means I can't even print a message without implementing virtual mode monitor,am I right?

Its possible to keep away from vmm-calling operations, but its not easy and you'll need the vmm later on anyway.

Quote:
I'm confused little bit now,my EFLAGS after the exception equal to 0x00003002
Nothing strange about it. That's just IOPL and the reserved one bit. When you entered the v8086 task all flags were clear, and they still are since there is no code changing that, and after the exception vm is cleared (for the change to protected mode), and your interrupt handler clears IF.

Quote:
If I want to enable virtual mode and not to do any thing,let's
say I don't want to print any message,but also I don't want to get a gpf,
are this the right steps:
*Enabling VM bit in EFLAGS.
*virtual task should be 1MB mark.
*pointing the eip field of the virtual task tss to virtual task address.
like this tss[1].eip=(dword *)0x1000.
*virtual task is emptylike this:
void task()
{
//no thing
}

* You can not put code for a v8086 task above the 1MB mark. That's the limit for real mode, and it still is for virtual tasks.
* You should point CS:(e)IP at the location where you put your v8086 task's code.
* You can not normally use GCC to generate code for virtual 8086 tasks. This is because GCC generates 32-bit code while in virtual mode code is executed as 16 bits. The easiest way is to write 16-bit assembly with nasm/yasm and use that.

Quote:
One last thing and I already said that,my virtual task works in PL0,
what about the vmm,what kind of PL does it work in?PL0 or PL3?

Like said many times before, a virtual8086 task ALWAYS runs in PL3. The vmm is normally executed in ring 0, though you can always route exceptions back to ring 3 if you so desire.

_________________
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jun 06, 2007 4:02 pm 
Offline
Member
Member

Joined: Sun Jan 14, 2007 9:15 pm
Posts: 2566
Location: Sydney, Australia (I come from a land down under!)
Christmas comes early for you:

This is the Mattise virtual mode monitor. 'r' is a pointer of type 'struct regs', it just points to the ESP at the time of calling with all sorts of data on the stack.
Code:
   // check if it's a GPF and we're in V8086 mode
   if( r->eflags & 0x20000 && r->int_no == 13 )
   {      
      // the IVT
      uint16_t* ivt = (uint16_t*) 0;
      
      // the stack, in 16-bit and 32-bit
      uint16_t* stack = (uint16_t*) FP_TO_LINEAR( 0x20, r->useresp );
      uint32_t* stack32 = (uint32_t*) stack;
      
      // instruction pointer
      uint8_t* ip = (uint8_t*) FP_TO_LINEAR( r->cs, r->eip );
      
      // index of execution
      uint32_t exc = 0;
      
      // operand and address sizes
      bool Op32 = false, Addr32 = false;
      
      // safe op?
      bool SafeOp = true;
      
      // knock out any extra stuff at the front
      while( SafeOp )
      {
         switch( ip[0] )
         {
            // 32-bit operand
            case 0x66:
            
               // we are using 32-bit operands
               Op32 = true;
               
               // increment the IP
               ip++;
               
               // set the new EIP in the stack
               r->eip++;
               
               break;
            
            // 32-bit address
            case 0x67:
            
               // 32-bit addresses
               Addr32 = true;
               
               // increment the IP
               ip++;
               
               // set the new EIP in the stack
               r->eip++;
               
               break;

            // PUSHF
            case 0x9C:
            
               // check for 32-bit
               if( Op32 )
               {
                  // decrement the stack by 4 bytes
                  r->useresp = ( ( r->useresp & 0xFFFF ) - 4 ) & 0xFFFF;
                  
                  // decrement the stack
                  stack32--;
                  
                  // put the flags on the stack
                  stack32[0] = r->eflags & 0xDFF;
                  
                  // see if we have interrupts enabled
                  if( r->eflags & 0x200 )
                     stack32[0] |= 0x200; // enable in flags
                  else
                     stack32[0] ^= 0x200; // disable
               }
               else
               {
                  // decrement the stack by 2 bytes
                  r->useresp = ( ( r->useresp & 0xFFFF ) - 2 ) & 0xFFFF;
                  
                  // decrement the stack
                  stack--;
                  
                  // put the flags on the stack
                  stack[0] = r->eflags;
                  
                  // see if we have interrupts enabled
                  if( r->eflags & 0x200 )
                     stack[0] |= 0x200; // enable in flags
                  else
                     stack[0] ^= 0x200; // disable
               }
                  
               // increment eip
               r->eip++;
               
               // go back to task
               return;
            
            // POPF
            case 0x9D:
            
               // check for 32-bit
               if( Op32 )
               {
                  // set the EFLAGS
                  r->eflags = 0x20200 | ( stack32[0] & 0xDDF );
                  
                  // set the new stack pointer
                  r->useresp = ( ( r->useresp & 0xFFFF ) + 4 ) & 0xFFFF;
               }
               else
               {
                  // set the EFLAGS
                  r->eflags = 0x20200 | stack[0];
                  
                  // set the new stack pointer
                  r->useresp = ( ( r->useresp & 0xFFFF ) + 2 ) & 0xFFFF;
               }
               
               // increment eip
               r->eip++;
               
               // return to the task
               return;
            
            // CLI
            case 0xFA:
            
               // take out the interrupt flag
               if( r->eflags & 0x200 )
                  r->eflags ^= 0x200;
               
               // increment eip
               r->eip++;
               
               // return to the task
               return;
            
            // STI
            case 0xFB:
            
               // put in the interrupt flag
               if( ( r->eflags & 0x200 ) == 0 )
                  r->eflags &= 0x200;
               
               // increment eip
               r->eip++;
               
               // return to the task
               return;
               
            // 0xCD: INT n
            case 0xCD:
            
               // int80 = kill current task
               if( ip[1] == 0x80 )
               {                  
                  // set the current task's registers
                  SetRegs( currpid(), r );
                  
                  // kill it
                  kill( currpid() );
                  
                  // reschedule
                  resched();
                  
                  // set the new esp
                  r->esp = current_task[0].esp;
                  
                  // increment the eip too
                  r->eip += 2;
                  
                  // return to the new task
                  return;
               }
               
               // decrement the stack 3 times
               stack -= 3;
               
               // put the data on the stack
               stack[0] = (uint16_t) ( r->eip + exc + 2 );
               stack[1] = r->cs;
               stack[2] = (uint16_t) r->eflags;
               
               // set the new stack pointer
               r->useresp = ( ( r->useresp & 0xFFFF ) - 6 ) & 0xFFFF;
               
               // set eflags
               if( r->eflags & 0x200 )
                  r->eflags ^= 0x200;
               
               // jump to the necessary location
               r->cs = ivt[ ip[exc+1] * 2 + 1 ];
               r->eip = ivt[ ip[exc+1] * 2 ];
               
               // return, this will take us to the interrupt handler
               return;
            
            // IRET
            case 0xCF:
            
               // set EFLAGS, CS and EIP, then refresh Ring3ESP
               r->eip = stack[0];
               r->cs = stack[1];
               r->eflags = stack[2] | 0x20200;
               
               // new stack pointer
               r->useresp = ( ( r->useresp & 0xFFFF ) + 6 ) & 0xFFFF;
               
               // return to the new place
               return;

            default:
            
               // oops!
               kprintf( "Unknown opcode: 0x%x!\n", ip[0] );
               
               // break free from the loop
               SafeOp = false;
         }
      }
      
      // loop forever - dud op
      while( true );
   }


Good luck.

By the way:
Quote:
You can not normally use GCC to generate code for virtual 8086 tasks. This is because GCC generates 32-bit code while in virtual mode code is executed as 16 bits. The easiest way is to write 16-bit assembly with nasm/yasm and use that.


That's true. I used NASM to write 16-bit code for my VBE switcher, that I put onto a hard drive and used
Code:
fread( (void*) 0x1000, /** offset **/ 0, /** count **/ fp.size, fp );

(i have an unusual fread)

The reason you use NASM is that 16- and 32-bit opcodes are different.

_________________
Pedigree | GitHub | Twitter | LinkedIn


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jun 07, 2007 7:12 am 
Offline
Member
Member
User avatar

Joined: Fri Sep 29, 2006 8:59 am
Posts: 397
Hi...

Quote:
GCC generates 32-bit code while in virtual mode code is executed as 16 bits. The easiest way is to write 16-bit assembly with nasm/yasm and use that.

You mean when I want to use BIOS INTs I have to write the code and compile it with nasm,am I right?
One last thing:

Quote:
* You can not put code for a v8086 task above the 1MB mark. That's the limit for real mode, and it still is for virtual tasks.


I "as you adviced me" did this:

memcpy((void *)0x1000,&task,1000);
ts[1].eip=(dword *)0x1000;

so my virtual task now 1MB mark and eip field of its tss point to it,
am I right?
if yes after the exception my eip value was 0x00100FC2 and never changed,why do you think?


@pcmattman thank you for your code.

Thanx.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jun 07, 2007 7:19 am 
Offline
Member
Member
User avatar

Joined: Sun Oct 22, 2006 7:01 am
Posts: 2637
Location: Devon, UK
Hi,

abuashraf wrote:
You mean when I want to use BIOS INTs I have to write the code and compile it with nasm,am I right?


Yes - you have to have your real mode IVT in place (in other words, don't mess about with the memory region 0-0x500 physical), be running in v86 mode, and have used 16 bit code (the [USE 32] or [BITS 32] directive, depending on what assembler you are using).

abuashraf wrote:
if yes after the exception my eip value was 0x00100FC2 and never changed,why do you think?


Have you actually organised your code with an entry point of 0x1000 [ORG 0x1000]? If you are using C, you will need to link to entry point 0x1000.

If not, I strongly suspect there is a JMP or CALL 0x00100FC2 somewhere in your code.

Cheers,
Adam


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jun 07, 2007 7:21 am 
Offline
Member
Member
User avatar

Joined: Wed Oct 18, 2006 3:45 am
Posts: 9289
Location: On the balcony, where I can actually keep 1½m distance
abuashraf wrote:
Hi...

Quote:
GCC generates 32-bit code while in virtual mode code is executed as 16 bits. The easiest way is to write 16-bit assembly with nasm/yasm and use that.

You mean when I want to use BIOS INTs I have to write the code and compile it with nasm,am I right?

Nasm is an assembler, not a compiler.

Quote:
One last thing:

Quote:
* You can not put code for a v8086 task above the 1MB mark. That's the limit for real mode, and it still is for virtual tasks.


I "as you adviced me" did this:

memcpy((void *)0x1000,&task,1000);
ts[1].eip=(dword *)0x1000;

so my virtual task now 1MB mark and eip field of its tss point to it,
am I right?

The virtual mode task is *NOT* at the 1MB mark, its at 4K, exactly where you copied it to.

Quote:
if yes after the exception my eip value was 0x00100FC2 and never changed,why do you think?
After an exception control is transferred to the kernel which DOES live above the 1MB mark. You are looking at the EIP of a JMP $ instruction inside the kernel. :shock:

_________________
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 67 posts ]  Go to page Previous  1, 2, 3, 4, 5  Next

All times are UTC - 6 hours


Who is online

Users browsing this forum: Ethin, Google [Bot], tyler569 and 15 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group