// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#pragma once

#include <ddk/io-buffer.h>
#include <fbl/intrusive_double_list.h>
#include <fbl/limits.h>
#include <fbl/unique_ptr.h>
#include <region-alloc/region-alloc.h>

namespace optee {

// OP-TEE Shared Memory Management
//
// Inter world memory is provided by the Secure OS. During driver bind, the OpteeController will
// query OP-TEE to discover the physical start address and size of the memory to be used for inter
// world communication. It can then create a SharedMemoryManager to manage that address space.
//
// The SharedMemoryManager will divide the shared address space into two pools: driver and client.
// The driver pool is for the allocation of driver messages, such as an OP-TEE message for opening
// a session. The driver messages are used entirely in-proc and do not require a VMO object for
// lifetime management. The client pool is for usage by client apps, which requires VMO objects for
// sharing between processes. As such, the client pool objects must all be page aligned. The
// benefits of splitting these different memory usages into distinct pools include preventing the
// client app allocations from starving the driver message usages and grouping similarly aligned
// objects together to reduce pool fragmentation.
//
// The SharedMemoryPool uses the region-alloc library to divide the provided address space into
// allocations for use. It provides region objects that will return to the allocator upon
// destruction. There's also a template trait class parameter that can be used to provide different
// traits for the different pools. This has the added benefit of creating distinct types for the
// driver and client pools, so we can restrict which messages can be allocated from which pool. For
// example, an open session message must be constructed from the driver pool.
//
// The SharedMemory object is essentially just a wrapper around the region object that was allocated
// by the SharedMemoryPool. The region object represents the offset and size within the memory pool
// that is allocated to this object. It is important to note that the destructor for the RegionPtr
// will recycle the region back to the RegionAllocator, eliminating the need for us to explicitly
// free it.
//
// TODO(rjascani): Add ability to create vmo object from a shared memory object that was created
// from the client pool.

class SharedMemory : public fbl::DoublyLinkedListable<fbl::unique_ptr<SharedMemory>> {
public:
    using RegionPtr = RegionAllocator::Region::UPtr;

    explicit SharedMemory(zx_vaddr_t base_vaddr, zx_paddr_t base_paddr, RegionPtr region);

    // Move only type
    SharedMemory(SharedMemory&&) = default;
    SharedMemory& operator=(SharedMemory&&) = default;

    zx_vaddr_t vaddr() const { return base_vaddr_ + region_->base; }
    zx_paddr_t paddr() const { return base_paddr_ + region_->base; }
    size_t size() const { return region_->size; }

private:
    zx_vaddr_t base_vaddr_;
    zx_paddr_t base_paddr_;
    // Upon destruction of the SharedMemory object, the RegionPtr will be recycled back to the
    // RegionAllocator by it's destructor.
    RegionPtr region_;
};

template <typename SharedMemoryPoolTraits>
class SharedMemoryPool {
public:
    explicit SharedMemoryPool(zx_vaddr_t vaddr, zx_paddr_t paddr, size_t size)
        : vaddr_(vaddr),
          paddr_(paddr),
          region_allocator_(
              RegionAllocator::RegionPool::Create(fbl::numeric_limits<size_t>::max())) {
        region_allocator_.AddRegion({.base = 0, .size = size});
    }

    zx_status_t Allocate(size_t size, fbl::unique_ptr<SharedMemory>* out_shared_memory) {
        // The RegionAllocator provides thread safety around allocations, so we currently don't
        // require any additional locking.

        // Let's try to carve off a region first.
        auto region = region_allocator_.GetRegion(size, kAlignment);
        if (!region) {
            return ZX_ERR_NO_RESOURCES;
        }

        fbl::AllocChecker ac;
        auto shared_memory = fbl::make_unique_checked<SharedMemory>(
            &ac, vaddr_, paddr_, fbl::move(region));
        if (!ac.check()) {
            return ZX_ERR_NO_MEMORY;
        }

        *out_shared_memory = fbl::move(shared_memory);
        return ZX_OK;
    }

private:
    static constexpr uint64_t kAlignment = SharedMemoryPoolTraits::kAlignment;

    const zx_vaddr_t vaddr_;
    const zx_paddr_t paddr_;
    RegionAllocator region_allocator_;
};

class SharedMemoryManager {
public:
    struct DriverPoolTraits {
        static constexpr uint64_t kAlignment = 8;
    };

    struct ClientPoolTraits {
        static constexpr uint64_t kAlignment = PAGE_SIZE;
    };

    using DriverMemoryPool = SharedMemoryPool<DriverPoolTraits>;
    using ClientMemoryPool = SharedMemoryPool<ClientPoolTraits>;

    static zx_status_t Create(zx_paddr_t shared_mem_start, size_t shared_mem_size,
                              fbl::unique_ptr<io_buffer_t> secure_world_memory,
                              fbl::unique_ptr<SharedMemoryManager>* out_manager);
    ~SharedMemoryManager();

    DriverMemoryPool* driver_pool() { return &driver_pool_; }
    ClientMemoryPool* client_pool() { return &client_pool_; }

private:
    static constexpr size_t kNumDriverSharedMemoryPages = 4;
    static constexpr size_t kDriverPoolSize = 4 * PAGE_SIZE;

    explicit SharedMemoryManager(zx_vaddr_t base_vaddr, zx_paddr_t base_paddr, size_t total_size,
                                 fbl::unique_ptr<io_buffer_t> secure_world_memory);

    fbl::unique_ptr<io_buffer_t> secure_world_memory_;
    DriverMemoryPool driver_pool_;
    ClientMemoryPool client_pool_;
};

} // namespace optee
