Index: /trunk/include/VBox/settings.h
===================================================================
--- /trunk/include/VBox/settings.h	(revision 71107)
+++ /trunk/include/VBox/settings.h	(revision 71108)
@@ -907,4 +907,6 @@
     bool                fIBPBOnVMExit;          //< added out of cycle, after 1.16 was out.
     bool                fIBPBOnVMEntry;         //< added out of cycle, after 1.16 was out.
+    bool                fSpecCtrl;              //< added out of cycle, after 1.16 was out.
+    bool                fSpecCtrlByHost;        //< added out of cycle, after 1.16 was out.
     bool                fNestedHWVirt;          //< requires settings version 1.17 (VirtualBox 6.0)
     typedef enum LongModeType { LongMode_Enabled, LongMode_Disabled, LongMode_Legacy } LongModeType;
Index: /trunk/include/VBox/vmm/cpum.h
===================================================================
--- /trunk/include/VBox/vmm/cpum.h	(revision 71107)
+++ /trunk/include/VBox/vmm/cpum.h	(revision 71108)
@@ -1223,4 +1223,6 @@
 VMMR0_INT_DECL(void)        CPUMR0SetGuestTscAux(PVMCPU pVCpu, uint64_t uValue);
 VMMR0_INT_DECL(uint64_t)    CPUMR0GetGuestTscAux(PVMCPU pVCpu);
+VMMR0_INT_DECL(void)        CPUMR0SetGuestSpecCtrl(PVMCPU pVCpu, uint64_t uValue);
+VMMR0_INT_DECL(uint64_t)    CPUMR0GetGuestSpecCtrl(PVMCPU pVCpu);
 /** @} */
 
Index: /trunk/src/VBox/Frontends/VBoxManage/VBoxManageHelp.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxManage/VBoxManageHelp.cpp	(revision 71107)
+++ /trunk/src/VBox/Frontends/VBoxManage/VBoxManageHelp.cpp	(revision 71108)
@@ -514,4 +514,5 @@
                      "                            [--ibpb-on-vm-exit on|off]\n"
                      "                            [--ibpb-on-vm-entry on|off]\n"
+                     "                            [--spec-ctrl on|off]\n"
                      "                            [--nested-hw-virt on|off]\n"
                      "                            [--cpu-profile \"host|Intel 80[86|286|386]\"]\n"
Index: /trunk/src/VBox/Frontends/VBoxManage/VBoxManageModifyVM.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxManage/VBoxManageModifyVM.cpp	(revision 71107)
+++ /trunk/src/VBox/Frontends/VBoxManage/VBoxManageModifyVM.cpp	(revision 71108)
@@ -77,4 +77,5 @@
     MODIFYVM_IBPB_ON_VM_EXIT,
     MODIFYVM_IBPB_ON_VM_ENTRY,
+    MODIFYVM_SPEC_CTRL,
     MODIFYVM_NESTED_HW_VIRT,
     MODIFYVM_CPUS,
@@ -260,5 +261,6 @@
     { "--ibpb-on-vm-exit",          MODIFYVM_IBPB_ON_VM_EXIT,           RTGETOPT_REQ_BOOL_ONOFF },
     { "--ibpb-on-vm-entry",         MODIFYVM_IBPB_ON_VM_ENTRY,          RTGETOPT_REQ_BOOL_ONOFF },
-    { "--nested-hw-virt",           MODIFYVM_NESTED_HW_VIRT,             RTGETOPT_REQ_BOOL_ONOFF },
+    { "--spec-ctrl",                MODIFYVM_SPEC_CTRL,                 RTGETOPT_REQ_BOOL_ONOFF },
+    { "--nested-hw-virt",           MODIFYVM_NESTED_HW_VIRT,            RTGETOPT_REQ_BOOL_ONOFF },
     { "--cpuid-set",                MODIFYVM_SETCPUID,                  RTGETOPT_REQ_UINT32_OPTIONAL_PAIR | RTGETOPT_FLAG_HEX },
     { "--cpuid-remove",             MODIFYVM_DELCPUID,                  RTGETOPT_REQ_UINT32_OPTIONAL_PAIR | RTGETOPT_FLAG_HEX },
@@ -808,4 +810,8 @@
                 break;
 
