0001
0002 #include <linux/linkage.h>
0003 #include <linux/errno.h>
0004 #include <asm/asm.h>
0005 #include <asm/msr.h>
0006
0007 #ifdef CONFIG_X86_64
0008
0009
0010
0011
0012
0013
0014 .macro op_safe_regs op
0015 SYM_FUNC_START(\op\()_safe_regs)
0016 pushq %rbx
0017 pushq %r12
0018 movq %rdi, %r10
0019 xorl %r11d, %r11d
0020 movl (%rdi), %eax
0021 movl 4(%rdi), %ecx
0022 movl 8(%rdi), %edx
0023 movl 12(%rdi), %ebx
0024 movl 20(%rdi), %r12d
0025 movl 24(%rdi), %esi
0026 movl 28(%rdi), %edi
0027 1: \op
0028 2: movl %eax, (%r10)
0029 movl %r11d, %eax
0030 movl %ecx, 4(%r10)
0031 movl %edx, 8(%r10)
0032 movl %ebx, 12(%r10)
0033 movl %r12d, 20(%r10)
0034 movl %esi, 24(%r10)
0035 movl %edi, 28(%r10)
0036 popq %r12
0037 popq %rbx
0038 RET
0039 3:
0040 movl $-EIO, %r11d
0041 jmp 2b
0042
0043 _ASM_EXTABLE(1b, 3b)
0044 SYM_FUNC_END(\op\()_safe_regs)
0045 .endm
0046
0047 #else
0048
0049 .macro op_safe_regs op
0050 SYM_FUNC_START(\op\()_safe_regs)
0051 pushl %ebx
0052 pushl %ebp
0053 pushl %esi
0054 pushl %edi
0055 pushl $0
0056 pushl %eax
0057 movl 4(%eax), %ecx
0058 movl 8(%eax), %edx
0059 movl 12(%eax), %ebx
0060 movl 20(%eax), %ebp
0061 movl 24(%eax), %esi
0062 movl 28(%eax), %edi
0063 movl (%eax), %eax
0064 1: \op
0065 2: pushl %eax
0066 movl 4(%esp), %eax
0067 popl (%eax)
0068 addl $4, %esp
0069 movl %ecx, 4(%eax)
0070 movl %edx, 8(%eax)
0071 movl %ebx, 12(%eax)
0072 movl %ebp, 20(%eax)
0073 movl %esi, 24(%eax)
0074 movl %edi, 28(%eax)
0075 popl %eax
0076 popl %edi
0077 popl %esi
0078 popl %ebp
0079 popl %ebx
0080 RET
0081 3:
0082 movl $-EIO, 4(%esp)
0083 jmp 2b
0084
0085 _ASM_EXTABLE(1b, 3b)
0086 SYM_FUNC_END(\op\()_safe_regs)
0087 .endm
0088
0089 #endif
0090
0091 op_safe_regs rdmsr
0092 op_safe_regs wrmsr
0093