>I've applied the patch, but those instructions appear to be broken:
>you have to increment or decrement %edi / %esi after performing the
>instruction.  Furthermore, you should really check the address size
>whether to use the word or dword index registers (e.g. %edi vs. %di).
>This has to be checked by the kernel part.
Oops, I forgot this, sorry. Following patch(es) corrects this - I hope.
Our local net is down, I couldn't test it. But looks ok and compiles...

jens

--- freemware/user/user.c       Tue Jan 18 12:01:43 2000
+++ freemware-jens/user/user.c  Wed Jan 19 12:12:18 2000
@@ -728,6 +728,79 @@
                plugin_emulate (EVT_OUTPORT, arg, 4, 1, &value);
                break;
 
+           case EMU_INSTR_INS_8:
+             plugin_emulate(EVT_INPORT,context.edx & 0xffff,1,1,&value);
+             /* FIXME: works only with flat memory models without paging and ES == DS 
+*/
+             if(((context.event_info >> 16) & 0xff) == 32)
+               *(u8 *)(ptr+context.edi)=(u8)value;
+             else
+               *(u8 *)(ptr+(context.edi & 0xffff))=(u8)value;          
+             if(context.eflags & 0x400) context.edi+=1;
+             else context.edi-=1;
+             break;
+
+           case EMU_INSTR_INS_16:
+             plugin_emulate(EVT_INPORT,context.edx & 0xffff,2,1,&value);
+             /* FIXME: works only with flat memory models without paging and ES == DS 
+*/
+             if(((context.event_info >> 16) & 0xff) == 32)
+               *(u16 *)(ptr+context.edi)=(u16)value;
+             else
+               *(u16 *)(ptr+(context.edi & 0xffff))=(u16)value;
+             if(context.eflags & 0x400) context.edi+=2;
+             else context.edi-=2;
+             break;
+
+           case EMU_INSTR_INS_32:
+             plugin_emulate(EVT_INPORT,context.edx & 0xffff,4,1,&value);
+             /* FIXME: works only with flat memory models without paging and ES == DS 
+*/
+             if(((context.event_info >> 16) & 0xff) == 32)
+               *(u32 *)(ptr+context.edi)=value;
+             else
+               *(u32 *)(ptr+(context.edi & 0xffff))=value;
+             if(context.eflags & 0x400) context.edi+=4;
+             else context.edi-=4;
+             break;
+
+           case EMU_INSTR_OUTS_8:
+             /* FIXME: works only with flat memory models without paging and ES == DS 
+*/
+             if(((context.event_info >> 16) & 0xff) == 32)
+               value=*(u8 *)(ptr+context.edi);
+             else
+               value=*(u8 *)(ptr+(context.edi & 0xffff));
+             plugin_emulate(EVT_OUTPORT,context.edx & 0xffff,1,1,&value);
+             if(context.eflags & 0x400) context.edi+=1;
+             else context.edi-=1;
+             break;
+
+           case EMU_INSTR_OUTS_16:
+             /* FIXME: works only with flat memory models without paging and ES == DS 
+*/
+             if(((context.event_info >> 16) & 0xff) == 32)
+               value=*(u16 *)(ptr+context.edi);
+             else
+               value=*(u16 *)(ptr+(context.edi & 0xffff));
+             plugin_emulate(EVT_OUTPORT,context.edx & 0xffff,2,1,&value);
+             if(context.eflags & 0x400) context.edi+=2;
+             else context.edi-=2;
+             break;
+
+           case EMU_INSTR_OUTS_32:
+             /* FIXME: works only with flat memory models without paging and ES == DS 
+*/
+             if(((context.event_info >> 16) & 0xff) == 32)
+               value=*(u32 *)(ptr+context.edi);
+             else
+               value=*(u32 *)(ptr+(context.edi & 0xffff));
+             plugin_emulate(EVT_OUTPORT,context.edx & 0xffff,4,1,&value);
+             if(context.eflags & 0x400) context.edi+=4;
+             else context.edi-=4;
+             break;
+
+           case EMU_INSTR_HLT:
+             fprintf(stderr,"HLT -- shutting down virtual machine\n");
+             abort_vm=1;
+             break;
+
+           case EMU_INSTR_CLI:
+           case EMU_INSTR_STI:
            default:
                fprintf (stderr, "Emulation of instruction 0x%x (0x%04x) not yet 
implemented\n",
                                 instr, arg);


--- freemware/kernel/emulation.c        Mon Jan 17 14:41:37 2000
+++ freemware-jens/kernel/emulation.c   Wed Jan 19 12:43:17 2000
@@ -26,11 +26,11 @@
 /*
  * Prototypes for instructions faulting in ring 3
  */
