@@ -996,7 +996,67 @@ static void riscv_iommu_iotlb_inval(struct riscv_iommu_domain *domain,
996996}
997997
998998#define RISCV_IOMMU_FSC_BARE 0
999+ /*
1000+ * This function sends IOTINVAL commands as required by the RISC-V
1001+ * IOMMU specification (Section 6.3.1 and 6.3.2 in 1.0 spec version)
1002+ * after modifying DDT or PDT entries
1003+ */
1004+ static void riscv_iommu_iodir_iotinval (struct riscv_iommu_device * iommu ,
1005+ bool inval_pdt , unsigned long iohgatp ,
1006+ struct riscv_iommu_dc * dc ,
1007+ struct riscv_iommu_pc * pc )
1008+ {
1009+ struct riscv_iommu_command cmd ;
1010+
1011+ riscv_iommu_cmd_inval_vma (& cmd );
9991012
1013+ if (FIELD_GET (RISCV_IOMMU_DC_IOHGATP_MODE , iohgatp ) ==
1014+ RISCV_IOMMU_DC_IOHGATP_MODE_BARE ) {
1015+ if (inval_pdt ) {
1016+ /*
1017+ * IOTINVAL.VMA with GV=AV=0, and PSCV=1, and
1018+ * PSCID=PC.PSCID
1019+ */
1020+ riscv_iommu_cmd_inval_set_pscid (& cmd ,
1021+ FIELD_GET (RISCV_IOMMU_PC_TA_PSCID , pc -> ta ));
1022+ } else {
1023+ if (!FIELD_GET (RISCV_IOMMU_DC_TC_PDTV , dc -> tc ) &&
1024+ FIELD_GET (RISCV_IOMMU_DC_FSC_MODE , dc -> fsc ) !=
1025+ RISCV_IOMMU_DC_FSC_MODE_BARE ) {
1026+ /*
1027+ * DC.tc.PDTV == 0 && DC.fsc.MODE != Bare
1028+ * IOTINVAL.VMA with GV=AV=0, and PSCV=1, and
1029+ * PSCID=DC.ta.PSCID
1030+ */
1031+ riscv_iommu_cmd_inval_set_pscid (& cmd ,
1032+ FIELD_GET (RISCV_IOMMU_DC_TA_PSCID , dc -> ta ));
1033+ }
1034+ /* else: IOTINVAL.VMA with GV=AV=PSCV=0 */
1035+ }
1036+ } else {
1037+ riscv_iommu_cmd_inval_set_gscid (& cmd ,
1038+ FIELD_GET (RISCV_IOMMU_DC_IOHGATP_GSCID , iohgatp ));
1039+
1040+ if (inval_pdt ) {
1041+ /*
1042+ * IOTINVAL.VMA with GV=1, AV=0, and PSCV=1, and
1043+ * GSCID=DC.iohgatp.GSCID, PSCID=PC.PSCID
1044+ */
1045+ riscv_iommu_cmd_inval_set_pscid (& cmd ,
1046+ FIELD_GET (RISCV_IOMMU_PC_TA_PSCID , pc -> ta ));
1047+ }
1048+ /*
1049+ * else: IOTINVAL.VMA with GV=1,AV=PSCV=0,and
1050+ * GSCID=DC.iohgatp.GSCID
1051+ *
1052+ * IOTINVAL.GVMA with GV=1,AV=0,and
1053+ * GSCID=DC.iohgatp.GSCID
1054+ * TODO: For now, the Second-Stage feature have not yet been merged,
1055+ * also issue IOTINVAL.GVMA once second-stage support is merged.
1056+ */
1057+ }
1058+ riscv_iommu_cmd_send (iommu , & cmd );
1059+ }
10001060/*
10011061 * Update IODIR for the device.
10021062 *
@@ -1031,6 +1091,11 @@ static void riscv_iommu_iodir_update(struct riscv_iommu_device *iommu,
10311091 riscv_iommu_cmd_iodir_inval_ddt (& cmd );
10321092 riscv_iommu_cmd_iodir_set_did (& cmd , fwspec -> ids [i ]);
10331093 riscv_iommu_cmd_send (iommu , & cmd );
1094+ /*
1095+ * For now, the SVA and PASID features have not yet been merged, the
1096+ * default configuration is inval_pdt=false and pc=NULL.
1097+ */
1098+ riscv_iommu_iodir_iotinval (iommu , false, dc -> iohgatp , dc , NULL );
10341099 sync_required = true;
10351100 }
10361101
@@ -1056,6 +1121,11 @@ static void riscv_iommu_iodir_update(struct riscv_iommu_device *iommu,
10561121 riscv_iommu_cmd_iodir_inval_ddt (& cmd );
10571122 riscv_iommu_cmd_iodir_set_did (& cmd , fwspec -> ids [i ]);
10581123 riscv_iommu_cmd_send (iommu , & cmd );
1124+ /*
1125+ * For now, the SVA and PASID features have not yet been merged, the
1126+ * default configuration is inval_pdt=false and pc=NULL.
1127+ */
1128+ riscv_iommu_iodir_iotinval (iommu , false, dc -> iohgatp , dc , NULL );
10591129 }
10601130
10611131 riscv_iommu_cmd_sync (iommu , RISCV_IOMMU_IOTINVAL_TIMEOUT );
0 commit comments