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

#pragma once

#include <assert.h>
#include <fbl/array.h>
#include <fbl/canary.h>
#include <fbl/intrusive_double_list.h>
#include <fbl/macros.h>
#include <fbl/ref_counted.h>
#include <fbl/ref_ptr.h>
#include <kernel/mutex.h>
#include <lib/user_copy/user_ptr.h>
#include <list.h>
#include <stdint.h>
#include <vm/page_source.h>
#include <vm/pmm.h>
#include <vm/vm.h>
#include <vm/vm_aspace.h>
#include <vm/vm_object.h>
#include <vm/vm_page_list.h>
#include <zircon/thread_annotations.h>
#include <zircon/types.h>

// the main VM object type, holding a list of pages
class VmObjectPaged final : public VmObject {
public:
    // |options_| is a bitmask of:
    static constexpr uint32_t kResizable = (1u << 0);
    static constexpr uint32_t kContiguous = (1u << 1);

    static zx_status_t Create(uint32_t pmm_alloc_flags,
                              uint32_t options,
                              uint64_t size, fbl::RefPtr<VmObject>* vmo);

    // Gets the raw VmObjectPaged pointer, or null if the VmObject is not paged.
    static VmObjectPaged* AsVmObjectPaged(const fbl::RefPtr<VmObject>& vmo) {
        if (vmo->is_paged()) {
            return static_cast<VmObjectPaged*>(vmo.get());
        } else {
            return nullptr;
        }
    }

    // Create a VMO backed by a contiguous range of physical memory.  The
    // returned vmo has all of its pages committed, and does not allow
    // decommitting them.
    static zx_status_t CreateContiguous(uint32_t pmm_alloc_flags, uint64_t size,
                                        uint8_t alignment_log2, fbl::RefPtr<VmObject>* vmo);

    static zx_status_t CreateFromROData(const void* data, size_t size, fbl::RefPtr<VmObject>* vmo);

    static zx_status_t CreateExternal(fbl::RefPtr<PageSource> src,
                                      uint64_t size, fbl::RefPtr<VmObject>* vmo);

    zx_status_t Resize(uint64_t size) override;
    zx_status_t ResizeLocked(uint64_t size) override TA_REQ(lock_);
    uint32_t create_options() const override { return options_; }
    uint64_t size() const override
        // TODO: Figure out whether it's safe to lock here without causing
        // any deadlocks.
        TA_NO_THREAD_SAFETY_ANALYSIS { return size_; }
    bool is_paged() const override { return true; }
    bool is_contiguous() const override { return (options_ & kContiguous); }
    bool is_resizable() const override { return (options_ & kResizable); }

    size_t AllocatedPagesInRange(uint64_t offset, uint64_t len) const override;

    zx_status_t CommitRange(uint64_t offset, uint64_t len) override;
    zx_status_t DecommitRange(uint64_t offset, uint64_t len) override;

    zx_status_t Pin(uint64_t offset, uint64_t len) override;
    void Unpin(uint64_t offset, uint64_t len) override;

    zx_status_t Read(void* ptr, uint64_t offset, size_t len) override;
    zx_status_t Write(const void* ptr, uint64_t offset, size_t len) override;
    zx_status_t Lookup(uint64_t offset, uint64_t len,
                       vmo_lookup_fn_t lookup_fn, void* context) override;

    zx_status_t ReadUser(user_out_ptr<void> ptr, uint64_t offset, size_t len) override;
    zx_status_t WriteUser(user_in_ptr<const void> ptr, uint64_t offset, size_t len) override;

    zx_status_t TakePages(uint64_t offset, uint64_t len, VmPageSpliceList* pages) override;
    zx_status_t SupplyPages(uint64_t offset, uint64_t len, VmPageSpliceList* pages) override;

    void Dump(uint depth, bool verbose) override;

    zx_status_t InvalidateCache(const uint64_t offset, const uint64_t len) override;
    zx_status_t CleanCache(const uint64_t offset, const uint64_t len) override;
    zx_status_t CleanInvalidateCache(const uint64_t offset, const uint64_t len) override;
    zx_status_t SyncCache(const uint64_t offset, const uint64_t len) override;

