// Copyright 2019 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_OBJECT_INCLUDE_OBJECT_MSI_INTERRUPT_DISPATCHER_H_
#define ZIRCON_KERNEL_OBJECT_INCLUDE_OBJECT_MSI_INTERRUPT_DISPATCHER_H_

#include <sys/types.h>
#include <zircon/types.h>

#include <cstddef>

#include <dev/interrupt.h>
#include <fbl/bits.h>
#include <fbl/ref_ptr.h>
#include <object/handle.h>
#include <object/interrupt_dispatcher.h>
#include <object/msi_dispatcher.h>
#include <object/vm_object_dispatcher.h>
#include <vm/vm_address_region.h>
#include <vm/vm_aspace.h>

// Specify that we should create an MSIX backed interrupt and the vmo passed
// to zx_msi_create contains the table entries, not the device's MSI capability.
#define ZX_MSI_VALID_OPTIONS (ZX_MSI_MODE_MSI_X)

// The common interface for all MSI related interrupt handling. This encompasses MSI and MSI-X.
class MsiInterruptDispatcher : public InterruptDispatcher {
 public:
  using RegisterIntFn = void (*)(const msi_block_t*, uint, int_handler, void*);

  static zx_status_t Create(fbl::RefPtr<MsiAllocation> alloc, uint32_t msi_id,
                            const fbl::RefPtr<VmObject>& vmo, zx_off_t cap_offset, uint32_t options,
                            zx_rights_t* out_rights,
                            KernelHandle<InterruptDispatcher>* out_interrupt,
                            RegisterIntFn = msi_register_handler);
  virtual ~MsiInterruptDispatcher();
  uint32_t msi_id() const { return msi_id_; }
  constexpr uint32_t vector() const { return base_irq_id_ + msi_id_; }
  void UnregisterInterruptHandler() final;
  zx_status_t RegisterInterruptHandler();
  void DeactivateInterrupt() final {}

 protected:
  MsiInterruptDispatcher(fbl::RefPtr<MsiAllocation> alloc, fbl::RefPtr<VmMapping> mapping,
                         uint32_t base_irq_id, uint32_t msi_id,
                         RegisterIntFn = msi_register_handler);
  const fbl::RefPtr<VmMapping>& mapping() const { return mapping_; }
  const fbl::RefPtr<MsiAllocation>& allocation() const { return alloc_; }
  static void IrqHandler(void* ctx);

 private:
  // The MSI allocation block this dispatcher shares.
  const fbl::RefPtr<MsiAllocation> alloc_;
  // The config space of the MSI capability controlling this MSI vector.
  const fbl::RefPtr<VmMapping> mapping_;
  // A pointer to the function to register the msi interrupt handler. Allows
  // tests to override msi_register_handler.
  const RegisterIntFn register_int_fn_;
  // Cache the base irq id of the block so we can use it without locking.
  const uint32_t base_irq_id_ = 0;
  // The specific MSI id within the block that this dispatcher services.
  const uint32_t msi_id_ = 0;
};

// Message Signaled Interrupts --
// This derived interrupt dispatcher handles operation of Messaged Signaled
// Interrupts (MSIs) and their associated interactions with userspace drivers.
// MSIs are allocated at the platform interrupt controller in contiguous blocks
// and then assigned as a group to a given PCI device. A PCI device may support
// 1 or more interrupts, and may or may not support masking of individual
// vectors. Operation of the MSI functionality is largely controlled in the
// device's capability space via its MSI Capability Structure. This includes
// enabling MSI, configuring vectors, and masking/unmasking vectors. To reduce
// interrupt latency all masking and unmasking at interrupt time is handled by
// this dispatcher, but all configuration is (will be: https://fxbug.dev/42108122) handled by the
// userspace PCI Bus Driver. To facilitate safe interactions between the two,
// all access to MSI configuration registers are synchronized via the MSI
// allocation lock. Userspace will rarely be accessing this outside of
// initialization so the performance overhead is minimal due to a lack of
// congestion and interrupts all being handled by the bootstrap CPU.
// Since the dispatcher only needs access to the Id register and Mask Bits register
// we are fortunately able to ignore the different formats due to the 32 bit and 64
// bit mask registers lining up.
// PCI Local Bus Specification rev 3.0 figure 6-9.
const uint8_t kMsiCapabilityId = (0x5);
const uint16_t kMsi64bitSupported = (1u << 7);
const uint16_t kMsiPvmSupported = (1u << 8);
struct MsiCapability {
  uint8_t id;
  uint8_t reserved0_;  // Next pointer
  uint16_t control;
  uint64_t reserved1_;    // For 32 bit this is Address, Data, and a reserved field.
                          // For 64 bit this is Address and Address Upper.
  uint32_t mask_bits_32;  // For 64 bit this is Data and a reserved field.
  uint32_t mask_bits_64;
  uint32_t reserved2_;  // Pending Bits
} __PACKED;
static_assert(offsetof(MsiCapability, mask_bits_32) == 0x0C);
static_assert(offsetof(MsiCapability, mask_bits_64) == 0x10);
static_assert(sizeof(MsiCapability) == 24);

