Re: "KVM internal error. Suberror: 1" with ancient 2.4 kernel as guest

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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 majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux