PatchworkOS
Loading...
Searching...
No Matches
rand.c
Go to the documentation of this file.
2
3#include <kernel/cpu/cpu.h>
4#include <kernel/cpu/smp.h>
5#include <kernel/log/log.h>
6
7#include <stdbool.h>
8#include <stdint.h>
9#include <sys/cpuid.h>
10
11static atomic_uint64_t seed = ATOMIC_VAR_INIT(0x123456789ABCDEF0);
12
14{
15 for (uint64_t i = 0; i < size; i++)
16 {
17 uint64_t currentSeed = atomic_load(&seed) + timer_uptime();
18 currentSeed ^= currentSeed << 13;
19 currentSeed ^= currentSeed >> 7;
20 currentSeed ^= currentSeed << 17;
21 atomic_store(&seed, currentSeed);
22 ((uint8_t*)buffer)[i] = (uint8_t)(currentSeed & 0xFF);
23 }
24
25 return 0;
26}
27
29{
32
33 ctx->rdrandAvail = (info.featuresEcx & CPUID_ECX_RDRAND) != 0;
34
35 if (!ctx->rdrandAvail)
36 {
37 return;
38 }
39
40 uint64_t prev = UINT64_MAX;
41 uint32_t test;
42 for (uint64_t i = 0; i < 10; i++)
43 {
44 if (rdrand_do(&test, 100) == ERR)
45 {
46 LOG_WARN("cpu%d rdrand instruction failed, disabling\n", smp_self_unsafe()->id);
47 ctx->rdrandAvail = false;
48 return;
49 }
50
51 if (prev != UINT64_MAX && prev == test)
52 {
53 LOG_WARN("cpu%d rdrand producing same value repeatedly, disabling\n", smp_self_unsafe()->id);
54 ctx->rdrandAvail = false;
55 return;
56 }
57 prev = test;
58 }
59}
60
62{
63 cpu_t* self = smp_self();
64
65 if (!self->rand.rdrandAvail)
66 {
67 smp_put();
68 return rand_gen_fallback(buffer, size);
69 }
70
71 uint8_t* ptr = (uint8_t*)buffer;
72 uint64_t remaining = size;
73 while (remaining >= sizeof(uint32_t))
74 {
75 uint32_t value;
76 if (rdrand_do(&value, 100) == ERR)
77 {
78 smp_put();
79 return ERR;
80 }
81 memcpy(ptr, &value, sizeof(uint32_t));
82 ptr += sizeof(uint32_t);
83 remaining -= sizeof(uint32_t);
84 }
85
86 if (remaining > 0)
87 {
88 uint32_t value;
89 if (rdrand_do(&value, 100) == ERR)
90 {
91 smp_put();
92 return ERR;
93 }
94 memcpy(ptr, &value, remaining);
95 }
96
97 smp_put();
98 return 0;
99}
static cpu_t * smp_self_unsafe(void)
Returns a pointer to the cpu_t structure of the current CPU.
Definition smp.h:90
static cpu_t * smp_self(void)
Returns a pointer to the cpu_t structure of the current CPU.
Definition smp.h:115
static void smp_put(void)
Re-enables interrupts after a call to smp_self().
Definition smp.h:125
uint64_t rdrand_do(uint32_t *value, uint8_t retries)
Generates a random 32-bit unsigned integer using the RDRAND instruction.
void rand_cpu_init(rand_cpu_ctx_t *ctx)
Initializes the random number generator.
Definition rand.c:28
uint64_t rand_gen(void *buffer, uint64_t size)
Fills a buffer with random bytes.
Definition rand.c:61
#define LOG_WARN(format,...)
Definition log.h:88
clock_t timer_uptime(void)
Time since boot.
Definition timer.c:73
static void cpuid_feature_info(cpuid_feature_info_t *info)
Wrapper to get CPU feature information.
Definition cpuid.h:204
@ CPUID_ECX_RDRAND
Definition cpuid.h:76
#define ERR
Integer error value.
Definition ERR.h:17
static fb_info_t info
Definition gop.c:41
static uint64_t rand_gen_fallback(void *buffer, uint64_t size)
Definition rand.c:13
static atomic_uint64_t seed
Definition rand.c:11
EFI_PHYSICAL_ADDRESS buffer
Definition mem.c:15
#define atomic_store(object, desired)
Definition stdatomic.h:289
#define atomic_load(object)
Definition stdatomic.h:288
#define ATOMIC_VAR_INIT(value)
Definition stdatomic.h:74
__UINT32_TYPE__ uint32_t
Definition stdint.h:15
__UINT64_TYPE__ uint64_t
Definition stdint.h:17
#define UINT64_MAX
Definition stdint.h:74
__UINT8_TYPE__ uint8_t
Definition stdint.h:11
_PUBLIC void * memcpy(void *_RESTRICT s1, const void *_RESTRICT s2, size_t n)
Definition memcpy.c:4
CPU structure.
Definition cpu.h:42
rand_cpu_ctx_t rand
Definition cpu.h:52
CPU feature information structure.
Definition cpuid.h:192
CPU random number generator context.
Definition rand.h:23
bool rdrandAvail
If set, the RDRAND instruction is avilable and working.
Definition rand.h:24