/*
 * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
 * Licensed under the GPL
 */

#include "linux/stddef.h"
#include "linux/config.h"
#include "linux/sched.h"
#include "linux/slab.h"
#include "linux/types.h"
#include "linux/errno.h"
#include "asm/uaccess.h"
#include "asm/smp.h"
#include "asm/ldt.h"
#include "asm/unistd.h"
#include "choose-mode.h"
#include "kern.h"
#include "mode_kern.h"
#include "os.h"

extern int modify_ldt(int func, void *ptr, unsigned long bytecount);

#ifdef CONFIG_MODE_TT

static long do_modify_ldt_tt(int func, void __user *ptr,
			      unsigned long bytecount)
{
	struct user_desc info;
	int res = 0;
	void *buf = NULL;
	void *p = NULL; /* What we pass to host. */

	switch(func){
	case 1:
	case 0x11: /* write_ldt */
		/* Do this check now to avoid overflows. */
		if (bytecount != sizeof(struct user_desc)) {
			res = -EINVAL;
			goto out;
		}

		if(copy_from_user(&info, ptr, sizeof(info))) {
			res = -EFAULT;
			goto out;
		}

		p = &info;
		break;
	case 0:
	case 2: /* read_ldt */

		/* The use of info avoids kmalloc on the write case, not on the
		 * read one. */
		buf = kmalloc(bytecount, GFP_KERNEL);
		if (!buf) {
			res = -ENOMEM;
			goto out;
		}
		p = buf;
		break;
	default:
		res = -ENOSYS;
		goto out;
	}

	res = modify_ldt(func, p, bytecount);
	if(res < 0)
		goto out;

	switch(func){
	case 0:
	case 2:
		/* Modify_ldt was for reading and returned the number of read
		 * bytes.*/
		if(copy_to_user(ptr, p, res))
			res = -EFAULT;
		break;
	}

out:
	kfree(buf);
	return res;
}

#endif

#ifdef CONFIG_MODE_SKAS

#include "skas.h"
#include "skas_ptrace.h"
#include "asm/mmu_context.h"
#include "proc_mm.h"

long write_ldt_entry(struct mm_id * mm_idp, int func, struct user_desc * desc,
		     void **addr, int done)
{
	long res;

	if(proc_mm){
		/* This is a special handling for the case, that the mm to
		 * modify isn't current->active_mm.
		 * If this is called directly by modify_ldt,
		 *     (current->active_mm->context.skas.u == mm_idp)
		 * will be true. So no call to switch_mm_skas(mm_idp) is done.
		 * If this is called in case of init_new_ldt or PTRACE_LDT,
		 * mm_idp won't belong to current->active_mm, but child->mm.
		 * So we need to switch child's mm into our userspace, then
		 * later switch back.
		 *
		 * Note: I'm unsure: should interrupts be disabled here?
		 */
		if(!current->active_mm || current->active_mm == &init_mm ||
		   mm_idp != &current->active_mm->context.skas.id)
			switch_mm_skas(mm_idp);
	}

	if(ptrace_ldt) {
		struct ptrace_ldt ldt_op = (struct ptrace_ldt) {
			.func = func,
			.ptr = desc,
			.bytecount = sizeof(*desc)};
		u32 cpu;
		int pid;

		if(!proc_mm)
			pid = mm_idp->u.pid;
		else {
			cpu = get_cpu();
			pid = userspace_pid[cpu];
		}

		res = os_ptrace_ldt(pid, 0, (unsigned long) &ldt_op);

		if(proc_mm)
			put_cpu();
	}
	else {
		void *stub_addr;
		res = syscall_stub_data(mm_idp, (unsigned long *)desc,
					(sizeof(*desc) + sizeof(long) - 1) &
					    ~(sizeof(long) - 1),
					addr, &stub_addr);
		if(!res){
			unsigned long args[] = { func,
						 (unsigned long)stub_addr,
						 sizeof(*desc),
						 0, 0, 0 };
			res = run_syscall_stub(mm_idp, __NR_modify_ldt, args,
					       0, addr, done);
		}
	}

	if(proc_mm){
		/* This is the second part of special handling, that makes
		 * PTRACE_LDT possible to implement.
		 */
		if(current->active_mm && current->active_mm != &init_mm &&
		   mm_idp != &current->active_mm->context.skas.id)
			switch_mm_skas(&current->active_mm->context.skas.id);
	}

	return res;
}

