/*
 * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230)
 *
 * SPDX-License-Identifier: BSD-2-Clause
 */

#include <autoconf.h>
#include <sel4test-driver/gen_config.h>
#include <assert.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>

#include <sel4/sel4.h>
#include <vka/object.h>
#include <vka/capops.h>
#include <sel4utils/util.h>
#include <sel4utils/mapping.h>

#include "../helpers.h"
#include "frame_type.h"

void touch_data(void *vaddr, char old_data, char new_data, size_t size_bits)
{
    char *data = (char *)vaddr;
    /* we test a sample of the bytes in the frame to ensure a couple of things
     1. a frame of the correct size is mapped in
     2. for larger frames that no part of the large frame shares a region with another part.
        this could happen with ARM large pages and super sections as they are comprised of
        16 entries in a paging structure, and not just a single entry in a higher level structure
     */
    for (size_t i = 0; i < 16; i++) {
        size_t offset = BIT(size_bits) / 16 * i;
        test_eq(data[offset], old_data);
        data[offset] = new_data;
        test_eq(data[offset], new_data);
    }
}

static int test_frame_exported(env_t env)
{
    /* Reserve a location that is aligned and large enough to map our
     * largest kind of frame */
    void *vaddr;
    reservation_t reserve = vspace_reserve_range_aligned(&env->vspace, VSPACE_RV_SIZE, VSPACE_RV_ALIGN_BITS,
                                                         seL4_AllRights, 1, &vaddr);
    test_assert(reserve.res);

    /* loop through frame sizes, allocate, map and touch them until we run out
     * of memory. */
    size_t mem_total = 0;
    int err;
    for (int i = 0; i < ARRAY_SIZE(frame_types); i++) {
        bool once = false;
        while (1) {
            /* Allocate the frame */
            seL4_CPtr frame = vka_alloc_frame_leaky(&env->vka, frame_types[i].size_bits);
            if (!frame) {
                break;
            }
            once = true;
            mem_total += BIT(frame_types[i].size_bits);

            uintptr_t cookie = 0;
            err = vspace_map_pages_at_vaddr(&env->vspace, &frame, &cookie, (void *)vaddr, 1, frame_types[i].size_bits, reserve);
            test_error_eq(err, seL4_NoError);

            /* Touch the memory */
            char *data = (char *)vaddr;
            touch_data(data, 0, 'U', frame_types[i].size_bits);

            err = seL4_ARCH_Page_Map(frame,
                                     env->page_directory,
                                     (seL4_Word) vaddr,
                                     seL4_AllRights,
                                     seL4_ARCH_Default_VMAttributes);
            test_error_eq(err, seL4_NoError);
            /* ensure the memory is what it was before and touch it again */
            touch_data(vaddr, 'U', 'V', frame_types[i].size_bits);

            vspace_unmap_pages(&env->vspace, (void *)vaddr, 1, frame_types[i].size_bits, VSPACE_PRESERVE);
            test_error_eq(err, seL4_NoError);
        }
        test_assert(once);
    }
    return sel4test_get_result();
}
DEFINE_TEST(FRAMEEXPORTS0001, "Test that we can access all exported frames", test_frame_exported, true)

/* Wait for a VM fault originating on the given EP the return the virtual
 * address it occurred at. Returns the sentinel 0xffffffff if the message
 * received was not a VM fault.
 */
static int handle(seL4_CPtr fault_ep, seL4_CPtr reply, seL4_Word arg3, seL4_Word arg4)
{
    seL4_MessageInfo_t info = api_recv(fault_ep, NULL, reply);
    if (seL4_MessageInfo_get_label(info) == seL4_Fault_VMFault) {
        return (int)seL4_GetMR(1);
    } else {
        return (int)0xffffffff;
    }
}

#if defined(CONFIG_ARCH_ARM)
/* XN support is only implemented for ARM currently. */

/* Function that generates a fault. If we're mapped XN we should instruction
 * fault at the start of the function. If not we should data fault on 0x42.
 */
static int fault(seL4_Word arg1, seL4_Word arg2, seL4_Word arg3, seL4_Word arg4)
{
    *(char *)0x42 = 'c';
    return 0;
}

