// Copyright 2016 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 "msd_intel_device.h"

#include <lib/magma/platform/platform_trace.h>
#include <lib/magma/util/dlog.h>
#include <lib/magma/util/short_macros.h>

#include <bitset>
#include <cstdio>
#include <iterator>
#include <string>

#include <fbl/string_printf.h>

#include "cache_config.h"
#include "device_id.h"
#include "forcewake.h"
#include "magma_intel_gen_defs.h"
#include "msd_intel_semaphore.h"
#include "registers.h"

inline uint64_t get_current_time_ns() {
  return std::chrono::time_point_cast<std::chrono::nanoseconds>(std::chrono::steady_clock::now())
      .time_since_epoch()
      .count();
}

class MsdIntelDevice::BatchRequest : public DeviceRequest {
 public:
  BatchRequest(std::unique_ptr<MappedBatch> batch) : batch_(std::move(batch)) {}

 protected:
  magma::Status Process(MsdIntelDevice* device) override {
    return device->ProcessBatch(std::move(batch_));
  }

 private:
  std::unique_ptr<MappedBatch> batch_;
};

class MsdIntelDevice::DestroyContextRequest : public DeviceRequest {
 public:
  DestroyContextRequest(std::shared_ptr<MsdIntelContext> client_context)
      : client_context_(std::move(client_context)) {}

 protected:
  magma::Status Process(MsdIntelDevice* device) override {
    return device->ProcessDestroyContext(std::move(client_context_));
  }

 private:
  std::shared_ptr<MsdIntelContext> client_context_;
};

class MsdIntelDevice::InterruptRequest : public DeviceRequest {
 public:
  InterruptRequest(uint64_t interrupt_time_ns, uint32_t render_interrupt_status,
                   uint32_t video_interrupt_status)
      : interrupt_time_ns_(interrupt_time_ns),
        render_interrupt_status_(render_interrupt_status),
        video_interrupt_status_(video_interrupt_status) {}

 protected:
  magma::Status Process(MsdIntelDevice* device) override {
    return device->ProcessInterrupts(interrupt_time_ns_, render_interrupt_status_,
                                     video_interrupt_status_);
  }
  uint64_t interrupt_time_ns_;
  uint32_t render_interrupt_status_;
  uint32_t video_interrupt_status_;
};

class MsdIntelDevice::DumpRequest : public DeviceRequest {
 public:
  DumpRequest() {}

 protected:
  magma::Status Process(MsdIntelDevice* device) override {
    return device->ProcessDumpStatusToLog();
  }
};

class MsdIntelDevice::TimestampRequest : public DeviceRequest {
 public:
  TimestampRequest(std::shared_ptr<magma::PlatformBuffer> buffer) : buffer_(std::move(buffer)) {}

 protected:
  magma::Status Process(MsdIntelDevice* device) override {
    return device->ProcessTimestampRequest(std::move(buffer_));
  }

  std::shared_ptr<magma::PlatformBuffer> buffer_;
};

class MsdIntelDevice::Topology : public magma_intel_gen_topology {
 public:
  std::vector<uint8_t> mask_data;
};

//////////////////////////////////////////////////////////////////////////////////////////////////

std::unique_ptr<MsdIntelDevice> MsdIntelDevice::Create(void* device_handle,
                                                       bool start_device_thread) {
  std::unique_ptr<MsdIntelDevice> device(new MsdIntelDevice());

  if (!device->Init(device_handle))
    return DRETP(nullptr, "Failed to initialize MsdIntelDevice");

  if (start_device_thread) {
    if (!device->StartDeviceThread())
      return DRETP(nullptr, "Failed to start device thread");
  }

  return device;
}

MsdIntelDevice::~MsdIntelDevice() { Destroy(); }

std::pair<magma_intel_gen_topology*, uint8_t*> MsdIntelDevice::GetTopology() {
  return {topology_.get(), topology_->mask_data.data()};
}

void MsdIntelDevice::Destroy() {
  DLOG("Destroy");
  CHECK_THREAD_NOT_CURRENT(device_thread_id_);

  device_thread_quit_flag_ = true;

  if (device_request_semaphore_)
    device_request_semaphore_->Signal();

  if (device_thread_.joinable()) {
    DLOG("joining device thread");
    device_thread_.join();
    DLOG("joined");
  }

  if (render_engine_cs_) {
    render_engine_cs_->Reset();
  }
  if (video_command_streamer_) {
    video_command_streamer_->Reset();
  }

  // Hardware interrupts disabled when device thread exits
  interrupt_manager_.reset();
}

std::unique_ptr<msd::Connection> MsdIntelDevice::Open(msd::msd_client_id_t client_id) {
  return std::make_unique<MsdIntelAbiConnection>(MsdIntelConnection::Create(this, client_id));
}

bool MsdIntelDevice::Init(void* device_handle) {
  if (!BaseInit(device_handle))
    return DRETF(false, "BaseInit failed");

  for (auto* engine : engine_command_streamers()) {
    InitEngine(engine);
  }

  if (DeviceId::is_gen12(device_id())) {
    if (!CacheConfig::InitCacheConfigGen12(register_io(),
                                           ForceWakeRequest(ForceWakeDomain::RENDER)))
      return DRETF(false, "failed to init cache config");
  }

  return true;
}

