[v5,00/10] KVM: s390: Extend MEM_OP ioctl by storage key checked cmpxchg

Message ID 20230110202632.2533978-1-scgl@linux.ibm.com
Headers
Series KVM: s390: Extend MEM_OP ioctl by storage key checked cmpxchg |

Message

Janis Schoetterl-Glausch Jan. 10, 2023, 8:26 p.m. UTC
  User space can use the MEM_OP ioctl to make storage key checked reads
and writes to the guest, however, it has no way of performing atomic,
key checked, accesses to the guest.
Extend the MEM_OP ioctl in order to allow for this, by adding a cmpxchg
mode. For now, support this mode for absolute accesses only.

This mode can be use, for example, to set the device-state-change
indicator and the adapter-local-summary indicator atomically.

Also contains some fixes/changes for the memop selftest independent of
the cmpxchg changes.

v4 -> v5
 * refuse cmpxchg if not write (thanks Thomas)
 * minor doc changes (thanks Claudio)
 * picked up R-b's (thanks Thomas & Claudio)
 * memop selftest fixes
 * rebased

v3 -> v4
 * no functional change intended
 * rework documentation a bit
 * name extension cap cmpxchg bit
 * picked up R-b (thanks Thomas)
 * various changes (rename variable, comments, ...) see range-diff below

v2 -> v3
 * rebase onto the wip/cmpxchg_user_key branch in the s390 kernel repo
 * use __uint128_t instead of unsigned __int128
 * put moving of testlist into main into separate patch
 * pick up R-b's (thanks Nico)

v1 -> v2
 * get rid of xrk instruction for cmpxchg byte and short implementation
 * pass old parameter via pointer instead of in mem_op struct
 * indicate failure of cmpxchg due to wrong old value by special return
   code
 * picked up R-b's (thanks Thomas)

Janis Schoetterl-Glausch (10):
  KVM: s390: Extend MEM_OP ioctl by storage key checked cmpxchg
  Documentation: KVM: s390: Describe KVM_S390_MEMOP_F_CMPXCHG
  KVM: s390: selftest: memop: Pass mop_desc via pointer
  KVM: s390: selftest: memop: Replace macros by functions
  KVM: s390: selftest: memop: Move testlist into main
  KVM: s390: selftest: memop: Add cmpxchg tests
  KVM: s390: selftest: memop: Add bad address test
  KVM: s390: selftest: memop: Fix typo
  KVM: s390: selftest: memop: Fix wrong address being used in test
  KVM: s390: selftest: memop: Fix integer literal

 Documentation/virt/kvm/api.rst            |  20 +-
 include/uapi/linux/kvm.h                  |   7 +
 arch/s390/kvm/gaccess.h                   |   3 +
 arch/s390/kvm/gaccess.c                   | 102 ++++
 arch/s390/kvm/kvm-s390.c                  |  41 +-
 tools/testing/selftests/kvm/s390x/memop.c | 675 +++++++++++++++++-----
 6 files changed, 696 insertions(+), 152 deletions(-)

