@@ -531,6 +531,16 @@ static inline void sti(void)
asm volatile ("sti");
}
+static inline unsigned long long rdrand(void)
+{
+ long long r;
+
+ asm volatile("1:;\n\
+ rdrand %0;\n\
+ jnc 1b;\n":"=r"(r));
+ return r;
+}
+
static inline unsigned long long rdtsc(void)
{
long long r;
@@ -2704,11 +2704,23 @@ static void _svm_npt_rsvd_bits_test(u64 *pxe, u64 pxe_rsvd_bits, u64 efer,
static u64 get_random_bits(u64 hi, u64 low)
{
- u64 rsvd_bits;
+ unsigned retry = 5;
+ u64 rsvd_bits = 0;
+
+ if (this_cpu_has(X86_FEATURE_RDRAND)) {
+ do {
+ rsvd_bits = (rdrand() << low) & GENMASK_ULL(hi, low);
+ retry--;
+ } while (!rsvd_bits && retry);
+ }
- do {
- rsvd_bits = (rdtsc() << low) & GENMASK_ULL(hi, low);
- } while (!rsvd_bits);
+ if (!rsvd_bits) {
+ retry = 5;
+ do {
+ rsvd_bits = (rdtsc() << low) & GENMASK_ULL(hi, low);
+ retry--;
+ } while (!rsvd_bits && retry);
+ }
return rsvd_bits;
}
@@ -2733,10 +2745,11 @@ static void svm_npt_rsvd_bits_test(void)
/*
* 4k PTEs don't have reserved bits if MAXPHYADDR >= 52, just skip the
- * sub-test. The NX test is still valid, but the extra bit of coverage
+ * sub-test. Also skip if cannot generate the valid random reserved bits.
+ * The NX test is still valid, but the extra bit of coverage
* isn't worth the extra complexity.
*/
- if (cpuid_maxphyaddr() >= 52)
+ if ((cpuid_maxphyaddr() >= 52) || !get_random_bits(51, cpuid_maxphyaddr()))
goto skip_pte_test;
_svm_npt_rsvd_bits_test(npt_get_pte((u64)basic_guest_main),