// 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 "arch/x86/idle_states.h"

#include <lib/arch/intrin.h>
#include <lib/unittest/unittest.h>
#include <platform.h>
#include <stdlib.h>
#include <zircon/time.h>

#include <arch/x86.h>
#include <arch/x86/feature.h>
#include <kernel/thread.h>
#include <platform/timer.h>

namespace {

x86_idle_states_t kC1OnlyIdleStates = {
    .states = {X86_CSTATE_C1(0)},
    .default_state_mask = kX86IdleStateMaskC1Only,
};

x86_idle_states_t kKabyLakeIdleStates = {
    .states = {{.name = "C6", .mwait_hint = 0x50, .exit_latency = 1000, .flushes_tlb = true},
               {.name = "C3", .mwait_hint = 0x20, .exit_latency = 100, .flushes_tlb = true},
               {.name = "C1E", .mwait_hint = 0x01, .exit_latency = 10, .flushes_tlb = false},
               X86_CSTATE_C1(0)},
    .default_state_mask = 0b0000'0000'0011'1111,
};

bool test_c1_only() {
  BEGIN_TEST;

  X86IdleStates states(&kC1OnlyIdleStates);
  ASSERT_EQ(states.NumStates(), 1U);
  X86IdleState* state = states.PickIdleState();
  EXPECT_EQ(strcmp(state->Name(), "C1"), 0);
  EXPECT_EQ(state->MwaitHint(), 0x00u);

  END_TEST;
}

bool test_kbl() {
  BEGIN_TEST;

  X86IdleStates states(&kKabyLakeIdleStates);
  ASSERT_EQ(states.NumStates(), 4U);

  X86IdleState* state = states.PickIdleState();
  EXPECT_EQ(strcmp(state->Name(), "C1"), 0);
  EXPECT_EQ(state->MwaitHint(), 0x00u);

  states.RecordDuration(zx_duration_from_usec(3U));
  state = states.PickIdleState();
  EXPECT_EQ(strcmp(state->Name(), "C1"), 0);
  EXPECT_EQ(state->MwaitHint(), 0x00u);

  states.RecordDuration(zx_duration_from_usec(4U));
  state = states.PickIdleState();
  EXPECT_EQ(strcmp(state->Name(), "C1E"), 0);
  EXPECT_EQ(state->MwaitHint(), 0x01u);

  states.RecordDuration(zx_duration_from_usec(34U));
  state = states.PickIdleState();
  EXPECT_EQ(strcmp(state->Name(), "C3"), 0);
  EXPECT_EQ(state->MwaitHint(), 0x20u);

  states.RecordDuration(zx_duration_from_usec(334U));
  state = states.PickIdleState();
  EXPECT_EQ(strcmp(state->Name(), "C6"), 0);
  EXPECT_EQ(state->MwaitHint(), 0x50u);

  END_TEST;
}

bool test_kbl_statemask() {
  BEGIN_TEST;

  X86IdleStates states(&kKabyLakeIdleStates);

  // Empty mask will always choose C1 or C1E
  states.SetStateMask(0b0000'0000'0000'0000);
  X86IdleState* state = states.PickIdleState();
  EXPECT_EQ(state->MwaitHint(), 0x00u);
  EXPECT_EQ(strcmp(state->Name(), "C1"), 0);
  states.RecordDuration(zx_duration_from_usec(3U));
  state = states.PickIdleState();
  EXPECT_EQ(state->MwaitHint(), 0x00u);
  EXPECT_EQ(strcmp(state->Name(), "C1"), 0);
  states.RecordDuration(zx_duration_from_usec(4U));
  state = states.PickIdleState();
  EXPECT_EQ(state->MwaitHint(), 0x01u);
  EXPECT_EQ(strcmp(state->Name(), "C1E"), 0);
  states.RecordDuration(zx_duration_from_usec(34U));
  state = states.PickIdleState();
  EXPECT_EQ(state->MwaitHint(), 0x01u);
  EXPECT_EQ(strcmp(state->Name(), "C1E"), 0);
  states.RecordDuration(zx_duration_from_usec(334U));
  state = states.PickIdleState();
  EXPECT_EQ(state->MwaitHint(), 0x01u);
  EXPECT_EQ(strcmp(state->Name(), "C1E"), 0);

  // Mask to only allow C6, C1/C1E
  states.SetStateMask(0b0000'0000'0010'0001);
  states.RecordDuration(zx_duration_from_usec(0u));
  state = states.PickIdleState();
  EXPECT_EQ(state->MwaitHint(), 0x00u);
  EXPECT_EQ(strcmp(state->Name(), "C1"), 0);
  states.RecordDuration(zx_duration_from_usec(3U));
  state = states.PickIdleState();
  EXPECT_EQ(state->MwaitHint(), 0x00u);
  EXPECT_EQ(strcmp(state->Name(), "C1"), 0);
  states.RecordDuration(zx_duration_from_usec(4U));
  state = states.PickIdleState();
  EXPECT_EQ(state->MwaitHint(), 0x01u);
  EXPECT_EQ(strcmp(state->Name(), "C1E"), 0);
  states.RecordDuration(zx_duration_from_usec(34U));
  state = states.PickIdleState();
  EXPECT_EQ(state->MwaitHint(), 0x01u);
  EXPECT_EQ(strcmp(state->Name(), "C1E"), 0);
  states.RecordDuration(zx_duration_from_usec(334U));
  state = states.PickIdleState();
  EXPECT_EQ(state->MwaitHint(), 0x50u);
  EXPECT_EQ(strcmp(state->Name(), "C6"), 0);

  END_TEST;
}

volatile uint8_t monitor;

static uint8_t kGuardValue = UINT8_MAX;

static int poke_monitor(void* arg) {
  // A short sleep ensures the main test thread has time to set up the monitor
  // and enter MWAIT.
  Thread::Current::SleepRelative(zx_duration_from_msec(1));
  monitor = kGuardValue;
  return 0;
}

bool test_enter_idle_states() {
  BEGIN_TEST;

  monitor = 0;

  if (x86_feature_test(X86_FEATURE_MON)) {
    X86IdleStates states(x86_get_idle_states());
    for (uint8_t i = 0; i < states.NumStates(); ++i) {
      const X86IdleState& state = states.States()[i];

      unittest_printf("Entering state '%s' (MWAIT 0x%02x) on CPU %u\n", state.Name(),
                      state.MwaitHint(), arch_curr_cpu_num());

      // Thread must be created and started before arming the monitor,
      // since thread creation appears to trip the monitor latch prematurely.
      Thread* thrd = Thread::Create("monitor_poker", &poke_monitor, nullptr, DEFAULT_PRIORITY);
      thrd->Resume();

      monitor = i;
      arch::ThreadMemoryBarrier();
      x86_monitor(&monitor);
      auto start = current_time();
      x86_mwait(state.MwaitHint());

      unittest_printf("Exiting state (%ld ns elapsed)\n", zx_time_sub_time(current_time(), start));
      thrd->Join(nullptr, ZX_TIME_INFINITE);
    }
  } else {
    unittest_printf("Skipping test; MWAIT/MONITOR not supported\n");
  }

  END_TEST;
}

}  // namespace

UNITTEST_START_TESTCASE(x86_idle_states_tests)
UNITTEST("Select an idle state using data from a CPU with only C1.", test_c1_only)
UNITTEST("Select an idle state using data from a Kabylake CPU.", test_kbl)
UNITTEST("Select an idle state using data from a Kabylake CPU, respecting a mask of valid states.",
         test_kbl_statemask)
UNITTEST("Enter each supported idle state using MWAIT/MONITOR.", test_enter_idle_states)
UNITTEST_END_TESTCASE(x86_idle_states_tests, "x86_idle_states",
                      "Test idle state enumeration and selection (x86 only).")
