// Copyright 2018 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_BUFFER_CHAIN_H_
#define ZIRCON_KERNEL_OBJECT_INCLUDE_OBJECT_BUFFER_CHAIN_H_

#include <lib/user_copy/user_ptr.h>
#include <stdint.h>
#include <string.h>
#include <zircon/types.h>

#include <cstddef>
#include <new>

#include <fbl/algorithm.h>
#include <fbl/canary.h>
#include <fbl/intrusive_single_list.h>
#include <ktl/algorithm.h>
#include <ktl/move.h>
#include <vm/page.h>
#include <vm/physmap.h>
#include <vm/pmm.h>

// BufferChain is a list of buffers allocated from the PMM.
//
// It's designed for use with channel messages.  Pages backing a BufferChain are marked as
// VM_PAGE_STATE_IPC.
//
// The BufferChain object itself lives *inside* its first buffer.  Here's what it looks like:
//
//   +--------------------------------+     +--------------------------------+
//   | page                           |     | page                           |
//   |+------------------------------+|     |+------------------------------+|
//   || Buffer                       |+---->|| Buffer                       ||
//   || raw_data:   +---------------+||     || raw_data:    +--------------+||
//   ||             |  BufferChain  |||     ||              | message data |||
//   || reserved -> | ~~~~~~~~~~~~~ |||     || reserved = 0 |  continued   |||
//   ||             |  message data |||     ||              |              |||
//   ||             +---------------+||     ||              +--------------+||
//   |+------------------------------+|     |+------------------------------+|
//   +--------------------------------+     +--------------------------------+
//
// BufferChain does not dynamically allocate. An initial Alloc() call allocates a list of
// pages that will be used to build the BufferChain. This allocation can exceed the size
// actually used by the buffer chain and the excess buffers can be freed with a call to
// FreeUnusedBuffers(). The motivation for sometimes allocating more than needed and later
// freeing is that the number of needed buffers is sometimes initially unknown and it is
// presumed to be more efficient to do a single allocation than multiple allocations.
//
class BufferChain {
 public:
  class Buffer;
  typedef fbl::SinglyLinkedList<Buffer*> BufferList;

  constexpr static size_t kSizeOfBuffer = PAGE_SIZE;
  constexpr static size_t kSizeOfBufferFields = 16;

  // kRawDataSize is the maximum number of bytes that can fit in a single Buffer.
  //
  // However, not every Buffer in a BufferChain can store this many bytes.  The first Buffer in a
  // BufferChain is special because it also stores the chain itself.  See also kContig.
  constexpr static size_t kRawDataSize = kSizeOfBuffer - kSizeOfBufferFields;

  // Unfortunately, we don't yet know sizeof(BufferChain) so estimate and rely on static_asserts
  // further down to verify.
  constexpr static size_t kSizeOfBufferChain =
      sizeof(BufferList) + 2 * sizeof(list_node) + sizeof(size_t) + sizeof(BufferList::iterator);

  // kContig is the number of bytes guaranteed to be stored contiguously in any buffer
  constexpr static size_t kContig = kRawDataSize - kSizeOfBufferChain;

  // Copies |size| bytes from this chain starting at offset |src_offset| to |dst|.
  //
  // |src_offset| must be in the range [0, kContig).
  zx_status_t CopyOut(user_out_ptr<char> dst, size_t src_offset, size_t size) {
    DEBUG_ASSERT(src_offset < buffers_.front().size());
    size_t copy_offset = src_offset;
    size_t rem = size;
    const auto end = buffers_.end();
    for (auto iter = buffers_.begin(); rem > 0 && iter != end; ++iter) {
      const size_t copy_len = ktl::min(rem, iter->size() - copy_offset);
      const char* src = iter->data() + copy_offset;
      const zx_status_t status = dst.copy_array_to_user(src, copy_len);
      if (unlikely(status != ZX_OK)) {
        return status;
      }
      dst = dst.byte_offset(copy_len);
      rem -= copy_len;
      copy_offset = 0;
    }
    return ZX_OK;
  }

