kernel kqemu vs vmmouse/vmware svga in qemu (workaround)

Juergen Lock nox at jelal.kn-bremen.de
Thu Feb 19 14:16:31 PST 2009


Hi!

 The fix of the recent -vga vmware breakage in qemu svn...
	http://lists.gnu.org/archive/html/qemu-devel/2009-02/msg01065.html
...inspired me to take a longer look at the userspace pio problem that
renders vmmouse and -vga vmware unworkable with -kernel-kqemu, and now I
found out that apparently in this case iopl changes made in the guest dont
get propagated back to userland properly.  The workaround below gets vmmouse
and -vga vmware going again at least for my usual sidux live iso guest and
also shows that iopl ends up still being 0 when it should be higher.

 I'll leave it to people knowing the kqemu code better than me to find
the root cause of this bug...

 Thanx,
	Juergen

Index: qemu/target-i386/op_helper.c
@@ -517,6 +517,11 @@
 #endif
 }
 
+#if 1
+#define VMPORT 0x5658
+int vmware_svga_io_base;
+#endif
+
 /* check if Port I/O is allowed in TSS */
 static inline void check_io(int addr, int size)
 {
@@ -527,6 +532,27 @@
         ((env->tr.flags >> DESC_TYPE_SHIFT) & 0xf) != 9 ||
         env->tr.limit < 103)
         goto fail;
+#if 1
+    if (addr == VMPORT) {
+        static int last_vmport_iopl = -1;
+        int iopl = (env->eflags >> IOPL_SHIFT) & 3;
+        if (iopl != last_vmport_iopl) {
+            printf("check_io vmport workaround: iopl = %d\n", iopl);
+            last_vmport_iopl = iopl;
+        }
+        return;
+    }
+    if (vmware_svga_io_base &&
+        addr >= vmware_svga_io_base && addr < vmware_svga_io_base + 3) {
+        static int last_svga_iopl = -1;
+        int iopl = (env->eflags >> IOPL_SHIFT) & 3;
+        if (iopl != last_svga_iopl) {
+            printf("check_io vmware svga workaround: iopl = %d\n", iopl);
+            last_svga_iopl = iopl;
+        }
+        return;
+    }
+#endif
     io_offset = lduw_kernel(env->tr.base + 0x66);
     io_offset += (addr >> 3);
     /* Note: the check needs two bytes */
Index: qemu/hw/vmware_vga.c
@@ -1175,12 +1175,19 @@
     return 0;
 }
 
+#if 1
+extern int vmware_svga_io_base;
+#endif
+
 static void pci_vmsvga_map_ioport(PCIDevice *pci_dev, int region_num,
                 uint32_t addr, uint32_t size, int type)
 {
     struct pci_vmsvga_state_s *d = (struct pci_vmsvga_state_s *) pci_dev;
     struct vmsvga_state_s *s = &d->chip;
 
+#if 1
+    vmware_svga_io_base = addr + SVGA_IO_MUL * SVGA_INDEX_PORT;
+#endif
     register_ioport_read(addr + SVGA_IO_MUL * SVGA_INDEX_PORT,
                     1, 4, vmsvga_index_read, s);
     register_ioport_write(addr + SVGA_IO_MUL * SVGA_INDEX_PORT,


More information about the freebsd-emulation mailing list