/*
 * Copyright 2019 The Hafnium Authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "../../src/arch/aarch64/hypervisor/perfmon.h"

#include "primary_with_secondary.h"
#include "sysregs.h"
#include "util.h"

/*
 * TODO(b/132394973): Devise a way to test exhaustively read/write behavior to
 * all debug registers that does not involve a separate service per register,
 * because creating a new test/VM for every instance becomes too slow.
 * This needs proper trap support as a starting point.
 */

TEST(perfmon, secondary_pmccfiltr_el0)
{
	struct hf_vcpu_run_return run_res;
	struct mailbox_buffers mb = set_up_mailbox();

	SERVICE_SELECT(SERVICE_VM0, "perfmon_secondary_pmccfiltr_el0", mb.send);

	run_res = hf_vcpu_run(SERVICE_VM0, 0);
	EXPECT_EQ(run_res.code, HF_VCPU_RUN_ABORTED);
}

TEST(perfmon, secondary_pmcr_el0)
{
	struct hf_vcpu_run_return run_res;
	struct mailbox_buffers mb = set_up_mailbox();

	SERVICE_SELECT(SERVICE_VM0, "perfmon_secondary_pmcr_el0", mb.send);

	run_res = hf_vcpu_run(SERVICE_VM0, 0);
	EXPECT_EQ(run_res.code, HF_VCPU_RUN_ABORTED);
}

TEST(perfmon, secondary_pmintenset_el1)
{
	struct hf_vcpu_run_return run_res;
	struct mailbox_buffers mb = set_up_mailbox();

	SERVICE_SELECT(SERVICE_VM0, "perfmon_secondary_pmintenset_el1",
		       mb.send);

	run_res = hf_vcpu_run(SERVICE_VM0, 0);
	EXPECT_EQ(run_res.code, HF_VCPU_RUN_ABORTED);
}

/**
 * Attempts to access performance monitor registers for read, without validating
 * their value.
 */
TEST(perfmon, primary_basic)
{
	EXPECT_EQ(hf_vm_get_id(), HF_PRIMARY_VM_ID);

	TRY_READ(PMCEID0_EL0);
	TRY_READ(PMCEID1_EL0);
	TRY_READ(PMCCFILTR_EL0);
	TRY_READ(PMCR_EL0);
}

/**
 * Tests a few performance counter registers for read and write, and checks that
 * the expected value is written/read.
 */
TEST(perfmon, primary_read_write)
{
	EXPECT_EQ(hf_vm_get_id(), HF_PRIMARY_VM_ID);

	TRY_WRITE_READ(PMCCNTR_EL0, 0xaaaa);

	write_msr(PMINTENCLR_EL1, 0xffff);
	CHECK_READ(PMINTENSET_EL1, 0);

	/* Bits set in PMINTENSET_EL1 can be read in PMINTENCLR_EL1. */
	write_msr(PMINTENSET_EL1, 0xf);
	CHECK_READ(PMINTENCLR_EL1, 0xf);

	/* Writes to PMINTENSET_EL1 do not clear already set bits. */
	write_msr(PMINTENSET_EL1, 0xf0);
	CHECK_READ(PMINTENCLR_EL1, 0xff);
}

/**
 * Attempts to read all performance counters supported by the current CPU
 * configuration.
 */
