// Copyright 2016 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/console.h>
#include <lib/debuglog.h>
#include <platform.h>
#include <stdio.h>
#include <string.h>

#include <arch/mp.h>
#include <arch/x86.h>
#include <arch/x86/apic.h>
#include <arch/x86/feature.h>
#include <arch/x86/mp.h>
#include <ktl/atomic.h>
#include <platform/keyboard.h>

// The I/O port to write to for QEMU debug exit.
const uint16_t kQEMUDebugExitPort = 0xf4;

// The return code that we should propagate to QEMU on isa-debug-exit.
// This number must be non-zero and odd, since QEMU calculates the return
// code as (val << 1) | 1 where "val" is the value written to 0xf4.
const uint8_t kQEMUExitCode = 0x1f;
static_assert(kQEMUExitCode != 0 && kQEMUExitCode % 2 != 0,
              "QEMU exit code must be non-zero and odd.");

static void reboot(void) {
  // select the default reboot reason
  x86_reboot_reason_func_t reboot_reason = x86_get_microarch_config()->reboot_reason;
  if (reboot_reason)
    reboot_reason(0u);
  // We fell through. Try normal reboot.
  x86_get_microarch_config()->reboot_system();
  // We fell through. Try rebooting via keyboard controller.
  pc_keyboard_reboot();
}

static void reboot_recovery() {
  x86_reboot_reason_func_t reboot_reason = x86_get_microarch_config()->reboot_reason;
  if (reboot_reason)
    reboot_reason(2u);
}

static void reboot_bootloader() {
  x86_reboot_reason_func_t reboot_reason = x86_get_microarch_config()->reboot_reason;
  if (reboot_reason)
    reboot_reason(4u);
}

static ktl::atomic<cpu_mask_t> halted_cpus(0);

static void halt_other_cpus(void) {
  static ktl::atomic<int> halted(0);

  if (halted.exchange(1) == 0) {
    // This function may have been called early in the boot process, before the
    // mp subsystem has been initialized or secondary CPUs have been brought
    // online.  To avoid calling into the mp subsystem before it has been
    // initialized, check the online mask.  If this CPU is the only one online,
    // then simply return.
    cpu_mask_t targets = mp_get_online_mask() & ~cpu_num_to_mask(arch_curr_cpu_num());
    if (targets == 0) {
      return;
    }

    // stop the other cpus
    printf("stopping other cpus\n");
    arch_mp_send_ipi(MP_IPI_TARGET_ALL_BUT_LOCAL, 0, MP_IPI_HALT);

    // spin for a while
    // TODO: find a better way to spin at this low level
    for (volatile int i = 0; i < 100000000; i++) {
      if (halted_cpus.load() == targets) {
        break;
      }
      __asm volatile("nop");
    }

    // Don't send an INIT IPI to the BSP, since that may cause the system to
    // reboot
    x86_force_halt_all_but_local_and_bsp();
  }
}

void platform_halt_cpu(void) {
  // Signal that this CPU is in its halt loop
  halted_cpus.fetch_or(cpu_num_to_mask(arch_curr_cpu_num()));
}

void platform_panic_start(void) {
  platform_debug_panic_start();
  arch_disable_ints();

  static ktl::atomic<int> panic_started(0);
  if (panic_started.exchange(1) == 0) {
    dlog_bluescreen_init();
  }

  halt_other_cpus();
}

extern const char* manufacturer;

void platform_specific_halt(platform_halt_action suggested_action, zircon_crash_reason_t reason,
                            bool halt_on_panic) {
  printf("platform_halt suggested_action %d reason %d\n", suggested_action,
         static_cast<int>(reason));

  arch_disable_ints();

  switch (suggested_action) {
    case HALT_ACTION_SHUTDOWN:
      if (strcmp("QEMU", manufacturer) == 0) {
        outp(kQEMUDebugExitPort, (kQEMUExitCode >> 1));
      }
      printf("Power off failed, halting\n");
      break;
    case HALT_ACTION_REBOOT:
      printf("Rebooting...\n");
      reboot();
      printf("Reboot failed, halting\n");
      break;
    case HALT_ACTION_HALT:
      printf("Halting...\n");
      halt_other_cpus();
      break;
    case HALT_ACTION_REBOOT_BOOTLOADER:
      printf("Rebooting ... To Boot Loader\n");
      reboot_bootloader();
      // We fell through.
      printf("platform_halt: Unsupported halt reason %d\n", suggested_action);
      break;
    case HALT_ACTION_REBOOT_RECOVERY:
      printf("Rebooting ... To Recovery\n");
      reboot_recovery();
      // We fell through.
      printf("platform_halt: Unsupported halt reason %d\n", suggested_action);
      break;
  }

  if (reason == ZirconCrashReason::Panic) {
    Thread::Current::PrintBacktrace();
  }

  if (!halt_on_panic) {
    printf("Rebooting...\n");
    reboot();
  }

  printf("Halted\n");

#if ENABLE_PANIC_SHELL
  panic_shell_start();
#endif

  for (;;) {
    x86_hlt();
  }
}
