81 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Test handler for the s390x DIAGNOSE 0x0318 instruction.4 *5 * Copyright (C) 2020, IBM6 */7 8#include "test_util.h"9#include "kvm_util.h"10 11#define ICPT_INSTRUCTION 0x0412#define IPA0_DIAG 0x830013 14static void guest_code(void)15{16 uint64_t diag318_info = 0x12345678;17 18 asm volatile ("diag %0,0,0x318\n" : : "d" (diag318_info));19}20 21/*22 * The DIAGNOSE 0x0318 instruction call must be handled via userspace. As such,23 * we create an ad-hoc VM here to handle the instruction then extract the24 * necessary data. It is up to the caller to decide what to do with that data.25 */26static uint64_t diag318_handler(void)27{28 struct kvm_vcpu *vcpu;29 struct kvm_vm *vm;30 struct kvm_run *run;31 uint64_t reg;32 uint64_t diag318_info;33 34 vm = vm_create_with_one_vcpu(&vcpu, guest_code);35 vcpu_run(vcpu);36 run = vcpu->run;37 38 TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_S390_SIEIC);39 TEST_ASSERT(run->s390_sieic.icptcode == ICPT_INSTRUCTION,40 "Unexpected intercept code: 0x%x", run->s390_sieic.icptcode);41 TEST_ASSERT((run->s390_sieic.ipa & 0xff00) == IPA0_DIAG,42 "Unexpected IPA0 code: 0x%x", (run->s390_sieic.ipa & 0xff00));43 44 reg = (run->s390_sieic.ipa & 0x00f0) >> 4;45 diag318_info = run->s.regs.gprs[reg];46 47 TEST_ASSERT(diag318_info != 0, "DIAGNOSE 0x0318 info not set");48 49 kvm_vm_free(vm);50 51 return diag318_info;52}53 54uint64_t get_diag318_info(void)55{56 static uint64_t diag318_info;57 static bool printed_skip;58 59 /*60 * If KVM does not support diag318, then return 0 to61 * ensure tests do not break.62 */63 if (!kvm_has_cap(KVM_CAP_S390_DIAG318)) {64 if (!printed_skip) {65 fprintf(stdout, "KVM_CAP_S390_DIAG318 not supported. "66 "Skipping diag318 test.\n");67 printed_skip = true;68 }69 return 0;70 }71 72 /*73 * If a test has previously requested the diag318 info,74 * then don't bother spinning up a temporary VM again.75 */76 if (!diag318_info)77 diag318_info = diag318_handler();78 79 return diag318_info;80}81