// Copyright 2017 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

#ifndef ZIRCON_KERNEL_HYPERVISOR_INCLUDE_HYPERVISOR_INTERRUPT_TRACKER_H_
#define ZIRCON_KERNEL_HYPERVISOR_INCLUDE_HYPERVISOR_INTERRUPT_TRACKER_H_

#include <lib/fit/defer.h>
#include <lib/ktrace.h>
#include <lib/zx/status.h>

#include <bitmap/raw-bitmap.h>
#include <bitmap/storage.h>
#include <hypervisor/ktrace.h>
#include <hypervisor/state_invalidator.h>
#include <kernel/auto_lock.h>
#include <kernel/event.h>

namespace hypervisor {

// InterruptBitmap relies on these precise enum values, do not modify without adjusting below.
enum class InterruptType : uint8_t {
  INACTIVE = 0,
  VIRTUAL = 1,
  PHYSICAL = 2,
};

template <uint32_t N>
class InterruptBitmap {
 public:
  InterruptBitmap() {
    zx_status_t result = bitmap_.Reset(kNumBits);
    // `bitmap_` uses static storage, so `Reset` cannot fail.
    DEBUG_ASSERT(result == ZX_OK);
  }

  InterruptType Get(uint32_t vector) const {
    if (vector >= N) {
      DEBUG_ASSERT(false);
      return InterruptType::INACTIVE;
    }
    size_t bitoff = vector * 2;
    size_t first;
    bool inactive = bitmap_.Scan(bitoff, bitoff + 2, false, &first);
    if (inactive) {
      return InterruptType::INACTIVE;
    }
    return bitoff == first ? InterruptType::VIRTUAL : InterruptType::PHYSICAL;
  }

  void Set(uint32_t vector, InterruptType type) {
    if (vector >= N) {
      DEBUG_ASSERT(false);
      return;
    }
    size_t bitoff = vector * 2;
    bitmap_.Clear(bitoff, bitoff + 2);
    if (type != InterruptType::INACTIVE) {
      auto state_bit = static_cast<size_t>(type) - 1;
      bitmap_.SetOne(bitoff + state_bit);
    }
  }

  void Clear(uint32_t min, uint32_t max) {
    if (max < min || max >= N) {
      DEBUG_ASSERT(false);
      return;
    }
    bitmap_.Clear(min * 2, max * 2);
  }

  InterruptType Scan(uint32_t* vector) {
    size_t bitoff;
#if ARCH_ARM64
    bool is_empty = bitmap_.Scan(0, kNumBits, false, &bitoff);
#elif ARCH_X86
    bool is_empty = bitmap_.ReverseScan(0, kNumBits, false, &bitoff);
#endif
    if (is_empty) {
      return InterruptType::INACTIVE;
    }
    *vector = static_cast<uint32_t>(bitoff / 2);
    if (bitoff % 2 == 0) {
      return InterruptType::VIRTUAL;
    } else {
      return InterruptType::PHYSICAL;
    }
  }

 private:
  static constexpr uint32_t kNumBits = N * 2;
  bitmap::RawBitmapGeneric<bitmap::FixedStorage<kNumBits>> bitmap_;
};

// |N| is the maximum number of interrupts to be tracked.
template <uint32_t N>
class InterruptTracker {
 public:
  // Returns whether there are pending interrupts.
  bool Pending() {
    uint32_t vector;
    Guard<SpinLock, IrqSave> lock{&lock_};
    return bitmap_.Scan(&vector) != InterruptType::INACTIVE;
  }

  // Clears all vectors in the range [min, max).
  void Clear(uint32_t min, uint32_t max) {
    Guard<SpinLock, IrqSave> lock{&lock_};
    bitmap_.Clear(min, max);
  }

  // Pops the specified vector, if it is pending.
  InterruptType TryPop(uint32_t vector) {
    Guard<SpinLock, IrqSave> lock{&lock_};
    InterruptType type = bitmap_.Get(vector);
    if (type != InterruptType::INACTIVE) {
      bitmap_.Set(vector, InterruptType::INACTIVE);
    }
    return type;
  }

  // Pops the highest priority interrupt.
  InterruptType Pop(uint32_t* vector) {
    Guard<SpinLock, IrqSave> lock{&lock_};
    InterruptType type = bitmap_.Scan(vector);
    if (type != InterruptType::INACTIVE) {
      bitmap_.Set(*vector, InterruptType::INACTIVE);
    }
    return type;
  }

  // Tracks the given interrupt.
  void Track(uint32_t vector, InterruptType type) {
    Guard<SpinLock, IrqSave> lock{&lock_};
    bitmap_.Set(vector, type);
  }

  // Tracks the given interrupt, and signals any waiters.
  void Interrupt(uint32_t vector, InterruptType type) {
    Track(vector, type);
    event_.Signal();
  }

  // Tracks the given virtual interrupt, and signals any waiters.
  void VirtualInterrupt(uint32_t vector) { Interrupt(vector, hypervisor::InterruptType::VIRTUAL); }

  // Cancels a wait for an interrupt.
  //
  // We signal `ZX_ERR_INTERNAL_INTR_RETRY`, so that if the status is propagated
  // to the syscall-layer, we will retry the syscall.
  void Cancel() { event_.Signal(ZX_ERR_INTERNAL_INTR_RETRY); }

  // Waits for an interrupt.
  zx::status<> Wait(zx_time_t deadline, StateInvalidator* invalidator = nullptr) {
    if (invalidator != nullptr) {
      invalidator->Invalidate();
    }
    ktrace_vcpu(TAG_VCPU_BLOCK, VCPU_INTERRUPT);
    auto defer = fit::defer([] { ktrace_vcpu(TAG_VCPU_UNBLOCK, VCPU_INTERRUPT); });
    do {
      zx_status_t status = event_.Wait(Deadline::no_slack(deadline));
      switch (status) {
        case ZX_OK:
          continue;
        case ZX_ERR_TIMED_OUT:
          // If the event timed out, return ZX_OK to resume the VCPU.
          return zx::ok();
        default:
          // Otherwise, return the status.
          return zx::error(status);
      }
    } while (!Pending());
    return zx::ok();
  }

 private:
  AutounsignalEvent event_;
  DECLARE_SPINLOCK(InterruptTracker) lock_;
  InterruptBitmap<N> bitmap_ TA_GUARDED(lock_);
};

}  // namespace hypervisor

#endif  // ZIRCON_KERNEL_HYPERVISOR_INCLUDE_HYPERVISOR_INTERRUPT_TRACKER_H_
