diff options
Diffstat (limited to 'sys/arch/i386/stand')
-rw-r--r-- | sys/arch/i386/stand/libsa/random_i386.S | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/sys/arch/i386/stand/libsa/random_i386.S b/sys/arch/i386/stand/libsa/random_i386.S new file mode 100644 index 00000000000..2c7bbd04a2b --- /dev/null +++ b/sys/arch/i386/stand/libsa/random_i386.S @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2013 Joel Sing <jsing@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <machine/param.h> +#include <machine/asm.h> +#include <machine/psl.h> + +ENTRY(md_random) + // See if we have CPU identification. + pushfl + popl %eax + movl %eax, %ecx + orl $PSL_ID, %eax + pushl %eax + popfl + pushfl + popl %eax + pushl %ecx + popfl + andl $PSL_ID, %eax + jz done + + // CPUID leaf = 0, subleaf = 0 + movl $0, %eax + movl $0, %ecx + cpuid + cmpl $0x756e6547, %ebx // "Genu" + jne done + cmpl $0x6c65746e, %ecx // "ineI" + jne done + cmpl $0x49656e69, %edx // "ntel" + jne done + + // CPUID leaf = 1, subleaf = 0 + movl $1, %eax + movl $0, %ecx + cpuid + + movl 4(%esp), %ebx + movl 8(%esp), %edx + shrl $2, %edx + shll $2, %edx + xorl %edi, %edi + + andl $0x40000000, %ecx // See if we have rdrand. + jnz userand + + movl %edx, %ecx + jmp usetsc + +userand: + rdrand %eax + xorl %eax, 0(%edi,%ebx) + addl $4, %edi + cmpl %edi, %edx + jne userand + ret + +usetsc: + rdtsc // Populates edx:eax. + mull %edx + xorl %eax, 0(%edi,%ebx) + addl $4, %edi + cmpl %edi, %ecx + jne usetsc + ret + +done: + ret |