diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 204f4a9..a636c8f 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1048,7 +1048,9 @@ void pc_hot_add_cpu(const int64_t id, Error **errp)
     pc_new_cpu(current_cpu_model, apic_id, icc_bridge, errp);
 }
 
-void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge)
+/* vmware_port_ring3 true says enable VMware port access in ring3. */
+void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge,
+                  bool vmware_port_ring3)
 {
     int i;
     X86CPU *cpu = NULL;
@@ -1079,6 +1081,9 @@ void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge)
             error_report_err(error);
             exit(1);
         }
+        if (vmware_port_ring3) {
+            cpu->env.hflags2 |= HF2_VMPORT_HACK_MASK;
+        }
     }
 
     /* map APIC MMIO area if CPU has APIC */
@@ -1816,6 +1821,21 @@ static bool pc_machine_get_aligned_dimm(Object *obj, Error **errp)
     return pcms->enforce_aligned_dimm;
 }
 
+static bool pc_machine_get_vmware_port_ring3(Object *obj, Error **errp)
+{
+    PCMachineState *pcms = PC_MACHINE(obj);
+
+    return pcms->vmware_port_ring3;
+}
+
+static void pc_machine_set_vmware_port_ring3(Object *obj, bool value,
+                                             Error **errp)
+{
+    PCMachineState *pcms = PC_MACHINE(obj);
+
+    pcms->vmware_port_ring3 = value;
+}
+
 static void pc_machine_initfn(Object *obj)
 {
     PCMachineState *pcms = PC_MACHINE(obj);
@@ -1846,6 +1866,12 @@ static void pc_machine_initfn(Object *obj)
     object_property_add_bool(obj, PC_MACHINE_ENFORCE_ALIGNED_DIMM,
                              pc_machine_get_aligned_dimm,
                              NULL, NULL);
+
+    pcms->vmware_port_ring3 = false;
+    object_property_add_bool(obj, PC_MACHINE_VMWARE_PORT_RING3,
+                             pc_machine_get_vmware_port_ring3,
+                             pc_machine_set_vmware_port_ring3,
+                             NULL);
 }
 
 static void pc_machine_class_init(ObjectClass *oc, void *data)
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index 36c69d7..8559860 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -147,7 +147,7 @@ static void pc_init1(MachineState *machine,
     object_property_add_child(qdev_get_machine(), "icc-bridge",
                               OBJECT(icc_bridge), NULL);
 
-    pc_cpus_init(machine->cpu_model, icc_bridge);
+    pc_cpus_init(machine->cpu_model, icc_bridge, pc_machine->vmware_port_ring3);
 
     if (kvm_enabled() && kvmclock_enabled) {
         kvmclock_create();
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index bc40537..7dcde5f 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -136,7 +136,7 @@ static void pc_q35_init(MachineState *machine)
     object_property_add_child(qdev_get_machine(), "icc-bridge",
                               OBJECT(icc_bridge), NULL);
 
-    pc_cpus_init(machine->cpu_model, icc_bridge);
+    pc_cpus_init(machine->cpu_model, icc_bridge, pc_machine->vmware_port_ring3);
     pc_acpi_init("q35-acpi-dsdt.aml");
 
     kvmclock_create();
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index 1b35168..2119d5d 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -40,6 +40,7 @@ struct PCMachineState {
 
     uint64_t max_ram_below_4g;
     OnOffAuto vmport;
+    bool vmware_port_ring3;
     bool enforce_aligned_dimm;
 };
 
@@ -48,6 +49,7 @@ struct PCMachineState {
 #define PC_MACHINE_MAX_RAM_BELOW_4G "max-ram-below-4g"
 #define PC_MACHINE_VMPORT           "vmport"
 #define PC_MACHINE_ENFORCE_ALIGNED_DIMM "enforce-aligned-dimm"
+#define PC_MACHINE_VMWARE_PORT_RING3 "vmware-port-ring3"
 
 /**
  * PCMachineClass:
@@ -163,7 +165,9 @@ extern int fd_bootchk;
 void pc_register_ferr_irq(qemu_irq irq);
 void pc_acpi_smi_interrupt(void *opaque, int irq, int level);
 
-void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge);
+/* vmware_port_ring3 true says enable VMware port access in ring3. */
+void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge,
+                  bool vmware_port_ring3);
 void pc_hot_add_cpu(const int64_t id, Error **errp);
 void pc_acpi_init(const char *default_dsdt);
 
diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index ed7e5d5..c1d513c 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -2571,6 +2571,7 @@ static void x86_cpu_reset(CPUState *s)
     X86CPUClass *xcc = X86_CPU_GET_CLASS(cpu);
     CPUX86State *env = &cpu->env;
     int i;
+    bool save_vmware_port_ring3 = env->hflags2 & HF2_VMPORT_HACK_MASK;
 
     xcc->parent_reset(s);
 
@@ -2586,6 +2587,9 @@ static void x86_cpu_reset(CPUState *s)
     env->hflags |= HF_SOFTMMU_MASK;
 #endif
     env->hflags2 |= HF2_GIF_MASK;
+    if (save_vmware_port_ring3) {
+        env->hflags2 |= HF2_VMPORT_HACK_MASK;
+    }
 
     cpu_x86_update_cr0(env, 0x60000010);
     env->a20_mask = ~0x0;
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index e4c27b1..a366944 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -186,11 +186,13 @@
 #define HF2_HIF_SHIFT        1 /* value of IF_MASK when entering SVM */
 #define HF2_NMI_SHIFT        2 /* CPU serving NMI */
 #define HF2_VINTR_SHIFT      3 /* value of V_INTR_MASKING bit */
+#define HF2_VMPORT_HACK_SHIFT 4 /* skip iopl checking for VMware port */
 
 #define HF2_GIF_MASK          (1 << HF2_GIF_SHIFT)
 #define HF2_HIF_MASK          (1 << HF2_HIF_SHIFT)
 #define HF2_NMI_MASK          (1 << HF2_NMI_SHIFT)
 #define HF2_VINTR_MASK        (1 << HF2_VINTR_SHIFT)
+#define HF2_VMPORT_HACK_MASK  (1 << HF2_VMPORT_HACK_SHIFT)
 
 #define CR0_PE_SHIFT 0
 #define CR0_MP_SHIFT 1
diff --git a/target-i386/seg_helper.c b/target-i386/seg_helper.c
index 2bc757a..3c52f28 100644
--- a/target-i386/seg_helper.c
+++ b/target-i386/seg_helper.c
@@ -2566,6 +2566,12 @@ static inline void check_io(CPUX86State *env, int addr, int size)
 {
     int io_offset, val, mask;
 
+    /* vmport hack: skip iopl checking for VMware port 0x5658 (see
+     * vmport_realizefn()) */
+    if ((env->hflags2 & HF2_VMPORT_HACK_MASK) && (addr == 0x5658)) {
+        return;
+    }
+
     /* TSS must be a valid 32 bit one */
     if (!(env->tr.flags & DESC_P_MASK) ||
         ((env->tr.flags >> DESC_TYPE_SHIFT) & 0xf) != 9 ||
