@@ -638,6 +638,36 @@ static void __init calculate_pv_max_policy(void)
p->extd.raw[0xa] = EMPTY_LEAF; /* No SVM for PV guests. */
}
+/*
+ * Allow virtual arch LBR with a single depth that's equal to that of the
+ * host. If this is not possible, disable arch LBR altogether.
+ */
+static void adjust_arch_lbr_depth(uint32_t fs[FEATURESET_NR_ENTRIES])
+{
+ uint64_t host_lbr_depth;
+ bool lbr_supported = true;
+
+ rdmsrl(MSR_IA32_LASTBRANCH_DEPTH, host_lbr_depth);
+ if ((host_lbr_depth == 0) ||
+ (host_lbr_depth % 8) ||
+ (host_lbr_depth > 64))
+ lbr_supported = false;
+
+ host_lbr_depth = 1ul << ((host_lbr_depth / 8) - 1);
+ if ((host_lbr_depth & fs[FEATURESET_1Ca] & 0xff) == 0)
+ lbr_supported = false;
+
+ if (lbr_supported)
+ {
+ fs[FEATURESET_1Ca] = (fs[FEATURESET_1Ca] & ~0xffu) | host_lbr_depth;
+ }
+ else
+ {
+ __clear_bit(X86_FEATURE_ARCH_LBR, fs);
+ fs[FEATURESET_1Ca] = fs[FEATURESET_1Cb] = fs[FEATURESET_1Cc] = 0;
+ }
+}
+
static void __init calculate_pv_def_policy(void)
{
struct cpu_policy *p = &pv_def_cpu_policy;
@@ -760,6 +790,9 @@ static void __init calculate_hvm_max_policy(void)
__clear_bit(X86_FEATURE_XSAVES, fs);
}
+ if ( test_bit(X86_FEATURE_ARCH_LBR, fs) )
+ adjust_arch_lbr_depth(fs);
+
/*
* Xen doesn't use PKS, so the guest support for it has opted to not use
* the VMCS load/save controls for efficiency reasons. This depends on