/*
 *
 * (C) COPYRIGHT 2008-2013, 2016 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>

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), paddr >> PAGE_SHIFT);
			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;
}

