On (Mon) 31 Aug 2015 [20:46:02], Thomas Huth wrote: > The PAPR interface provides a hypercall to pass high-quality > hardware generated random numbers to guests. So let's provide > this call in QEMU, too, so that guests that do not support > virtio-rnd yet can get good random numbers, too.
virtio-rng, not rnd. Can you elaborate what you mean by 'guests that do not support virtio-rng yet'? The Linux kernel has had the virtio-rng driver since 2.6.26, so I'm assuming that's not the thing you're alluding to. Not saying this hypercall isn't a good idea, just asking why. I think there's are valid reasons like the driver fails to load, or the driver is compiled out, or simply is loaded too late in the boot cycle. > Please note that this hypercall should provide "good" random data > instead of pseudo-random, so the function uses the RngBackend to > retrieve the values instead of using a "simple" library function > like rand() or g_random_int(). Since there are multiple RngBackends > available, the user must select an appropriate backend via the > "h-random" property of the the machine state to enable it, e.g. > > qemu-system-ppc64 -M pseries,h-random=rng-random ... > > to use the /dev/random backend, or "h-random=rng-egd" to use the > Entropy Gathering Daemon instead. I was going to suggest using -object here, but already I see you and David have reached an agreement for that. Out of curiosity: what does the host kernel use for its source when going the hypercall route? > +static void random_recv(void *dest, const void *src, size_t size) > +{ > + HRandomData *hrcrdp = dest; > + > + if (src && size > 0) { > + memcpy(&hrcrdp->val.v8[hrcrdp->received], src, size); > + hrcrdp->received += size; > + } > + qemu_sem_post(&hrcrdp->sem); > +} > + > +static target_ulong h_random(PowerPCCPU *cpu, sPAPRMachineState *spapr, > + target_ulong opcode, target_ulong *args) > +{ > + HRandomData hrcrd; > + > + if (!hrandom_rng) { > + return H_HARDWARE; > + } > + > + qemu_sem_init(&hrcrd.sem, 0); > + hrcrd.val.v64 = 0; > + hrcrd.received = 0; > + > + qemu_mutex_unlock_iothread(); > + while (hrcrd.received < 8) { > + rng_backend_request_entropy((RngBackend *)hrandom_rng, > + 8 - hrcrd.received, random_recv, &hrcrd); > + qemu_sem_wait(&hrcrd.sem); > + } Is it possible for a second hypercall to arrive while the first is waiting for the backend to provide data? > + qemu_mutex_lock_iothread(); > + > + qemu_sem_destroy(&hrcrd.sem); > + args[0] = hrcrd.val.v64; > + > + return H_SUCCESS; > +} Amit