Skip to content

Commit 78a5fbe

Browse files
jgunthorpewilldeacon
authored andcommitted
iommu/arm-smmu-v3: Make CD programming use arm_smmu_write_entry()
CD table entries and STE's have the same essential programming sequence, just with different types. Use the new ops indirection to link CD programming to the common writer. In a few more patches all CD writers will call an appropriate make function and then directly call arm_smmu_write_cd_entry(). arm_smmu_write_ctx_desc() will be removed. Until then lightly tweak arm_smmu_write_ctx_desc() to also use the new programmer by using the same logic as right now to build the target CD on the stack, sanitizing it to meet the used rules, and then using the writer. Sanitizing is necessary because the writer expects that the currently programmed CD follows the used rules. Next patches add new make functions and new direct calls to arm_smmu_write_cd_entry() which will require this. Signed-off-by: Michael Shavit <mshavit@google.com> Tested-by: Nicolin Chen <nicolinc@nvidia.com> Tested-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com> Reviewed-by: Moritz Fischer <moritzf@google.com> Reviewed-by: Nicolin Chen <nicolinc@nvidia.com> Signed-off-by: Jason Gunthorpe <jgg@nvidia.com> Link: https://lore.kernel.org/r/2-v9-5040dc602008+177d7-smmuv3_newapi_p2_jgg@nvidia.com Signed-off-by: Will Deacon <will@kernel.org>
1 parent de31c35 commit 78a5fbe

1 file changed

Lines changed: 67 additions & 22 deletions

File tree

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

