diff mbox

spapr: Add support for hwrng when available

Message ID 1380177444-4961-1-git-send-email-michael@ellerman.id.au
State New
Headers show

Commit Message

Michael Ellerman Sept. 26, 2013, 6:37 a.m. UTC
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 <michael@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(+)

Comments

Alexander Graf Sept. 26, 2013, 11:06 a.m. UTC | #1
On 26.09.2013, at 08:37, Michael Ellerman wrote:

> 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 <michael@ellerman.id.au>

Please implement this 100% without KVM first, then if we end up running into performance bottlenecks we can always add KVM acceleration.

Also, please make sure to CC qemu-ppc@nongnu.org on PPC patches :).


Alex
Michael Ellerman Sept. 27, 2013, 8:36 a.m. UTC | #2
On Thu, 2013-09-26 at 13:06 +0200, Alexander Graf wrote:
> On 26.09.2013, at 08:37, Michael Ellerman wrote:
> 
> > 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 <michael@ellerman.id.au>
> 
> Please implement this 100% without KVM first, then if we end up running into performance bottlenecks we can always add KVM acceleration.

So have the host kernel read from the hwrng, export it to userspace via
a char device, which is then read by qemu, which then copies it back
into the host kernel, which can then give it to the guest.

Or from the guest perspective, instead of a cheap switch to host real
mode and back - a full switch to kernel virtual, then to user, back to
kernel, back to user, back to kernel, back to guest.

Frankly I can't see why that is a superior option?


> Also, please make sure to CC qemu-ppc@nongnu.org on PPC patches :).

Sorry, didn't realise there was one, will add it in future.

cheers
Paolo Bonzini Sept. 27, 2013, 8:58 a.m. UTC | #3
Il 27/09/2013 10:36, Michael Ellerman ha scritto:
> So have the host kernel read from the hwrng, export it to userspace via
> a char device, which is then read by qemu, which then copies it back
> into the host kernel, which can then give it to the guest.
> 
> Or from the guest perspective, instead of a cheap switch to host real
> mode and back - a full switch to kernel virtual, then to user, back to
> kernel, back to user, back to kernel, back to guest.
> 
> Frankly I can't see why that is a superior option?

Because this is not a fast path at all.  Doing things in QEMU lets
people test and configure the paravirtualized hwrng even if they do not
have a hwrng in the host, and even if they are running with emulation
(TCG) instead of KVM.

But as I mentioned in the kernel thread, perhaps you do not need the
hypercall at all if virtio-rng is enough (it should be for Linux guests).

Paolo
diff mbox

Patch

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