static int test_xn(env_t env, seL4_ArchObjectType frame_type)
{
    int err;
    /* Find the size of the frame type we want to test. */
    int sz_bits = 0;
    for (unsigned int i = 0; i < ARRAY_SIZE(frame_types); i++) {
        if (frame_types[i].type == frame_type) {
            sz_bits = frame_types[i].size_bits;
            break;
        }
    }
    test_assert(sz_bits != 0);

    /* Get ourselves a frame. */
    seL4_CPtr frame_cap = vka_alloc_frame_leaky(&env->vka, sz_bits);
    test_assert(frame_cap != seL4_CapNull);

    /* Map it in */
    uintptr_t cookie = 0;
    void *dest = vspace_map_pages(&env->vspace, &frame_cap, &cookie, seL4_AllRights, 1, sz_bits, 1);
    test_assert(dest != NULL);

    /* Set up a function we're going to have another thread call. Assume that
     * the function is no more than 100 bytes long.
     */
    memcpy(dest, (void *)fault, 100);

    /* Unify the instruction and data caches so our code is seen */
    seL4_ARM_Page_Unify_Instruction(frame_cap, 0, BIT(sz_bits));

    /* First setup a fault endpoint.
     */
    seL4_CPtr fault_ep = vka_alloc_endpoint_leaky(&env->vka);
    cspacepath_t path;
    vka_cspace_make_path(&env->vka, fault_ep, &path);
    test_assert(fault_ep != seL4_CapNull);

    /* Then setup the thread that will, itself, fault. */
    helper_thread_t faulter;
    create_helper_thread(env, &faulter);
    set_helper_priority(env, &faulter, 100);
    err = api_tcb_set_space(get_helper_tcb(&faulter),
                            fault_ep,
                            env->cspace_root,
                            api_make_guard_skip_word(seL4_WordBits - env->cspace_size_bits),
                            env->page_directory, seL4_NilData);
    start_helper(env, &faulter, dest, 0, 0, 0, 0);

    /* Now a fault handler that will catch and diagnose its fault. */
    helper_thread_t handler;
    create_helper_thread(env, &handler);
    set_helper_priority(env, &handler, 100);
    start_helper(env, &handler, handle, fault_ep, get_helper_reply(&faulter), 0, 0);

    /* Wait for the fault to happen */
    void *res = (void *)(seL4_Word)wait_for_helper(&handler);

    test_assert(res == (void *)0x42);

    cleanup_helper(env, &handler);
    cleanup_helper(env, &faulter);

    /* Now let's remap the page with XN set and confirm that we can't execute
     * in it any more.
     */
    err = seL4_ARM_Page_Map(frame_cap, env->page_directory, (seL4_Word) dest, seL4_AllRights,
                            seL4_ARM_Default_VMAttributes | seL4_ARM_ExecuteNever);
    test_error_eq(err, 0);

    /* The page should still contain our code from before. */
    test_assert(!memcmp(dest, (void *)fault, 100));

    /* We need to reallocate a fault EP because the thread cleanup above
     * inadvertently destroys the EP we were using.
     */
    fault_ep = vka_alloc_endpoint_leaky(&env->vka);
    test_assert(fault_ep != seL4_CapNull);

    /* Recreate our two threads. */
    create_helper_thread(env, &faulter);
    set_helper_priority(env, &faulter, 100);
    err = api_tcb_configure(get_helper_tcb(&faulter),
                            fault_ep, seL4_CapNull,
                            get_helper_sched_context(&faulter),
                            env->cspace_root,
                            api_make_guard_skip_word(seL4_WordBits - env->cspace_size_bits),
                            env->page_directory, seL4_NilData,
                            faulter.thread.ipc_buffer_addr,
                            faulter.thread.ipc_buffer);
    start_helper(env, &faulter, dest, 0, 0, 0, 0);
    create_helper_thread(env, &handler);
    set_helper_priority(env, &handler, 100);
    start_helper(env, &handler, handle, fault_ep, get_helper_reply(&faulter), 0, 0);

    /* Wait for the fault to happen */
    res = (void *)(seL4_Word)wait_for_helper(&handler);

    /* Confirm that, this time, we faulted at the start of the XN-mapped page. */
    test_assert(res == (void *)dest);

    /* Resource tear down. */
    cleanup_helper(env, &handler);
    cleanup_helper(env, &faulter);

    return sel4test_get_result();
}

static int test_xn_small_frame(env_t env)
{
    return test_xn(env, seL4_ARM_SmallPageObject);
}
DEFINE_TEST(FRAMEXN0001, "Test that we can map a small frame XN", test_xn_small_frame, config_set(CONFIG_ARCH_ARM))

static int test_xn_large_frame(env_t env)
{
    return test_xn(env, seL4_ARM_LargePageObject);
}
DEFINE_TEST(FRAMEXN0002, "Test that we can map a large frame XN", test_xn_large_frame, config_set(CONFIG_ARCH_ARM))
#endif /* CONFIG_ARCH_ARM */

static int test_device_frame_ipcbuf(env_t env)
{
    cspacepath_t path;
    cspacepath_t frame_path;
    int error;
    error = vka_cspace_alloc_path(&env->vka, &path);
    vka_cspace_make_path(&env->vka, env->device_frame, &frame_path);
    vka_cnode_copy(&path, &frame_path, seL4_AllRights);
    test_error_eq(error, 0);

    helper_thread_t other;
    create_helper_thread(env, &other);
    /* Try and create a thread with a device frame as its IPC buffer */
    error = api_tcb_configure(get_helper_tcb(&other),
                              0, seL4_CapNull,
                              get_helper_sched_context(&other),
                              env->cspace_root,
                              api_make_guard_skip_word(seL4_WordBits - env->cspace_size_bits),
                              env->page_directory, seL4_NilData,
                              get_helper_ipc_buffer_addr(&other),
                              path.capPtr);
    test_neq(error, 0);
    cleanup_helper(env, &other);

    return sel4test_get_result();
}
DEFINE_TEST(FRAMEDIPC0001, "Test that we cannot create a thread with an IPC buffer that is a frame",
            test_device_frame_ipcbuf, !config_set(CONFIG_PLAT_SPIKE))