class MsiInterruptDispatcherImpl : public MsiInterruptDispatcher {
 public:
  MsiInterruptDispatcherImpl(fbl::RefPtr<MsiAllocation> alloc, uint32_t base_irq_id,
                             uint32_t msi_id, fbl::RefPtr<VmMapping> mapping, zx_off_t reg_offset,
                             bool has_cap_pvm, bool has_64bit, RegisterIntFn register_int_fn)
      : MsiInterruptDispatcher(ktl::move(alloc), ktl::move(mapping), base_irq_id, msi_id,
                               register_int_fn),
        has_platform_pvm_(msi_supports_masking()),
        has_cap_pvm_(has_cap_pvm),
        has_64bit_(has_64bit),
        capability_(reinterpret_cast<MsiCapability*>(this->mapping()->base_locked() + reg_offset)) {
  }
  void MaskInterrupt() final;
  void UnmaskInterrupt() final;

 private:
  // Not all interrupt controllers / configurations support masking at the
  // platform level. This is set accordingly if support is detected.
  const bool has_platform_pvm_;
  // Whether or not the given device function supports per vector masking within
  // the PCI MSI capability.
  const bool has_cap_pvm_;
  const bool has_64bit_;
  // A pointer to the MSI Mask Register for this specific device function. To
  // synchronize with other MSI interactions in the device it requires the MSI
  // allocation's lock.
  volatile MsiCapability* const capability_ TA_GUARDED(allocation()->lock());
};

// For MSI-X, the kernel only needs to interact with a given table entry for a specific vector.
// Furthermore, since each vector has its own entry and MsiInterruptDispatchers hold a reference to
// their allocation there is no need to lock any of the accesses. If the PCI bus driver wishes
// to disable MSI-X on the device function then it can do so with the function level disable
// in the capability before tearing down any interrupts.
//
// MSI-X table entries are covered in the PCI Local Bus Spec v3.0 section 6.8.2.7
struct MsixTableEntry {
  uint32_t msg_addr;
  uint32_t msg_upper_addr;
  uint32_t msg_data;
  uint32_t vector_control;
};

#define kMsixVectorControlMaskBit 0
constexpr zx_off_t MsixTableOffset(uint32_t id) { return id * sizeof(MsixTableEntry); }

class MsixInterruptDispatcherImpl : public MsiInterruptDispatcher {
 public:
  explicit MsixInterruptDispatcherImpl(fbl::RefPtr<MsiAllocation> alloc, uint32_t base_irq_id,
                                       uint32_t msi_id, fbl::RefPtr<VmMapping> mapping,
                                       zx_off_t table_offset, RegisterIntFn register_int_fn);
  virtual ~MsixInterruptDispatcherImpl();

  void MaskInterrupt() final;
  void UnmaskInterrupt() final;

 private:
  volatile MsixTableEntry* const table_entries_ = {};
};

#endif  // ZIRCON_KERNEL_OBJECT_INCLUDE_OBJECT_MSI_INTERRUPT_DISPATCHER_H_
