// 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;
  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 root 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;
    }

    status = vmo.replace_as_executable(zx::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_.allocate2(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;
}
