// SPDX-License-Identifier: GPL-2.0-only
/*
 * Test for s390x KVM_CAP_SYNC_REGS
 *
 * Based on the same test for x86:
 * Copyright (C) 2018, Google LLC.
 *
 * Adaptions for s390x:
 * Copyright (C) 2019, Red Hat, Inc.
 *
 * Test expected behavior of the KVM_CAP_SYNC_REGS functionality.
 */
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>

#include "test_util.h"
#include "kvm_util.h"
#include "diag318_test_handler.h"
#include "kselftest.h"

static void guest_code(void)
{
	/*
	 * We embed diag 501 here instead of doing a ucall to avoid that
	 * the compiler has messed with r11 at the time of the ucall.
	 */
	asm volatile (
		"0:	diag 0,0,0x501\n"
		"	ahi 11,1\n"
		"	j 0b\n"
	);
}

#define REG_COMPARE(reg) \
	TEST_ASSERT(left->reg == right->reg, \
		    "Register " #reg \
		    " values did not match: 0x%llx, 0x%llx", \
		    left->reg, right->reg)

#define REG_COMPARE32(reg) \
	TEST_ASSERT(left->reg == right->reg, \
		    "Register " #reg \
		    " values did not match: 0x%x, 0x%x", \
		    left->reg, right->reg)


static void compare_regs(struct kvm_regs *left, struct kvm_sync_regs *right)
{
	int i;

	for (i = 0; i < 16; i++)
		REG_COMPARE(gprs[i]);
}

static void compare_sregs(struct kvm_sregs *left, struct kvm_sync_regs *right)
{
	int i;

	for (i = 0; i < 16; i++)
		REG_COMPARE32(acrs[i]);

	for (i = 0; i < 16; i++)
		REG_COMPARE(crs[i]);
}

#undef REG_COMPARE

#define TEST_SYNC_FIELDS   (KVM_SYNC_GPRS|KVM_SYNC_ACRS|KVM_SYNC_CRS|KVM_SYNC_DIAG318)
#define INVALID_SYNC_FIELD 0x80000000

void test_read_invalid(struct kvm_vcpu *vcpu)
{
	struct kvm_run *run = vcpu->run;
	int rv;

	/* Request reading invalid register set from VCPU. */
	run->kvm_valid_regs = INVALID_SYNC_FIELD;
	rv = _vcpu_run(vcpu);
	TEST_ASSERT(rv < 0 && errno == EINVAL,
		    "Invalid kvm_valid_regs did not cause expected KVM_RUN error: %d",
		    rv);
	run->kvm_valid_regs = 0;

	run->kvm_valid_regs = INVALID_SYNC_FIELD | TEST_SYNC_FIELDS;
	rv = _vcpu_run(vcpu);
	TEST_ASSERT(rv < 0 && errno == EINVAL,
		    "Invalid kvm_valid_regs did not cause expected KVM_RUN error: %d",
		    rv);
	run->kvm_valid_regs = 0;
}

void test_set_invalid(struct kvm_vcpu *vcpu)
{
	struct kvm_run *run = vcpu->run;
	int rv;

	/* Request setting invalid register set into VCPU. */
	run->kvm_dirty_regs = INVALID_SYNC_FIELD;
	rv = _vcpu_run(vcpu);
	TEST_ASSERT(rv < 0 && errno == EINVAL,
		    "Invalid kvm_dirty_regs did not cause expected KVM_RUN error: %d",
		    rv);
	run->kvm_dirty_regs = 0;

	run->kvm_dirty_regs = INVALID_SYNC_FIELD | TEST_SYNC_FIELDS;
	rv = _vcpu_run(vcpu);
	TEST_ASSERT(rv < 0 && errno == EINVAL,
		    "Invalid kvm_dirty_regs did not cause expected KVM_RUN error: %d",
		    rv);
	run->kvm_dirty_regs = 0;
}

void test_req_and_verify_all_valid_regs(struct kvm_vcpu *vcpu)
{
	struct kvm_run *run = vcpu->run;
	struct kvm_sregs sregs;
	struct kvm_regs regs;
	int rv;

	/* Request and verify all valid register sets. */
	run->kvm_valid_regs = TEST_SYNC_FIELDS;
	rv = _vcpu_run(vcpu);
	TEST_ASSERT(rv == 0, "vcpu_run failed: %d", rv);
	TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_S390_SIEIC);
	TEST_ASSERT(run->s390_sieic.icptcode == 4 &&
		    (run->s390_sieic.ipa >> 8) == 0x83 &&
		    (run->s390_sieic.ipb >> 16) == 0x501,
		    "Unexpected interception code: ic=%u, ipa=0x%x, ipb=0x%x",
		    run->s390_sieic.icptcode, run->s390_sieic.ipa,
		    run->s390_sieic.ipb);

	vcpu_regs_get(vcpu, &regs);
	compare_regs(&regs, &run->s.regs);

	vcpu_sregs_get(vcpu, &sregs);
	compare_sregs(&sregs, &run->s.regs);
}