static long read_ldt_from_host(void __user * ptr, unsigned long bytecount)
{
	int res, n;
	struct ptrace_ldt ptrace_ldt = (struct ptrace_ldt) {
			.func = 0,
			.bytecount = bytecount,
			.ptr = (void *)kmalloc(bytecount, GFP_KERNEL)};
	u32 cpu;

	if(ptrace_ldt.ptr == NULL)
		return -ENOMEM;

	/* This is called from sys_modify_ldt only, so userspace_pid gives
	 * us the right number
	 */

	cpu = get_cpu();
	res = os_ptrace_ldt(userspace_pid[cpu], 0, (unsigned long) &ptrace_ldt);
	put_cpu();
	if(res < 0)
		goto out;

	n = copy_to_user(ptr, ptrace_ldt.ptr, res);
	if(n != 0)
		res = -EFAULT;

  out:
	kfree(ptrace_ldt.ptr);

	return res;
}

/*
 * In skas mode, we hold our own ldt data in UML.
 * Thus, the code implementing sys_modify_ldt_skas
 * is very similar to (and mostly stolen from) sys_modify_ldt
 * for arch/i386/kernel/ldt.c
 * The routines copied and modified in part are:
 * - read_ldt
 * - read_default_ldt
 * - write_ldt
 * - sys_modify_ldt_skas
 */

static int read_ldt(void __user * ptr, unsigned long bytecount)
{
	int i, err = 0;
	unsigned long size;
	uml_ldt_t * ldt = &current->mm->context.skas.ldt;

	if(!ldt->entry_count)
		goto out;
	if(bytecount > LDT_ENTRY_SIZE*LDT_ENTRIES)
		bytecount = LDT_ENTRY_SIZE*LDT_ENTRIES;
	err = bytecount;

	if(ptrace_ldt){
		return read_ldt_from_host(ptr, bytecount);
	}

	down(&ldt->semaphore);
	if(ldt->entry_count <= LDT_DIRECT_ENTRIES){
		size = LDT_ENTRY_SIZE*LDT_DIRECT_ENTRIES;
		if(size > bytecount)
			size = bytecount;
		if(copy_to_user(ptr, ldt->u.entries, size))
			err = -EFAULT;
		bytecount -= size;
		ptr += size;
	}
	else {
		for(i=0; i<ldt->entry_count/LDT_ENTRIES_PER_PAGE && bytecount;
			 i++){
			size = PAGE_SIZE;
			if(size > bytecount)
				size = bytecount;
			if(copy_to_user(ptr, ldt->u.pages[i], size)){
				err = -EFAULT;
				break;
			}
			bytecount -= size;
			ptr += size;
		}
	}
	up(&ldt->semaphore);

	if(bytecount == 0 || err == -EFAULT)
		goto out;

	if(clear_user(ptr, bytecount))
		err = -EFAULT;

out:
	return err;
}

static int read_default_ldt(void __user * ptr, unsigned long bytecount)
{
	int err;

	if(bytecount > 5*LDT_ENTRY_SIZE)
		bytecount = 5*LDT_ENTRY_SIZE;

	err = bytecount;
	/* UML doesn't support lcall7 and lcall27.
	 * So, we don't really have a default ldt, but emulate
	 * an empty ldt of common host default ldt size.
	 */
	if(clear_user(ptr, bytecount))
		err = -EFAULT;

	return err;
}

