Some powerpc systems have support for a hardware random number generator (hwrng). If such a hwrng is present the host kernel can provide access to it via the H_RANDOM hcall.
The kernel advertises the presence of a hwrng with the KVM_CAP_PPC_HWRNG capability. If this is detected we add the appropriate device tree bits to advertise the presence of the hwrng to the guest kernel. Signed-off-by: Michael Ellerman <mich...@ellerman.id.au> --- hw/ppc/spapr.c | 16 ++++++++++++++++ include/hw/ppc/spapr.h | 1 + linux-headers/linux/kvm.h | 1 + target-ppc/kvm.c | 5 +++++ target-ppc/kvm_ppc.h | 5 +++++ 5 files changed, 28 insertions(+) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 004184d..5909df1 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -497,6 +497,22 @@ static void *spapr_create_fdt_skel(const char *cpu_model, _FDT((fdt_end_node(fdt))); + if (kvmppc_hwrng_present()) { + _FDT(fdt_begin_node(fdt, "ibm,platform-facilities")); + + _FDT(fdt_property_string(fdt, "name", "ibm,platform-facilities")); + _FDT(fdt_property_string(fdt, "device_type", + "ibm,platform-facilities")); + _FDT(fdt_property_cell(fdt, "#address-cells", 0x1)); + _FDT(fdt_property_cell(fdt, "#size-cells", 0x0)); + _FDT(fdt_begin_node(fdt, "ibm,random-v1")); + _FDT(fdt_property_string(fdt, "name", "ibm,random-v1")); + _FDT(fdt_property_string(fdt, "compatible", "ibm,random")); + _FDT((fdt_end_node(fdt))); + } + + _FDT((fdt_end_node(fdt))); + /* event-sources */ spapr_events_fdt_skel(fdt, epow_irq); diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h index e37b419..c509500 100644 --- a/include/hw/ppc/spapr.h +++ b/include/hw/ppc/spapr.h @@ -283,6 +283,7 @@ typedef struct sPAPREnvironment { #define H_GET_EM_PARMS 0x2B8 #define H_SET_MPP 0x2D0 #define H_GET_MPP 0x2D4 +#define H_RANDOM 0x300 #define H_SET_MODE 0x31C #define MAX_HCALL_OPCODE H_SET_MODE diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h index c614070..7be746c 100644 --- a/linux-headers/linux/kvm.h +++ b/linux-headers/linux/kvm.h @@ -666,6 +666,7 @@ struct kvm_ppc_smmu_info { #define KVM_CAP_IRQ_MPIC 90 #define KVM_CAP_PPC_RTAS 91 #define KVM_CAP_IRQ_XICS 92 +#define KVM_CAP_PPC_HWRNG 95 #ifdef KVM_CAP_IRQ_ROUTING diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c index 8a196c6..faf5dae 100644 --- a/target-ppc/kvm.c +++ b/target-ppc/kvm.c @@ -1875,3 +1875,8 @@ int kvm_arch_on_sigbus(int code, void *addr) void kvm_arch_init_irq_routing(KVMState *s) { } + +bool kvmppc_hwrng_present(void) +{ + return kvm_enabled() && kvm_check_extension(kvm_state, KVM_CAP_PPC_HWRNG); +} diff --git a/target-ppc/kvm_ppc.h b/target-ppc/kvm_ppc.h index 4ae7bf2..b7b898b 100644 --- a/target-ppc/kvm_ppc.h +++ b/target-ppc/kvm_ppc.h @@ -42,6 +42,7 @@ int kvmppc_get_htab_fd(bool write); int kvmppc_save_htab(QEMUFile *f, int fd, size_t bufsize, int64_t max_ns); int kvmppc_load_htab_chunk(QEMUFile *f, int fd, uint32_t index, uint16_t n_valid, uint16_t n_invalid); +bool kvmppc_hwrng_present(void); #else @@ -181,6 +182,10 @@ static inline int kvmppc_load_htab_chunk(QEMUFile *f, int fd, uint32_t index, abort(); } +static inline bool kvmppc_hwrng_present(void) +{ + return false; +} #endif #ifndef CONFIG_KVM -- 1.8.1.2