+            case MODIFYVM_SPEC_CTRL:
+                CHECK_ERROR(sessionMachine, SetCPUProperty(CPUPropertyType_SpecCtrl, ValueUnion.f));
+                break;
+
             case MODIFYVM_NESTED_HW_VIRT:
                 CHECK_ERROR(sessionMachine, SetCPUProperty(CPUPropertyType_HWVirt, ValueUnion.f));
Index: /trunk/src/VBox/Main/idl/VirtualBox.xidl
===================================================================
--- /trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 71107)
+++ /trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 71108)
@@ -1009,5 +1009,5 @@
         host CPU supports it.  This setting will significantly slow down workloads
         causing many VM exits, so it is only recommended for situation where there
-        real need to be paranoid.
+        is a real need to be paranoid.
       </desc>
     </const>
@@ -1017,5 +1017,5 @@
         host CPU supports it.  This setting will significantly slow down workloads
         causing many VM exits, so it is only recommended for situation where there
-        real need to be paranoid.
+        is a real need to be paranoid.
       </desc>
     </const>
@@ -1024,4 +1024,17 @@
         Enabled the hardware virtualization (AMD-V/VT-x) feature on the guest CPU.
         This requires hardware virtualization on the host CPU.
+      </desc>
+    </const>
+    <const name="SpecCtrl"              value="9">
+      <desc>
+        If set, the speculation control CPUID bits and MSRs, when available on the
+        host, are exposed to the guest. Depending on the host CPU and operating
+        system, this may significantly slow down workloads causing many VM exits.
+      </desc>
+    </const>
+    <const name="SpecCtrlByHost"        value="10">
+      <desc>
+        If set, the speculation controls are managed by the host. This is intended
+        for guests which do not set the speculation controls themselves.
       </desc>
     </const>
Index: /trunk/src/VBox/Main/include/MachineImpl.h
===================================================================
--- /trunk/src/VBox/Main/include/MachineImpl.h	(revision 71107)
+++ /trunk/src/VBox/Main/include/MachineImpl.h	(revision 71108)
@@ -290,4 +290,6 @@
         BOOL                mIBPBOnVMExit;
         BOOL                mIBPBOnVMEntry;
+        BOOL                mSpecCtrl;
+        BOOL                mSpecCtrlByHost;
         BOOL                mNestedHWVirt;
         ULONG               mCPUCount;
Index: /trunk/src/VBox/Main/src-client/ConsoleImpl2.cpp
===================================================================
--- /trunk/src/VBox/Main/src-client/ConsoleImpl2.cpp	(revision 71107)
+++ /trunk/src/VBox/Main/src-client/ConsoleImpl2.cpp	(revision 71108)
@@ -1022,4 +1022,9 @@
         }
 
+        /* Speculation Control. */
+        BOOL fSpecCtrl = FALSE;
+        hrc = pMachine->GetCPUProperty(CPUPropertyType_SpecCtrl, &fSpecCtrl);      H();
+        InsertConfigInteger(pCPUM, "SpecCtrl", fSpecCtrl);
+
         /* Nested VT-x / AMD-V. */
         BOOL fNestedHWVirt = FALSE;
@@ -1172,4 +1177,8 @@
         hrc = pMachine->GetCPUProperty(CPUPropertyType_IBPBOnVMEntry, &fIBPBOnVMEntry); H();
         InsertConfigInteger(pHM, "IBPBOnVMEntry", fIBPBOnVMEntry);
+
+        BOOL fSpecCtrlByHost = false;
+        hrc = pMachine->GetCPUProperty(CPUPropertyType_SpecCtrlByHost, &fSpecCtrlByHost); H();
+        InsertConfigInteger(pHM, "SpecCtrlByHost", fSpecCtrlByHost);
 
         /* Reset overwrite. */
Index: /trunk/src/VBox/Main/src-server/MachineImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/src-server/MachineImpl.cpp	(revision 71107)
+++ /trunk/src/VBox/Main/src-server/MachineImpl.cpp	(revision 71108)
@@ -198,4 +198,6 @@
     mIBPBOnVMExit = false;
     mIBPBOnVMEntry = false;
+    mSpecCtrl = false;
+    mSpecCtrlByHost = false;
     mNestedHWVirt = false;
     mHPETEnabled = false;
@@ -2267,4 +2269,12 @@
             break;
 
