diff options
author | Borislav Petkov <petkovbb@googlemail.com> | 2009-08-31 03:50:09 -0400 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2009-08-31 18:14:26 -0400 |
commit | 132ec92f3f70fe365c1f4b8d46e66cf8a2a16880 (patch) | |
tree | f8e3f3ab5541f583030b0bcd5f3f81ca338f77a2 /arch/x86/lib | |
parent | 366d19e181be873c70f4aafca3931d77d781ccd7 (diff) |
x86, msr: Add rd/wrmsr interfaces with preset registers
native_{rdmsr,wrmsr}_safe_regs are two new interfaces which allow
presetting of a subset of eight x86 GPRs before executing the rd/wrmsr
instructions. This is needed at least on AMD K8 for accessing an erratum
workaround MSR.
Originally based on an idea by H. Peter Anvin.
Signed-off-by: Borislav Petkov <petkovbb@gmail.com>
LKML-Reference: <1251705011-18636-1-git-send-email-petkovbb@gmail.com>
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Diffstat (limited to 'arch/x86/lib')
-rw-r--r-- | arch/x86/lib/Makefile | 1 | ||||
-rw-r--r-- | arch/x86/lib/msr-reg.S | 98 |
2 files changed, 99 insertions, 0 deletions
diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile index 07c31899c9c2..b59c0647d809 100644 --- a/arch/x86/lib/Makefile +++ b/arch/x86/lib/Makefile | |||
@@ -8,6 +8,7 @@ lib-y := delay.o | |||
8 | lib-y += thunk_$(BITS).o | 8 | lib-y += thunk_$(BITS).o |
9 | lib-y += usercopy_$(BITS).o getuser.o putuser.o | 9 | lib-y += usercopy_$(BITS).o getuser.o putuser.o |
10 | lib-y += memcpy_$(BITS).o | 10 | lib-y += memcpy_$(BITS).o |
11 | lib-y += msr-reg.o | ||
11 | 12 | ||
12 | ifeq ($(CONFIG_X86_32),y) | 13 | ifeq ($(CONFIG_X86_32),y) |
13 | obj-y += atomic64_32.o | 14 | obj-y += atomic64_32.o |
diff --git a/arch/x86/lib/msr-reg.S b/arch/x86/lib/msr-reg.S new file mode 100644 index 000000000000..51f1bb3f8c79 --- /dev/null +++ b/arch/x86/lib/msr-reg.S | |||
@@ -0,0 +1,98 @@ | |||
1 | #include <linux/linkage.h> | ||
2 | #include <linux/errno.h> | ||
3 | #include <asm/asm.h> | ||
4 | #include <asm/msr.h> | ||
5 | |||
6 | #ifdef CONFIG_X86_64 | ||
7 | /* | ||
8 | * int native_{rdmsr,wrmsr}_safe_regs(u32 gprs[8]); | ||
9 | * | ||
10 | * reg layout: u32 gprs[eax, ecx, edx, ebx, esp, ebp, esi, edi] | ||
11 | * | ||
12 | */ | ||
13 | .macro op_safe_regs op:req | ||
14 | ENTRY(native_\op\()_safe_regs) | ||
15 | push %rbx | ||
16 | push %rbp | ||
17 | push $0 /* Return value */ | ||
18 | push %rdi | ||
19 | movl (%rdi), %eax | ||
20 | movl 4(%rdi), %ecx | ||
21 | movl 8(%rdi), %edx | ||
22 | movl 12(%rdi), %ebx | ||
23 | movl 20(%rdi), %ebp | ||
24 | movl 24(%rdi), %esi | ||
25 | movl 28(%rdi), %edi | ||
26 | 1: \op | ||
27 | 2: movl %edi, %r10d | ||
28 | pop %rdi | ||
29 | movl %eax, (%rdi) | ||
30 | movl %ecx, 4(%rdi) | ||
31 | movl %edx, 8(%rdi) | ||
32 | movl %ebx, 12(%rdi) | ||
33 | movl %ebp, 20(%rdi) | ||
34 | movl %esi, 24(%rdi) | ||
35 | movl %r10d, 28(%rdi) | ||
36 | pop %rax | ||
37 | pop %rbp | ||
38 | pop %rbx | ||
39 | ret | ||
40 | 3: | ||
41 | movq $-EIO, 8(%rsp) | ||
42 | jmp 2b | ||
43 | .section __ex_table,"ax" | ||
44 | .balign 4 | ||
45 | .quad 1b, 3b | ||
46 | .previous | ||
47 | ENDPROC(native_\op\()_safe_regs) | ||
48 | .endm | ||
49 | |||
50 | #else /* X86_32 */ | ||
51 | |||
52 | .macro op_safe_regs op:req | ||
53 | ENTRY(native_\op\()_safe_regs) | ||
54 | push %ebx | ||
55 | push %ebp | ||
56 | push %esi | ||
57 | push %edi | ||
58 | push $0 /* Return value */ | ||
59 | push %eax | ||
60 | movl 4(%eax), %ecx | ||
61 | movl 8(%eax), %edx | ||
62 | movl 12(%eax), %ebx | ||
63 | movl 20(%eax), %ebp | ||
64 | movl 24(%eax), %esi | ||
65 | movl 28(%eax), %edi | ||
66 | movl (%eax), %eax | ||
67 | 1: \op | ||
68 | 2: push %eax | ||
69 | movl 4(%esp), %eax | ||
70 | pop (%eax) | ||
71 | addl $4, %esp | ||
72 | movl %ecx, 4(%eax) | ||
73 | movl %edx, 8(%eax) | ||
74 | movl %ebx, 12(%eax) | ||
75 | movl %ebp, 20(%eax) | ||
76 | movl %esi, 24(%eax) | ||
77 | movl %edi, 28(%eax) | ||
78 | pop %eax | ||
79 | pop %edi | ||
80 | pop %esi | ||
81 | pop %ebp | ||
82 | pop %ebx | ||
83 | ret | ||
84 | 3: | ||
85 | movl $-EIO, 4(%esp) | ||
86 | jmp 2b | ||
87 | .section __ex_table,"ax" | ||
88 | .balign 4 | ||
89 | .long 1b, 3b | ||
90 | .previous | ||
91 | ENDPROC(native_\op\()_safe_regs) | ||
92 | .endm | ||
93 | |||
94 | #endif | ||
95 | |||
96 | op_safe_regs rdmsr | ||
97 | op_safe_regs wrmsr | ||
98 | |||