/* NOLINTNEXTLINE(readability-function-size) */
TEST(perfmon, primary_counters)
{
	uintreg_t pmcr_el0 = read_msr(PMCR_EL0);
	uintreg_t perf_mon_count = GET_PMCR_EL0_N(pmcr_el0);

	EXPECT_EQ(hf_vm_get_id(), HF_PRIMARY_VM_ID);

	if (perf_mon_count == 0) {
		return;
	}

	switch (perf_mon_count - 1) {
	default:
		FAIL("More performance monitor registers than supported.");
	case 30:
		TRY_READ(PMEVCNTR30_EL0);
		TRY_WRITE_READ(PMEVTYPER30_EL0, 0x1);
		/* fallthrough */
	case 29:
		TRY_READ(PMEVCNTR29_EL0);
		TRY_WRITE_READ(PMEVTYPER29_EL0, 0x1);
		/* fallthrough */
	case 28:
		TRY_READ(PMEVCNTR28_EL0);
		TRY_WRITE_READ(PMEVTYPER28_EL0, 0x1);
		/* fallthrough */
	case 27:
		TRY_READ(PMEVCNTR27_EL0);
		TRY_WRITE_READ(PMEVTYPER27_EL0, 0x1);
		/* fallthrough */
	case 26:
		TRY_READ(PMEVCNTR26_EL0);
		TRY_WRITE_READ(PMEVTYPER26_EL0, 0x1);
		/* fallthrough */
	case 25:
		TRY_READ(PMEVCNTR25_EL0);
		TRY_WRITE_READ(PMEVTYPER25_EL0, 0x1);
		/* fallthrough */
	case 24:
		TRY_READ(PMEVCNTR24_EL0);
		TRY_WRITE_READ(PMEVTYPER24_EL0, 0x1);
		/* fallthrough */
	case 23:
		TRY_READ(PMEVCNTR23_EL0);
		TRY_WRITE_READ(PMEVTYPER23_EL0, 0x1);
		/* fallthrough */
	case 22:
		TRY_READ(PMEVCNTR22_EL0);
		TRY_WRITE_READ(PMEVTYPER22_EL0, 0x1);
		/* fallthrough */
	case 21:
		TRY_READ(PMEVCNTR21_EL0);
		TRY_WRITE_READ(PMEVTYPER21_EL0, 0x1);
		/* fallthrough */
	case 20:
		TRY_READ(PMEVCNTR20_EL0);
		TRY_WRITE_READ(PMEVTYPER20_EL0, 0x1);
		/* fallthrough */
	case 19:
		TRY_READ(PMEVCNTR19_EL0);
		TRY_WRITE_READ(PMEVTYPER19_EL0, 0x1);
		/* fallthrough */
	case 18:
		TRY_READ(PMEVCNTR18_EL0);
		TRY_WRITE_READ(PMEVTYPER18_EL0, 0x1);
		/* fallthrough */
	case 17:
		TRY_READ(PMEVCNTR17_EL0);
		TRY_WRITE_READ(PMEVTYPER17_EL0, 0x1);
		/* fallthrough */
	case 16:
		TRY_READ(PMEVCNTR16_EL0);
		TRY_WRITE_READ(PMEVTYPER16_EL0, 0x1);
		/* fallthrough */
	case 15:
		TRY_READ(PMEVCNTR15_EL0);
		TRY_WRITE_READ(PMEVTYPER15_EL0, 0x1);
		/* fallthrough */
	case 14:
		TRY_READ(PMEVCNTR14_EL0);
		TRY_WRITE_READ(PMEVTYPER14_EL0, 0x1);
		/* fallthrough */
	case 13:
		TRY_READ(PMEVCNTR13_EL0);
		TRY_WRITE_READ(PMEVTYPER13_EL0, 0x1);
		/* fallthrough */
	case 12:
		TRY_READ(PMEVCNTR12_EL0);
		TRY_WRITE_READ(PMEVTYPER12_EL0, 0x1);
		/* fallthrough */
	case 11:
		TRY_READ(PMEVCNTR11_EL0);
		TRY_WRITE_READ(PMEVTYPER11_EL0, 0x1);
		/* fallthrough */
	case 10:
		TRY_READ(PMEVCNTR10_EL0);
		TRY_WRITE_READ(PMEVTYPER10_EL0, 0x1);
		/* fallthrough */
	case 9:
		TRY_READ(PMEVCNTR9_EL0);
		TRY_WRITE_READ(PMEVTYPER9_EL0, 0x1);
		/* fallthrough */
	case 8:
		TRY_READ(PMEVCNTR8_EL0);
		TRY_WRITE_READ(PMEVTYPER8_EL0, 0x1);
		/* fallthrough */
	case 7:
		TRY_READ(PMEVCNTR7_EL0);
		TRY_WRITE_READ(PMEVTYPER7_EL0, 0x1);
		/* fallthrough */
	case 6:
		TRY_READ(PMEVCNTR6_EL0);
		TRY_WRITE_READ(PMEVTYPER6_EL0, 0x1);
		/* fallthrough */
	case 5:
		TRY_READ(PMEVCNTR5_EL0);
		TRY_WRITE_READ(PMEVTYPER5_EL0, 0x1);
		/* fallthrough */
	case 4:
		TRY_READ(PMEVCNTR4_EL0);
		TRY_WRITE_READ(PMEVTYPER4_EL0, 0x1);
		/* fallthrough */
	case 3:
		TRY_READ(PMEVCNTR3_EL0);
		TRY_WRITE_READ(PMEVTYPER3_EL0, 0x1);
		/* fallthrough */
	case 2:
		TRY_READ(PMEVCNTR2_EL0);
		TRY_WRITE_READ(PMEVTYPER2_EL0, 0x1);
		/* fallthrough */
	case 1:
		TRY_READ(PMEVCNTR1_EL0);
		TRY_WRITE_READ(PMEVTYPER1_EL0, 0x1);
		/* fallthrough */
	case 0:
		TRY_READ(PMEVCNTR0_EL0);
		TRY_WRITE_READ(PMEVTYPER0_EL0, 0x1);
		break;
	}
}
