Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Michael Ellerman and committed by
Alexander Graf
e928e9cb 99342cf8

+191 -2
+17
Documentation/virtual/kvm/api.txt
··· 3573 3573 @ar - access register number 3574 3574 3575 3575 KVM handlers should exit to userspace with rc = -EREMOTE. 3576 + 3577 + 3578 + 8. Other capabilities. 3579 + ---------------------- 3580 + 3581 + This section lists capabilities that give information about other 3582 + features of the KVM implementation. 3583 + 3584 + 8.1 KVM_CAP_PPC_HWRNG 3585 + 3586 + Architectures: ppc 3587 + 3588 + This capability, if KVM_CHECK_EXTENSION indicates that it is 3589 + available, means that that the kernel has an implementation of the 3590 + H_RANDOM hypercall backed by a hardware random-number generator. 3591 + If present, the kernel H_RANDOM handler can be enabled for guest use 3592 + with the KVM_CAP_PPC_ENABLE_HCALL capability.
+9 -2
arch/powerpc/include/asm/archrandom.h
··· 30 30 return !!ppc_md.get_random_long; 31 31 } 32 32 33 - int powernv_get_random_long(unsigned long *v); 34 - 35 33 static inline int arch_get_random_seed_long(unsigned long *v) 36 34 { 37 35 return 0; ··· 44 46 } 45 47 46 48 #endif /* CONFIG_ARCH_RANDOM */ 49 + 50 + #ifdef CONFIG_PPC_POWERNV 51 + int powernv_hwrng_present(void); 52 + int powernv_get_random_long(unsigned long *v); 53 + int powernv_get_random_real_mode(unsigned long *v); 54 + #else 55 + static inline int powernv_hwrng_present(void) { return 0; } 56 + static inline int powernv_get_random_real_mode(unsigned long *v) { return 0; } 57 + #endif 47 58 48 59 #endif /* _ASM_POWERPC_ARCHRANDOM_H */
+2
arch/powerpc/include/asm/kvm_ppc.h
··· 302 302 return kvm->arch.kvm_ops == kvmppc_hv_ops; 303 303 } 304 304 305 + extern int kvmppc_hwrng_present(void); 306 + 305 307 /* 306 308 * Cuts out inst bits with ordering according to spec. 307 309 * That means the leftmost bit is zero. All given bits are included.
+15
arch/powerpc/kvm/book3s_hv_builtin.c
··· 21 21 #include <asm/cputable.h> 22 22 #include <asm/kvm_ppc.h> 23 23 #include <asm/kvm_book3s.h> 24 + #include <asm/archrandom.h> 24 25 25 26 #define KVM_CMA_CHUNK_ORDER 18 26 27 ··· 170 169 return 0; 171 170 } 172 171 EXPORT_SYMBOL_GPL(kvmppc_hcall_impl_hv_realmode); 172 + 173 + int kvmppc_hwrng_present(void) 174 + { 175 + return powernv_hwrng_present(); 176 + } 177 + EXPORT_SYMBOL_GPL(kvmppc_hwrng_present); 178 + 179 + long kvmppc_h_random(struct kvm_vcpu *vcpu) 180 + { 181 + if (powernv_get_random_real_mode(&vcpu->arch.gpr[4])) 182 + return H_SUCCESS; 183 + 184 + return H_HARDWARE; 185 + }
+115
arch/powerpc/kvm/book3s_hv_rmhandlers.S
··· 1839 1839 .long 0 /* 0x12c */ 1840 1840 .long 0 /* 0x130 */ 1841 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 1957 .globl hcall_real_table_end 1843 1958 hcall_real_table_end: 1844 1959
+3
arch/powerpc/kvm/powerpc.c
··· 529 529 case KVM_CAP_PPC_RMA: 530 530 r = 0; 531 531 break; 532 + case KVM_CAP_PPC_HWRNG: 533 + r = kvmppc_hwrng_present(); 534 + break; 532 535 #endif 533 536 case KVM_CAP_SYNC_MMU: 534 537 #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
+29
arch/powerpc/platforms/powernv/rng.c
··· 24 24 25 25 struct powernv_rng { 26 26 void __iomem *regs; 27 + void __iomem *regs_real; 27 28 unsigned long mask; 28 29 }; 29 30 30 31 static DEFINE_PER_CPU(struct powernv_rng *, powernv_rng); 31 32 33 + 34 + int 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 + } 32 42 33 43 static unsigned long rng_whiten(struct powernv_rng *rng, unsigned long val) 34 44 { ··· 54 44 rng->mask = (rng->mask << 1) | (parity & 1); 55 45 56 46 return val; 47 + } 48 + 49 + int powernv_get_random_real_mode(unsigned long *v) 50 + { 51 + struct powernv_rng *rng; 52 + 53 + rng = raw_cpu_read(powernv_rng); 54 + 55 + *v = rng_whiten(rng, in_rm64(rng->regs_real)); 56 + 57 + return 1; 57 58 } 58 59 59 60 int powernv_get_random_long(unsigned long *v) ··· 101 80 static __init int rng_create(struct device_node *dn) 102 81 { 103 82 struct powernv_rng *rng; 83 + struct resource res; 104 84 unsigned long val; 105 85 106 86 rng = kzalloc(sizeof(*rng), GFP_KERNEL); 107 87 if (!rng) 108 88 return -ENOMEM; 89 + 90 + if (of_address_to_resource(dn, 0, &res)) { 91 + kfree(rng); 92 + return -ENXIO; 93 + } 94 + 95 + rng->regs_real = (void __iomem *)res.start; 109 96 110 97 rng->regs = of_iomap(dn, 0); 111 98 if (!rng->regs) {
+1
include/uapi/linux/kvm.h
··· 813 813 #define KVM_CAP_MIPS_MSA 112 814 814 #define KVM_CAP_S390_INJECT_IRQ 113 815 815 #define KVM_CAP_S390_IRQ_STATE 114 816 + #define KVM_CAP_PPC_HWRNG 115 816 817 817 818 #ifdef KVM_CAP_IRQ_ROUTING 818 819