aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Auger <eric.auger@redhat.com>2020-04-02 16:52:27 +0200
committerAndrew Jones <drjones@redhat.com>2020-04-04 10:03:44 +0200
commitde582149c5be94a1ff7d3d8ee3526501b26c7f03 (patch)
tree2b2f9107dde947ee7799830f004ad3bf3aa5540f
parent64260a5fb31b8b91a76f85ee156c265e5dfa0b1b (diff)
downloadkvm-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.c152
-rw-r--r--arm/unittests.cfg16
-rw-r--r--errata.txt1
3 files changed, 169 insertions, 0 deletions
diff --git a/arm/gic.c b/arm/gic.c
index d98d70a..dc1e88c 100644
--- a/arm/gic.c
+++ b/arm/gic.c
@@ -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
diff --git a/errata.txt b/errata.txt
index 7d6abc2..b66afaa 100644
--- a/errata.txt
+++ b/errata.txt
@@ -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
#---------------:-------------------------------:---------------------------------------------------