@@ -27,68 +27,90 @@ static bool riscv_insn_valid_32bit_offset(ptrdiff_t val)
2727#endif
2828}
2929
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 )
3156{
3257 if (v != (u32 )v ) {
3358 pr_err ("%s: value %016llx out of range for 32-bit field\n" ,
3459 me -> name , (long long )v );
3560 return - EINVAL ;
3661 }
37- * location = v ;
62+ * ( u32 * ) location = v ;
3863 return 0 ;
3964}
4065
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 )
4267{
4368 * (u64 * )location = v ;
4469 return 0 ;
4570}
4671
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 ,
4873 Elf_Addr v )
4974{
50- ptrdiff_t offset = (void * )v - ( void * ) location ;
75+ ptrdiff_t offset = (void * )v - location ;
5176 u32 imm12 = (offset & 0x1000 ) << (31 - 12 );
5277 u32 imm11 = (offset & 0x800 ) >> (11 - 7 );
5378 u32 imm10_5 = (offset & 0x7e0 ) << (30 - 10 );
5479 u32 imm4_1 = (offset & 0x1e ) << (11 - 4 );
5580
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 );
5882}
5983
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 ,
6185 Elf_Addr v )
6286{
63- ptrdiff_t offset = (void * )v - ( void * ) location ;
87+ ptrdiff_t offset = (void * )v - location ;
6488 u32 imm20 = (offset & 0x100000 ) << (31 - 20 );
6589 u32 imm19_12 = (offset & 0xff000 );
6690 u32 imm11 = (offset & 0x800 ) << (20 - 11 );
6791 u32 imm10_1 = (offset & 0x7fe ) << (30 - 10 );
6892
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 );
7194}
7295
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 ,
7497 Elf_Addr v )
7598{
76- ptrdiff_t offset = (void * )v - ( void * ) location ;
99+ ptrdiff_t offset = (void * )v - location ;
77100 u16 imm8 = (offset & 0x100 ) << (12 - 8 );
78101 u16 imm7_6 = (offset & 0xc0 ) >> (6 - 5 );
79102 u16 imm5 = (offset & 0x20 ) >> (5 - 2 );
80103 u16 imm4_3 = (offset & 0x18 ) << (12 - 5 );
81104 u16 imm2_1 = (offset & 0x6 ) << (12 - 10 );
82105
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 );
86108}
87109
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 ,
89111 Elf_Addr v )
90112{
91- ptrdiff_t offset = (void * )v - ( void * ) location ;
113+ ptrdiff_t offset = (void * )v - location ;
92114 u16 imm11 = (offset & 0x800 ) << (12 - 11 );
93115 u16 imm10 = (offset & 0x400 ) >> (10 - 8 );
94116 u16 imm9_8 = (offset & 0x300 ) << (12 - 11 );
@@ -98,16 +120,14 @@ static int apply_r_riscv_rvc_jump_rela(struct module *me, u32 *location,
98120 u16 imm4 = (offset & 0x10 ) << (12 - 5 );
99121 u16 imm3_1 = (offset & 0xe ) << (12 - 10 );
100122
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 );
104125}
105126
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 ,
107128 Elf_Addr v )
108129{
109- ptrdiff_t offset = (void * )v - (void * )location ;
110- s32 hi20 ;
130+ ptrdiff_t offset = (void * )v - location ;
111131
112132 if (!riscv_insn_valid_32bit_offset (offset )) {
113133 pr_err (
@@ -116,23 +136,20 @@ static int apply_r_riscv_pcrel_hi20_rela(struct module *me, u32 *location,
116136 return - EINVAL ;
117137 }
118138
119- hi20 = (offset + 0x800 ) & 0xfffff000 ;
120- * location = (* location & 0xfff ) | hi20 ;
121- return 0 ;
139+ return riscv_insn_rmw (location , 0xfff , (offset + 0x800 ) & 0xfffff000 );
122140}
123141
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 ,
125143 Elf_Addr v )
126144{
127145 /*
128146 * v is the lo12 value to fill. It is calculated before calling this
129147 * handler.
130148 */
131- * location = (* location & 0xfffff ) | ((v & 0xfff ) << 20 );
132- return 0 ;
149+ return riscv_insn_rmw (location , 0xfffff , (v & 0xfff ) << 20 );
133150}
134151
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 ,
136153 Elf_Addr v )
137154{
138155 /*
@@ -142,82 +159,72 @@ static int apply_r_riscv_pcrel_lo12_s_rela(struct module *me, u32 *location,
142159 u32 imm11_5 = (v & 0xfe0 ) << (31 - 11 );
143160 u32 imm4_0 = (v & 0x1f ) << (11 - 4 );
144161
145- * location = (* location & 0x1fff07f ) | imm11_5 | imm4_0 ;
146- return 0 ;
162+ return riscv_insn_rmw (location , 0x1fff07f , imm11_5 | imm4_0 );
147163}
148164
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 ,
150166 Elf_Addr v )
151167{
152- s32 hi20 ;
153-
154168 if (IS_ENABLED (CONFIG_CMODEL_MEDLOW )) {
155169 pr_err (
156170 "%s: target %016llx can not be addressed by the 32-bit offset from PC = %p\n" ,
157171 me -> name , (long long )v , location );
158172 return - EINVAL ;
159173 }
160174
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 );
164176}
165177
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 ,
167179 Elf_Addr v )
168180{
169181 /* Skip medlow checking because of filtering by HI20 already */
170182 s32 hi20 = ((s32 )v + 0x800 ) & 0xfffff000 ;
171183 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 ) ;
174186}
175187
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 ,
177189 Elf_Addr v )
178190{
179191 /* Skip medlow checking because of filtering by HI20 already */
180192 s32 hi20 = ((s32 )v + 0x800 ) & 0xfffff000 ;
181193 s32 lo12 = ((s32 )v - hi20 );
182194 u32 imm11_5 = (lo12 & 0xfe0 ) << (31 - 11 );
183195 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 ) ;
186198}
187199
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 ,
189201 Elf_Addr v )
190202{
191- ptrdiff_t offset = (void * )v - (void * )location ;
192- s32 hi20 ;
203+ ptrdiff_t offset = (void * )v - location ;
193204
194205 /* Always emit the got entry */
195206 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 ;
198208 } else {
199209 pr_err (
200210 "%s: can not generate the GOT entry for symbol = %016llx from PC = %p\n" ,
201211 me -> name , (long long )v , location );
202212 return - EINVAL ;
203213 }
204214
205- hi20 = (offset + 0x800 ) & 0xfffff000 ;
206- * location = (* location & 0xfff ) | hi20 ;
207- return 0 ;
215+ return riscv_insn_rmw (location , 0xfff , (offset + 0x800 ) & 0xfffff000 );
208216}
209217
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 ,
211219 Elf_Addr v )
212220{
213- ptrdiff_t offset = (void * )v - ( void * ) location ;
221+ ptrdiff_t offset = (void * )v - location ;
214222 u32 hi20 , lo12 ;
215223
216224 if (!riscv_insn_valid_32bit_offset (offset )) {
217225 /* Only emit the plt entry if offset over 32-bit range */
218226 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 ;
221228 } else {
222229 pr_err (
223230 "%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,
228235
229236 hi20 = (offset + 0x800 ) & 0xfffff000 ;
230237 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 );
234240}
235241
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 ,
237243 Elf_Addr v )
238244{
239- ptrdiff_t offset = (void * )v - ( void * ) location ;
245+ ptrdiff_t offset = (void * )v - location ;
240246 u32 hi20 , lo12 ;
241247
242248 if (!riscv_insn_valid_32bit_offset (offset )) {
@@ -248,18 +254,17 @@ static int apply_r_riscv_call_rela(struct module *me, u32 *location,
248254
249255 hi20 = (offset + 0x800 ) & 0xfffff000 ;
250256 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 );
254259}
255260
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 ,
257262 Elf_Addr v )
258263{
259264 return 0 ;
260265}
261266
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 ,
263268 Elf_Addr v )
264269{
265270 pr_err (
@@ -268,49 +273,49 @@ static int apply_r_riscv_align_rela(struct module *me, u32 *location,
268273 return - EINVAL ;
269274}
270275
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 ,
272277 Elf_Addr v )
273278{
274279 * (u16 * )location += (u16 )v ;
275280 return 0 ;
276281}
277282
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 ,
279284 Elf_Addr v )
280285{
281286 * (u32 * )location += (u32 )v ;
282287 return 0 ;
283288}
284289
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 ,
286291 Elf_Addr v )
287292{
288293 * (u64 * )location += (u64 )v ;
289294 return 0 ;
290295}
291296
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 ,
293298 Elf_Addr v )
294299{
295300 * (u16 * )location -= (u16 )v ;
296301 return 0 ;
297302}
298303
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 ,
300305 Elf_Addr v )
301306{
302307 * (u32 * )location -= (u32 )v ;
303308 return 0 ;
304309}
305310
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 ,
307312 Elf_Addr v )
308313{
309314 * (u64 * )location -= (u64 )v ;
310315 return 0 ;
311316}
312317
313- static int (* reloc_handlers_rela []) (struct module * me , u32 * location ,
318+ static int (* reloc_handlers_rela []) (struct module * me , void * location ,
314319 Elf_Addr v ) = {
315320 [R_RISCV_32 ] = apply_r_riscv_32_rela ,
316321 [R_RISCV_64 ] = apply_r_riscv_64_rela ,
@@ -342,9 +347,9 @@ int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
342347 struct module * me )
343348{
344349 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 );
346351 Elf_Sym * sym ;
347- u32 * location ;
352+ void * location ;
348353 unsigned int i , type ;
349354 Elf_Addr v ;
350355 int res ;
0 commit comments