On 30/07/2019 12.48, Andrew Jones wrote: > On Tue, Jul 30, 2019 at 12:01:11PM +0200, Thomas Huth wrote: >> On s390x, we can neither exit via PIO nor MMIO, but have to use >> an instruction like DIAGNOSE. While we're at it, rename UCALL_PIO >> to UCALL_DEFAULT, since PIO only works on x86 anyway, and this >> way we can re-use the "default" type for the DIAGNOSE exit on s390x. >> >> Now that ucall() is implemented, we can use it in the sync_reg_test >> on s390x, too. >> >> Signed-off-by: Thomas Huth <thuth@xxxxxxxxxx> >> --- >> .../testing/selftests/kvm/include/kvm_util.h | 2 +- >> tools/testing/selftests/kvm/lib/ucall.c | 34 +++++++++++++++---- >> .../selftests/kvm/s390x/sync_regs_test.c | 6 ++-- >> 3 files changed, 32 insertions(+), 10 deletions(-) >> >> diff --git a/tools/testing/selftests/kvm/include/kvm_util.h b/tools/testing/selftests/kvm/include/kvm_util.h >> index e0e66b115ef2..c37aea2e33e5 100644 >> --- a/tools/testing/selftests/kvm/include/kvm_util.h >> +++ b/tools/testing/selftests/kvm/include/kvm_util.h >> @@ -167,7 +167,7 @@ int vm_create_device(struct kvm_vm *vm, struct kvm_create_device *cd); >> >> /* ucall implementation types */ >> typedef enum { >> - UCALL_PIO, >> + UCALL_DEFAULT, > > I'd rather we keep explicit types defined; keep PIO and add DIAG. Then > we can have > > /* Set default ucall types */ > #if defined(__x86_64__) > ucall_type = UCALL_PIO; > #elif defined(__aarch64__) > ucall_type = UCALL_MMIO; > ucall_requires_init = true; > #elif defined(__s390x__) > ucall_type = UCALL_DIAG; > #endif > > And add an assert in get_ucall() > > assert(!ucall_requires_init || ucall_initialized); I'm not sure whether I really like that. It's yet another additional #ifdef block, and yet another variable ... What do you think about removing the enum completely and simply code it directly, without the ucall_type indirection, i.e.: void ucall(uint64_t cmd, int nargs, ...) { struct ucall uc = { .cmd = cmd, }; va_list va; int i; nargs = nargs <= UCALL_MAX_ARGS ? nargs : UCALL_MAX_ARGS; va_start(va, nargs); for (i = 0; i < nargs; ++i) uc.args[i] = va_arg(va, uint64_t); va_end(va); #if defined(__x86_64__) /* Exit via PIO */ asm volatile("in %[port], %%al" : : [port] "d" (UCALL_PIO_PORT), "D" (&uc) : "rax"); #elif defined(__aarch64__) *ucall_exit_mmio_addr = (vm_vaddr_t)&uc; #elif defined(__s390x__) /* Exit via DIAGNOSE 0x501 (normally used for breakpoints) */ asm volatile ("diag 0,%0,0x501" : : "a"(&uc) : "memory"); #endif } I think that's way less confusing than having to understand the meaning of ucall_type etc. before...? Thomas