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