// Copyright 2016 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 <align.h>
#include <lib/fit/defer.h>
#include <lib/user_copy/user_ptr.h>
#include <platform.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <trace.h>
#include <zircon/errors.h>
#include <zircon/rights.h>
#include <zircon/syscalls/iommu.h>
#include <zircon/syscalls/pci.h>
#include <zircon/syscalls/smc.h>
#include <zircon/types.h>

#include <new>

#include <dev/interrupt.h>
#include <dev/iommu.h>
#include <dev/udisplay.h>
#include <fbl/inline_array.h>
#include <object/bus_transaction_initiator_dispatcher.h>
#include <object/handle.h>
#include <object/interrupt_dispatcher.h>
#include <object/interrupt_event_dispatcher.h>
#include <object/iommu_dispatcher.h>
#include <object/msi_dispatcher.h>
#include <object/msi_interrupt_dispatcher.h>
#include <object/process_dispatcher.h>
#include <object/resource.h>
#include <object/vcpu_dispatcher.h>
#include <object/virtual_interrupt_dispatcher.h>
#include <object/vm_object_dispatcher.h>
#include <vm/vm.h>
#include <vm/vm_object_paged.h>
#include <vm/vm_object_physical.h>

#if ARCH_X86
#include <platform/pc/bootloader.h>
#include <platform/pc/smbios.h>
#endif

#include <lib/syscalls/forward.h>

#include "ddk_priv.h"

#define LOCAL_TRACE 0

// TODO(fxbug.dev/91213): Remove this when zx_pc_firmware_tables() goes away.
zx_paddr_t gAcpiRsdp = 0;

// TODO(fxbug.dev/91213): Remove this when zx_pc_firmware_tables() goes away.
zx_paddr_t gSmbiosPhys = 0;

// zx_status_t zx_vmo_create_contiguous
zx_status_t sys_vmo_create_contiguous(zx_handle_t bti, size_t size, uint32_t alignment_log2,
                                      user_out_handle* out) {
  LTRACEF("size 0x%zu\n", size);

  if (size == 0) {
    return ZX_ERR_INVALID_ARGS;
  }

  if (alignment_log2 == 0) {
    alignment_log2 = PAGE_SIZE_SHIFT;
  }
  // catch obviously wrong values
  if (alignment_log2 < PAGE_SIZE_SHIFT || alignment_log2 >= (8 * sizeof(uint64_t))) {
    return ZX_ERR_INVALID_ARGS;
  }

  auto up = ProcessDispatcher::GetCurrent();
  zx_status_t status = up->EnforceBasicPolicy(ZX_POL_NEW_VMO);
  if (status != ZX_OK) {
    return status;
  }

  fbl::RefPtr<BusTransactionInitiatorDispatcher> bti_dispatcher;
  status = up->handle_table().GetDispatcherWithRights(*up, bti, ZX_RIGHT_MAP, &bti_dispatcher);
  if (status != ZX_OK) {
    return status;
  }

  auto align_log2_arg = static_cast<uint8_t>(alignment_log2);

  // create a vm object
  fbl::RefPtr<VmObjectPaged> vmo;
  status = VmObjectPaged::CreateContiguous(PMM_ALLOC_FLAG_ANY, size, align_log2_arg, &vmo);
  if (status != ZX_OK) {
    return status;
  }

  // create a Vm Object dispatcher
  KernelHandle<VmObjectDispatcher> kernel_handle;
  zx_rights_t rights;
  zx_status_t result = VmObjectDispatcher::Create(ktl::move(vmo), size,
                                                  VmObjectDispatcher::InitialMutability::kMutable,
                                                  &kernel_handle, &rights);
  if (result != ZX_OK) {
    return result;
  }

  // create a handle and attach the dispatcher to it
  return out->make(ktl::move(kernel_handle), rights);
}

