desc_64.h 4.4 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10
/* 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>
11
#include <linux/smp.h>
12
#include <asm/desc_defs.h>
13

L
Linus Torvalds 已提交
14 15 16
#include <asm/segment.h>
#include <asm/mmu.h>

17
extern struct desc_struct cpu_gdt_table[GDT_ENTRIES];
L
Linus Torvalds 已提交
18 19 20 21 22 23 24 25 26 27 28

#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))

/*
 * This is the ldt that every process will get unless we need
 * something other than this.
 */
extern struct desc_struct default_ldt[];
extern struct gate_struct idt_table[]; 
29
extern struct desc_ptr cpu_gdt_descr[];
L
Linus Torvalds 已提交
30

31 32 33
/* the cpu gdt accessor */
#define cpu_gdt(_cpu) ((struct desc_struct *)cpu_gdt_descr[_cpu].address)

L
Linus Torvalds 已提交
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
static inline void _set_gate(void *adr, unsigned type, unsigned long func, unsigned dpl, unsigned ist)  
{
	struct gate_struct 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) 
{ 
53
	BUG_ON((unsigned)nr > 0xFF);
L
Linus Torvalds 已提交
54 55 56 57 58
	_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) 
{ 
59
	BUG_ON((unsigned)nr > 0xFF);
L
Linus Torvalds 已提交
60 61 62 63 64
	_set_gate(&idt_table[nr], GATE_INTERRUPT, (unsigned long) func, 0, ist); 
} 

static inline void set_system_gate(int nr, void *func) 
{ 
65
	BUG_ON((unsigned)nr > 0xFF);
L
Linus Torvalds 已提交
66 67 68
	_set_gate(&idt_table[nr], GATE_INTERRUPT, (unsigned long) func, 3, 0); 
} 

69 70 71 72 73
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);
}

L
Linus Torvalds 已提交
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
static inline void set_tssldt_descriptor(void *ptr, unsigned long tss, unsigned type, 
					 unsigned size) 
{ 
	struct ldttss_desc 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)
{ 
S
Siddha, Suresh B 已提交
92 93 94 95 96 97 98
	/*
	 * 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
	 */
99
	set_tssldt_descriptor(&cpu_gdt(cpu)[GDT_ENTRY_TSS],
S
Siddha, Suresh B 已提交
100 101
		(unsigned long)addr, DESC_TSS,
		IO_BITMAP_OFFSET + IO_BITMAP_BYTES + sizeof(unsigned long) - 1);
L
Linus Torvalds 已提交
102 103 104 105
} 

static inline void set_ldt_desc(unsigned cpu, void *addr, int size)
{ 
106
	set_tssldt_descriptor(&cpu_gdt(cpu)[GDT_ENTRY_LDT], (unsigned long)addr,
L
Linus Torvalds 已提交
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
			      DESC_LDT, size * 8 - 1);
}

#define LDT_entry_a(info) \
	((((info)->base_addr & 0x0000ffff) << 16) | ((info)->limit & 0x0ffff))
/* Don't allow setting of the lm bit. It is useless anyways because 
   64bit system calls require __USER_CS. */ 
#define LDT_entry_b(info) \
	(((info)->base_addr & 0xff000000) | \
	(((info)->base_addr & 0x00ff0000) >> 16) | \
	((info)->limit & 0xf0000) | \
	(((info)->read_exec_only ^ 1) << 9) | \
	((info)->contents << 10) | \
	(((info)->seg_not_present ^ 1) << 15) | \
	((info)->seg_32bit << 22) | \
	((info)->limit_in_pages << 23) | \
	((info)->useable << 20) | \
	/* ((info)->lm << 21) | */ \
	0x7000)

#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)
{
140
	unsigned int i;
141
	u64 *gdt = (u64 *)(cpu_gdt(cpu) + GDT_ENTRY_TLS_MIN);
142 143 144

	for (i = 0; i < GDT_ENTRY_TLS_ENTRIES; i++)
		gdt[i] = t->tls_array[i];
L
Linus Torvalds 已提交
145 146 147 148 149
} 

/*
 * load one particular LDT into the current CPU
 */
150
static inline void load_LDT_nolock (mm_context_t *pc, int cpu)
L
Linus Torvalds 已提交
151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
{
	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;

#endif /* !__ASSEMBLY__ */

#endif