+        case CPUPropertyType_SpecCtrl:
+            *aValue = mHWData->mSpecCtrl;
+            break;
+
+        case CPUPropertyType_SpecCtrlByHost:
+            *aValue = mHWData->mSpecCtrlByHost;
+            break;
+
         case CPUPropertyType_HWVirt:
             *aValue = mHWData->mNestedHWVirt;
@@ -2330,4 +2340,16 @@
             mHWData.backup();
             mHWData->mIBPBOnVMEntry = !!aValue;
+            break;
+
+        case CPUPropertyType_SpecCtrl:
+            i_setModified(IsModified_MachineData);
+            mHWData.backup();
+            mHWData->mSpecCtrl = !!aValue;
+            break;
+
+        case CPUPropertyType_SpecCtrlByHost:
+            i_setModified(IsModified_MachineData);
+            mHWData.backup();
+            mHWData->mSpecCtrlByHost = !!aValue;
             break;
 
@@ -9023,4 +9045,6 @@
         mHWData->mIBPBOnVMExit                = data.fIBPBOnVMExit;
         mHWData->mIBPBOnVMEntry               = data.fIBPBOnVMEntry;
+        mHWData->mSpecCtrl                    = data.fSpecCtrl;
+        mHWData->mSpecCtrlByHost              = data.fSpecCtrlByHost;
         mHWData->mNestedHWVirt                = data.fNestedHWVirt;
         mHWData->mCPUCount                    = data.cCPUs;
@@ -10349,4 +10373,6 @@
         data.fIBPBOnVMExit          = !!mHWData->mIBPBOnVMExit;
         data.fIBPBOnVMEntry         = !!mHWData->mIBPBOnVMEntry;
+        data.fSpecCtrl              = !!mHWData->mSpecCtrl;
+        data.fSpecCtrlByHost        = !!mHWData->mSpecCtrlByHost;
         data.fNestedHWVirt          = !!mHWData->mNestedHWVirt;
         data.cCPUs                  = mHWData->mCPUCount;
Index: /trunk/src/VBox/Main/xml/Settings.cpp
===================================================================
--- /trunk/src/VBox/Main/xml/Settings.cpp	(revision 71107)
+++ /trunk/src/VBox/Main/xml/Settings.cpp	(revision 71108)
@@ -2780,4 +2780,6 @@
     fIBPBOnVMExit(false),
     fIBPBOnVMEntry(false),
+    fSpecCtrl(false),
+    fSpecCtrlByHost(false),
     fNestedHWVirt(false),
     enmLongMode(HC_ARCH_BITS == 64 ? Hardware::LongMode_Enabled : Hardware::LongMode_Disabled),
@@ -2936,4 +2938,6 @@
             && fIBPBOnVMExit             == h.fIBPBOnVMExit
             && fIBPBOnVMEntry            == h.fIBPBOnVMEntry
+            && fSpecCtrl                 == h.fSpecCtrl
+            && fSpecCtrlByHost           == h.fSpecCtrlByHost
             && fNestedHWVirt             == h.fNestedHWVirt
             && cCPUs                     == h.cCPUs
@@ -3945,4 +3949,10 @@
                 pelmCPUChild->getAttributeValue("vmentry", hw.fIBPBOnVMEntry);
             }
+            pelmCPUChild = pelmHwChild->findChildElement("SpecCtrl");
+            if (pelmCPUChild)
+                pelmCPUChild->getAttributeValue("enabled", hw.fSpecCtrl);
+            pelmCPUChild = pelmHwChild->findChildElement("SpecCtrlByHost");
+            if (pelmCPUChild)
+                pelmCPUChild->getAttributeValue("enabled", hw.fSpecCtrlByHost);
             pelmCPUChild = pelmHwChild->findChildElement("NestedHWVirt");
             if (pelmCPUChild)
@@ -5284,4 +5294,8 @@
         }
     }
+    if (m->sv >= SettingsVersion_v1_16 && hw.fSpecCtrl)
+        pelmCPU->createChild("SpecCtrl")->setAttribute("enabled", hw.fSpecCtrl);
+    if (m->sv >= SettingsVersion_v1_16 && hw.fSpecCtrlByHost)
+        pelmCPU->createChild("SpecCtrlByHost")->setAttribute("enabled", hw.fSpecCtrlByHost);
     if (m->sv >= SettingsVersion_v1_17 && hw.fNestedHWVirt)
         pelmCPU->createChild("NestedHWVirt")->setAttribute("enabled", hw.fNestedHWVirt);
