xref: /xnu-11417.121.6/osfmk/arm64/static_if.c (revision a1e26a70f38d1d7daa7b49b258e2f8538ad81650)
1 /* * Copyright (c) 2021 Apple Inc. All rights reserved.
2  *
3  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
4  *
5  * This file contains Original Code and/or Modifications of Original Code
6  * as defined in and that are subject to the Apple Public Source License
7  * Version 2.0 (the 'License'). You may not use this file except in
8  * compliance with the License. The rights granted to you under the License
9  * may not be used to create, or enable the creation or redistribution of,
10  * unlawful or unlicensed copies of an Apple operating system, or to
11  * circumvent, violate, or enable the circumvention or violation of, any
12  * terms of an Apple operating system software license agreement.
13  *
14  * Please obtain a copy of the License at
15  * http://www.opensource.apple.com/apsl/ and read it before using this file.
16  *
17  * The Original Code and all software distributed under the License are
18  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
19  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
20  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
21  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
22  * Please see the License for the specific language governing rights and
23  * limitations under the License.
24  *
25  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
26  */
27 
28 #include <mach/vm_types.h>
29 #include <machine/static_if.h>
30 #include <arm64/amcc_rorgn.h>
31 #include <arm64/proc_reg.h>
32 #include <kern/startup.h>
33 
34 extern char __text_exec_start[] __SEGMENT_START_SYM("__TEXT_EXEC");
35 extern char __text_exec_end[]   __SEGMENT_END_SYM("__TEXT_EXEC");
36 
37 __attribute__((always_inline))
38 static uint32_t
arm64_insn_nop(void)39 arm64_insn_nop(void)
40 {
41 	return 0xd503201f;
42 }
43 
44 __attribute__((always_inline))
45 static uint32_t
arm64_insn_b(int32_t delta)46 arm64_insn_b(int32_t delta)
47 {
48 	return 0x14000000u | ((delta >> 2) & 0x03ffffff);
49 }
50 
51 MARK_AS_FIXUP_TEXT void
ml_static_if_entry_patch(static_if_entry_t sie,int branch)52 ml_static_if_entry_patch(static_if_entry_t sie, int branch)
53 {
54 	vm_offset_t patch_point = __static_if_entry_patch_point(sie);
55 	uint32_t insn;
56 
57 	if (branch) {
58 		insn = arm64_insn_b(sie->sie_target);
59 	} else {
60 		insn = arm64_insn_nop();
61 	}
62 
63 	if ((vm_offset_t)__text_exec_start <= patch_point &&
64 	    patch_point < (vm_offset_t)__text_exec_end) {
65 		asm volatile (""
66 		     /* patch the instruction */
67                      "str     %w1, [%0]"     "\n\t"
68 #if !__ARM_IC_NOALIAS_ICACHE__
69 		     /* invalidate icache cacheline */
70                      "ic      ivau, %0"      "\n\t"
71                      "dsb     sy"            "\n\t"
72                      "isb     sy"
73 #endif /* !__ARM_IC_NOALIAS_ICACHE__ */
74                      : : "r"(patch_point), "r"(insn) : "memory");
75 	}
76 }
77 
78 MARK_AS_FIXUP_TEXT void
ml_static_if_flush_icache(void)79 ml_static_if_flush_icache(void)
80 {
81 	asm volatile (""
82              "ic      ialluis"       "\n\t"
83              "dsb     sy"            "\n\t"
84              "isb     sy" : : : "memory");
85 }
86