/* Written 2000 by Andi Kleen */
#ifndef __ARCH_DESC_H
#define __ARCH_DESC_H

#include <linux/threads.h>
#include <asm/ldt.h>

#ifndef __ASSEMBLY__

#include <linux/string.h>
#include <linux/smp.h>
#include <asm/desc_defs.h>

#include <asm/segment.h>
#include <asm/mmu.h>

extern struct desc_struct cpu_gdt_table[GDT_ENTRIES];

#define load_TR_desc() asm volatile("ltr %w0"::"r" (GDT_ENTRY_TSS*8))
#define load_LDT_desc() asm volatile("lldt %w0"::"r" (GDT_ENTRY_LDT*8))
#define clear_LDT()  asm volatile("lldt %w0"::"r" (0))

static inline unsigned long __store_tr(void)
{
       unsigned long tr;

       asm volatile ("str %w0":"=r" (tr));
       return tr;
}

#define store_tr(tr) (tr) = __store_tr()

extern gate_desc idt_table[];
extern struct desc_ptr cpu_gdt_descr[];

static inline void write_ldt_entry(struct desc_struct *ldt,
				   int entry, u32 entry_low, u32 entry_high)
{
	__u32 *lp = (__u32 *)((entry << 3) + (char *)ldt);

	lp[0] = entry_low;
	lp[1] = entry_high;
}

/* the cpu gdt accessor */
#define get_cpu_gdt_table(x) ((struct desc_struct *)cpu_gdt_descr[x].address)

static inline void load_gdt(const struct desc_ptr *ptr)
{
	asm volatile("lgdt %w0"::"m" (*ptr));
}

static inline void store_gdt(struct desc_ptr *ptr)
{
       asm("sgdt %w0":"=m" (*ptr));
}

static inline void _set_gate(void *adr, unsigned type, unsigned long func,
			     unsigned dpl, unsigned ist)
{
	gate_desc s;

	s.offset_low = PTR_LOW(func);
	s.segment = __KERNEL_CS;
	s.ist = ist;
	s.p = 1;
	s.dpl = dpl;
	s.zero0 = 0;
	s.zero1 = 0;
	s.type = type;
	s.offset_middle = PTR_MIDDLE(func);
	s.offset_high = PTR_HIGH(func);
	/*
	 * does not need to be atomic because it is only done once at
	 * setup time
	 */
	memcpy(adr, &s, 16);
}

static inline void set_intr_gate(int nr, void *func)
{
	BUG_ON((unsigned)nr > 0xFF);
	_set_gate(&idt_table[nr], GATE_INTERRUPT, (unsigned long) func, 0, 0);
}

static inline void set_intr_gate_ist(int nr, void *func, unsigned ist)
{
	BUG_ON((unsigned)nr > 0xFF);
	_set_gate(&idt_table[nr], GATE_INTERRUPT, (unsigned long) func, 0, ist);
}

static inline void set_system_gate(int nr, void *func)
{
	BUG_ON((unsigned)nr > 0xFF);
	_set_gate(&idt_table[nr], GATE_INTERRUPT, (unsigned long) func, 3, 0);
}

static inline void set_system_gate_ist(int nr, void *func, unsigned ist)
{
	_set_gate(&idt_table[nr], GATE_INTERRUPT, (unsigned long) func, 3, ist);
}

static inline void load_idt(const struct desc_ptr *ptr)
{
	asm volatile("lidt %w0"::"m" (*ptr));
}

static inline void store_idt(struct desc_ptr *dtr)
{
       asm("sidt %w0":"=m" (*dtr));
}

static inline void set_tssldt_descriptor(void *ptr, unsigned long tss,
					 unsigned type, unsigned size)
{
	struct ldttss_desc64 d;

	memset(&d, 0, sizeof(d));
	d.limit0 = size & 0xFFFF;
	d.base0 = PTR_LOW(tss);
	d.base1 = PTR_MIDDLE(tss) & 0xFF;
	d.type = type;
	d.p = 1;
	d.limit1 = (size >> 16) & 0xF;
	d.base2 = (PTR_MIDDLE(tss) >> 8) & 0xFF;
	d.base3 = PTR_HIGH(tss);
	memcpy(ptr, &d, 16);
}

static inline void set_tss_desc(unsigned cpu, void *addr)
{
	/*
	 * sizeof(unsigned long) coming from an extra "long" at the end
	 * of the iobitmap. See tss_struct definition in processor.h
	 *
	 * -1? seg base+limit should be pointing to the address of the
	 * last valid byte
	 */
	set_tssldt_descriptor(&get_cpu_gdt_table(cpu)[GDT_ENTRY_TSS],
		(unsigned long)addr, DESC_TSS,
		IO_BITMAP_OFFSET + IO_BITMAP_BYTES + sizeof(unsigned long) - 1);
}

static inline void set_ldt_desc(unsigned cpu, void *addr, int size)
{
	set_tssldt_descriptor(&get_cpu_gdt_table(cpu)[GDT_ENTRY_LDT],
			     (unsigned long)addr, DESC_LDT, size * 8 - 1);
}

#define LDT_empty(info) (\
	(info)->base_addr	== 0	&& \
	(info)->limit		== 0	&& \
	(info)->contents	== 0	&& \
	(info)->read_exec_only	== 1	&& \
	(info)->seg_32bit	== 0	&& \
	(info)->limit_in_pages	== 0	&& \
	(info)->seg_not_present	== 1	&& \
	(info)->useable		== 0	&& \
	(info)->lm		== 0)

static inline void load_TLS(struct thread_struct *t, unsigned int cpu)
{
	unsigned int i;
	u64 *gdt = (u64 *)(get_cpu_gdt_table(cpu) + GDT_ENTRY_TLS_MIN);

	for (i = 0; i < GDT_ENTRY_TLS_ENTRIES; i++)
		gdt[i] = t->tls_array[i];
}

/*
 * load one particular LDT into the current CPU
 */
static inline void load_LDT_nolock(mm_context_t *pc, int cpu)
{
	int count = pc->size;

	if (likely(!count)) {
		clear_LDT();
		return;
	}

	set_ldt_desc(cpu, pc->ldt, count);
	load_LDT_desc();
}

static inline void load_LDT(mm_context_t *pc)
{
	int cpu = get_cpu();

	load_LDT_nolock(pc, cpu);
	put_cpu();
}

extern struct desc_ptr idt_descr;

static inline unsigned long get_desc_base(const void *ptr)
{
	const u32 *desc = ptr;
	unsigned long base;
	base = ((desc[0] >> 16)  & 0x0000ffff) |
		((desc[1] << 16) & 0x00ff0000) |
		(desc[1] & 0xff000000);
	return base;
}

#endif /* !__ASSEMBLY__ */

#endif
