// Copyright (C) 2019 The Android Open Source Project
// Copyright (C) 2019 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <linux/types.h>
#include <linux/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include <cstdlib>
#include <errno.h>
#include <memory>

#if PLATFORM_SDK_VERSION < 26
#include <cutils/log.h>
#else
#include <log/log.h>
#endif

#include "goldfish_address_space.h"

namespace {

struct goldfish_address_space_allocate_block {
    __u64 size;
    __u64 offset;
    __u64 phys_addr;
};

struct goldfish_address_space_claim_shared {
    __u64 offset;
    __u64 size;
};

#define GOLDFISH_ADDRESS_SPACE_IOCTL_MAGIC		'G'
#define GOLDFISH_ADDRESS_SPACE_IOCTL_OP(OP, T)		_IOWR(GOLDFISH_ADDRESS_SPACE_IOCTL_MAGIC, OP, T)
#define GOLDFISH_ADDRESS_SPACE_IOCTL_ALLOCATE_BLOCK	GOLDFISH_ADDRESS_SPACE_IOCTL_OP(10, struct goldfish_address_space_allocate_block)
#define GOLDFISH_ADDRESS_SPACE_IOCTL_DEALLOCATE_BLOCK	GOLDFISH_ADDRESS_SPACE_IOCTL_OP(11, __u64)
#define GOLDFISH_ADDRESS_SPACE_IOCTL_PING		GOLDFISH_ADDRESS_SPACE_IOCTL_OP(12, struct goldfish_address_space_ping)
#define GOLDFISH_ADDRESS_SPACE_IOCTL_CLAIM_SHARED		GOLDFISH_ADDRESS_SPACE_IOCTL_OP(13, struct goldfish_address_space_claim_shared)
#define GOLDFISH_ADDRESS_SPACE_IOCTL_UNCLAIM_SHARED		GOLDFISH_ADDRESS_SPACE_IOCTL_OP(14, __u64)

const char GOLDFISH_ADDRESS_SPACE_DEVICE_NAME[] = "/dev/goldfish_address_space";

const int HOST_MEMORY_ALLOCATOR_COMMAND_ALLOCATE_ID = 1;
const int HOST_MEMORY_ALLOCATOR_COMMAND_UNALLOCATE_ID = 2;

int create_address_space_fd()
{
    return ::open(GOLDFISH_ADDRESS_SPACE_DEVICE_NAME, O_RDWR);
}

long ioctl_allocate(int fd, struct goldfish_address_space_allocate_block *request)
{
    return ::ioctl(fd, GOLDFISH_ADDRESS_SPACE_IOCTL_ALLOCATE_BLOCK, request);
}

long ioctl_deallocate(int fd, uint64_t offset)
{
    return ::ioctl(fd, GOLDFISH_ADDRESS_SPACE_IOCTL_DEALLOCATE_BLOCK, &offset);
}

long ioctl_ping(int fd, struct goldfish_address_space_ping *request)
{
    return ::ioctl(fd, GOLDFISH_ADDRESS_SPACE_IOCTL_PING, request);
}

long set_address_space_subdevice_type(int fd, uint64_t type)
{
    struct goldfish_address_space_ping request;
    ::memset(&request, 0, sizeof(request));
    request.version = sizeof(request);
    request.metadata = type;

    return ioctl_ping(fd, &request);
}

long ioctl_claim_shared(int fd, struct goldfish_address_space_claim_shared *request)
{
    return ::ioctl(fd, GOLDFISH_ADDRESS_SPACE_IOCTL_CLAIM_SHARED, request);
}

long ioctl_unclaim_shared(int fd, uint64_t offset)
{
    return ::ioctl(fd, GOLDFISH_ADDRESS_SPACE_IOCTL_UNCLAIM_SHARED, &offset);
}

}  // namespace

GoldfishAddressSpaceBlockProvider::GoldfishAddressSpaceBlockProvider(uint64_t subdevice)
  : m_handle(create_address_space_fd())
{
    if ((subdevice != SUBDEVICE_TYPE_NO_SUBDEVICE_ID) && is_opened()) {
        const long ret = set_address_space_subdevice_type(m_handle, subdevice);
        if (ret) {
            ALOGE("%s: set_address_space_subdevice_type failed for device_type=%lu, ret=%ld",
                  __func__, static_cast<unsigned long>(subdevice), ret);
            close();
        }
    }
}

GoldfishAddressSpaceBlockProvider::~GoldfishAddressSpaceBlockProvider()
{
    if (is_opened()) {
        ::close(m_handle);
    }
}

bool GoldfishAddressSpaceBlockProvider::is_opened() const
{
    return m_handle >= 0;
}

void GoldfishAddressSpaceBlockProvider::close()
{
    if (is_opened()) {
        ::close(m_handle);
        m_handle = -1;
    }
}

address_space_handle_t GoldfishAddressSpaceBlockProvider::release()
{
    address_space_handle_t handle = m_handle;
    m_handle = -1;
    return handle;
}

void GoldfishAddressSpaceBlockProvider::closeHandle(address_space_handle_t handle)
{
    ::close(handle);
}