// zx_status_t zx_vmo_create_physical
zx_status_t sys_vmo_create_physical(zx_handle_t hrsrc, zx_paddr_t paddr, size_t size,
                                    user_out_handle* out) {
  LTRACEF("size 0x%zu\n", size);

  auto up = ProcessDispatcher::GetCurrent();
  zx_status_t status = up->EnforceBasicPolicy(ZX_POL_NEW_VMO);
  if (status != ZX_OK) {
    return status;
  }

  // Memory should be subtracted from the PhysicalAspace allocators, so it's
  // safe to assume that if the caller has access to a resource for this specified
  // region of MMIO space then it is safe to allow the vmo to be created.
  if ((status = validate_resource_mmio(hrsrc, paddr, size)) != ZX_OK) {
    return status;
  }

  size = ROUNDUP_PAGE_SIZE(size);

  // create a vm object
  fbl::RefPtr<VmObjectPhysical> vmo;
  zx_status_t result = VmObjectPhysical::Create(paddr, size, &vmo);
  if (result != ZX_OK) {
    return result;
  }

  // create a Vm Object dispatcher
  KernelHandle<VmObjectDispatcher> kernel_handle;
  zx_rights_t rights;
  result = VmObjectDispatcher::Create(ktl::move(vmo), size,
                                      VmObjectDispatcher::InitialMutability::kMutable,
                                      &kernel_handle, &rights);
  if (result != ZX_OK) {
    return result;
  }

  // create a handle and attach the dispatcher to it
  return out->make(ktl::move(kernel_handle), rights);
}

// zx_status_t zx_framebuffer_get_info
zx_status_t sys_framebuffer_get_info(zx_handle_t handle, user_out_ptr<uint32_t> format,
                                     user_out_ptr<uint32_t> width, user_out_ptr<uint32_t> height,
                                     user_out_ptr<uint32_t> stride) {
  zx_status_t status;
  if ((status = validate_resource(handle, ZX_RSRC_KIND_ROOT)) < 0) {
    return status;
  }
#if ARCH_X86
  if (!bootloader.fb.base) {
    return ZX_ERR_INVALID_ARGS;
  }
  status = format.copy_to_user(bootloader.fb.format);
  if (status != ZX_OK) {
    return status;
  }
  status = width.copy_to_user(bootloader.fb.width);
  if (status != ZX_OK) {
    return status;
  }
  status = height.copy_to_user(bootloader.fb.height);
  if (status != ZX_OK) {
    return status;
  }
  status = stride.copy_to_user(bootloader.fb.stride);
  if (status != ZX_OK) {
    return status;
  }
  return ZX_OK;
#else
  return ZX_ERR_NOT_SUPPORTED;
#endif
}

// zx_status_t zx_framebuffer_set_range
zx_status_t sys_framebuffer_set_range(zx_handle_t hrsrc, zx_handle_t vmo_handle, uint32_t len,
                                      uint32_t format, uint32_t width, uint32_t height,
                                      uint32_t stride) {
  zx_status_t status;
  if ((status = validate_resource(hrsrc, ZX_RSRC_KIND_ROOT)) < 0) {
    return status;
  }

  if (vmo_handle == ZX_HANDLE_INVALID) {
    udisplay_clear_framebuffer_vmo();
    return ZX_OK;
  }

  auto up = ProcessDispatcher::GetCurrent();

  // lookup the dispatcher from handle
  fbl::RefPtr<VmObjectDispatcher> vmo;
  status = up->handle_table().GetDispatcher(*up, vmo_handle, &vmo);
  if (status != ZX_OK) {
    return status;
  }

  status = udisplay_set_framebuffer(vmo->vmo());
  if (status != ZX_OK) {
    return status;
  }

  display_info di;
  memset(&di, 0, sizeof(display_info));
  di.format = format;
  di.width = width;
  di.height = height;
  di.stride = stride;
  di.flags = DISPLAY_FLAG_HW_FRAMEBUFFER;
  udisplay_set_display_info(&di);

  return ZX_OK;
}

