1/*
2 * Copyright (c) 2023, Google Inc. All rights reserved
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files
6 * (the "Software"), to deal in the Software without restriction,
7 * including without limitation the rights to use, copy, modify, merge,
8 * publish, distribute, sublicense, and/or sell copies of the Software,
9 * and to permit persons to whom the Software is furnished to do so,
10 * subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 */
23
24#include <asm.h>
25#include <arch/asm_macros.h>
26#include <err.h>
27
28#define X86_CR4_SMAP            0x00200000 /* SMAP protection enabling */
29
30.macro copy_from_anywhere_loop with_smap, fault_label
31.Lcopy_from_anywhere_loop\@:
32.if \with_smap
33	stac
34.endif
35	set_fault_handler	\fault_label
36	movb	(%rsi), %cl
37.if \with_smap
38	clac
39.endif
40
41	inc	%rsi
42	movb	%cl, (%rdi)
43	inc	%rdi
44	dec	%rdx
45	ja	.Lcopy_from_anywhere_loop\@
46.endm
47
48/* status_t copy_from_anywhere(void *kdest, user_addr_t usrc, size_t len) */
49FUNCTION(copy_from_anywhere)
50	test	%rdx, %rdx
51	jz	.Lcopy_from_anywhere_done
52	movq	%cr4, %r8
53	test	$X86_CR4_SMAP, %r8
54	jz	.Lcopy_from_anywhere_without_smap
55	copy_from_anywhere_loop 1, .Lcopy_from_anywhere_with_smap_fault
56.Lcopy_from_anywhere_done:
57	xor	%eax, %eax
58	ret
59
60.Lcopy_from_anywhere_without_smap:
61	copy_from_anywhere_loop 0, .Lcopy_from_anywhere_without_smap_fault
62	xor	%eax, %eax
63	ret
64
65.Lcopy_from_anywhere_with_smap_fault:
66	clac
67.Lcopy_from_anywhere_without_smap_fault:
68.Lcopy_from_anywhere_fault_loop:
69	movb	$0, (%rdi)
70	inc	%rdi
71	dec	%rdx
72	ja	.Lcopy_from_anywhere_fault_loop
73	mov	$ERR_FAULT, %eax
74	ret
75