>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;
+}