-int emulate_hlt(void);
-int emulate_cli(void);
-int emulate_sti(void);
-int emulate_ins(void);
-int emulate_outs(void);
+int emulate_hlt(guest_context_t *context);
+int emulate_cli(guest_context_t *context);
+int emulate_sti(guest_context_t *context);
+int emulate_ins(guest_context_t *context, int op_size, int address_size);
+int emulate_outs(guest_context_t *context, int op_size, int address_size);
 int emulate_clts(void);
 int emulate_rdmsr(void);
 int emulate_wrmsr(void);
@@ -452,6 +452,22 @@
         action = emulate_load_ds(context, val);
         break;
 
+    case 0x6c: /* insb == ins dx, m8 */
+      action = emulate_ins(context,8,address_size);
+      break;
+
+    case 0x6d: /* insw || insd */
+      action = emulate_ins(context, operand_size,address_size);
+      break;
+
+    case 0x6e: /* outsb == outs dx, m8 */
+      action = emulate_outs(context,8,address_size);
+      break;
+
+    case 0x6f: /* outsw || outsd */
+      action = emulate_outs(context, operand_size,address_size);
+      break;
+
     case 0x8e: /* mov Sw, Ew */
         c = read_guest_byte(&eip);  /* RegModRM */
         val = decode_rm_operand(context, 16, address_size, c, &eip);
@@ -511,12 +527,17 @@
         action = emulate_out(context, operand_size, context->edx & 0xffff);
         break;
 
+    case 0xf4: /* hlt */
+        action = emulate_hlt(context);
+       context->eip=eip;
+        break;
+
     case 0xfa: /* cli */
-        action = emulate_cli();
+        action = emulate_cli(context);
         break;
 
     case 0xfb: /* sti */
-        action = emulate_sti();
+        action = emulate_sti(context);
         break;
 
     case 0x0f:
@@ -562,6 +583,16 @@
             action = emulate_clts();
             break;
 
+       case 0x08: /* invd */
+         action = emulate_invd();
+         context->eip=eip;
+         break;
+           
+       case 0x09: /* wbinvd */
+         action = emulate_wbinvd();
+         context->eip=eip;
+         break;
+
         case 0xa1: /* pop FS */
             val = guest_stack_pop(&esp, operand_size);
             action = emulate_load_fs(context, val);
@@ -594,7 +625,6 @@
         context->eip = eip;
         context->esp = esp;
         return 2;
-
     case 4:   /* Try to emulate in user space */
         context->eip = eip;
         context->esp = esp;
@@ -604,25 +634,23 @@
 
 
 int
-emulate_cli(void)
+emulate_cli(guest_context_t *context)
      /*
       * Emulate cli instruction
       */
 {
-    /* here may reside some checks or so and emulation code */
-    vm_nexus()->debug_msg.msg_code = EMU_CLI_MSG;
-    return 0;
+  context->event_info=EMU_INSTR_CLI | (RET_BECAUSE_USEREMU << 8);
+  return 4;
 }
 
 int
-emulate_sti(void) 
+emulate_sti(guest_context_t *context) 
      /* 
       * Emulate sti instruction
       */
 {
-    /* here may reside some checks or so and emulation code */
-    vm_nexus()->debug_msg.msg_code = EMU_STI_MSG;
-    return 0;
+  context->event_info=EMU_INSTR_STI | (RET_BECAUSE_USEREMU << 8);
+  return 4;
 }
 
 int
@@ -1028,3 +1056,56 @@
     return 4;
 }
 
+int
+emulate_outs(guest_context_t *context, int operand_size, int address_size)
+     /*
+      * Emulate outs instruction
+      */
+{
+  switch(operand_size)
+    {
+    case 8: context->event_info=EMU_INSTR_OUTS_8;break;
+    case 16: context->event_info=EMU_INSTR_OUTS_16;break;
+    case 32: context->event_info=EMU_INSTR_OUTS_32;break;
+    }
+  context->event_info |= (RET_BECAUSE_USEREMU << 8) | (address_size << 16);
+  return 4;
+}
+
+
+int
+emulate_ins(guest_context_t *context, int operand_size, int address_size)
+     /*
+      * Emulate ins instruction
+      */
+{
+  switch(operand_size)
+    {
+    case 8: context->event_info=EMU_INSTR_INS_8;break;
+    case 16: context->event_info=EMU_INSTR_INS_16;break;
+    case 32: context->event_info=EMU_INSTR_INS_32;break;
+    }
+  context->event_info |= (RET_BECAUSE_USEREMU << 8) | (address_size << 16);
+  return 4;
+}
+
+int
+emulate_invd() {
+
+  /* nothing to do ;) */
+  return 1;
+}
+
+int
+emulate_wbinvd() {
+
+  /* nothing to do ;) */
+  return 1;
+}
+
+int
+emulate_hlt(guest_context_t *context) {
+
+  context->event_info=EMU_INSTR_HLT | (RET_BECAUSE_USEREMU << 8);
+  return 4;
+}

Reply via email to