KVM: selftests: Add a test for the KVM_S390_MEM_OP ioctl
PATCH v3 1/1 KVM: selftests: Add a test for the KVM_S390_MEM_OP ioctl
Check that we can write and read the guest memory with this s390x ioctl, and that some error cases are handled correctly.
---
v3:
- Replaced wrong copy-n-pasted report string with a proper one
- Check for errno after calling the ioctl with size = 0
tools/testing/selftests/kvm/Makefile | 1 + tools/testing/selftests/kvm/s390x/memop.c | 166 ++++++++++++++++++++++ 2 files changed, 167 insertions(+) create mode 100644 tools/testing/selftests/kvm/s390x/memop.c
tools/testing/selftests/kvm/Makefile +1 -0
@@ -32,6 +32,7 @@ TEST_GEN_PROGS_aarch64 += clear_dirty_log_test TEST_GEN_PROGS_aarch64 += dirty_log_test TEST_GEN_PROGS_aarch64 += kvm_create_max_vcpus +TEST_GEN_PROGS_s390x = s390x/memop TEST_GEN_PROGS_s390x += s390x/sync_regs_test TEST_GEN_PROGS_s390x += dirty_log_test TEST_GEN_PROGS_s390x += kvm_create_max_vcpus
tools/testing/selftests/kvm/s390x/memop.c new file +166 -0
166 lines not on this page · raw message
Signature · 1 line
2.18.1
Quoted 8 lines · Thomas Huth
Check that we can write and read the guest memory with this s390x ioctl, and that some error cases are handled correctly.
Signed-off-by Thomas Huth <[email protected]>---
v3:
- Replaced wrong copy-n-pasted report string with a proper one
- Check for errno after calling the ioctl with size = 0
the test succeeds (as the vmalloc fails) but dmesg then has the warning. Do we have a chance to parse dmesg somehow?
I will apply this nevertheless for the time being together with the fix.
Quoted 191 lines
tools/testing/selftests/kvm/Makefile | 1 + tools/testing/selftests/kvm/s390x/memop.c | 166 ++++++++++++++++++++++ 2 files changed, 167 insertions(+) create mode 100644 tools/testing/selftests/kvm/s390x/memop.ctools/testing/selftests/kvm/Makefile +1
-0@@ -32,6 +32,7 @@ TEST_GEN_PROGS_aarch64 += clear_dirty_log_test TEST_GEN_PROGS_aarch64 += dirty_log_test TEST_GEN_PROGS_aarch64 += kvm_create_max_vcpus +TEST_GEN_PROGS_s390x = s390x/memop TEST_GEN_PROGS_s390x += s390x/sync_regs_test TEST_GEN_PROGS_s390x += dirty_log_test TEST_GEN_PROGS_s390x += kvm_create_max_vcpustools/testing/selftests/kvm/s390x/memop.c new file +166
-0@@ -0,0 +1,166 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* +* Test for s390x KVM_S390_MEM_OP +* +* Copyright (C) 2019, Red Hat, Inc. +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/ioctl.h> + +#include "test_util.h" +#include "kvm_util.h" + +#define VCPU_ID 1 + +static uint8_t mem1[65536 ]; +static uint8_t mem2[65536 ]; + +static void guest_code (void ) +{ +int i; + +for (;;) { +for (i =0 ; i <sizeof (mem2); i++) + mem2[i] = mem1[i]; +GUEST_SYNC (0 ); + } +} + +int main (int argc,char *argv[]) +{ +struct kvm_vm *vm; +struct kvm_run *run; +struct kvm_s390_mem_op ksmo; +int rv, i, maxsize; + +setbuf (stdout,NULL );/* Tell stdout not to buffer its content */ + + maxsize =kvm_check_cap (KVM_CAP_S390_MEM_OP ); +if (!maxsize) { +fprintf (stderr,"CAP_S390_MEM_OP not supported -> skip test\n" ); +exit (KSFT_SKIP ); + } +if (maxsize >sizeof (mem1)) + maxsize =sizeof (mem1); + +/* Create VM */ + vm =vm_create_default (VCPU_ID ,0 , guest_code); + run =vcpu_state (vm,VCPU_ID ); + +for (i =0 ; i <sizeof (mem1); i++) + mem1[i] = i * i + i; + +/* Set the first array */ + ksmo.gaddr =addr_gva2gpa (vm, (uintptr_t )mem1); + ksmo.flags =0 ; + ksmo.size = maxsize; + ksmo.op =KVM_S390_MEMOP_LOGICAL_WRITE ; + ksmo.buf = (uintptr_t )mem1; + ksmo.ar =0 ; +vcpu_ioctl (vm,VCPU_ID ,KVM_S390_MEM_OP , &ksmo); + +/* Let the guest code copy the first array to the second */ +vcpu_run (vm,VCPU_ID ); +TEST_ASSERT (run->exit_reason ==KVM_EXIT_S390_SIEIC , +"Unexpected exit reason: %u (%s)\n" , + run->exit_reason, +exit_reason_str (run->exit_reason)); + +memset (mem2,0xaa ,sizeof (mem2)); + +/* Get the second array */ + ksmo.gaddr = (uintptr_t )mem2; + ksmo.flags =0 ; + ksmo.size = maxsize; + ksmo.op =KVM_S390_MEMOP_LOGICAL_READ ; + ksmo.buf = (uintptr_t )mem2; + ksmo.ar =0 ; +vcpu_ioctl (vm,VCPU_ID ,KVM_S390_MEM_OP , &ksmo); + +TEST_ASSERT (!memcmp (mem1, mem2, maxsize), +"Memory contents do not match!" ); + +/* Check error conditions - first bad size: */ + ksmo.gaddr = (uintptr_t )mem1; + ksmo.flags =0 ; + ksmo.size =-1 ; + ksmo.op =KVM_S390_MEMOP_LOGICAL_WRITE ; + ksmo.buf = (uintptr_t )mem1; + ksmo.ar =0 ; + rv =_vcpu_ioctl (vm,VCPU_ID ,KVM_S390_MEM_OP , &ksmo); +TEST_ASSERT (rv ==-1 && errno ==E2BIG ,"ioctl allows insane sizes" ); + +/* Zero size: */ + ksmo.gaddr = (uintptr_t )mem1; + ksmo.flags =0 ; + ksmo.size =0 ; + ksmo.op =KVM_S390_MEMOP_LOGICAL_WRITE ; + ksmo.buf = (uintptr_t )mem1; + ksmo.ar =0 ; + rv =_vcpu_ioctl (vm,VCPU_ID ,KVM_S390_MEM_OP , &ksmo); +TEST_ASSERT (rv ==-1 && (errno ==EINVAL || errno ==ENOMEM ), +"ioctl allows 0 as size" ); + +/* Bad flags: */ + ksmo.gaddr = (uintptr_t )mem1; + ksmo.flags =-1 ; + ksmo.size = maxsize; + ksmo.op =KVM_S390_MEMOP_LOGICAL_WRITE ; + ksmo.buf = (uintptr_t )mem1; + ksmo.ar =0 ; + rv =_vcpu_ioctl (vm,VCPU_ID ,KVM_S390_MEM_OP , &ksmo); +TEST_ASSERT (rv ==-1 && errno ==EINVAL ,"ioctl allows all flags" ); + +/* Bad operation: */ + ksmo.gaddr = (uintptr_t )mem1; + ksmo.flags =0 ; + ksmo.size = maxsize; + ksmo.op =-1 ; + ksmo.buf = (uintptr_t )mem1; + ksmo.ar =0 ; + rv =_vcpu_ioctl (vm,VCPU_ID ,KVM_S390_MEM_OP , &ksmo); +TEST_ASSERT (rv ==-1 && errno ==EINVAL ,"ioctl allows bad operations" ); + +/* Bad guest address: */ + ksmo.gaddr = ~0xfffUL ; + ksmo.flags =KVM_S390_MEMOP_F_CHECK_ONLY ; + ksmo.size = maxsize; + ksmo.op =KVM_S390_MEMOP_LOGICAL_WRITE ; + ksmo.buf = (uintptr_t )mem1; + ksmo.ar =0 ; + rv =_vcpu_ioctl (vm,VCPU_ID ,KVM_S390_MEM_OP , &ksmo); +TEST_ASSERT (rv >0 ,"ioctl does not report bad guest memory access" ); + +/* Bad host address: */ + ksmo.gaddr = (uintptr_t )mem1; + ksmo.flags =0 ; + ksmo.size = maxsize; + ksmo.op =KVM_S390_MEMOP_LOGICAL_WRITE ; + ksmo.buf =0 ; + ksmo.ar =0 ; + rv =_vcpu_ioctl (vm,VCPU_ID ,KVM_S390_MEM_OP , &ksmo); +TEST_ASSERT (rv ==-1 && errno ==EFAULT , +"ioctl does not report bad host memory address" ); + +/* Bad access register: */ + run->psw_mask &= ~(3UL << (63 -17 )); + run->psw_mask |=1UL << (63 -17 );/* Enable AR mode */ +vcpu_run (vm,VCPU_ID );/* To sync new state to SIE block */ + ksmo.gaddr = (uintptr_t )mem1; + ksmo.flags =0 ; + ksmo.size = maxsize; + ksmo.op =KVM_S390_MEMOP_LOGICAL_WRITE ; + ksmo.buf = (uintptr_t )mem1; + ksmo.ar =17 ; + rv =_vcpu_ioctl (vm,VCPU_ID ,KVM_S390_MEM_OP , &ksmo); +TEST_ASSERT (rv ==-1 && errno ==EINVAL ,"ioctl allows ARs > 15" ); + run->psw_mask &= ~(3UL << (63 -17 ));/* Disable AR mode */ +vcpu_run (vm,VCPU_ID );/* Run to sync new state */ + +kvm_vm_free (vm); + +return 0 ; +}
Quoted 6 lines · Christian Borntraeger
Quoted 3 lines · Thomas Huth
Check that we can write and read the guest memory with this s390x ioctl, and that some error cases are handled correctly.
Quoted 8 lines
Quoted 5 lines
Signed-off-by Thomas Huth <[email protected]>---
v3:
- Replaced wrong copy-n-pasted report string with a proper one
- Check for errno after calling the ioctl with size = 0the test succeeds (as the vmalloc fails) but dmesg then has the warning. Do we have a chance to parse dmesg somehow?
I'm not aware of an easy way to do this from within the KVM selftests.
Quoted 1 line
I will apply this nevertheless for the time being together with the fix.
Thanks!
Thomas
Christian Borntraeger
Appliedthanks applied.
Quoted 199 lines · Thomas Huth
Check that we can write and read the guest memory with this s390x ioctl, and that some error cases are handled correctly.
Signed-off-by Thomas Huth <[email protected]>---
v3:
- Replaced wrong copy-n-pasted report string with a proper one
- Check for errno after calling the ioctl with size = 0tools/testing/selftests/kvm/Makefile | 1 + tools/testing/selftests/kvm/s390x/memop.c | 166 ++++++++++++++++++++++ 2 files changed, 167 insertions(+) create mode 100644 tools/testing/selftests/kvm/s390x/memop.ctools/testing/selftests/kvm/Makefile +1
-0@@ -32,6 +32,7 @@ TEST_GEN_PROGS_aarch64 += clear_dirty_log_test TEST_GEN_PROGS_aarch64 += dirty_log_test TEST_GEN_PROGS_aarch64 += kvm_create_max_vcpus +TEST_GEN_PROGS_s390x = s390x/memop TEST_GEN_PROGS_s390x += s390x/sync_regs_test TEST_GEN_PROGS_s390x += dirty_log_test TEST_GEN_PROGS_s390x += kvm_create_max_vcpustools/testing/selftests/kvm/s390x/memop.c new file +166
-0@@ -0,0 +1,166 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* +* Test for s390x KVM_S390_MEM_OP +* +* Copyright (C) 2019, Red Hat, Inc. +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/ioctl.h> + +#include "test_util.h" +#include "kvm_util.h" + +#define VCPU_ID 1 + +static uint8_t mem1[65536 ]; +static uint8_t mem2[65536 ]; + +static void guest_code (void ) +{ +int i; + +for (;;) { +for (i =0 ; i <sizeof (mem2); i++) + mem2[i] = mem1[i]; +GUEST_SYNC (0 ); + } +} + +int main (int argc,char *argv[]) +{ +struct kvm_vm *vm; +struct kvm_run *run; +struct kvm_s390_mem_op ksmo; +int rv, i, maxsize; + +setbuf (stdout,NULL );/* Tell stdout not to buffer its content */ + + maxsize =kvm_check_cap (KVM_CAP_S390_MEM_OP ); +if (!maxsize) { +fprintf (stderr,"CAP_S390_MEM_OP not supported -> skip test\n" ); +exit (KSFT_SKIP ); + } +if (maxsize >sizeof (mem1)) + maxsize =sizeof (mem1); + +/* Create VM */ + vm =vm_create_default (VCPU_ID ,0 , guest_code); + run =vcpu_state (vm,VCPU_ID ); + +for (i =0 ; i <sizeof (mem1); i++) + mem1[i] = i * i + i; + +/* Set the first array */ + ksmo.gaddr =addr_gva2gpa (vm, (uintptr_t )mem1); + ksmo.flags =0 ; + ksmo.size = maxsize; + ksmo.op =KVM_S390_MEMOP_LOGICAL_WRITE ; + ksmo.buf = (uintptr_t )mem1; + ksmo.ar =0 ; +vcpu_ioctl (vm,VCPU_ID ,KVM_S390_MEM_OP , &ksmo); + +/* Let the guest code copy the first array to the second */ +vcpu_run (vm,VCPU_ID ); +TEST_ASSERT (run->exit_reason ==KVM_EXIT_S390_SIEIC , +"Unexpected exit reason: %u (%s)\n" , + run->exit_reason, +exit_reason_str (run->exit_reason)); + +memset (mem2,0xaa ,sizeof (mem2)); + +/* Get the second array */ + ksmo.gaddr = (uintptr_t )mem2; + ksmo.flags =0 ; + ksmo.size = maxsize; + ksmo.op =KVM_S390_MEMOP_LOGICAL_READ ; + ksmo.buf = (uintptr_t )mem2; + ksmo.ar =0 ; +vcpu_ioctl (vm,VCPU_ID ,KVM_S390_MEM_OP , &ksmo); + +TEST_ASSERT (!memcmp (mem1, mem2, maxsize), +"Memory contents do not match!" ); + +/* Check error conditions - first bad size: */ + ksmo.gaddr = (uintptr_t )mem1; + ksmo.flags =0 ; + ksmo.size =-1 ; + ksmo.op =KVM_S390_MEMOP_LOGICAL_WRITE ; + ksmo.buf = (uintptr_t )mem1; + ksmo.ar =0 ; + rv =_vcpu_ioctl (vm,VCPU_ID ,KVM_S390_MEM_OP , &ksmo); +TEST_ASSERT (rv ==-1 && errno ==E2BIG ,"ioctl allows insane sizes" ); + +/* Zero size: */ + ksmo.gaddr = (uintptr_t )mem1; + ksmo.flags =0 ; + ksmo.size =0 ; + ksmo.op =KVM_S390_MEMOP_LOGICAL_WRITE ; + ksmo.buf = (uintptr_t )mem1; + ksmo.ar =0 ; + rv =_vcpu_ioctl (vm,VCPU_ID ,KVM_S390_MEM_OP , &ksmo); +TEST_ASSERT (rv ==-1 && (errno ==EINVAL || errno ==ENOMEM ), +"ioctl allows 0 as size" ); + +/* Bad flags: */ + ksmo.gaddr = (uintptr_t )mem1; + ksmo.flags =-1 ; + ksmo.size = maxsize; + ksmo.op =KVM_S390_MEMOP_LOGICAL_WRITE ; + ksmo.buf = (uintptr_t )mem1; + ksmo.ar =0 ; + rv =_vcpu_ioctl (vm,VCPU_ID ,KVM_S390_MEM_OP , &ksmo); +TEST_ASSERT (rv ==-1 && errno ==EINVAL ,"ioctl allows all flags" ); + +/* Bad operation: */ + ksmo.gaddr = (uintptr_t )mem1; + ksmo.flags =0 ; + ksmo.size = maxsize; + ksmo.op =-1 ; + ksmo.buf = (uintptr_t )mem1; + ksmo.ar =0 ; + rv =_vcpu_ioctl (vm,VCPU_ID ,KVM_S390_MEM_OP , &ksmo); +TEST_ASSERT (rv ==-1 && errno ==EINVAL ,"ioctl allows bad operations" ); + +/* Bad guest address: */ + ksmo.gaddr = ~0xfffUL ; + ksmo.flags =KVM_S390_MEMOP_F_CHECK_ONLY ; + ksmo.size = maxsize; + ksmo.op =KVM_S390_MEMOP_LOGICAL_WRITE ; + ksmo.buf = (uintptr_t )mem1; + ksmo.ar =0 ; + rv =_vcpu_ioctl (vm,VCPU_ID ,KVM_S390_MEM_OP , &ksmo); +TEST_ASSERT (rv >0 ,"ioctl does not report bad guest memory access" ); + +/* Bad host address: */ + ksmo.gaddr = (uintptr_t )mem1; + ksmo.flags =0 ; + ksmo.size = maxsize; + ksmo.op =KVM_S390_MEMOP_LOGICAL_WRITE ; + ksmo.buf =0 ; + ksmo.ar =0 ; + rv =_vcpu_ioctl (vm,VCPU_ID ,KVM_S390_MEM_OP , &ksmo); +TEST_ASSERT (rv ==-1 && errno ==EFAULT , +"ioctl does not report bad host memory address" ); + +/* Bad access register: */ + run->psw_mask &= ~(3UL << (63 -17 )); + run->psw_mask |=1UL << (63 -17 );/* Enable AR mode */ +vcpu_run (vm,VCPU_ID );/* To sync new state to SIE block */ + ksmo.gaddr = (uintptr_t )mem1; + ksmo.flags =0 ; + ksmo.size = maxsize; + ksmo.op =KVM_S390_MEMOP_LOGICAL_WRITE ; + ksmo.buf = (uintptr_t )mem1; + ksmo.ar =17 ; + rv =_vcpu_ioctl (vm,VCPU_ID ,KVM_S390_MEM_OP , &ksmo); +TEST_ASSERT (rv ==-1 && errno ==EINVAL ,"ioctl allows ARs > 15" ); + run->psw_mask &= ~(3UL << (63 -17 ));/* Disable AR mode */ +vcpu_run (vm,VCPU_ID );/* Run to sync new state */ + +kvm_vm_free (vm); + +return 0 ; +}