// zx_status_t zx_iommu_create
zx_status_t sys_iommu_create(zx_handle_t resource, uint32_t type, user_in_ptr<const void> desc,
                             size_t desc_size, user_out_handle* out) {
  // TODO: finer grained validation
  zx_status_t status;
  if ((status = validate_resource(resource, ZX_RSRC_KIND_ROOT)) < 0) {
    return status;
  }

  if (desc_size > ZX_IOMMU_MAX_DESC_LEN) {
    return ZX_ERR_INVALID_ARGS;
  }

  KernelHandle<IommuDispatcher> handle;
  zx_rights_t rights;

  {
    // Copy the descriptor into the kernel and try to create the dispatcher
    // using it.
    fbl::AllocChecker ac;
    ktl::unique_ptr<uint8_t[]> copied_desc(new (&ac) uint8_t[desc_size]);
    if (!ac.check()) {
      return ZX_ERR_NO_MEMORY;
    }
    if ((status = desc.reinterpret<const uint8_t>().copy_array_from_user(copied_desc.get(),
                                                                         desc_size)) != ZX_OK) {
      return status;
    }
    status = IommuDispatcher::Create(type, ktl::unique_ptr<const uint8_t[]>(copied_desc.release()),
                                     desc_size, &handle, &rights);
    if (status != ZX_OK) {
      return status;
    }
  }

  return out->make(ktl::move(handle), rights);
}

#if ARCH_X86
#include <arch/x86/descriptor.h>
#include <arch/x86/ioport.h>

// zx_status_t zx_ioports_request
zx_status_t sys_ioports_request(zx_handle_t hrsrc, uint16_t io_addr, uint32_t len) {
  zx_status_t status;
  if ((status = validate_resource_ioport(hrsrc, io_addr, len)) != ZX_OK) {
    return status;
  }

  LTRACEF("addr 0x%x len 0x%x\n", io_addr, len);

  return IoBitmap::GetCurrent()->SetIoBitmap(io_addr, len, /*enable=*/true);
}

// zx_status_t zx_ioports_release
zx_status_t sys_ioports_release(zx_handle_t hrsrc, uint16_t io_addr, uint32_t len) {
  zx_status_t status;
  if ((status = validate_resource_ioport(hrsrc, io_addr, len)) != ZX_OK) {
    return status;
  }

  LTRACEF("addr 0x%x len 0x%x\n", io_addr, len);

  return IoBitmap::GetCurrent()->SetIoBitmap(io_addr, len, /*enable=*/false);
}

#else
// zx_status_t zx_ioports_request
zx_status_t sys_ioports_request(zx_handle_t hrsrc, uint16_t io_addr, uint32_t len) {
  // doesn't make sense on non-x86
  return ZX_ERR_NOT_SUPPORTED;
}

// zx_status_t zx_ioports_release
zx_status_t sys_ioports_release(zx_handle_t hrsrc, uint16_t io_addr, uint32_t len) {
  return ZX_ERR_NOT_SUPPORTED;
}
#endif

// zx_status_t zx_msi_allocate
zx_status_t sys_msi_allocate(zx_handle_t root, uint32_t count, user_out_handle* out) {
  zx_status_t status;
  if ((status = validate_resource(root, ZX_RSRC_KIND_ROOT)) != ZX_OK) {
    return status;
  }

  fbl::RefPtr<MsiAllocation> alloc;
  if ((status = MsiAllocation::Create(count, &alloc)) != ZX_OK) {
    return status;
  }

  zx_rights_t rights;
  KernelHandle<MsiDispatcher> alloc_handle;
  if ((status = MsiDispatcher::Create(ktl::move(alloc), &alloc_handle, &rights)) != ZX_OK) {
    return status;
  }

  return out->make(ktl::move(alloc_handle), rights);
}