@@ -6969,5 +6983,7 @@
             || hardwareMachine.fX2APIC
             || hardwareMachine.fIBPBOnVMExit
-            || hardwareMachine.fIBPBOnVMEntry)
+            || hardwareMachine.fIBPBOnVMEntry
+            || hardwareMachine.fSpecCtrl
+            || hardwareMachine.fSpecCtrlByHost)
         {
             m->sv = SettingsVersion_v1_16;
Index: /trunk/src/VBox/VMM/VMMAll/CPUMAllMsrs.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/CPUMAllMsrs.cpp	(revision 71107)
+++ /trunk/src/VBox/VMM/VMMAll/CPUMAllMsrs.cpp	(revision 71108)
@@ -6295,4 +6295,29 @@
 }
 
+/**
+ * Fast way for HM to access the IA32_SPEC_CTRL register.
+ *
+ * @returns The register value.
+ * @param   pVCpu   The cross context virtual CPU structure of the calling EMT.
+ * @thread  EMT(pVCpu)
+ */
+VMMR0_INT_DECL(uint64_t) CPUMR0GetGuestSpecCtrl(PVMCPU pVCpu)
+{
+    return pVCpu->cpum.s.GuestMsrs.msr.SpecCtrl;
+}
+
+
+/**
+ * Fast way for HM to access the IA32_SPEC_CTRL register.
+ *
+ * @param   pVCpu   The cross context virtual CPU structure of the calling EMT.
+ * @param   uValue  The new value.
+ * @thread  EMT(pVCpu)
+ */
+VMMR0_INT_DECL(void) CPUMR0SetGuestSpecCtrl(PVMCPU pVCpu, uint64_t uValue)
+{
+    pVCpu->cpum.s.GuestMsrs.msr.SpecCtrl = uValue;
+}
+
 #endif /* IN_RING0 */
 
Index: /trunk/src/VBox/VMM/VMMR0/HMVMXR0.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR0/HMVMXR0.cpp	(revision 71107)
+++ /trunk/src/VBox/VMM/VMMR0/HMVMXR0.cpp	(revision 71108)
@@ -2491,4 +2491,11 @@
         }
 #endif
+        /*
+         * The IA32_PRED_CMD MSR is write-only and has no state associated with it. We never need to intercept
+         * access (writes need to be executed without exiting, reds will #GP-fault anyway).
+         */
+        if (pVM->cpum.ro.GuestFeatures.fIbpb)
+            hmR0VmxSetMsrPermission(pVCpu, MSR_IA32_PRED_CMD,     VMXMSREXIT_PASSTHRU_READ, VMXMSREXIT_PASSTHRU_WRITE);
+
         /* Though MSR_IA32_PERF_GLOBAL_CTRL is saved/restored lazily, we want intercept reads/write to it for now. */
     }
@@ -6630,4 +6637,5 @@
             case MSR_K8_SF_MASK:        pMixedCtx->msrSFMASK       = pMsr->u64Value;             break;
             case MSR_K8_KERNEL_GS_BASE: pMixedCtx->msrKERNELGSBASE = pMsr->u64Value;             break;
+            case MSR_IA32_SPEC_CTRL:    CPUMR0SetGuestSpecCtrl(pVCpu, pMsr->u64Value);           break;
             case MSR_K6_EFER: /* Nothing to do here since we intercept writes, see hmR0VmxLoadGuestMsrs(). */
                 break;
@@ -9172,4 +9180,19 @@
             Assert(!pVCpu->hm.s.vmx.cMsrs || pVCpu->hm.s.vmx.fUpdatedHostMsrs);
         }
