Skip to content

Commit f0ea207

Browse files
nicolincjgunthorpe
authored andcommitted
iommu/arm-smmu-v3: Introduce struct arm_smmu_vmaster
Use it to store all vSMMU-related data. The vsid (Virtual Stream ID) will be the first use case. Since the vsid reader will be the eventq handler that already holds a streams_mutex, reuse that to fence the vmaster too. Also add a pair of arm_smmu_attach_prepare/commit_vmaster helpers to set or unset the master->vmaster pointer. Put the helpers inside the existing arm_smmu_attach_prepare/commit(). For identity/blocked ops that don't call arm_smmu_attach_prepare/commit(), add a simpler arm_smmu_master_clear_vmaster helper to unset the vmaster. Link: https://patch.msgid.link/r/a7f282e1a531279e25f06c651e95d56f6b120886.1741719725.git.nicolinc@nvidia.com Reviewed-by: Jason Gunthorpe <[email protected]> Reviewed-by: Pranjal Shrivastava <[email protected]> Acked-by: Will Deacon <[email protected]> Signed-off-by: Nicolin Chen <[email protected]> Signed-off-by: Jason Gunthorpe <[email protected]>
1 parent 2ec0458 commit f0ea207

File tree

3 files changed

+86
-1
lines changed

3 files changed

+86
-1
lines changed

drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,47 @@ static void arm_smmu_make_nested_domain_ste(
8585
}
8686
}
8787