bool MsdIntelDevice::BaseInit(void* device_handle) {
  DASSERT(!platform_device_);

  DLOG("Init device_handle %p", device_handle);

  platform_device_ = MsdIntelPciDevice::CreateShim(device_handle);
  if (!platform_device_)
    return DRETF(false, "failed to create pci device");

  uint16_t pci_dev_id;
  if (!platform_device_->ReadPciConfig16(2, &pci_dev_id))
    return DRETF(false, "ReadPciConfig16 failed");

  uint16_t revision;
  if (!platform_device_->ReadPciConfig16(8, &revision))
    return DRETF(false, "ReadPciConfig16 failed");

  revision_ = revision & 0xFF;

  device_id_ = pci_dev_id;
  DLOG("device_id 0x%x revision 0x%x", device_id_, revision);

  if (!DeviceId::is_gen9(device_id_) && !DeviceId::is_gen12(device_id_)) {
    MAGMA_LOG(WARNING, "Unrecognized graphics PCI device id 0x%x", device_id_);
    return false;
  }

  std::unique_ptr<magma::PlatformMmio> mmio(
      platform_device_->CpuMapPciMmio(0, magma::PlatformMmio::CACHE_POLICY_UNCACHED_DEVICE));
  if (!mmio)
    return DRETF(false, "failed to map pci bar 0");

  register_io_ = std::make_unique<MsdIntelRegisterIo>(this, std::move(mmio), device_id_);

  forcewake_ = std::make_unique<ForceWake>(register_io_.get(), device_id_);

  topology_ = std::make_unique<Topology>();

  bus_mapper_ = magma::PlatformBusMapper::Create(platform_device_->GetBusTransactionInitiator());
  if (!bus_mapper_)
    return DRETF(false, "failed to create bus mapper");

  HardwarePreinit();

  interrupt_manager_ = InterruptManager::CreateShim(this);
  if (!interrupt_manager_)
    return DRETF(false, "failed to create interrupt manager");

  gtt_ = std::shared_ptr<Gtt>(Gtt::CreateShim(this));

  // Arbitrary
  constexpr uint32_t kFirstSequenceNumber = 0x1000;
  sequencer_ = std::unique_ptr<Sequencer>(new Sequencer(kFirstSequenceNumber));

  CreateEngineCommandStreamers();

  global_context_ = std::shared_ptr<MsdIntelContext>(new MsdIntelContext(gtt_));

  indirect_context_batch_ = render_engine_cs_->CreateIndirectContextBatch(gtt_);

  // Creates the context backing store.
  // Global context used to execute the render init batch.
  if (!InitContextForEngine(global_context_.get(), render_engine_cs_.get()))
    return DRETF(false, "Failed to init global context for RCS");

  device_request_semaphore_ = magma::PlatformSemaphore::Create();

  CheckEngines();

  return true;
}

std::shared_ptr<ForceWakeDomain> MsdIntelDevice::ForceWakeRequest(ForceWakeDomain domain) {
  bool result = forcewake_->Request(register_io(), domain);
  DASSERT(result);

  return register_io()->GetForceWakeToken(domain);
}

void MsdIntelDevice::ForceWakeRelease(ForceWakeDomain domain) {
  // Ensure no tokens are held.
  DASSERT(register_io()->forcewake_token_count(domain) == 0);

  bool result = forcewake_->Release(register_io(), domain);
  DASSERT(result);
}

bool MsdIntelDevice::HardwarePreinit() {
  DASSERT(register_io());

  forcewake_->Reset(register_io(), ForceWakeDomain::RENDER);

  if (DeviceId::is_gen12(device_id_)) {
    forcewake_->Reset(register_io(), ForceWakeDomain::GEN12_VDBOX0);
  } else if (DeviceId::is_gen9(device_id_)) {
    forcewake_->Reset(register_io(), ForceWakeDomain::GEN9_MEDIA);
  }

  auto forcewake = ForceWakeRequest(ForceWakeDomain::RENDER);

  if (DeviceId::is_gen12(device_id_)) {
    // Power gate everything, assume missing engines will be ignored.
    // On gen9 there are issues around engine reset, so leave power gating disabled for now.
    registers::PowerGateEnable::GetAddr()
        .FromValue(registers::PowerGateEnable::kPowerGateAll)
        .WriteTo(register_io());
  }

  // Clear faults
  registers::AllEngineFault::GetAddr(device_id_).FromValue(0).set_valid(0).WriteTo(register_io());

  DASSERT(topology_);

  if (DeviceId::is_gen12(device_id())) {
    QuerySliceInfoGen12(forcewake, &subslice_total_, &eu_total_, topology_.get());

    PerProcessGtt::InitPrivatePatGen12(register_io_.get(), forcewake);
  } else {
    QuerySliceInfoGen9(forcewake, &subslice_total_, &eu_total_, topology_.get());

    PerProcessGtt::InitPrivatePat(register_io_.get(), forcewake);
  }

  timestamp_freq_ = GetTimestampFrequency(forcewake);

  return true;
}

uint64_t MsdIntelDevice::GetTimestampFrequency(std::shared_ptr<ForceWakeDomain> domain) {
  auto ctc_mode = registers::CtcMode::GetAddr().ReadFrom(register_io());
  DASSERT(ctc_mode.source_is_crystal_clock());

  auto rpm_config = registers::RenderPerformanceConfig::GetAddr().ReadFrom(register_io());

  return DeviceId::is_gen12(device_id()) ? rpm_config.get_timestamp_frequency_gen12()
                                         : ctc_mode.get_timestamp_frequency_gen9();
}

bool MsdIntelDevice::CreateEngineCommandStreamers() {
  constexpr bool kCreateVideoEngineCs = true;

  DASSERT(gtt_);

  {
    auto mapping =
        AddressSpace::MapBufferGpu(gtt_, MsdIntelBuffer::Create(magma::page_size(), "RCS HWSP"));
    if (!mapping)
      return DRETF(false, "MapBufferGpu failed for RCS HWSP");

    render_engine_cs_ = std::make_unique<RenderEngineCommandStreamer>(this, std::move(mapping));
  }

  if (kCreateVideoEngineCs) {
    auto mapping =
        AddressSpace::MapBufferGpu(gtt_, MsdIntelBuffer::Create(magma::page_size(), "VCS HWSP"));
    if (!mapping)
      return DRETF(false, "MapBufferGpu failed for VCS HWSP");

    video_command_streamer_ = std::make_unique<VideoCommandStreamer>(this, std::move(mapping));
  }

  return true;
}

