/* Copyright (c) 2017 Google Inc.
 * See LICENSE for details.
 *
 * Set up paging, using the minphys and maxphys in the vm struct. */

#include <parlib/stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <ros/arch/mmu.h>
#include <vmm/vmm.h>
#include <vmm/util.h>
#include <string.h>
#include <stdint.h>
#include <errno.h>
#include <parlib/uthread.h>
#include <parlib/arch/arch.h>

static bool debug;

struct ptp {
	uintptr_t pte[NPTENTRIES];
};

#define PAGE_RESOLUTION PML3_PTE_REACH

/* We put the page tables after 4Gb, where it exactly is doesn't matter as long
 * as it's accessible by the guest. */
#define PAGE_TABLE_ROOT_START 0x100000000

static void check_jumbo_pages(void *arg)
{
	uint32_t edx;

	parlib_cpuid(0x80000001, 0x0, NULL, NULL, NULL, &edx);
	if (!(edx & (1 << 26)))
		panic("1 GB Jumbo Pages are not supported on this hardware!");
}

/*
 * This function assumes that after the p512 page table, there is memory mapped
 * (though not necessarily populated) for each PML3 page table. This assumes
 * a total of 2M + 4K memory mapped. PML3 table n is located at 4K*(n+1) from
 * the start of the p512 table.
 * This function does a 1:1 mapping of va to pa. vm->root must be set
 * */
void add_pte_entries(struct virtual_machine *vm, uintptr_t start, uintptr_t end)
{
	struct ptp *p512;
	uintptr_t cur_page, aligned_start, aligned_end, pml4, pml3;
	static parlib_once_t once = PARLIB_ONCE_INIT;

	/* We check once if we can use 1Gb pages and die if we can't. */
	parlib_run_once(&once, check_jumbo_pages, NULL);

	uth_mutex_lock(&vm->mtx);
	p512 = vm->root;
	if (!p512)
		panic("vm->root page table pointer was not set!");

	/* We align the start down and the end up to make sure we cover the full
	 * area. */
	aligned_start = ALIGN_DOWN(start, PAGE_RESOLUTION);
	aligned_end = ALIGN(end, PAGE_RESOLUTION);

	cur_page = aligned_start;
	/* We always do end-1 because end from /proc/self/maps is not inclusive
	 * */
	for (pml4 = PML4(start); pml4 <= PML4(end - 1); pml4++) {
		struct ptp *p1 = p512 + pml4 + 1;

		/* Create the PML4 entry. Rather than check, I just overwrite
		 * it. */
		p512->pte[pml4] = (uintptr_t) p1 | PTE_KERN_RW;

		for (pml3 = PML3(cur_page);
		     pml3 < NPTENTRIES && cur_page < aligned_end;
		     pml3++, cur_page += PML3_PTE_REACH) {
			/* Create the PML3 entry. */
			p1->pte[pml3] = cur_page | PTE_KERN_RW | PTE_PS;
		}
	}
	uth_mutex_unlock(&vm->mtx);
}

/* This function sets up the default page tables for the guest. It parses
 * /proc/self/maps to figure out what pages are mapped for the uthread, and
 * sets up a 1:1 mapping for the vm guest. This function can be called
 * multiple times after startup to update the page tables, though regular
 * vmms should call add_pte_entries if they mmap something for the guest after
 * calling setup_paging to avoid having to parse /proc/self/maps again. */
void setup_paging(struct virtual_machine *vm)
{
	FILE *maps;
	char *line = NULL;
	size_t line_sz;
	char *strtok_save;
	char *p;
	uintptr_t first, second;

	/* How many page table pages do we need?
	 * If we create 1G PTEs for the whole space, it just takes 2M + 4k worth
	 * of memory. Perhaps we should just identity map the whole space
	 * upfront.  Right now we don't MAP_POPULATE because we don't expect all
	 * the PTEs to be used. */
	if (!vm->root)
		vm->root = mmap((void *)PAGE_TABLE_ROOT_START, 0x201000,
		                PROT_READ | PROT_WRITE,
		                MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);

	if (vm->root == MAP_FAILED || (uintptr_t)vm->root >= BRK_START)
		panic("page table page alloc");

	/* We parse /proc/self/maps to figure out the currently mapped memory.
	 * This way all the memory that's available to the HR3 process is also
	 * reflected in the page tables. Our smallest PTEs here are 1Gb so there
	 * may be memory locations described in the page tables that are not
	 * mapped though. /proc/self/maps parsing code courtesy of Barret. */
	maps = fopen("/proc/self/maps", "r");
	if (!maps)
		panic("unable to open /proc/self/maps");

	/* returns -1 on error or EOF. */
	while (getline(&line, &line_sz, maps) >= 0) {
		if (debug)
			fprintf(stderr, "Got line %s", line);

		p = strchr(line, ' ');
		/* No space, probably an error */
		if (!p)
			continue;
		*p = '\0';
		p = strtok_r(line, "-", &strtok_save);
		/* No first element! */
		if (!p)
			continue;
		first = strtoul(p, NULL, 16);
		p = strtok_r(NULL, "-", &strtok_save);
		/* No second element! */
		if (!p)
			continue;
		second = strtoul(p, NULL, 16);

		if (debug)
			printf("first %p, second %p\n\n", first, second);

		add_pte_entries(vm, first, second);

	}
	free(line);
	fclose(maps);
}
