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

    long ret = ioctl_ping(fd, &request);
    if (ret) {
        return ret;
    }

    return request.metadata;
}

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(GoldfishAddressSpaceSubdeviceType subdevice)
  : m_handle(create_address_space_fd())
{
    if ((subdevice != GoldfishAddressSpaceSubdeviceType::NoSubdevice) && is_opened()) {
        const long ret = set_address_space_subdevice_type(m_handle, subdevice);
        if (ret != 0 && ret != subdevice) {  // TODO: retire the 'ret != subdevice' check
            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(bool useSharedSlots)
  : m_provider(useSharedSlots
        ? GoldfishAddressSpaceSubdeviceType::SharedSlotsHostMemoryAllocator
        : GoldfishAddressSpaceSubdeviceType::HostMemoryAllocator),
    m_useSharedSlots(useSharedSlots)
{}

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;
    }

    struct goldfish_address_space_ping request;
    if (m_useSharedSlots) {
        // shared memory slots are supported
        ::memset(&request, 0, sizeof(request));
        request.version = sizeof(request);
        request.size = 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->claimShared(&m_provider, request.offset, request.size);
    } else {
        // shared memory slots are not supported
        if (!block->allocate(&m_provider, size)) {
            return -ENOMEM;
        }

        ::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_set_subdevice_type(
    address_space_handle_t handle, GoldfishAddressSpaceSubdeviceType type,
    address_space_handle_t* handle_out) {
    struct goldfish_address_space_ping request;
    request.metadata = (uint64_t)type;
    *handle_out = handle;
    return goldfish_address_space_ping(handle, &request);
}

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;
}