void MsdIntelDevice::EnableInterrupts(EngineCommandStreamer* engine, bool enable) {
  auto mask_op =
      enable ? registers::InterruptRegisterBase::UNMASK : registers::InterruptRegisterBase::MASK;

  constexpr auto kBits = registers::InterruptRegisterBase::kUserBit |
                         registers::InterruptRegisterBase::kContextSwitchBit;

  if (DeviceId::is_gen12(device_id())) {
    switch (engine->id()) {
      case RENDER_COMMAND_STREAMER:
        registers::GtInterruptMask0Gen12::mask_render(register_io(), mask_op, kBits);
        registers::GtInterruptEnable0Gen12::enable_render(register_io(), enable, kBits);
        break;

      case VIDEO_COMMAND_STREAMER:
        registers::GtInterruptMask2Gen12::mask_vcs0(register_io(), mask_op, kBits);
        registers::GtInterruptEnable1Gen12::enable_video_decode(register_io(), enable, kBits);
        break;
    }
  } else {
    DASSERT(DeviceId::is_gen9(device_id()));

    switch (engine->id()) {
      case RENDER_COMMAND_STREAMER:
        registers::GtInterruptMask0::mask_render(register_io(), mask_op, kBits);
        registers::GtInterruptEnable0::enable_render(register_io(), enable, kBits);
        break;

      case VIDEO_COMMAND_STREAMER:
        registers::GtInterruptMask1::mask_vcs0(register_io(), mask_op, kBits);
        registers::GtInterruptEnable1::enable_vcs0(register_io(), enable, kBits);
        break;
    }
  }
}

void MsdIntelDevice::InitEngine(EngineCommandStreamer* engine) {
  CHECK_THREAD_IS_CURRENT(device_thread_id_);

  engine->InitHardware();

  // Top level (not engine specific) workarounds.
  switch (engine->id()) {
    case RENDER_COMMAND_STREAMER:
      if (DeviceId::is_gen9(device_id())) {
        // WaEnableGapsTsvCreditFix
        registers::ArbiterControl::workaround(register_io());
      }
      break;
    case VIDEO_COMMAND_STREAMER:
      break;
  }
}

bool MsdIntelDevice::RenderInitBatch() {
  if (DeviceId::is_gen12(device_id_))
    return true;

  auto init_batch = render_engine_cs_->CreateRenderInitBatch(device_id_);
  if (!init_batch)
    return DRETF(false, "failed to create render init batch");

  if (!render_engine_cs_->RenderInit(global_context_, std::move(init_batch), gtt_))
    return DRETF(false, "render_engine_cs failed RenderInit");

  return true;
}

bool MsdIntelDevice::EngineReset(EngineCommandStreamer* engine) {
  MAGMA_LOG(WARNING, "resetting engine %s", engine->Name());

  engine->ResetCurrentContext();

  InitEngine(engine);

  registers::AllEngineFault::GetAddr(device_id_)
      .FromValue(0)
      .set_valid(0)
      .WriteTo(register_io_.get());

  if (engine->id() == RENDER_COMMAND_STREAMER) {
    if (!RenderInitBatch())
      return false;
  }

  return true;
}

bool MsdIntelDevice::StartDeviceThread() {
  DASSERT(!device_thread_.joinable());
  device_thread_ = std::thread([this] { this->DeviceThreadLoop(); });

  // Don't start interrupt processing until the device thread is running.
  uint32_t mask = DeviceId::is_gen9(device_id())
                      ? registers::MasterInterruptControl::kRenderInterruptsPendingBitMask |
                            registers::MasterInterruptControl::kVideoInterruptsPendingBitMask
                      : 0;

  return interrupt_manager_->RegisterCallback(InterruptCallback, this, mask);
}

void MsdIntelDevice::InterruptCallback(void* data, uint32_t master_interrupt_control,
                                       uint64_t interrupt_timestamp) {
  DASSERT(data);
  auto device = reinterpret_cast<MsdIntelDevice*>(data);

  device->last_interrupt_callback_timestamp_ = magma::get_monotonic_ns();
  device->last_interrupt_timestamp_ = interrupt_timestamp;

  // We're running in the core driver's interrupt thread.
  MsdIntelRegisterIo* register_io = device->register_io_for_interrupt();

  uint64_t now = get_current_time_ns();
  uint32_t render_interrupt_status = 0;
  uint32_t video_interrupt_status = 0;

  if (DeviceId::is_gen12(device->device_id())) {
    if (auto status = registers::GtInterruptStatus0Gen12::Get(register_io); status.reg_value()) {
      if (status.rcs0()) {
        // Select the engine for the identity register.
        registers::GtInterruptSelector0Gen12::write_rcs0(register_io);

        auto identity = registers::GtInterruptIdentityGen12::GetBank0(register_io);

        if (identity.SpinUntilValid(register_io, std::chrono::microseconds(100))) {
          DASSERT(identity.data_valid());
          DASSERT(identity.instance_id() == 0);
          DASSERT(identity.class_id() == 0);

          render_interrupt_status = identity.interrupt();

          identity.Clear(register_io);
        } else {
          MAGMA_LOG(WARNING, "RCS interrupt identity invalid");
        }
      }

      status.WriteTo(register_io);  // clear
    }

    if (auto status = registers::GtInterruptStatus1Gen12::Get(register_io); status.reg_value()) {
      if (status.vcs0()) {
        // Select the engine for the identity register.
        registers::GtInterruptSelector1Gen12::write_vcs0(register_io);

        auto identity = registers::GtInterruptIdentityGen12::GetBank1(register_io);

        if (identity.SpinUntilValid(register_io, std::chrono::microseconds(100))) {
          DASSERT(identity.data_valid());
          DASSERT(identity.instance_id() == 0);
          DASSERT(identity.class_id() == 1);

          video_interrupt_status = identity.interrupt();

          identity.Clear(register_io);
        } else {
          MAGMA_LOG(WARNING, "VCS0 interrupt identity invalid");
        }
      }

      status.WriteTo(register_io);  // clear
    }
  } else {
    DASSERT(DeviceId::is_gen9(device->device_id()));

    if (master_interrupt_control &
        registers::MasterInterruptControl::kRenderInterruptsPendingBitMask) {
      render_interrupt_status = registers::GtInterruptIdentity0::read(register_io);
      DLOG("gt IIR0 0x%08x", render_interrupt_status);

      if (render_interrupt_status & registers::InterruptRegisterBase::kUserBit) {
        registers::GtInterruptIdentity0::clear(register_io,
                                               registers::InterruptRegisterBase::kUserBit);
      }
      if (render_interrupt_status & registers::InterruptRegisterBase::kContextSwitchBit) {
        registers::GtInterruptIdentity0::clear(register_io,
                                               registers::InterruptRegisterBase::kContextSwitchBit);
      }
    }

    if (master_interrupt_control &
        registers::MasterInterruptControl::kVideoInterruptsPendingBitMask) {
      video_interrupt_status = registers::GtInterruptIdentity1::read(register_io);
      DLOG("gt IIR1 0x%08x", video_interrupt_status);

      if (video_interrupt_status & registers::InterruptRegisterBase::kUserBit) {
        registers::GtInterruptIdentity1::clear(register_io,
                                               registers::InterruptRegisterBase::kUserBit);
      }
      if (video_interrupt_status & registers::InterruptRegisterBase::kContextSwitchBit) {
        registers::GtInterruptIdentity1::clear(register_io,
                                               registers::InterruptRegisterBase::kContextSwitchBit);
      }
    }
  }

  if (render_interrupt_status || video_interrupt_status) {
    device->EnqueueDeviceRequest(
        std::make_unique<InterruptRequest>(now, render_interrupt_status, video_interrupt_status));
  }
}

