1419b0af8Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 2419b0af8Sopenharmony_ci/* 3419b0af8Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd. 4419b0af8Sopenharmony_ci */ 5419b0af8Sopenharmony_ci 6419b0af8Sopenharmony_ci#include <asm/asm-offsets.h> 7419b0af8Sopenharmony_ci#include <asm/ptrace.h> 8419b0af8Sopenharmony_ci#include <linux/irqflags.h> 9419b0af8Sopenharmony_ci 10419b0af8Sopenharmony_ci/* The members of arrays below are corresponding to the enum defined in pointer_auth_context.h: 11419b0af8Sopenharmony_ci * enum pac_pt_regs { 12419b0af8Sopenharmony_ci * REGS_X16 = 0, 13419b0af8Sopenharmony_ci * REGS_X17, 14419b0af8Sopenharmony_ci * REGS_LR, 15419b0af8Sopenharmony_ci * REGS_SP, 16419b0af8Sopenharmony_ci * REGS_PC, 17419b0af8Sopenharmony_ci * REGS_PSTATE, 18419b0af8Sopenharmony_ci * }; 19419b0af8Sopenharmony_ci * 20419b0af8Sopenharmony_ci * compat_regs_offset_array[]: 21419b0af8Sopenharmony_ci * S_X14: the offset of compat_lr 22419b0af8Sopenharmony_ci * S_X13: the offset of compat_sp 23419b0af8Sopenharmony_ci */ 24419b0af8Sopenharmony_cistatic off_t compat_regs_offset_array[] = {0, 0, S_X14, S_X13, S_PC, S_PSTATE}; 25419b0af8Sopenharmony_cistatic off_t regs_offset_array[] = {S_X16, S_X17, S_LR, S_SP, S_PC, S_PSTATE}; 26419b0af8Sopenharmony_ci 27419b0af8Sopenharmony_ciint set_compat_exception_context_register(void *regs, enum pac_pt_regs regs_enum, u64 val) 28419b0af8Sopenharmony_ci{ 29419b0af8Sopenharmony_ci switch (regs_enum) { 30419b0af8Sopenharmony_ci case REGS_LR: 31419b0af8Sopenharmony_ci case REGS_SP: 32419b0af8Sopenharmony_ci case REGS_PC: 33419b0af8Sopenharmony_ci case REGS_PSTATE: 34419b0af8Sopenharmony_ci return set_compat_exception_context_register_asm(regs, compat_regs_offset_array[regs_enum], val); 35419b0af8Sopenharmony_ci default: 36419b0af8Sopenharmony_ci return -EINVAL; 37419b0af8Sopenharmony_ci } 38419b0af8Sopenharmony_ci} 39419b0af8Sopenharmony_ci 40419b0af8Sopenharmony_ciint set_exception_context_register(void *regs, enum pac_pt_regs regs_enum, u64 val) 41419b0af8Sopenharmony_ci{ 42419b0af8Sopenharmony_ci if (compat_user_mode((struct pt_regs *)regs)) { 43419b0af8Sopenharmony_ci return set_compat_exception_context_register(regs, regs_enum, val); 44419b0af8Sopenharmony_ci } else { 45419b0af8Sopenharmony_ci switch (regs_enum) { 46419b0af8Sopenharmony_ci case REGS_X16: 47419b0af8Sopenharmony_ci case REGS_X17: 48419b0af8Sopenharmony_ci case REGS_LR: 49419b0af8Sopenharmony_ci case REGS_SP: 50419b0af8Sopenharmony_ci case REGS_PC: 51419b0af8Sopenharmony_ci case REGS_PSTATE: 52419b0af8Sopenharmony_ci return set_exception_context_register_asm(regs, regs_offset_array[regs_enum], val); 53419b0af8Sopenharmony_ci default: 54419b0af8Sopenharmony_ci return -EINVAL; 55419b0af8Sopenharmony_ci } 56419b0af8Sopenharmony_ci } 57419b0af8Sopenharmony_ci} 58419b0af8Sopenharmony_ci 59419b0af8Sopenharmony_civoid set_compat_exception_context_register_index(struct pt_regs *regs, int index, uint64_t val) 60419b0af8Sopenharmony_ci{ 61419b0af8Sopenharmony_ci /* 14 means the index of compat_lr */ 62419b0af8Sopenharmony_ci if (index == 14) { 63419b0af8Sopenharmony_ci set_compat_exception_context_register_asm(regs, S_X14, val); 64419b0af8Sopenharmony_ci /* 13 means the index of compat_sp */ 65419b0af8Sopenharmony_ci } else if (index == 13) { 66419b0af8Sopenharmony_ci set_compat_exception_context_register_asm(regs, S_X13, val); 67419b0af8Sopenharmony_ci } else { 68419b0af8Sopenharmony_ci regs->regs[index] = val; 69419b0af8Sopenharmony_ci } 70419b0af8Sopenharmony_ci} 71419b0af8Sopenharmony_ci 72419b0af8Sopenharmony_civoid set_exception_context_register_index(struct pt_regs *regs, int index, uint64_t val) 73419b0af8Sopenharmony_ci{ 74419b0af8Sopenharmony_ci off_t offset; 75419b0af8Sopenharmony_ci 76419b0af8Sopenharmony_ci if (compat_user_mode(regs)) { 77419b0af8Sopenharmony_ci set_compat_exception_context_register_index(regs, index, val); 78419b0af8Sopenharmony_ci } else { 79419b0af8Sopenharmony_ci switch (index) { 80419b0af8Sopenharmony_ci /* 16 means the index of regs[16] */ 81419b0af8Sopenharmony_ci case 16: 82419b0af8Sopenharmony_ci /* 17 means the index of regs[17] */ 83419b0af8Sopenharmony_ci case 17: 84419b0af8Sopenharmony_ci /* 30 means the index of regs[30] */ 85419b0af8Sopenharmony_ci case 30: 86419b0af8Sopenharmony_ci offset = offsetof(struct pt_regs, regs[index]); 87419b0af8Sopenharmony_ci set_exception_context_register_asm(regs, offset, val); 88419b0af8Sopenharmony_ci break; 89419b0af8Sopenharmony_ci default: 90419b0af8Sopenharmony_ci regs->regs[index] = val; 91419b0af8Sopenharmony_ci } 92419b0af8Sopenharmony_ci } 93419b0af8Sopenharmony_ci} 94419b0af8Sopenharmony_ci 95419b0af8Sopenharmony_civoid sign_compat_exception_context(void *regs) 96419b0af8Sopenharmony_ci{ 97419b0af8Sopenharmony_ci unsigned long irq_flags; 98419b0af8Sopenharmony_ci local_irq_save(irq_flags); 99419b0af8Sopenharmony_ci sign_compat_exception_context_asm(regs); 100419b0af8Sopenharmony_ci local_irq_restore(irq_flags); 101419b0af8Sopenharmony_ci} 102419b0af8Sopenharmony_ci 103419b0af8Sopenharmony_civoid auth_compat_exception_context(void *regs) 104419b0af8Sopenharmony_ci{ 105419b0af8Sopenharmony_ci unsigned long irq_flags; 106419b0af8Sopenharmony_ci local_irq_save(irq_flags); 107419b0af8Sopenharmony_ci auth_compat_exception_context_asm(regs); 108419b0af8Sopenharmony_ci local_irq_restore(irq_flags); 109419b0af8Sopenharmony_ci} 110419b0af8Sopenharmony_ci 111419b0af8Sopenharmony_civoid sign_exception_context(void *regs) 112419b0af8Sopenharmony_ci{ 113419b0af8Sopenharmony_ci unsigned long irq_flags; 114419b0af8Sopenharmony_ci local_irq_save(irq_flags); 115419b0af8Sopenharmony_ci if (compat_user_mode((struct pt_regs *)regs)) { 116419b0af8Sopenharmony_ci sign_compat_exception_context_asm(regs); 117419b0af8Sopenharmony_ci } else { 118419b0af8Sopenharmony_ci sign_exception_context_asm(regs); 119419b0af8Sopenharmony_ci } 120419b0af8Sopenharmony_ci local_irq_restore(irq_flags); 121419b0af8Sopenharmony_ci} 122419b0af8Sopenharmony_ci 123419b0af8Sopenharmony_civoid auth_exception_context(void *regs) 124419b0af8Sopenharmony_ci{ 125419b0af8Sopenharmony_ci unsigned long irq_flags; 126419b0af8Sopenharmony_ci local_irq_save(irq_flags); 127419b0af8Sopenharmony_ci if (compat_user_mode((struct pt_regs *)regs)) { 128419b0af8Sopenharmony_ci auth_compat_exception_context_asm(regs); 129419b0af8Sopenharmony_ci } else { 130419b0af8Sopenharmony_ci auth_exception_context_asm(regs); 131419b0af8Sopenharmony_ci } 132419b0af8Sopenharmony_ci local_irq_restore(irq_flags); 133419b0af8Sopenharmony_ci} 134