kaslr.c 2.1 KB

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