void MsdIntelDevice::DumpStatusToLog() { EnqueueDeviceRequest(std::make_unique<DumpRequest>()); }

void MsdIntelDevice::SubmitBatch(std::unique_ptr<MappedBatch> batch) {
  DLOG("SubmitBatch");
  CHECK_THREAD_NOT_CURRENT(device_thread_id_);

  EnqueueDeviceRequest(std::make_unique<BatchRequest>(std::move(batch)));
}

void MsdIntelDevice::DestroyContext(std::shared_ptr<MsdIntelContext> client_context) {
  DLOG("DestroyContext");
  CHECK_THREAD_NOT_CURRENT(device_thread_id_);

  EnqueueDeviceRequest(std::make_unique<DestroyContextRequest>(std::move(client_context)));
}

//////////////////////////////////////////////////////////////////////////////////////////////////

void MsdIntelDevice::EnqueueDeviceRequest(std::unique_ptr<DeviceRequest> request,
                                          bool enqueue_front) {
  TRACE_DURATION("magma", "EnqueueDeviceRequest");
  std::unique_lock<std::mutex> lock(device_request_mutex_);
  if (enqueue_front) {
    device_request_list_.emplace_front(std::move(request));
  } else {
    device_request_list_.emplace_back(std::move(request));
  }
  device_request_semaphore_->Signal();
}

#ifdef HANGCHECK_TIMEOUT_MS
constexpr uint32_t kHangcheckTimeoutMs = HANGCHECK_TIMEOUT_MS;
#else
constexpr uint32_t kHangcheckTimeoutMs = 1000;
#endif

constexpr uint32_t kForceWakeReleaseTimeoutMs = 100;

constexpr uint32_t kFreqPollPeriodMs = 16;

// Returns the minimum timeout across all timer sources.
std::chrono::milliseconds MsdIntelDevice::GetDeviceRequestTimeoutMs(
    const std::vector<EngineCommandStreamer*>& engines) {
  auto timeout = std::chrono::steady_clock::duration::max();

  auto now = std::chrono::steady_clock::now();

  // Get the minimum hangcheck timeout for active engines.
  for (auto& engine : engines) {
    timeout = std::min(timeout, engine->progress()->GetHangcheckTimeout(kHangcheckTimeoutMs, now));
  }

  // Account for any forcewake release timeouts.
  for (auto& engine : engines) {
    auto maybe_domain = engine->get_forcewake_domain();

    if (maybe_domain && kForceWakeReleaseTimeoutMs) {
      timeout = std::min(timeout, register_io()->GetForceWakeReleaseTimeout(
                                      *maybe_domain, kForceWakeReleaseTimeoutMs, now));
    }
  }

  std::chrono::milliseconds timeout_ms =
      std::max(std::chrono::milliseconds(0), std::chrono::ceil<std::chrono::milliseconds>(timeout));

  if (timeout != std::chrono::steady_clock::duration::max()) {
    timeout_ms = std::min(timeout_ms, std::chrono::milliseconds(kFreqPollPeriodMs));
  }

  return timeout_ms;
}

void MsdIntelDevice::DeviceRequestTimedOut(const std::vector<EngineCommandStreamer*>& engines) {
  // Sometimes the interrupt thread has been observed to be massively delayed in
  // responding to a pending interrupt.  In that case the InterruptRequest can be posted
  // after the timeout has expired, so always check if there is work to do before jumping
  // to conclusions.
  {
    std::unique_lock<std::mutex> lock(device_request_mutex_);
    if (!device_request_list_.empty())
      return;
  }

  auto now = std::chrono::steady_clock::now();

  for (auto& engine : engines) {
    if (engine->progress()->GetHangcheckTimeout(kHangcheckTimeoutMs, now) <=
        std::chrono::steady_clock::duration::zero()) {
      HangCheckTimeout(kHangcheckTimeoutMs, engine->id());
    }
  }

  for (auto& engine : engines) {
    auto maybe_domain = engine->get_forcewake_domain();

    if (maybe_domain && kForceWakeReleaseTimeoutMs) {
      if (register_io()->GetForceWakeReleaseTimeout(*maybe_domain, kForceWakeReleaseTimeoutMs,
                                                    now) <=
          std::chrono::steady_clock::duration::zero()) {
        ForceWakeRelease(*maybe_domain);
      }
    }
  }
}

void MsdIntelDevice::TraceFreq(std::chrono::steady_clock::time_point& last_freq_poll_time) {
  auto now = std::chrono::steady_clock::now();

  if (std::chrono::ceil<std::chrono::milliseconds>(now - last_freq_poll_time).count() >=
      kFreqPollPeriodMs) {
    last_freq_poll_time = now;

    if (TRACE_ENABLED()) {
      uint32_t ATTRIBUTE_UNUSED actual_mhz =
          registers::RenderPerformanceStatus::read_current_frequency_gen9(register_io_.get());
      uint32_t ATTRIBUTE_UNUSED requested_mhz =
          registers::RenderPerformanceNormalFrequencyRequest::read(register_io_.get());
      TRACE_COUNTER("magma", "gpu freq", 0, "request_mhz", requested_mhz, "actual_mhz", actual_mhz);
    }
  }
}

