// Copyright 2021 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 "handoff-prep.h"

#include <lib/boot-options/boot-options.h>
#include <lib/llvm-profdata/llvm-profdata.h>
#include <lib/memalloc/pool-mem-config.h>
#include <lib/memalloc/pool.h>
#include <lib/memalloc/range.h>
#include <lib/trivial-allocator/new.h>
#include <stdio.h>
#include <string-file.h>
#include <zircon/assert.h>

#include <ktl/algorithm.h>
#include <phys/allocation.h>
#include <phys/handoff.h>
#include <phys/symbolize.h>

#include <ktl/enforce.h>

namespace {

// Carve out some physical pages requested for testing before handing off.
void FindTestRamReservation(RamReservation& ram) {
  ZX_ASSERT_MSG(!ram.paddr, "Must use kernel.test.ram.reserve=SIZE without ,ADDRESS!");

  memalloc::Pool& pool = Allocation::GetPool();

  // Don't just use Pool::Allocate because that will use the first (lowest)
  // address with space.  The kernel's PMM initialization doesn't like the
  // earliest memory being split up too small, and anyway that's not very
  // representative of just a normal machine with some device memory elsewhere,
  // which is what the test RAM reservation is really meant to simulate.
  // Instead, find the highest-addressed, most likely large chunk that is big
  // enough and just make it a little smaller, which is probably more like what
  // an actual machine with a little less RAM would look like.

  auto it = pool.end();
  while (true) {
    if (it == pool.begin()) {
      break;
    }
    --it;
    if (it->type == memalloc::Type::kFreeRam && it->size >= ram.size) {
      uint64_t aligned_start = (it->addr + it->size - ram.size) & -uint64_t{ZX_PAGE_SIZE};
      uint64_t aligned_end = aligned_start + ram.size;
      if (aligned_start >= it->addr && aligned_end <= aligned_start + ram.size) {
        if (pool.UpdateFreeRamSubranges(memalloc::Type::kTestRamReserve, aligned_start, ram.size)
                .is_ok()) {
          ram.paddr = aligned_start;
          if (gBootOptions->phys_verbose) {
            // Dump out the memory usage again to show the reservation.
            printf("%s: Physical memory after kernel.test.ram.reserve carve-out:\n", ProgramName());
            pool.PrintMemoryRanges(ProgramName());
          }
          return;
        }
        // Don't try another spot if something went wrong.
        break;
      }
    }
  }

  printf("%s: ERROR: Cannot reserve %#" PRIx64
         " bytes of RAM for kernel.test.ram.reserve request!\n",
         ProgramName(), ram.size);
}

}  // namespace

void HandoffPrep::Init(ktl::span<ktl::byte> buffer) {
  // TODO(fxbug.dev/84107): Use the buffer inside the data ZBI via a
  // SingleHeapAllocator.  Later allocator() will return a real(ish) allocator.
  allocator_.allocate_function() = AllocateFunction(buffer);

  fbl::AllocChecker ac;
  handoff_ = new (allocator(), ac) PhysHandoff;
  ZX_ASSERT_MSG(ac.check(), "handoff buffer too small for PhysHandoff!");
}

void HandoffPrep::SetInstrumentation() {
  ZX_DEBUG_ASSERT(gSymbolize);

  // Publish llvm-profdata if present.
  LlvmProfdata profdata;
  profdata.Init(gSymbolize->BuildId());
  if (profdata.size_bytes() != 0) {
    fbl::AllocChecker ac;
    ktl::span buffer = New(handoff()->instrumentation.llvm_profdata, ac, profdata.size_bytes());
    ZX_ASSERT_MSG(ac.check(), "cannot allocate %zu bytes for llvm-profdata", profdata.size_bytes());
    ZX_DEBUG_ASSERT(buffer.size() == profdata.size_bytes());

    // Copy the fixed data and initial counter values and then start updating
    // the handoff data in place.
    ktl::span counters = profdata.WriteFixedData(buffer);
    profdata.CopyCounters(counters);
    LlvmProfdata::UseCounters(counters);
  }

  // Collect the symbolizer logging, including logs for each nonempty dump.
  SetSymbolizerLog({
      {
          .announce = LlvmProfdata::kAnnounce,
          .sink_name = LlvmProfdata::kDataSinkName,
          .vmo_name = "physboot.profraw",
          .size_bytes = profdata.size_bytes(),
      },
  });
}

void HandoffPrep::SetSymbolizerLog(ktl::initializer_list<Debugdata> dumps) {
  auto log_to = [dumps](FILE& file) {
    Symbolize symbolize(ProgramName(), &file);
    symbolize.Context();
    for (const Debugdata& dump : dumps) {
      if (dump.size_bytes != 0) {
        symbolize.DumpFile(dump.sink_name, dump.vmo_name, dump.announce, dump.size_bytes);
      }
    }
  };

  // First generate the symbolzer log text just to count its size.
  struct CountFile {
   public:
    size_t size() const { return size_; }

    int Write(ktl::string_view str) {
      size_ += str.size();
      return static_cast<int>(str.size());
    }

   private:
    size_t size_ = 0;
  };
  CountFile counter;
  FILE count_file(&counter);
  log_to(count_file);

  // Now we can allocate the handoff buffer for that data.
  fbl::AllocChecker ac;
  ktl::span buffer = New(handoff()->instrumentation.symbolizer_log, ac, counter.size() + 1);
  ZX_ASSERT_MSG(ac.check(), "cannot allocate %zu bytes for symbolizer log", counter.size());

  // Finally, generate the same text again to fill the buffer.
  StringFile buffer_file(buffer);
  log_to(buffer_file);

  // We had to add an extra char to the buffer since StringFile wants to
  // NUL-terminate it.  But we don't want the NUL, so make it whitespace.
  ktl::move(buffer_file).take().back() = '\n';
}

BootOptions& HandoffPrep::SetBootOptions(const BootOptions& boot_options) {
  fbl::AllocChecker ac;
  BootOptions* handoff_options = New(handoff()->boot_options, ac, *gBootOptions);
  ZX_ASSERT_MSG(ac.check(), "cannot allocate handoff BootOptions!");

  if (handoff_options->test_ram_reserve) {
    FindTestRamReservation(*handoff_options->test_ram_reserve);
  }

  return *handoff_options;
}