GoldfishAddressSpaceBlock::GoldfishAddressSpaceBlock()
    : m_handle(-1)
    , m_mmaped_ptr(NULL)
    , m_phys_addr(0)
    , m_host_addr(0)
    , m_offset(0)
    , m_size(0) {}

GoldfishAddressSpaceBlock::~GoldfishAddressSpaceBlock()
{
    destroy();
}

GoldfishAddressSpaceBlock &GoldfishAddressSpaceBlock::operator=(const GoldfishAddressSpaceBlock &rhs)
{
    m_mmaped_ptr = rhs.m_mmaped_ptr;
    m_phys_addr = rhs.m_phys_addr;
    m_host_addr = rhs.m_host_addr;
    m_offset = rhs.m_offset;
    m_size = rhs.m_size;
    m_handle = rhs.m_handle;

    return *this;
}

bool GoldfishAddressSpaceBlock::allocate(GoldfishAddressSpaceBlockProvider *provider, size_t size)
{
    ALOGD("%s: Ask for block of size 0x%llx\n", __func__,
         (unsigned long long)size);

    destroy();

    if (!provider->is_opened()) {
        return false;
    }

    struct goldfish_address_space_allocate_block request;
    ::memset(&request, 0, sizeof(request));
    request.size = size;

    long res = ioctl_allocate(provider->m_handle, &request);
    if (res) {
        return false;
    } else {
        m_phys_addr = request.phys_addr;
        m_offset = request.offset;
        m_size = request.size;
        m_handle = provider->m_handle;
        m_is_shared_mapping = false;

        ALOGD("%s: ioctl allocate returned offset 0x%llx size 0x%llx\n", __func__,
                (unsigned long long)m_offset,
                (unsigned long long)m_size);

        return true;
    }
}

bool GoldfishAddressSpaceBlock::claimShared(GoldfishAddressSpaceBlockProvider *provider, uint64_t offset, uint64_t size)
{
    ALOGD("%s: Ask to claim region [0x%llx 0x%llx]\n", __func__,
         (unsigned long long)offset,
         (unsigned long long)offset + size);

    destroy();

    if (!provider->is_opened()) {
        return false;
    }

    struct goldfish_address_space_claim_shared request;
    request.offset = offset;
    request.size = size;
    long res = ioctl_claim_shared(provider->m_handle, &request);

    if (res) {
        return false;
    }

    m_offset = offset;
    m_size = size;
    m_handle = provider->m_handle;
    m_is_shared_mapping = true;

    return true;
}

uint64_t GoldfishAddressSpaceBlock::physAddr() const
{
    return m_phys_addr;
}

uint64_t GoldfishAddressSpaceBlock::hostAddr() const
{
    return m_host_addr;
}

void *GoldfishAddressSpaceBlock::mmap(uint64_t host_addr)
{
    if (m_size == 0) {
        ALOGE("%s: called with zero size\n", __func__);
        return NULL;
    }
    if (m_mmaped_ptr) {
        ALOGE("'mmap' called for an already mmaped address block");
        ::abort();
    }

    void *result;
    const int res = memoryMap(NULL, m_size, m_handle, m_offset, &result);
    if (res) {
        ALOGE("%s: host memory map failed with size 0x%llx "
              "off 0x%llx errno %d\n",
              __func__,
              (unsigned long long)m_size,
              (unsigned long long)m_offset, res);
        return NULL;
    } else {
        m_mmaped_ptr = result;
        m_host_addr = host_addr;
        return guestPtr();
    }
}

void *GoldfishAddressSpaceBlock::guestPtr() const
{
    return reinterpret_cast<char *>(m_mmaped_ptr) + (m_host_addr & (PAGE_SIZE - 1));
}

void GoldfishAddressSpaceBlock::destroy()
{
    if (m_mmaped_ptr && m_size) {
        memoryUnmap(m_mmaped_ptr, m_size);
        m_mmaped_ptr = NULL;
    }

    if (m_size) {
        long res = -EINVAL;

        if (m_is_shared_mapping) {
            res = ioctl_unclaim_shared(m_handle, m_offset);
            if (res) {
                ALOGE("ioctl_unclaim_shared failed, res=%ld", res);
                ::abort();
            }
        } else {
            res = ioctl_deallocate(m_handle, m_offset);
            if (res) {
                ALOGE("ioctl_deallocate failed, res=%ld", res);
                ::abort();
            }
        }

        m_is_shared_mapping = false;

        m_phys_addr = 0;
        m_host_addr = 0;
        m_offset = 0;
        m_size = 0;
    }
}

void GoldfishAddressSpaceBlock::release()
{
    m_handle = -1;
    m_mmaped_ptr = NULL;
    m_phys_addr = 0;
    m_host_addr = 0;
    m_offset = 0;
    m_size = 0;
}

int GoldfishAddressSpaceBlock::memoryMap(void *addr,
                                         size_t len,
                                         address_space_handle_t fd,
                                         uint64_t off,
                                         void** dst) {
    void* ptr = ::mmap64(addr, len, PROT_WRITE, MAP_SHARED, fd, off);
    if (MAP_FAILED == ptr) {
        return errno;
    } else {
        *dst = ptr;
        return 0;
    }
}