int MsdIntelDevice::DeviceThreadLoop() {
  magma::PlatformThreadHelper::SetCurrentThreadName("DeviceThread");

  std::unique_lock<std::mutex> lock(device_request_mutex_);
  // Manipulate device_thread_id_ while locked, here and below
  device_thread_id_ = std::make_unique<magma::PlatformThreadId>();
  lock.unlock();

  CHECK_THREAD_IS_CURRENT(device_thread_id_);

  DLOG("DeviceThreadLoop starting thread 0x%lx", device_thread_id_->id());

  std::vector<EngineCommandStreamer*> engines = engine_command_streamers();

  for (auto& engine : engines) {
    EnableInterrupts(engine, true);
  }

  {
    bool result = RenderInitBatch();
    DASSERT(result);
  }

  std::chrono::steady_clock::time_point last_freq_poll_time;

  while (true) {
    std::chrono::milliseconds timeout_ms = GetDeviceRequestTimeoutMs(engines);

    // When the semaphore wait returns the semaphore will be reset.
    // The reset may race with subsequent enqueue/signals on the semaphore,
    // which is fine because we process everything available in the queue
    // before returning here to wait.
    DASSERT(timeout_ms.count() >= 0);
    magma::Status status = device_request_semaphore_->Wait(timeout_ms.count());

    switch (status.get()) {
      case MAGMA_STATUS_OK:
        break;
      case MAGMA_STATUS_TIMED_OUT: {
        DeviceRequestTimedOut(engines);
        break;
      }
      default:
        MAGMA_LOG(WARNING, "device_request_semaphore_ Wait failed: %d", status.get());
        DASSERT(false);
        // TODO(https://fxbug.dev/42082881): should we trigger a restart of the driver?
        std::this_thread::sleep_for(std::chrono::seconds(5));
    }

    while (true) {
      lock.lock();
      if (!device_request_list_.size())
        break;
      auto request = std::move(device_request_list_.front());
      device_request_list_.pop_front();
      lock.unlock();
      request->ProcessAndReply(this);
    }
    lock.unlock();

    if (device_thread_quit_flag_)
      break;

    TraceFreq(last_freq_poll_time);
  }

  for (auto& engine : engines) {
    EnableInterrupts(engine, false);
  }

  DLOG("DeviceThreadLoop exit");
  lock.lock();
  device_thread_id_.reset();

  return 0;
}

void MsdIntelDevice::ProcessCompletedCommandBuffers(EngineCommandStreamerId id) {
  CHECK_THREAD_IS_CURRENT(device_thread_id_);
  TRACE_DURATION("magma", "ProcessCompletedCommandBuffers");

  switch (id) {
    case RENDER_COMMAND_STREAMER:
      render_engine_cs_->ProcessCompletedCommandBuffers(
          render_engine_cs()->hardware_status_page()->read_sequence_number());
      break;
    case VIDEO_COMMAND_STREAMER:
      video_command_streamer_->ProcessCompletedCommandBuffers(
          video_command_streamer()->hardware_status_page()->read_sequence_number());
      break;
    default:
      DASSERT(false);
  }
}

magma::Status MsdIntelDevice::ProcessInterrupts(uint64_t interrupt_time_ns,
                                                uint32_t render_interrupt_status,
                                                uint32_t video_interrupt_status) {
  TRACE_DURATION("magma", "ProcessInterrupts");

  DLOG("ProcessInterrupts render_interrupt_status 0x%08x video_interrupt_status 0x%08x",
       render_interrupt_status, video_interrupt_status);

  if (render_interrupt_status & registers::InterruptRegisterBase::kUserBit) {
    ProcessCompletedCommandBuffers(RENDER_COMMAND_STREAMER);
  }
  if (render_interrupt_status & registers::InterruptRegisterBase::kContextSwitchBit) {
    render_engine_cs_->ContextSwitched();
  }

  if (video_interrupt_status & registers::InterruptRegisterBase::kUserBit) {
    ProcessCompletedCommandBuffers(VIDEO_COMMAND_STREAMER);
  }
  if (video_interrupt_status & registers::InterruptRegisterBase::kContextSwitchBit) {
    video_command_streamer_->ContextSwitched();
  }

  auto fault_reg = registers::AllEngineFault::GetAddr(device_id_).ReadFrom(register_io_.get());

  if (fault_reg.valid()) {
    std::vector<std::string> dump;
    DumpToString(dump);
    MAGMA_LOG(WARNING, "GPU fault detected\n");
    for (auto& str : dump) {
      MAGMA_LOG(WARNING, "%s", str.c_str());
    }

    switch (fault_reg.engine()) {
      case registers::AllEngineFault::RCS:
        EngineReset(render_engine_cs());
        break;
      case registers::AllEngineFault::VCS1:
        EngineReset(video_command_streamer());
        break;
      default:
        DASSERT(false);
    }
  }

  return MAGMA_STATUS_OK;
}

magma::Status MsdIntelDevice::ProcessDumpStatusToLog() {
  std::vector<std::string> dump;
  DumpToString(dump);
  for (auto& str : dump) {
    MAGMA_LOG(INFO, "%s", str.c_str());
  }
  return MAGMA_STATUS_OK;
}

void MsdIntelDevice::HangCheckTimeout(uint64_t timeout_ms, EngineCommandStreamerId id) {
  std::vector<std::string> dump;
  DumpToString(dump);

  uint32_t interrupt_status[2];
  bool pending_interrupt;

  if (DeviceId::is_gen12(device_id())) {
    interrupt_status[0] = registers::GtInterruptStatus0Gen12::Get(register_io_.get()).reg_value();
    interrupt_status[1] = registers::GtInterruptStatus1Gen12::Get(register_io_.get()).reg_value();
    pending_interrupt = interrupt_status[0] || interrupt_status[1];
  } else {
    interrupt_status[0] = registers::MasterInterruptControl::read(register_io_.get());
    interrupt_status[1] = 0;
    pending_interrupt = interrupt_status[0] & ~registers::MasterInterruptControl::kEnableBitMask;
  }

  EngineCommandStreamer* engine;

  switch (id) {
    case RENDER_COMMAND_STREAMER:
      engine = render_engine_cs();
      break;

    case VIDEO_COMMAND_STREAMER:
      engine = video_command_streamer();
      break;
  }

  if (pending_interrupt) {
    MAGMA_LOG(WARNING,
              "%s: Hang check timeout (%lu ms) while pending interrupt; slow interrupt handler?\n"
              "last submitted sequence number 0x%x interrupt status 0x%08x (0x%08x) "
              "last_interrupt_callback_timestamp %lu last_interrupt_timestamp %lu",
              engine->Name(), timeout_ms, engine->progress()->last_submitted_sequence_number(),
              interrupt_status[0], interrupt_status[1], last_interrupt_callback_timestamp_.load(),
              last_interrupt_timestamp_.load());
    for (auto& str : dump) {
      MAGMA_LOG(WARNING, "%s", str.c_str());
    }
    return;
  }

  MAGMA_LOG(WARNING,
            "%s: Suspected GPU hang (%lu ms):\nlast submitted sequence number "
            "0x%x interrupt status 0x%08x (0x%08x) last_interrupt_callback_timestamp %lu "
            "last_interrupt_timestamp %lu",
            engine->Name(), timeout_ms, engine->progress()->last_submitted_sequence_number(),
            interrupt_status[0], interrupt_status[1], last_interrupt_callback_timestamp_.load(),
            last_interrupt_timestamp_.load());

  for (auto& str : dump) {
    MAGMA_LOG(WARNING, "%s", str.c_str());
  }

  suspected_gpu_hang_count_ += 1;

  EngineReset(engine);
}

