| Borislav Petkov | 132ec92 | 2009-08-31 09:50:09 +0200 | [diff] [blame] | 1 | #include <linux/linkage.h> | 
 | 2 | #include <linux/errno.h> | 
| H. Peter Anvin | 79c5dca | 2009-08-31 13:59:53 -0700 | [diff] [blame] | 3 | #include <asm/dwarf2.h> | 
| Borislav Petkov | 132ec92 | 2009-08-31 09:50:09 +0200 | [diff] [blame] | 4 | #include <asm/asm.h> | 
 | 5 | #include <asm/msr.h> | 
 | 6 |  | 
 | 7 | #ifdef CONFIG_X86_64 | 
 | 8 | /* | 
 | 9 |  * int native_{rdmsr,wrmsr}_safe_regs(u32 gprs[8]); | 
 | 10 |  * | 
 | 11 |  * reg layout: u32 gprs[eax, ecx, edx, ebx, esp, ebp, esi, edi] | 
 | 12 |  * | 
 | 13 |  */ | 
| H. Peter Anvin | f6909f3 | 2009-09-01 13:31:52 -0700 | [diff] [blame] | 14 | .macro op_safe_regs op | 
| Borislav Petkov | 132ec92 | 2009-08-31 09:50:09 +0200 | [diff] [blame] | 15 | ENTRY(native_\op\()_safe_regs) | 
| H. Peter Anvin | 79c5dca | 2009-08-31 13:59:53 -0700 | [diff] [blame] | 16 | 	CFI_STARTPROC | 
 | 17 | 	pushq_cfi %rbx | 
 | 18 | 	pushq_cfi %rbp | 
 | 19 | 	movq	%rdi, %r10	/* Save pointer */ | 
 | 20 | 	xorl	%r11d, %r11d	/* Return value */ | 
| Borislav Petkov | 132ec92 | 2009-08-31 09:50:09 +0200 | [diff] [blame] | 21 | 	movl    (%rdi), %eax | 
 | 22 | 	movl    4(%rdi), %ecx | 
 | 23 | 	movl    8(%rdi), %edx | 
 | 24 | 	movl    12(%rdi), %ebx | 
 | 25 | 	movl    20(%rdi), %ebp | 
 | 26 | 	movl    24(%rdi), %esi | 
 | 27 | 	movl    28(%rdi), %edi | 
| H. Peter Anvin | 79c5dca | 2009-08-31 13:59:53 -0700 | [diff] [blame] | 28 | 	CFI_REMEMBER_STATE | 
| Borislav Petkov | 132ec92 | 2009-08-31 09:50:09 +0200 | [diff] [blame] | 29 | 1:	\op | 
| H. Peter Anvin | 79c5dca | 2009-08-31 13:59:53 -0700 | [diff] [blame] | 30 | 2:	movl    %eax, (%r10) | 
 | 31 | 	movl	%r11d, %eax	/* Return value */ | 
 | 32 | 	movl    %ecx, 4(%r10) | 
 | 33 | 	movl    %edx, 8(%r10) | 
 | 34 | 	movl    %ebx, 12(%r10) | 
 | 35 | 	movl    %ebp, 20(%r10) | 
 | 36 | 	movl    %esi, 24(%r10) | 
 | 37 | 	movl    %edi, 28(%r10) | 
 | 38 | 	popq_cfi %rbp | 
 | 39 | 	popq_cfi %rbx | 
| Borislav Petkov | 132ec92 | 2009-08-31 09:50:09 +0200 | [diff] [blame] | 40 | 	ret | 
 | 41 | 3: | 
| H. Peter Anvin | 79c5dca | 2009-08-31 13:59:53 -0700 | [diff] [blame] | 42 | 	CFI_RESTORE_STATE | 
 | 43 | 	movl    $-EIO, %r11d | 
| Borislav Petkov | 132ec92 | 2009-08-31 09:50:09 +0200 | [diff] [blame] | 44 | 	jmp     2b | 
| H. Peter Anvin | 79c5dca | 2009-08-31 13:59:53 -0700 | [diff] [blame] | 45 |  | 
 | 46 | 	_ASM_EXTABLE(1b, 3b) | 
 | 47 | 	CFI_ENDPROC | 
| Borislav Petkov | 132ec92 | 2009-08-31 09:50:09 +0200 | [diff] [blame] | 48 | ENDPROC(native_\op\()_safe_regs) | 
 | 49 | .endm | 
 | 50 |  | 
 | 51 | #else /* X86_32 */ | 
 | 52 |  | 