void GoldfishAddressSpaceBlock::memoryUnmap(void *ptr, size_t size)
{
    ::munmap(ptr, size);
}

GoldfishAddressSpaceHostMemoryAllocator::GoldfishAddressSpaceHostMemoryAllocator()
  : m_provider(GoldfishAddressSpaceBlockProvider::SUBDEVICE_TYPE_HOST_MEMORY_ALLOCATOR_ID) {}

bool GoldfishAddressSpaceHostMemoryAllocator::is_opened() const { return m_provider.is_opened(); }

long GoldfishAddressSpaceHostMemoryAllocator::hostMalloc(GoldfishAddressSpaceBlock *block, size_t size)
{
    if (size == 0) {
        return -EINVAL;
    }
    if (block->size() > 0) {
        return -EINVAL;
    }
    if (!m_provider.is_opened()) {
        return -ENODEV;
    }
    if (!block->allocate(&m_provider, size)) {
        return -ENOMEM;
    }

    struct goldfish_address_space_ping request;
    ::memset(&request, 0, sizeof(request));
    request.version = sizeof(request);
    request.offset = block->offset();
    request.size = block->size();
    request.metadata = HOST_MEMORY_ALLOCATOR_COMMAND_ALLOCATE_ID;

    long ret = ioctl_ping(m_provider.m_handle, &request);
    if (ret) {
        return ret;
    }
    ret = static_cast<long>(request.metadata);
    if (ret) {
        return ret;
    }

    block->mmap(0);
    return 0;
}

void GoldfishAddressSpaceHostMemoryAllocator::hostFree(GoldfishAddressSpaceBlock *block)
{
    if (block->size() == 0) {
        return;
    }

    if (!m_provider.is_opened()) {
        ALOGE("%s: device is not available", __func__);
        ::abort();
    }

    if (block->guestPtr()) {
        struct goldfish_address_space_ping request;
        ::memset(&request, 0, sizeof(request));
        request.version = sizeof(request);
        request.offset = block->offset();
        request.metadata = HOST_MEMORY_ALLOCATOR_COMMAND_UNALLOCATE_ID;

        const long ret = ioctl_ping(m_provider.m_handle, &request);
        if (ret) {
            ALOGE("%s: ioctl_ping failed, ret=%ld", __func__, ret);
            ::abort();
        }
    }

    block->replace(NULL);
}

address_space_handle_t goldfish_address_space_open() {
    return ::open(GOLDFISH_ADDRESS_SPACE_DEVICE_NAME, O_RDWR);
}

void goldfish_address_space_close(address_space_handle_t handle) {
    ::close(handle);
}

bool goldfish_address_space_allocate(
    address_space_handle_t handle,
    size_t size, uint64_t* phys_addr, uint64_t* offset) {

    struct goldfish_address_space_allocate_block request;
    ::memset(&request, 0, sizeof(request));
    request.size = size;

    long res = ioctl_allocate(handle, &request);

    if (res) return false;

    *phys_addr = request.phys_addr;
    *offset = request.offset;
    return true;
}

bool goldfish_address_space_free(
    address_space_handle_t handle, uint64_t offset) {

    long res = ioctl_deallocate(handle, offset);

    if (res) {
        ALOGE("ioctl_deallocate failed, res=%ld", res);
        ::abort();
    }

    return true;
}

bool goldfish_address_space_claim_shared(
    address_space_handle_t handle, uint64_t offset, uint64_t size) {

    struct goldfish_address_space_claim_shared request;
    request.offset = offset;
    request.size = size;
    long res = ioctl_claim_shared(handle, &request);

    if (res) return false;

    return true;
}

bool goldfish_address_space_unclaim_shared(
        address_space_handle_t handle, uint64_t offset) {
    long res = ioctl_unclaim_shared(handle, offset);
    if (res) {
        ALOGE("ioctl_unclaim_shared failed, res=%ld", res);
        ::abort();
    }

    return true;
}

// pgoff is the offset into the page to return in the result
void* goldfish_address_space_map(
    address_space_handle_t handle,
    uint64_t offset, uint64_t size,
    uint64_t pgoff) {

    void* res = ::mmap64(0, size, PROT_WRITE, MAP_SHARED, handle, offset);

    if (res == MAP_FAILED) {
        ALOGE("%s: failed to map. errno: %d\n", __func__, errno);
        return 0;
    }

    return (void*)(((char*)res) + (uintptr_t)(pgoff & (PAGE_SIZE - 1)));
}

void goldfish_address_space_unmap(void* ptr, uint64_t size) {
    void* pagePtr = (void*)(((uintptr_t)ptr) & ~(PAGE_SIZE - 1));
    ::munmap(pagePtr, size);
}

bool goldfish_address_space_ping(
    address_space_handle_t handle,
    struct goldfish_address_space_ping* ping) {
    long res = ioctl_ping(handle, ping);

    if (res) {
        ALOGE("%s: ping failed: errno: %d\n", __func__, errno);
        return false;
    }

    return true;
}
