1// Copyright 2016 The Fuchsia Authors 2// 3// Use of this source code is governed by a MIT-style 4// license that can be found in the LICENSE file or at 5// https://opensource.org/licenses/MIT 6 7#include <asm.h> 8#include <err.h> 9 10lr .req x30 11dst .req x0 12src .req x1 13len .req x2 14fault_return_ptr .req x3 15temp .req x15 16 17// NOTE! We know here that the memcpy code doesn't touch these registers, 18// so we can use them to save values. But they are call-clobbered in the 19// C ABI, so we don't need a stack frame. 20saved_fault_return_ptr .req x16 21saved_lr .req x17 22 23// zx_status_t _arm64_user_copy(void *dst, const void *src, size_t len, void **fault_return) 24.section .text._arm64_user_copy,"ax" 25.balign 64 // Align to cache line. This code fits in one cache line. 26FUNCTION(_arm64_user_copy) 27 28 adr temp, .Lfault_from_user 29 30 mov saved_fault_return_ptr, fault_return_ptr 31 .cfi_register fault_return_ptr, saved_fault_return_ptr 32 mov saved_lr, lr 33 .cfi_register lr, saved_lr 34 35 // Just call our normal memcpy. The caller has ensured that the 36 // address range is in the user portion of the address space. 37 // While fault_return_ptr is set, userspace data faults will be 38 // redirected to .Lfault_from_user, below. 39 // 40 // NOTE! We make important assumptions here about what the memcpy 41 // code does: it never moves the stack pointer, and it never touches 42 // the registers we're using for saved_fault_return_ptr and saved_lr. 43 str temp, [fault_return_ptr] 44 bl memcpy 45 mov x0, #ZX_OK 46 47.Luser_copy_return: 48 str xzr, [saved_fault_return_ptr] 49 mov lr, saved_lr 50 .cfi_same_value lr 51 ret 52END_FUNCTION(_arm64_user_copy) 53 54.section .text.cold._arm64_user_copy,"ax" 55.Lfault_from_user: 56 .cfi_startproc 57 .cfi_register fault_return_ptr, saved_fault_return_ptr 58 .cfi_register lr, saved_lr 59 mov x0, #ZX_ERR_INVALID_ARGS 60 b .Luser_copy_return 61 .cfi_endproc 62