/*
 * IA32 helper functions
 *
 * Copyright (C) 1999 Arun Sharma <arun.sharma@intel.com>
 * Copyright (C) 2000 Asit K. Mallick <asit.k.mallick@intel.com>
 * Copyright (C) 2001-2002 Hewlett-Packard Co
 *	David Mosberger-Tang <davidm@hpl.hp.com>
 *
 * 06/16/00	A. Mallick	added csd/ssd/tssd for ia32 thread context
 * 02/19/01	D. Mosberger	dropped tssd; it's not needed
 * 09/14/01	D. Mosberger	fixed memory management for gdt/tss page
 * 09/29/01	D. Mosberger	added ia32_load_segment_descriptors()
 */

#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/sched.h>

#include <asm/intrinsics.h>
#include <asm/page.h>
#include <asm/pgtable.h>
#include <asm/system.h>
#include <asm/processor.h>
#include <asm/uaccess.h>

#include "ia32priv.h"

extern int die_if_kernel (char *str, struct pt_regs *regs, long err);

struct page *ia32_shared_page[NR_CPUS];
unsigned long *ia32_boot_gdt;
unsigned long *cpu_gdt_table[NR_CPUS];
struct page *ia32_gate_page;

static unsigned long
load_desc (u16 selector)
{
	unsigned long *table, limit, index;

	if (!selector)
		return 0;
	if (selector & IA32_SEGSEL_TI) {
		table = (unsigned long *) IA32_LDT_OFFSET;
		limit = IA32_LDT_ENTRIES;
	} else {
		table = cpu_gdt_table[smp_processor_id()];
		limit = IA32_PAGE_SIZE / sizeof(ia32_boot_gdt[0]);
	}
	index = selector >> IA32_SEGSEL_INDEX_SHIFT;
	if (index >= limit)
		return 0;
	return IA32_SEG_UNSCRAMBLE(table[index]);
}

void
ia32_load_segment_descriptors (struct task_struct *task)
{
	struct pt_regs *regs = task_pt_regs(task);

	/* Setup the segment descriptors */
	regs->r24 = load_desc(regs->r16 >> 16);		/* ESD */
	regs->r27 = load_desc(regs->r16 >>  0);		/* DSD */
	regs->r28 = load_desc(regs->r16 >> 32);		/* FSD */
	regs->r29 = load_desc(regs->r16 >> 48);		/* GSD */
	regs->ar_csd = load_desc(regs->r17 >>  0);	/* CSD */
	regs->ar_ssd = load_desc(regs->r17 >> 16);	/* SSD */
}

int
ia32_clone_tls (struct task_struct *child, struct pt_regs *childregs)
{
	struct desc_struct *desc;
	struct ia32_user_desc info;
	int idx;

	if (copy_from_user(&info, (void __user *)(childregs->r14 & 0xffffffff), sizeof(info)))
		return -EFAULT;
	if (LDT_empty(&info))
		return -EINVAL;

	idx = info.entry_number;
	if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
		return -EINVAL;

	desc = child->thread.tls_array + idx - GDT_ENTRY_TLS_MIN;
	desc->a = LDT_entry_a(&info);
	desc->b = LDT_entry_b(&info);

	/* XXX: can this be done in a cleaner way ? */
	load_TLS(&child->thread, smp_processor_id());
	ia32_load_segment_descriptors(child);
	load_TLS(&current->thread, smp_processor_id());

	return 0;
}

void
ia32_save_state (struct task_struct *t)
{
	t->thread.eflag = ia64_getreg(_IA64_REG_AR_EFLAG);
	t->thread.fsr   = ia64_getreg(_IA64_REG_AR_FSR);
	t->thread.fcr   = ia64_getreg(_IA64_REG_AR_FCR);
	t->thread.fir   = ia64_getreg(_IA64_REG_AR_FIR);
	t->thread.fdr   = ia64_getreg(_IA64_REG_AR_FDR);
	ia64_set_kr(IA64_KR_IO_BASE, t->thread.old_iob);
	ia64_set_kr(IA64_KR_TSSD, t->thread.old_k1);
}

void
ia32_load_state (struct task_struct *t)
{
	unsigned long eflag, fsr, fcr, fir, fdr, tssd;
	struct pt_regs *regs = task_pt_regs(t);

	eflag = t->thread.eflag;
	fsr = t->thread.fsr;
	fcr = t->thread.fcr;
	fir = t->thread.fir;
	fdr = t->thread.fdr;
	tssd = load_desc(_TSS);					/* TSSD */

	ia64_setreg(_IA64_REG_AR_EFLAG, eflag);
	ia64_setreg(_IA64_REG_AR_FSR, fsr);
	ia64_setreg(_IA64_REG_AR_FCR, fcr);
	ia64_setreg(_IA64_REG_AR_FIR, fir);
	ia64_setreg(_IA64_REG_AR_FDR, fdr);
	current->thread.old_iob = ia64_get_kr(IA64_KR_IO_BASE);
	current->thread.old_k1 = ia64_get_kr(IA64_KR_TSSD);
	ia64_set_kr(IA64_KR_IO_BASE, IA32_IOBASE);
	ia64_set_kr(IA64_KR_TSSD, tssd);

	regs->r17 = (_TSS << 48) | (_LDT << 32) | (__u32) regs->r17;
	regs->r30 = load_desc(_LDT);				/* LDTD */
	load_TLS(&t->thread, smp_processor_id());
}