static int write_ldt(void __user * ptr, unsigned long bytecount, int func)
{
	uml_ldt_t * ldt = &current->mm->context.skas.ldt;
	struct mm_id * mm_idp = &current->mm->context.skas.id;
	int i, err;
	struct user_desc ldt_info;
	struct ldt_entry entry0, *ldt_p;
	void *addr = NULL;

	err = -EINVAL;
	if(bytecount != sizeof(ldt_info))
		goto out;
	err = -EFAULT;
	if(copy_from_user(&ldt_info, ptr, sizeof(ldt_info)))
		goto out;

	err = -EINVAL;
	if(ldt_info.entry_number >= LDT_ENTRIES)
		goto out;
	if(ldt_info.contents == 3){
		if (func == 1)
			goto out;
		if (ldt_info.seg_not_present == 0)
			goto out;
	}

        if(!ptrace_ldt)
                down(&ldt->semaphore);

	err = write_ldt_entry(mm_idp, func, &ldt_info, &addr, 1);
	if(err)
		goto out_unlock;
        else if(ptrace_ldt) {
	/* With PTRACE_LDT available, this is used as a flag only */
                ldt->entry_count = 1;
                goto out;
        }

	if(ldt_info.entry_number >= ldt->entry_count &&
	   ldt_info.entry_number >= LDT_DIRECT_ENTRIES){
		for(i=ldt->entry_count/LDT_ENTRIES_PER_PAGE;
		    i*LDT_ENTRIES_PER_PAGE <= ldt_info.entry_number;
		    i++){
			if(i == 0)
				memcpy(&entry0, ldt->u.entries,
				       sizeof(entry0));
			ldt->u.pages[i] = (struct ldt_entry *)
				__get_free_page(GFP_KERNEL|__GFP_ZERO);
			if(!ldt->u.pages[i]){
				err = -ENOMEM;
				/* Undo the change in host */
				memset(&ldt_info, 0, sizeof(ldt_info));
				write_ldt_entry(mm_idp, 1, &ldt_info, &addr, 1);
				goto out_unlock;
			}
			if(i == 0) {
				memcpy(ldt->u.pages[0], &entry0,
				       sizeof(entry0));
				memcpy(ldt->u.pages[0]+1, ldt->u.entries+1,
				       sizeof(entry0)*(LDT_DIRECT_ENTRIES-1));
			}
			ldt->entry_count = (i + 1) * LDT_ENTRIES_PER_PAGE;
		}
	}
	if(ldt->entry_count <= ldt_info.entry_number)
		ldt->entry_count = ldt_info.entry_number + 1;

	if(ldt->entry_count <= LDT_DIRECT_ENTRIES)
		ldt_p = ldt->u.entries + ldt_info.entry_number;
	else
		ldt_p = ldt->u.pages[ldt_info.entry_number/LDT_ENTRIES_PER_PAGE] +
			ldt_info.entry_number%LDT_ENTRIES_PER_PAGE;

	if(ldt_info.base_addr == 0 && ldt_info.limit == 0 &&
	   (func == 1 || LDT_empty(&ldt_info))){
		ldt_p->a = 0;
		ldt_p->b = 0;
	}
	else{
		if (func == 1)
			ldt_info.useable = 0;
		ldt_p->a = LDT_entry_a(&ldt_info);
		ldt_p->b = LDT_entry_b(&ldt_info);
	}
	err = 0;

out_unlock:
	up(&ldt->semaphore);
out:
	return err;
}

static long do_modify_ldt_skas(int func, void __user *ptr,
			       unsigned long bytecount)
{
	int ret = -ENOSYS;

	switch (func) {
		case 0:
			ret = read_ldt(ptr, bytecount);
			break;
		case 1:
		case 0x11:
			ret = write_ldt(ptr, bytecount, func);
			break;
		case 2:
			ret = read_default_ldt(ptr, bytecount);
			break;
	}
	return ret;
}

short dummy_list[9] = {0, -1};
short * host_ldt_entries = NULL;

void ldt_get_host_info(void)
{
	long ret;
	struct ldt_entry * ldt;
	int i, size, k, order;

	host_ldt_entries = dummy_list+1;

	for(i = LDT_PAGES_MAX-1, order=0; i; i>>=1, order++);

	ldt = (struct ldt_entry *)
	      __get_free_pages(GFP_KERNEL|__GFP_ZERO, order);
	if(ldt == NULL) {
		printk("ldt_get_host_info: couldn't allocate buffer for host ldt\n");
		return;
	}

	ret = modify_ldt(0, ldt, (1<<order)*PAGE_SIZE);
	if(ret < 0) {
		printk("ldt_get_host_info: couldn't read host ldt\n");
		goto out_free;
	}
	if(ret == 0) {
		/* default_ldt is active, simply write an empty entry 0 */
		host_ldt_entries = dummy_list;
		goto out_free;
	}

	for(i=0, size=0; i<ret/LDT_ENTRY_SIZE; i++){
		if(ldt[i].a != 0 || ldt[i].b != 0)
			size++;
	}

	if(size < ARRAY_SIZE(dummy_list))
		host_ldt_entries = dummy_list;
	else {
		size = (size + 1) * sizeof(dummy_list[0]);
		host_ldt_entries = (short *)kmalloc(size, GFP_KERNEL);
		if(host_ldt_entries == NULL) {
			printk("ldt_get_host_info: couldn't allocate host ldt list\n");
			goto out_free;
		}
	}

	for(i=0, k=0; i<ret/LDT_ENTRY_SIZE; i++){
		if(ldt[i].a != 0 || ldt[i].b != 0) {
			host_ldt_entries[k++] = i;
		}
	}
	host_ldt_entries[k] = -1;

out_free:
	free_pages((unsigned long)ldt, order);
}

