@@ -67,6 +67,9 @@ struct kvm_ffa_buffers {
67
67
*/
68
68
static struct kvm_ffa_buffers hyp_buffers ;
69
69
static struct kvm_ffa_buffers host_buffers ;
70
+ static u32 hyp_ffa_version ;
71
+ static bool has_version_negotiated ;
72
+ static hyp_spinlock_t version_lock ;
70
73
71
74
static void ffa_to_smccc_error (struct arm_smccc_res * res , u64 ffa_errno )
72
75
{
@@ -639,6 +642,83 @@ static bool do_ffa_features(struct arm_smccc_res *res,
639
642
return true;
640
643
}
641
644
645
+ static int hyp_ffa_post_init (void )
646
+ {
647
+ size_t min_rxtx_sz ;
648
+ struct arm_smccc_res res ;
649
+
650
+ arm_smccc_1_1_smc (FFA_ID_GET , 0 , 0 , 0 , 0 , 0 , 0 , 0 , & res );
651
+ if (res .a0 != FFA_SUCCESS )
652
+ return - EOPNOTSUPP ;
653
+
654
+ if (res .a2 != HOST_FFA_ID )
655
+ return - EINVAL ;
656
+
657
+ arm_smccc_1_1_smc (FFA_FEATURES , FFA_FN64_RXTX_MAP ,
658
+ 0 , 0 , 0 , 0 , 0 , 0 , & res );
659
+ if (res .a0 != FFA_SUCCESS )
660
+ return - EOPNOTSUPP ;
661
+
662
+ switch (res .a2 ) {
663
+ case FFA_FEAT_RXTX_MIN_SZ_4K :
664
+ min_rxtx_sz = SZ_4K ;
665
+ break ;
666
+ case FFA_FEAT_RXTX_MIN_SZ_16K :
667
+ min_rxtx_sz = SZ_16K ;
668
+ break ;
669
+ case FFA_FEAT_RXTX_MIN_SZ_64K :
670
+ min_rxtx_sz = SZ_64K ;
671
+ break ;
672
+ default :
673
+ return - EINVAL ;
674
+ }
675
+
676
+ if (min_rxtx_sz > PAGE_SIZE )
677
+ return - EOPNOTSUPP ;
678
+
679
+ return 0 ;
680
+ }
681
+
682
+ static void do_ffa_version (struct arm_smccc_res * res ,
683
+ struct kvm_cpu_context * ctxt )
684
+ {
685
+ DECLARE_REG (u32 , ffa_req_version , ctxt , 1 );
686
+
687
+ if (FFA_MAJOR_VERSION (ffa_req_version ) != 1 ) {
688
+ res -> a0 = FFA_RET_NOT_SUPPORTED ;
689
+ return ;
690
+ }
691
+
692
+ hyp_spin_lock (& version_lock );
693
+ if (has_version_negotiated ) {
694
+ res -> a0 = hyp_ffa_version ;
695
+ goto unlock ;
696
+ }
697
+
698
+ /*
699
+ * If the client driver tries to downgrade the version, we need to ask
700
+ * first if TEE supports it.
701
+ */
702
+ if (FFA_MINOR_VERSION (ffa_req_version ) < FFA_MINOR_VERSION (hyp_ffa_version )) {
703
+ arm_smccc_1_1_smc (FFA_VERSION , ffa_req_version , 0 ,
704
+ 0 , 0 , 0 , 0 , 0 ,
705
+ res );
706
+ if (res -> a0 == FFA_RET_NOT_SUPPORTED )
707
+ goto unlock ;
708
+
709
+ hyp_ffa_version = ffa_req_version ;
710
+ }
711
+
712
+ if (hyp_ffa_post_init ())
713
+ res -> a0 = FFA_RET_NOT_SUPPORTED ;
714
+ else {
715
+ has_version_negotiated = true;
716
+ res -> a0 = hyp_ffa_version ;
717
+ }
718
+ unlock :
719
+ hyp_spin_unlock (& version_lock );
720
+ }
721
+
642
722
bool kvm_host_ffa_handler (struct kvm_cpu_context * host_ctxt , u32 func_id )
643
723
{
644
724
struct arm_smccc_res res ;
@@ -659,6 +739,11 @@ bool kvm_host_ffa_handler(struct kvm_cpu_context *host_ctxt, u32 func_id)
659
739
if (!is_ffa_call (func_id ))
660
740
return false;
661
741
742
+ if (!has_version_negotiated && func_id != FFA_VERSION ) {
743
+ ffa_to_smccc_error (& res , FFA_RET_INVALID_PARAMETERS );
744
+ goto out_handled ;
745
+ }
746
+
662
747
switch (func_id ) {
663
748
case FFA_FEATURES :
664
749
if (!do_ffa_features (& res , host_ctxt ))
@@ -685,6 +770,9 @@ bool kvm_host_ffa_handler(struct kvm_cpu_context *host_ctxt, u32 func_id)
685
770
case FFA_MEM_FRAG_TX :
686
771
do_ffa_mem_frag_tx (& res , host_ctxt );
687
772
goto out_handled ;
773
+ case FFA_VERSION :
774
+ do_ffa_version (& res , host_ctxt );
775
+ goto out_handled ;
688
776
}
689
777
690
778
if (ffa_call_supported (func_id ))
@@ -699,7 +787,6 @@ bool kvm_host_ffa_handler(struct kvm_cpu_context *host_ctxt, u32 func_id)
699
787
int hyp_ffa_init (void * pages )
700
788
{
701
789
struct arm_smccc_res res ;
702
- size_t min_rxtx_sz ;
703
790
void * tx , * rx ;
704
791
705
792
if (kvm_host_psci_config .smccc_version < ARM_SMCCC_VERSION_1_2 )
@@ -725,35 +812,7 @@ int hyp_ffa_init(void *pages)
725
812
if (FFA_MAJOR_VERSION (res .a0 ) != 1 )
726
813
return - EOPNOTSUPP ;
727
814
728
- arm_smccc_1_1_smc (FFA_ID_GET , 0 , 0 , 0 , 0 , 0 , 0 , 0 , & res );
729
- if (res .a0 != FFA_SUCCESS )
730
- return - EOPNOTSUPP ;
731
-
732
- if (res .a2 != HOST_FFA_ID )
733
- return - EINVAL ;
734
-
735
- arm_smccc_1_1_smc (FFA_FEATURES , FFA_FN64_RXTX_MAP ,
736
- 0 , 0 , 0 , 0 , 0 , 0 , & res );
737
- if (res .a0 != FFA_SUCCESS )
738
- return - EOPNOTSUPP ;
739
-
740
- switch (res .a2 ) {
741
- case FFA_FEAT_RXTX_MIN_SZ_4K :
742
- min_rxtx_sz = SZ_4K ;
743
- break ;
744
- case FFA_FEAT_RXTX_MIN_SZ_16K :
745
- min_rxtx_sz = SZ_16K ;
746
- break ;
747
- case FFA_FEAT_RXTX_MIN_SZ_64K :
748
- min_rxtx_sz = SZ_64K ;
749
- break ;
750
- default :
751
- return - EINVAL ;
752
- }
753
-
754
- if (min_rxtx_sz > PAGE_SIZE )
755
- return - EOPNOTSUPP ;
756
-
815
+ hyp_ffa_version = FFA_VERSION_1_0 ;
757
816
tx = pages ;
758
817
pages += KVM_FFA_MBOX_NR_PAGES * PAGE_SIZE ;
759
818
rx = pages ;
@@ -775,5 +834,6 @@ int hyp_ffa_init(void *pages)
775
834
.lock = __HYP_SPIN_LOCK_UNLOCKED ,
776
835
};
777
836
837
+ version_lock = __HYP_SPIN_LOCK_UNLOCKED ;
778
838
return 0 ;
779
839
}
0 commit comments