root/arch/x86/lib/kaslr.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. i8254
  2. kaslr_get_random_long

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

/* [<][>][^][v][top][bottom][index][help] */