]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - include/linux/regset.h
mm/hotplug: invalid PFNs from pfn_to_online_page()
[mirror_ubuntu-bionic-kernel.git] / include / linux / regset.h
CommitLineData
bdf88217
RM
1/*
2 * User-mode machine state access
3 *
4 * Copyright (C) 2007 Red Hat, Inc. All rights reserved.
5 *
6 * This copyrighted material is made available to anyone wishing to use,
7 * modify, copy, or redistribute it subject to the terms and conditions
8 * of the GNU General Public License v.2.
9 *
10 * Red Hat Author: Roland McGrath.
11 */
12
13#ifndef _LINUX_REGSET_H
14#define _LINUX_REGSET_H 1
15
16#include <linux/compiler.h>
17#include <linux/types.h>
187f1882 18#include <linux/bug.h>
bae3f7c3 19#include <linux/uaccess.h>
bdf88217
RM
20struct task_struct;
21struct user_regset;
22
23
24/**
25 * user_regset_active_fn - type of @active function in &struct user_regset
26 * @target: thread being examined
27 * @regset: regset being examined
28 *
29 * Return -%ENODEV if not available on the hardware found.
30 * Return %0 if no interesting state in this thread.
31 * Return >%0 number of @size units of interesting state.
32 * Any get call fetching state beyond that number will
33 * see the default initialization state for this data,
34 * so a caller that knows what the default state is need
35 * not copy it all out.
36 * This call is optional; the pointer is %NULL if there
37 * is no inexpensive check to yield a value < @n.
38 */
39typedef int user_regset_active_fn(struct task_struct *target,
40 const struct user_regset *regset);
41
42/**
43 * user_regset_get_fn - type of @get function in &struct user_regset
44 * @target: thread being examined
45 * @regset: regset being examined
46 * @pos: offset into the regset data to access, in bytes
47 * @count: amount of data to copy, in bytes
48 * @kbuf: if not %NULL, a kernel-space pointer to copy into
49 * @ubuf: if @kbuf is %NULL, a user-space pointer to copy into
50 *
51 * Fetch register values. Return %0 on success; -%EIO or -%ENODEV
52 * are usual failure returns. The @pos and @count values are in
53 * bytes, but must be properly aligned. If @kbuf is non-null, that
54 * buffer is used and @ubuf is ignored. If @kbuf is %NULL, then
55 * ubuf gives a userland pointer to access directly, and an -%EFAULT
56 * return value is possible.
57 */
58typedef int user_regset_get_fn(struct task_struct *target,
59 const struct user_regset *regset,
60 unsigned int pos, unsigned int count,
61 void *kbuf, void __user *ubuf);
62
63/**
64 * user_regset_set_fn - type of @set function in &struct user_regset
65 * @target: thread being examined
66 * @regset: regset being examined
67 * @pos: offset into the regset data to access, in bytes
68 * @count: amount of data to copy, in bytes
69 * @kbuf: if not %NULL, a kernel-space pointer to copy from
70 * @ubuf: if @kbuf is %NULL, a user-space pointer to copy from
71 *
72 * Store register values. Return %0 on success; -%EIO or -%ENODEV
73 * are usual failure returns. The @pos and @count values are in
74 * bytes, but must be properly aligned. If @kbuf is non-null, that
75 * buffer is used and @ubuf is ignored. If @kbuf is %NULL, then
76 * ubuf gives a userland pointer to access directly, and an -%EFAULT
77 * return value is possible.
78 */
79typedef int user_regset_set_fn(struct task_struct *target,
80 const struct user_regset *regset,
81 unsigned int pos, unsigned int count,
82 const void *kbuf, const void __user *ubuf);
83
84/**
85 * user_regset_writeback_fn - type of @writeback function in &struct user_regset
86 * @target: thread being examined
87 * @regset: regset being examined
88 * @immediate: zero if writeback at completion of next context switch is OK
89 *
90 * This call is optional; usually the pointer is %NULL. When
91 * provided, there is some user memory associated with this regset's
92 * hardware, such as memory backing cached register data on register
93 * window machines; the regset's data controls what user memory is
94 * used (e.g. via the stack pointer value).
95 *
96 * Write register data back to user memory. If the @immediate flag
97 * is nonzero, it must be written to the user memory so uaccess or
98 * access_process_vm() can see it when this call returns; if zero,
99 * then it must be written back by the time the task completes a
100 * context switch (as synchronized with wait_task_inactive()).
101 * Return %0 on success or if there was nothing to do, -%EFAULT for
102 * a memory problem (bad stack pointer or whatever), or -%EIO for a
103 * hardware problem.
104 */
105typedef int user_regset_writeback_fn(struct task_struct *target,
106 const struct user_regset *regset,
107 int immediate);
108
27e64b4b
DM
109/**
110 * user_regset_get_size_fn - type of @get_size function in &struct user_regset
111 * @target: thread being examined
112 * @regset: regset being examined
113 *
114 * This call is optional; usually the pointer is %NULL.
115 *
116 * When provided, this function must return the current size of regset
117 * data, as observed by the @get function in &struct user_regset. The
118 * value returned must be a multiple of @size. The returned size is
119 * required to be valid only until the next time (if any) @regset is
120 * modified for @target.
121 *
122 * This function is intended for dynamically sized regsets. A regset
123 * that is statically sized does not need to implement it.
124 *
125 * This function should not be called directly: instead, callers should
126 * call regset_size() to determine the current size of a regset.
127 */
128typedef unsigned int user_regset_get_size_fn(struct task_struct *target,
129 const struct user_regset *regset);
130
bdf88217
RM
131/**
132 * struct user_regset - accessible thread CPU state
133 * @n: Number of slots (registers).
134 * @size: Size in bytes of a slot (register).
135 * @align: Required alignment, in bytes.
136 * @bias: Bias from natural indexing.
137 * @core_note_type: ELF note @n_type value used in core dumps.
138 * @get: Function to fetch values.
139 * @set: Function to store values.
140 * @active: Function to report if regset is active, or %NULL.
141 * @writeback: Function to write data back to user memory, or %NULL.
27e64b4b 142 * @get_size: Function to return the regset's size, or %NULL.
bdf88217
RM
143 *
144 * This data structure describes a machine resource we call a register set.
145 * This is part of the state of an individual thread, not necessarily
146 * actual CPU registers per se. A register set consists of a number of
147 * similar slots, given by @n. Each slot is @size bytes, and aligned to
27e64b4b
DM
148 * @align bytes (which is at least @size). For dynamically-sized
149 * regsets, @n must contain the maximum possible number of slots for the
150 * regset, and @get_size must point to a function that returns the
151 * current regset size.
bdf88217 152 *
27e64b4b
DM
153 * Callers that need to know only the current size of the regset and do
154 * not care about its internal structure should call regset_size()
155 * instead of inspecting @n or calling @get_size.
156 *
157 * For backward compatibility, the @get and @set methods must pad to, or
158 * accept, @n * @size bytes, even if the current regset size is smaller.
159 * The precise semantics of these operations depend on the regset being
160 * accessed.
161 *
162 * The functions to which &struct user_regset members point must be
163 * called only on the current thread or on a thread that is in
164 * %TASK_STOPPED or %TASK_TRACED state, that we are guaranteed will not
165 * be woken up and return to user mode, and that we have called
166 * wait_task_inactive() on. (The target thread always might wake up for
167 * SIGKILL while these functions are working, in which case that
168 * thread's user_regset state might be scrambled.)
bdf88217
RM
169 *
170 * The @pos argument must be aligned according to @align; the @count
171 * argument must be a multiple of @size. These functions are not
172 * responsible for checking for invalid arguments.
173 *
174 * When there is a natural value to use as an index, @bias gives the
175 * difference between the natural index and the slot index for the
176 * register set. For example, x86 GDT segment descriptors form a regset;
177 * the segment selector produces a natural index, but only a subset of
178 * that index space is available as a regset (the TLS slots); subtracting
179 * @bias from a segment selector index value computes the regset slot.
180 *
181 * If nonzero, @core_note_type gives the n_type field (NT_* value)
182 * of the core file note in which this regset's data appears.
183 * NT_PRSTATUS is a special case in that the regset data starts at
184 * offsetof(struct elf_prstatus, pr_reg) into the note data; that is
185 * part of the per-machine ELF formats userland knows about. In
186 * other cases, the core file note contains exactly the whole regset
187 * (@n * @size) and nothing else. The core file note is normally
188 * omitted when there is an @active function and it returns zero.
189 */
190struct user_regset {
191 user_regset_get_fn *get;
192 user_regset_set_fn *set;
193 user_regset_active_fn *active;
194 user_regset_writeback_fn *writeback;
27e64b4b 195 user_regset_get_size_fn *get_size;
bdf88217
RM
196 unsigned int n;
197 unsigned int size;
198 unsigned int align;
199 unsigned int bias;
200 unsigned int core_note_type;
201};
202
203/**
204 * struct user_regset_view - available regsets
205 * @name: Identifier, e.g. UTS_MACHINE string.
206 * @regsets: Array of @n regsets available in this view.
207 * @n: Number of elements in @regsets.
208 * @e_machine: ELF header @e_machine %EM_* value written in core dumps.
209 * @e_flags: ELF header @e_flags value written in core dumps.
210 * @ei_osabi: ELF header @e_ident[%EI_OSABI] value written in core dumps.
211 *
212 * A regset view is a collection of regsets (&struct user_regset,
213 * above). This describes all the state of a thread that can be seen
214 * from a given architecture/ABI environment. More than one view might
215 * refer to the same &struct user_regset, or more than one regset
216 * might refer to the same machine-specific state in the thread. For
217 * example, a 32-bit thread's state could be examined from the 32-bit
218 * view or from the 64-bit view. Either method reaches the same thread
219 * register state, doing appropriate widening or truncation.
220 */
221struct user_regset_view {
222 const char *name;
223 const struct user_regset *regsets;
224 unsigned int n;
225 u32 e_flags;
226 u16 e_machine;
227 u8 ei_osabi;
228};
229
230/*
231 * This is documented here rather than at the definition sites because its
232 * implementation is machine-dependent but its interface is universal.
233 */
234/**
235 * task_user_regset_view - Return the process's native regset view.
236 * @tsk: a thread of the process in question
237 *
238 * Return the &struct user_regset_view that is native for the given process.
239 * For example, what it would access when it called ptrace().
240 * Throughout the life of the process, this only changes at exec.
241 */
242const struct user_regset_view *task_user_regset_view(struct task_struct *tsk);
243
244
bae3f7c3
RM
245/*
246 * These are helpers for writing regset get/set functions in arch code.
247 * Because @start_pos and @end_pos are always compile-time constants,
248 * these are inlined into very little code though they look large.
249 *
250 * Use one or more calls sequentially for each chunk of regset data stored
251 * contiguously in memory. Call with constants for @start_pos and @end_pos,
252 * giving the range of byte positions in the regset that data corresponds
253 * to; @end_pos can be -1 if this chunk is at the end of the regset layout.
254 * Each call updates the arguments to point past its chunk.
255 */
256
257static inline int user_regset_copyout(unsigned int *pos, unsigned int *count,
258 void **kbuf,
259 void __user **ubuf, const void *data,
260 const int start_pos, const int end_pos)
261{
262 if (*count == 0)
263 return 0;
264 BUG_ON(*pos < start_pos);
265 if (end_pos < 0 || *pos < end_pos) {
266 unsigned int copy = (end_pos < 0 ? *count
267 : min(*count, end_pos - *pos));
268 data += *pos - start_pos;
269 if (*kbuf) {
270 memcpy(*kbuf, data, copy);
271 *kbuf += copy;
272 } else if (__copy_to_user(*ubuf, data, copy))
273 return -EFAULT;
274 else
275 *ubuf += copy;
276 *pos += copy;
277 *count -= copy;
278 }
279 return 0;
280}
281
282static inline int user_regset_copyin(unsigned int *pos, unsigned int *count,
283 const void **kbuf,
284 const void __user **ubuf, void *data,
285 const int start_pos, const int end_pos)
286{
287 if (*count == 0)
288 return 0;
289 BUG_ON(*pos < start_pos);
290 if (end_pos < 0 || *pos < end_pos) {
291 unsigned int copy = (end_pos < 0 ? *count
292 : min(*count, end_pos - *pos));
293 data += *pos - start_pos;
294 if (*kbuf) {
295 memcpy(data, *kbuf, copy);
296 *kbuf += copy;
297 } else if (__copy_from_user(data, *ubuf, copy))
298 return -EFAULT;
299 else
300 *ubuf += copy;
301 *pos += copy;
302 *count -= copy;
303 }
304 return 0;
305}
306
307/*
308 * These two parallel the two above, but for portions of a regset layout
309 * that always read as all-zero or for which writes are ignored.
310 */
311static inline int user_regset_copyout_zero(unsigned int *pos,
312 unsigned int *count,
313 void **kbuf, void __user **ubuf,
314 const int start_pos,
315 const int end_pos)
316{
317 if (*count == 0)
318 return 0;
319 BUG_ON(*pos < start_pos);
320 if (end_pos < 0 || *pos < end_pos) {
321 unsigned int copy = (end_pos < 0 ? *count
322 : min(*count, end_pos - *pos));
323 if (*kbuf) {
324 memset(*kbuf, 0, copy);
325 *kbuf += copy;
326 } else if (__clear_user(*ubuf, copy))
327 return -EFAULT;
328 else
329 *ubuf += copy;
330 *pos += copy;
331 *count -= copy;
332 }
333 return 0;
334}
335
336static inline int user_regset_copyin_ignore(unsigned int *pos,
337 unsigned int *count,
338 const void **kbuf,
339 const void __user **ubuf,
340 const int start_pos,
341 const int end_pos)
342{
343 if (*count == 0)
344 return 0;
345 BUG_ON(*pos < start_pos);
346 if (end_pos < 0 || *pos < end_pos) {
347 unsigned int copy = (end_pos < 0 ? *count
348 : min(*count, end_pos - *pos));
349 if (*kbuf)
350 *kbuf += copy;
351 else
352 *ubuf += copy;
353 *pos += copy;
354 *count -= copy;
355 }
356 return 0;
357}
358
5bde4d18
RM
359/**
360 * copy_regset_to_user - fetch a thread's user_regset data into user memory
361 * @target: thread to be examined
362 * @view: &struct user_regset_view describing user thread machine state
363 * @setno: index in @view->regsets
364 * @offset: offset into the regset data, in bytes
365 * @size: amount of data to copy, in bytes
366 * @data: user-mode pointer to copy into
367 */
368static inline int copy_regset_to_user(struct task_struct *target,
369 const struct user_regset_view *view,
370 unsigned int setno,
371 unsigned int offset, unsigned int size,
372 void __user *data)
373{
374 const struct user_regset *regset = &view->regsets[setno];
375
c8e25258
PA
376 if (!regset->get)
377 return -EOPNOTSUPP;
378
5bde4d18 379 if (!access_ok(VERIFY_WRITE, data, size))
5189fa19 380 return -EFAULT;
5bde4d18
RM
381
382 return regset->get(target, regset, offset, size, NULL, data);
383}
384
385/**
386 * copy_regset_from_user - store into thread's user_regset data from user memory
387 * @target: thread to be examined
388 * @view: &struct user_regset_view describing user thread machine state
389 * @setno: index in @view->regsets
390 * @offset: offset into the regset data, in bytes
391 * @size: amount of data to copy, in bytes
392 * @data: user-mode pointer to copy from
393 */
394static inline int copy_regset_from_user(struct task_struct *target,
395 const struct user_regset_view *view,
396 unsigned int setno,
397 unsigned int offset, unsigned int size,
398 const void __user *data)
399{
400 const struct user_regset *regset = &view->regsets[setno];
401
c8e25258
PA
402 if (!regset->set)
403 return -EOPNOTSUPP;
404
5bde4d18 405 if (!access_ok(VERIFY_READ, data, size))
5189fa19 406 return -EFAULT;
5bde4d18
RM
407
408 return regset->set(target, regset, offset, size, NULL, data);
409}
410
27e64b4b
DM
411/**
412 * regset_size - determine the current size of a regset
413 * @target: thread to be examined
414 * @regset: regset to be examined
415 *
416 * Note that the returned size is valid only until the next time
417 * (if any) @regset is modified for @target.
418 */
419static inline unsigned int regset_size(struct task_struct *target,
420 const struct user_regset *regset)
421{
422 if (!regset->get_size)
423 return regset->n * regset->size;
424 else
425 return regset->get_size(target, regset);
426}
bae3f7c3 427
bdf88217 428#endif /* <linux/regset.h> */