/*
 * Copyright (c) 2020 Intel Corporation
 * Copyright (c) 2023 Huawei France Technologies SASU
 *
 * SPDX-License-Identifier: Apache-2.0
 */

/* we piggyback the log level using ivshmem knob */
#define LOG_MODULE_NAME	ivshmem_doorbell_test
#define LOG_LEVEL CONFIG_IVSHMEM_LOG_LEVEL
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(LOG_MODULE_NAME);

#include <zephyr/kernel.h>
#ifdef CONFIG_USERSPACE
#include <zephyr/sys/libc-hooks.h>
#endif

#include <stdio.h>
#include <stdlib.h>

#include <zephyr/drivers/virtualization/ivshmem.h>

/*
 * result of an interrupt
 *
 * Using the ivshmem API, we will receive a signal event + two integers (the
 * interrupt itself is dealt in the internal ivshmem driver api)
 */
struct ivshmem_irq {
	/* k_poll was signaled or not */
	unsigned int signaled;
	/* vector received */
	int result;
};

struct ivshmem_ctx {
	/* dev, received via DTS */
	const struct device *dev;
	/* virtual address to access shared memory of ivshmem */
	void		*mem;
	/* size of shared memory */
	size_t		 size;
	/* my id for ivshmem protocol */
	uint32_t	 id;
	/* number of MSI vectors allocated */
	uint16_t	 vectors;
};

#ifdef CONFIG_USERSPACE
K_APPMEM_PARTITION_DEFINE(app_a_partition);
struct k_mem_domain app_a_domain;

#define APP_A_DATA	K_APP_DMEM(app_a_partition)
#define APP_A_BSS	K_APP_BMEM(app_a_partition)
#else
#define APP_A_DATA
#define APP_A_BSS
#endif

/* used for interrupt events, see wait_for_int() */
APP_A_BSS static struct ivshmem_irq irq;
APP_A_BSS static struct ivshmem_ctx ctx;

/* signal structure necessary for ivshmem API */
APP_A_BSS static struct k_poll_signal *sig;

/*
 * wait for an interrupt event.
 */
static int wait_for_int(const struct ivshmem_ctx *ctx)
{
	int ret;
	struct k_poll_event events[] = {
		K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_SIGNAL,
					 K_POLL_MODE_NOTIFY_ONLY,
					 sig),
	};

	LOG_DBG("%s: waiting interrupt from client...", __func__);
	ret = k_poll(events, ARRAY_SIZE(events), K_FOREVER);
	if (ret < 0) {
		printf("poll failed\n");
		return ret;
	}

	k_poll_signal_check(sig, &irq.signaled, &irq.result);
	LOG_DBG("%s: sig %p signaled %u result %d", __func__,
		sig, irq.signaled, irq.result);
	/* get ready for next signal */
	k_poll_signal_reset(sig);
	return 0;
}

/*
 * host <-> guest communication loop
 */
static void ivshmem_event_loop(struct ivshmem_ctx *ctx)
{
	int ret;
	char *buf;
	bool truncated;

	buf = malloc(ctx->size);
	if (buf == NULL) {
		printf("Could not allocate message buffer\n");
		return;
	}

	printf("Use write_shared_memory.sh and ivshmem-client to send a message\n");
	while (1) {
		/* host --> guest */
		ret = wait_for_int(ctx);
		if (ret < 0) {
			break;
		}

		/*
		 * QEMU may fail here if the shared memory has been downsized;
		 * the shared memory object must be protected against rogue
		 * users (check README for details)
		 */
		memcpy(buf, ctx->mem, ctx->size);
		truncated = (buf[ctx->size - 1] != '\0');
		buf[ctx->size - 1] = '\0';

		printf("received IRQ and %s message: %s\n",
		       truncated ? "truncated" : "full", buf);
	}
	free(buf);
}

/*
 * setup ivshmem parameters
 *
 * allocates a k_object in sig if running on kernelspace
 */
