diff --git a/xen/arch/x86/pv/domain.c b/xen/arch/x86/pv/domain.c
index 4b6f48dea2..3c930cffaa 100644
--- a/xen/arch/x86/pv/domain.c
+++ b/xen/arch/x86/pv/domain.c
@@ -343,7 +343,7 @@ int pv_domain_initialise(struct domain *d)
     return rc;
 }
 
-bool __init xpti_pcid_enabled(void)
+bool xpti_pcid_enabled(void)
 {
     return use_invpcid && cpu_has_pcid &&
            (opt_pcid == PCID_ALL || opt_pcid == PCID_XPTI);
diff --git a/xen/arch/x86/spec_ctrl.c b/xen/arch/x86/spec_ctrl.c
index aa632bdcee..dce101e9c3 100644
--- a/xen/arch/x86/spec_ctrl.c
+++ b/xen/arch/x86/spec_ctrl.c
@@ -18,6 +18,7 @@
  */
 #include <xen/errno.h>
 #include <xen/init.h>
+#include <xen/keyhandler.h>
 #include <xen/lib.h>
 #include <xen/warning.h>
 
@@ -35,8 +36,8 @@ static bool __initdata opt_msr_sc_pv = true;
 static bool __initdata opt_msr_sc_hvm = true;
 static bool __initdata opt_rsb_pv = true;
 static bool __initdata opt_rsb_hvm = true;
-static int8_t __initdata opt_md_clear_pv = -1;
-static int8_t __initdata opt_md_clear_hvm = -1;
+static int8_t opt_md_clear_pv = -1;
+static int8_t opt_md_clear_hvm = -1;
 
 /* Cmdline controls for Xen's speculative settings. */
 static enum ind_thunk {
@@ -59,12 +60,15 @@ uint8_t __read_mostly default_xen_spec_ctrl;
 uint8_t __read_mostly default_spec_ctrl_flags;
 
 paddr_t __read_mostly l1tf_addr_mask, __read_mostly l1tf_safe_maddr;
-static bool __initdata cpu_has_bug_l1tf;
-static unsigned int __initdata l1d_maxphysaddr;
+static bool cpu_has_bug_l1tf;
+static unsigned int l1d_maxphysaddr;
 
 static bool __initdata cpu_has_bug_msbds_only; /* => minimal HT impact. */
 static bool __initdata cpu_has_bug_mds; /* Any other M{LP,SB,FB}DS combination. */
 
+static enum ind_thunk __read_mostly thunk = THUNK_DEFAULT;
+static uint64_t __read_mostly cached_caps;
+
 static int __init parse_spec_ctrl(const char *s)
 {
     const char *ss;
@@ -300,7 +304,7 @@ static __init int parse_pv_l1tf(const char *s)
 }
 custom_param("pv-l1tf", parse_pv_l1tf);
 
-static void __init print_details(enum ind_thunk thunk, uint64_t caps)
+static void print_details(unsigned char key)
 {
     unsigned int _7d0 = 0, e8b = 0, tmp;
 
@@ -320,14 +324,14 @@ static void __init print_details(enum ind_thunk thunk, uint64_t caps)
            (_7d0 & cpufeat_mask(X86_FEATURE_SSBD))  ? " SSBD"      : "",
            (_7d0 & cpufeat_mask(X86_FEATURE_MD_CLEAR)) ? " MD_CLEAR" : "",
            (e8b  & cpufeat_mask(X86_FEATURE_IBPB))  ? " IBPB"      : "",
-           (caps & ARCH_CAPS_IBRS_ALL)              ? " IBRS_ALL"  : "",
-           (caps & ARCH_CAPS_RDCL_NO)               ? " RDCL_NO"   : "",
-           (caps & ARCH_CAPS_RSBA)                  ? " RSBA"      : "",
-           (caps & ARCH_CAPS_SKIP_L1DFL)            ? " SKIP_L1DFL": "",
-           (caps & ARCH_CAPS_SSB_NO)                ? " SSB_NO"    : "",
-           (caps & ARCH_CAPS_MDS_NO)                ? " MDS_NO"    : "",
-           (caps & ARCH_CAPS_TSX_CTRL)              ? " TSX_CTRL"  : "",
-           (caps & ARCH_CAPS_TAA_NO)                ? " TAA_NO"    : "");
+           (cached_caps & ARCH_CAPS_IBRS_ALL)       ? " IBRS_ALL"  : "",
+           (cached_caps & ARCH_CAPS_RDCL_NO)        ? " RDCL_NO"   : "",
+           (cached_caps & ARCH_CAPS_RSBA)           ? " RSBA"      : "",
+           (cached_caps & ARCH_CAPS_SKIP_L1DFL)     ? " SKIP_L1DFL": "",
+           (cached_caps & ARCH_CAPS_SSB_NO)         ? " SSB_NO"    : "",
+           (cached_caps & ARCH_CAPS_MDS_NO)         ? " MDS_NO"    : "",
+           (cached_caps & ARCH_CAPS_TSX_CTRL)       ? " TSX_CTRL"  : "",
+           (cached_caps & ARCH_CAPS_TAA_NO)         ? " TAA_NO"    : "");
 
     /* Compiled-in support which pertains to mitigations. */
     if ( IS_ENABLED(CONFIG_INDIRECT_THUNK) || IS_ENABLED(CONFIG_SHADOW_PAGING) )
@@ -350,7 +354,7 @@ static void __init print_details(enum ind_thunk thunk, uint64_t caps)
            (default_xen_spec_ctrl & SPEC_CTRL_IBRS)  ? "IBRS+" :  "IBRS-",
            !boot_cpu_has(X86_FEATURE_SSBD)           ? "" :
            (default_xen_spec_ctrl & SPEC_CTRL_SSBD)  ? " SSBD+" : " SSBD-",
-           !(caps & ARCH_CAPS_TSX_CTRL)              ? "" :
+           !(cached_caps & ARCH_CAPS_TSX_CTRL)       ? "" :
            (opt_tsx & 1)                             ? " TSX+" : " TSX-",
            opt_ibpb                                  ? " IBPB"  : "",
            opt_l1d_flush                             ? " L1D_FLUSH" : "",
@@ -872,13 +876,11 @@ static __init void mds_calculations(uint64_t caps)
 
 void __init init_speculation_mitigations(void)
 {
-    enum ind_thunk thunk = THUNK_DEFAULT;
     bool use_spec_ctrl = false, ibrs = false, hw_smt_enabled;
     bool cpu_has_bug_taa;
-    uint64_t caps = 0;
 
     if ( boot_cpu_has(X86_FEATURE_ARCH_CAPS) )
-        rdmsrl(MSR_ARCH_CAPABILITIES, caps);
+        rdmsrl(MSR_ARCH_CAPABILITIES, cached_caps);
 
     hw_smt_enabled = check_smt_enabled();
 
@@ -909,7 +911,7 @@ void __init init_speculation_mitigations(void)
              * On Intel hardware, we'd like to use retpoline in preference to
              * IBRS, but only if it is safe on this hardware.
              */
-            else if ( retpoline_safe(caps) )
+            else if ( retpoline_safe(cached_caps) )
                 thunk = THUNK_RETPOLINE;
             else if ( boot_cpu_has(X86_FEATURE_IBRSB) )
                 ibrs = true;
@@ -1016,9 +1018,9 @@ void __init init_speculation_mitigations(void)
     if ( default_xen_spec_ctrl )
         setup_force_cpu_cap(X86_FEATURE_SC_MSR_IDLE);
 
-    xpti_init_default(caps);
+    xpti_init_default(cached_caps);
 
-    l1tf_calculations(caps);
+    l1tf_calculations(cached_caps);
 
     /*
      * By default, enable PV domU L1TF mitigations on all L1TF-vulnerable
@@ -1039,7 +1041,7 @@ void __init init_speculation_mitigations(void)
     if ( !boot_cpu_has(X86_FEATURE_L1D_FLUSH) )
         opt_l1d_flush = 0;
     else if ( opt_l1d_flush == -1 )
-        opt_l1d_flush = cpu_has_bug_l1tf && !(caps & ARCH_CAPS_SKIP_L1DFL);
+        opt_l1d_flush = cpu_has_bug_l1tf && !(cached_caps & ARCH_CAPS_SKIP_L1DFL);
 
     if ( opt_branch_harden )
         setup_force_cpu_cap(X86_FEATURE_SC_BRANCH_HARDEN);
@@ -1061,7 +1063,7 @@ void __init init_speculation_mitigations(void)
             "enabled.  Please assess your configuration and choose an\n"
             "explicit 'smt=<bool>' setting.  See XSA-273.\n");
 
-    mds_calculations(caps);
+    mds_calculations(cached_caps);
 
     /*
      * By default, enable PV and HVM mitigations on MDS-vulnerable hardware.
@@ -1089,7 +1091,7 @@ void __init init_speculation_mitigations(void)
         setup_force_cpu_cap(X86_FEATURE_SC_VERW_PV);
     if ( opt_md_clear_pv || opt_md_clear_hvm )
         setup_force_cpu_cap(X86_FEATURE_SC_VERW_IDLE);
-    if ( opt_md_clear_hvm && !(caps & ARCH_CAPS_SKIP_L1DFL) && !opt_l1d_flush )
+    if ( opt_md_clear_hvm && !(cached_caps & ARCH_CAPS_SKIP_L1DFL) && !opt_l1d_flush )
         setup_force_cpu_cap(X86_FEATURE_SC_VERW_HVM);
 
     /*
@@ -1121,8 +1123,8 @@ void __init init_speculation_mitigations(void)
      *       we check both to spot TSX in a microcode/cmdline independent way.
      */
     cpu_has_bug_taa =
-        (cpu_has_rtm || (caps & ARCH_CAPS_TSX_CTRL)) &&
-        (caps & (ARCH_CAPS_MDS_NO | ARCH_CAPS_TAA_NO)) == ARCH_CAPS_MDS_NO;
+        (cpu_has_rtm || (cached_caps & ARCH_CAPS_TSX_CTRL)) &&
+        (cached_caps & (ARCH_CAPS_MDS_NO | ARCH_CAPS_TAA_NO)) == ARCH_CAPS_MDS_NO;
 
     /*
      * On TAA-affected hardware, disabling TSX is the preferred mitigation, vs
@@ -1138,7 +1140,7 @@ void __init init_speculation_mitigations(void)
      * plausibly value TSX higher than Hyperthreading...), disable TSX to
      * mitigate TAA.
      */
-    if ( opt_tsx == -1 && cpu_has_bug_taa && (caps & ARCH_CAPS_TSX_CTRL) &&
+    if ( opt_tsx == -1 && cpu_has_bug_taa && (cached_caps & ARCH_CAPS_TSX_CTRL) &&
          ((hw_smt_enabled && opt_smt) ||
           !boot_cpu_has(X86_FEATURE_SC_VERW_IDLE)) )
     {
@@ -1149,7 +1151,7 @@ void __init init_speculation_mitigations(void)
         tsx_init();
     }
 
-    print_details(thunk, caps);
+    print_details('b');
 
     /*
      * If MSR_SPEC_CTRL is available, apply Xen's default setting and discard
@@ -1180,6 +1182,8 @@ void __init init_speculation_mitigations(void)
 
         wrmsrl(MSR_SPEC_CTRL, bsp_delay_spec_ctrl ? 0 : default_xen_spec_ctrl);
     }
+
+    register_keyhandler('b', print_details, "dump vulnerability details", 1);
 }
 
 static void __init __maybe_unused build_assertions(void)
