.. | .. |
---|
| 1 | +/* SPDX-License-Identifier: GPL-2.0-only */ |
---|
1 | 2 | /* |
---|
2 | 3 | * Based on arch/arm/include/asm/ptrace.h |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright (C) 1996-2003 Russell King |
---|
5 | 6 | * Copyright (C) 2012 ARM Ltd. |
---|
6 | | - * |
---|
7 | | - * This program is free software; you can redistribute it and/or modify |
---|
8 | | - * it under the terms of the GNU General Public License version 2 as |
---|
9 | | - * published by the Free Software Foundation. |
---|
10 | | - * |
---|
11 | | - * This program is distributed in the hope that it will be useful, |
---|
12 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
13 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
14 | | - * GNU General Public License for more details. |
---|
15 | | - * |
---|
16 | | - * You should have received a copy of the GNU General Public License |
---|
17 | | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
---|
18 | 7 | */ |
---|
19 | 8 | #ifndef __ASM_PTRACE_H |
---|
20 | 9 | #define __ASM_PTRACE_H |
---|
| 10 | + |
---|
| 11 | +#include <asm/cpufeature.h> |
---|
21 | 12 | |
---|
22 | 13 | #include <uapi/asm/ptrace.h> |
---|
23 | 14 | |
---|
24 | 15 | /* Current Exception Level values, as contained in CurrentEL */ |
---|
25 | 16 | #define CurrentEL_EL1 (1 << 2) |
---|
26 | 17 | #define CurrentEL_EL2 (2 << 2) |
---|
| 18 | + |
---|
| 19 | +#define INIT_PSTATE_EL1 \ |
---|
| 20 | + (PSR_D_BIT | PSR_A_BIT | PSR_I_BIT | PSR_F_BIT | PSR_MODE_EL1h) |
---|
| 21 | +#define INIT_PSTATE_EL2 \ |
---|
| 22 | + (PSR_D_BIT | PSR_A_BIT | PSR_I_BIT | PSR_F_BIT | PSR_MODE_EL2h) |
---|
| 23 | + |
---|
| 24 | +/* |
---|
| 25 | + * PMR values used to mask/unmask interrupts. |
---|
| 26 | + * |
---|
| 27 | + * GIC priority masking works as follows: if an IRQ's priority is a higher value |
---|
| 28 | + * than the value held in PMR, that IRQ is masked. Lowering the value of PMR |
---|
| 29 | + * means masking more IRQs (or at least that the same IRQs remain masked). |
---|
| 30 | + * |
---|
| 31 | + * To mask interrupts, we clear the most significant bit of PMR. |
---|
| 32 | + * |
---|
| 33 | + * Some code sections either automatically switch back to PSR.I or explicitly |
---|
| 34 | + * require to not use priority masking. If bit GIC_PRIO_PSR_I_SET is included |
---|
| 35 | + * in the priority mask, it indicates that PSR.I should be set and |
---|
| 36 | + * interrupt disabling temporarily does not rely on IRQ priorities. |
---|
| 37 | + */ |
---|
| 38 | +#define GIC_PRIO_IRQON 0xe0 |
---|
| 39 | +#define __GIC_PRIO_IRQOFF (GIC_PRIO_IRQON & ~0x80) |
---|
| 40 | +#define __GIC_PRIO_IRQOFF_NS 0xa0 |
---|
| 41 | +#define GIC_PRIO_PSR_I_SET (1 << 4) |
---|
| 42 | + |
---|
| 43 | +#define GIC_PRIO_IRQOFF \ |
---|
| 44 | + ({ \ |
---|
| 45 | + extern struct static_key_false gic_nonsecure_priorities;\ |
---|
| 46 | + u8 __prio = __GIC_PRIO_IRQOFF; \ |
---|
| 47 | + \ |
---|
| 48 | + if (static_branch_unlikely(&gic_nonsecure_priorities)) \ |
---|
| 49 | + __prio = __GIC_PRIO_IRQOFF_NS; \ |
---|
| 50 | + \ |
---|
| 51 | + __prio; \ |
---|
| 52 | + }) |
---|
| 53 | + |
---|
| 54 | +/* Additional SPSR bits not exposed in the UABI */ |
---|
| 55 | +#define PSR_MODE_THREAD_BIT (1 << 0) |
---|
| 56 | +#define PSR_IL_BIT (1 << 20) |
---|
27 | 57 | |
---|
28 | 58 | /* AArch32-specific ptrace requests */ |
---|
29 | 59 | #define COMPAT_PTRACE_GETREGS 12 |
---|
.. | .. |
---|
165 | 195 | #endif |
---|
166 | 196 | |
---|
167 | 197 | u64 orig_addr_limit; |
---|
168 | | - u64 unused; // maintain 16 byte alignment |
---|
| 198 | + /* Only valid when ARM64_HAS_IRQ_PRIO_MASKING is enabled. */ |
---|
| 199 | + u64 pmr_save; |
---|
169 | 200 | u64 stackframe[2]; |
---|
| 201 | + |
---|
| 202 | + /* Only valid for some EL1 exceptions. */ |
---|
| 203 | + u64 lockdep_hardirqs; |
---|
| 204 | + u64 exit_rcu; |
---|
170 | 205 | }; |
---|
171 | 206 | |
---|
172 | 207 | static inline bool in_syscall(struct pt_regs const *regs) |
---|
.. | .. |
---|
200 | 235 | #define processor_mode(regs) \ |
---|
201 | 236 | ((regs)->pstate & PSR_MODE_MASK) |
---|
202 | 237 | |
---|
203 | | -#define interrupts_enabled(regs) \ |
---|
204 | | - (!((regs)->pstate & PSR_I_BIT)) |
---|
| 238 | +#define irqs_priority_unmasked(regs) \ |
---|
| 239 | + (system_uses_irq_prio_masking() ? \ |
---|
| 240 | + (regs)->pmr_save == GIC_PRIO_IRQON : \ |
---|
| 241 | + true) |
---|
| 242 | + |
---|
| 243 | +#define interrupts_enabled(regs) \ |
---|
| 244 | + (!((regs)->pstate & PSR_I_BIT) && irqs_priority_unmasked(regs)) |
---|
205 | 245 | |
---|
206 | 246 | #define fast_interrupts_enabled(regs) \ |
---|
207 | 247 | (!((regs)->pstate & PSR_F_BIT)) |
---|
208 | 248 | |
---|
209 | | -#define GET_USP(regs) \ |
---|
210 | | - (!compat_user_mode(regs) ? (regs)->sp : (regs)->compat_sp) |
---|
211 | | - |
---|
212 | | -#define SET_USP(ptregs, value) \ |
---|
213 | | - (!compat_user_mode(regs) ? ((regs)->sp = value) : ((regs)->compat_sp = value)) |
---|
| 249 | +static inline unsigned long user_stack_pointer(struct pt_regs *regs) |
---|
| 250 | +{ |
---|
| 251 | + if (compat_user_mode(regs)) |
---|
| 252 | + return regs->compat_sp; |
---|
| 253 | + return regs->sp; |
---|
| 254 | +} |
---|
214 | 255 | |
---|
215 | 256 | extern int regs_query_register_offset(const char *name); |
---|
216 | 257 | extern unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, |
---|
.. | .. |
---|
280 | 321 | |
---|
281 | 322 | static inline unsigned long regs_return_value(struct pt_regs *regs) |
---|
282 | 323 | { |
---|
283 | | - return regs->regs[0]; |
---|
| 324 | + unsigned long val = regs->regs[0]; |
---|
| 325 | + |
---|
| 326 | + /* |
---|
| 327 | + * Audit currently uses regs_return_value() instead of |
---|
| 328 | + * syscall_get_return_value(). Apply the same sign-extension here until |
---|
| 329 | + * audit is updated to use syscall_get_return_value(). |
---|
| 330 | + */ |
---|
| 331 | + if (compat_user_mode(regs)) |
---|
| 332 | + val = sign_extend64(val, 31); |
---|
| 333 | + |
---|
| 334 | + return val; |
---|
| 335 | +} |
---|
| 336 | + |
---|
| 337 | +static inline void regs_set_return_value(struct pt_regs *regs, unsigned long rc) |
---|
| 338 | +{ |
---|
| 339 | + regs->regs[0] = rc; |
---|
| 340 | +} |
---|
| 341 | + |
---|
| 342 | +/** |
---|
| 343 | + * regs_get_kernel_argument() - get Nth function argument in kernel |
---|
| 344 | + * @regs: pt_regs of that context |
---|
| 345 | + * @n: function argument number (start from 0) |
---|
| 346 | + * |
---|
| 347 | + * regs_get_argument() returns @n th argument of the function call. |
---|
| 348 | + * |
---|
| 349 | + * Note that this chooses the most likely register mapping. In very rare |
---|
| 350 | + * cases this may not return correct data, for example, if one of the |
---|
| 351 | + * function parameters is 16 bytes or bigger. In such cases, we cannot |
---|
| 352 | + * get access the parameter correctly and the register assignment of |
---|
| 353 | + * subsequent parameters will be shifted. |
---|
| 354 | + */ |
---|
| 355 | +static inline unsigned long regs_get_kernel_argument(struct pt_regs *regs, |
---|
| 356 | + unsigned int n) |
---|
| 357 | +{ |
---|
| 358 | +#define NR_REG_ARGUMENTS 8 |
---|
| 359 | + if (n < NR_REG_ARGUMENTS) |
---|
| 360 | + return pt_regs_read_reg(regs, n); |
---|
| 361 | + return 0; |
---|
284 | 362 | } |
---|
285 | 363 | |
---|
286 | 364 | /* We must avoid circular header include via sched.h */ |
---|
287 | 365 | struct task_struct; |
---|
288 | 366 | int valid_user_regs(struct user_pt_regs *regs, struct task_struct *task); |
---|
289 | 367 | |
---|
290 | | -#define GET_IP(regs) ((unsigned long)(regs)->pc) |
---|
291 | | -#define SET_IP(regs, value) ((regs)->pc = ((u64) (value))) |
---|
| 368 | +static inline unsigned long instruction_pointer(struct pt_regs *regs) |
---|
| 369 | +{ |
---|
| 370 | + return regs->pc; |
---|
| 371 | +} |
---|
| 372 | +static inline void instruction_pointer_set(struct pt_regs *regs, |
---|
| 373 | + unsigned long val) |
---|
| 374 | +{ |
---|
| 375 | + regs->pc = val; |
---|
| 376 | +} |
---|
292 | 377 | |
---|
293 | | -#define GET_FP(ptregs) ((unsigned long)(ptregs)->regs[29]) |
---|
294 | | -#define SET_FP(ptregs, value) ((ptregs)->regs[29] = ((u64) (value))) |
---|
295 | | - |
---|
296 | | -#include <asm-generic/ptrace.h> |
---|
| 378 | +static inline unsigned long frame_pointer(struct pt_regs *regs) |
---|
| 379 | +{ |
---|
| 380 | + return regs->regs[29]; |
---|
| 381 | +} |
---|
297 | 382 | |
---|
298 | 383 | #define procedure_link_pointer(regs) ((regs)->regs[30]) |
---|
299 | 384 | |
---|
.. | .. |
---|
303 | 388 | procedure_link_pointer(regs) = val; |
---|
304 | 389 | } |
---|
305 | 390 | |
---|
306 | | -#undef profile_pc |
---|
307 | 391 | extern unsigned long profile_pc(struct pt_regs *regs); |
---|
308 | 392 | |
---|
309 | 393 | #endif /* __ASSEMBLY__ */ |
---|