static int setup_ivshmem(bool in_kernel)
{
	int ret;
	size_t i;

	ctx.dev = DEVICE_DT_GET(DT_NODELABEL(ivshmem0));
	if (!device_is_ready(ctx.dev)) {
		printf("Could not get ivshmem device\n");
		return -1;
	}

	ctx.size = ivshmem_get_mem(ctx.dev, (uintptr_t *)&ctx.mem);
	if (ctx.size == 0) {
		printf("Size cannot not be 0");
		return -1;
	}
	if (ctx.mem == NULL) {
		printf("Shared memory cannot be null\n");
		return -1;
	}

	ctx.id = ivshmem_get_id(ctx.dev);
	LOG_DBG("id for doorbell: %u", ctx.id);

	ctx.vectors = ivshmem_get_vectors(ctx.dev);
	if (ctx.vectors == 0) {
		printf("ivshmem-doorbell must have vectors\n");
		return -1;
	}

	if (in_kernel) {
		sig = k_malloc(sizeof(*sig));
		if (sig == NULL) {
			printf("could not allocate sig\n");
			return -1;
		}
		k_poll_signal_init(sig);
	}

	for (i = 0; i < ctx.vectors; i++) {
		ret = ivshmem_register_handler(ctx.dev, sig, i);
		if (ret < 0) {
			printf("registering handlers must be supported\n");
			return -1;
		}
	}
	return 0;
}

static void ivshmem_sample_failed(void)
{
	printf("test has failed\n");
	while (1) {
	}
}

#ifndef CONFIG_USERSPACE
static void ivshmem_sample_doorbell(void)
{
	int ret;

	ret = setup_ivshmem(true);
	if (ret < 0)
		return;
	ivshmem_event_loop(&ctx);
	/*
	 * if ivshmem_event_loop() returns, it means the function failed
	 *
	 * for kernelspace, if ivshmem_event_loop() fails, it will lead to
	 * main(), which, in turn, will call ivshmem_sample_failed()
	 */
	k_object_free(sig);
}
#else
static void user_entry(void *a, void *b, void *c)
{
	int ret;

	ret = setup_ivshmem(false);
	if (ret < 0) {
		goto fail;
	}
	ivshmem_event_loop(&ctx);
	/* if ivshmem_event_loop() returns, it means the function failed */
fail:
	k_object_release(sig);
	ivshmem_sample_failed();
}

static void ivshmem_sample_userspace_doorbell(void)
{
	int ret;
	const struct device *dev;
	struct k_mem_partition *parts[] = {
#if Z_LIBC_PARTITION_EXISTS
		&z_libc_partition,
#endif
#if Z_MALLOC_PARTITION_EXISTS
		&z_malloc_partition,
#endif
		&app_a_partition,
	};

	ret = k_mem_domain_init(&app_a_domain, ARRAY_SIZE(parts), parts);
	if (ret != 0) {
		printf("k_mem_domain_init failed %d\n", ret);
		return;
	}

	k_mem_domain_add_thread(&app_a_domain, k_current_get());

	dev = DEVICE_DT_GET(DT_NODELABEL(ivshmem0));
	if (!device_is_ready(dev)) {
		printf("Could not get ivshmem device\n");
		return;
	}

	sig = k_object_alloc(K_OBJ_POLL_SIGNAL);
	if (sig == NULL) {
		printf("could not allocate sig\n");
		return;
	}
	k_poll_signal_init(sig);

	k_object_access_grant(dev, k_current_get());
	k_object_access_grant(sig, k_current_get());

	k_thread_user_mode_enter(user_entry, NULL, NULL, NULL);
}
#endif /* CONFIG_USERSPACE */

int main(void)
{
#ifdef CONFIG_USERSPACE
	ivshmem_sample_userspace_doorbell();
#else
	ivshmem_sample_doorbell();
#endif
	/* if the code reaches here, it means the setup/loop has failed */
	ivshmem_sample_failed();
	return 0;
}