static int wait_func(seL4_Word ep)
{
    seL4_Send(ep, seL4_MessageInfo_new(0, 0, 0, 0));
    seL4_Send(ep, seL4_MessageInfo_new(0, 0, 0, 0));
    return 0;
}

static int test_switch_device_frame_ipcbuf(env_t env)
{
    cspacepath_t path;
    cspacepath_t frame_path;
    int error;
    seL4_CPtr ep;
    error = vka_cspace_alloc_path(&env->vka, &path);
    vka_cspace_make_path(&env->vka, env->device_frame, &frame_path);
    vka_cnode_copy(&path, &frame_path, seL4_AllRights);
    test_error_eq(error, 0);

    ep = vka_alloc_endpoint_leaky(&env->vka);
    test_assert(ep != seL4_CapNull);

    helper_thread_t other;
    create_helper_thread(env, &other);
    /* start the thread and make sure it works */
    start_helper(env, &other, (helper_fn_t)wait_func, (seL4_Word)ep, 0, 0, 0);
    seL4_Wait(ep, NULL);
    /* now switch its IPC buffer, which should fail */
    error = seL4_TCB_SetIPCBuffer(get_helper_tcb(&other), get_helper_ipc_buffer_addr(&other), path.capPtr);
    test_neq(error, 0);
    /* thread should still be working */
    seL4_Wait(ep, NULL);
    /* all done */
    wait_for_helper(&other);
    cleanup_helper(env, &other);
    return sel4test_get_result();
}
DEFINE_TEST(FRAMEDIPC0002, "Test that we cannot switch a threads IPC buffer to a device frame",
            test_switch_device_frame_ipcbuf, !config_set(CONFIG_PLAT_SPIKE))

static int touch_data_fault(seL4_Word data, seL4_Word fault_ep, seL4_Word arg3, seL4_Word arg4)
{
    *(volatile int *)data = 42;
    /* if we got here we should wake the fault handler up with an error so the test doesn't hang forever.
     * we do that by generating a different fault */
    utils_undefined_instruction();
    return sel4test_get_result();
}

static int test_unmap_on_delete(env_t env)
{
    int err;
    /* Get ourselves a frame. */
    cspacepath_t frame_path;
    seL4_CPtr frame_cap = vka_alloc_frame_leaky(&env->vka, seL4_PageBits);
    test_assert(frame_cap != seL4_CapNull);
    vka_cspace_make_path(&env->vka, frame_cap, &frame_path);

    /* create a copy of the frame cap */
    cspacepath_t frame_copy;
    err = vka_cspace_alloc_path(&env->vka, &frame_copy);
    test_error_eq(err, seL4_NoError);
    vka_cnode_copy(&frame_copy, &frame_path, seL4_AllRights);

    /* Map it in */
    uintptr_t cookie = 0;
    void *dest = vspace_map_pages(&env->vspace, &frame_copy.capPtr, &cookie, seL4_AllRights, 1, seL4_PageBits, 1);
    test_assert(dest != NULL);

    /* verify we can access it */
    *(volatile int *)dest = 0;

    /* now delete the copy of the frame we mapped in */
    vka_cnode_delete(&frame_copy);

    /* Setup a fault endpoint. */
    seL4_CPtr fault_ep = vka_alloc_endpoint_leaky(&env->vka);
    cspacepath_t path;
    vka_cspace_make_path(&env->vka, fault_ep, &path);
    test_assert(fault_ep != seL4_CapNull);

    /* Then setup the thread that will fault. */
    helper_thread_t faulter;
    create_helper_thread(env, &faulter);
    set_helper_priority(env, &faulter, 100);
    err = api_tcb_set_space(get_helper_tcb(&faulter),
                            fault_ep,
                            env->cspace_root,
                            api_make_guard_skip_word(seL4_WordBits - env->cspace_size_bits),
                            env->page_directory, seL4_NilData);
    start_helper(env, &faulter, touch_data_fault, (seL4_Word)dest, 0, 0, 0);

    /* Now a fault handler that will catch and diagnose its fault. */
    helper_thread_t handler;
    create_helper_thread(env, &handler);
    set_helper_priority(env, &handler, 100);
    start_helper(env, &handler, handle, fault_ep, get_helper_reply(&faulter), 0, 0);

    /* Wait for the fault to happen */
    void *res = (void *)(seL4_Word)wait_for_helper(&handler);

    /* check that we got a fault as expected */
    test_eq((uintptr_t)res, (uintptr_t)dest);

    cleanup_helper(env, &handler);
    cleanup_helper(env, &faulter);

    return sel4test_get_result();
}
DEFINE_TEST(FRAMEDIPC0003, "Test that deleting a frame cap unmaps the frame", test_unmap_on_delete, true)
