// Copyright 2022 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 "live-memory-cache.h"

#include <lib/stdcompat/span.h>
#include <lib/zx/process.h>
#include <lib/zxdump/buffer.h>
#include <zircon/assert.h>
#include <zircon/syscalls.h>

#include <cinttypes>

#include "buffer-impl.h"

namespace zxdump {
namespace {

const size_t kPagesize = zx_system_get_page_size();

}  // namespace

cpp20::span<const std::byte> TaskHolder::LiveMemoryCache::Page::contents() const {
  return {contents_.get(), kPagesize};
}

TaskHolder::LiveMemoryCache::Page::~Page() {
  ZX_DEBUG_ASSERT(refs_ == 0);

  // Remove this page from the per-process cache index.
  owner_.cache_index().erase(*this);
}

TaskHolder::LiveMemoryCache::PageRef::~PageRef() {
  ZX_DEBUG_ASSERT(page_.refs_ > 0);
  if (--page_.refs_ == 0) {
    // When a page goes from some refs to no refs, it counts as cached.
    page_.owner_.shared_cache().OnCachedPage();
  }
}

TaskHolder::LiveMemoryCache::PageRefPtr TaskHolder::LiveMemoryCache::NewPage(
    Process::LiveMemory& owner, uint64_t vaddr, PageContentsPtr contents) {
  // Page is only constructed here and held in std::unique_ptr<Page>.
  auto page = std::make_unique<Page>(owner, vaddr, std::move(contents));

  // Insert the raw pointer into the owner's cache index.
  // The Page destructor will remove it from the index.
  owner.cache_index().insert(page.get());

  // The new page starts with one ref, owned by the return value.
  PageRefPtr ref = std::make_unique<PageRef>(*page);

  // Move the ownership to the end of the shared cache list, in MRU position.
  // This will be removed and destroyed only be OnCachedPage, below.
  cache_.push_back(std::move(page));

  return ref;
}

TaskHolder::LiveMemoryCache::PageRefPtr TaskHolder::LiveMemoryCache::Reuse(Page& page) {
  // Simply slice it out of the list and move it to the end (MRU position).
  cache_.push_back(cache_.erase(page));

  // Return a new reference to the now-MRU page.
  return std::make_unique<PageRef>(page);
}

void TaskHolder::LiveMemoryCache::OnCachedPage() {
  // One more page is now cached.
  cache_size_ += kPagesize;

  PruneCache();
}

void TaskHolder::LiveMemoryCache::PruneCache() {
  if (cache_size_ <= cache_limit_) {
    return;
  }

  // There are now too many pages cached, so drop the LRU cached page.  The
  // pages with refs don't count towards the cache size, so there must be a
  // page with no refs in the list.  But in LRU order there might be pages
  // with live refs earlier in the list.  They are kept there so that as soon
  // as their last ref is dropped by the past Process::read_memory caller
  // later destroying their Buffer, that page is eligible to be reclaimed
  // before pages from Process::read_memory calls more recent than that one.
  auto head = cache_.begin();
  ZX_DEBUG_ASSERT(head != cache_.end());
  while (head->has_refs()) {
    ++head;
    ZX_DEBUG_ASSERT(head != cache_.end());
  }

  // This returns the std::unique_ptr and so deletes the Page.
  // The Page destructor removes itself from its owner's cache index.
  cache_.erase(head++);
}

fit::result<Error, Buffer<>> Process::LiveMemory::ReadLiveMemory(
    uint64_t vaddr, size_t size, ReadMemorySize size_mode, const LiveHandle& handle,
    TaskHolder::LiveMemoryCache& shared_cache) {
  zx::unowned_process process(handle.get());
  ZX_DEBUG_ASSERT(process->is_valid());

  auto read_one_page = [this, process,
                        &shared_cache](uint64_t page_vaddr) -> fit::result<Error, PageRefPtr> {
    if (auto it = cache_index_.find(page_vaddr); it != cache_index_.end()) {
      // Found a cached page.  Mark it as reused and get a fresh reference.
      return fit::ok(shared_cache.Reuse(*it));
    }

    // This page isn't available in the cache, so read it from the process.
    TaskHolder::LiveMemoryCache::PageContentsPtr contents(new std::byte[kPagesize]);
    size_t bytes_read = 0;
    if (zx_status_t status =
            process->read_memory(page_vaddr, contents.get(), kPagesize, &bytes_read);
        status != ZX_OK) {
      return fit::error{Error{
          .op_ = "zx_process_read_memory",
          .status_ = status,
      }};
    }

    ZX_ASSERT_MSG(bytes_read == kPagesize,
                  "zx_process_read_memory on aligned address %#" PRIx64
                  " returned %#zx bytes vs expected page size %#zx",
                  page_vaddr, bytes_read, kPagesize);

    return fit::ok(shared_cache_.NewPage(*this, page_vaddr, std::move(contents)));
  };

  uint64_t first_page = vaddr & -kPagesize;
  uint64_t last_page = (vaddr + size - 1) & -kPagesize;

  // Most reads will fit inside a single page.
  if (first_page == last_page || size_mode == ReadMemorySize::kLess) {
    auto result = read_one_page(vaddr & -kPagesize);
    if (result.is_error()) {
      return result.take_error();
    }
    Buffer<> buffer;
    buffer.data_ = (**result)->contents().subspan(vaddr & (kPagesize - 1));
    if (size_mode == ReadMemorySize::kExact && buffer.data_.size_bytes() > size) {
      buffer.data_ = buffer.data_.subspan(0, size);
    }
    buffer.impl_ = *std::move(result);
    return fit::ok(std::move(buffer));
  }

  // The request spans multiple pages, so we'll read separate whole
  // pages and then copy out of them into a plain BufferImplVector.
  const size_t page_count = ((last_page - first_page) / kPagesize) + 1;
  std::vector<PageRefPtr> pages;
  pages.reserve(page_count);
  while (first_page <= last_page) {
    PageRefPtr page;
    if (auto result = read_one_page(first_page); result.is_ok()) {
      page = *std::move(result);
    } else {
      return result.take_error();
    }
    pages.push_back(std::move(page));
    first_page += kPagesize;
  }

  auto copy = std::make_unique<internal::BufferImplVector>();
  copy->reserve(size);
  for (PageRefPtr& ref : pages) {
    // Take ownership of the page so it can die as soon as its data is copied.
    PageRefPtr page = std::move(ref);

    auto contents = (*page)->contents().subspan(vaddr & (kPagesize - 1));
    if (contents.size_bytes() > size) {
      contents = contents.subspan(0, size);
    }
    copy->insert(copy->end(), contents.begin(), contents.end());

    vaddr &= -kPagesize;
    vaddr += kPagesize;
    size -= contents.size_bytes();
  }

  Buffer<> buffer;
  buffer.data_ = cpp20::span(*copy);
  buffer.impl_ = std::move(copy);
  return fit::ok(std::move(buffer));
}

}  // namespace zxdump