bool MsdIntelDevice::InitContextForEngine(MsdIntelContext* context,
                                          EngineCommandStreamer* command_streamer) {
  if (!command_streamer->InitContext(context))
    return DRETF(false, "failed to initialize context");

  if (!context->Map(gtt(), command_streamer->id()))
    return DRETF(false, "failed to map context");

  // TODO(https://fxbug.dev/42161302): any workarounds or cache config for VCS?
  if (command_streamer->id() == RENDER_COMMAND_STREAMER) {
    if (DeviceId::is_gen9(device_id_)) {
      // TODO(https://fxbug.dev/42060584) - workarounds for gen12
      if (!command_streamer->InitContextWorkarounds(context))
        return DRETF(false, "failed to init workarounds");

      if (!command_streamer->InitContextCacheConfig(context))
        return DRETF(false, "failed to init cache config");

      // TODO(https://fxbug.dev/42060586) - indirect context for gen12
      command_streamer->InitIndirectContext(context, indirect_context_batch_);
    }
  }

  return true;
}

magma::Status MsdIntelDevice::ProcessBatch(std::unique_ptr<MappedBatch> batch) {
  CHECK_THREAD_IS_CURRENT(device_thread_id_);
  TRACE_DURATION("magma", "Device::ProcessBatch");

  DLOG("preparing batch for execution");

  auto context = batch->GetContext().lock();

  if (!context && batch->GetType() == MappedBatch::BatchType::MAPPING_RELEASE_BATCH) {
    // Use the global context for submitting release batches.
    reinterpret_cast<MappingReleaseBatch*>(batch.get())->SetContext(global_context_);

    context = batch->GetContext().lock();
  }

  DASSERT(context);

  if (context->killed())
    return DRET_MSG(MAGMA_STATUS_CONTEXT_KILLED, "Context killed");

  EngineCommandStreamer* command_streamer = nullptr;

  switch (batch->get_command_streamer()) {
    case RENDER_COMMAND_STREAMER:
      command_streamer = render_engine_cs();
      break;
    case VIDEO_COMMAND_STREAMER:
      command_streamer = video_command_streamer();
      break;
  }

  if (!command_streamer)
    return DRET_MSG(MAGMA_STATUS_UNIMPLEMENTED, "Engine command streamer %d not supported",
                    batch->get_command_streamer());

  if (!context->IsInitializedForEngine(command_streamer->id())) {
    if (!InitContextForEngine(context.get(), command_streamer))
      return DRET_MSG(MAGMA_STATUS_INTERNAL_ERROR, "Failed to initialize context");
  }

  uint64_t ATTRIBUTE_UNUSED buffer_id = batch->GetBatchBufferId();
  {
    TRACE_DURATION("magma", "Device::SubmitBatch");
    TRACE_FLOW_STEP("magma", "command_buffer", buffer_id);
    command_streamer->SubmitBatch(std::move(batch));
  }

  RequestMaxFreq();

  return MAGMA_STATUS_OK;
}

magma::Status MsdIntelDevice::ProcessDestroyContext(
    std::shared_ptr<MsdIntelContext> client_context) {
  DLOG("ProcessDestroyContext");
  TRACE_DURATION("magma", "ProcessDestroyContext");

  CHECK_THREAD_IS_CURRENT(device_thread_id_);
  // Just let it go out of scope

  return MAGMA_STATUS_OK;
}

bool MsdIntelDevice::WaitIdleForTest(uint32_t timeout_ms) {
  CHECK_THREAD_IS_CURRENT(device_thread_id_);

  uint32_t sequence_number = Sequencer::kInvalidSequenceNumber;

  auto start = std::chrono::high_resolution_clock::now();

  for (auto engine : engine_command_streamers()) {
    while (!engine->IsIdle()) {
      ProcessCompletedCommandBuffers(engine->id());

      auto end = std::chrono::high_resolution_clock::now();
      std::chrono::duration<double, std::milli> elapsed = end - start;

      if (engine->progress()->last_completed_sequence_number() != sequence_number) {
        sequence_number = engine->progress()->last_completed_sequence_number();
        start = end;
      } else {
        if (elapsed.count() > timeout_ms)
          return DRETF(false, "WaitIdle timeout (%u ms)", timeout_ms);

        std::this_thread::sleep_for(std::chrono::milliseconds(10));
      }
    }
  }

  return true;
}

void MsdIntelDevice::RequestMaxFreq() {
  CHECK_THREAD_IS_CURRENT(device_thread_id_);

  uint32_t mhz = registers::RenderPerformanceStateCapability::read_rp0_frequency(register_io());
  registers::RenderPerformanceNormalFrequencyRequest::write_frequency_request_gen9(register_io(),
                                                                                   mhz);
}

uint32_t MsdIntelDevice::GetCurrentFrequency() {
  CHECK_THREAD_IS_CURRENT(device_thread_id_);

  if (DeviceId::is_gen9(device_id_))
    return registers::RenderPerformanceStatus::read_current_frequency_gen9(register_io());

  DLOG("GetCurrentGraphicsFrequency not implemented");
  return 0;
}

