Skip to content

Commit 9f58486

Browse files
brooniewilldeacon
authored andcommitted
arm64/sve: Make access to FFR optional
SME introduces streaming SVE mode in which FFR is not present and the instructions for accessing it UNDEF. In preparation for handling this update the low level SVE state access functions to take a flag specifying if FFR should be handled. When saving the register state we store a zero for FFR to guard against uninitialized data being read. No behaviour change should be introduced by this patch. Signed-off-by: Mark Brown <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Will Deacon <[email protected]>
1 parent 12cc235 commit 9f58486

File tree

5 files changed

+39
-22
lines changed

5 files changed

+39
-22
lines changed

arch/arm64/include/asm/fpsimd.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,10 @@ static inline void *sve_pffr(struct thread_struct *thread)
6565
return (char *)thread->sve_state + sve_ffr_offset(thread->sve_vl);
6666
}
6767

68-
extern void sve_save_state(void *state, u32 *pfpsr);
68+
extern void sve_save_state(void *state, u32 *pfpsr, int save_ffr);
6969
extern void sve_load_state(void const *state, u32 const *pfpsr,
70-
unsigned long vq_minus_1);
71-
extern void sve_flush_live(unsigned long vq_minus_1);
70+
int restore_ffr, unsigned long vq_minus_1);
71+
extern void sve_flush_live(bool flush_ffr, unsigned long vq_minus_1);
7272
extern unsigned int sve_get_vl(void);
7373
extern void sve_set_vq(unsigned long vq_minus_1);
7474

arch/arm64/include/asm/fpsimdmacros.h

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -217,28 +217,36 @@
217217
.macro sve_flush_z
218218
_for n, 0, 31, _sve_flush_z \n
219219
.endm
220-
.macro sve_flush_p_ffr
220+
.macro sve_flush_p
221221
_for n, 0, 15, _sve_pfalse \n
222+
.endm
223+
.macro sve_flush_ffr
222224
_sve_wrffr 0
223225
.endm
224226

