cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

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}