void MsdIntelDevice::QuerySliceInfoGen12(std::shared_ptr<ForceWakeDomain> forcewake,
                                         uint32_t* subslice_total_out, uint32_t* eu_total_out,
                                         Topology* topology_out) {
  // EU mask is shared amongst all subslices
  std::bitset<registers::MirrorEuDisableGen12::kEuDisableBits> eu_disable_bits =
      registers::MirrorEuDisableGen12::read(register_io());

  // Expand each disable bit into two enable bits.
  static_assert(registers::MirrorEuDisableGen12::kEuDisableBits * 2 <= 16);
  uint16_t eu_enable_mask = 0;
  {
    std::bitset<registers::MirrorEuDisableGen12::kEuDisableBits> eu_enable_bits(
        ~eu_disable_bits.to_ulong());

    for (size_t i = 0; i < eu_enable_bits.size(); i++) {
      uint8_t enable_bit = eu_enable_bits[i];
      eu_enable_mask |= (enable_bit << (i * 2)) | (enable_bit << (i * 2 + 1));
    }
  }
  DASSERT(eu_enable_mask);

  topology_out->max_slice_count = 1;
  topology_out->max_subslice_count = registers::MirrorDssEnable::kDssPerSlice;
  topology_out->max_eu_count = registers::MirrorEuDisableGen12::kEusPerSubslice;

  {
    // Assume that the single slice is enabled.
    constexpr uint8_t kSliceMask = 1 << 0;
    topology_out->mask_data.push_back(kSliceMask);
  }

  std::vector<std::bitset<registers::MirrorDssEnable::kDssPerSlice>> dss_enable_masks =
      registers::MirrorDssEnable::read(register_io());

  uint32_t subslice_total = 0;

  {
    auto& dss_enable_mask = dss_enable_masks[0];  // subslice mask for the one enabled slice
    subslice_total += dss_enable_mask.count();

    DASSERT(dss_enable_mask.to_ulong() <= std::numeric_limits<uint8_t>::max());
    topology_out->mask_data.push_back(static_cast<uint8_t>(dss_enable_mask.to_ulong()));

    for (size_t i = 0; i < dss_enable_mask.count(); i++) {
      topology_out->mask_data.push_back(eu_enable_mask & 0xFF);
      topology_out->mask_data.push_back(eu_enable_mask >> 8);
    }
  }

  topology_out->data_byte_count = magma::to_uint32(topology_out->mask_data.size());

  if (subslice_total_out) {
    *subslice_total_out = subslice_total;
  }
  if (eu_total_out) {
    uint32_t eus_per_subslice = registers::MirrorEuDisableGen12::kEusPerSubslice -
                                2u * static_cast<uint32_t>(eu_disable_bits.count());

    *eu_total_out = subslice_total * eus_per_subslice;
  }
}

void MsdIntelDevice::QuerySliceInfoGen9(std::shared_ptr<ForceWakeDomain> forcewake,
                                        uint32_t* subslice_total_out, uint32_t* eu_total_out,
                                        Topology* topology_out) {
  uint32_t slice_enable_mask;
  uint32_t subslice_enable_mask;

  registers::Fuse2ControlDwordMirror::read(register_io_.get(), &slice_enable_mask,
                                           &subslice_enable_mask);

  DLOG("slice_enable_mask 0x%x subslice_enable_mask 0x%x", slice_enable_mask, subslice_enable_mask);

  std::bitset<registers::MirrorEuDisable::kMaxSliceCount> slice_bitset(slice_enable_mask);
  std::bitset<registers::MirrorEuDisable::kMaxSubsliceCount> subslice_bitset(subslice_enable_mask);

  *subslice_total_out = magma::to_uint32(slice_bitset.count() * subslice_bitset.count());
  *eu_total_out = 0;

  topology_out->max_slice_count = registers::MirrorEuDisable::kMaxSliceCount;
  topology_out->max_subslice_count = registers::MirrorEuDisable::kMaxSubsliceCount;
  topology_out->max_eu_count = registers::MirrorEuDisable::kEuPerSubslice;

  DASSERT(slice_enable_mask <= std::numeric_limits<uint8_t>::max());
  topology_out->mask_data.push_back(static_cast<uint8_t>(slice_enable_mask));

  for (uint8_t slice = 0; slice < registers::MirrorEuDisable::kMaxSliceCount; slice++) {
    if ((slice_enable_mask & (1 << slice)) == 0)
      continue;  // skip disabled slice

    DASSERT(subslice_enable_mask <= std::numeric_limits<uint8_t>::max());
    topology_out->mask_data.push_back(static_cast<uint8_t>(subslice_enable_mask));

    std::vector<uint32_t> eu_disable_mask;
    registers::MirrorEuDisable::read(register_io_.get(), slice, eu_disable_mask);

    for (uint32_t subslice = 0; subslice < eu_disable_mask.size(); subslice++) {
      if ((subslice_enable_mask & (1 << subslice)) == 0)
        continue;  // skip disabled subslice

      DLOG("subslice %u eu_disable_mask 0x%x", subslice, eu_disable_mask[subslice]);

      DASSERT(eu_disable_mask[subslice] <= std::numeric_limits<uint8_t>::max());
      uint8_t eu_enable_mask = ~static_cast<uint8_t>(eu_disable_mask[subslice]);
      topology_out->mask_data.push_back(eu_enable_mask);

      size_t eu_disable_count =
          std::bitset<registers::MirrorEuDisable::kEuPerSubslice>(eu_disable_mask[subslice])
              .count();
      *eu_total_out += registers::MirrorEuDisable::kEuPerSubslice - eu_disable_count;
    }
  }

  topology_out->data_byte_count = magma::to_uint32(topology_out->mask_data.size());
}

magma::Status MsdIntelDevice::QueryTimestamp(std::unique_ptr<magma::PlatformBuffer> buffer) {
  auto request = std::make_unique<TimestampRequest>(std::move(buffer));
  auto reply = request->GetReply();

  EnqueueDeviceRequest(std::move(request));

  constexpr uint32_t kWaitTimeoutMs = 1000;
  magma::Status status = reply->Wait(kWaitTimeoutMs);
  if (!status.ok())
    return DRET_MSG(status.get(), "reply wait failed");

  return MAGMA_STATUS_OK;
}

