// SPDX-License-Identifier: GPL-2.0-only
/*
 * Initialize machine setup information and I/O.
 *
 * Copyright (C) 2023, Ventana Micro Systems Inc., Andrew Jones <ajones@ventanamicro.com>
 */
#include <libcflat.h>
#include <alloc.h>
#include <alloc_page.h>
#include <alloc_phys.h>
#include <argv.h>
#include <auxinfo.h>
#include <cpumask.h>
#include <devicetree.h>
#include <memregions.h>
#include <on-cpus.h>
#include <vmalloc.h>
#include <asm/csr.h>
#include <asm/mmu.h>
#include <asm/page.h>
#include <asm/processor.h>
#include <asm/setup.h>
#include <asm/timer.h>

#define VA_BASE			((phys_addr_t)3 * SZ_1G)
#if __riscv_xlen == 64
#define VA_TOP			((phys_addr_t)4 * SZ_1G)
#else
#define VA_TOP			((phys_addr_t)0)
#endif

#define MAX_DT_MEM_REGIONS	16
#define NR_MEM_REGIONS		(MAX_DT_MEM_REGIONS + 16)

extern unsigned long _etext;

char *initrd;
u32 initrd_size;

struct thread_info cpus[NR_CPUS];
int nr_cpus;
uint64_t timebase_frequency;

static struct mem_region riscv_mem_regions[NR_MEM_REGIONS + 1];

int hartid_to_cpu(unsigned long hartid)
{
	int cpu;

	for_each_present_cpu(cpu)
		if (cpus[cpu].hartid == hartid)
			return cpu;
	return -1;
}

static void cpu_set_fdt(int fdtnode __unused, u64 regval, void *info __unused)
{
	int cpu = nr_cpus++;

	assert_msg(cpu < NR_CPUS, "Number cpus exceeds maximum supported (%d).", NR_CPUS);

	cpus[cpu].cpu = cpu;
	cpus[cpu].hartid = regval;
	set_cpu_present(cpu, true);
}

static void cpu_init_acpi(void)
{
	assert_msg(false, "ACPI not available");
}

static void cpu_init(void)
{
	int ret;

	nr_cpus = 0;
	if (dt_available()) {
		ret = dt_for_each_cpu_node(cpu_set_fdt, NULL);
		assert(ret == 0);
	} else {
		cpu_init_acpi();
	}

	set_cpu_online(hartid_to_cpu(csr_read(CSR_SSCRATCH)), true);
	cpu0_calls_idle = true;
}

static void mem_allocator_init(phys_addr_t freemem_start, phys_addr_t freemem_end)
{
	phys_addr_t base, top;

	freemem_start = PAGE_ALIGN(freemem_start);
	freemem_end &= PAGE_MASK;

	/*
	 * The assert below is mostly checking that the free memory doesn't
	 * start in the 3G-4G range, which is reserved for virtual addresses,
	 * but it also confirms that there is some free memory (the amount
	 * is arbitrarily selected, but should be sufficient for a unit test)
	 *
	 * TODO: Allow the VA range to shrink and move.
	 */
	if (freemem_end > VA_BASE)
		freemem_end = VA_BASE;
	assert(freemem_end - freemem_start >= SZ_1M * 16);

	init_alloc_vpage(__va(VA_TOP));

	/*
	 * TODO: Remove the need for this phys allocator dance, since, as we
	 * can see with the assert, we could have gone straight to the page
	 * allocator.
	 */
	phys_alloc_init(freemem_start, freemem_end - freemem_start);
	phys_alloc_set_minimum_alignment(PAGE_SIZE);
	phys_alloc_get_unused(&base, &top);
	assert(base == freemem_start && top == freemem_end);

	page_alloc_init_area(0, freemem_start >> PAGE_SHIFT, freemem_end >> PAGE_SHIFT);
	page_alloc_ops_enable();
}

static void mem_init(phys_addr_t freemem_start)
{
	struct mem_region *freemem, *code, *data;

	memregions_init(riscv_mem_regions, NR_MEM_REGIONS);
	memregions_add_dt_regions(MAX_DT_MEM_REGIONS);

	/* Split the region with the code into two regions; code and data */
	memregions_split((unsigned long)&_etext, &code, &data);
	assert(code);
	code->flags |= MR_F_CODE;

	freemem = memregions_find(freemem_start);
	assert(freemem && !(freemem->flags & (MR_F_IO | MR_F_CODE)));

	mem_allocator_init(freemem_start, freemem->end);
}