    zx_status_t GetPageLocked(uint64_t offset, uint pf_flags, list_node* free_list,
                              PageRequest* page_request, vm_page_t**, paddr_t*) override
        // Calls a Locked method of the parent, which confuses analysis.
        TA_NO_THREAD_SAFETY_ANALYSIS;

    zx_status_t CloneCOW(bool resizable, uint64_t offset, uint64_t size, bool copy_name,
                         fbl::RefPtr<VmObject>* clone_vmo) override
        // Calls a Locked method of the child, which confuses analysis.
        TA_NO_THREAD_SAFETY_ANALYSIS;

    void RangeChangeUpdateFromParentLocked(uint64_t offset, uint64_t len) override
        // Called under the parent's lock, which confuses analysis.
        TA_NO_THREAD_SAFETY_ANALYSIS;

    uint32_t GetMappingCachePolicy() const override;
    zx_status_t SetMappingCachePolicy(const uint32_t cache_policy) override;

    void DetachSource() override {
        DEBUG_ASSERT(page_source_);
        page_source_->Detach();
    }

    // The size is clamped to allow VmPageList to use a one-past-the-end for
    // VmPageListNode offsets.
    static const uint64_t MAX_SIZE = ROUNDDOWN(UINT64_MAX, VmPageListNode::kPageFanOut * PAGE_SIZE);

private:
    // private constructor (use Create())
    VmObjectPaged(
        uint32_t options, uint32_t pmm_alloc_flags, uint64_t size,
        fbl::RefPtr<VmObject> parent, fbl::RefPtr<PageSource> page_source);

    // private destructor, only called from refptr
    ~VmObjectPaged() override;
    friend fbl::RefPtr<VmObjectPaged>;

    DISALLOW_COPY_ASSIGN_AND_MOVE(VmObjectPaged);

    // perform a cache maintenance operation against the vmo.
    enum class CacheOpType { Invalidate,
                             Clean,
                             CleanInvalidate,
                             Sync
    };
    zx_status_t CacheOp(const uint64_t offset, const uint64_t len, const CacheOpType type);

    // add a page to the object
    zx_status_t AddPage(vm_page_t* p, uint64_t offset);
    zx_status_t AddPageLocked(vm_page_t* p, uint64_t offset) TA_REQ(lock_);

    // internal page list routine
    void AddPageToArray(size_t index, vm_page_t* p);

    zx_status_t PinLocked(uint64_t offset, uint64_t len) TA_REQ(lock_);
    void UnpinLocked(uint64_t offset, uint64_t len) TA_REQ(lock_);

    fbl::RefPtr<PageSource> GetRootPageSourceLocked()
        // Walks the clone chain to get the root page source, which confuses analysis.
        TA_NO_THREAD_SAFETY_ANALYSIS;

    // internal check if any pages in a range are pinned
    bool AnyPagesPinnedLocked(uint64_t offset, size_t len) TA_REQ(lock_);

    // see AllocatedPagesInRange
    size_t AllocatedPagesInRangeLocked(uint64_t offset, uint64_t len) const TA_REQ(lock_);

    // internal read/write routine that takes a templated copy function to help share some code
    template <typename T>
    zx_status_t ReadWriteInternal(uint64_t offset, size_t len, bool write, T copyfunc);

    // set our offset within our parent
    zx_status_t SetParentOffsetLocked(uint64_t o) TA_REQ(lock_);

    // members
    const uint32_t options_;
    uint64_t size_ TA_GUARDED(lock_) = 0;
    uint64_t parent_offset_ TA_GUARDED(lock_) = 0;
    uint32_t pmm_alloc_flags_ TA_GUARDED(lock_) = PMM_ALLOC_FLAG_ANY;
    uint32_t cache_policy_ TA_GUARDED(lock_) = ARCH_MMU_FLAG_CACHED;

    // The page source, if any.
    const fbl::RefPtr<PageSource> page_source_;

    // a tree of pages
    VmPageList page_list_ TA_GUARDED(lock_);
};
