blob: 17e26cf2fc52d6e1e508068189f1cd546abe2d84 [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT
#include <lib/unittest/unittest.h>
#include <arch/hypervisor.h>
static bool has_pending_interrupt() {
BEGIN_TEST;
GichState gich_state;
ASSERT_EQ(ZX_OK, gich_state.Init(), "");
IchState ich_state = {};
ich_state.num_lrs = 2;
// Test one pending vector.
ich_state.lr[0] = gic_get_lr_from_vector(false /* hardware */, 0 /* priority */,
InterruptState::PENDING, 1u /* vector */);
ich_state.lr[1] = 0;
gich_state.SetAllInterruptStates(&ich_state);
EXPECT_EQ(true, gich_state.HasPendingInterrupt(), "");
// Test reset.
ich_state.lr[0] = 0;
ich_state.lr[1] = 0;
gich_state.SetAllInterruptStates(&ich_state);
EXPECT_EQ(false, gich_state.HasPendingInterrupt(), "");
// Test one active vector.
ich_state.lr[0] = gic_get_lr_from_vector(false /* hardware */, 0 /* priority */,
InterruptState::ACTIVE, 1u /* vector */);
ich_state.lr[1] = 0;
gich_state.SetAllInterruptStates(&ich_state);
EXPECT_EQ(false, gich_state.HasPendingInterrupt(), "");
// Test one active and one pending vector.
ich_state.lr[0] = gic_get_lr_from_vector(false /* hardware */, 0 /* priority */,
InterruptState::ACTIVE, 1u /* vector */);
ich_state.lr[1] = gic_get_lr_from_vector(false /* hardware */, 0 /* priority */,
InterruptState::PENDING, 2u /* vector */);
gich_state.SetAllInterruptStates(&ich_state);
EXPECT_EQ(true, gich_state.HasPendingInterrupt(), "");
// Test one pending_and_active vector.
ich_state.lr[0] = gic_get_lr_from_vector(false /* hardware */, 0 /* priority */,
InterruptState::PENDING_AND_ACTIVE, 1u /* vector */);
ich_state.lr[1] = 0;
gich_state.SetAllInterruptStates(&ich_state);
EXPECT_EQ(true, gich_state.HasPendingInterrupt(), "");
END_TEST;
}
static bool get_interrupt_state() {
BEGIN_TEST;
GichState gich_state;
ASSERT_EQ(ZX_OK, gich_state.Init(), "");
// Test initial state
for (uint32_t i = 0; i != kNumInterrupts - 1; ++i) {
EXPECT_EQ(InterruptState::INACTIVE, gich_state.GetInterruptState(i), "");
}
IchState ich_state = {};
ich_state.num_lrs = 2;
// Test one pending vector.
ich_state.lr[0] = gic_get_lr_from_vector(false /* hardware */, 0 /* priority */,
InterruptState::PENDING, 1u /* vector */);
ich_state.lr[1] = 0;
gich_state.SetAllInterruptStates(&ich_state);
EXPECT_EQ(InterruptState::PENDING, gich_state.GetInterruptState(1u), "");
for (uint32_t i = 0; i != kNumInterrupts - 1; ++i) {
if (i == 1u) {
continue;
}
EXPECT_EQ(InterruptState::INACTIVE, gich_state.GetInterruptState(i), "");
}
// Test reset.
ich_state.lr[0] = 0;
ich_state.lr[1] = 0;
gich_state.SetAllInterruptStates(&ich_state);
for (uint32_t i = 0; i != kNumInterrupts - 1; ++i) {
EXPECT_EQ(InterruptState::INACTIVE, gich_state.GetInterruptState(i), "");
}
// Test other states.
ich_state.lr[0] = gic_get_lr_from_vector(false /* hardware */, 0 /* priority */,
InterruptState::ACTIVE, 1u /* vector */);
ich_state.lr[1] = gic_get_lr_from_vector(false /* hardware */, 0 /* priority */,
InterruptState::PENDING_AND_ACTIVE, 2u /* vector */);
gich_state.SetAllInterruptStates(&ich_state);
EXPECT_EQ(InterruptState::ACTIVE, gich_state.GetInterruptState(1u), "");
EXPECT_EQ(InterruptState::PENDING_AND_ACTIVE, gich_state.GetInterruptState(2u), "");
for (uint32_t i = 0; i != kNumInterrupts - 1; ++i) {
if (i == 1u || i == 2u) {
continue;
}
EXPECT_EQ(InterruptState::INACTIVE, gich_state.GetInterruptState(i), "");
}
END_TEST;
}
// Use the function name as the test name
#define GICH_STATE_UNITTEST(fname) UNITTEST(#fname, fname)
UNITTEST_START_TESTCASE(gich_state)
GICH_STATE_UNITTEST(has_pending_interrupt)
GICH_STATE_UNITTEST(get_interrupt_state)
UNITTEST_END_TESTCASE(gich_state, "gich_state", "Tests for hypervisor GICH state.");