// zx_status_t zx_msi_create
zx_status_t sys_msi_create(zx_handle_t msi_alloc, uint32_t options, uint32_t msi_id,
                           zx_handle_t vmo, size_t vmo_offset, user_out_handle* out) {
  auto* up = ProcessDispatcher::GetCurrent();
  fbl::RefPtr<MsiDispatcher> msi_alloc_disp;

  zx_status_t status;
  if ((status = up->handle_table().GetDispatcher(*up, msi_alloc, &msi_alloc_disp)) != ZX_OK) {
    return status;
  }

  fbl::RefPtr<VmObjectDispatcher> vmo_disp;
  if ((status = up->handle_table().GetDispatcherWithRights(*up, vmo, ZX_RIGHT_MAP, &vmo_disp)) !=
      ZX_OK) {
    return status;
  }

  zx_rights_t rights;
  KernelHandle<InterruptDispatcher> msi_handle;
  if ((status = MsiInterruptDispatcher::Create(
           msi_alloc_disp->msi_allocation(), /* msi_id= */ msi_id, vmo_disp->vmo(),
           /* cap_offset= */ vmo_offset, /* options= */ options, &rights, &msi_handle)) != ZX_OK) {
    return status;
  }

  return out->make(ktl::move(msi_handle), rights);
}

// TODO(fxbug.dev/91213): Remove zx_pc_firmware_tables().
// zx_status_t zx_pc_firmware_tables
zx_status_t sys_pc_firmware_tables(zx_handle_t hrsrc, user_out_ptr<zx_paddr_t> acpi_rsdp,
                                   user_out_ptr<zx_paddr_t> smbios) {
  // TODO(fxbug.dev/30918): finer grained validation
  zx_status_t status;
  if ((status = validate_resource(hrsrc, ZX_RSRC_KIND_ROOT)) < 0) {
    return status;
  }
  if ((status = acpi_rsdp.copy_to_user(gAcpiRsdp)) != ZX_OK) {
    return status;
  }

  if ((status = smbios.copy_to_user(gSmbiosPhys)) != ZX_OK) {
    return status;
  }

  return ZX_OK;
}

// zx_status_t zx_bti_create
zx_status_t sys_bti_create(zx_handle_t iommu, uint32_t options, uint64_t bti_id,
                           user_out_handle* out) {
  auto up = ProcessDispatcher::GetCurrent();

  if (options != 0) {
    return ZX_ERR_INVALID_ARGS;
  }

  fbl::RefPtr<IommuDispatcher> iommu_dispatcher;
  // TODO(teisenbe): This should probably have a right on it.
  zx_status_t status =
      up->handle_table().GetDispatcherWithRights(*up, iommu, ZX_RIGHT_NONE, &iommu_dispatcher);
  if (status != ZX_OK) {
    return status;
  }

  KernelHandle<BusTransactionInitiatorDispatcher> handle;
  zx_rights_t rights;
  status = BusTransactionInitiatorDispatcher::Create(ktl::move(iommu_dispatcher), bti_id, &handle,
                                                     &rights);
  if (status != ZX_OK) {
    return status;
  }

  return out->make(ktl::move(handle), rights);
}

