// SPDX-License-Identifier: GPL-2.0
/*
 * Test that KVM_GET_MSR_INDEX_LIST and
 * KVM_GET_MSR_FEATURE_INDEX_LIST work as intended
 *
 * Copyright (C) 2020, Red Hat, Inc.
 */
#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 "processor.h"

static int kvm_num_index_msrs(int kvm_fd, int nmsrs)
{
	struct kvm_msr_list *list;
	int r;

	list = malloc(sizeof(*list) + nmsrs * sizeof(list->indices[0]));
	list->nmsrs = nmsrs;
	r = ioctl(kvm_fd, KVM_GET_MSR_INDEX_LIST, list);
	TEST_ASSERT(r == -1 && errno == E2BIG,
				"Unexpected result from KVM_GET_MSR_INDEX_LIST probe, r: %i",
				r);

	r = list->nmsrs;
	free(list);
	return r;
}

static void test_get_msr_index(void)
{
	int old_res, res, kvm_fd, r;
	struct kvm_msr_list *list;

	kvm_fd = open_kvm_dev_path_or_exit();

	old_res = kvm_num_index_msrs(kvm_fd, 0);
	TEST_ASSERT(old_res != 0, "Expecting nmsrs to be > 0");

	if (old_res != 1) {
		res = kvm_num_index_msrs(kvm_fd, 1);
		TEST_ASSERT(res > 1, "Expecting nmsrs to be > 1");
		TEST_ASSERT(res == old_res, "Expecting nmsrs to be identical");
	}

	list = malloc(sizeof(*list) + old_res * sizeof(list->indices[0]));
	list->nmsrs = old_res;
	r = ioctl(kvm_fd, KVM_GET_MSR_INDEX_LIST, list);

	TEST_ASSERT(r == 0,
		    "Unexpected result from KVM_GET_MSR_FEATURE_INDEX_LIST, r: %i",
		    r);
	TEST_ASSERT(list->nmsrs == old_res, "Expecting nmsrs to be identical");
	free(list);

	close(kvm_fd);
}

static int kvm_num_feature_msrs(int kvm_fd, int nmsrs)
{
	struct kvm_msr_list *list;
	int r;

	list = malloc(sizeof(*list) + nmsrs * sizeof(list->indices[0]));
	list->nmsrs = nmsrs;
	r = ioctl(kvm_fd, KVM_GET_MSR_FEATURE_INDEX_LIST, list);
	TEST_ASSERT(r == -1 && errno == E2BIG,
		"Unexpected result from KVM_GET_MSR_FEATURE_INDEX_LIST probe, r: %i",
				r);

	r = list->nmsrs;
	free(list);
	return r;
}

struct kvm_msr_list *kvm_get_msr_feature_list(int kvm_fd, int nmsrs)
{
	struct kvm_msr_list *list;
	int r;

	list = malloc(sizeof(*list) + nmsrs * sizeof(list->indices[0]));
	list->nmsrs = nmsrs;
	r = ioctl(kvm_fd, KVM_GET_MSR_FEATURE_INDEX_LIST, list);

	TEST_ASSERT(r == 0,
		"Unexpected result from KVM_GET_MSR_FEATURE_INDEX_LIST, r: %i",
		r);

	return list;
}

static void test_get_msr_feature(void)
{
	int res, old_res, i, kvm_fd;
	struct kvm_msr_list *feature_list;

	kvm_fd = open_kvm_dev_path_or_exit();

	old_res = kvm_num_feature_msrs(kvm_fd, 0);
	TEST_ASSERT(old_res != 0, "Expecting nmsrs to be > 0");

	if (old_res != 1) {
		res = kvm_num_feature_msrs(kvm_fd, 1);
		TEST_ASSERT(res > 1, "Expecting nmsrs to be > 1");
		TEST_ASSERT(res == old_res, "Expecting nmsrs to be identical");
	}

	feature_list = kvm_get_msr_feature_list(kvm_fd, old_res);
	TEST_ASSERT(old_res == feature_list->nmsrs,
				"Unmatching number of msr indexes");

	for (i = 0; i < feature_list->nmsrs; i++)
		kvm_get_feature_msr(feature_list->indices[i]);

	free(feature_list);
	close(kvm_fd);
}

int main(int argc, char *argv[])
{
	if (kvm_check_cap(KVM_CAP_GET_MSR_FEATURES))
		test_get_msr_feature();

	test_get_msr_index();
}
