162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci#include <linux/linkage.h> 362306a36Sopenharmony_ci#include <linux/errno.h> 462306a36Sopenharmony_ci#include <asm/asm.h> 562306a36Sopenharmony_ci#include <asm/msr.h> 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#ifdef CONFIG_X86_64 862306a36Sopenharmony_ci/* 962306a36Sopenharmony_ci * int {rdmsr,wrmsr}_safe_regs(u32 gprs[8]); 1062306a36Sopenharmony_ci * 1162306a36Sopenharmony_ci * reg layout: u32 gprs[eax, ecx, edx, ebx, esp, ebp, esi, edi] 1262306a36Sopenharmony_ci * 1362306a36Sopenharmony_ci */ 1462306a36Sopenharmony_ci.macro op_safe_regs op 1562306a36Sopenharmony_ciSYM_FUNC_START(\op\()_safe_regs) 1662306a36Sopenharmony_ci pushq %rbx 1762306a36Sopenharmony_ci pushq %r12 1862306a36Sopenharmony_ci movq %rdi, %r10 /* Save pointer */ 1962306a36Sopenharmony_ci xorl %r11d, %r11d /* Return value */ 2062306a36Sopenharmony_ci movl (%rdi), %eax 2162306a36Sopenharmony_ci movl 4(%rdi), %ecx 2262306a36Sopenharmony_ci movl 8(%rdi), %edx 2362306a36Sopenharmony_ci movl 12(%rdi), %ebx 2462306a36Sopenharmony_ci movl 20(%rdi), %r12d 2562306a36Sopenharmony_ci movl 24(%rdi), %esi 2662306a36Sopenharmony_ci movl 28(%rdi), %edi 2762306a36Sopenharmony_ci1: \op 2862306a36Sopenharmony_ci2: movl %eax, (%r10) 2962306a36Sopenharmony_ci movl %r11d, %eax /* Return value */ 3062306a36Sopenharmony_ci movl %ecx, 4(%r10) 3162306a36Sopenharmony_ci movl %edx, 8(%r10) 3262306a36Sopenharmony_ci movl %ebx, 12(%r10) 3362306a36Sopenharmony_ci movl %r12d, 20(%r10) 3462306a36Sopenharmony_ci movl %esi, 24(%r10) 3562306a36Sopenharmony_ci movl %edi, 28(%r10) 3662306a36Sopenharmony_ci popq %r12 3762306a36Sopenharmony_ci popq %rbx 3862306a36Sopenharmony_ci RET 3962306a36Sopenharmony_ci3: 4062306a36Sopenharmony_ci movl $-EIO, %r11d 4162306a36Sopenharmony_ci jmp 2b 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci _ASM_EXTABLE(1b, 3b) 4462306a36Sopenharmony_ciSYM_FUNC_END(\op\()_safe_regs) 4562306a36Sopenharmony_ci.endm 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci#else /* X86_32 */ 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci.macro op_safe_regs op 5062306a36Sopenharmony_ciSYM_FUNC_START(\op\()_safe_regs) 5162306a36Sopenharmony_ci pushl %ebx 5262306a36Sopenharmony_ci pushl %ebp 5362306a36Sopenharmony_ci pushl %esi 5462306a36Sopenharmony_ci pushl %edi 5562306a36Sopenharmony_ci pushl $0 /* Return value */ 5662306a36Sopenharmony_ci pushl %eax 5762306a36Sopenharmony_ci movl 4(%eax), %ecx 5862306a36Sopenharmony_ci movl 8(%eax), %edx 5962306a36Sopenharmony_ci movl 12(%eax), %ebx 6062306a36Sopenharmony_ci movl 20(%eax), %ebp 6162306a36Sopenharmony_ci movl 24(%eax), %esi 6262306a36Sopenharmony_ci movl 28(%eax), %edi 6362306a36Sopenharmony_ci movl (%eax), %eax 6462306a36Sopenharmony_ci1: \op 6562306a36Sopenharmony_ci2: pushl %eax 6662306a36Sopenharmony_ci movl 4(%esp), %eax 6762306a36Sopenharmony_ci popl (%eax) 6862306a36Sopenharmony_ci addl $4, %esp 6962306a36Sopenharmony_ci movl %ecx, 4(%eax) 7062306a36Sopenharmony_ci movl %edx, 8(%eax) 7162306a36Sopenharmony_ci movl %ebx, 12(%eax) 7262306a36Sopenharmony_ci movl %ebp, 20(%eax) 7362306a36Sopenharmony_ci movl %esi, 24(%eax) 7462306a36Sopenharmony_ci movl %edi, 28(%eax) 7562306a36Sopenharmony_ci popl %eax 7662306a36Sopenharmony_ci popl %edi 7762306a36Sopenharmony_ci popl %esi 7862306a36Sopenharmony_ci popl %ebp 7962306a36Sopenharmony_ci popl %ebx 8062306a36Sopenharmony_ci RET 8162306a36Sopenharmony_ci3: 8262306a36Sopenharmony_ci movl $-EIO, 4(%esp) 8362306a36Sopenharmony_ci jmp 2b 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci _ASM_EXTABLE(1b, 3b) 8662306a36Sopenharmony_ciSYM_FUNC_END(\op\()_safe_regs) 8762306a36Sopenharmony_ci.endm 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci#endif 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ciop_safe_regs rdmsr 9262306a36Sopenharmony_ciop_safe_regs wrmsr 9362306a36Sopenharmony_ci 94