Range-diff against v4:
 1:  75a20d2e27f2 !  1:  6adc166ee141 KVM: s390: Extend MEM_OP ioctl by storage key checked cmpxchg
    @@ arch/s390/kvm/kvm-s390.c: static int kvm_s390_vm_mem_op(struct kvm *kvm, struct
     +		 */
     +		if (mop->size > sizeof(new))
     +			return -EINVAL;
    ++		if (mop->op != KVM_S390_MEMOP_ABSOLUTE_WRITE)
    ++			return -EINVAL;
     +		if (copy_from_user(&new.raw[off_in_quad], uaddr, mop->size))
     +			return -EFAULT;
     +		if (copy_from_user(&old.raw[off_in_quad], old_addr, mop->size))
 2:  5c5ad96a4c81 !  2:  fce9a063ab70 Documentation: KVM: s390: Describe KVM_S390_MEMOP_F_CMPXCHG
    @@ Commit message
         checked) cmpxchg operations on guest memory.
     
         Signed-off-by: Janis Schoetterl-Glausch <scgl@linux.ibm.com>
    +    Reviewed-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
     
      ## Documentation/virt/kvm/api.rst ##
     @@ Documentation/virt/kvm/api.rst: The fields in each entry are defined as follows:
    @@ Documentation/virt/kvm/api.rst: The fields in each entry are defined as follows:
      :Returns: = 0 on success,
                < 0 on generic error (e.g. -EFAULT or -ENOMEM),
     -          > 0 if an exception occurred while walking the page tables
    -+          16 bit program exception code if the access causes such an exception
    -+          other code > 0xffff with special meaning
    ++          16 bit program exception code if the access causes such an exception,
    ++          other code > 0xffff with special meaning.
      
      Read or write data from/to the VM's memory.
      The KVM_CAP_S390_MEM_OP_EXTENSION capability specifies what functionality is
 3:  9cbcb313d91d =  3:  94c1165ae24a KVM: s390: selftest: memop: Pass mop_desc via pointer
 4:  21d98b9deaae !  4:  027c87eee0ac KVM: s390: selftest: memop: Replace macros by functions
    @@ Commit message
         need the exta flexibility.
     
         Signed-off-by: Janis Schoetterl-Glausch <scgl@linux.ibm.com>
    +    Reviewed-by: Thomas Huth <thuth@redhat.com>
     
      ## tools/testing/selftests/kvm/s390x/memop.c ##
     @@ tools/testing/selftests/kvm/s390x/memop.c: struct mop_desc {
 5:  866fcd7fbc97 !  5:  16ac410ecc0f KVM: s390: selftest: memop: Move testlist into main
    @@ tools/testing/selftests/kvm/s390x/memop.c: static void test_errors(void)
      {
      	int extension_cap, idx;
      
    -+	setbuf(stdout, NULL);	/* Tell stdout not to buffer its content */
      	TEST_REQUIRE(kvm_has_cap(KVM_CAP_S390_MEM_OP));
     +	extension_cap = kvm_check_cap(KVM_CAP_S390_MEM_OP_EXTENSION);
      
    --	setbuf(stdout, NULL);	/* Tell stdout not to buffer its content */
    +-	ksft_print_header();
     +	struct testdef {
     +		const char *name;
     +		void (*test)(void);
    @@ tools/testing/selftests/kvm/s390x/memop.c: static void test_errors(void)
     +		},
     +	};
      
    - 	ksft_print_header();
    --
    ++	ksft_print_header();
      	ksft_set_plan(ARRAY_SIZE(testlist));
      
     -	extension_cap = kvm_check_cap(KVM_CAP_S390_MEM_OP_EXTENSION);
    @@ tools/testing/selftests/kvm/s390x/memop.c: static void test_errors(void)
     -			ksft_test_result_skip("%s - extension level %d not supported\n",
     -					      testlist[idx].name,
     -					      testlist[idx].extension);
    -+			ksft_test_result_skip("%s - requirements not met (kernel has extension cap %#x\n)",
    ++			ksft_test_result_skip("%s - requirements not met (kernel has extension cap %#x)\n",
     +					      testlist[idx].name, extension_cap);
      		}
      	}
 6:  c3e473677786 !  6:  214281b6eb96 KVM: s390: selftest: memop: Add cmpxchg tests
    @@ tools/testing/selftests/kvm/s390x/memop.c: static void test_errors(void)
     +		rv = ERR_MOP(t.vm, ABSOLUTE, WRITE, mem1, i, GADDR((void *)~0xfffUL),
     +			     CMPXCHG_OLD(&old));
     +		TEST_ASSERT(rv > 0, "ioctl allows bad guest address for cmpxchg");
    ++		rv = ERR_MOP(t.vm, ABSOLUTE, READ, mem1, i, GADDR_V(mem1),
    ++			     CMPXCHG_OLD(&old));
    ++		TEST_ASSERT(rv == -1 && errno == EINVAL,
    ++			    "ioctl allows read cmpxchg call");
     +	}
     +	for (i = 2; i <= 16; i *= 2) {
     +		rv = ERR_MOP(t.vm, ABSOLUTE, WRITE, mem1, i, GADDR_V(mem1 + 1),
 7:  90288760656e =  7:  2d6776733e64 KVM: s390: selftest: memop: Add bad address test
 8:  e3d4b9b2ba61 =  8:  8c49eafd2881 KVM: s390: selftest: memop: Fix typo
 9:  13fedd6e3d9e =  9:  0af907110b34 KVM: s390: selftest: memop: Fix wrong address being used in test
 -:  ------------ > 10:  886c80b2bdce KVM: s390: selftest: memop: Fix integer literal
  

Comments

Janosch Frank Jan. 11, 2023, 11:31 a.m. UTC | #1
On 1/10/23 21:26, Janis Schoetterl-Glausch wrote:
> User space can use the MEM_OP ioctl to make storage key checked reads
> and writes to the guest, however, it has no way of performing atomic,
> key checked, accesses to the guest.
> Extend the MEM_OP ioctl in order to allow for this, by adding a cmpxchg
> mode. For now, support this mode for absolute accesses only.
> 
> This mode can be use, for example, to set the device-state-change
> indicator and the adapter-local-summary indicator atomically.
> 
> Also contains some fixes/changes for the memop selftest independent of
> the cmpxchg changes.

Since the selftest fixes seem to apply and run without the new code I'm 
considering splitting them off entirely.

Most of them have reviews already and they are lower risk anyway so we 
could add them to devel rather soonish.