// zx_status_t zx_bti_pin
zx_status_t sys_bti_pin(zx_handle_t handle, uint32_t options, zx_handle_t vmo, uint64_t offset,
                        uint64_t size, user_out_ptr<zx_paddr_t> addrs, size_t addrs_count,
                        user_out_handle* pmt) {
  auto up = ProcessDispatcher::GetCurrent();
  fbl::RefPtr<BusTransactionInitiatorDispatcher> bti_dispatcher;
  zx_status_t status =
      up->handle_table().GetDispatcherWithRights(*up, handle, ZX_RIGHT_MAP, &bti_dispatcher);
  if (status != ZX_OK) {
    return status;
  }

  if (!IS_PAGE_ALIGNED(offset) || !IS_PAGE_ALIGNED(size)) {
    return ZX_ERR_INVALID_ARGS;
  }

  fbl::RefPtr<VmObjectDispatcher> vmo_dispatcher;
  zx_rights_t vmo_rights;
  status = up->handle_table().GetDispatcherAndRights(*up, vmo, &vmo_dispatcher, &vmo_rights);
  if (status != ZX_OK) {
    return status;
  }
  if (!(vmo_rights & ZX_RIGHT_MAP)) {
    return ZX_ERR_ACCESS_DENIED;
  }

  // Convert requested permissions and check against VMO rights
  uint32_t iommu_perms = 0;
  bool compress_results = false;
  bool contiguous = false;
  if (options & ZX_BTI_PERM_READ) {
    if (!(vmo_rights & ZX_RIGHT_READ)) {
      return ZX_ERR_ACCESS_DENIED;
    }
    iommu_perms |= IOMMU_FLAG_PERM_READ;
    options &= ~ZX_BTI_PERM_READ;
  }
  if (options & ZX_BTI_PERM_WRITE) {
    if (!(vmo_rights & ZX_RIGHT_WRITE)) {
      return ZX_ERR_ACCESS_DENIED;
    }
    iommu_perms |= IOMMU_FLAG_PERM_WRITE;
    options &= ~ZX_BTI_PERM_WRITE;
  }
  if (options & ZX_BTI_PERM_EXECUTE) {
    // Note: We check ZX_RIGHT_READ instead of ZX_RIGHT_EXECUTE
    // here because the latter applies to execute permission of
    // the host CPU, whereas ZX_BTI_PERM_EXECUTE applies to
    // transactions initiated by the bus device.
    if (!(vmo_rights & ZX_RIGHT_READ)) {
      return ZX_ERR_ACCESS_DENIED;
    }
    iommu_perms |= IOMMU_FLAG_PERM_EXECUTE;
    options &= ~ZX_BTI_PERM_EXECUTE;
  }
  if (!((options & ZX_BTI_COMPRESS) && (options & ZX_BTI_CONTIGUOUS))) {
    if (options & ZX_BTI_COMPRESS) {
      compress_results = true;
      options &= ~ZX_BTI_COMPRESS;
    }
    if (options & ZX_BTI_CONTIGUOUS && vmo_dispatcher->vmo()->is_contiguous()) {
      contiguous = true;
      options &= ~ZX_BTI_CONTIGUOUS;
    }
  }
  if (options) {
    return ZX_ERR_INVALID_ARGS;
  }

  constexpr size_t kAddrsLenLimitForStack = 4;
  fbl::AllocChecker ac;
  fbl::InlineArray<dev_vaddr_t, kAddrsLenLimitForStack> mapped_addrs(&ac, addrs_count);
  if (!ac.check()) {
    return ZX_ERR_NO_MEMORY;
  }

  KernelHandle<PinnedMemoryTokenDispatcher> new_pmt_handle;
  zx_rights_t new_pmt_rights;
  status = bti_dispatcher->Pin(vmo_dispatcher->vmo(), offset, size, iommu_perms, &new_pmt_handle,
                               &new_pmt_rights);
  if (status != ZX_OK) {
    return status;
  }

  // If anything goes wrong from here on out, we _must_ remember to unpin the
  // PMT we are holding.  Failure to do this means that the PMT will hit
  // on-zero-handles while it still has pages pinned and end up in the BTI's
  // quarantine list.  This is definitely not correct as the user never got
  // access to the PMT handle in order to unpin the data.
  //
  // Notice that we're holding a RefPtr to the dispatcher rather than a
  // reference to the |new_pmt_handle|.  Just before we return, |new_pmt_handle|
  // will be moved in order to make a user_out_handle.  |new_pmt_handle| will
  // not be valid after the move so we keep a RefPtr to the dispatcher instead.
  auto cleanup = fit::defer([disp = new_pmt_handle.dispatcher()]() { disp->Unpin(); });

  status = new_pmt_handle.dispatcher()->EncodeAddrs(compress_results, contiguous,
                                                    mapped_addrs.get(), addrs_count);
  if (status != ZX_OK) {
    return status;
  }

  static_assert(sizeof(dev_vaddr_t) == sizeof(zx_paddr_t), "mismatched types");
  if ((status = addrs.copy_array_to_user(mapped_addrs.get(), addrs_count)) != ZX_OK) {
    return status;
  }

  zx_status_t res = pmt->make(ktl::move(new_pmt_handle), new_pmt_rights);
  if (res == ZX_OK) {
    cleanup.cancel();
  }

  return res;
}

