/* SPDX-License-Identifier: GPL-2.0-only */1/* Copyright(c) 2016-2020 Intel Corporation. All rights reserved. */23#include <linux/linkage.h>4#include <asm/asm.h>56#ifndef CONFIG_UML78#ifdef CONFIG_X86_MCE910/*11* copy_mc_fragile - copy memory with indication if an exception / fault happened12*13* The 'fragile' version is opted into by platform quirks and takes14* pains to avoid unrecoverable corner cases like 'fast-string'15* instruction sequences, and consuming poison across a cacheline16* boundary. The non-fragile version is equivalent to memcpy()17* regardless of CPU machine-check-recovery capability.18*/19SYM_FUNC_START(copy_mc_fragile)20cmpl $8, %edx21/* Less than 8 bytes? Go to byte copy loop */22jb .L_no_whole_words2324/* Check for bad alignment of source */25testl $7, %esi26/* Already aligned */27jz .L_8byte_aligned2829/* Copy one byte at a time until source is 8-byte aligned */30movl %esi, %ecx31andl $7, %ecx32subl $8, %ecx33negl %ecx34subl %ecx, %edx35.L_read_leading_bytes:36movb (%rsi), %al37.L_write_leading_bytes:38movb %al, (%rdi)39incq %rsi40incq %rdi41decl %ecx42jnz .L_read_leading_bytes4344.L_8byte_aligned:45movl %edx, %ecx46andl $7, %edx47shrl $3, %ecx48jz .L_no_whole_words4950.L_read_words:51movq (%rsi), %r852.L_write_words:53movq %r8, (%rdi)54addq $8, %rsi55addq $8, %rdi56decl %ecx57jnz .L_read_words5859/* Any trailing bytes? */60.L_no_whole_words:61andl %edx, %edx62jz .L_done_memcpy_trap6364/* Copy trailing bytes */65movl %edx, %ecx66.L_read_trailing_bytes:67movb (%rsi), %al68.L_write_trailing_bytes:69movb %al, (%rdi)70incq %rsi71incq %rdi72decl %ecx73jnz .L_read_trailing_bytes7475/* Copy successful. Return zero */76.L_done_memcpy_trap:77xorl %eax, %eax78.L_done:79RET8081/*82* Return number of bytes not copied for any failure. Note that83* there is no "tail" handling since the source buffer is 8-byte84* aligned and poison is cacheline aligned.85*/86.E_read_words:87shll $3, %ecx88.E_leading_bytes:89addl %edx, %ecx90.E_trailing_bytes:91mov %ecx, %eax92jmp .L_done9394/*95* For write fault handling, given the destination is unaligned,96* we handle faults on multi-byte writes with a byte-by-byte97* copy up to the write-protected page.98*/99.E_write_words:100shll $3, %ecx101addl %edx, %ecx102movl %ecx, %edx103jmp copy_mc_fragile_handle_tail104105_ASM_EXTABLE_TYPE(.L_read_leading_bytes, .E_leading_bytes, EX_TYPE_DEFAULT_MCE_SAFE)106_ASM_EXTABLE_TYPE(.L_read_words, .E_read_words, EX_TYPE_DEFAULT_MCE_SAFE)107_ASM_EXTABLE_TYPE(.L_read_trailing_bytes, .E_trailing_bytes, EX_TYPE_DEFAULT_MCE_SAFE)108_ASM_EXTABLE(.L_write_leading_bytes, .E_leading_bytes)109_ASM_EXTABLE(.L_write_words, .E_write_words)110_ASM_EXTABLE(.L_write_trailing_bytes, .E_trailing_bytes)111112SYM_FUNC_END(copy_mc_fragile)113#endif /* CONFIG_X86_MCE */114115/*116* copy_mc_enhanced_fast_string - memory copy with exception handling117*118* Fast string copy + fault / exception handling. If the CPU does119* support machine check exception recovery, but does not support120* recovering from fast-string exceptions then this CPU needs to be121* added to the copy_mc_fragile_key set of quirks. Otherwise, absent any122* machine check recovery support this version should be no slower than123* standard memcpy.124*/125SYM_FUNC_START(copy_mc_enhanced_fast_string)126movq %rdi, %rax127movq %rdx, %rcx128.L_copy:129rep movsb130/* Copy successful. Return zero */131xorl %eax, %eax132RET133134.E_copy:135/*136* On fault %rcx is updated such that the copy instruction could137* optionally be restarted at the fault position, i.e. it138* contains 'bytes remaining'. A non-zero return indicates error139* to copy_mc_generic() users, or indicate short transfers to140* user-copy routines.141*/142movq %rcx, %rax143RET144145_ASM_EXTABLE_TYPE(.L_copy, .E_copy, EX_TYPE_DEFAULT_MCE_SAFE)146147SYM_FUNC_END(copy_mc_enhanced_fast_string)148#endif /* !CONFIG_UML */149150151