aboutsummaryrefslogtreecommitdiffstats
path: root/include/asm-i386/desc.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/asm-i386/desc.h')
-rw-r--r--include/asm-i386/desc.h95
1 files changed, 55 insertions, 40 deletions
diff --git a/include/asm-i386/desc.h b/include/asm-i386/desc.h
index 5874ef119ffd..f398cc456448 100644
--- a/include/asm-i386/desc.h
+++ b/include/asm-i386/desc.h
@@ -4,8 +4,6 @@
4#include <asm/ldt.h> 4#include <asm/ldt.h>
5#include <asm/segment.h> 5#include <asm/segment.h>
6 6
7#define CPU_16BIT_STACK_SIZE 1024
8
9#ifndef __ASSEMBLY__ 7#ifndef __ASSEMBLY__
10 8
11#include <linux/preempt.h> 9#include <linux/preempt.h>
@@ -16,8 +14,6 @@
16 14
17extern struct desc_struct cpu_gdt_table[GDT_ENTRIES]; 15extern struct desc_struct cpu_gdt_table[GDT_ENTRIES];
18 16
19DECLARE_PER_CPU(unsigned char, cpu_16bit_stack[CPU_16BIT_STACK_SIZE]);
20
21struct Xgt_desc_struct { 17struct Xgt_desc_struct {
22 unsigned short size; 18 unsigned short size;
23 unsigned long address __attribute__((packed)); 19 unsigned long address __attribute__((packed));
@@ -33,11 +29,6 @@ static inline struct desc_struct *get_cpu_gdt_table(unsigned int cpu)
33 return (struct desc_struct *)per_cpu(cpu_gdt_descr, cpu).address; 29 return (struct desc_struct *)per_cpu(cpu_gdt_descr, cpu).address;
34} 30}
35 31
36/*
37 * This is the ldt that every process will get unless we need
38 * something other than this.
39 */
40extern struct desc_struct default_ldt[];
41extern struct desc_struct idt_table[]; 32extern struct desc_struct idt_table[];
42extern void set_intr_gate(unsigned int irq, void * addr); 33extern void set_intr_gate(unsigned int irq, void * addr);
43 34
@@ -64,8 +55,10 @@ static inline void pack_gate(__u32 *a, __u32 *b,
64#define DESCTYPE_DPL3 0x60 /* DPL-3 */ 55#define DESCTYPE_DPL3 0x60 /* DPL-3 */
65#define DESCTYPE_S 0x10 /* !system */ 56#define DESCTYPE_S 0x10 /* !system */
66 57
58#ifdef CONFIG_PARAVIRT
59#include <asm/paravirt.h>
60#else
67#define load_TR_desc() __asm__ __volatile__("ltr %w0"::"q" (GDT_ENTRY_TSS*8)) 61#define load_TR_desc() __asm__ __volatile__("ltr %w0"::"q" (GDT_ENTRY_TSS*8))
68#define load_LDT_desc() __asm__ __volatile__("lldt %w0"::"q" (GDT_ENTRY_LDT*8))
69 62
70#define load_gdt(dtr) __asm__ __volatile("lgdt %0"::"m" (*dtr)) 63#define load_gdt(dtr) __asm__ __volatile("lgdt %0"::"m" (*dtr))
71#define load_idt(dtr) __asm__ __volatile("lidt %0"::"m" (*dtr)) 64#define load_idt(dtr) __asm__ __volatile("lidt %0"::"m" (*dtr))
@@ -88,6 +81,10 @@ static inline void load_TLS(struct thread_struct *t, unsigned int cpu)
88#undef C 81#undef C
89} 82}
90 83
84#define write_ldt_entry(dt, entry, a, b) write_dt_entry(dt, entry, a, b)
85#define write_gdt_entry(dt, entry, a, b) write_dt_entry(dt, entry, a, b)
86#define write_idt_entry(dt, entry, a, b) write_dt_entry(dt, entry, a, b)
87
91static inline void write_dt_entry(void *dt, int entry, __u32 entry_a, __u32 entry_b) 88static inline void write_dt_entry(void *dt, int entry, __u32 entry_a, __u32 entry_b)
92{ 89{
93 __u32 *lp = (__u32 *)((char *)dt + entry*8); 90 __u32 *lp = (__u32 *)((char *)dt + entry*8);
@@ -95,9 +92,25 @@ static inline void write_dt_entry(void *dt, int entry, __u32 entry_a, __u32 entr
95 *(lp+1) = entry_b; 92 *(lp+1) = entry_b;
96} 93}
97 94
98#define write_ldt_entry(dt, entry, a, b) write_dt_entry(dt, entry, a, b) 95#define set_ldt native_set_ldt
99#define write_gdt_entry(dt, entry, a, b) write_dt_entry(dt, entry, a, b) 96#endif /* CONFIG_PARAVIRT */
100#define write_idt_entry(dt, entry, a, b) write_dt_entry(dt, entry, a, b) 97
98static inline fastcall void native_set_ldt(const void *addr,
99 unsigned int entries)
100{
101 if (likely(entries == 0))
102 __asm__ __volatile__("lldt %w0"::"q" (0));
103 else {
104 unsigned cpu = smp_processor_id();
105 __u32 a, b;
106
107 pack_descriptor(&a, &b, (unsigned long)addr,
108 entries * sizeof(struct desc_struct) - 1,
109 DESCTYPE_LDT, 0);
110 write_gdt_entry(get_cpu_gdt_table(cpu), GDT_ENTRY_LDT, a, b);
111 __asm__ __volatile__("lldt %w0"::"q" (GDT_ENTRY_LDT*8));
112 }
113}
101 114
102static inline void _set_gate(int gate, unsigned int type, void *addr, unsigned short seg) 115static inline void _set_gate(int gate, unsigned int type, void *addr, unsigned short seg)
103{ 116{
@@ -115,14 +128,6 @@ static inline void __set_tss_desc(unsigned int cpu, unsigned int entry, const vo
115 write_gdt_entry(get_cpu_gdt_table(cpu), entry, a, b); 128 write_gdt_entry(get_cpu_gdt_table(cpu), entry, a, b);
116} 129}
117 130
118static inline void set_ldt_desc(unsigned int cpu, void *addr, unsigned int entries)
119{
120 __u32 a, b;
121 pack_descriptor(&a, &b, (unsigned long)addr,
122 entries * sizeof(struct desc_struct) - 1,
123 DESCTYPE_LDT, 0);
124 write_gdt_entry(get_cpu_gdt_table(cpu), GDT_ENTRY_LDT, a, b);
125}
126 131
127#define set_tss_desc(cpu,addr) __set_tss_desc(cpu, GDT_ENTRY_TSS, addr) 132#define set_tss_desc(cpu,addr) __set_tss_desc(cpu, GDT_ENTRY_TSS, addr)
128 133
@@ -153,35 +158,22 @@ static inline void set_ldt_desc(unsigned int cpu, void *addr, unsigned int entri
153 158
154static inline void clear_LDT(void) 159static inline void clear_LDT(void)
155{ 160{
156 int cpu = get_cpu(); 161 set_ldt(NULL, 0);
157
158 set_ldt_desc(cpu, &default_ldt[0], 5);
159 load_LDT_desc();
160 put_cpu();
161} 162}
162 163
163/* 164/*
164 * load one particular LDT into the current CPU 165 * load one particular LDT into the current CPU
165 */ 166 */
166static inline void load_LDT_nolock(mm_context_t *pc, int cpu) 167static inline void load_LDT_nolock(mm_context_t *pc)
167{ 168{
168 void *segments = pc->ldt; 169 set_ldt(pc->ldt, pc->size);
169 int count = pc->size;
170
171 if (likely(!count)) {
172 segments = &default_ldt[0];
173 count = 5;
174 }
175
176 set_ldt_desc(cpu, segments, count);
177 load_LDT_desc();
178} 170}
179 171
180static inline void load_LDT(mm_context_t *pc) 172static inline void load_LDT(mm_context_t *pc)
181{ 173{
182 int cpu = get_cpu(); 174 preempt_disable();
183 load_LDT_nolock(pc, cpu); 175 load_LDT_nolock(pc);
184 put_cpu(); 176 preempt_enable();
185} 177}
186 178
187static inline unsigned long get_desc_base(unsigned long *desc) 179static inline unsigned long get_desc_base(unsigned long *desc)
@@ -193,6 +185,29 @@ static inline unsigned long get_desc_base(unsigned long *desc)
193 return base; 185 return base;
194} 186}
195 187
188#else /* __ASSEMBLY__ */
189
190/*
191 * GET_DESC_BASE reads the descriptor base of the specified segment.
192 *
193 * Args:
194 * idx - descriptor index
195 * gdt - GDT pointer
196 * base - 32bit register to which the base will be written
197 * lo_w - lo word of the "base" register
198 * lo_b - lo byte of the "base" register
199 * hi_b - hi byte of the low word of the "base" register
200 *
201 * Example:
202 * GET_DESC_BASE(GDT_ENTRY_ESPFIX_SS, %ebx, %eax, %ax, %al, %ah)
203 * Will read the base address of GDT_ENTRY_ESPFIX_SS and put it into %eax.
204 */
205#define GET_DESC_BASE(idx, gdt, base, lo_w, lo_b, hi_b) \
206 movb idx*8+4(gdt), lo_b; \
207 movb idx*8+7(gdt), hi_b; \
208 shll $16, base; \
209 movw idx*8+2(gdt), lo_w;
210
196#endif /* !__ASSEMBLY__ */ 211#endif /* !__ASSEMBLY__ */
197 212
198#endif 213#endif