2023-01-10 21:01:03

by Janis Schoetterl-Glausch

[permalink] [raw]
Subject: [PATCH v5 00/10] KVM: s390: Extend MEM_OP ioctl by storage key checked cmpxchg

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 <[email protected]>
+ Reviewed-by: Claudio Imbrenda <[email protected]>

## 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 <[email protected]>
+ Reviewed-by: Thomas Huth <[email protected]>

## 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
--
2.34.1


2023-01-10 21:13:14

by Janis Schoetterl-Glausch

[permalink] [raw]
Subject: [PATCH v5 10/10] KVM: s390: selftest: memop: Fix integer literal

The address is a 64 bit value, specifying a 32 bit value can crash the
guest. In this case things worked out with -O2 but not -O0.

Signed-off-by: Janis Schoetterl-Glausch <[email protected]>
Fixes: 1bb873495a9e ("KVM: s390: selftests: Add more copy memop tests")
---
tools/testing/selftests/kvm/s390x/memop.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/testing/selftests/kvm/s390x/memop.c b/tools/testing/selftests/kvm/s390x/memop.c
index 03f74c6c9fee..2173f7bca601 100644
--- a/tools/testing/selftests/kvm/s390x/memop.c
+++ b/tools/testing/selftests/kvm/s390x/memop.c
@@ -838,7 +838,7 @@ static void guest_copy_key_fetch_prot_override(void)
GUEST_SYNC(STAGE_INITED);
set_storage_key_range(0, PAGE_SIZE, 0x18);
set_storage_key_range((void *)last_page_addr, PAGE_SIZE, 0x0);
- asm volatile ("sske %[key],%[addr]\n" :: [addr] "r"(0), [key] "r"(0x18) : "cc");
+ asm volatile ("sske %[key],%[addr]\n" :: [addr] "r"(0L), [key] "r"(0x18) : "cc");
GUEST_SYNC(STAGE_SKEYS_SET);

for (;;) {
--
2.34.1

2023-01-10 21:20:13

by Janis Schoetterl-Glausch

[permalink] [raw]
Subject: [PATCH v5 09/10] KVM: s390: selftest: memop: Fix wrong address being used in test

The guest code sets the key for mem1 only. In order to provoke a
protection exception the test codes needs to address mem1.

Signed-off-by: Janis Schoetterl-Glausch <[email protected]>
Reviewed-by: Nico Boehr <[email protected]>
---
tools/testing/selftests/kvm/s390x/memop.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/tools/testing/selftests/kvm/s390x/memop.c b/tools/testing/selftests/kvm/s390x/memop.c
index 238a3f20bcc1..03f74c6c9fee 100644
--- a/tools/testing/selftests/kvm/s390x/memop.c
+++ b/tools/testing/selftests/kvm/s390x/memop.c
@@ -756,9 +756,9 @@ static void test_errors_key(void)

/* vm/vcpu, mismatching keys, fetch protection in effect */
CHECK_N_DO(ERR_PROT_MOP, t.vcpu, LOGICAL, WRITE, mem1, t.size, GADDR_V(mem1), KEY(2));
- CHECK_N_DO(ERR_PROT_MOP, t.vcpu, LOGICAL, READ, mem2, t.size, GADDR_V(mem2), KEY(2));
+ CHECK_N_DO(ERR_PROT_MOP, t.vcpu, LOGICAL, READ, mem2, t.size, GADDR_V(mem1), KEY(2));
CHECK_N_DO(ERR_PROT_MOP, t.vm, ABSOLUTE, WRITE, mem1, t.size, GADDR_V(mem1), KEY(2));
- CHECK_N_DO(ERR_PROT_MOP, t.vm, ABSOLUTE, READ, mem2, t.size, GADDR_V(mem2), KEY(2));
+ CHECK_N_DO(ERR_PROT_MOP, t.vm, ABSOLUTE, READ, mem2, t.size, GADDR_V(mem1), KEY(2));

kvm_vm_free(t.kvm_vm);
}
--
2.34.1

2023-01-11 11:41:13

by Janosch Frank

[permalink] [raw]
Subject: Re: [PATCH v5 00/10] KVM: s390: Extend MEM_OP ioctl by storage key checked cmpxchg

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.