aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorMichael Ellerman <michael@ellerman.id.au>2015-03-20 05:39:41 -0400
committerAlexander Graf <agraf@suse.de>2015-04-21 09:21:29 -0400
commite928e9cb3601ce240189bfea05b67ebd391c85ae (patch)
treed76d6501bea8ffe04a448e5a5660d8926f22b3b4 /arch/powerpc
parent99342cf8044420eebdf9297ca03a14cb6a7085a1 (diff)
KVM: PPC: Book3S HV: Add fast real-mode H_RANDOM implementation.
Some PowerNV systems include a hardware random-number generator. This HWRNG is present on POWER7+ and POWER8 chips and is capable of generating one 64-bit random number every microsecond. The random numbers are produced by sampling a set of 64 unstable high-frequency oscillators and are almost completely entropic. PAPR defines an H_RANDOM hypercall which guests can use to obtain one 64-bit random sample from the HWRNG. This adds a real-mode implementation of the H_RANDOM hypercall. This hypercall was implemented in real mode because the latency of reading the HWRNG is generally small compared to the latency of a guest exit and entry for all the threads in the same virtual core. Userspace can detect the presence of the HWRNG and the H_RANDOM implementation by querying the KVM_CAP_PPC_HWRNG capability. The H_RANDOM hypercall implementation will only be invoked when the guest does an H_RANDOM hypercall if userspace first enables the in-kernel H_RANDOM implementation using the KVM_CAP_PPC_ENABLE_HCALL capability. Signed-off-by: Michael Ellerman <michael@ellerman.id.au> Signed-off-by: Paul Mackerras <paulus@samba.org> Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/include/asm/archrandom.h11
-rw-r--r--arch/powerpc/include/asm/kvm_ppc.h2
-rw-r--r--arch/powerpc/kvm/book3s_hv_builtin.c15
-rw-r--r--arch/powerpc/kvm/book3s_hv_rmhandlers.S115
-rw-r--r--arch/powerpc/kvm/powerpc.c3
-rw-r--r--arch/powerpc/platforms/powernv/rng.c29
6 files changed, 173 insertions, 2 deletions
diff --git a/arch/powerpc/include/asm/archrandom.h b/arch/powerpc/include/asm/archrandom.h
index bde531103638..0cc6eedc4780 100644
--- a/arch/powerpc/include/asm/archrandom.h
+++ b/arch/powerpc/include/asm/archrandom.h
@@ -30,8 +30,6 @@ static inline int arch_has_random(void)
30 return !!ppc_md.get_random_long; 30 return !!ppc_md.get_random_long;
31} 31}
32 32
33int powernv_get_random_long(unsigned long *v);
34
35static inline int arch_get_random_seed_long(unsigned long *v) 33static inline int arch_get_random_seed_long(unsigned long *v)
36{ 34{
37 return 0; 35 return 0;
@@ -47,4 +45,13 @@ static inline int arch_has_random_seed(void)
47 45
48#endif /* CONFIG_ARCH_RANDOM */ 46#endif /* CONFIG_ARCH_RANDOM */
49 47
48#ifdef CONFIG_PPC_POWERNV
49int powernv_hwrng_present(void);
50int powernv_get_random_long(unsigned long *v);
51int powernv_get_random_real_mode(unsigned long *v);
52#else
53static inline int powernv_hwrng_present(void) { return 0; }
54static inline int powernv_get_random_real_mode(unsigned long *v) { return 0; }
55#endif
56
50#endif /* _ASM_POWERPC_ARCHRANDOM_H */ 57#endif /* _ASM_POWERPC_ARCHRANDOM_H */
diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h
index 46bf652c9169..b8475daad884 100644
--- a/arch/powerpc/include/asm/kvm_ppc.h
+++ b/arch/powerpc/include/asm/kvm_ppc.h
@@ -302,6 +302,8 @@ static inline bool is_kvmppc_hv_enabled(struct kvm *kvm)
302 return kvm->arch.kvm_ops == kvmppc_hv_ops; 302 return kvm->arch.kvm_ops == kvmppc_hv_ops;
303} 303}
304 304
305extern int kvmppc_hwrng_present(void);
306
305/* 307/*
306 * Cuts out inst bits with ordering according to spec. 308 * Cuts out inst bits with ordering according to spec.
307 * That means the leftmost bit is zero. All given bits are included. 309 * That means the leftmost bit is zero. All given bits are included.
diff --git a/arch/powerpc/kvm/book3s_hv_builtin.c b/arch/powerpc/kvm/book3s_hv_builtin.c
index 1f083ff8a61a..1954a1c4b1f9 100644
--- a/arch/powerpc/kvm/book3s_hv_builtin.c
+++ b/arch/powerpc/kvm/book3s_hv_builtin.c
@@ -21,6 +21,7 @@
21#include <asm/cputable.h> 21#include <asm/cputable.h>
22#include <asm/kvm_ppc.h> 22#include <asm/kvm_ppc.h>
23#include <asm/kvm_book3s.h> 23#include <asm/kvm_book3s.h>
24#include <asm/archrandom.h>
24 25
25#define KVM_CMA_CHUNK_ORDER 18 26#define KVM_CMA_CHUNK_ORDER 18
26 27
@@ -169,3 +170,17 @@ int kvmppc_hcall_impl_hv_realmode(unsigned long cmd)
169 return 0; 170 return 0;
170} 171}
171EXPORT_SYMBOL_GPL(kvmppc_hcall_impl_hv_realmode); 172EXPORT_SYMBOL_GPL(kvmppc_hcall_impl_hv_realmode);
173
174int kvmppc_hwrng_present(void)
175{
176 return powernv_hwrng_present();
177}
178EXPORT_SYMBOL_GPL(kvmppc_hwrng_present);
179
180long kvmppc_h_random(struct kvm_vcpu *vcpu)
181{
182 if (powernv_get_random_real_mode(&vcpu->arch.gpr[4]))
183 return H_SUCCESS;
184
185 return H_HARDWARE;
186}
diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
index 6cbf1630cb70..0814ca122fcd 100644
--- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
+++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
@@ -1839,6 +1839,121 @@ hcall_real_table:
1839 .long 0 /* 0x12c */ 1839 .long 0 /* 0x12c */
1840 .long 0 /* 0x130 */ 1840 .long 0 /* 0x130 */
1841 .long DOTSYM(kvmppc_h_set_xdabr) - hcall_real_table 1841 .long DOTSYM(kvmppc_h_set_xdabr) - hcall_real_table
1842 .long 0 /* 0x138 */
1843 .long 0 /* 0x13c */
1844 .long 0 /* 0x140 */
1845 .long 0 /* 0x144 */
1846 .long 0 /* 0x148 */
1847 .long 0 /* 0x14c */
1848 .long 0 /* 0x150 */
1849 .long 0 /* 0x154 */
1850 .long 0 /* 0x158 */
1851 .long 0 /* 0x15c */
1852 .long 0 /* 0x160 */
1853 .long 0 /* 0x164 */
1854 .long 0 /* 0x168 */
1855 .long 0 /* 0x16c */
1856 .long 0 /* 0x170 */
1857 .long 0 /* 0x174 */
1858 .long 0 /* 0x178 */
1859 .long 0 /* 0x17c */
1860 .long 0 /* 0x180 */
1861 .long 0 /* 0x184 */
1862 .long 0 /* 0x188 */
1863 .long 0 /* 0x18c */
1864 .long 0 /* 0x190 */
1865 .long 0 /* 0x194 */
1866 .long 0 /* 0x198 */
1867 .long 0 /* 0x19c */
1868 .long 0 /* 0x1a0 */
1869 .long 0 /* 0x1a4 */
1870 .long 0 /* 0x1a8 */
1871 .long 0 /* 0x1ac */
1872 .long 0 /* 0x1b0 */
1873 .long 0 /* 0x1b4 */
1874 .long 0 /* 0x1b8 */
1875 .long 0 /* 0x1bc */
1876 .long 0 /* 0x1c0 */
1877 .long 0 /* 0x1c4 */
1878 .long 0 /* 0x1c8 */
1879 .long 0 /* 0x1cc */
1880 .long 0 /* 0x1d0 */
1881 .long 0 /* 0x1d4 */
1882 .long 0 /* 0x1d8 */
1883 .long 0 /* 0x1dc */
1884 .long 0 /* 0x1e0 */
1885 .long 0 /* 0x1e4 */
1886 .long 0 /* 0x1e8 */
1887 .long 0 /* 0x1ec */
1888 .long 0 /* 0x1f0 */
1889 .long 0 /* 0x1f4 */
1890 .long 0 /* 0x1f8 */
1891 .long 0 /* 0x1fc */
1892 .long 0 /* 0x200 */
1893 .long 0 /* 0x204 */
1894 .long 0 /* 0x208 */
1895 .long 0 /* 0x20c */
1896 .long 0 /* 0x210 */
1897 .long 0 /* 0x214 */
1898 .long 0 /* 0x218 */
1899 .long 0 /* 0x21c */
1900 .long 0 /* 0x220 */
1901 .long 0 /* 0x224 */
1902 .long 0 /* 0x228 */
1903 .long 0 /* 0x22c */
1904 .long 0 /* 0x230 */
1905 .long 0 /* 0x234 */
1906 .long 0 /* 0x238 */
1907 .long 0 /* 0x23c */
1908 .long 0 /* 0x240 */
1909 .long 0 /* 0x244 */
1910 .long 0 /* 0x248 */
1911 .long 0 /* 0x24c */
1912 .long 0 /* 0x250 */
1913 .long 0 /* 0x254 */
1914 .long 0 /* 0x258 */
1915 .long 0 /* 0x25c */
1916 .long 0 /* 0x260 */
1917 .long 0 /* 0x264 */
1918 .long 0 /* 0x268 */
1919 .long 0 /* 0x26c */
1920 .long 0 /* 0x270 */
1921 .long 0 /* 0x274 */
1922 .long 0 /* 0x278 */
1923 .long 0 /* 0x27c */
1924 .long 0 /* 0x280 */
1925 .long 0 /* 0x284 */
1926 .long 0 /* 0x288 */
1927 .long 0 /* 0x28c */
1928 .long 0 /* 0x290 */
1929 .long 0 /* 0x294 */
1930 .long 0 /* 0x298 */
1931 .long 0 /* 0x29c */
1932 .long 0 /* 0x2a0 */
1933 .long 0 /* 0x2a4 */
1934 .long 0 /* 0x2a8 */
1935 .long 0 /* 0x2ac */
1936 .long 0 /* 0x2b0 */
1937 .long 0 /* 0x2b4 */
1938 .long 0 /* 0x2b8 */
1939 .long 0 /* 0x2bc */
1940 .long 0 /* 0x2c0 */
1941 .long 0 /* 0x2c4 */
1942 .long 0 /* 0x2c8 */
1943 .long 0 /* 0x2cc */
1944 .long 0 /* 0x2d0 */
1945 .long 0 /* 0x2d4 */
1946 .long 0 /* 0x2d8 */
1947 .long 0 /* 0x2dc */
1948 .long 0 /* 0x2e0 */
1949 .long 0 /* 0x2e4 */
1950 .long 0 /* 0x2e8 */
1951 .long 0 /* 0x2ec */
1952 .long 0 /* 0x2f0 */
1953 .long 0 /* 0x2f4 */
1954 .long 0 /* 0x2f8 */
1955 .long 0 /* 0x2fc */
1956 .long DOTSYM(kvmppc_h_random) - hcall_real_table
1842 .globl hcall_real_table_end 1957 .globl hcall_real_table_end
1843hcall_real_table_end: 1958hcall_real_table_end:
1844 1959
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
index 24bfe401373e..55a4763d6d11 100644
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -529,6 +529,9 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
529 case KVM_CAP_PPC_RMA: 529 case KVM_CAP_PPC_RMA:
530 r = 0; 530 r = 0;
531 break; 531 break;
532 case KVM_CAP_PPC_HWRNG:
533 r = kvmppc_hwrng_present();
534 break;
532#endif 535#endif
533 case KVM_CAP_SYNC_MMU: 536 case KVM_CAP_SYNC_MMU:
534#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE 537#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
diff --git a/arch/powerpc/platforms/powernv/rng.c b/arch/powerpc/platforms/powernv/rng.c
index 80db43944afe..6eb808ff637e 100644
--- a/arch/powerpc/platforms/powernv/rng.c
+++ b/arch/powerpc/platforms/powernv/rng.c
@@ -24,12 +24,22 @@
24 24
25struct powernv_rng { 25struct powernv_rng {
26 void __iomem *regs; 26 void __iomem *regs;
27 void __iomem *regs_real;
27 unsigned long mask; 28 unsigned long mask;
28}; 29};
29 30
30static DEFINE_PER_CPU(struct powernv_rng *, powernv_rng); 31static DEFINE_PER_CPU(struct powernv_rng *, powernv_rng);
31 32
32 33
34int powernv_hwrng_present(void)
35{
36 struct powernv_rng *rng;
37
38 rng = get_cpu_var(powernv_rng);
39 put_cpu_var(rng);
40 return rng != NULL;
41}
42
33static unsigned long rng_whiten(struct powernv_rng *rng, unsigned long val) 43static unsigned long rng_whiten(struct powernv_rng *rng, unsigned long val)
34{ 44{
35 unsigned long parity; 45 unsigned long parity;
@@ -46,6 +56,17 @@ static unsigned long rng_whiten(struct powernv_rng *rng, unsigned long val)
46 return val; 56 return val;
47} 57}
48 58
59int powernv_get_random_real_mode(unsigned long *v)
60{
61 struct powernv_rng *rng;
62
63 rng = raw_cpu_read(powernv_rng);
64
65 *v = rng_whiten(rng, in_rm64(rng->regs_real));
66
67 return 1;
68}
69
49int powernv_get_random_long(unsigned long *v) 70int powernv_get_random_long(unsigned long *v)
50{ 71{
51 struct powernv_rng *rng; 72 struct powernv_rng *rng;
@@ -80,12 +101,20 @@ static __init void rng_init_per_cpu(struct powernv_rng *rng,
80static __init int rng_create(struct device_node *dn) 101static __init int rng_create(struct device_node *dn)
81{ 102{
82 struct powernv_rng *rng; 103 struct powernv_rng *rng;
104 struct resource res;
83 unsigned long val; 105 unsigned long val;
84 106
85 rng = kzalloc(sizeof(*rng), GFP_KERNEL); 107 rng = kzalloc(sizeof(*rng), GFP_KERNEL);
86 if (!rng) 108 if (!rng)
87 return -ENOMEM; 109 return -ENOMEM;
88 110
111 if (of_address_to_resource(dn, 0, &res)) {
112 kfree(rng);
113 return -ENXIO;
114 }
115
116 rng->regs_real = (void __iomem *)res.start;
117
89 rng->regs = of_iomap(dn, 0); 118 rng->regs = of_iomap(dn, 0);
90 if (!rng->regs) { 119 if (!rng->regs) {
91 kfree(rng); 120 kfree(rng);