unsigned long kaslr_get_random_long(const char *purpose) { #ifdef CONFIG_X86_64 const unsigned long mix_const = 0x5d6008cbf3848dd3UL; #else const unsigned long mix_const = 0x3f39e593UL; #endif unsigned long raw, random = get_boot_seed(); bool use_i8254 = true; debug_putstr(purpose); debug_putstr(" KASLR using"); if (has_cpuflag(X86_FEATURE_RDRAND)) { debug_putstr(" RDRAND"); if (rdrand_long(&raw)) { random ^= raw; use_i8254 = false; } } if (has_cpuflag(X86_FEATURE_TSC)) { debug_putstr(" RDTSC"); raw = rdtsc(); random ^= raw; use_i8254 = false; } if (use_i8254) { debug_putstr(" i8254"); random ^= i8254(); } /* Circular multiply for better bit diffusion */ asm("mul %3" : "=a" (random), "=d" (raw) : "a" (random), "rm" (mix_const)); random += raw; debug_putstr("...\n"); return random; }
void x86_init_rdrand(struct cpuinfo_x86 *c) { #ifdef CONFIG_ARCH_RANDOM unsigned long tmp; int i, count, ok; if (!cpu_has(c, X86_FEATURE_RDRAND)) return; /* Nothing to do */ for (count = i = 0; i < RESEED_LOOP; i++) { ok = rdrand_long(&tmp); if (ok) count++; } if (count != RESEED_LOOP) clear_cpu_cap(c, X86_FEATURE_RDRAND); #endif }