// zx_status_t zx_bti_release_quarantine
zx_status_t sys_bti_release_quarantine(zx_handle_t handle) {
  auto up = ProcessDispatcher::GetCurrent();
  fbl::RefPtr<BusTransactionInitiatorDispatcher> bti_dispatcher;

  zx_status_t status =
      up->handle_table().GetDispatcherWithRights(*up, handle, ZX_RIGHT_WRITE, &bti_dispatcher);
  if (status != ZX_OK) {
    return status;
  }

  bti_dispatcher->ReleaseQuarantine();
  return ZX_OK;
}

// Having a single-purpose syscall like this is a bit of an anti-pattern in our
// syscall API, but we feel there is benefit in this over trying to extend the
// semantics of handle closing in sys_handle_close and process death.  In
// particular, PMTs are the only objects in the system that track the lifetime
// of something external to the process model (external hardware DMA
// capabilities).
// zx_status_t zx_pmt_unpin
zx_status_t sys_pmt_unpin(zx_handle_t handle) {
  auto up = ProcessDispatcher::GetCurrent();

  HandleOwner handle_owner = up->handle_table().RemoveHandle(*up, handle);
  if (!handle_owner) {
    return ZX_ERR_BAD_HANDLE;
  }

  fbl::RefPtr<Dispatcher> dispatcher = handle_owner->dispatcher();
  auto pmt_dispatcher = DownCastDispatcher<PinnedMemoryTokenDispatcher>(&dispatcher);
  if (!pmt_dispatcher) {
    return ZX_ERR_WRONG_TYPE;
  }

  pmt_dispatcher->Unpin();

  return ZX_OK;
}

// zx_status_t zx_interrupt_create
zx_status_t sys_interrupt_create(zx_handle_t src_obj, uint32_t src_num, uint32_t options,
                                 user_out_handle* out_handle) {
  LTRACEF("options 0x%x\n", options);

  // resource not required for virtual interrupts
  if (!(options & ZX_INTERRUPT_VIRTUAL)) {
    zx_status_t status;
    if ((status = validate_resource_irq(src_obj, src_num)) != ZX_OK) {
      return status;
    }
  }

  KernelHandle<InterruptDispatcher> handle;
  zx_rights_t rights;
  zx_status_t result;
  if (options & ZX_INTERRUPT_VIRTUAL) {
    result = VirtualInterruptDispatcher::Create(&handle, &rights, options);
  } else {
    result = InterruptEventDispatcher::Create(&handle, &rights, src_num, options);
  }
  if (result != ZX_OK) {
    return result;
  }

  return out_handle->make(ktl::move(handle), rights);
}

// zx_status_t zx_interrupt_bind
zx_status_t sys_interrupt_bind(zx_handle_t handle, zx_handle_t port_handle, uint64_t key,
                               uint32_t options) {
  LTRACEF("handle %x\n", handle);
  if ((options != ZX_INTERRUPT_BIND) && (options != ZX_INTERRUPT_UNBIND)) {
    return ZX_ERR_INVALID_ARGS;
  }

  zx_status_t status;
  auto up = ProcessDispatcher::GetCurrent();
  fbl::RefPtr<InterruptDispatcher> interrupt;
  status = up->handle_table().GetDispatcherWithRights(*up, handle, ZX_RIGHT_READ, &interrupt);
  if (status != ZX_OK) {
    return status;
  }

  fbl::RefPtr<PortDispatcher> port;
  status = up->handle_table().GetDispatcherWithRights(*up, port_handle, ZX_RIGHT_WRITE, &port);
  if (status != ZX_OK) {
    return status;
  }
  if (!port->can_bind_to_interrupt()) {
    return ZX_ERR_WRONG_TYPE;
  }

  if (options == ZX_INTERRUPT_BIND) {
    return interrupt->Bind(ktl::move(port), key);
  } else {
    return interrupt->Unbind(ktl::move(port));
  }
}