long init_new_ldt(struct mmu_context_skas * new_mm,
		  struct mmu_context_skas * from_mm)
{
	struct user_desc desc;
	short * num_p;
	int i;
	long page, err=0;
	void *addr = NULL;
	struct proc_mm_op copy;


	if(!ptrace_ldt)
		init_MUTEX(&new_mm->ldt.semaphore);

	if(!from_mm){
		memset(&desc, 0, sizeof(desc));
		/*
		 * We have to initialize a clean ldt.
		 */
		if(proc_mm) {
			/*
			 * If the new mm was created using proc_mm, host's
			 * default-ldt currently is assigned, which normally
			 * contains the call-gates for lcall7 and lcall27.
			 * To remove these gates, we simply write an empty
			 * entry as number 0 to the host.
			 */
			err = write_ldt_entry(&new_mm->id, 1, &desc,
					      &addr, 1);
		}
		else{
			/*
			 * Now we try to retrieve info about the ldt, we
			 * inherited from the host. All ldt-entries found
			 * will be reset in the following loop
			 */
			if(host_ldt_entries == NULL)
				ldt_get_host_info();
			for(num_p=host_ldt_entries; *num_p != -1; num_p++){
				desc.entry_number = *num_p;
				err = write_ldt_entry(&new_mm->id, 1, &desc,
						      &addr, *(num_p + 1) == -1);
				if(err)
					break;
			}
		}
		new_mm->ldt.entry_count = 0;

		goto out;
	}

	if(proc_mm){
		/* We have a valid from_mm, so we now have to copy the LDT of
		 * from_mm to new_mm, because using proc_mm an new mm with
		 * an empty/default LDT was created in new_mm()
		 */
		copy = ((struct proc_mm_op) { .op 	= MM_COPY_SEGMENTS,
					      .u 	=
					      { .copy_segments =
							from_mm->id.u.mm_fd } } );
		i = os_write_file(new_mm->id.u.mm_fd, &copy, sizeof(copy));
		if(i != sizeof(copy))
			printk("new_mm : /proc/mm copy_segments failed, "
			       "err = %d\n", -i);
	}

	if(!ptrace_ldt) {
		/* Our local LDT is used to supply the data for
		 * modify_ldt(READLDT), if PTRACE_LDT isn't available,
		 * i.e., we have to use the stub for modify_ldt, which
		 * can't handle the big read buffer of up to 64kB.
		 */
		down(&from_mm->ldt.semaphore);
		if(from_mm->ldt.entry_count <= LDT_DIRECT_ENTRIES){
			memcpy(new_mm->ldt.u.entries, from_mm->ldt.u.entries,
			       sizeof(new_mm->ldt.u.entries));
		}
		else{
			i = from_mm->ldt.entry_count / LDT_ENTRIES_PER_PAGE;
			while(i-->0){
				page = __get_free_page(GFP_KERNEL|__GFP_ZERO);
				if (!page){
					err = -ENOMEM;
					break;
				}
				new_mm->ldt.u.pages[i] =
					(struct ldt_entry *) page;
				memcpy(new_mm->ldt.u.pages[i],
				       from_mm->ldt.u.pages[i], PAGE_SIZE);
			}
		}
		new_mm->ldt.entry_count = from_mm->ldt.entry_count;
		up(&from_mm->ldt.semaphore);
	}

    out:
	return err;
}


void free_ldt(struct mmu_context_skas * mm)
{
	int i;

	if(!ptrace_ldt && mm->ldt.entry_count > LDT_DIRECT_ENTRIES){
		i = mm->ldt.entry_count / LDT_ENTRIES_PER_PAGE;
		while(i-- > 0){
			free_page((long )mm->ldt.u.pages[i]);
		}
	}
	mm->ldt.entry_count = 0;
}
#endif

int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount)
{
	return(CHOOSE_MODE_PROC(do_modify_ldt_tt, do_modify_ldt_skas, func,
	                        ptr, bytecount));
}
