linux/tools/testing/selftests/kvm/lib/s390x/diag318_test_handler.c
<<
>>
Prefs
   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}
  83