  // Creates a BufferChain with enough buffers to store |size| bytes.
  //
  // It is the caller's responsibility to free the chain with BufferChain::Free.
  //
  // Returns nullptr on error.
  static BufferChain* Alloc(size_t size) {
    size += sizeof(BufferChain);
    const size_t num_buffers = (size + kRawDataSize - 1) / kRawDataSize;

    // Allocate a list of pages.
    list_node unused_pages = LIST_INITIAL_VALUE(unused_pages);
    zx_status_t status = pmm_alloc_pages(num_buffers, 0, &unused_pages);
    if (unlikely(status != ZX_OK)) {
      return nullptr;
    }

    // We now have a list of pages.  Allocate a page for the initial Buffer and construct the
    // BufferChain within it.
    BufferChain::BufferList temp;
    list_node used_pages = LIST_INITIAL_VALUE(used_pages);
    status = AddNextBuffer(&unused_pages, &used_pages, &temp, temp.end());
    if (unlikely(status != ZX_OK)) {
      return nullptr;
    }
    BufferChain* chain = new (temp.front().data()) BufferChain(&temp, &unused_pages, &used_pages);

    return chain;
  }

  // Frees |chain| and its buffers.
  static void Free(BufferChain* chain) {
    // Remove the buffers and vm_page_t's from the chain *before* destroying it.
    BufferChain::BufferList buffers(ktl::move(*chain->buffers()));
    list_node pages = LIST_INITIAL_VALUE(pages);
    list_move(&chain->used_pages_, &pages);
    list_splice_after(&chain->unused_pages_, &pages);

    chain->~BufferChain();

    while (!buffers.is_empty()) {
      BufferChain::Buffer* buf = buffers.pop_front();
      buf->Buffer::~Buffer();
    }
    pmm_free(&pages);
  }

  // Free unused pages.
  void FreeUnusedBuffers() {
    if (list_is_empty(&unused_pages_)) {
      // Avoid calling pmm_free if not needed.
      return;
    }
    list_node pages = LIST_INITIAL_VALUE(pages);
    list_move(&unused_pages_, &pages);
    pmm_free(&pages);
  }

  // Skips the specified number of bytes, so they won't be consumed by Append or AppendKernel.
  //
  // Assumes that it is called only at the beginning of the buffer chain.
  void Skip(size_t size) {
    DEBUG_ASSERT(buffer_offset_ == 0);
    DEBUG_ASSERT(size <= kContig);
    buffer_offset_ += size;
  }

  // Appends |size| bytes from |src| to this chain|.
  //
  // If there is insufficient remaining space in the buffer chain, ZX_ERR_OUT_OF_RANGE will be
  // returned.
  zx_status_t Append(user_in_ptr<const char> src, size_t size) { return AppendCommon(src, size); }

  // Same as Append except |src| can be in kernel space.
  //
  // If there is insufficient remaining space in the buffer chain, ZX_ERR_OUT_OF_RANGE will be
  // returned.
  zx_status_t AppendKernel(const char* src, size_t size);

  class Buffer final : public fbl::SinglyLinkedListable<Buffer*> {
   public:
    Buffer() = default;
    ~Buffer() = default;

    char* data() {
      canary_.Assert();
      return raw_data_ + reserved_;
    }

    size_t size() const { return sizeof(raw_data_) - reserved_; }

    void set_reserved(uint32_t reserved) {
      DEBUG_ASSERT(reserved < sizeof(raw_data_));
      reserved_ = reserved;
    }

   private:
    fbl::Canary<fbl::magic("BUFC")> canary_;
    uint32_t reserved_ = 0;
    char raw_data_[kRawDataSize];
  };
  static_assert(sizeof(BufferChain::Buffer) == BufferChain::kSizeOfBuffer, "");

  BufferList* buffers() { return &buffers_; }

