diff options
author | Eric Auger <eric.auger@redhat.com> | 2020-04-02 16:52:27 +0200 |
---|---|---|
committer | Andrew Jones <drjones@redhat.com> | 2020-04-04 10:03:44 +0200 |
commit | de582149c5be94a1ff7d3d8ee3526501b26c7f03 (patch) | |
tree | 2b2f9107dde947ee7799830f004ad3bf3aa5540f | |
parent | 64260a5fb31b8b91a76f85ee156c265e5dfa0b1b (diff) | |
download | kvm-unit-tests-de582149c5be94a1ff7d3d8ee3526501b26c7f03.tar.gz |
arm/arm64: ITS: pending table migration test
Add two new migration tests. One testing the migration of
a topology where collection were unmapped. The second test
checks the migration of the pending table.
Signed-off-by: Eric Auger <eric.auger@redhat.com>
[ Complete migration even when the test is skipped. Otherwise the
migration scripts hang. Also, without the KVM fix for unmapped
collections, migration will fail and the test will hang, so use
errata to skip it instead. ]
Signed-off-by: Andrew Jones <drjones@redhat.com>
-rw-r--r-- | arm/gic.c | 152 | ||||
-rw-r--r-- | arm/unittests.cfg | 16 | ||||
-rw-r--r-- | errata.txt | 1 |
3 files changed, 169 insertions, 0 deletions
@@ -12,6 +12,7 @@ * This work is licensed under the terms of the GNU LGPL, version 2. */ #include <libcflat.h> +#include <errata.h> #include <asm/setup.h> #include <asm/processor.h> #include <asm/delay.h> @@ -193,6 +194,7 @@ static void lpi_handler(struct pt_regs *regs __unused) smp_rmb(); /* pairs with wmb in lpi_stats_expect */ lpi_stats.observed.cpu_id = smp_processor_id(); lpi_stats.observed.lpi_id = irqnr; + acked[lpi_stats.observed.cpu_id]++; smp_wmb(); /* pairs with rmb in check_lpi_stats */ } @@ -238,6 +240,22 @@ static void secondary_lpi_test(void) while (1) wfi(); } + +static void check_lpi_hits(int *expected, const char *msg) +{ + bool pass = true; + int i; + + for_each_present_cpu(i) { + if (acked[i] != expected[i]) { + report_info("expected %d LPIs on PE #%d, %d observed", + expected[i], i, acked[i]); + pass = false; + break; + } + } + report(pass, "%s", msg); +} #endif static void gicv2_ipi_send_self(void) @@ -593,6 +611,8 @@ static void gic_test_mmio(void) static void test_its_introspection(void) {} static void test_its_trigger(void) {} static void test_its_migration(void) {} +static void test_its_pending_migration(void) {} +static void test_migrate_unmapped_collection(void) {} #else /* __aarch64__ */ @@ -798,6 +818,130 @@ do_migrate: its_send_int(dev7, 255); check_lpi_stats("dev7/eventid=255 triggers LPI 8196 on PE #2 after migration"); } + +#define ERRATA_UNMAPPED_COLLECTIONS "ERRATA_8c58be34494b" + +static void test_migrate_unmapped_collection(void) +{ + struct its_collection *col = NULL; + struct its_device *dev2 = NULL, *dev7 = NULL; + bool test_skipped = false; + int pe0 = 0; + u8 config; + + if (its_setup1()) { + test_skipped = true; + goto do_migrate; + } + + if (!errata(ERRATA_UNMAPPED_COLLECTIONS)) { + report_skip("Skipping test, as this test hangs without the fix. " + "Set %s=y to enable.", ERRATA_UNMAPPED_COLLECTIONS); + test_skipped = true; + goto do_migrate; + } + + col = its_create_collection(pe0, pe0); + dev2 = its_get_device(2); + dev7 = its_get_device(7); + + /* MAPTI with the collection unmapped */ + its_send_mapti(dev2, 8192, 0, col); + gicv3_lpi_set_config(8192, LPI_PROP_DEFAULT); + +do_migrate: + puts("Now migrate the VM, then press a key to continue...\n"); + (void)getchar(); + report_info("Migration complete"); + if (test_skipped) + return; + + /* on the destination, map the collection */ + its_send_mapc(col, true); + its_send_invall(col); + + lpi_stats_expect(2, 8196); + its_send_int(dev7, 255); + check_lpi_stats("dev7/eventid= 255 triggered LPI 8196 on PE #2"); + + config = gicv3_lpi_get_config(8192); + report(config == LPI_PROP_DEFAULT, + "Config of LPI 8192 was properly migrated"); + + lpi_stats_expect(pe0, 8192); + its_send_int(dev2, 0); + check_lpi_stats("dev2/eventid = 0 triggered LPI 8192 on PE0"); +} + +static void test_its_pending_migration(void) +{ + struct its_device *dev; + struct its_collection *collection[2]; + int *expected = calloc(nr_cpus, sizeof(int)); + int pe0 = nr_cpus - 1, pe1 = nr_cpus - 2; + bool test_skipped = false; + u64 pendbaser; + void *ptr; + int i; + + if (its_prerequisites(4)) { + test_skipped = true; + goto do_migrate; + } + + dev = its_create_device(2 /* dev id */, 8 /* nb_ites */); + its_send_mapd(dev, true); + + collection[0] = its_create_collection(pe0, pe0); + collection[1] = its_create_collection(pe1, pe1); + its_send_mapc(collection[0], true); + its_send_mapc(collection[1], true); + + /* disable lpi at redist level */ + gicv3_lpi_rdist_disable(pe0); + gicv3_lpi_rdist_disable(pe1); + + /* lpis are interleaved inbetween the 2 PEs */ + for (i = 0; i < 256; i++) { + struct its_collection *col = i % 2 ? collection[0] : + collection[1]; + int vcpu = col->target_address >> 16; + + its_send_mapti(dev, LPI(i), i, col); + gicv3_lpi_set_config(LPI(i), LPI_PROP_DEFAULT); + gicv3_lpi_set_clr_pending(vcpu, LPI(i), true); + } + its_send_invall(collection[0]); + its_send_invall(collection[1]); + + /* Clear the PTZ bit on each pendbaser */ + + expected[pe0] = 128; + expected[pe1] = 128; + + ptr = gicv3_data.redist_base[pe0] + GICR_PENDBASER; + pendbaser = readq(ptr); + writeq(pendbaser & ~GICR_PENDBASER_PTZ, ptr); + + ptr = gicv3_data.redist_base[pe1] + GICR_PENDBASER; + pendbaser = readq(ptr); + writeq(pendbaser & ~GICR_PENDBASER_PTZ, ptr); + + gicv3_lpi_rdist_enable(pe0); + gicv3_lpi_rdist_enable(pe1); + +do_migrate: + puts("Now migrate the VM, then press a key to continue...\n"); + (void)getchar(); + report_info("Migration complete"); + if (test_skipped) + return; + + /* let's wait for the 256 LPIs to be handled */ + mdelay(1000); + + check_lpi_hits(expected, "128 LPIs on both PE0 and PE1 after migration"); +} #endif int main(int argc, char **argv) @@ -839,6 +983,14 @@ int main(int argc, char **argv) report_prefix_push(argv[1]); test_its_migration(); report_prefix_pop(); + } else if (!strcmp(argv[1], "its-pending-migration")) { + report_prefix_push(argv[1]); + test_its_pending_migration(); + report_prefix_pop(); + } else if (!strcmp(argv[1], "its-migrate-unmapped-collection")) { + report_prefix_push(argv[1]); + test_migrate_unmapped_collection(); + report_prefix_pop(); } else if (strcmp(argv[1], "its-introspection") == 0) { report_prefix_push(argv[1]); test_its_introspection(); diff --git a/arm/unittests.cfg b/arm/unittests.cfg index 20a1ae2..f776b66 100644 --- a/arm/unittests.cfg +++ b/arm/unittests.cfg @@ -199,6 +199,22 @@ extra_params = -machine gic-version=3 -append 'its-migration' groups = its migration arch = arm64 +[its-pending-migration] +file = gic.flat +smp = $MAX_SMP +accel = kvm +extra_params = -machine gic-version=3 -append 'its-pending-migration' +groups = its migration +arch = arm64 + +[its-migrate-unmapped-collection] +file = gic.flat +smp = $MAX_SMP +accel = kvm +extra_params = -machine gic-version=3 -append 'its-migrate-unmapped-collection' +groups = its migration +arch = arm64 + # Test PSCI emulation [psci] file = psci.flat @@ -5,4 +5,5 @@ 9e3f7a296940 : 4.9 : arm64: KVM: pmu: Fix AArch32 cycle counter access 7b6b46311a85 : 4.11 : KVM: arm/arm64: Emulate the EL1 phys timer registers 6c7a5dce22b3 : 4.12 : KVM: arm/arm64: fix races in kvm_psci_vcpu_on +8c58be34494b : 5.6 : KVM: arm/arm64: vgic-its: Fix restoration of unmapped collections #---------------:-------------------------------:--------------------------------------------------- |