xref: /xnu-8020.121.3/osfmk/arm64/pac_asm.h (revision fdd8201d7b966f0c3ea610489d29bd841d358941)
1 /*
2  * Copyright (c) 2019 Apple Inc. All rights reserved.
3  *
4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5  *
6  * This file contains Original Code and/or Modifications of Original Code
7  * as defined in and that are subject to the Apple Public Source License
8  * Version 2.0 (the 'License'). You may not use this file except in
9  * compliance with the License. The rights granted to you under the License
10  * may not be used to create, or enable the creation or redistribution of,
11  * unlawful or unlicensed copies of an Apple operating system, or to
12  * circumvent, violate, or enable the circumvention or violation of, any
13  * terms of an Apple operating system software license agreement.
14  *
15  * Please obtain a copy of the License at
16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17  *
18  * The Original Code and all software distributed under the License are
19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23  * Please see the License for the specific language governing rights and
24  * limitations under the License.
25  *
26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27  */
28 
29 #ifndef _ARM64_PAC_ASM_H_
30 #define _ARM64_PAC_ASM_H_
31 
32 #ifndef __ASSEMBLER__
33 #error "This header should only be used in .s files"
34 #endif
35 
36 #include <pexpert/arm64/board_config.h>
37 #include <arm64/proc_reg.h>
38 #if HAS_PARAVIRTUALIZED_PAC
39 #include "smccc_asm.h"
40 #endif
41 #include "assym.s"
42 
43 #if defined(HAS_APPLE_PAC)
44 
45 
46 /* BEGIN IGNORE CODESTYLE */
47 
48 /**
49  * REPROGRAM_JOP_KEYS
50  *
51  * Loads a userspace process's JOP key (task->jop_pid) into the CPU, and
52  * updates current_cpu_datap()->jop_key accordingly.  This reprogramming process
53  * is skipped whenever the "new" JOP key has already been loaded into the CPU.
54  *
55  *   skip_label - branch to this label if new_jop_key is already loaded into CPU
56  *   new_jop_key - process's jop_pid
57  *   cpudatap - current cpu_data_t *
58  *   tmp - scratch register
59  */
60 .macro REPROGRAM_JOP_KEYS	skip_label, new_jop_key, cpudatap, tmp
61 	ldr		\tmp, [\cpudatap, CPU_JOP_KEY]
62 	cmp		\new_jop_key, \tmp
63 	b.eq	\skip_label
64 	SET_JOP_KEY_REGISTERS	\new_jop_key, \tmp
65 	str		\new_jop_key, [\cpudatap, CPU_JOP_KEY]
66 .endmacro
67 
68 /**
69  * REPROGRAM_ROP_KEYS
70  *
71  * Loads a userspace process's ROP key (task->rop_pid) into the CPU, and
72  * updates current_cpu_datap()->rop_key accordingly.  This reprogramming process
73  * is skipped whenever the "new" ROP key has already been loaded into the CPU.
74  *
75  *   skip_label - branch to this label if new_rop_key is already loaded into CPU
76  *   new_rop_key - process's rop_pid
77  *   cpudatap - current cpu_data_t *
78  *   tmp - scratch register
79  */
80 .macro REPROGRAM_ROP_KEYS	skip_label, new_rop_key, cpudatap, tmp
81 	ldr		\tmp, [\cpudatap, CPU_ROP_KEY]
82 	cmp		\new_rop_key, \tmp
83 	b.eq	\skip_label
84 	SET_ROP_KEY_REGISTERS	\new_rop_key, \tmp
85 	str		\new_rop_key, [\cpudatap, CPU_ROP_KEY]
86 .endmacro
87 
88 /**
89  * SET_JOP_KEY_REGISTERS
90  *
91  * Unconditionally loads a userspace process's JOP key (task->jop_pid) into the
92  * CPU.  The caller is responsible for updating current_cpu_datap()->jop_key as
93  * needed.
94  *
95  *   new_jop_key - process's jop_pid
96  *   tmp - scratch register
97  */
98 .macro SET_JOP_KEY_REGISTERS	new_jop_key, tmp
99 #if HAS_PARAVIRTUALIZED_PAC
100 	SAVE_SMCCC_CLOBBERED_REGISTERS
101 	/*
102 	 * We're deliberately calling PAC_SET_EL0_DIVERSIFIER here, even though the
103 	 * EL0 diversifier affects both A (JOP) and B (ROP) keys.  We don't want
104 	 * SET_JOP_KEY_REGISTERS to have an impact on the EL1 A key state, since
105 	 * these are the keys the kernel uses to sign pointers on the heap.
106 	 *
107 	 * Using new_jop_key as the EL0 diversifer has the same net effect of giving
108 	 * userspace its own set of JOP keys, but doesn't affect EL1 A key state.
109 	 */
110 	MOV64	x0, VMAPPLE_PAC_SET_EL0_DIVERSIFIER
111 	mov		x1, \new_jop_key
112 	hvc		#0
113 	LOAD_SMCCC_CLOBBERED_REGISTERS
114 #endif /* HAS_PARAVIRTUALIZED_PAC */
115 .endmacro
116 
117 /**
118  * SET_ROP_KEY_REGISTERS
119  *
120  * Unconditionally loads a userspace process's ROP key (task->rop_pid) into the
121  * CPU.  The caller is responsible for updating current_cpu_datap()->rop_key as
122  * needed.
123  *
124  *   new_rop_key - process's rop_pid
125  *   tmp - scratch register
126  */
127 .macro SET_ROP_KEY_REGISTERS	new_rop_key, tmp
128 #if HAS_PARAVIRTUALIZED_PAC
129 	SAVE_SMCCC_CLOBBERED_REGISTERS
130 	MOV64	x0, VMAPPLE_PAC_SET_B_KEYS
131 	mov		x1, \new_rop_key
132 	hvc		#0
133 	LOAD_SMCCC_CLOBBERED_REGISTERS
134 #endif /* HAS_PARAVIRTUALIZED_PAC */
135 .endmacro
136 
137 /**
138  * PAC_INIT_KEY_STATE
139  *
140  * Sets the initial PAC key state, but does not enable the keys.
141  *
142  *   tmp - scratch register
143  *   tmp2 - scratch register
144  */
145 .macro PAC_INIT_KEY_STATE	tmp, tmp2
146 #if HAS_PARAVIRTUALIZED_PAC
147 #if HIBERNATION
148 	#error PAC_INIT_KEY_STATE is not implemented for HAS_PARAVIRTUALIZED_PAC && HIBERNATION
149 #endif
150 	/*
151 	 * This call clobbers x0-x3.  However we only initialize PAC at a point in
152 	 * common_start where x0-x3 are safe to clobber, and where we don't yet have
153 	 * a working stack to stash the existing values anyway.
154 	 */
155 	mov		x0, #VMAPPLE_PAC_SET_INITIAL_STATE
156 	hvc		#0
157 #endif /* HAS_PARAVIRTUALIZED_PAC */
158 .endmacro
159 
160 /* END IGNORE CODESTYLE */
161 
162 #endif /* defined(HAS_APPLE_PAC) */
163 
164 #endif /* _ARM64_PAC_ASM_H_ */
165 
166 /* vim: set ts=4 ft=asm: */
167