1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
|
Index: qemu/target-i386/op_helper.c
@@ -517,6 +517,12 @@
#endif
}
+#if 1
+#define IOPL_WORKAROUND
+#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 +533,27 @@
((env->tr.flags >> DESC_TYPE_SHIFT) & 0xf) != 9 ||
env->tr.limit < 103)
goto fail;
+#ifdef IOPL_WORKAROUND
+ 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,20 @@
return 0;
}
+#if 1 && defined(TARGET_I386)
+#define IOPL_WORKAROUND
+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;
+#ifdef IOPL_WORKAROUND
+ 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,
|