/*
 * Setup IA32 GDT and TSS
 */
void
ia32_gdt_init (void)
{
	int cpu = smp_processor_id();

	ia32_shared_page[cpu] = alloc_page(GFP_KERNEL);
	if (!ia32_shared_page[cpu])
		panic("failed to allocate ia32_shared_page[%d]\n", cpu);

	cpu_gdt_table[cpu] = page_address(ia32_shared_page[cpu]);

	/* Copy from the boot cpu's GDT */
	memcpy(cpu_gdt_table[cpu], ia32_boot_gdt, PAGE_SIZE);
}


/*
 * Setup IA32 GDT and TSS
 */
static void
ia32_boot_gdt_init (void)
{
	unsigned long ldt_size;

	ia32_shared_page[0] = alloc_page(GFP_KERNEL);
	if (!ia32_shared_page[0])
		panic("failed to allocate ia32_shared_page[0]\n");

	ia32_boot_gdt = page_address(ia32_shared_page[0]);
	cpu_gdt_table[0] = ia32_boot_gdt;

	/* CS descriptor in IA-32 (scrambled) format */
	ia32_boot_gdt[__USER_CS >> 3]
		= IA32_SEG_DESCRIPTOR(0, (IA32_GATE_END-1) >> IA32_PAGE_SHIFT,
				      0xb, 1, 3, 1, 1, 1, 1);

	/* DS descriptor in IA-32 (scrambled) format */
	ia32_boot_gdt[__USER_DS >> 3]
		= IA32_SEG_DESCRIPTOR(0, (IA32_GATE_END-1) >> IA32_PAGE_SHIFT,
				      0x3, 1, 3, 1, 1, 1, 1);

	ldt_size = PAGE_ALIGN(IA32_LDT_ENTRIES*IA32_LDT_ENTRY_SIZE);
	ia32_boot_gdt[TSS_ENTRY] = IA32_SEG_DESCRIPTOR(IA32_TSS_OFFSET, 235,
						       0xb, 0, 3, 1, 1, 1, 0);
	ia32_boot_gdt[LDT_ENTRY] = IA32_SEG_DESCRIPTOR(IA32_LDT_OFFSET, ldt_size - 1,
						       0x2, 0, 3, 1, 1, 1, 0);
}

static void
ia32_gate_page_init(void)
{
	unsigned long *sr;

	ia32_gate_page = alloc_page(GFP_KERNEL);
	sr = page_address(ia32_gate_page);
	/* This is popl %eax ; movl $,%eax ; int $0x80 */
	*sr++ = 0xb858 | (__IA32_NR_sigreturn << 16) | (0x80cdUL << 48);

	/* This is movl $,%eax ; int $0x80 */
	*sr = 0xb8 | (__IA32_NR_rt_sigreturn << 8) | (0x80cdUL << 40);
}

void
ia32_mem_init(void)
{
	ia32_boot_gdt_init();
	ia32_gate_page_init();
}

/*
 * Handle bad IA32 interrupt via syscall
 */
void
ia32_bad_interrupt (unsigned long int_num, struct pt_regs *regs)
{
	siginfo_t siginfo;

	if (die_if_kernel("Bad IA-32 interrupt", regs, int_num))
		return;

	siginfo.si_signo = SIGTRAP;
	siginfo.si_errno = int_num;	/* XXX is it OK to abuse si_errno like this? */
	siginfo.si_flags = 0;
	siginfo.si_isr = 0;
	siginfo.si_addr = NULL;
	siginfo.si_imm = 0;
	siginfo.si_code = TRAP_BRKPT;
	force_sig_info(SIGTRAP, &siginfo, current);
}

void
ia32_cpu_init (void)
{
	/* initialize global ia32 state - CR0 and CR4 */
	ia64_setreg(_IA64_REG_AR_CFLAG, (((ulong) IA32_CR4 << 32) | IA32_CR0));
}

static int __init
ia32_init (void)
{
#if PAGE_SHIFT > IA32_PAGE_SHIFT
	{
		extern struct kmem_cache *ia64_partial_page_cachep;

		ia64_partial_page_cachep = kmem_cache_create("ia64_partial_page_cache",
					sizeof(struct ia64_partial_page),
					0, SLAB_PANIC, NULL);
	}
#endif
	return 0;
}

__initcall(ia32_init);