+    }
+
+    if (pVM->cpum.ro.GuestFeatures.fIbrs)
+    {
+        bool fMsrUpdated;
+        int rc2 = hmR0VmxSaveGuestAutoLoadStoreMsrs(pVCpu, pMixedCtx);
+        AssertRC(rc2);
+        Assert(HMVMXCPU_GST_IS_UPDATED(pVCpu, HMVMX_UPDATED_GUEST_AUTO_LOAD_STORE_MSRS));
+
+        rc2 = hmR0VmxAddAutoLoadStoreMsr(pVCpu, MSR_IA32_SPEC_CTRL, CPUMR0GetGuestSpecCtrl(pVCpu), true /* fUpdateHostMsr */,
+                                         &fMsrUpdated);
+        AssertRC(rc2);
+        Assert(fMsrUpdated || pVCpu->hm.s.vmx.fUpdatedHostMsrs);
+        /* Finally, mark that all host MSR values are updated so we don't redo it without leaving VT-x. See @bugref{6956}. */
+        pVCpu->hm.s.vmx.fUpdatedHostMsrs = true;
     }
 
Index: /trunk/src/VBox/VMM/VMMR3/CPUMR3CpuId.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR3/CPUMR3CpuId.cpp	(revision 71107)
+++ /trunk/src/VBox/VMM/VMMR3/CPUMR3CpuId.cpp	(revision 71108)
@@ -1750,5 +1750,7 @@
             pFeatures->fIbrs                = pFeatures->fIbpb;
             pFeatures->fStibp               = RT_BOOL(pSxfLeaf0->uEdx & X86_CPUID_STEXT_FEATURE_EDX_STIBP);
+#if 0   // Disabled until IA32_ARCH_CAPABILITIES support can be tested
             pFeatures->fArchCap             = RT_BOOL(pSxfLeaf0->uEdx & X86_CPUID_STEXT_FEATURE_EDX_ARCHCAP);
+#endif
         }
 
@@ -4314,5 +4316,5 @@
 
         /* Check if speculation control is enabled. */
-        rc = CFGMR3QueryBoolDef(CFGMR3GetRoot(pVM), "EnableSpecCtrl", &fEnable, false);
+        rc = CFGMR3QueryBoolDef(pCpumCfg, "SpecCtrl", &fEnable, false);
         AssertRCReturn(rc, rc);
         if (fEnable)
@@ -4621,6 +4623,10 @@
                 {
                     pLeaf->uEdx |= X86_CPUID_STEXT_FEATURE_EDX_IBRS_IBPB;
+                    pVM->cpum.s.GuestFeatures.fIbrs = 1;
                     if (pVM->cpum.s.HostFeatures.fStibp)
+                    {
                         pLeaf->uEdx |= X86_CPUID_STEXT_FEATURE_EDX_STIBP;
+                        pVM->cpum.s.GuestFeatures.fStibp = 1;
+                    }
 
                     /* Make sure we have the speculation control MSR... */
Index: /trunk/src/VBox/VMM/VMMR3/HM.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR3/HM.cpp	(revision 71107)
+++ /trunk/src/VBox/VMM/VMMR3/HM.cpp	(revision 71108)
@@ -464,4 +464,5 @@
                               "|IBPBOnVMExit"
                               "|IBPBOnVMEntry"
+                              "|SpecCtrlByHost"
                               "|TPRPatchingEnabled"
                               "|64bitEnabled"
@@ -649,4 +650,9 @@
      * Costly paranoia setting. */
     rc = CFGMR3QueryBoolDef(pCfgHm, "IBPBOnVMEntry", &pVM->hm.s.fIbpbOnVmEntry, false);
+    AssertLogRelRCReturn(rc, rc);
+
+    /** @cfgm{/HM/SpecCtrlByHost, bool}
+     * Another expensive paranoia setting. */
+    rc = CFGMR3QueryBoolDef(pCfgHm, "SpecCtrlByHost", &pVM->hm.s.fSpecCtrlByHost, false);
     AssertLogRelRCReturn(rc, rc);
 
Index: /trunk/src/VBox/VMM/include/HMInternal.h
===================================================================
--- /trunk/src/VBox/VMM/include/HMInternal.h	(revision 71107)
+++ /trunk/src/VBox/VMM/include/HMInternal.h	(revision 71108)
@@ -421,6 +421,8 @@
     /** Set if indirect branch prediction barrier on VM entry. */
     bool                        fIbpbOnVmEntry;
+    /** Set if host manages speculation control settings. */
+    bool                        fSpecCtrlByHost;
     /** Explicit padding. */
-    bool                        afPadding[3];
+    bool                        afPadding[2];
 
     /** Maximum ASID allowed. */