225-
.macro sve_save nxbase, xpfpsr, nxtmp
227+
.macro sve_save nxbase, xpfpsr, save_ffr, nxtmp
226228
_for n, 0, 31, _sve_str_v \n, \nxbase, \n - 34
227229
_for n, 0, 15, _sve_str_p \n, \nxbase, \n - 16
230+
cbz \save_ffr, 921f
228231
_sve_rdffr 0
229232
_sve_str_p 0, \nxbase
230233
_sve_ldr_p 0, \nxbase, -16
231-
234+
b 922f
235+
921:
236+
str xzr, [x\nxbase] // Zero out FFR
237+
922:
232238
mrs x\nxtmp, fpsr
233239
str w\nxtmp, [\xpfpsr]
234240
mrs x\nxtmp, fpcr
235241
str w\nxtmp, [\xpfpsr, #4]
236242
.endm
237243

238-
.macro __sve_load nxbase, xpfpsr, nxtmp
244+
.macro __sve_load nxbase, xpfpsr, restore_ffr, nxtmp
239245
_for n, 0, 31, _sve_ldr_v \n, \nxbase, \n - 34
246+
cbz \restore_ffr, 921f
240247
_sve_ldr_p 0, \nxbase
241248
_sve_wrffr 0
249+
921:
242250
_for n, 0, 15, _sve_ldr_p \n, \nxbase, \n - 16
243251

244252
ldr w\nxtmp, [\xpfpsr]
@@ -247,7 +255,7 @@
247255
msr fpcr, x\nxtmp
248256
.endm
249257

250-
.macro sve_load nxbase, xpfpsr, xvqminus1, nxtmp, xtmp2
258+
.macro sve_load nxbase, xpfpsr, restore_ffr, xvqminus1, nxtmp, xtmp2
251259
sve_load_vq \xvqminus1, x\nxtmp, \xtmp2
252-
__sve_load \nxbase, \xpfpsr, \nxtmp
260+
__sve_load \nxbase, \xpfpsr, \restore_ffr, \nxtmp
253261
.endm

arch/arm64/kernel/entry-fpsimd.S

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,10 @@ SYM_FUNC_END(fpsimd_load_state)
3838
*
3939
* x0 - pointer to buffer for state
4040
* x1 - pointer to storage for FPSR
41+
* x2 - Save FFR if non-zero
4142
*/
4243
SYM_FUNC_START(sve_save_state)
43-
sve_save 0, x1, 2
44+
sve_save 0, x1, x2, 3
4445
ret
4546
SYM_FUNC_END(sve_save_state)
4647

@@ -49,10 +50,11 @@ SYM_FUNC_END(sve_save_state)
4950
*
5051
* x0 - pointer to buffer for state
5152
* x1 - pointer to storage for FPSR
52-
* x2 - VQ-1
53+
* x2 - Restore FFR if non-zero
54+
* x3 - VQ-1
5355
*/
5456
SYM_FUNC_START(sve_load_state)
55-
sve_load 0, x1, x2, 3, x4
57+
sve_load 0, x1, x2, x3, 4, x5
5658
ret
5759
SYM_FUNC_END(sve_load_state)
5860

@@ -72,13 +74,16 @@ SYM_FUNC_END(sve_set_vq)
7274
* VQ must already be configured by caller, any further updates of VQ
7375
* will need to ensure that the register state remains valid.
7476
*
75-
* x0 = VQ - 1
77+
* x0 = include FFR?
78+
* x1 = VQ - 1
7679
*/
7780
SYM_FUNC_START(sve_flush_live)
78-
cbz x0, 1f // A VQ-1 of 0 is 128 bits so no extra Z state
81+
cbz x1, 1f // A VQ-1 of 0 is 128 bits so no extra Z state
7982
sve_flush_z
80-
1: sve_flush_p_ffr
81-
ret
83+
1: sve_flush_p
84+
tbz x0, #0, 2f
85+
sve_flush_ffr
86+
2: ret
8287
SYM_FUNC_END(sve_flush_live)
8388

8489
#endif /* CONFIG_ARM64_SVE */

arch/arm64/kernel/fpsimd.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,7 @@ static void task_fpsimd_load(void)
289289

290290
if (IS_ENABLED(CONFIG_ARM64_SVE) && test_thread_flag(TIF_SVE))
291291
sve_load_state(sve_pffr(&current->thread),
292-
&current->thread.uw.fpsimd_state.fpsr,
292+
&current->thread.uw.fpsimd_state.fpsr, true,
293293
sve_vq_from_vl(current->thread.sve_vl) - 1);
294294
else
295295
fpsimd_load_state(&current->thread.uw.fpsimd_state);
@@ -325,7 +325,7 @@ static void fpsimd_save(void)
325325

326326
sve_save_state((char *)last->sve_state +
327327
sve_ffr_offset(last->sve_vl),
328-
&last->st->fpsr);
328+
&last->st->fpsr, true);
329329
} else {
330330
fpsimd_save_state(last->st);
331331
}
@@ -962,7 +962,7 @@ void do_sve_acc(unsigned int esr, struct pt_regs *regs)
962962
unsigned long vq_minus_one =
963963
sve_vq_from_vl(current->thread.sve_vl) - 1;
964964
sve_set_vq(vq_minus_one);
965-
sve_flush_live(vq_minus_one);
965+
sve_flush_live(true, vq_minus_one);
966966
fpsimd_bind_task_to_cpu();
967967
} else {
968968
fpsimd_to_sve(current);
@@ -1356,7 +1356,8 @@ void __efi_fpsimd_begin(void)
13561356
__this_cpu_write(efi_sve_state_used, true);
13571357

13581358
sve_save_state(sve_state + sve_ffr_offset(sve_max_vl),
1359-
&this_cpu_ptr(&efi_fpsimd_state)->fpsr);
1359+
&this_cpu_ptr(&efi_fpsimd_state)->fpsr,
1360+
true);
13601361
} else {
13611362
fpsimd_save_state(this_cpu_ptr(&efi_fpsimd_state));
13621363
}
@@ -1382,6 +1383,7 @@ void __efi_fpsimd_end(void)
13821383

13831384
sve_load_state(sve_state + sve_ffr_offset(sve_max_vl),
13841385
&this_cpu_ptr(&efi_fpsimd_state)->fpsr,
1386+
true,
13851387
sve_vq_from_vl(sve_get_vl()) - 1);
13861388

13871389
__this_cpu_write(efi_sve_state_used, false);

arch/arm64/kvm/hyp/fpsimd.S

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,13 @@ SYM_FUNC_START(__fpsimd_restore_state)
2121
SYM_FUNC_END(__fpsimd_restore_state)
2222

2323
SYM_FUNC_START(__sve_restore_state)
24-
__sve_load 0, x1, 2
24+
mov x2, #1
25+
__sve_load 0, x1, x2, 3
2526
ret
2627
SYM_FUNC_END(__sve_restore_state)
2728

2829
SYM_FUNC_START(__sve_save_state)
29-
sve_save 0, x1, 2
30+
mov x2, #1
31+
sve_save 0, x1, x2, 3
3032
ret
3133
SYM_FUNC_END(__sve_save_state)

0 commit comments

Comments
 (0)