118
118
* returned from the 2nd syscall yet, TIF_FOREIGN_FPSTATE is still set so
119
119
* whatever is in the FPSIMD registers is not saved to memory, but discarded.
120
120
*/
121
- struct fpsimd_last_state_struct {
122
- struct user_fpsimd_state * st ;
123
- void * sve_state ;
124
- void * za_state ;
125
- u64 * svcr ;
126
- unsigned int sve_vl ;
127
- unsigned int sme_vl ;
128
- };
129
121
130
- static DEFINE_PER_CPU (struct fpsimd_last_state_struct , fpsimd_last_state ) ;
122
+ static DEFINE_PER_CPU (struct cpu_fp_state , fpsimd_last_state ) ;
131
123
132
124
__ro_after_init struct vl_info vl_info [ARM64_VEC_MAX ] = {
133
125
#ifdef CONFIG_ARM64_SVE
@@ -330,15 +322,6 @@ void task_set_vl_onexec(struct task_struct *task, enum vec_type type,
330
322
* The task can execute SVE instructions while in userspace without
331
323
* trapping to the kernel.
332
324
*
333
- * When stored, Z0-Z31 (incorporating Vn in bits[127:0] or the
334
- * corresponding Zn), P0-P15 and FFR are encoded in
335
- * task->thread.sve_state, formatted appropriately for vector
336
- * length task->thread.sve_vl or, if SVCR.SM is set,
337
- * task->thread.sme_vl.
338
- *
339
- * task->thread.sve_state must point to a valid buffer at least
340
- * sve_state_size(task) bytes in size.
341
- *
342
325
* During any syscall, the kernel may optionally clear TIF_SVE and
343
326
* discard the vector state except for the FPSIMD subset.
344
327
*
@@ -348,15 +331,39 @@ void task_set_vl_onexec(struct task_struct *task, enum vec_type type,
348
331
* do_sve_acc() to be called, which does some preparation and then
349
332
* sets TIF_SVE.
350
333
*
351
- * When stored, FPSIMD registers V0-V31 are encoded in
334
+ * During any syscall, the kernel may optionally clear TIF_SVE and
335
+ * discard the vector state except for the FPSIMD subset.
336
+ *
337
+ * The data will be stored in one of two formats:
338
+ *
339
+ * * FPSIMD only - FP_STATE_FPSIMD:
340
+ *
341
+ * When the FPSIMD only state stored task->thread.fp_type is set to
342
+ * FP_STATE_FPSIMD, the FPSIMD registers V0-V31 are encoded in
352
343
* task->thread.uw.fpsimd_state; bits [max : 128] for each of Z0-Z31 are
353
344
* logically zero but not stored anywhere; P0-P15 and FFR are not
354
345
* stored and have unspecified values from userspace's point of
355
346
* view. For hygiene purposes, the kernel zeroes them on next use,
356
347
* but userspace is discouraged from relying on this.
357
348
*
358
349
* task->thread.sve_state does not need to be non-NULL, valid or any
359
- * particular size: it must not be dereferenced.
350
+ * particular size: it must not be dereferenced and any data stored
351
+ * there should be considered stale and not referenced.
352
+ *
353
+ * * SVE state - FP_STATE_SVE:
354
+ *
355
+ * When the full SVE state is stored task->thread.fp_type is set to
356
+ * FP_STATE_SVE and Z0-Z31 (incorporating Vn in bits[127:0] or the
357
+ * corresponding Zn), P0-P15 and FFR are encoded in in
358
+ * task->thread.sve_state, formatted appropriately for vector
359
+ * length task->thread.sve_vl or, if SVCR.SM is set,
360
+ * task->thread.sme_vl. The storage for the vector registers in
361
+ * task->thread.uw.fpsimd_state should be ignored.
362
+ *
363
+ * task->thread.sve_state must point to a valid buffer at least
364
+ * sve_state_size(task) bytes in size. The data stored in
365
+ * task->thread.uw.fpsimd_state.vregs should be considered stale
366
+ * and not referenced.
360
367
*
361
368
* * FPSR and FPCR are always stored in task->thread.uw.fpsimd_state
362
369
* irrespective of whether TIF_SVE is clear or set, since these are
@@ -378,11 +385,37 @@ static void task_fpsimd_load(void)
378
385
WARN_ON (!system_supports_fpsimd ());
379
386
WARN_ON (!have_cpu_fpsimd_context ());
380
387
381
- /* Check if we should restore SVE first */
382
- if (IS_ENABLED (CONFIG_ARM64_SVE ) && test_thread_flag (TIF_SVE )) {
383
- sve_set_vq (sve_vq_from_vl (task_get_sve_vl (current )) - 1 );
384
- restore_sve_regs = true;
385
- restore_ffr = true;
388
+ if (system_supports_sve ()) {
389
+ switch (current -> thread .fp_type ) {
390
+ case FP_STATE_FPSIMD :
391
+ /* Stop tracking SVE for this task until next use. */
392
+ if (test_and_clear_thread_flag (TIF_SVE ))
393
+ sve_user_disable ();
394
+ break ;
395
+ case FP_STATE_SVE :
396
+ if (!thread_sm_enabled (& current -> thread ) &&
397
+ !WARN_ON_ONCE (!test_and_set_thread_flag (TIF_SVE )))
398
+ sve_user_enable ();
399
+
400
+ if (test_thread_flag (TIF_SVE ))
401
+ sve_set_vq (sve_vq_from_vl (task_get_sve_vl (current )) - 1 );
402
+
403
+ restore_sve_regs = true;
404
+ restore_ffr = true;
405
+ break ;
406
+ default :
407
+ /*
408
+ * This indicates either a bug in
409
+ * fpsimd_save() or memory corruption, we
410
+ * should always record an explicit format
411
+ * when we save. We always at least have the
412
+ * memory allocated for FPSMID registers so
413
+ * try that and hope for the best.
414
+ */
415
+ WARN_ON_ONCE (1 );
416
+ clear_thread_flag (TIF_SVE );
417
+ break ;
418
+ }
386
419
}
387
420
388
421
/* Restore SME, override SVE register configuration if needed */
@@ -398,18 +431,19 @@ static void task_fpsimd_load(void)
398
431
if (thread_za_enabled (& current -> thread ))
399
432
za_load_state (current -> thread .za_state );
400
433
401
- if (thread_sm_enabled (& current -> thread )) {
402
- restore_sve_regs = true;
434
+ if (thread_sm_enabled (& current -> thread ))
403
435
restore_ffr = system_supports_fa64 ();
404
- }
405
436
}
406
437
407
- if (restore_sve_regs )
438
+ if (restore_sve_regs ) {
439
+ WARN_ON_ONCE (current -> thread .fp_type != FP_STATE_SVE );
408
440
sve_load_state (sve_pffr (& current -> thread ),
409
441
& current -> thread .uw .fpsimd_state .fpsr ,
410
442
restore_ffr );
411
- else
443
+ } else {
444
+ WARN_ON_ONCE (current -> thread .fp_type != FP_STATE_FPSIMD );
412
445
fpsimd_load_state (& current -> thread .uw .fpsimd_state );
446
+ }
413
447
}
414
448
415
449
/*
@@ -419,12 +453,12 @@ static void task_fpsimd_load(void)
419
453
* last, if KVM is involved this may be the guest VM context rather
420
454
* than the host thread for the VM pointed to by current. This means
421
455
* that we must always reference the state storage via last rather
422
- * than via current, other than the TIF_ flags which KVM will
423
- * carefully maintain for us .
456
+ * than via current, if we are saving KVM state then it will have
457
+ * ensured that the type of registers to save is set in last->to_save .
424
458
*/
425
459
static void fpsimd_save (void )
426
460
{
427
- struct fpsimd_last_state_struct const * last =
461
+ struct cpu_fp_state const * last =
428
462
this_cpu_ptr (& fpsimd_last_state );
429
463
/* set by fpsimd_bind_task_to_cpu() or fpsimd_bind_state_to_cpu() */
430
464
bool save_sve_regs = false;
@@ -437,7 +471,14 @@ static void fpsimd_save(void)
437
471
if (test_thread_flag (TIF_FOREIGN_FPSTATE ))
438
472
return ;
439
473
440
- if (test_thread_flag (TIF_SVE )) {
474
+ /*
475
+ * If a task is in a syscall the ABI allows us to only
476
+ * preserve the state shared with FPSIMD so don't bother
477
+ * saving the full SVE state in that case.
478
+ */
479
+ if ((last -> to_save == FP_STATE_CURRENT && test_thread_flag (TIF_SVE ) &&
480
+ !in_syscall (current_pt_regs ())) ||
481
+ last -> to_save == FP_STATE_SVE ) {
441
482
save_sve_regs = true;
442
483
save_ffr = true;
443
484
vl = last -> sve_vl ;
@@ -474,8 +515,10 @@ static void fpsimd_save(void)
474
515
sve_save_state ((char * )last -> sve_state +
475
516
sve_ffr_offset (vl ),
476
517
& last -> st -> fpsr , save_ffr );
518
+ * last -> fp_type = FP_STATE_SVE ;
477
519
} else {
478
520
fpsimd_save_state (last -> st );
521
+ * last -> fp_type = FP_STATE_FPSIMD ;
479
522
}
480
523
}
481
524
@@ -768,8 +811,7 @@ void fpsimd_sync_to_sve(struct task_struct *task)
768
811
*/
769
812
void sve_sync_to_fpsimd (struct task_struct * task )
770
813
{
771
- if (test_tsk_thread_flag (task , TIF_SVE ) ||
772
- thread_sm_enabled (& task -> thread ))
814
+ if (task -> thread .fp_type == FP_STATE_SVE )
773
815
sve_to_fpsimd (task );
774
816
}
775
817
@@ -848,8 +890,10 @@ int vec_set_vector_length(struct task_struct *task, enum vec_type type,
848
890
849
891
fpsimd_flush_task_state (task );
850
892
if (test_and_clear_tsk_thread_flag (task , TIF_SVE ) ||
851
- thread_sm_enabled (& task -> thread ))
893
+ thread_sm_enabled (& task -> thread )) {
852
894
sve_to_fpsimd (task );
895
+ task -> thread .fp_type = FP_STATE_FPSIMD ;
896
+ }
853
897
854
898
if (system_supports_sme () && type == ARM64_VEC_SME ) {
855
899
task -> thread .svcr &= ~(SVCR_SM_MASK |
@@ -1368,6 +1412,7 @@ static void sve_init_regs(void)
1368
1412
fpsimd_bind_task_to_cpu ();
1369
1413
} else {
1370
1414
fpsimd_to_sve (current );
1415
+ current -> thread .fp_type = FP_STATE_SVE ;
1371
1416
}
1372
1417
}
1373
1418
@@ -1596,6 +1641,8 @@ void fpsimd_flush_thread(void)
1596
1641
current -> thread .svcr = 0 ;
1597
1642
}
1598
1643
1644
+ current -> thread .fp_type = FP_STATE_FPSIMD ;
1645
+
1599
1646
put_cpu_fpsimd_context ();
1600
1647
kfree (sve_state );
1601
1648
kfree (za_state );
@@ -1627,15 +1674,39 @@ void fpsimd_signal_preserve_current_state(void)
1627
1674
sve_to_fpsimd (current );
1628
1675
}
1629
1676
1677
+ /*
1678
+ * Called by KVM when entering the guest.
1679
+ */
1680
+ void fpsimd_kvm_prepare (void )
1681
+ {
1682
+ if (!system_supports_sve ())
1683
+ return ;
1684
+
1685
+ /*
1686
+ * KVM does not save host SVE state since we can only enter
1687
+ * the guest from a syscall so the ABI means that only the
1688
+ * non-saved SVE state needs to be saved. If we have left
1689
+ * SVE enabled for performance reasons then update the task
1690
+ * state to be FPSIMD only.
1691
+ */
1692
+ get_cpu_fpsimd_context ();
1693
+
1694
+ if (test_and_clear_thread_flag (TIF_SVE )) {
1695
+ sve_to_fpsimd (current );
1696
+ current -> thread .fp_type = FP_STATE_FPSIMD ;
1697
+ }
1698
+
1699
+ put_cpu_fpsimd_context ();
1700
+ }
1701
+
1630
1702
/*
1631
1703
* Associate current's FPSIMD context with this cpu
1632
1704
* The caller must have ownership of the cpu FPSIMD context before calling
1633
1705
* this function.
1634
1706
*/
1635
1707
static void fpsimd_bind_task_to_cpu (void )
1636
1708
{
1637
- struct fpsimd_last_state_struct * last =
1638
- this_cpu_ptr (& fpsimd_last_state );
1709
+ struct cpu_fp_state * last = this_cpu_ptr (& fpsimd_last_state );
1639
1710
1640
1711
WARN_ON (!system_supports_fpsimd ());
1641
1712
last -> st = & current -> thread .uw .fpsimd_state ;
@@ -1644,6 +1715,8 @@ static void fpsimd_bind_task_to_cpu(void)
1644
1715
last -> sve_vl = task_get_sve_vl (current );
1645
1716
last -> sme_vl = task_get_sme_vl (current );
1646
1717
last -> svcr = & current -> thread .svcr ;
1718
+ last -> fp_type = & current -> thread .fp_type ;
1719
+ last -> to_save = FP_STATE_CURRENT ;
1647
1720
current -> thread .fpsimd_cpu = smp_processor_id ();
1648
1721
1649
1722
/*
@@ -1665,22 +1738,14 @@ static void fpsimd_bind_task_to_cpu(void)
1665
1738
}
1666
1739
}
1667
1740
1668
- void fpsimd_bind_state_to_cpu (struct user_fpsimd_state * st , void * sve_state ,
1669
- unsigned int sve_vl , void * za_state ,
1670
- unsigned int sme_vl , u64 * svcr )
1741
+ void fpsimd_bind_state_to_cpu (struct cpu_fp_state * state )
1671
1742
{
1672
- struct fpsimd_last_state_struct * last =
1673
- this_cpu_ptr (& fpsimd_last_state );
1743
+ struct cpu_fp_state * last = this_cpu_ptr (& fpsimd_last_state );
1674
1744
1675
1745
WARN_ON (!system_supports_fpsimd ());
1676
1746
WARN_ON (!in_softirq () && !irqs_disabled ());
1677
1747
1678
- last -> st = st ;
1679
- last -> svcr = svcr ;
1680
- last -> sve_state = sve_state ;
1681
- last -> za_state = za_state ;
1682
- last -> sve_vl = sve_vl ;
1683
- last -> sme_vl = sme_vl ;
1748
+ * last = * state ;
1684
1749
}
1685
1750
1686
1751
/*
0 commit comments