xref: /xnu-11215.41.3/osfmk/kern/restartable.h (revision 33de042d024d46de5ff4e89f2471de6608e37fa4)
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 _KERN_RESTARTABLE_H_
30 #define _KERN_RESTARTABLE_H_
31 
32 #include <sys/cdefs.h>
33 #include <mach/message.h>
34 #include <mach/task.h>
35 
36 __BEGIN_DECLS
37 
38 /*!
39  * @typedef task_restartable_range_t
40  *
41  * @brief
42  * Describes a userspace recoverable range.
43  *
44  * @field location
45  * The pointer to the beginning of a restartable section.
46  *
47  * @field length
48  * The length of the critical section anchored at location.
49  *
50  * @field recovery_offs
51  * The offset from the initial location that should be used for the recovery
52  * codepath.
53  *
54  * @field flags
55  * Currently unused, pass 0.
56  */
57 typedef struct {
58 	mach_vm_address_t location;
59 	unsigned short    length;
60 	unsigned short    recovery_offs;
61 	unsigned int      flags;
62 } task_restartable_range_t;
63 
64 typedef task_restartable_range_t *task_restartable_range_array_t;
65 
66 /*!
67  * @function task_restartable_ranges_register
68  *
69  * @brief
70  * Register a set of restartable ranges for the current task.
71  *
72  * @param task
73  * The task to operate on
74  *
75  * @param ranges
76  * An array of address ranges for which PC resets are performed.
77  *
78  * @param count
79  * The number of address ranges.
80  *
81  * @returns
82  * - KERN_SUCCESS on success
83  * - KERN_FAILURE if the task isn't the current one
84  * - KERN_INVALID_ARGUMENT for various invalid inputs
85  * - KERN_NOT_SUPPORTED the request is not supported (second registration on
86  *   release kernels, registration when the task has gone wide)
87  * - KERN_RESOURCE_SHORTAGE if not enough memory
88  */
89 extern kern_return_t task_restartable_ranges_register(
90 	task_t                         task,
91 	task_restartable_range_array_t ranges,
92 	mach_msg_type_number_t         count);
93 
94 /*!
95  * @function task_restartable_ranges_synchronize
96  *
97  * @brief
98  * Require for all threads in the task to reset their PC
99  * if within a restartable range.
100  *
101  * @param task
102  * The task to operate on (needs to be current task)
103  *
104  * @returns
105  * - KERN_SUCCESS
106  * - KERN_FAILURE if the task isn't the current one
107  */
108 extern kern_return_t task_restartable_ranges_synchronize(task_t task);
109 
110 /*!
111  * @const TASK_RESTARTABLE_OFFSET_MAX
112  * The maximum value length / recovery_offs can have.
113  */
114 #define TASK_RESTARTABLE_OFFSET_MAX  4096u
115 
116 #ifdef KERNEL_PRIVATE
117 #pragma GCC visibility push(hidden)
118 
119 struct restartable_ranges;
120 
121 /**
122  * @function restartable_init
123  *
124  * @brief
125  * Initializes the restartable module.
126  */
127 extern void restartable_init(void);
128 
129 /**
130  * @function restartable_ranges_release
131  *
132  * @brief
133  * Release a reference on a restartable range.
134  */
135 extern void restartable_ranges_release(struct restartable_ranges *ranges);
136 
137 /**
138  * @function thread_reset_pcs_in_range
139  *
140  * @brief
141  * Returns whether a non running thread is currently in a critical range.
142  */
143 extern bool thread_reset_pcs_in_range(task_t task, struct thread *thread);
144 
145 /**
146  * @function thread_reset_pcs_will_fault
147  *
148  * @brief
149  * Called by the platform code when about to handle a user fault exception.
150  */
151 extern void thread_reset_pcs_will_fault(struct thread *thread);
152 
153 /**
154  * @function thread_reset_pcs_done_faulting
155  *
156  * @brief
157  * Called by the platform code when being done handling a user fault
158  * exception.
159  */
160 extern void thread_reset_pcs_done_faulting(struct thread *thread);
161 
162 /**
163  * @function thread_reset_pcs_ast
164  *
165  * @brief
166  * Perform the work at the AST boundary to reset thread PCS.
167  */
168 extern void thread_reset_pcs_ast(task_t task, struct thread *thread);
169 
170 /**
171  * @function thread_reset_pcs_ack_IPI
172  *
173  * @brief
174  * Called by the scheduler code when acking the reset-pcs IPI.
175  */
176 extern void thread_reset_pcs_ack_IPI(struct thread *thread);
177 
178 #pragma GCC visibility pop
179 #endif // KERNEL_PRIVATE
180 
181 __END_DECLS
182 
183 #endif  /* _KERN_RESTARTABLE_H_ */
184