// Copyright 2018 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 "device_context.h"

#include <align.h>
#include <lib/fit/defer.h>
#include <trace.h>

#include <new>

#include <kernel/range_check.h>
#include <ktl/algorithm.h>
#include <ktl/move.h>
#include <ktl/unique_ptr.h>
#include <vm/vm.h>
#include <vm/vm_object_paged.h>

#include "hw.h"
#include "iommu_impl.h"

#define LOCAL_TRACE 0

namespace intel_iommu {

DeviceContext::DeviceContext(ds::Bdf bdf, uint32_t domain_id, IommuImpl* parent,
                             volatile ds::ExtendedContextEntry* context_entry)
    : parent_(parent),
      extended_context_entry_(context_entry),
      second_level_pt_(parent, this),
      region_alloc_(),
      bdf_(bdf),
      extended_(true),
      domain_id_(domain_id) {}

DeviceContext::DeviceContext(ds::Bdf bdf, uint32_t domain_id, IommuImpl* parent,
                             volatile ds::ContextEntry* context_entry)
    : parent_(parent),
      context_entry_(context_entry),
      second_level_pt_(parent, this),
      region_alloc_(),
      bdf_(bdf),
      extended_(false),
      domain_id_(domain_id) {}

DeviceContext::~DeviceContext() {
  bool was_present;
  if (extended_) {
    ds::ExtendedContextEntry entry;
    entry.ReadFrom(extended_context_entry_);
    was_present = entry.present();
    entry.set_present(0);
    entry.WriteTo(extended_context_entry_);
  } else {
    ds::ContextEntry entry;
    entry.ReadFrom(context_entry_);
    was_present = entry.present();
    entry.set_present(0);
    entry.WriteTo(context_entry_);
  }

  if (was_present) {
    // When modifying a present (extended) context entry, we must serially
    // invalidate the context-cache, the PASID-cache, then the IOTLB (see
    // 6.2.2.1 "Context-Entry Programming Considerations" in the VT-d spec,
    // Oct 2014 rev).
    parent_->InvalidateContextCacheDomain(domain_id_);
    // TODO(teisenbe): Invalidate the PASID cache once we support those
    parent_->InvalidateIotlbDomainAll(domain_id_);
  }

  second_level_pt_.Destroy();
}

zx_status_t DeviceContext::InitCommon() {
  // TODO(teisenbe): don't hardcode PML4_L
  DEBUG_ASSERT(parent_->caps()->supports_48_bit_agaw());
  zx_status_t status = second_level_pt_.Init(PageTableLevel::PML4_L);
  if (status != ZX_OK) {
    return status;
  }

  constexpr size_t kMaxAllocatorMemoryUsage = 16 * PAGE_SIZE;
  fbl::RefPtr<RegionAllocator::RegionPool> region_pool =
      RegionAllocator::RegionPool::Create(kMaxAllocatorMemoryUsage);
  if (region_pool == nullptr) {
    return ZX_ERR_NO_MEMORY;
  }
  status = region_alloc_.SetRegionPool(ktl::move(region_pool));
  if (status != ZX_OK) {
    return status;
  }

  // Start the allocations at 1MB to handle the equivalent of nullptr
  // dereferences.
  uint64_t base = 1ull << 20;
  uint64_t size = aspace_size() - base;
  region_alloc_.AddRegion({.base = 1ull << 20, .size = size});
  return ZX_OK;
}

zx_status_t DeviceContext::Create(ds::Bdf bdf, uint32_t domain_id, IommuImpl* parent,
                                  volatile ds::ContextEntry* context_entry,
                                  ktl::unique_ptr<DeviceContext>* device) {
  ds::ContextEntry entry;
  entry.ReadFrom(context_entry);

  // It's a bug if we're trying to re-initialize an existing entry
  ASSERT(!entry.present());

  fbl::AllocChecker ac;
  ktl::unique_ptr<DeviceContext> dev(new (&ac)
                                         DeviceContext(bdf, domain_id, parent, context_entry));
  if (!ac.check()) {
    return ZX_ERR_NO_MEMORY;
  }

  zx_status_t status = dev->InitCommon();
  if (status != ZX_OK) {
    return status;
  }

  entry.set_present(1);
  entry.set_fault_processing_disable(0);
  entry.set_translation_type(ds::ContextEntry::kDeviceTlbDisabled);
  // TODO(teisenbe): don't hardcode this
  entry.set_address_width(ds::ContextEntry::k48Bit);
  entry.set_domain_id(domain_id);
  entry.set_second_level_pt_ptr(dev->second_level_pt_.phys() >> 12);

  entry.WriteTo(context_entry);

  *device = ktl::move(dev);
  return ZX_OK;
}

zx_status_t DeviceContext::Create(ds::Bdf bdf, uint32_t domain_id, IommuImpl* parent,
                                  volatile ds::ExtendedContextEntry* context_entry,
                                  ktl::unique_ptr<DeviceContext>* device) {
  ds::ExtendedContextEntry entry;
  entry.ReadFrom(context_entry);

  // It's a bug if we're trying to re-initialize an existing entry
  ASSERT(!entry.present());

  fbl::AllocChecker ac;
  ktl::unique_ptr<DeviceContext> dev(new (&ac)
                                         DeviceContext(bdf, domain_id, parent, context_entry));
  if (!ac.check()) {
    return ZX_ERR_NO_MEMORY;
  }

  zx_status_t status = dev->InitCommon();
  if (status != ZX_OK) {
    return status;
  }

  entry.set_present(1);
  entry.set_fault_processing_disable(0);
  entry.set_translation_type(ds::ExtendedContextEntry::kHostModeWithDeviceTlbDisabled);
  entry.set_deferred_invld_enable(0);
  entry.set_page_request_enable(0);
  entry.set_nested_translation_enable(0);
  entry.set_pasid_enable(0);
  entry.set_global_page_enable(0);
  // TODO(teisenbe): don't hardcode this
  entry.set_address_width(ds::ExtendedContextEntry::k48Bit);
  entry.set_no_exec_enable(1);
  entry.set_write_protect_enable(1);
  entry.set_cache_disable(0);
  entry.set_extended_mem_type_enable(0);
  entry.set_domain_id(domain_id);
  entry.set_smep_enable(1);
  entry.set_extended_accessed_flag_enable(0);
  entry.set_execute_requests_enable(0);
  entry.set_second_level_execute_bit_enable(0);
  entry.set_second_level_pt_ptr(dev->second_level_pt_.phys() >> 12);

  entry.WriteTo(context_entry);

  *device = ktl::move(dev);
  return ZX_OK;
}

namespace {

uint perms_to_arch_mmu_flags(uint32_t perms) {
  uint flags = 0;
  if (perms & IOMMU_FLAG_PERM_READ) {
    flags |= ARCH_MMU_FLAG_PERM_READ;
  }
  if (perms & IOMMU_FLAG_PERM_WRITE) {
    flags |= ARCH_MMU_FLAG_PERM_WRITE;
  }
  if (perms & IOMMU_FLAG_PERM_EXECUTE) {
    flags |= ARCH_MMU_FLAG_PERM_EXECUTE;
  }
  return flags;
}

}  // namespace

zx_status_t DeviceContext::SecondLevelMap(const fbl::RefPtr<VmObject>& vmo, uint64_t offset,
                                          size_t size, uint32_t perms, bool map_contiguous,
                                          paddr_t* virt_paddr, size_t* mapped_len) {
  DEBUG_ASSERT(IS_PAGE_ALIGNED(offset));

  uint flags = perms_to_arch_mmu_flags(perms);

  if (vmo->LookupContiguous(offset, size, nullptr) == ZX_OK) {
    return SecondLevelMapDiscontiguous(vmo, offset, size, flags, map_contiguous, virt_paddr,
                                       mapped_len);
  }
  return SecondLevelMapContiguous(vmo, offset, size, flags, virt_paddr, mapped_len);
}

zx_status_t DeviceContext::SecondLevelMapDiscontiguous(const fbl::RefPtr<VmObject>& vmo,
                                                       uint64_t offset, size_t size, uint flags,
                                                       bool map_contiguous, paddr_t* virt_paddr,
                                                       size_t* mapped_len) {
  // If we don't need to map everything, don't try to map more than
  // the min contiguity at a time.
  const uint64_t min_contig = minimum_contiguity();
  if (!map_contiguous && size > min_contig) {
    size = min_contig;
  }

  RegionAllocator::Region::UPtr region;
  zx_status_t status = region_alloc_.GetRegion(size, min_contig, region);
  if (status != ZX_OK) {
    return status;
  }

  // Reserve a spot in the allocated regions list, so the extension can't fail
  // after we do the map.
  fbl::AllocChecker ac;
  allocated_regions_.reserve(allocated_regions_.size() + 1, &ac);
  if (!ac.check()) {
    return ZX_ERR_NO_MEMORY;
  }

  paddr_t base = region->base;
  size_t remaining = size;

  auto cleanup_partial = fit::defer([&]() {
    size_t allocated = base - region->base;
    size_t unmapped;
    second_level_pt_.UnmapPages(base, allocated / PAGE_SIZE, &unmapped);
    DEBUG_ASSERT(unmapped == allocated / PAGE_SIZE);
  });

  while (remaining > 0) {
    const size_t kNumEntriesPerLookup = 32;
    size_t chunk_size = ktl::min(remaining, kNumEntriesPerLookup * PAGE_SIZE);
    paddr_t paddrs[kNumEntriesPerLookup] = {};
    size_t pages_found = 0;
    auto lookup_fn = [&paddrs, &pages_found, &offset](uint64_t page_offset, paddr_t pa) {
      size_t index = (page_offset - offset) / PAGE_SIZE;
      paddrs[index] = pa;
      pages_found++;
      return ZX_ERR_NEXT;
    };
    status = vmo->Lookup(offset, chunk_size, lookup_fn);
    if (status != ZX_OK) {
      return status;
    }
    if (pages_found != chunk_size / PAGE_SIZE) {
      return ZX_ERR_NO_MEMORY;
    }

    size_t map_len = chunk_size / PAGE_SIZE;
    size_t mapped;
    status = second_level_pt_.MapPages(base, paddrs, map_len, flags,
                                       SecondLevelPageTable::ExistingEntryAction::Error, &mapped);
    if (status != ZX_OK) {
      return status;
    }
    ASSERT(mapped == map_len);

    base += chunk_size;
    offset += chunk_size;
    remaining -= chunk_size;
  }

  cleanup_partial.cancel();

  *virt_paddr = region->base;
  *mapped_len = size;

  allocated_regions_.push_back(ktl::move(region), &ac);
  // Check shouldn't be able to fail, since we reserved the capacity already
  ASSERT(ac.check());

  LTRACEF("Map(%02x:%02x.%1x): -> [%p, %p) %#x\n", bdf_.bus(), bdf_.dev(), bdf_.func(),
          (void*)*virt_paddr, (void*)(*virt_paddr + *mapped_len), flags);
  return ZX_OK;
}

zx_status_t DeviceContext::SecondLevelMapContiguous(const fbl::RefPtr<VmObject>& vmo,
                                                    uint64_t offset, size_t size, uint flags,
                                                    paddr_t* virt_paddr, size_t* mapped_len) {
  paddr_t paddr = UINT64_MAX;
  zx_status_t status = vmo->LookupContiguous(offset, size, &paddr);
  if (status != ZX_OK) {
    return status;
  }
  DEBUG_ASSERT(paddr != UINT64_MAX);

  RegionAllocator::Region::UPtr region;
  uint64_t min_contig = minimum_contiguity();
  status = region_alloc_.GetRegion(size, min_contig, region);
  if (status != ZX_OK) {
    return status;
  }

  // Reserve a spot in the allocated regions list, so the extension can't fail
  // after we do the map.
  fbl::AllocChecker ac;
  allocated_regions_.reserve(allocated_regions_.size() + 1, &ac);
  if (!ac.check()) {
    return ZX_ERR_NO_MEMORY;
  }

  size_t map_len = size / PAGE_SIZE;
  size_t mapped;
  status = second_level_pt_.MapPagesContiguous(region->base, paddr, map_len, flags, &mapped);
  if (status != ZX_OK) {
    return status;
  }
  ASSERT(mapped == map_len);

  *virt_paddr = region->base;
  *mapped_len = map_len * PAGE_SIZE;

  allocated_regions_.push_back(ktl::move(region), &ac);
  // Check shouldn't be able to fail, since we reserved the capacity already
  ASSERT(ac.check());

  LTRACEF("Map(%02x:%02x.%1x): [%p, %p) -> %p %#x\n", bdf_.bus(), bdf_.dev(), bdf_.func(),
          (void*)paddr, (void*)(paddr + size), (void*)paddr, flags);
  return ZX_OK;
}

zx_status_t DeviceContext::SecondLevelMapIdentity(paddr_t base, size_t size, uint32_t perms) {
  DEBUG_ASSERT(IS_PAGE_ALIGNED(base));
  DEBUG_ASSERT(IS_PAGE_ALIGNED(size));

  uint flags = perms_to_arch_mmu_flags(perms);

  RegionAllocator::Region::UPtr region;
  zx_status_t status = region_alloc_.GetRegion({base, size}, region);
  if (status != ZX_OK) {
    return status;
  }

  // Reserve a spot in the allocated regions list, so the extension can't fail
  // after we do the map.
  fbl::AllocChecker ac;
  allocated_regions_.reserve(allocated_regions_.size() + 1, &ac);
  if (!ac.check()) {
    return ZX_ERR_NO_MEMORY;
  }

  size_t map_len = size / PAGE_SIZE;
  size_t mapped;
  status = second_level_pt_.MapPagesContiguous(base, base, map_len, flags, &mapped);
  if (status != ZX_OK) {
    return status;
  }
  ASSERT(mapped == map_len);

  allocated_regions_.push_back(ktl::move(region), &ac);
  ASSERT(ac.check());
  return ZX_OK;
}

zx_status_t DeviceContext::SecondLevelUnmap(paddr_t virt_paddr, size_t size) {
  DEBUG_ASSERT(IS_PAGE_ALIGNED(virt_paddr));
  DEBUG_ASSERT(IS_PAGE_ALIGNED(size));

  // Check if we're trying to partially unmap a region, and if so fail.
  for (size_t i = 0; i < allocated_regions_.size(); ++i) {
    const auto& region = allocated_regions_[i];

    paddr_t intersect_base;
    size_t intersect_size;
    if (!GetIntersect(virt_paddr, size, region->base, region->size, &intersect_base,
                      &intersect_size)) {
      continue;
    }

    if (intersect_base != region->base || intersect_size != region->size) {
      return ZX_ERR_NOT_SUPPORTED;
    }
  }

  for (size_t i = 0; i < allocated_regions_.size(); ++i) {
    const auto& region = allocated_regions_[i];
    if (region->base < virt_paddr || region->base + region->size > virt_paddr + size) {
      continue;
    }

    size_t unmapped;
    LTRACEF("Unmap(%02x:%02x.%1x): [%p, %p)\n", bdf_.bus(), bdf_.dev(), bdf_.func(),
            (void*)region->base, (void*)(region->base + region->size));
    zx_status_t status =
        second_level_pt_.UnmapPages(region->base, region->size / PAGE_SIZE, &unmapped);
    // Unmap should only be able to fail if an input was invalid
    ASSERT(status == ZX_OK);
    allocated_regions_.erase(i);
    i--;
  }

  return ZX_OK;
}

void DeviceContext::SecondLevelUnmapAllLocked() {
  while (allocated_regions_.size() > 0) {
    auto& region = allocated_regions_[allocated_regions_.size() - 1];
    zx_status_t status = SecondLevelUnmap(region->base, region->size);
    // SecondLevelUnmap only fails on invalid inputs, and our inputs would only be invalid if our
    // internals are corrupt.
    ASSERT(status == ZX_OK);
  }
}

uint64_t DeviceContext::minimum_contiguity() const {
  // TODO(teisenbe): Do not hardcode this.
  return 1ull << 20;
}

uint64_t DeviceContext::aspace_size() const {
  // TODO(teisenbe): Do not hardcode this
  // 2^48 is the size of an address space using 4-levevel translation.
  return 1ull << 48;
}

}  // namespace intel_iommu
