Loading arch/s390/configs/debug_defconfig +1 −0 Original line number Diff line number Diff line Loading @@ -59,6 +59,7 @@ CONFIG_CMM=m CONFIG_APPLDATA_BASE=y CONFIG_S390_HYPFS_FS=y CONFIG_KVM=m CONFIG_KVM_S390_UCONTROL=y CONFIG_S390_UNWIND_SELFTEST=m CONFIG_S390_KPROBES_SANITY_TEST=m CONFIG_S390_MODULES_SANITY_TEST=m Loading arch/s390/kvm/kvm-s390.c +18 −9 Original line number Diff line number Diff line Loading @@ -348,20 +348,29 @@ static inline int plo_test_bit(unsigned char nr) return cc == 0; } static __always_inline void __insn32_query(unsigned int opcode, u8 *query) static __always_inline void __sortl_query(u8 (*query)[32]) { asm volatile( " lghi 0,0\n" " lgr 1,%[query]\n" " la 1,%[query]\n" /* Parameter registers are ignored */ " .insn rrf,%[opc] << 16,2,4,6,0\n" " .insn rre,0xb9380000,2,4\n" : [query] "=R" (*query) : : [query] "d" ((unsigned long)query), [opc] "i" (opcode) : "cc", "memory", "0", "1"); : "cc", "0", "1"); } #define INSN_SORTL 0xb938 #define INSN_DFLTCC 0xb939 static __always_inline void __dfltcc_query(u8 (*query)[32]) { asm volatile( " lghi 0,0\n" " la 1,%[query]\n" /* Parameter registers are ignored */ " .insn rrf,0xb9390000,2,4,6,0\n" : [query] "=R" (*query) : : "cc", "0", "1"); } static void __init kvm_s390_cpu_feat_init(void) { Loading Loading @@ -415,10 +424,10 @@ static void __init kvm_s390_cpu_feat_init(void) kvm_s390_available_subfunc.kdsa); if (test_facility(150)) /* SORTL */ __insn32_query(INSN_SORTL, kvm_s390_available_subfunc.sortl); __sortl_query(&kvm_s390_available_subfunc.sortl); if (test_facility(151)) /* DFLTCC */ __insn32_query(INSN_DFLTCC, kvm_s390_available_subfunc.dfltcc); __dfltcc_query(&kvm_s390_available_subfunc.dfltcc); if (MACHINE_HAS_ESOP) allow_cpu_feat(KVM_S390_VM_CPU_FEAT_ESOP); Loading tools/testing/selftests/kvm/.gitignore +1 −0 Original line number Diff line number Diff line Loading @@ -5,3 +5,4 @@ !*.h !*.S !*.sh !config tools/testing/selftests/kvm/Makefile +1 −0 Original line number Diff line number Diff line Loading @@ -188,6 +188,7 @@ TEST_GEN_PROGS_s390x += s390x/tprot TEST_GEN_PROGS_s390x += s390x/cmma_test TEST_GEN_PROGS_s390x += s390x/debug_test TEST_GEN_PROGS_s390x += s390x/shared_zeropage_test TEST_GEN_PROGS_s390x += s390x/ucontrol_test TEST_GEN_PROGS_s390x += demand_paging_test TEST_GEN_PROGS_s390x += dirty_log_test TEST_GEN_PROGS_s390x += guest_print_test Loading tools/testing/selftests/kvm/include/s390x/debug_print.h 0 → 100644 +69 −0 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0-only */ /* * Definition for kernel virtual machines on s390x * * Copyright IBM Corp. 2024 * * Authors: * Christoph Schlameuss <schlameuss@linux.ibm.com> */ #ifndef SELFTEST_KVM_DEBUG_PRINT_H #define SELFTEST_KVM_DEBUG_PRINT_H #include "asm/ptrace.h" #include "kvm_util.h" #include "sie.h" static inline void print_hex_bytes(const char *name, u64 addr, size_t len) { u64 pos; pr_debug("%s (%p)\n", name, (void *)addr); pr_debug(" 0/0x00---------|"); if (len > 8) pr_debug(" 8/0x08---------|"); if (len > 16) pr_debug(" 16/0x10--------|"); if (len > 24) pr_debug(" 24/0x18--------|"); for (pos = 0; pos < len; pos += 8) { if ((pos % 32) == 0) pr_debug("\n %3lu 0x%.3lx ", pos, pos); pr_debug(" %16lx", *((u64 *)(addr + pos))); } pr_debug("\n"); } static inline void print_hex(const char *name, u64 addr) { print_hex_bytes(name, addr, 512); } static inline void print_psw(struct kvm_run *run, struct kvm_s390_sie_block *sie_block) { pr_debug("flags:0x%x psw:0x%.16llx:0x%.16llx exit:%u %s\n", run->flags, run->psw_mask, run->psw_addr, run->exit_reason, exit_reason_str(run->exit_reason)); pr_debug("sie_block psw:0x%.16llx:0x%.16llx\n", sie_block->psw_mask, sie_block->psw_addr); } static inline void print_run(struct kvm_run *run, struct kvm_s390_sie_block *sie_block) { print_hex_bytes("run", (u64)run, 0x150); print_hex("sie_block", (u64)sie_block); print_psw(run, sie_block); } static inline void print_regs(struct kvm_run *run) { struct kvm_sync_regs *sync_regs = &run->s.regs; print_hex_bytes("GPRS", (u64)sync_regs->gprs, 8 * NUM_GPRS); print_hex_bytes("ACRS", (u64)sync_regs->acrs, 4 * NUM_ACRS); print_hex_bytes("CRS", (u64)sync_regs->crs, 8 * NUM_CRS); } #endif /* SELFTEST_KVM_DEBUG_PRINT_H */ Loading
arch/s390/configs/debug_defconfig +1 −0 Original line number Diff line number Diff line Loading @@ -59,6 +59,7 @@ CONFIG_CMM=m CONFIG_APPLDATA_BASE=y CONFIG_S390_HYPFS_FS=y CONFIG_KVM=m CONFIG_KVM_S390_UCONTROL=y CONFIG_S390_UNWIND_SELFTEST=m CONFIG_S390_KPROBES_SANITY_TEST=m CONFIG_S390_MODULES_SANITY_TEST=m Loading
arch/s390/kvm/kvm-s390.c +18 −9 Original line number Diff line number Diff line Loading @@ -348,20 +348,29 @@ static inline int plo_test_bit(unsigned char nr) return cc == 0; } static __always_inline void __insn32_query(unsigned int opcode, u8 *query) static __always_inline void __sortl_query(u8 (*query)[32]) { asm volatile( " lghi 0,0\n" " lgr 1,%[query]\n" " la 1,%[query]\n" /* Parameter registers are ignored */ " .insn rrf,%[opc] << 16,2,4,6,0\n" " .insn rre,0xb9380000,2,4\n" : [query] "=R" (*query) : : [query] "d" ((unsigned long)query), [opc] "i" (opcode) : "cc", "memory", "0", "1"); : "cc", "0", "1"); } #define INSN_SORTL 0xb938 #define INSN_DFLTCC 0xb939 static __always_inline void __dfltcc_query(u8 (*query)[32]) { asm volatile( " lghi 0,0\n" " la 1,%[query]\n" /* Parameter registers are ignored */ " .insn rrf,0xb9390000,2,4,6,0\n" : [query] "=R" (*query) : : "cc", "0", "1"); } static void __init kvm_s390_cpu_feat_init(void) { Loading Loading @@ -415,10 +424,10 @@ static void __init kvm_s390_cpu_feat_init(void) kvm_s390_available_subfunc.kdsa); if (test_facility(150)) /* SORTL */ __insn32_query(INSN_SORTL, kvm_s390_available_subfunc.sortl); __sortl_query(&kvm_s390_available_subfunc.sortl); if (test_facility(151)) /* DFLTCC */ __insn32_query(INSN_DFLTCC, kvm_s390_available_subfunc.dfltcc); __dfltcc_query(&kvm_s390_available_subfunc.dfltcc); if (MACHINE_HAS_ESOP) allow_cpu_feat(KVM_S390_VM_CPU_FEAT_ESOP); Loading
tools/testing/selftests/kvm/.gitignore +1 −0 Original line number Diff line number Diff line Loading @@ -5,3 +5,4 @@ !*.h !*.S !*.sh !config
tools/testing/selftests/kvm/Makefile +1 −0 Original line number Diff line number Diff line Loading @@ -188,6 +188,7 @@ TEST_GEN_PROGS_s390x += s390x/tprot TEST_GEN_PROGS_s390x += s390x/cmma_test TEST_GEN_PROGS_s390x += s390x/debug_test TEST_GEN_PROGS_s390x += s390x/shared_zeropage_test TEST_GEN_PROGS_s390x += s390x/ucontrol_test TEST_GEN_PROGS_s390x += demand_paging_test TEST_GEN_PROGS_s390x += dirty_log_test TEST_GEN_PROGS_s390x += guest_print_test Loading
tools/testing/selftests/kvm/include/s390x/debug_print.h 0 → 100644 +69 −0 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0-only */ /* * Definition for kernel virtual machines on s390x * * Copyright IBM Corp. 2024 * * Authors: * Christoph Schlameuss <schlameuss@linux.ibm.com> */ #ifndef SELFTEST_KVM_DEBUG_PRINT_H #define SELFTEST_KVM_DEBUG_PRINT_H #include "asm/ptrace.h" #include "kvm_util.h" #include "sie.h" static inline void print_hex_bytes(const char *name, u64 addr, size_t len) { u64 pos; pr_debug("%s (%p)\n", name, (void *)addr); pr_debug(" 0/0x00---------|"); if (len > 8) pr_debug(" 8/0x08---------|"); if (len > 16) pr_debug(" 16/0x10--------|"); if (len > 24) pr_debug(" 24/0x18--------|"); for (pos = 0; pos < len; pos += 8) { if ((pos % 32) == 0) pr_debug("\n %3lu 0x%.3lx ", pos, pos); pr_debug(" %16lx", *((u64 *)(addr + pos))); } pr_debug("\n"); } static inline void print_hex(const char *name, u64 addr) { print_hex_bytes(name, addr, 512); } static inline void print_psw(struct kvm_run *run, struct kvm_s390_sie_block *sie_block) { pr_debug("flags:0x%x psw:0x%.16llx:0x%.16llx exit:%u %s\n", run->flags, run->psw_mask, run->psw_addr, run->exit_reason, exit_reason_str(run->exit_reason)); pr_debug("sie_block psw:0x%.16llx:0x%.16llx\n", sie_block->psw_mask, sie_block->psw_addr); } static inline void print_run(struct kvm_run *run, struct kvm_s390_sie_block *sie_block) { print_hex_bytes("run", (u64)run, 0x150); print_hex("sie_block", (u64)sie_block); print_psw(run, sie_block); } static inline void print_regs(struct kvm_run *run) { struct kvm_sync_regs *sync_regs = &run->s.regs; print_hex_bytes("GPRS", (u64)sync_regs->gprs, 8 * NUM_GPRS); print_hex_bytes("ACRS", (u64)sync_regs->acrs, 4 * NUM_ACRS); print_hex_bytes("CRS", (u64)sync_regs->crs, 8 * NUM_CRS); } #endif /* SELFTEST_KVM_DEBUG_PRINT_H */