 private:
  explicit BufferChain(BufferList* buffers, list_node* unused_pages, list_node* used_pages) {
    buffer_tail_ = buffers->begin();
    buffers_.swap(*buffers);

    buffer_offset_ = 0;

    list_move(unused_pages, &unused_pages_);
    list_move(used_pages, &used_pages_);

    // |this| now lives inside the first buffer.
    buffers_.front().set_reserved(sizeof(BufferChain));
  }

  ~BufferChain() {
    DEBUG_ASSERT(list_is_empty(&used_pages_));
    DEBUG_ASSERT(list_is_empty(&unused_pages_));
  }

  // Add a new Buffer to the end of |buffers| (marked by |buffer_tail|) by taking a page from the
  // |unused_pages| list. In doing so, this page will be moved to the |used_pages| list.
  static zx_status_t AddNextBuffer(list_node* unused_pages, list_node* used_pages,
                                   BufferList* buffers, BufferList::iterator buffer_tail) {
    if (list_is_empty(unused_pages)) {
      return ZX_ERR_OUT_OF_RANGE;
    }
    vm_page_t* page = list_remove_head_type(unused_pages, vm_page, queue_node);
    DEBUG_ASSERT(page != nullptr);
    DEBUG_ASSERT(page->state() == VM_PAGE_STATE_ALLOC);
    page->set_state(VM_PAGE_STATE_IPC);
    list_add_tail(used_pages, &page->queue_node);

    void* va = paddr_to_physmap(page->paddr());
    if (buffers->is_empty()) {
      buffers->push_front(new (va) BufferChain::Buffer);
    } else {
      buffers->insert_after(buffer_tail, new (va) BufferChain::Buffer);
    }
    return ZX_OK;
  }

  // |PTR_IN| is a user_in_ptr-like type.
  template <typename PTR_IN>
  zx_status_t AppendCommon(PTR_IN src, size_t size) {
    if (size == 0) {
      return ZX_OK;
    }
    if (buffer_tail_ == buffers_.end()) {
      return ZX_ERR_OUT_OF_RANGE;
    }

    size_t rem = size;
    while (true) {
      Buffer& buf = *buffer_tail_;
      const size_t copy_len = ktl::min(rem, buf.size() - buffer_offset_);
      char* dst = buf.data() + buffer_offset_;
      zx_status_t status = src.copy_array_from_user(dst, copy_len);
      if (unlikely(status != ZX_OK)) {
        buffer_tail_ = buffers_.end();
        return status;
      }

      buffer_offset_ += copy_len;
      src = src.byte_offset(copy_len);
      rem -= copy_len;

      if (rem == 0) {
        break;
      }
      status = AddNextBuffer(&unused_pages_, &used_pages_, &buffers_, buffer_tail_);
      if (status != ZX_OK) {
        buffer_tail_ = buffers_.end();
        return status;
      }
      buffer_offset_ = 0;
      buffer_tail_++;
    }
    return ZX_OK;
  }

  // Take care when adding fields as BufferChain lives inside the first buffer of buffers_.
  BufferList buffers_;

  // Iterator pointing to the last valid element in the buffer.
  BufferList::iterator buffer_tail_;

  // Position of the next byte to write in the Buffer pointed to by |buffer_tail_|.
  size_t buffer_offset_;

  // used_pages_ is a list of vm_page_t descriptors for the pages that back BufferList.
  list_node used_pages_ = LIST_INITIAL_VALUE(used_pages_);

  // unused_pages is a list of vm_page_t descriptors for pages that have been allocated but have
  // not yet been used. These pages will be migrated to used_pages_ once they are needed for
  // the BufferList.
  list_node unused_pages_ = LIST_INITIAL_VALUE(unused_pages_);

  DISALLOW_COPY_ASSIGN_AND_MOVE(BufferChain);
};
static_assert(sizeof(BufferChain) == BufferChain::kSizeOfBufferChain, "");

#endif  // ZIRCON_KERNEL_OBJECT_INCLUDE_OBJECT_BUFFER_CHAIN_H_
