mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-06 13:27:25 -04:00
iommu/arm-smmu-v3: Test the STE S1DSS functionality
S1DSS brings in quite a few new transition pairs that are interesting. Test to/from S1DSS_BYPASS <-> S1DSS_SSID0, and BYPASS <-> S1DSS_SSID0. Test a contrived non-hitless flow to make sure that the logic works. Tested-by: Nicolin Chen <nicolinc@nvidia.com> Signed-off-by: Michael Shavit <mshavit@google.com> Reviewed-by: Nicolin Chen <nicolinc@nvidia.com> Reviewed-by: Jerry Snitselaar <jsnitsel@redhat.com> Signed-off-by: Jason Gunthorpe <jgg@nvidia.com> Link: https://lore.kernel.org/r/12-v9-5cd718286059+79186-smmuv3_newapi_p2b_jgg@nvidia.com Signed-off-by: Will Deacon <will@kernel.org>
This commit is contained in:
committed by
Will Deacon
parent
ce26ea9e6e
commit
3b5302cbb0
@@ -144,6 +144,14 @@ static void arm_smmu_v3_test_ste_expect_transition(
|
||||
KUNIT_EXPECT_MEMEQ(test, target->data, cur_copy.data, sizeof(cur_copy));
|
||||
}
|
||||
|
||||
static void arm_smmu_v3_test_ste_expect_non_hitless_transition(
|
||||
struct kunit *test, const struct arm_smmu_ste *cur,
|
||||
const struct arm_smmu_ste *target, unsigned int num_syncs_expected)
|
||||
{
|
||||
arm_smmu_v3_test_ste_expect_transition(test, cur, target,
|
||||
num_syncs_expected, false);
|
||||
}
|
||||
|
||||
static void arm_smmu_v3_test_ste_expect_hitless_transition(
|
||||
struct kunit *test, const struct arm_smmu_ste *cur,
|
||||
const struct arm_smmu_ste *target, unsigned int num_syncs_expected)
|
||||
@@ -155,6 +163,7 @@ static void arm_smmu_v3_test_ste_expect_hitless_transition(
|
||||
static const dma_addr_t fake_cdtab_dma_addr = 0xF0F0F0F0F0F0;
|
||||
|
||||
static void arm_smmu_test_make_cdtable_ste(struct arm_smmu_ste *ste,
|
||||
unsigned int s1dss,
|
||||
const dma_addr_t dma_addr)
|
||||
{
|
||||
struct arm_smmu_master master = {
|
||||
@@ -164,7 +173,7 @@ static void arm_smmu_test_make_cdtable_ste(struct arm_smmu_ste *ste,
|
||||
.smmu = &smmu,
|
||||
};
|
||||
|
||||
arm_smmu_make_cdtable_ste(ste, &master, true, STRTAB_STE_1_S1DSS_SSID0);
|
||||
arm_smmu_make_cdtable_ste(ste, &master, true, s1dss);
|
||||
}
|
||||
|
||||
static void arm_smmu_v3_write_ste_test_bypass_to_abort(struct kunit *test)
|
||||
@@ -194,7 +203,8 @@ static void arm_smmu_v3_write_ste_test_cdtable_to_abort(struct kunit *test)
|
||||
{
|
||||
struct arm_smmu_ste ste;
|
||||
|
||||
arm_smmu_test_make_cdtable_ste(&ste, fake_cdtab_dma_addr);
|
||||
arm_smmu_test_make_cdtable_ste(&ste, STRTAB_STE_1_S1DSS_SSID0,
|
||||
fake_cdtab_dma_addr);
|
||||
arm_smmu_v3_test_ste_expect_hitless_transition(test, &ste, &abort_ste,
|
||||
NUM_EXPECTED_SYNCS(2));
|
||||
}
|
||||
@@ -203,7 +213,8 @@ static void arm_smmu_v3_write_ste_test_abort_to_cdtable(struct kunit *test)
|
||||
{
|
||||
struct arm_smmu_ste ste;
|
||||
|
||||
arm_smmu_test_make_cdtable_ste(&ste, fake_cdtab_dma_addr);
|
||||
arm_smmu_test_make_cdtable_ste(&ste, STRTAB_STE_1_S1DSS_SSID0,
|
||||
fake_cdtab_dma_addr);
|
||||
arm_smmu_v3_test_ste_expect_hitless_transition(test, &abort_ste, &ste,
|
||||
NUM_EXPECTED_SYNCS(2));
|
||||
}
|
||||
@@ -212,7 +223,8 @@ static void arm_smmu_v3_write_ste_test_cdtable_to_bypass(struct kunit *test)
|
||||
{
|
||||
struct arm_smmu_ste ste;
|
||||
|
||||
arm_smmu_test_make_cdtable_ste(&ste, fake_cdtab_dma_addr);
|
||||
arm_smmu_test_make_cdtable_ste(&ste, STRTAB_STE_1_S1DSS_SSID0,
|
||||
fake_cdtab_dma_addr);
|
||||
arm_smmu_v3_test_ste_expect_hitless_transition(test, &ste, &bypass_ste,
|
||||
NUM_EXPECTED_SYNCS(3));
|
||||
}
|
||||
@@ -221,11 +233,54 @@ static void arm_smmu_v3_write_ste_test_bypass_to_cdtable(struct kunit *test)
|
||||
{
|
||||
struct arm_smmu_ste ste;
|
||||
|
||||
arm_smmu_test_make_cdtable_ste(&ste, fake_cdtab_dma_addr);
|
||||
arm_smmu_test_make_cdtable_ste(&ste, STRTAB_STE_1_S1DSS_SSID0,
|
||||
fake_cdtab_dma_addr);
|
||||
arm_smmu_v3_test_ste_expect_hitless_transition(test, &bypass_ste, &ste,
|
||||
NUM_EXPECTED_SYNCS(3));
|
||||
}
|
||||
|
||||
static void arm_smmu_v3_write_ste_test_cdtable_s1dss_change(struct kunit *test)
|
||||
{
|
||||
struct arm_smmu_ste ste;
|
||||
struct arm_smmu_ste s1dss_bypass;
|
||||
|
||||
arm_smmu_test_make_cdtable_ste(&ste, STRTAB_STE_1_S1DSS_SSID0,
|
||||
fake_cdtab_dma_addr);
|
||||
arm_smmu_test_make_cdtable_ste(&s1dss_bypass, STRTAB_STE_1_S1DSS_BYPASS,
|
||||
fake_cdtab_dma_addr);
|
||||
|
||||
/*
|
||||
* Flipping s1dss on a CD table STE only involves changes to the second
|
||||
* qword of an STE and can be done in a single write.
|
||||
*/
|
||||
arm_smmu_v3_test_ste_expect_hitless_transition(
|
||||
test, &ste, &s1dss_bypass, NUM_EXPECTED_SYNCS(1));
|
||||
arm_smmu_v3_test_ste_expect_hitless_transition(
|
||||
test, &s1dss_bypass, &ste, NUM_EXPECTED_SYNCS(1));
|
||||
}
|
||||
|
||||
static void
|
||||
arm_smmu_v3_write_ste_test_s1dssbypass_to_stebypass(struct kunit *test)
|
||||
{
|
||||
struct arm_smmu_ste s1dss_bypass;
|
||||
|
||||
arm_smmu_test_make_cdtable_ste(&s1dss_bypass, STRTAB_STE_1_S1DSS_BYPASS,
|
||||
fake_cdtab_dma_addr);
|
||||
arm_smmu_v3_test_ste_expect_hitless_transition(
|
||||
test, &s1dss_bypass, &bypass_ste, NUM_EXPECTED_SYNCS(2));
|
||||
}
|
||||
|
||||
static void
|
||||
arm_smmu_v3_write_ste_test_stebypass_to_s1dssbypass(struct kunit *test)
|
||||
{
|
||||
struct arm_smmu_ste s1dss_bypass;
|
||||
|
||||
arm_smmu_test_make_cdtable_ste(&s1dss_bypass, STRTAB_STE_1_S1DSS_BYPASS,
|
||||
fake_cdtab_dma_addr);
|
||||
arm_smmu_v3_test_ste_expect_hitless_transition(
|
||||
test, &bypass_ste, &s1dss_bypass, NUM_EXPECTED_SYNCS(2));
|
||||
}
|
||||
|
||||
static void arm_smmu_test_make_s2_ste(struct arm_smmu_ste *ste,
|
||||
bool ats_enabled)
|
||||
{
|
||||
@@ -285,6 +340,48 @@ static void arm_smmu_v3_write_ste_test_bypass_to_s2(struct kunit *test)
|
||||
NUM_EXPECTED_SYNCS(2));
|
||||
}
|
||||
|
||||
static void arm_smmu_v3_write_ste_test_s1_to_s2(struct kunit *test)
|
||||
{
|
||||
struct arm_smmu_ste s1_ste;
|
||||
struct arm_smmu_ste s2_ste;
|
||||
|
||||
arm_smmu_test_make_cdtable_ste(&s1_ste, STRTAB_STE_1_S1DSS_SSID0,
|
||||
fake_cdtab_dma_addr);
|
||||
arm_smmu_test_make_s2_ste(&s2_ste, true);
|
||||
arm_smmu_v3_test_ste_expect_hitless_transition(test, &s1_ste, &s2_ste,
|
||||
NUM_EXPECTED_SYNCS(3));
|
||||
}
|
||||
|
||||
static void arm_smmu_v3_write_ste_test_s2_to_s1(struct kunit *test)
|
||||
{
|
||||
struct arm_smmu_ste s1_ste;
|
||||
struct arm_smmu_ste s2_ste;
|
||||
|
||||
arm_smmu_test_make_cdtable_ste(&s1_ste, STRTAB_STE_1_S1DSS_SSID0,
|
||||
fake_cdtab_dma_addr);
|
||||
arm_smmu_test_make_s2_ste(&s2_ste, true);
|
||||
arm_smmu_v3_test_ste_expect_hitless_transition(test, &s2_ste, &s1_ste,
|
||||
NUM_EXPECTED_SYNCS(3));
|
||||
}
|
||||
|
||||
static void arm_smmu_v3_write_ste_test_non_hitless(struct kunit *test)
|
||||
{
|
||||
struct arm_smmu_ste ste;
|
||||
struct arm_smmu_ste ste_2;
|
||||
|
||||
/*
|
||||
* Although no flow resembles this in practice, one way to force an STE
|
||||
* update to be non-hitless is to change its CD table pointer as well as
|
||||
* s1 dss field in the same update.
|
||||
*/
|
||||
arm_smmu_test_make_cdtable_ste(&ste, STRTAB_STE_1_S1DSS_SSID0,
|
||||
fake_cdtab_dma_addr);
|
||||
arm_smmu_test_make_cdtable_ste(&ste_2, STRTAB_STE_1_S1DSS_BYPASS,
|
||||
0x4B4B4b4B4B);
|
||||
arm_smmu_v3_test_ste_expect_non_hitless_transition(
|
||||
test, &ste, &ste_2, NUM_EXPECTED_SYNCS(3));
|
||||
}
|
||||
|
||||
static void arm_smmu_v3_test_cd_expect_transition(
|
||||
struct kunit *test, const struct arm_smmu_cd *cur,
|
||||
const struct arm_smmu_cd *target, unsigned int num_syncs_expected,
|
||||
@@ -438,10 +535,16 @@ static struct kunit_case arm_smmu_v3_test_cases[] = {
|
||||
KUNIT_CASE(arm_smmu_v3_write_ste_test_abort_to_cdtable),
|
||||
KUNIT_CASE(arm_smmu_v3_write_ste_test_cdtable_to_bypass),
|
||||
KUNIT_CASE(arm_smmu_v3_write_ste_test_bypass_to_cdtable),
|
||||
KUNIT_CASE(arm_smmu_v3_write_ste_test_cdtable_s1dss_change),
|
||||
KUNIT_CASE(arm_smmu_v3_write_ste_test_s1dssbypass_to_stebypass),
|
||||
KUNIT_CASE(arm_smmu_v3_write_ste_test_stebypass_to_s1dssbypass),
|
||||
KUNIT_CASE(arm_smmu_v3_write_ste_test_s2_to_abort),
|
||||
KUNIT_CASE(arm_smmu_v3_write_ste_test_abort_to_s2),
|
||||
KUNIT_CASE(arm_smmu_v3_write_ste_test_s2_to_bypass),
|
||||
KUNIT_CASE(arm_smmu_v3_write_ste_test_bypass_to_s2),
|
||||
KUNIT_CASE(arm_smmu_v3_write_ste_test_s1_to_s2),
|
||||
KUNIT_CASE(arm_smmu_v3_write_ste_test_s2_to_s1),
|
||||
KUNIT_CASE(arm_smmu_v3_write_ste_test_non_hitless),
|
||||
KUNIT_CASE(arm_smmu_v3_write_cd_test_s1_clear),
|
||||
KUNIT_CASE(arm_smmu_v3_write_cd_test_s1_change_asid),
|
||||
KUNIT_CASE(arm_smmu_v3_write_cd_test_sva_clear),
|
||||
|
||||
Reference in New Issue
Block a user