// zx_status_t zx_interrupt_bind_vcpu
zx_status_t sys_interrupt_bind_vcpu(zx_handle_t handle, zx_handle_t vcpu, uint32_t options) {
  LTRACEF("handle %x\n", handle);

  auto up = ProcessDispatcher::GetCurrent();
  fbl::RefPtr<InterruptDispatcher> interrupt_dispatcher;
  zx_status_t status =
      up->handle_table().GetDispatcherWithRights(*up, handle, ZX_RIGHT_READ, &interrupt_dispatcher);
  if (status != ZX_OK) {
    return status;
  }

  fbl::RefPtr<VcpuDispatcher> vcpu_dispatcher;
  status = up->handle_table().GetDispatcherWithRights(*up, vcpu, ZX_RIGHT_WRITE, &vcpu_dispatcher);
  if (status != ZX_OK) {
    return status;
  }

  return interrupt_dispatcher->BindVcpu(ktl::move(vcpu_dispatcher));
}

// zx_status_t zx_interrupt_ack
zx_status_t sys_interrupt_ack(zx_handle_t inth) {
  LTRACEF("handle %x\n", inth);

  zx_status_t status;
  auto up = ProcessDispatcher::GetCurrent();
  fbl::RefPtr<InterruptDispatcher> interrupt;
  status = up->handle_table().GetDispatcherWithRights(*up, inth, ZX_RIGHT_WRITE, &interrupt);
  if (status != ZX_OK) {
    return status;
  }
  return interrupt->Ack();
}

// zx_status_t zx_interrupt_wait
zx_status_t sys_interrupt_wait(zx_handle_t handle, user_out_ptr<zx_time_t> out_timestamp) {
  LTRACEF("handle %x\n", handle);

  zx_status_t status;
  auto up = ProcessDispatcher::GetCurrent();
  fbl::RefPtr<InterruptDispatcher> interrupt;
  status = up->handle_table().GetDispatcherWithRights(*up, handle, ZX_RIGHT_WAIT, &interrupt);
  if (status != ZX_OK) {
    return status;
  }

  zx_time_t timestamp;
  status = interrupt->WaitForInterrupt(&timestamp);
  if (status == ZX_OK && out_timestamp) {
    status = out_timestamp.copy_to_user(timestamp);
  }

  return status;
}

// zx_status_t zx_interrupt_destroy
zx_status_t sys_interrupt_destroy(zx_handle_t handle) {
  LTRACEF("handle %x\n", handle);

  zx_status_t status;
  auto up = ProcessDispatcher::GetCurrent();
  fbl::RefPtr<InterruptDispatcher> interrupt;
  status = up->handle_table().GetDispatcher(*up, handle, &interrupt);
  if (status != ZX_OK) {
    return status;
  }

  return interrupt->Destroy();
}

// zx_status_t zx_interrupt_trigger
zx_status_t sys_interrupt_trigger(zx_handle_t handle, uint32_t options, zx_time_t timestamp) {
  LTRACEF("handle %x\n", handle);

  if (options) {
    return ZX_ERR_INVALID_ARGS;
  }

  zx_status_t status;
  auto up = ProcessDispatcher::GetCurrent();
  fbl::RefPtr<InterruptDispatcher> interrupt;
  status = up->handle_table().GetDispatcherWithRights(*up, handle, ZX_RIGHT_SIGNAL, &interrupt);
  if (status != ZX_OK) {
    return status;
  }

  return interrupt->Trigger(timestamp);
}

// zx_status_t zx_smc_call
zx_status_t sys_smc_call(zx_handle_t handle, user_in_ptr<const zx_smc_parameters_t> parameters,
                         user_out_ptr<zx_smc_result_t> out_smc_result) {
  if (!parameters || !out_smc_result) {
    return ZX_ERR_INVALID_ARGS;
  }

  zx_smc_parameters_t params;
  zx_status_t status = parameters.copy_from_user(&params);
  if (status != ZX_OK) {
    return status;
  }

  uint32_t service_call_num = ARM_SMC_GET_SERVICE_CALL_NUM_FROM_FUNC_ID(params.func_id);
  if ((status = validate_resource_smc(handle, service_call_num)) != ZX_OK) {
    return status;
  }

  zx_smc_result_t result;

  status = arch_smc_call(&params, &result);
  if (status != ZX_OK) {
    return status;
  }
  return out_smc_result.copy_to_user(result);
}
