^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Entropy functions used on early boot for KASLR base and memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * randomization. The base randomization is done in the compressed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * kernel and memory randomization is done early when the regular
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * kernel starts. This file is included in the compressed kernel and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * normally linked in the regular.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <asm/asm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <asm/kaslr.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <asm/msr.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <asm/archrandom.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <asm/e820/api.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <asm/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * When built for the regular kernel, several functions need to be stubbed out
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * or changed to their regular kernel equivalent.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #ifndef KASLR_COMPRESSED_BOOT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <asm/cpufeature.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <asm/setup.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define debug_putstr(v) early_printk("%s", v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define has_cpuflag(f) boot_cpu_has(f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define get_boot_seed() kaslr_offset()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define I8254_PORT_CONTROL 0x43
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define I8254_PORT_COUNTER0 0x40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define I8254_CMD_READBACK 0xC0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define I8254_SELECT_COUNTER0 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define I8254_STATUS_NOTREADY 0x40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) static inline u16 i8254(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) u16 status, timer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) outb(I8254_CMD_READBACK | I8254_SELECT_COUNTER0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) I8254_PORT_CONTROL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) status = inb(I8254_PORT_COUNTER0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) timer = inb(I8254_PORT_COUNTER0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) timer |= inb(I8254_PORT_COUNTER0) << 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) } while (status & I8254_STATUS_NOTREADY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) return timer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) unsigned long kaslr_get_random_long(const char *purpose)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #ifdef CONFIG_X86_64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) const unsigned long mix_const = 0x5d6008cbf3848dd3UL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) const unsigned long mix_const = 0x3f39e593UL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) unsigned long raw, random = get_boot_seed();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) bool use_i8254 = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) debug_putstr(purpose);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) debug_putstr(" KASLR using");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) if (has_cpuflag(X86_FEATURE_RDRAND)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) debug_putstr(" RDRAND");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) if (rdrand_long(&raw)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) random ^= raw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) use_i8254 = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) if (has_cpuflag(X86_FEATURE_TSC)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) debug_putstr(" RDTSC");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) raw = rdtsc();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) random ^= raw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) use_i8254 = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) if (use_i8254) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) debug_putstr(" i8254");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) random ^= i8254();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) /* Circular multiply for better bit diffusion */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) asm(_ASM_MUL "%3"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) : "=a" (random), "=d" (raw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) : "a" (random), "rm" (mix_const));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) random += raw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) debug_putstr("...\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) return random;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) }