// 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:
  explicit MsiInterruptDispatcher(fbl::RefPtr<MsiAllocation>&& alloc,
                                  fbl::RefPtr<VmMapping>&& mapping, uint32_t base_irq_id,
                                  uint32_t msi_id, RegisterIntFn = msi_register_handler);
  fbl::RefPtr<VmMapping>& mapping() { return mapping_; }
  fbl::RefPtr<MsiAllocation>& allocation() { return alloc_; }
  static interrupt_eoi IrqHandler(void* ctx);

 private:
  // The MSI allocation block this dispatcher shares.
  fbl::RefPtr<MsiAllocation> alloc_;
  // The config space of the MSI capability controlling this MSI vector.
  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: fxbug.dev/32978) 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:
  explicit 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() + 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 MsixDispatcherImpl : public MsiInterruptDispatcher {
 public:
  explicit MsixDispatcherImpl(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 ~MsixDispatcherImpl();

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

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

#endif  // ZIRCON_KERNEL_OBJECT_INCLUDE_OBJECT_MSI_INTERRUPT_DISPATCHER_H_
