18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci#include <linux/linkage.h>
38c2ecf20Sopenharmony_ci#include <linux/errno.h>
48c2ecf20Sopenharmony_ci#include <asm/asm.h>
58c2ecf20Sopenharmony_ci#include <asm/msr.h>
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci#ifdef CONFIG_X86_64
88c2ecf20Sopenharmony_ci/*
98c2ecf20Sopenharmony_ci * int {rdmsr,wrmsr}_safe_regs(u32 gprs[8]);
108c2ecf20Sopenharmony_ci *
118c2ecf20Sopenharmony_ci * reg layout: u32 gprs[eax, ecx, edx, ebx, esp, ebp, esi, edi]
128c2ecf20Sopenharmony_ci *
138c2ecf20Sopenharmony_ci */
148c2ecf20Sopenharmony_ci.macro op_safe_regs op
158c2ecf20Sopenharmony_ciSYM_FUNC_START(\op\()_safe_regs)
168c2ecf20Sopenharmony_ci	pushq %rbx
178c2ecf20Sopenharmony_ci	pushq %r12
188c2ecf20Sopenharmony_ci	movq	%rdi, %r10	/* Save pointer */
198c2ecf20Sopenharmony_ci	xorl	%r11d, %r11d	/* Return value */
208c2ecf20Sopenharmony_ci	movl    (%rdi), %eax
218c2ecf20Sopenharmony_ci	movl    4(%rdi), %ecx
228c2ecf20Sopenharmony_ci	movl    8(%rdi), %edx
238c2ecf20Sopenharmony_ci	movl    12(%rdi), %ebx
248c2ecf20Sopenharmony_ci	movl    20(%rdi), %r12d
258c2ecf20Sopenharmony_ci	movl    24(%rdi), %esi
268c2ecf20Sopenharmony_ci	movl    28(%rdi), %edi
278c2ecf20Sopenharmony_ci1:	\op
288c2ecf20Sopenharmony_ci2:	movl    %eax, (%r10)
298c2ecf20Sopenharmony_ci	movl	%r11d, %eax	/* Return value */
308c2ecf20Sopenharmony_ci	movl    %ecx, 4(%r10)
318c2ecf20Sopenharmony_ci	movl    %edx, 8(%r10)
328c2ecf20Sopenharmony_ci	movl    %ebx, 12(%r10)
338c2ecf20Sopenharmony_ci	movl    %r12d, 20(%r10)
348c2ecf20Sopenharmony_ci	movl    %esi, 24(%r10)
358c2ecf20Sopenharmony_ci	movl    %edi, 28(%r10)
368c2ecf20Sopenharmony_ci	popq %r12
378c2ecf20Sopenharmony_ci	popq %rbx
388c2ecf20Sopenharmony_ci	RET
398c2ecf20Sopenharmony_ci3:
408c2ecf20Sopenharmony_ci	movl    $-EIO, %r11d
418c2ecf20Sopenharmony_ci	jmp     2b
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci	_ASM_EXTABLE(1b, 3b)
448c2ecf20Sopenharmony_ciSYM_FUNC_END(\op\()_safe_regs)
458c2ecf20Sopenharmony_ci.endm
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ci#else /* X86_32 */
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci.macro op_safe_regs op
508c2ecf20Sopenharmony_ciSYM_FUNC_START(\op\()_safe_regs)
518c2ecf20Sopenharmony_ci	pushl %ebx
528c2ecf20Sopenharmony_ci	pushl %ebp
538c2ecf20Sopenharmony_ci	pushl %esi
548c2ecf20Sopenharmony_ci	pushl %edi
558c2ecf20Sopenharmony_ci	pushl $0              /* Return value */
568c2ecf20Sopenharmony_ci	pushl %eax
578c2ecf20Sopenharmony_ci	movl    4(%eax), %ecx
588c2ecf20Sopenharmony_ci	movl    8(%eax), %edx
598c2ecf20Sopenharmony_ci	movl    12(%eax), %ebx
608c2ecf20Sopenharmony_ci	movl    20(%eax), %ebp
618c2ecf20Sopenharmony_ci	movl    24(%eax), %esi
628c2ecf20Sopenharmony_ci	movl    28(%eax), %edi
638c2ecf20Sopenharmony_ci	movl    (%eax), %eax
648c2ecf20Sopenharmony_ci1:	\op
658c2ecf20Sopenharmony_ci2:	pushl %eax
668c2ecf20Sopenharmony_ci	movl    4(%esp), %eax
678c2ecf20Sopenharmony_ci	popl (%eax)
688c2ecf20Sopenharmony_ci	addl    $4, %esp
698c2ecf20Sopenharmony_ci	movl    %ecx, 4(%eax)
708c2ecf20Sopenharmony_ci	movl    %edx, 8(%eax)
718c2ecf20Sopenharmony_ci	movl    %ebx, 12(%eax)
728c2ecf20Sopenharmony_ci	movl    %ebp, 20(%eax)
738c2ecf20Sopenharmony_ci	movl    %esi, 24(%eax)
748c2ecf20Sopenharmony_ci	movl    %edi, 28(%eax)
758c2ecf20Sopenharmony_ci	popl %eax
768c2ecf20Sopenharmony_ci	popl %edi
778c2ecf20Sopenharmony_ci	popl %esi
788c2ecf20Sopenharmony_ci	popl %ebp
798c2ecf20Sopenharmony_ci	popl %ebx
808c2ecf20Sopenharmony_ci	RET
818c2ecf20Sopenharmony_ci3:
828c2ecf20Sopenharmony_ci	movl    $-EIO, 4(%esp)
838c2ecf20Sopenharmony_ci	jmp     2b
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_ci	_ASM_EXTABLE(1b, 3b)
868c2ecf20Sopenharmony_ciSYM_FUNC_END(\op\()_safe_regs)
878c2ecf20Sopenharmony_ci.endm
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_ci#endif
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ciop_safe_regs rdmsr
928c2ecf20Sopenharmony_ciop_safe_regs wrmsr
938c2ecf20Sopenharmony_ci
94