Lines changed: 67 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ struct arm_smmu_entry_writer_ops {
5555

5656
#define NUM_ENTRY_QWORDS 8
5757
static_assert(sizeof(struct arm_smmu_ste) == NUM_ENTRY_QWORDS * sizeof(u64));
58+
static_assert(sizeof(struct arm_smmu_cd) == NUM_ENTRY_QWORDS * sizeof(u64));
5859

5960
static phys_addr_t arm_smmu_msi_cfg[ARM_SMMU_MAX_MSIS][3] = {
6061
[EVTQ_MSI_INDEX] = {
@@ -1230,6 +1231,59 @@ static struct arm_smmu_cd *arm_smmu_get_cd_ptr(struct arm_smmu_master *master,
12301231
return &l1_desc->l2ptr[idx];
12311232
}
12321233

1234+
struct arm_smmu_cd_writer {
1235+
struct arm_smmu_entry_writer writer;
1236+
unsigned int ssid;
1237+
};
1238+
1239+
static void arm_smmu_get_cd_used(const __le64 *ent, __le64 *used_bits)
1240+
{
1241+
used_bits[0] = cpu_to_le64(CTXDESC_CD_0_V);
1242+
if (!(ent[0] & cpu_to_le64(CTXDESC_CD_0_V)))
1243+
return;
1244+
memset(used_bits, 0xFF, sizeof(struct arm_smmu_cd));
1245+
1246+
/*
1247+
* If EPD0 is set by the make function it means
1248+
* T0SZ/TG0/IR0/OR0/SH0/TTB0 are IGNORED
1249+
*/
1250+
if (ent[0] & cpu_to_le64(CTXDESC_CD_0_TCR_EPD0)) {
1251+
used_bits[0] &= ~cpu_to_le64(
1252+
CTXDESC_CD_0_TCR_T0SZ | CTXDESC_CD_0_TCR_TG0 |
1253+
CTXDESC_CD_0_TCR_IRGN0 | CTXDESC_CD_0_TCR_ORGN0 |
1254+
CTXDESC_CD_0_TCR_SH0);
1255+
used_bits[1] &= ~cpu_to_le64(CTXDESC_CD_1_TTB0_MASK);
1256+
}
1257+
}
1258+
1259+
static void arm_smmu_cd_writer_sync_entry(struct arm_smmu_entry_writer *writer)
1260+
{
1261+
struct arm_smmu_cd_writer *cd_writer =
1262+
container_of(writer, struct arm_smmu_cd_writer, writer);
1263+
1264+
arm_smmu_sync_cd(writer->master, cd_writer->ssid, true);
1265+
}
1266+
1267+
static const struct arm_smmu_entry_writer_ops arm_smmu_cd_writer_ops = {
1268+
.sync = arm_smmu_cd_writer_sync_entry,
1269+
.get_used = arm_smmu_get_cd_used,
1270+
};
1271+
1272+
static void arm_smmu_write_cd_entry(struct arm_smmu_master *master, int ssid,
1273+
struct arm_smmu_cd *cdptr,
1274+
const struct arm_smmu_cd *target)
1275+
{
1276+
struct arm_smmu_cd_writer cd_writer = {
1277+
.writer = {
1278+
.ops = &arm_smmu_cd_writer_ops,
1279+
.master = master,
1280+
},
1281+
.ssid = ssid,
1282+
};
1283+
1284+
arm_smmu_write_entry(&cd_writer.writer, cdptr->data, target->data);
1285+
}
1286+
12331287
int arm_smmu_write_ctx_desc(struct arm_smmu_master *master, int ssid,
12341288
struct arm_smmu_ctx_desc *cd)
12351289
{
@@ -1246,26 +1300,34 @@ int arm_smmu_write_ctx_desc(struct arm_smmu_master *master, int ssid,
12461300
*/
12471301
u64 val;
12481302
bool cd_live;
1249-
struct arm_smmu_cd *cdptr;
1303+
struct arm_smmu_cd target;
1304+
struct arm_smmu_cd *cdptr = &target;
1305+
struct arm_smmu_cd *cd_table_entry;
12501306
struct arm_smmu_ctx_desc_cfg *cd_table = &master->cd_table;
12511307
struct arm_smmu_device *smmu = master->smmu;
12521308

12531309
if (WARN_ON(ssid >= (1 << cd_table->s1cdmax)))
12541310
return -E2BIG;
12551311

1256-
cdptr = arm_smmu_get_cd_ptr(master, ssid);
1257-
if (!cdptr)
1312+
cd_table_entry = arm_smmu_get_cd_ptr(master, ssid);
1313+
if (!cd_table_entry)
12581314
return -ENOMEM;
12591315

1316+
target = *cd_table_entry;
12601317
val = le64_to_cpu(cdptr->data[0]);
12611318
cd_live = !!(val & CTXDESC_CD_0_V);
12621319

12631320
if (!cd) { /* (5) */
1321+
memset(cdptr, 0, sizeof(*cdptr));
12641322
val = 0;
12651323
} else if (cd == &quiet_cd) { /* (4) */
1324+
val &= ~(CTXDESC_CD_0_TCR_T0SZ | CTXDESC_CD_0_TCR_TG0 |
1325+
CTXDESC_CD_0_TCR_IRGN0 | CTXDESC_CD_0_TCR_ORGN0 |
1326+
CTXDESC_CD_0_TCR_SH0);
12661327
if (!(smmu->features & ARM_SMMU_FEAT_STALL_FORCE))
12671328
val &= ~(CTXDESC_CD_0_S | CTXDESC_CD_0_R);
12681329
val |= CTXDESC_CD_0_TCR_EPD0;
1330+
cdptr->data[1] &= ~cpu_to_le64(CTXDESC_CD_1_TTB0_MASK);
12691331
} else if (cd_live) { /* (3) */
12701332
val &= ~CTXDESC_CD_0_ASID;
12711333
val |= FIELD_PREP(CTXDESC_CD_0_ASID, cd->asid);
@@ -1278,13 +1340,6 @@ int arm_smmu_write_ctx_desc(struct arm_smmu_master *master, int ssid,
12781340
cdptr->data[2] = 0;
12791341
cdptr->data[3] = cpu_to_le64(cd->mair);
12801342

1281-
/*
1282-
* STE may be live, and the SMMU might read dwords of this CD in any
1283-
* order. Ensure that it observes valid values before reading
1284-
* V=1.
1285-
*/
1286-
arm_smmu_sync_cd(master, ssid, true);
1287-
12881343
val = cd->tcr |
12891344
#ifdef __BIG_ENDIAN
12901345
CTXDESC_CD_0_ENDI |
@@ -1298,18 +1353,8 @@ int arm_smmu_write_ctx_desc(struct arm_smmu_master *master, int ssid,
12981353
if (cd_table->stall_enabled)
12991354
val |= CTXDESC_CD_0_S;
13001355
}
1301-
1302-
/*
1303-
* The SMMU accesses 64-bit values atomically. See IHI0070Ca 3.21.3
1304-
* "Configuration structures and configuration invalidation completion"
1305-
*
1306-
* The size of single-copy atomic reads made by the SMMU is
1307-
* IMPLEMENTATION DEFINED but must be at least 64 bits. Any single
1308-
* field within an aligned 64-bit span of a structure can be altered
1309-
* without first making the structure invalid.
1310-
*/
1311-
WRITE_ONCE(cdptr->data[0], cpu_to_le64(val));
1312-
arm_smmu_sync_cd(master, ssid, true);
1356+
cdptr->data[0] = cpu_to_le64(val);
1357+
arm_smmu_write_cd_entry(master, ssid, cd_table_entry, &target);
13131358
return 0;
13141359
}
13151360

0 commit comments

Comments
 (0)