#include <linux/linkage.h> | |
#include <linux/errno.h> | |
#include <asm/dwarf2.h> | |
#include <asm/asm.h> | |
#include <asm/msr.h> | |
#ifdef CONFIG_X86_64 | |
/* | |
* int native_{rdmsr,wrmsr}_safe_regs(u32 gprs[8]); | |
* | |
* reg layout: u32 gprs[eax, ecx, edx, ebx, esp, ebp, esi, edi] | |
* | |
*/ | |
.macro op_safe_regs op | |
ENTRY(native_\op\()_safe_regs) | |
CFI_STARTPROC | |
pushq_cfi %rbx | |
pushq_cfi %rbp | |
movq %rdi, %r10 /* Save pointer */ | |
xorl %r11d, %r11d /* Return value */ | |
movl (%rdi), %eax | |
movl 4(%rdi), %ecx | |
movl 8(%rdi), %edx | |
movl 12(%rdi), %ebx | |
movl 20(%rdi), %ebp | |
movl 24(%rdi), %esi | |
movl 28(%rdi), %edi | |
CFI_REMEMBER_STATE | |
1: \op | |
2: movl %eax, (%r10) | |
movl %r11d, %eax /* Return value */ | |
movl %ecx, 4(%r10) | |
movl %edx, 8(%r10) | |
movl %ebx, 12(%r10) | |
movl %ebp, 20(%r10) | |
movl %esi, 24(%r10) | |
movl %edi, 28(%r10) | |
popq_cfi %rbp | |
popq_cfi %rbx | |
ret | |
3: | |
CFI_RESTORE_STATE | |
movl $-EIO, %r11d | |
jmp 2b | |
_ASM_EXTABLE(1b, 3b) | |
CFI_ENDPROC | |
ENDPROC(native_\op\()_safe_regs) | |
.endm | |
#else /* X86_32 */ | |
.macro op_safe_regs op | |
ENTRY(native_\op\()_safe_regs) | |
CFI_STARTPROC | |
pushl_cfi %ebx | |
pushl_cfi %ebp | |
pushl_cfi %esi | |
pushl_cfi %edi | |
pushl_cfi $0 /* Return value */ | |
pushl_cfi %eax | |
movl 4(%eax), %ecx | |
movl 8(%eax), %edx | |
movl 12(%eax), %ebx | |
movl 20(%eax), %ebp | |
movl 24(%eax), %esi | |
movl 28(%eax), %edi | |
movl (%eax), %eax | |
CFI_REMEMBER_STATE | |
1: \op | |
2: pushl_cfi %eax | |
movl 4(%esp), %eax | |
popl_cfi (%eax) | |
addl $4, %esp | |
CFI_ADJUST_CFA_OFFSET -4 | |
movl %ecx, 4(%eax) | |
movl %edx, 8(%eax) | |
movl %ebx, 12(%eax) | |
movl %ebp, 20(%eax) | |
movl %esi, 24(%eax) | |
movl %edi, 28(%eax) | |
popl_cfi %eax | |
popl_cfi %edi | |
popl_cfi %esi | |
popl_cfi %ebp | |
popl_cfi %ebx | |
ret | |
3: | |
CFI_RESTORE_STATE | |
movl $-EIO, 4(%esp) | |
jmp 2b | |
_ASM_EXTABLE(1b, 3b) | |
CFI_ENDPROC | |
ENDPROC(native_\op\()_safe_regs) | |
.endm | |
#endif | |
op_safe_regs rdmsr | |
op_safe_regs wrmsr | |