Regression test for the bug where ESSA emulation in migration mode silently dropped addressing exceptions instead of injecting PGM_ADDRESSING into the guest.
The test is integrated into cmma_test alongside the existing CMMA migration tests. Signed-off-by: Gautam Gala <[email protected]> Acked-by: Christian Borntraeger <[email protected]> --- tools/testing/selftests/kvm/s390/cmma_test.c | 79 ++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/tools/testing/selftests/kvm/s390/cmma_test.c b/tools/testing/selftests/kvm/s390/cmma_test.c index 15d81b2ed7ad..2b351b4fc894 100644 --- a/tools/testing/selftests/kvm/s390/cmma_test.c +++ b/tools/testing/selftests/kvm/s390/cmma_test.c @@ -8,6 +8,7 @@ * Nico Boehr <[email protected]> */ #include <fcntl.h> +#include <signal.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -18,6 +19,12 @@ #include "kselftest.h" #include "ucall_common.h" #include "processor.h" +#include "sie.h" + +#define PGM_ADDRESSING 0x05 +#define VCPU_RUN_TIMEOUT_S 2 +#define UNMAPPED_GFN 0xffff000UL +#define __LC_PGM_NEW_PSW 0x1d0 #define MAIN_PAGE_COUNT 512 @@ -651,6 +658,77 @@ static void test_get_skip_holes(void) assert_no_pages_cmma_dirty(vm); } +static void pgm_handler_c(void) +{ + GUEST_SYNC(PGM_ADDRESSING); + for (;;) + ; +} + +static void guest_essa_unmapped(void) +{ + unsigned long addr = UNMAPPED_GFN << PAGE_SHIFT; + + asm volatile( + " lg 2,%[addr]\n" + /* ESSA r1,r2,orc=1 */ + " .insn rrf,0xb9ab0000,1,2,1,0\n" + "0: j 0b\n" + : + : [addr] "Q"(addr) + : "r1", "r2", "cc", "memory" + ); +} + +static void handle_alarm(int sig __maybe_unused) +{ + ksft_test_result_fail( + "ESSA migration mode: vcpu_run timed out - PGM_ADDRESSING was not injected\n"); + ksft_finished(); +} + +static void test_essa_migration_pgm(void) +{ + struct kvm_vcpu *vcpu; + struct kvm_vm *vm; + struct ucall uc; + char *lowcore; + u64 pgm_psw[2] = {}; + + vm = __vm_create(VM_SHAPE_DEFAULT, 1, 0); + + enable_cmma(vm); + + vcpu = vm_vcpu_add(vm, 0, guest_essa_unmapped); + + lowcore = addr_gpa2hva(vm, 0); + pgm_psw[0] = vcpu->run->psw_mask; + pgm_psw[1] = (u64)pgm_handler_c; + memcpy(lowcore + __LC_PGM_NEW_PSW, pgm_psw, 16); + + /* Migration mode requires dirty tracking on all memslots. */ + vm_mem_region_set_flags(vm, 0, KVM_MEM_LOG_DIRTY_PAGES); + enable_migration_mode(vm); + + signal(SIGALRM, handle_alarm); + alarm(VCPU_RUN_TIMEOUT_S); + + vcpu_run(vcpu); + + alarm(0); + + TEST_ASSERT_EQ(vcpu->run->exit_reason, KVM_EXIT_S390_SIEIC); + TEST_ASSERT_EQ(vcpu->run->s390_sieic.icptcode, ICPT_INST); + TEST_ASSERT_EQ(vcpu->run->s390_sieic.ipa & 0xff00, 0x8300); /* DIAG */ + TEST_ASSERT_EQ(vcpu->run->s390_sieic.ipb >> 16, 0x501); + + get_ucall(vcpu, &uc); + TEST_ASSERT_EQ(uc.cmd, UCALL_SYNC); + TEST_ASSERT_EQ(uc.args[1], PGM_ADDRESSING); + + kvm_vm_free(vm); +} + struct testdef { const char *name; void (*test)(void); @@ -659,6 +737,7 @@ struct testdef { { "GET_CMMA_BITS: basic calls", test_get_cmma_basic }, { "GET_CMMA_BITS: all pages are dirty initially", test_get_initial_dirty }, { "GET_CMMA_BITS: holes are skipped", test_get_skip_holes }, + { "ESSA migration mode: PGM_ADDRESSING injected on unmapped GFN", test_essa_migration_pgm }, }; /** -- 2.55.0