void test_set_and_verify_various_reg_values(struct kvm_vcpu *vcpu)
{
	struct kvm_run *run = vcpu->run;
	struct kvm_sregs sregs;
	struct kvm_regs regs;
	int rv;

	/* Set and verify various register values */
	run->s.regs.gprs[11] = 0xBAD1DEA;
	run->s.regs.acrs[0] = 1 << 11;

	run->kvm_valid_regs = TEST_SYNC_FIELDS;
	run->kvm_dirty_regs = KVM_SYNC_GPRS | KVM_SYNC_ACRS;

	if (get_diag318_info() > 0) {
		run->s.regs.diag318 = get_diag318_info();
		run->kvm_dirty_regs |= KVM_SYNC_DIAG318;
	}

	rv = _vcpu_run(vcpu);
	TEST_ASSERT(rv == 0, "vcpu_run failed: %d", rv);
	TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_S390_SIEIC);
	TEST_ASSERT(run->s.regs.gprs[11] == 0xBAD1DEA + 1,
		    "r11 sync regs value incorrect 0x%llx.",
		    run->s.regs.gprs[11]);
	TEST_ASSERT(run->s.regs.acrs[0]  == 1 << 11,
		    "acr0 sync regs value incorrect 0x%x.",
		    run->s.regs.acrs[0]);
	TEST_ASSERT(run->s.regs.diag318 == get_diag318_info(),
		    "diag318 sync regs value incorrect 0x%llx.",
		    run->s.regs.diag318);

	vcpu_regs_get(vcpu, &regs);
	compare_regs(&regs, &run->s.regs);

	vcpu_sregs_get(vcpu, &sregs);
	compare_sregs(&sregs, &run->s.regs);
}

void test_clear_kvm_dirty_regs_bits(struct kvm_vcpu *vcpu)
{
	struct kvm_run *run = vcpu->run;
	int rv;

	/* Clear kvm_dirty_regs bits, verify new s.regs values are
	 * overwritten with existing guest values.
	 */
	run->kvm_valid_regs = TEST_SYNC_FIELDS;
	run->kvm_dirty_regs = 0;
	run->s.regs.gprs[11] = 0xDEADBEEF;
	run->s.regs.diag318 = 0x4B1D;
	rv = _vcpu_run(vcpu);
	TEST_ASSERT(rv == 0, "vcpu_run failed: %d", rv);
	TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_S390_SIEIC);
	TEST_ASSERT(run->s.regs.gprs[11] != 0xDEADBEEF,
		    "r11 sync regs value incorrect 0x%llx.",
		    run->s.regs.gprs[11]);
	TEST_ASSERT(run->s.regs.diag318 != 0x4B1D,
		    "diag318 sync regs value incorrect 0x%llx.",
		    run->s.regs.diag318);
}

struct testdef {
	const char *name;
	void (*test)(struct kvm_vcpu *vcpu);
} testlist[] = {
	{ "read invalid", test_read_invalid },
	{ "set invalid", test_set_invalid },
	{ "request+verify all valid regs", test_req_and_verify_all_valid_regs },
	{ "set+verify various regs", test_set_and_verify_various_reg_values },
	{ "clear kvm_dirty_regs bits", test_clear_kvm_dirty_regs_bits },
};

int main(int argc, char *argv[])
{
	struct kvm_vcpu *vcpu;
	struct kvm_vm *vm;
	int idx;

	TEST_REQUIRE(kvm_has_cap(KVM_CAP_SYNC_REGS));

	ksft_print_header();

	ksft_set_plan(ARRAY_SIZE(testlist));

	/* Create VM */
	vm = vm_create_with_one_vcpu(&vcpu, guest_code);

	for (idx = 0; idx < ARRAY_SIZE(testlist); idx++) {
		testlist[idx].test(vcpu);
		ksft_test_result_pass("%s\n", testlist[idx].name);
	}

	kvm_vm_free(vm);

	ksft_finished();	/* Print results and exit() accordingly */
}
