cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

kaslr.c (2268B)


      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/shared/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
     34static 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
     49unsigned 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	if (purpose) {
     60		debug_putstr(purpose);
     61		debug_putstr(" KASLR using");
     62	}
     63
     64	if (has_cpuflag(X86_FEATURE_RDRAND)) {
     65		if (purpose)
     66			debug_putstr(" RDRAND");
     67		if (rdrand_long(&raw)) {
     68			random ^= raw;
     69			use_i8254 = false;
     70		}
     71	}
     72
     73	if (has_cpuflag(X86_FEATURE_TSC)) {
     74		if (purpose)
     75			debug_putstr(" RDTSC");
     76		raw = rdtsc();
     77
     78		random ^= raw;
     79		use_i8254 = false;
     80	}
     81
     82	if (use_i8254) {
     83		if (purpose)
     84			debug_putstr(" i8254");
     85		random ^= i8254();
     86	}
     87
     88	/* Circular multiply for better bit diffusion */
     89	asm(_ASM_MUL "%3"
     90	    : "=a" (random), "=d" (raw)
     91	    : "a" (random), "rm" (mix_const));
     92	random += raw;
     93
     94	if (purpose)
     95		debug_putstr("...\n");
     96
     97	return random;
     98}