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

#include <object/vm_address_region_dispatcher.h>

#include <vm/vm_address_region.h>
#include <vm/vm_aspace.h>
#include <vm/vm_object.h>

#include <zircon/rights.h>

#include <fbl/alloc_checker.h>

#include <assert.h>
#include <err.h>
#include <inttypes.h>
#include <trace.h>

#define LOCAL_TRACE 0

namespace {

// Split out the syscall flags into vmar flags and mmu flags.  Note that this
// does not validate that the requested protections in *flags* are valid.  For
// that use is_valid_mapping_protection()
zx_status_t split_syscall_flags(uint32_t flags, uint32_t* vmar_flags, uint* arch_mmu_flags) {
    // Figure out arch_mmu_flags
    uint mmu_flags = 0;
    switch (flags & (ZX_VM_PERM_READ | ZX_VM_PERM_WRITE)) {
        case ZX_VM_PERM_READ:
            mmu_flags |= ARCH_MMU_FLAG_PERM_READ;
            break;
        case ZX_VM_PERM_READ | ZX_VM_PERM_WRITE:
            mmu_flags |= ARCH_MMU_FLAG_PERM_READ | ARCH_MMU_FLAG_PERM_WRITE;
            break;
    }

    if (flags & ZX_VM_PERM_EXECUTE) {
        mmu_flags |= ARCH_MMU_FLAG_PERM_EXECUTE;
    }

    // Mask out arch_mmu_flags options
    flags &= ~(ZX_VM_PERM_READ | ZX_VM_PERM_WRITE | ZX_VM_PERM_EXECUTE);

    // Figure out vmar flags
    uint32_t vmar = 0;
    if (flags & ZX_VM_COMPACT) {
        vmar |= VMAR_FLAG_COMPACT;
        flags &= ~ZX_VM_COMPACT;
    }
    if (flags & ZX_VM_SPECIFIC) {
        vmar |= VMAR_FLAG_SPECIFIC;
        flags &= ~ZX_VM_SPECIFIC;
    }
    if (flags & ZX_VM_SPECIFIC_OVERWRITE) {
        vmar |= VMAR_FLAG_SPECIFIC_OVERWRITE;
        flags &= ~ZX_VM_SPECIFIC_OVERWRITE;
    }
    if (flags & ZX_VM_CAN_MAP_SPECIFIC) {
        vmar |= VMAR_FLAG_CAN_MAP_SPECIFIC;
        flags &= ~ZX_VM_CAN_MAP_SPECIFIC;
    }
    if (flags & ZX_VM_CAN_MAP_READ) {
        vmar |= VMAR_FLAG_CAN_MAP_READ;
        flags &= ~ZX_VM_CAN_MAP_READ;
    }
    if (flags & ZX_VM_CAN_MAP_WRITE) {
        vmar |= VMAR_FLAG_CAN_MAP_WRITE;
        flags &= ~ZX_VM_CAN_MAP_WRITE;
    }
    if (flags & ZX_VM_CAN_MAP_EXECUTE) {
        vmar |= VMAR_FLAG_CAN_MAP_EXECUTE;
        flags &= ~ZX_VM_CAN_MAP_EXECUTE;
    }
    if (flags & ZX_VM_REQUIRE_NON_RESIZABLE) {
        vmar |= VMAR_FLAG_REQUIRE_NON_RESIZABLE;
        flags &= ~ZX_VM_REQUIRE_NON_RESIZABLE;
    }

    if (flags != 0)
        return ZX_ERR_INVALID_ARGS;

    *vmar_flags = vmar;
    *arch_mmu_flags |= mmu_flags;
    return ZX_OK;
}

} // namespace

zx_status_t VmAddressRegionDispatcher::Create(fbl::RefPtr<VmAddressRegion> vmar,
                                              uint base_arch_mmu_flags,
                                              fbl::RefPtr<Dispatcher>* dispatcher,
                                              zx_rights_t* rights) {

    // The initial rights should match the VMAR's creation permissions
    zx_rights_t vmar_rights = default_rights();
    uint32_t vmar_flags = vmar->flags();
    if (vmar_flags & VMAR_FLAG_CAN_MAP_READ) {
        vmar_rights |= ZX_RIGHT_READ;
    }
    if (vmar_flags & VMAR_FLAG_CAN_MAP_WRITE) {
        vmar_rights |= ZX_RIGHT_WRITE;
    }
    if (vmar_flags & VMAR_FLAG_CAN_MAP_EXECUTE) {
        vmar_rights |= ZX_RIGHT_EXECUTE;
    }

    fbl::AllocChecker ac;
    auto disp = new (&ac) VmAddressRegionDispatcher(ktl::move(vmar), base_arch_mmu_flags);
    if (!ac.check())
        return ZX_ERR_NO_MEMORY;

    *rights = vmar_rights;
    *dispatcher = fbl::AdoptRef<Dispatcher>(disp);
    return ZX_OK;
}

