spapr/irq: initialize the IRQ device only once
[qemu/ar7.git] / util / guest-random.c
blobe8124a3cad4895235bf1ebbbea4310f407469670
1 /*
2 * QEMU guest-visible random functions
4 * Copyright 2019 Linaro, Ltd.
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the Free
8 * Software Foundation; either version 2 of the License, or (at your option)
9 * any later version.
12 #include "qemu/osdep.h"
13 #include "qemu-common.h"
14 #include "qemu/cutils.h"
15 #include "qapi/error.h"
16 #include "qemu/guest-random.h"
17 #include "crypto/random.h"
20 static __thread GRand *thread_rand;
21 static bool deterministic;
24 static int glib_random_bytes(void *buf, size_t len)
26 GRand *rand = thread_rand;
27 size_t i;
28 uint32_t x;
30 if (unlikely(rand == NULL)) {
31 /* Thread not initialized for a cpu, or main w/o -seed. */
32 thread_rand = rand = g_rand_new();
35 for (i = 0; i + 4 <= len; i += 4) {
36 x = g_rand_int(rand);
37 __builtin_memcpy(buf + i, &x, 4);
39 if (i < len) {
40 x = g_rand_int(rand);
41 __builtin_memcpy(buf + i, &x, i - len);
43 return 0;
46 int qemu_guest_getrandom(void *buf, size_t len, Error **errp)
48 if (unlikely(deterministic)) {
49 /* Deterministic implementation using Glib's Mersenne Twister. */
50 return glib_random_bytes(buf, len);
51 } else {
52 /* Non-deterministic implementation using crypto routines. */
53 return qcrypto_random_bytes(buf, len, errp);
57 void qemu_guest_getrandom_nofail(void *buf, size_t len)
59 qemu_guest_getrandom(buf, len, &error_fatal);
62 uint64_t qemu_guest_random_seed_thread_part1(void)
64 if (deterministic) {
65 uint64_t ret;
66 glib_random_bytes(&ret, sizeof(ret));
67 return ret;
69 return 0;
72 void qemu_guest_random_seed_thread_part2(uint64_t seed)
74 g_assert(thread_rand == NULL);
75 if (deterministic) {
76 thread_rand =
77 g_rand_new_with_seed_array((const guint32 *)&seed,
78 sizeof(seed) / sizeof(guint32));
82 int qemu_guest_random_seed_main(const char *optarg, Error **errp)
84 unsigned long long seed;
85 if (parse_uint_full(optarg, &seed, 0)) {
86 error_setg(errp, "Invalid seed number: %s", optarg);
87 return -1;
88 } else {
89 deterministic = true;
90 qemu_guest_random_seed_thread_part2(seed);
91 return 0;