• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (c) 2023 Huawei Device Co., Ltd.
4  */
5 
6 #include <asm/asm-offsets.h>
7 #include <asm/ptrace.h>
8 #include <linux/irqflags.h>
9 
10 /* The members of arrays below are corresponding to the enum defined in pointer_auth_context.h:
11  * enum pac_pt_regs {
12  *   REGS_X16 = 0,
13  *   REGS_X17,
14  *   REGS_LR,
15  *   REGS_SP,
16  *   REGS_PC,
17  *   REGS_PSTATE,
18  * };
19  *
20  * compat_regs_offset_array[]:
21  *   S_X14: the offset of compat_lr
22  *   S_X13: the offset of compat_sp
23  */
24 static off_t compat_regs_offset_array[] = {0, 0, S_X14, S_X13, S_PC, S_PSTATE};
25 static off_t regs_offset_array[] = {S_X16, S_X17, S_LR, S_SP, S_PC, S_PSTATE};
26 
set_compat_exception_context_register(void * regs,enum pac_pt_regs regs_enum,u64 val)27 int set_compat_exception_context_register(void *regs, enum pac_pt_regs regs_enum, u64 val)
28 {
29 	switch (regs_enum) {
30 	case REGS_LR:
31 	case REGS_SP:
32 	case REGS_PC:
33 	case REGS_PSTATE:
34 		return set_compat_exception_context_register_asm(regs, compat_regs_offset_array[regs_enum], val);
35 	default:
36 		return -EINVAL;
37 	}
38 }
39 
set_exception_context_register(void * regs,enum pac_pt_regs regs_enum,u64 val)40 int set_exception_context_register(void *regs, enum pac_pt_regs regs_enum, u64 val)
41 {
42 	if (compat_user_mode((struct pt_regs *)regs)) {
43 		return set_compat_exception_context_register(regs, regs_enum, val);
44 	} else {
45 		switch (regs_enum) {
46 		case REGS_X16:
47 		case REGS_X17:
48 		case REGS_LR:
49 		case REGS_SP:
50 		case REGS_PC:
51 		case REGS_PSTATE:
52 			return set_exception_context_register_asm(regs, regs_offset_array[regs_enum], val);
53 		default:
54 			return -EINVAL;
55 		}
56 	}
57 }
58 
set_compat_exception_context_register_index(struct pt_regs * regs,int index,uint64_t val)59 void set_compat_exception_context_register_index(struct pt_regs *regs, int index, uint64_t val)
60 {
61 	/* 14 means the index of compat_lr */
62 	if (index == 14) {
63 		set_compat_exception_context_register_asm(regs, S_X14, val);
64 	/* 13 means the index of compat_sp */
65 	} else if (index == 13) {
66 		set_compat_exception_context_register_asm(regs, S_X13, val);
67 	} else {
68 		regs->regs[index] = val;
69 	}
70 }
71 
set_exception_context_register_index(struct pt_regs * regs,int index,uint64_t val)72 void set_exception_context_register_index(struct pt_regs *regs, int index, uint64_t val)
73 {
74 	off_t offset;
75 
76 	if (compat_user_mode(regs)) {
77 		set_compat_exception_context_register_index(regs, index, val);
78 	} else {
79 		switch (index) {
80 		/* 16 means the index of regs[16] */
81 		case 16:
82 		/* 17 means the index of regs[17] */
83 		case 17:
84 		/* 30 means the index of regs[30] */
85 		case 30:
86 			offset = offsetof(struct pt_regs, regs[index]);
87 			set_exception_context_register_asm(regs, offset, val);
88 			break;
89 		default:
90 			regs->regs[index] = val;
91 		}
92 	}
93 }
94 
sign_compat_exception_context(void * regs)95 void sign_compat_exception_context(void *regs)
96 {
97 	unsigned long irq_flags;
98 	local_irq_save(irq_flags);
99 	sign_compat_exception_context_asm(regs);
100 	local_irq_restore(irq_flags);
101 }
102 
auth_compat_exception_context(void * regs)103 void auth_compat_exception_context(void *regs)
104 {
105 	unsigned long irq_flags;
106 	local_irq_save(irq_flags);
107 	auth_compat_exception_context_asm(regs);
108 	local_irq_restore(irq_flags);
109 }
110 
sign_exception_context(void * regs)111 void sign_exception_context(void *regs)
112 {
113 	unsigned long irq_flags;
114 	local_irq_save(irq_flags);
115 	if (compat_user_mode((struct pt_regs *)regs)) {
116 		sign_compat_exception_context_asm(regs);
117 	} else {
118 		sign_exception_context_asm(regs);
119 	}
120 	local_irq_restore(irq_flags);
121 }
122 
auth_exception_context(void * regs)123 void auth_exception_context(void *regs)
124 {
125 	unsigned long irq_flags;
126 	local_irq_save(irq_flags);
127 	if (compat_user_mode((struct pt_regs *)regs)) {
128 		auth_compat_exception_context_asm(regs);
129 	} else {
130 		auth_exception_context_asm(regs);
131 	}
132 	local_irq_restore(irq_flags);
133 }
134