88+
int arm_smmu_attach_prepare_vmaster(struct arm_smmu_attach_state *state,
89+
struct arm_smmu_nested_domain *nested_domain)
90+
{
91+
struct arm_smmu_vmaster *vmaster;
92+
unsigned long vsid;
93+
int ret;
94+
95+
iommu_group_mutex_assert(state->master->dev);
96+
97+
ret = iommufd_viommu_get_vdev_id(&nested_domain->vsmmu->core,
98+
state->master->dev, &vsid);
99+
if (ret)
100+
return ret;
101+
102+
vmaster = kzalloc(sizeof(*vmaster), GFP_KERNEL);
103+
if (!vmaster)
104+
return -ENOMEM;
105+
vmaster->vsmmu = nested_domain->vsmmu;
106+
vmaster->vsid = vsid;
107+
state->vmaster = vmaster;
108+
109+
return 0;
110+
}
111+
112+
void arm_smmu_attach_commit_vmaster(struct arm_smmu_attach_state *state)
113+
{
114+
struct arm_smmu_master *master = state->master;
115+
116+
mutex_lock(&master->smmu->streams_mutex);
117+
kfree(master->vmaster);
118+
master->vmaster = state->vmaster;
119+
mutex_unlock(&master->smmu->streams_mutex);
120+
}
121+
122+
void arm_smmu_master_clear_vmaster(struct arm_smmu_master *master)
123+
{
124+
struct arm_smmu_attach_state state = { .master = master };
125+
126+
arm_smmu_attach_commit_vmaster(&state);
127+
}
128+
88129
static int arm_smmu_attach_dev_nested(struct iommu_domain *domain,
89130
struct device *dev)
90131
{

drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2803,6 +2803,7 @@ int arm_smmu_attach_prepare(struct arm_smmu_attach_state *state,
28032803
struct arm_smmu_domain *smmu_domain =
28042804
to_smmu_domain_devices(new_domain);
28052805
unsigned long flags;
2806+
int ret;
28062807

28072808
/*
28082809
* arm_smmu_share_asid() must not see two domains pointing to the same
@@ -2832,9 +2833,18 @@ int arm_smmu_attach_prepare(struct arm_smmu_attach_state *state,
28322833
}
28332834

28342835
if (smmu_domain) {
2836+
if (new_domain->type == IOMMU_DOMAIN_NESTED) {
2837+
ret = arm_smmu_attach_prepare_vmaster(
2838+
state, to_smmu_nested_domain(new_domain));
2839+
if (ret)
2840+
return ret;
2841+
}
2842+
28352843
master_domain = kzalloc(sizeof(*master_domain), GFP_KERNEL);
2836-
if (!master_domain)
2844+
if (!master_domain) {
2845+
kfree(state->vmaster);
28372846
return -ENOMEM;
2847+
}
28382848
master_domain->master = master;
28392849
master_domain->ssid = state->ssid;
28402850
if (new_domain->type == IOMMU_DOMAIN_NESTED)
@@ -2861,6 +2871,7 @@ int arm_smmu_attach_prepare(struct arm_smmu_attach_state *state,
28612871
spin_unlock_irqrestore(&smmu_domain->devices_lock,
28622872
flags);
28632873
kfree(master_domain);
2874+
kfree(state->vmaster);
28642875
return -EINVAL;
28652876
}
28662877

@@ -2893,6 +2904,8 @@ void arm_smmu_attach_commit(struct arm_smmu_attach_state *state)
28932904

28942905
lockdep_assert_held(&arm_smmu_asid_lock);
28952906

2907+
arm_smmu_attach_commit_vmaster(state);
2908+
28962909
if (state->ats_enabled && !master->ats_enabled) {
28972910
arm_smmu_enable_ats(master);
28982911
} else if (state->ats_enabled && master->ats_enabled) {
@@ -3162,6 +3175,7 @@ static int arm_smmu_attach_dev_identity(struct iommu_domain *domain,
31623175
struct arm_smmu_ste ste;
31633176
struct arm_smmu_master *master = dev_iommu_priv_get(dev);
31643177

3178+
arm_smmu_master_clear_vmaster(master);
31653179
arm_smmu_make_bypass_ste(master->smmu, &ste);
31663180
arm_smmu_attach_dev_ste(domain, dev, &ste, STRTAB_STE_1_S1DSS_BYPASS);
31673181
return 0;
@@ -3180,7 +3194,9 @@ static int arm_smmu_attach_dev_blocked(struct iommu_domain *domain,
31803194
struct device *dev)
31813195
{
31823196
struct arm_smmu_ste ste;
3197+
struct arm_smmu_master *master = dev_iommu_priv_get(dev);
31833198

3199+
arm_smmu_master_clear_vmaster(master);
31843200
arm_smmu_make_abort_ste(&ste);
31853201
arm_smmu_attach_dev_ste(domain, dev, &ste,
31863202
STRTAB_STE_1_S1DSS_TERMINATE);

drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -799,6 +799,11 @@ struct arm_smmu_stream {
799799
struct rb_node node;
800800
};
801801

802+
struct arm_smmu_vmaster {
803+
struct arm_vsmmu *vsmmu;
804+
unsigned long vsid;
805+
};
806+
802807
struct arm_smmu_event {
803808
u8 stall : 1,
804809
ssv : 1,
@@ -824,6 +829,7 @@ struct arm_smmu_master {
824829
struct arm_smmu_device *smmu;
825830
struct device *dev;
826831
struct arm_smmu_stream *streams;
832+
struct arm_smmu_vmaster *vmaster; /* use smmu->streams_mutex */
827833
/* Locked by the iommu core using the group mutex */
828834
struct arm_smmu_ctx_desc_cfg cd_table;
829835
unsigned int num_streams;
@@ -972,6 +978,7 @@ struct arm_smmu_attach_state {
972978
bool disable_ats;
973979
ioasid_t ssid;
974980
/* Resulting state */
981+
struct arm_smmu_vmaster *vmaster;
975982
bool ats_enabled;
976983
};
977984

@@ -1055,9 +1062,30 @@ struct iommufd_viommu *arm_vsmmu_alloc(struct device *dev,
10551062
struct iommu_domain *parent,
10561063
struct iommufd_ctx *ictx,
10571064
unsigned int viommu_type);
1065+
int arm_smmu_attach_prepare_vmaster(struct arm_smmu_attach_state *state,
1066+
struct arm_smmu_nested_domain *nested_domain);
1067+
void arm_smmu_attach_commit_vmaster(struct arm_smmu_attach_state *state);
1068+
void arm_smmu_master_clear_vmaster(struct arm_smmu_master *master);
10581069
#else
10591070
#define arm_smmu_hw_info NULL
10601071
#define arm_vsmmu_alloc NULL
1072+
1073+
static inline int
1074+
arm_smmu_attach_prepare_vmaster(struct arm_smmu_attach_state *state,
1075+
struct arm_smmu_nested_domain *nested_domain)
1076+
{
1077+
return 0;
1078+
}
1079+
1080+
static inline void
1081+
arm_smmu_attach_commit_vmaster(struct arm_smmu_attach_state *state)
1082+
{
1083+
}
1084+
1085+
static inline void
1086+
arm_smmu_master_clear_vmaster(struct arm_smmu_master *master)
1087+
{
1088+
}
10611089
#endif /* CONFIG_ARM_SMMU_V3_IOMMUFD */
10621090

10631091
#endif /* _ARM_SMMU_V3_H */

0 commit comments

Comments
 (0)