VmAddressRegionDispatcher::VmAddressRegionDispatcher(fbl::RefPtr<VmAddressRegion> vmar,
                                                     uint base_arch_mmu_flags)
    : vmar_(ktl::move(vmar)), base_arch_mmu_flags_(base_arch_mmu_flags) {}

VmAddressRegionDispatcher::~VmAddressRegionDispatcher() {}

zx_status_t VmAddressRegionDispatcher::Allocate(
    size_t offset, size_t size, uint32_t flags,
    fbl::RefPtr<VmAddressRegionDispatcher>* new_dispatcher,
    zx_rights_t* new_rights) {

    canary_.Assert();

    uint32_t vmar_flags;
    uint arch_mmu_flags = 0;
    zx_status_t status = split_syscall_flags(flags, &vmar_flags, &arch_mmu_flags);
    if (status != ZX_OK)
        return status;

    // Check if any MMU-related flags were requested.
    if (arch_mmu_flags != 0) {
        return ZX_ERR_INVALID_ARGS;
    }

    fbl::RefPtr<VmAddressRegion> new_vmar;
    status = vmar_->CreateSubVmar(offset, size, /* align_pow2 */ 0 , vmar_flags,
                                  "useralloc", &new_vmar);
    if (status != ZX_OK)
        return status;

    // Create the dispatcher.
    fbl::RefPtr<Dispatcher> dispatcher;
    status = VmAddressRegionDispatcher::Create(ktl::move(new_vmar),
                                               base_arch_mmu_flags_,
                                               &dispatcher, new_rights);
    if (status != ZX_OK)
        return status;

    *new_dispatcher =
        DownCastDispatcher<VmAddressRegionDispatcher>(&dispatcher);
    return ZX_OK;
}

zx_status_t VmAddressRegionDispatcher::Destroy() {
    canary_.Assert();

    return vmar_->Destroy();
}

zx_status_t VmAddressRegionDispatcher::Map(size_t vmar_offset, fbl::RefPtr<VmObject> vmo,
                                           uint64_t vmo_offset, size_t len, uint32_t flags,
                                           fbl::RefPtr<VmMapping>* out) {
    canary_.Assert();

    if (!is_valid_mapping_protection(flags))
        return ZX_ERR_INVALID_ARGS;

    // Split flags into vmar_flags and arch_mmu_flags
    uint32_t vmar_flags;
    uint arch_mmu_flags = base_arch_mmu_flags_;
    zx_status_t status = split_syscall_flags(flags, &vmar_flags, &arch_mmu_flags);
    if (status != ZX_OK)
        return status;

    if (vmar_flags & VMAR_FLAG_REQUIRE_NON_RESIZABLE) {
        vmar_flags &= ~VMAR_FLAG_REQUIRE_NON_RESIZABLE;
        if (vmo->is_resizable())
            return ZX_ERR_NOT_SUPPORTED;
    }

    fbl::RefPtr<VmMapping> result(nullptr);
    status = vmar_->CreateVmMapping(vmar_offset, len, /* align_pow2 */ 0,
                                    vmar_flags, ktl::move(vmo), vmo_offset,
                                    arch_mmu_flags, "useralloc",
                                    &result);
    if (status != ZX_OK) {
        return status;
    }

    *out = ktl::move(result);
    return ZX_OK;
}

zx_status_t VmAddressRegionDispatcher::Protect(vaddr_t base, size_t len, uint32_t flags) {
    canary_.Assert();

    if (!IS_PAGE_ALIGNED(base)) {
        return ZX_ERR_INVALID_ARGS;
    }

    if (!is_valid_mapping_protection(flags))
        return ZX_ERR_INVALID_ARGS;

    uint32_t vmar_flags;
    uint arch_mmu_flags = base_arch_mmu_flags_;
    zx_status_t status = split_syscall_flags(flags, &vmar_flags, &arch_mmu_flags);
    if (status != ZX_OK)
        return status;

    // This request does not allow any VMAR flags to be set
    if (vmar_flags)
        return ZX_ERR_INVALID_ARGS;

    return vmar_->Protect(base, len, arch_mmu_flags);
}

zx_status_t VmAddressRegionDispatcher::Unmap(vaddr_t base, size_t len) {
    canary_.Assert();

    if (!IS_PAGE_ALIGNED(base)) {
        return ZX_ERR_INVALID_ARGS;
    }

    return vmar_->Unmap(base, len);
}

bool VmAddressRegionDispatcher::is_valid_mapping_protection(uint32_t flags) {
    if (!(flags & ZX_VM_PERM_READ)) {
        // No way to express non-readable mappings that are also writeable or
        // executable.
        if (flags & (ZX_VM_PERM_WRITE | ZX_VM_PERM_EXECUTE)) {
            return false;
        }
    }
    return true;
}