static uint64_t get_ns_monotonic(bool raw) {
  struct timespec time;
  int ret = clock_gettime(raw ? CLOCK_MONOTONIC_RAW : CLOCK_MONOTONIC, &time);
  if (ret < 0)
    return 0;
  return static_cast<uint64_t>(time.tv_sec) * 1000000000ULL + time.tv_nsec;
}

magma::Status MsdIntelDevice::ProcessTimestampRequest(
    std::shared_ptr<magma::PlatformBuffer> buffer) {
  magma_intel_gen_timestamp_query* query;
  {
    void* ptr;
    if (!buffer->MapCpu(&ptr))
      return DRET_MSG(MAGMA_STATUS_INTERNAL_ERROR, "failed to map query buffer");
    query = reinterpret_cast<magma_intel_gen_timestamp_query*>(ptr);
  }

  auto token = ForceWakeRequest(ForceWakeDomain::RENDER);

  // The monotonic raw timestamps represent the start/end of the sample interval.
  query->monotonic_raw_timestamp[0] = get_ns_monotonic(true);
  query->monotonic_timestamp = get_ns_monotonic(false);
  query->device_timestamp =
      registers::Timestamp::read(register_io_.get(), render_engine_cs()->mmio_base());
  query->monotonic_raw_timestamp[1] = get_ns_monotonic(true);

  buffer->UnmapCpu();

  return MAGMA_STATUS_OK;
}

//////////////////////////////////////////////////////////////////////////////////////////////////

magma_status_t MsdIntelDevice::Query(uint64_t id, zx::vmo* result_buffer_out,
                                     uint64_t* result_out) {
  switch (id) {
    case MAGMA_QUERY_VENDOR_ID:
      *result_out = MAGMA_VENDOR_ID_INTEL;
      break;

    case MAGMA_QUERY_DEVICE_ID:
      *result_out = device_id();
      break;

    case MAGMA_QUERY_VENDOR_VERSION:
      *result_out = MAGMA_VENDOR_VERSION_INTEL;
      break;

    case MAGMA_QUERY_IS_TOTAL_TIME_SUPPORTED:
      *result_out = 0;
      break;

    case kMagmaIntelGenQuerySubsliceAndEuTotal:
      *result_out = subslice_total();
      *result_out = (*result_out << 32) | eu_total();
      break;

    case kMagmaIntelGenQueryGttSize:
      *result_out = 1ul << 48;
      break;

    case kMagmaIntelGenQueryExtraPageCount:
      *result_out = PerProcessGtt::ExtraPageCount();
      break;

    case kMagmaIntelGenQueryTimestampFrequency:
      *result_out = timestamp_frequency();
      break;

    case kMagmaIntelGenQueryTimestamp: {
      auto buffer = magma::PlatformBuffer::Create(magma::page_size(), "timestamps");
      if (!buffer)
        return DRET_MSG(MAGMA_STATUS_INTERNAL_ERROR, "failed to create timestamp buffer");

      zx::handle handle;
      if (!buffer->duplicate_handle(&handle))
        return DRET_MSG(MAGMA_STATUS_INTERNAL_ERROR, "failed to dupe timestamp buffer");

      *result_buffer_out = zx::vmo(std::move(handle));

      return QueryTimestamp(std::move(buffer)).get();
    }

    case kMagmaIntelGenQueryTopology: {
      auto [topology, mask_data] = GetTopology();
      if (!topology)
        return DRET_MSG(MAGMA_STATUS_UNIMPLEMENTED, "topology not present");

      size_t size = sizeof(magma_intel_gen_topology) + topology->data_byte_count;
      auto buffer = magma::PlatformBuffer::Create(size, "topology");
      if (!buffer)
        return DRET_MSG(MAGMA_STATUS_INTERNAL_ERROR, "failed to create topology buffer");

      {
        void* ptr;
        if (!buffer->MapCpu(&ptr))
          return DRET_MSG(MAGMA_STATUS_INTERNAL_ERROR, "failed to map topology buffer");

        memcpy(ptr, topology, sizeof(magma_intel_gen_topology));
        memcpy(reinterpret_cast<uint8_t*>(ptr) + sizeof(magma_intel_gen_topology), mask_data,
               topology->data_byte_count);

        buffer->UnmapCpu();
      }

      zx::handle handle;
      if (!buffer->duplicate_handle(&handle))
        return DRET_MSG(MAGMA_STATUS_INTERNAL_ERROR, "failed to dupe topology buffer");

      *result_buffer_out = zx::vmo(std::move(handle));

      return MAGMA_STATUS_OK;
    }

    case kMagmaIntelGenQueryHasContextIsolation: {
      *result_out = engines_have_context_isolation();
      break;
    }

    default:
      return DRET_MSG(MAGMA_STATUS_INVALID_ARGS, "unhandled id %" PRIu64, id);
  }

  if (result_buffer_out)
    *result_buffer_out = zx::vmo();

  return MAGMA_STATUS_OK;
}

void MsdIntelDevice::CheckEngines() {
  // Most engines support context isolation, but some may not; as support
  // for more engines are added, this should be revisited.
  engines_have_context_isolation_ = true;

  for (auto& engine : engine_command_streamers()) {
    switch (engine->id()) {
      case RENDER_COMMAND_STREAMER:
      case VIDEO_COMMAND_STREAMER:
        break;
    }
  }
}

void MsdIntelDevice::DumpStatus(uint32_t dump_flags) { DumpStatusToLog(); }

magma_status_t MsdIntelDevice::GetIcdList(std::vector<msd::MsdIcdInfo>* icd_info_out) {
  const char* kSuffixes[] = {"_test", ""};
  constexpr uint32_t kMediaIcdCount = 1;
  constexpr uint32_t kTotalIcdCount = std::size(kSuffixes) + kMediaIcdCount;

  std::vector<msd::MsdIcdInfo> icd_info;
  icd_info.resize(kTotalIcdCount);

  for (uint32_t i = 0; i < std::size(kSuffixes); i++) {
    icd_info[i].component_url = fbl::StringPrintf(
        "fuchsia-pkg://fuchsia.com/libvulkan_intel_gen%s#meta/vulkan.cm", kSuffixes[i]);
    icd_info[i].support_flags = msd::ICD_SUPPORT_FLAG_VULKAN;
  }

  icd_info.swap(*icd_info_out);

  return MAGMA_STATUS_OK;
}
