// 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 "second_level_pt.h"

#include <arch/x86/mmu.h>

#include "device_context.h"
#include "iommu_impl.h"

#define LOCAL_TRACE 0

namespace {

constexpr PtFlags kSlptRead = 1u << 0;
constexpr PtFlags kSlptWrite = 1u << 1;
constexpr PtFlags kSlptExecute = 1u << 2;

vaddr_t compute_vaddr_mask(PageTableLevel top_level) {
  uint width;
  switch (top_level) {
    case PageTableLevel::PD_L:
      width = 30;
      break;
    case PageTableLevel::PDP_L:
      width = 39;
      break;
    case PageTableLevel::PML4_L:
      width = 48;
      break;
    default:
      panic("Unsupported iommu width\n");
  }

  // Valid vaddrs for mapping should be page-aligned and not larger than the
  // width of the top level.
  return ((1ull << width) - 1) & ~(PAGE_SIZE - 1);
}

}  // namespace

namespace intel_iommu {

SecondLevelPageTable::SecondLevelPageTable(IommuImpl* iommu, DeviceContext* parent)
    : iommu_(iommu),
      parent_(parent),
      needs_flushes_(!iommu->extended_caps()->page_walk_coherency()),
      supports_2mb_(iommu->caps()->supports_second_level_2mb_page()),
      supports_1gb_(iommu->caps()->supports_second_level_1gb_page()),
      initialized_(false) {}

SecondLevelPageTable::~SecondLevelPageTable() { DEBUG_ASSERT(!initialized_); }

zx_status_t SecondLevelPageTable::Init(PageTableLevel top_level) {
  DEBUG_ASSERT(!initialized_);

  top_level_ = top_level;
  valid_vaddr_mask_ = compute_vaddr_mask(top_level);
  zx_status_t status = X86PageTableBase::Init(nullptr);
  if (status != ZX_OK) {
    return status;
  }
  initialized_ = true;
  return ZX_OK;
}

void SecondLevelPageTable::Destroy() {
  if (!initialized_) {
    return;
  }

  size_t size = valid_vaddr_mask_ + PAGE_SIZE;
  initialized_ = false;
  X86PageTableBase::Destroy(0, size);
}

bool SecondLevelPageTable::allowed_flags(uint flags) {
  constexpr uint kSupportedFlags =
      ARCH_MMU_FLAG_PERM_READ | ARCH_MMU_FLAG_PERM_WRITE | ARCH_MMU_FLAG_PERM_EXECUTE;
  if (flags & ~kSupportedFlags) {
    return false;
  }
  return true;
}

// Validation for host physical addresses
bool SecondLevelPageTable::check_paddr(paddr_t paddr) { return x86_mmu_check_paddr(paddr); }

// Validation for virtual physical addresses
bool SecondLevelPageTable::check_vaddr(vaddr_t vaddr) { return !(vaddr & ~valid_vaddr_mask_); }

bool SecondLevelPageTable::supports_page_size(PageTableLevel level) {
  switch (level) {
    case PageTableLevel::PT_L:
      return true;
    case PageTableLevel::PD_L:
      return supports_2mb_;
    case PageTableLevel::PDP_L:
      return supports_1gb_;
    default:
      return false;
  }
}

IntermediatePtFlags SecondLevelPageTable::intermediate_flags() {
  return kSlptRead | kSlptWrite | kSlptExecute;
}

PtFlags SecondLevelPageTable::terminal_flags(PageTableLevel level, uint flags) {
  PtFlags terminal_flags = 0;

  if (flags & ARCH_MMU_FLAG_PERM_READ) {
    terminal_flags |= kSlptRead;
  }
  if (flags & ARCH_MMU_FLAG_PERM_WRITE) {
    terminal_flags |= kSlptWrite;
  }
  if (flags & ARCH_MMU_FLAG_PERM_EXECUTE) {
    terminal_flags |= kSlptExecute;
  }

  return terminal_flags;
}

PtFlags SecondLevelPageTable::split_flags(PageTableLevel level, PtFlags flags) {
  // We don't need to relocate any flags on split
  return flags;
}

// We disable thread safety analysis here, since the lock being held is being
// held across the MMU operations, but goes through code that is not aware of
// the lock.
void SecondLevelPageTable::TlbInvalidate(PendingTlbInvalidation* pending)
    TA_NO_THREAD_SAFETY_ANALYSIS {
  DEBUG_ASSERT(!pending->contains_global);

  if (pending->full_shootdown) {
    iommu_->InvalidateIotlbDomainAllLocked(parent_->domain_id());
    pending->clear();
    return;
  }

  constexpr uint kBitsPerLevel = 9;
  for (uint i = 0; i < pending->count; ++i) {
    const auto& item = pending->item[i];
    uint address_mask = kBitsPerLevel * static_cast<uint>(item.page_level());

    if (!item.is_terminal()) {
      // If this is non-terminal, force the paging-structure cache to be
      // cleared for this address still, even though a terminal mapping hasn't
      // been changed.
      // TODO(teisenbe): Not completely sure this is necessary.  Including for
      // now out of caution.
      address_mask = 0;
    }
    iommu_->InvalidateIotlbPageLocked(parent_->domain_id(), item.addr(), address_mask);
  }
  pending->clear();
}

uint SecondLevelPageTable::pt_flags_to_mmu_flags(PtFlags flags, PageTableLevel level) {
  uint mmu_flags = 0;

  if (flags & kSlptRead) {
    mmu_flags |= ARCH_MMU_FLAG_PERM_READ;
  }
  if (flags & kSlptWrite) {
    mmu_flags |= ARCH_MMU_FLAG_PERM_WRITE;
  }
  if (flags & kSlptExecute) {
    mmu_flags |= ARCH_MMU_FLAG_PERM_EXECUTE;
  }

  return mmu_flags;
}

}  // namespace intel_iommu
