/*
 *
 * (C) COPYRIGHT 2008-2013, 2016-2017 ARM Limited. All rights reserved.
 *
 * This program is free software and is provided to you under the terms of the
 * GNU General Public License version 2 as published by the Free Software
 * Foundation, and any use by you of this program is subject to the terms
 * of such GNU licence.
 *
 * A copy of the licence is included with the program, and can also be obtained
 * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA  02110-1301, USA.
 *
 */





#include <linux/ump.h>
#include <linux/ump-ioctl.h>

#include <linux/version.h>
#include <linux/module.h>            /* kernel module definitions */
#include <linux/fs.h>                /* file system operations */
#include <linux/cdev.h>              /* character device definitions */
#include <linux/ioport.h>            /* request_mem_region */
#include <linux/mm.h> /* memory mananger definitions */
#include <linux/pfn.h>
#include <linux/highmem.h> /*kmap*/

#include <linux/compat.h> /* is_compat_task */

#include <common/ump_kernel_core.h>
#include <ump_arch.h>
#include <common/ump_kernel_priv.h>

#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 5, 0)
#define phys_to_pfn_t(phys, flags) (phys >> PAGE_SHIFT)
#else
#include <linux/pfn_t.h>
#endif

static void umpp_vm_close(struct vm_area_struct *vma)
{
	umpp_cpu_mapping * mapping;
	umpp_session * session;
	ump_dd_handle handle;

	mapping = (umpp_cpu_mapping*)vma->vm_private_data;
	UMP_ASSERT(mapping);
	
	session = mapping->session;
	handle = mapping->handle;

	umpp_dd_remove_cpu_mapping(mapping->handle, mapping); /* will free the mapping object */
	ump_dd_release(handle);
}


static const struct vm_operations_struct umpp_vm_ops = {
	.close = umpp_vm_close
};

int umpp_phys_commit(umpp_allocation * alloc)
{
	uint64_t i;

	/* round up to a page boundary */
	alloc->size = (alloc->size + PAGE_SIZE - 1) & ~((uint64_t)PAGE_SIZE-1) ;
	/* calculate number of pages */
	alloc->blocksCount = alloc->size >> PAGE_SHIFT;

	if( (sizeof(ump_dd_physical_block_64) * alloc->blocksCount) > ((size_t)-1))
	{
		printk(KERN_WARNING "UMP: umpp_phys_commit - trying to allocate more than possible\n");
		return -ENOMEM;
	}

	alloc->block_array = kmalloc(sizeof(ump_dd_physical_block_64) * alloc->blocksCount, __GFP_HARDWALL | GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN);
	if (NULL == alloc->block_array)
	{
		return -ENOMEM;
	}

	for (i = 0; i < alloc->blocksCount; i++)
	{
		void * mp;
		struct page * page = alloc_page(GFP_HIGHUSER | __GFP_NORETRY | __GFP_NOWARN | __GFP_COLD);
		if (NULL == page)
		{
			break;
		}

		alloc->block_array[i].addr = PFN_PHYS(page_to_pfn(page));
		alloc->block_array[i].size = PAGE_SIZE;

		mp = kmap(page);
		if (NULL == mp)
		{
			__free_page(page);
			break;
		}

		memset(mp, 0x00, PAGE_SIZE); /* instead of __GFP_ZERO, so we can do cache maintenance */
		ump_sync_to_memory(PFN_PHYS(page_to_pfn(page)), mp, PAGE_SIZE);
		kunmap(page);
	}

	if (i == alloc->blocksCount)
	{
		return 0;
	}
	else
	{
		uint64_t j;
		for (j = 0; j < i; j++)
		{
			struct page * page;
			page = pfn_to_page(alloc->block_array[j].addr >> PAGE_SHIFT);
			__free_page(page);
		}
		
		kfree(alloc->block_array);

		return -ENOMEM;
	}
}

void umpp_phys_free(umpp_allocation * alloc)
{
	uint64_t i;

	for (i = 0; i < alloc->blocksCount; i++)
	{
		__free_page(pfn_to_page(alloc->block_array[i].addr >> PAGE_SHIFT));
	}

	kfree(alloc->block_array);
}

int umpp_linux_mmap(struct file * filp, struct vm_area_struct * vma)
{
	ump_secure_id id;
	ump_dd_handle h;
	size_t offset;
	int err = -EINVAL;
	size_t length = vma->vm_end - vma->vm_start;

	umpp_cpu_mapping * map = NULL;
	umpp_session *session = filp->private_data;

	if ( 0 == length )
	{
		return -EINVAL;
	}

	map = kzalloc(sizeof(*map), GFP_KERNEL);
	if (NULL == map)
	{
		WARN_ON(1);
		err = -ENOMEM;
		goto out;
	}

	/* unpack our arg */
#if defined CONFIG_64BIT && CONFIG_64BIT
	if (is_compat_task())
	{
#endif
		id = vma->vm_pgoff >> UMP_LINUX_OFFSET_BITS_32;
		offset = vma->vm_pgoff & UMP_LINUX_OFFSET_MASK_32;
#if defined CONFIG_64BIT && CONFIG_64BIT
	}
	else
	{
		id = vma->vm_pgoff >> UMP_LINUX_OFFSET_BITS_64;
		offset = vma->vm_pgoff & UMP_LINUX_OFFSET_MASK_64;
	}
#endif

	h = ump_dd_from_secure_id(id);
	if (UMP_DD_INVALID_MEMORY_HANDLE != h)
	{
		uint64_t i;
		uint64_t block_idx;
		uint64_t block_offset;
		uint64_t paddr;
		umpp_allocation * alloc;
		uint64_t last_byte;

#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0))
		vma->vm_flags |= VM_DONTCOPY | VM_DONTEXPAND | VM_IO | VM_MIXEDMAP | VM_DONTDUMP;
#else
		vma->vm_flags |= VM_DONTCOPY | VM_DONTEXPAND | VM_RESERVED | VM_IO | VM_MIXEDMAP;
#endif
		vma->vm_ops = &umpp_vm_ops;
		vma->vm_private_data = map;

		alloc = (umpp_allocation*)h;

		if( (alloc->flags & UMP_CONSTRAINT_UNCACHED) != 0)
		{
			/* cache disabled flag set, disable caching for cpu mappings */
			vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
		}

		last_byte = length + (offset << PAGE_SHIFT) - 1;
		if (last_byte >= alloc->size || last_byte < (offset << PAGE_SHIFT))
		{
			goto err_out;
		}

		if (umpp_dd_find_start_block(alloc, offset << PAGE_SHIFT, &block_idx, &block_offset))
		{
			goto err_out;
		}

		paddr = alloc->block_array[block_idx].addr + block_offset;

		for (i = 0; i < (length >> PAGE_SHIFT); i++)
		{
			/* check if we've overrrun the current block, if so move to the next block */
			if (paddr >= (alloc->block_array[block_idx].addr + alloc->block_array[block_idx].size))
			{
				block_idx++;
				UMP_ASSERT(block_idx < alloc->blocksCount);
				paddr = alloc->block_array[block_idx].addr;
			}

			err = vm_insert_mixed(vma,
					vma->vm_start + (i << PAGE_SHIFT),
					phys_to_pfn_t(paddr, 0));
			paddr += PAGE_SIZE;
		}

		map->vaddr_start = (void*)vma->vm_start;
		map->nr_pages = length >> PAGE_SHIFT;
		map->page_off = offset;
		map->handle = h;
		map->session = session;

		umpp_dd_add_cpu_mapping(h, map);

		return 0;

		err_out:

		ump_dd_release(h);
	}

	kfree(map);

out:

	return err;
}

