On 03/26/2011 12:12 AM, Wei Xu wrote:
Jiri& Avi:
I attached the patched I did for movq and movdqa emulation. Please note:
(1) I only implemented those two. Other instructions like addq may be
following same way.
(2) I use same guest_fx_image to hold value and fxsave/fxrstor to copy
to/from registers. This is not very efficient I admit.
Any suggestions let me know.
Patch is severely whitespace damaged. Please observe the kernel
whitespace style.
I just remembered that I implemented this once - see the (very old)
branch sse-mmio in kvm.git.
Index: linux/contents/arch/x86/include/asm/kvm_emulate.h
===================================================================
--- linux.orig/contents/arch/x86/include/asm/kvm_emulate.h 2010-07-19
06:42:26.000000000 -0700
+++ linux/contents/arch/x86/include/asm/kvm_emulate.h 2011-03-21
09:16:39.000000000 -0700
@@ -116,6 +116,7 @@
enum { OP_REG, OP_MEM, OP_IMM, OP_NONE } type;
unsigned int bytes;
unsigned long val, orig_val, *ptr;
+ unsigned long val_simd[2];
};
Breaks on i386 (ulong is 32-bit).
if (c->src.type == OP_MEM) {
+ void *val;
c->src.ptr = (unsigned long *)memop;
c->src.val = 0;
+ if (c->src.bytes> 8) { /* movdq case */
+ c->src.val_simd[0] = c->src.val_simd[1] = 0;
+ val = c->src.val_simd;
+ } else {
+ val =&c->src.val;
+ }
We have a union there for that purpose.
@@ -2506,6 +2529,55 @@
if (!test_cc(c->b, ctxt->eflags))
c->dst.type = OP_NONE; /* no writeback */
break;
+ case 0x6f: /* movq from mm/m64 to mm; movdqa from xmm/m128 to xmm */
+ if (c->op_bytes == 8){
+ ctxt->vcpu->arch.guest_fx_image.st_space[c->modrm_reg<<2] =
+ (c->src.val& 0x0ffffffff);
+ ctxt->vcpu->arch.guest_fx_image.st_space[(c->modrm_reg<<2)+1] =
+ (c->src.val>> 32);
+ kvm_fx_restore(&ctxt->vcpu->arch.guest_fx_image);
+ c->dst.type = OP_NONE; /* Disable writeback. */
+ break;
+ } else { /* movdqa */
+ ctxt->vcpu->arch.guest_fx_image.xmm_space[c->modrm_reg<<2] =
+ (c->src.val_simd[0]& 0x0ffffffff);
+ ctxt->vcpu->arch.guest_fx_image.xmm_space[(c->modrm_reg<<2)+1] =
+ (c->src.val_simd[0]>> 32);
+ ctxt->vcpu->arch.guest_fx_image.xmm_space[(c->modrm_reg<<2)+2] =
+ (c->src.val_simd[1]& 0x0ffffffff);
+ ctxt->vcpu->arch.guest_fx_image.xmm_space[(c->modrm_reg<<2)+3] =
+ (c->src.val_simd[1]>> 32);
+ kvm_fx_restore(&ctxt->vcpu->arch.guest_fx_image);
+ c->dst.type = OP_NONE; /* Disable writeback. */
+ break;
+ }
+ case 0x7f: /* movq from mm to mm/m64; movdqa from xmm to xmm/m128 */
+ if (c->op_bytes == 8) { /* movq */
+ kvm_fx_save(&ctxt->vcpu->arch.guest_fx_image);
+ if (c->dst.type == OP_MEM) {
+ unsigned long lval,uval;
+ lval =
ctxt->vcpu->arch.guest_fx_image.st_space[c->modrm_reg<<2];
+ uval =
ctxt->vcpu->arch.guest_fx_image.st_space[(c->modrm_reg<<2)+1];
+ c->dst.val = (uval<<32) + lval;
+ } else {
+ c->dst.type = OP_NONE; /* Disable writeback. */
+ }
+ break;
+ } else { /* movdqa */
+ kvm_fx_save(&ctxt->vcpu->arch.guest_fx_image);
+ if (c->dst.type == OP_MEM) {
+ unsigned long lval,uval;
+ lval =
ctxt->vcpu->arch.guest_fx_image.xmm_space[c->modrm_reg<<2];
+ uval =
ctxt->vcpu->arch.guest_fx_image.xmm_space[(c->modrm_reg<<2)+1];
+ c->dst.val_simd[0] = (uval<<32) + lval;
+ lval =
ctxt->vcpu->arch.guest_fx_image.xmm_space[(c->modrm_reg<<2)+2];
+ uval =
ctxt->vcpu->arch.guest_fx_image.xmm_space[(c->modrm_reg<<2)+3];
+ c->dst.val_simd[1] = (uval<<32) + lval;
+ } else {
+ c->dst.type = OP_NONE; /* Disable writeback. */
+ }
+ break;
+ }
In my implementation, I just forced the guest mmu to be active, and used
the sse instructions directly.
Index: linux/contents/include/linux/kvm.h
===================================================================
--- linux.orig/contents/include/linux/kvm.h 2010-07-19 06:42:23.000000000
-0700
+++ linux/contents/include/linux/kvm.h 2011-03-21 09:16:39.000000000 -0700
@@ -152,7 +152,7 @@
/* KVM_EXIT_MMIO */
struct {
__u64 phys_addr;
- __u8 data[8];
+ __u8 data[16];
__u32 len;
__u8 is_write;
} mmio;
This breaks the userspace interface. My implementation split the I/O
into two separate 64-bit writes.
I guess I'll have to rebase it.
--
error compiling committee.c: too many arguments to function
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html