@@ -27,68 +27,90 @@ static bool riscv_insn_valid_32bit_offset(ptrdiff_t val)
27
27
#endif
28
28
}
29
29
30
- static int apply_r_riscv_32_rela (struct module * me , u32 * location , Elf_Addr v )
30
+ static int riscv_insn_rmw (void * location , u32 keep , u32 set )
31
+ {
32
+ u16 * parcel = location ;
33
+ u32 insn = (u32 )le16_to_cpu (parcel [0 ]) | (u32 )le16_to_cpu (parcel [1 ]) << 16 ;
34
+
35
+ insn &= keep ;
36
+ insn |= set ;
37
+
38
+ parcel [0 ] = cpu_to_le16 (insn );
39
+ parcel [1 ] = cpu_to_le16 (insn >> 16 );
40
+ return 0 ;
41
+ }
42
+
43
+ static int riscv_insn_rvc_rmw (void * location , u16 keep , u16 set )
44
+ {
45
+ u16 * parcel = location ;
46
+ u16 insn = le16_to_cpu (* parcel );
47
+
48
+ insn &= keep ;
49
+ insn |= set ;
50
+
51
+ * parcel = cpu_to_le16 (insn );
52
+ return 0 ;
53
+ }
54
+
55
+ static int apply_r_riscv_32_rela (struct module * me , void * location , Elf_Addr v )
31
56
{
32
57
if (v != (u32 )v ) {
33
58
pr_err ("%s: value %016llx out of range for 32-bit field\n" ,
34
59
me -> name , (long long )v );
35
60
return - EINVAL ;
36
61
}
37
- * location = v ;
62
+ * ( u32 * ) location = v ;
38
63
return 0 ;
39
64
}
40
65
41
- static int apply_r_riscv_64_rela (struct module * me , u32 * location , Elf_Addr v )
66
+ static int apply_r_riscv_64_rela (struct module * me , void * location , Elf_Addr v )
42
67
{
43
68
* (u64 * )location = v ;
44
69
return 0 ;
45
70
}
46
71
47
- static int apply_r_riscv_branch_rela (struct module * me , u32 * location ,
72
+ static int apply_r_riscv_branch_rela (struct module * me , void * location ,
48
73
Elf_Addr v )
49
74
{
50
- ptrdiff_t offset = (void * )v - ( void * ) location ;
75
+ ptrdiff_t offset = (void * )v - location ;
51
76
u32 imm12 = (offset & 0x1000 ) << (31 - 12 );
52
77
u32 imm11 = (offset & 0x800 ) >> (11 - 7 );
53
78
u32 imm10_5 = (offset & 0x7e0 ) << (30 - 10 );
54
79
u32 imm4_1 = (offset & 0x1e ) << (11 - 4 );
55
80
56
- * location = (* location & 0x1fff07f ) | imm12 | imm11 | imm10_5 | imm4_1 ;
57
- return 0 ;
81
+ return riscv_insn_rmw (location , 0x1fff07f , imm12 | imm11 | imm10_5 | imm4_1 );
58
82
}
59
83
60
- static int apply_r_riscv_jal_rela (struct module * me , u32 * location ,
84
+ static int apply_r_riscv_jal_rela (struct module * me , void * location ,
61
85
Elf_Addr v )
62
86
{
63
- ptrdiff_t offset = (void * )v - ( void * ) location ;
87
+ ptrdiff_t offset = (void * )v - location ;
64
88
u32 imm20 = (offset & 0x100000 ) << (31 - 20 );
65
89
u32 imm19_12 = (offset & 0xff000 );
66
90
u32 imm11 = (offset & 0x800 ) << (20 - 11 );
67
91
u32 imm10_1 = (offset & 0x7fe ) << (30 - 10 );
68
92
69
- * location = (* location & 0xfff ) | imm20 | imm19_12 | imm11 | imm10_1 ;
70
- return 0 ;
93
+ return riscv_insn_rmw (location , 0xfff , imm20 | imm19_12 | imm11 | imm10_1 );
71
94
}
72
95
73
- static int apply_r_riscv_rvc_branch_rela (struct module * me , u32 * location ,
96
+ static int apply_r_riscv_rvc_branch_rela (struct module * me , void * location ,
74
97
Elf_Addr v )
75
98
{
76
- ptrdiff_t offset = (void * )v - ( void * ) location ;
99
+ ptrdiff_t offset = (void * )v - location ;
77
100
u16 imm8 = (offset & 0x100 ) << (12 - 8 );
78
101
u16 imm7_6 = (offset & 0xc0 ) >> (6 - 5 );
79
102
u16 imm5 = (offset & 0x20 ) >> (5 - 2 );
80
103
u16 imm4_3 = (offset & 0x18 ) << (12 - 5 );
81
104
u16 imm2_1 = (offset & 0x6 ) << (12 - 10 );
82
105
83
- * (u16 * )location = (* (u16 * )location & 0xe383 ) |
84
- imm8 | imm7_6 | imm5 | imm4_3 | imm2_1 ;
85
- return 0 ;
106
+ return riscv_insn_rvc_rmw (location , 0xe383 ,
107
+ imm8 | imm7_6 | imm5 | imm4_3 | imm2_1 );
86
108
}
87
109
88
- static int apply_r_riscv_rvc_jump_rela (struct module * me , u32 * location ,
110
+ static int apply_r_riscv_rvc_jump_rela (struct module * me , void * location ,
89
111
Elf_Addr v )
90
112
{
91
- ptrdiff_t offset = (void * )v - ( void * ) location ;
113
+ ptrdiff_t offset = (void * )v - location ;
92
114
u16 imm11 = (offset & 0x800 ) << (12 - 11 );
93
115
u16 imm10 = (offset & 0x400 ) >> (10 - 8 );
94
116
u16 imm9_8 = (offset & 0x300 ) << (12 - 11 );
@@ -98,16 +120,14 @@ static int apply_r_riscv_rvc_jump_rela(struct module *me, u32 *location,
98
120
u16 imm4 = (offset & 0x10 ) << (12 - 5 );
99
121
u16 imm3_1 = (offset & 0xe ) << (12 - 10 );
100
122
101
- * (u16 * )location = (* (u16 * )location & 0xe003 ) |
102
- imm11 | imm10 | imm9_8 | imm7 | imm6 | imm5 | imm4 | imm3_1 ;
103
- return 0 ;
123
+ return riscv_insn_rvc_rmw (location , 0xe003 ,
124
+ imm11 | imm10 | imm9_8 | imm7 | imm6 | imm5 | imm4 | imm3_1 );
104
125
}
105
126
106
- static int apply_r_riscv_pcrel_hi20_rela (struct module * me , u32 * location ,
127
+ static int apply_r_riscv_pcrel_hi20_rela (struct module * me , void * location ,
107
128
Elf_Addr v )
108
129
{
109
- ptrdiff_t offset = (void * )v - (void * )location ;
110
- s32 hi20 ;
130
+ ptrdiff_t offset = (void * )v - location ;
111
131
112
132
if (!riscv_insn_valid_32bit_offset (offset )) {
113
133
pr_err (
@@ -116,23 +136,20 @@ static int apply_r_riscv_pcrel_hi20_rela(struct module *me, u32 *location,
116
136
return - EINVAL ;
117
137
}
118
138
119
- hi20 = (offset + 0x800 ) & 0xfffff000 ;
120
- * location = (* location & 0xfff ) | hi20 ;
121
- return 0 ;
139
+ return riscv_insn_rmw (location , 0xfff , (offset + 0x800 ) & 0xfffff000 );
122
140
}
123
141
124
- static int apply_r_riscv_pcrel_lo12_i_rela (struct module * me , u32 * location ,
142
+ static int apply_r_riscv_pcrel_lo12_i_rela (struct module * me , void * location ,
125
143
Elf_Addr v )
126
144
{
127
145
/*
128
146
* v is the lo12 value to fill. It is calculated before calling this
129
147
* handler.
130
148
*/
131
- * location = (* location & 0xfffff ) | ((v & 0xfff ) << 20 );
132
- return 0 ;
149
+ return riscv_insn_rmw (location , 0xfffff , (v & 0xfff ) << 20 );
133
150
}
134
151
135
- static int apply_r_riscv_pcrel_lo12_s_rela (struct module * me , u32 * location ,
152
+ static int apply_r_riscv_pcrel_lo12_s_rela (struct module * me , void * location ,
136
153
Elf_Addr v )
137
154
{
138
155
/*
@@ -142,82 +159,72 @@ static int apply_r_riscv_pcrel_lo12_s_rela(struct module *me, u32 *location,
142
159
u32 imm11_5 = (v & 0xfe0 ) << (31 - 11 );
143
160
u32 imm4_0 = (v & 0x1f ) << (11 - 4 );
144
161
145
- * location = (* location & 0x1fff07f ) | imm11_5 | imm4_0 ;
146
- return 0 ;
162
+ return riscv_insn_rmw (location , 0x1fff07f , imm11_5 | imm4_0 );
147
163
}
148
164
149
- static int apply_r_riscv_hi20_rela (struct module * me , u32 * location ,
165
+ static int apply_r_riscv_hi20_rela (struct module * me , void * location ,
150
166
Elf_Addr v )
151
167
{
152
- s32 hi20 ;
153
-
154
168
if (IS_ENABLED (CONFIG_CMODEL_MEDLOW )) {
155
169
pr_err (
156
170
"%s: target %016llx can not be addressed by the 32-bit offset from PC = %p\n" ,
157
171
me -> name , (long long )v , location );
158
172
return - EINVAL ;
159
173
}
160
174
161
- hi20 = ((s32 )v + 0x800 ) & 0xfffff000 ;
162
- * location = (* location & 0xfff ) | hi20 ;
163
- return 0 ;
175
+ return riscv_insn_rmw (location , 0xfff , ((s32 )v + 0x800 ) & 0xfffff000 );
164
176
}
165
177
166
- static int apply_r_riscv_lo12_i_rela (struct module * me , u32 * location ,
178
+ static int apply_r_riscv_lo12_i_rela (struct module * me , void * location ,
167
179
Elf_Addr v )
168
180
{
169
181
/* Skip medlow checking because of filtering by HI20 already */
170
182
s32 hi20 = ((s32 )v + 0x800 ) & 0xfffff000 ;
171
183
s32 lo12 = ((s32 )v - hi20 );
172
- * location = ( * location & 0xfffff ) | (( lo12 & 0xfff ) << 20 );
173
- return 0 ;
184
+
185
+ return riscv_insn_rmw ( location , 0xfffff , ( lo12 & 0xfff ) << 20 ) ;
174
186
}
175
187
176
- static int apply_r_riscv_lo12_s_rela (struct module * me , u32 * location ,
188
+ static int apply_r_riscv_lo12_s_rela (struct module * me , void * location ,
177
189
Elf_Addr v )
178
190
{
179
191
/* Skip medlow checking because of filtering by HI20 already */
180
192
s32 hi20 = ((s32 )v + 0x800 ) & 0xfffff000 ;
181
193
s32 lo12 = ((s32 )v - hi20 );
182
194
u32 imm11_5 = (lo12 & 0xfe0 ) << (31 - 11 );
183
195
u32 imm4_0 = (lo12 & 0x1f ) << (11 - 4 );
184
- * location = ( * location & 0x1fff07f ) | imm11_5 | imm4_0 ;
185
- return 0 ;
196
+
197
+ return riscv_insn_rmw ( location , 0x1fff07f , imm11_5 | imm4_0 ) ;
186
198
}
187
199
188
- static int apply_r_riscv_got_hi20_rela (struct module * me , u32 * location ,
200
+ static int apply_r_riscv_got_hi20_rela (struct module * me , void * location ,
189
201
Elf_Addr v )
190
202
{
191
- ptrdiff_t offset = (void * )v - (void * )location ;
192
- s32 hi20 ;
203
+ ptrdiff_t offset = (void * )v - location ;
193
204
194
205
/* Always emit the got entry */
195
206
if (IS_ENABLED (CONFIG_MODULE_SECTIONS )) {
196
- offset = module_emit_got_entry (me , v );
197
- offset = (void * )offset - (void * )location ;
207
+ offset = (void * )module_emit_got_entry (me , v ) - location ;
198
208
} else {
199
209
pr_err (
200
210
"%s: can not generate the GOT entry for symbol = %016llx from PC = %p\n" ,
201
211
me -> name , (long long )v , location );
202
212
return - EINVAL ;
203
213
}
204
214
205
- hi20 = (offset + 0x800 ) & 0xfffff000 ;
206
- * location = (* location & 0xfff ) | hi20 ;
207
- return 0 ;
215
+ return riscv_insn_rmw (location , 0xfff , (offset + 0x800 ) & 0xfffff000 );
208
216
}
209
217
210
- static int apply_r_riscv_call_plt_rela (struct module * me , u32 * location ,
218
+ static int apply_r_riscv_call_plt_rela (struct module * me , void * location ,
211
219
Elf_Addr v )
212
220
{
213
- ptrdiff_t offset = (void * )v - ( void * ) location ;
221
+ ptrdiff_t offset = (void * )v - location ;
214
222
u32 hi20 , lo12 ;
215
223
216
224
if (!riscv_insn_valid_32bit_offset (offset )) {
217
225
/* Only emit the plt entry if offset over 32-bit range */
218
226
if (IS_ENABLED (CONFIG_MODULE_SECTIONS )) {
219
- offset = module_emit_plt_entry (me , v );
220
- offset = (void * )offset - (void * )location ;
227
+ offset = (void * )module_emit_plt_entry (me , v ) - location ;
221
228
} else {
222
229
pr_err (
223
230
"%s: target %016llx can not be addressed by the 32-bit offset from PC = %p\n" ,
@@ -228,15 +235,14 @@ static int apply_r_riscv_call_plt_rela(struct module *me, u32 *location,
228
235
229
236
hi20 = (offset + 0x800 ) & 0xfffff000 ;
230
237
lo12 = (offset - hi20 ) & 0xfff ;
231
- * location = (* location & 0xfff ) | hi20 ;
232
- * (location + 1 ) = (* (location + 1 ) & 0xfffff ) | (lo12 << 20 );
233
- return 0 ;
238
+ riscv_insn_rmw (location , 0xfff , hi20 );
239
+ return riscv_insn_rmw (location + 4 , 0xfffff , lo12 << 20 );
234
240
}
235
241
236
- static int apply_r_riscv_call_rela (struct module * me , u32 * location ,
242
+ static int apply_r_riscv_call_rela (struct module * me , void * location ,
237
243
Elf_Addr v )
238
244
{
239
- ptrdiff_t offset = (void * )v - ( void * ) location ;
245
+ ptrdiff_t offset = (void * )v - location ;
240
246
u32 hi20 , lo12 ;
241
247
242
248
if (!riscv_insn_valid_32bit_offset (offset )) {
@@ -248,18 +254,17 @@ static int apply_r_riscv_call_rela(struct module *me, u32 *location,
248
254
249
255
hi20 = (offset + 0x800 ) & 0xfffff000 ;
250
256
lo12 = (offset - hi20 ) & 0xfff ;
251
- * location = (* location & 0xfff ) | hi20 ;
252
- * (location + 1 ) = (* (location + 1 ) & 0xfffff ) | (lo12 << 20 );
253
- return 0 ;
257
+ riscv_insn_rmw (location , 0xfff , hi20 );
258
+ return riscv_insn_rmw (location + 4 , 0xfffff , lo12 << 20 );
254
259
}
255
260
256
- static int apply_r_riscv_relax_rela (struct module * me , u32 * location ,
261
+ static int apply_r_riscv_relax_rela (struct module * me , void * location ,
257
262
Elf_Addr v )
258
263
{
259
264
return 0 ;
260
265
}
261
266
262
- static int apply_r_riscv_align_rela (struct module * me , u32 * location ,
267
+ static int apply_r_riscv_align_rela (struct module * me , void * location ,
263
268
Elf_Addr v )
264
269
{
265
270
pr_err (
@@ -268,49 +273,49 @@ static int apply_r_riscv_align_rela(struct module *me, u32 *location,
268
273
return - EINVAL ;
269
274
}
270
275
271
- static int apply_r_riscv_add16_rela (struct module * me , u32 * location ,
276
+ static int apply_r_riscv_add16_rela (struct module * me , void * location ,
272
277
Elf_Addr v )
273
278
{
274
279
* (u16 * )location += (u16 )v ;
275
280
return 0 ;
276
281
}
277
282
278
- static int apply_r_riscv_add32_rela (struct module * me , u32 * location ,
283
+ static int apply_r_riscv_add32_rela (struct module * me , void * location ,
279
284
Elf_Addr v )
280
285
{
281
286
* (u32 * )location += (u32 )v ;
282
287
return 0 ;
283
288
}
284
289
285
- static int apply_r_riscv_add64_rela (struct module * me , u32 * location ,
290
+ static int apply_r_riscv_add64_rela (struct module * me , void * location ,
286
291
Elf_Addr v )
287
292
{
288
293
* (u64 * )location += (u64 )v ;
289
294
return 0 ;
290
295
}
291
296
292
- static int apply_r_riscv_sub16_rela (struct module * me , u32 * location ,
297
+ static int apply_r_riscv_sub16_rela (struct module * me , void * location ,
293
298
Elf_Addr v )
294
299
{
295
300
* (u16 * )location -= (u16 )v ;
296
301
return 0 ;
297
302
}
298
303
299
- static int apply_r_riscv_sub32_rela (struct module * me , u32 * location ,
304
+ static int apply_r_riscv_sub32_rela (struct module * me , void * location ,
300
305
Elf_Addr v )
301
306
{
302
307
* (u32 * )location -= (u32 )v ;
303
308
return 0 ;
304
309
}
305
310
306
- static int apply_r_riscv_sub64_rela (struct module * me , u32 * location ,
311
+ static int apply_r_riscv_sub64_rela (struct module * me , void * location ,
307
312
Elf_Addr v )
308
313
{
309
314
* (u64 * )location -= (u64 )v ;
310
315
return 0 ;
311
316
}
312
317
313
- static int (* reloc_handlers_rela []) (struct module * me , u32 * location ,
318
+ static int (* reloc_handlers_rela []) (struct module * me , void * location ,
314
319
Elf_Addr v ) = {
315
320
[R_RISCV_32 ] = apply_r_riscv_32_rela ,
316
321
[R_RISCV_64 ] = apply_r_riscv_64_rela ,
@@ -342,9 +347,9 @@ int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
342
347
struct module * me )
343
348
{
344
349
Elf_Rela * rel = (void * ) sechdrs [relsec ].sh_addr ;
345
- int (* handler )(struct module * me , u32 * location , Elf_Addr v );
350
+ int (* handler )(struct module * me , void * location , Elf_Addr v );
346
351
Elf_Sym * sym ;
347
- u32 * location ;
352
+ void * location ;
348
353
unsigned int i , type ;
349
354
Elf_Addr v ;
350
355
int res ;
0 commit comments