// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/virtualization/bin/vmm/guest.h"

#include <fcntl.h>
#include <lib/fdio/directory.h>
#include <lib/fdio/fd.h>
#include <lib/fdio/fdio.h>
#include <lib/syslog/cpp/macros.h>
#include <lib/zx/channel.h>
#include <limits.h>
#include <string.h>
#include <unistd.h>
#include <zircon/process.h>
#include <zircon/syscalls.h>
#include <zircon/syscalls/hypervisor.h>
#include <zircon/syscalls/port.h>
#include <zircon/threads.h>

#include "src/lib/fxl/strings/string_printf.h"
#include "src/virtualization/bin/vmm/sysinfo.h"

#ifdef __aarch64__
static constexpr uint8_t kSpiBase = 32;
#endif

static constexpr uint32_t trap_kind(TrapType type) {
  switch (type) {
    case TrapType::MMIO_SYNC:
      return ZX_GUEST_TRAP_MEM;
    case TrapType::MMIO_BELL:
      return ZX_GUEST_TRAP_BELL;
    case TrapType::PIO_SYNC:
      return ZX_GUEST_TRAP_IO;
    default:
      ZX_PANIC("Unhandled TrapType %d\n", static_cast<int>(type));
      return 0;
  }
}

static constexpr uint32_t cache_policy(fuchsia::virtualization::MemoryPolicy policy) {
  switch (policy) {
    case fuchsia::virtualization::MemoryPolicy::HOST_DEVICE:
      return ZX_CACHE_POLICY_UNCACHED_DEVICE;
    default:
      return ZX_CACHE_POLICY_CACHED;
  }
}

zx_status_t Guest::Init(const std::vector<fuchsia::virtualization::MemorySpec>& memory) {
  zx::resource hypervisor_resource;
  zx_status_t status = get_hypervisor_resource(&hypervisor_resource);
  if (status != ZX_OK) {
    FX_LOGS(ERROR) << "Failed to get hypervisor resource " << status;
    return status;
  }
  status = zx::guest::create(hypervisor_resource, 0, &guest_, &vmar_);
  if (status != ZX_OK) {
    FX_LOGS(ERROR) << "Failed to create guest " << status;
    return status;
  }

  zx::resource mmio_resource;
  zx::resource vmex_resource;
  for (const fuchsia::virtualization::MemorySpec& spec : memory) {
    zx::vmo vmo;
    switch (spec.policy) {
      case fuchsia::virtualization::MemoryPolicy::GUEST_CACHED:
        status = zx::vmo::create(spec.size, 0, &vmo);
        if (status != ZX_OK) {
          FX_LOGS(ERROR) << "Failed to create VMO " << status;
          return status;
        }
        break;
      case fuchsia::virtualization::MemoryPolicy::HOST_CACHED:
      case fuchsia::virtualization::MemoryPolicy::HOST_DEVICE:
        if (!mmio_resource) {
          status = get_mmio_resource(&mmio_resource);
          if (status != ZX_OK) {
            FX_LOGS(ERROR) << "Failed to get mmio resource " << status;
            return status;
          }
        }
        status = zx::vmo::create_physical(mmio_resource, spec.base, spec.size, &vmo);
        if (status != ZX_OK) {
          FX_LOGS(ERROR) << "Failed to create physical VMO " << status;
          return status;
        }
        status = vmo.set_cache_policy(cache_policy(spec.policy));
        if (status != ZX_OK) {
          FX_LOGS(ERROR) << "Failed to set cache policy on VMO " << status;
          return status;
        }
        break;
      default:
        FX_LOGS(ERROR) << "Unknown memory policy " << static_cast<uint32_t>(spec.policy);
        return ZX_ERR_INVALID_ARGS;
    }

    if (!vmex_resource) {
      status = get_vmex_resource(&vmex_resource);
      if (status != ZX_OK) {
        FX_LOGS(ERROR) << "Failed to get VMEX resource " << status;
        return status;
      }
    }
    status = vmo.replace_as_executable(vmex_resource, &vmo);
    if (status != ZX_OK) {
      FX_LOGS(ERROR) << "Failed to make VMO executable " << status;
      return status;
    }

    zx_gpaddr_t addr;
    status = vmar_.map(ZX_VM_PERM_READ | ZX_VM_PERM_WRITE | ZX_VM_PERM_EXECUTE | ZX_VM_SPECIFIC |
                           ZX_VM_REQUIRE_NON_RESIZABLE,
                       spec.base, vmo, 0, spec.size, &addr);
    if (status != ZX_OK) {
      FX_LOGS(ERROR) << "Failed to map guest physical memory " << status;
      return status;
    }
    if (!phys_mem_.vmo() && spec.policy == fuchsia::virtualization::MemoryPolicy::GUEST_CACHED) {
      status = phys_mem_.Init(std::move(vmo));
      if (status != ZX_OK) {
        FX_LOGS(ERROR) << "Failed to initialize guest physical memory " << status;
        return status;
      }
    }
  }

  return ZX_OK;
}

zx_status_t Guest::CreateMapping(TrapType type, uint64_t addr, size_t size, uint64_t offset,
                                 IoHandler* handler, async_dispatcher_t* dispatcher) {
  uint32_t kind = trap_kind(type);
  mappings_.emplace_front(kind, addr, size, offset, handler);
  zx_status_t status = mappings_.front().SetTrap(this, dispatcher);
  if (status != ZX_OK) {
    mappings_.pop_front();
    return status;
  }
  return ZX_OK;
}

zx_status_t Guest::CreateSubVmar(uint64_t addr, size_t size, zx::vmar* vmar) {
  uintptr_t guest_addr;
  return vmar_.allocate(ZX_VM_CAN_MAP_READ | ZX_VM_CAN_MAP_WRITE | ZX_VM_SPECIFIC, addr, size,
                        vmar, &guest_addr);
}

zx_status_t Guest::StartVcpu(uint64_t id, zx_gpaddr_t entry, zx_gpaddr_t boot_ptr,
                             async::Loop* loop) {
  if (id >= kMaxVcpus) {
    FX_LOGS(ERROR) << "Failed to start VCPU-" << id << ", up to " << kMaxVcpus
                   << " VCPUs are supported";
    return ZX_ERR_OUT_OF_RANGE;
  }

  std::lock_guard<std::shared_mutex> lock(mutex_);
  if (vcpus_[0] == nullptr && id != 0) {
    FX_LOGS(ERROR) << "VCPU-0 must be started before other VCPUs";
    return ZX_ERR_BAD_STATE;
  }
  if (vcpus_[id] != nullptr) {
    // The guest might make multiple requests to start a particular VCPU. On
    // x86, the guest should send two START_UP IPIs but we initialize the VCPU
    // on the first. So, we ignore subsequent requests.
    return ZX_OK;
  }
  vcpus_[id] = std::make_unique<Vcpu>(id, this, entry, boot_ptr, loop);
  return vcpus_[id]->Start();
}

zx_status_t Guest::Interrupt(uint64_t mask, uint8_t vector) {
  std::shared_lock<std::shared_mutex> lock(mutex_);
  for (size_t id = 0; id != kMaxVcpus; ++id) {
    if (!(mask & (1ul << id)) || !vcpus_[id]) {
      continue;
    }
    zx_status_t status = vcpus_[id]->Interrupt(vector);
    if (status != ZX_OK) {
      return status;
    }
#ifdef __aarch64__
    if (vector >= kSpiBase) {
      break;
    }
#endif
  }
  return ZX_OK;
}