| Ingo Molnar | 8adf65c | 2009-09-03 21:26:34 +0200 | [diff] [blame] | 53 | .macro op_safe_regs op | 
| Borislav Petkov | 132ec92 | 2009-08-31 09:50:09 +0200 | [diff] [blame] | 54 | ENTRY(native_\op\()_safe_regs) | 
| H. Peter Anvin | 79c5dca | 2009-08-31 13:59:53 -0700 | [diff] [blame] | 55 | 	CFI_STARTPROC | 
 | 56 | 	pushl_cfi %ebx | 
 | 57 | 	pushl_cfi %ebp | 
 | 58 | 	pushl_cfi %esi | 
 | 59 | 	pushl_cfi %edi | 
 | 60 | 	pushl_cfi $0              /* Return value */ | 
 | 61 | 	pushl_cfi %eax | 
| Borislav Petkov | 132ec92 | 2009-08-31 09:50:09 +0200 | [diff] [blame] | 62 | 	movl    4(%eax), %ecx | 
 | 63 | 	movl    8(%eax), %edx | 
 | 64 | 	movl    12(%eax), %ebx | 
 | 65 | 	movl    20(%eax), %ebp | 
 | 66 | 	movl    24(%eax), %esi | 
 | 67 | 	movl    28(%eax), %edi | 
 | 68 | 	movl    (%eax), %eax | 
| H. Peter Anvin | 79c5dca | 2009-08-31 13:59:53 -0700 | [diff] [blame] | 69 | 	CFI_REMEMBER_STATE | 
| Borislav Petkov | 132ec92 | 2009-08-31 09:50:09 +0200 | [diff] [blame] | 70 | 1:	\op | 
| H. Peter Anvin | 79c5dca | 2009-08-31 13:59:53 -0700 | [diff] [blame] | 71 | 2:	pushl_cfi %eax | 
| Borislav Petkov | 132ec92 | 2009-08-31 09:50:09 +0200 | [diff] [blame] | 72 | 	movl    4(%esp), %eax | 
| H. Peter Anvin | 79c5dca | 2009-08-31 13:59:53 -0700 | [diff] [blame] | 73 | 	popl_cfi (%eax) | 
| Borislav Petkov | 132ec92 | 2009-08-31 09:50:09 +0200 | [diff] [blame] | 74 | 	addl    $4, %esp | 
| H. Peter Anvin | 79c5dca | 2009-08-31 13:59:53 -0700 | [diff] [blame] | 75 | 	CFI_ADJUST_CFA_OFFSET -4 | 
| Borislav Petkov | 132ec92 | 2009-08-31 09:50:09 +0200 | [diff] [blame] | 76 | 	movl    %ecx, 4(%eax) | 
 | 77 | 	movl    %edx, 8(%eax) | 
 | 78 | 	movl    %ebx, 12(%eax) | 
 | 79 | 	movl    %ebp, 20(%eax) | 
 | 80 | 	movl    %esi, 24(%eax) | 
 | 81 | 	movl    %edi, 28(%eax) | 
| H. Peter Anvin | 79c5dca | 2009-08-31 13:59:53 -0700 | [diff] [blame] | 82 | 	popl_cfi %eax | 
 | 83 | 	popl_cfi %edi | 
 | 84 | 	popl_cfi %esi | 
 | 85 | 	popl_cfi %ebp | 
 | 86 | 	popl_cfi %ebx | 
| Borislav Petkov | 132ec92 | 2009-08-31 09:50:09 +0200 | [diff] [blame] | 87 | 	ret | 
 | 88 | 3: | 
| H. Peter Anvin | 79c5dca | 2009-08-31 13:59:53 -0700 | [diff] [blame] | 89 | 	CFI_RESTORE_STATE | 
| Borislav Petkov | 132ec92 | 2009-08-31 09:50:09 +0200 | [diff] [blame] | 90 | 	movl    $-EIO, 4(%esp) | 
 | 91 | 	jmp     2b | 
| H. Peter Anvin | 79c5dca | 2009-08-31 13:59:53 -0700 | [diff] [blame] | 92 |  | 
 | 93 | 	_ASM_EXTABLE(1b, 3b) | 
 | 94 | 	CFI_ENDPROC | 
| Borislav Petkov | 132ec92 | 2009-08-31 09:50:09 +0200 | [diff] [blame] | 95 | ENDPROC(native_\op\()_safe_regs) | 
 | 96 | .endm | 
 | 97 |  | 
 | 98 | #endif | 
 | 99 |  | 
 | 100 | op_safe_regs rdmsr | 
 | 101 | op_safe_regs wrmsr | 
 | 102 |  |