static void freemem_push_fdt(void **freemem, const void *fdt)
{
	u32 fdt_size;
	int ret;

	fdt_size = fdt_totalsize(fdt);
	ret = fdt_move(fdt, *freemem, fdt_size);
	assert(ret == 0);
	ret = dt_init(*freemem);
	assert(ret == 0);
	*freemem += fdt_size;
}

static void freemem_push_dt_initrd(void **freemem)
{
	const char *tmp;
	int ret;

	ret = dt_get_initrd(&tmp, &initrd_size);
	assert(ret == 0 || ret == -FDT_ERR_NOTFOUND);
	if (ret == 0) {
		initrd = *freemem;
		memmove(initrd, tmp, initrd_size);
		*freemem += initrd_size;
	}
}

static void initrd_setup(void)
{
	char *env;

	if (!initrd)
		return;

	/* environ is currently the only file in the initrd */
	env = malloc(initrd_size);
	memcpy(env, initrd, initrd_size);
	setup_env(env, initrd_size);
}

static void banner(void)
{
	puts("\n");
	puts("##########################################################################\n");
	puts("#    kvm-unit-tests\n");
	puts("##########################################################################\n");
	puts("\n");
}

void setup(const void *fdt, phys_addr_t freemem_start)
{
	void *freemem;
	const char *bootargs;
	int ret;

	assert(sizeof(long) == 8 || freemem_start < VA_BASE);
	freemem = __va(freemem_start);

	freemem_push_fdt(&freemem, fdt);
	freemem_push_dt_initrd(&freemem);

	mem_init(PAGE_ALIGN(__pa(freemem)));
	cpu_init();
	timer_get_frequency();
	thread_info_init();
	io_init();

	ret = dt_get_bootargs(&bootargs);
	assert(ret == 0 || ret == -FDT_ERR_NOTFOUND);
	setup_args_progname(bootargs);

	initrd_setup();

	if (!(auxinfo.flags & AUXINFO_MMU_OFF))
		setup_vm();

	banner();
}

#ifdef CONFIG_EFI
#include <efi.h>

extern unsigned long exception_vectors;
extern unsigned long boot_hartid;

static efi_status_t efi_mem_init(efi_bootinfo_t *efi_bootinfo)
{
	struct mem_region *freemem_mr = NULL, *code, *data;
	void *freemem;

	memregions_init(riscv_mem_regions, NR_MEM_REGIONS);

	memregions_efi_init(&efi_bootinfo->mem_map, &freemem_mr);
	if (!freemem_mr)
		return EFI_OUT_OF_RESOURCES;

	memregions_split((unsigned long)&_etext, &code, &data);
	assert(code && (code->flags & MR_F_CODE));
	if (data)
		data->flags &= ~MR_F_CODE;

	for (struct mem_region *m = mem_regions; m->end; ++m)
		assert(m == code || !(m->flags & MR_F_CODE));

	freemem = (void *)PAGE_ALIGN(freemem_mr->start);

	if (efi_bootinfo->fdt)
		freemem_push_fdt(&freemem, efi_bootinfo->fdt);

	mmu_disable();
	mem_allocator_init((unsigned long)freemem, freemem_mr->end);

	return EFI_SUCCESS;
}

efi_status_t setup_efi(efi_bootinfo_t *efi_bootinfo)
{
	efi_status_t status;

	csr_write(CSR_STVEC, (unsigned long)&exception_vectors);
	csr_write(CSR_SSCRATCH, boot_hartid);

	status = efi_mem_init(efi_bootinfo);
	if (status != EFI_SUCCESS) {
		printf("Failed to initialize memory\n");
		return status;
	}

	cpu_init();
	timer_get_frequency();
	thread_info_init();
	io_init();
	initrd_setup();

	if (!(auxinfo.flags & AUXINFO_MMU_OFF))
		setup_vm();

	banner();

	return EFI_SUCCESS;
}
#endif /* CONFIG_EFI */
