5 #include <asm/segment.h>
6 #include <asm/desc_defs.h>
10 #include <linux/preempt.h>
11 #include <linux/smp.h>
12 #include <linux/percpu.h>
16 struct desc_struct gdt[GDT_ENTRIES];
17 } __attribute__((aligned(PAGE_SIZE)));
18 DECLARE_PER_CPU(struct gdt_page, gdt_page);
20 static inline struct desc_struct *get_cpu_gdt_table(unsigned int cpu)
22 return per_cpu(gdt_page, cpu).gdt;
25 extern void set_intr_gate(unsigned int irq, void * addr);
27 static inline void pack_descriptor(struct desc_struct *desc,
28 unsigned long base, unsigned long limit, unsigned char type, unsigned char flags)
30 desc->a = ((base & 0xffff) << 16) | (limit & 0xffff);
31 desc->b = (base & 0xff000000) | ((base & 0xff0000) >> 16) |
32 (limit & 0x000f0000) | ((type & 0xff) << 8) | ((flags & 0xf) << 20);
36 static inline void pack_gate(gate_desc *gate,
37 unsigned long base, unsigned short seg, unsigned char type, unsigned char flags)
39 gate->a = (seg << 16) | (base & 0xffff);
40 gate->b = (base & 0xffff0000) | ((type & 0xff) << 8) | (flags & 0xff);
43 #ifdef CONFIG_PARAVIRT
44 #include <asm/paravirt.h>
46 #define load_TR_desc() native_load_tr_desc()
47 #define load_gdt(dtr) native_load_gdt(dtr)
48 #define load_idt(dtr) native_load_idt(dtr)
49 #define load_tr(tr) __asm__ __volatile("ltr %0"::"m" (tr))
50 #define load_ldt(ldt) __asm__ __volatile("lldt %0"::"m" (ldt))
52 #define store_gdt(dtr) native_store_gdt(dtr)
53 #define store_idt(dtr) native_store_idt(dtr)
54 #define store_tr(tr) (tr = native_store_tr())
55 #define store_ldt(ldt) __asm__ ("sldt %0":"=m" (ldt))
57 #define load_TLS(t, cpu) native_load_tls(t, cpu)
58 #define set_ldt native_set_ldt
60 #define write_ldt_entry(dt, entry, desc) \
61 native_write_ldt_entry(dt, entry, desc)
62 #define write_gdt_entry(dt, entry, desc, type) \
63 native_write_gdt_entry(dt, entry, desc, type)
64 #define write_idt_entry(dt, entry, g) native_write_idt_entry(dt, entry, g)
67 static inline void native_write_ldt_entry(struct desc_struct *ldt, int entry,
70 memcpy(&ldt[entry], desc, sizeof(struct desc_struct));
73 static inline void native_write_idt_entry(gate_desc *idt, int entry,
74 const gate_desc *gate)
76 memcpy(&idt[entry], gate, sizeof(*gate));
79 static inline void native_write_gdt_entry(struct desc_struct *gdt, int entry,
80 const void *desc, int type)
82 memcpy(&gdt[entry], desc, sizeof(struct desc_struct));
85 static inline void write_dt_entry(struct desc_struct *dt,
86 int entry, u32 entry_low, u32 entry_high)
88 dt[entry].a = entry_low;
89 dt[entry].b = entry_high;
93 static inline void native_set_ldt(const void *addr, unsigned int entries)
95 if (likely(entries == 0))
96 __asm__ __volatile__("lldt %w0"::"q" (0));
98 unsigned cpu = smp_processor_id();
101 pack_descriptor(&ldt, (unsigned long)addr,
102 entries * sizeof(struct desc_struct) - 1,
104 write_gdt_entry(get_cpu_gdt_table(cpu), GDT_ENTRY_LDT,
106 __asm__ __volatile__("lldt %w0"::"q" (GDT_ENTRY_LDT*8));
111 static inline void native_load_tr_desc(void)
113 asm volatile("ltr %w0"::"q" (GDT_ENTRY_TSS*8));
116 static inline void native_load_gdt(const struct desc_ptr *dtr)
118 asm volatile("lgdt %0"::"m" (*dtr));
121 static inline void native_load_idt(const struct desc_ptr *dtr)
123 asm volatile("lidt %0"::"m" (*dtr));
126 static inline void native_store_gdt(struct desc_ptr *dtr)
128 asm ("sgdt %0":"=m" (*dtr));
131 static inline void native_store_idt(struct desc_ptr *dtr)
133 asm ("sidt %0":"=m" (*dtr));
136 static inline unsigned long native_store_tr(void)
139 asm ("str %0":"=r" (tr));
143 static inline void native_load_tls(struct thread_struct *t, unsigned int cpu)
146 struct desc_struct *gdt = get_cpu_gdt_table(cpu);
148 for (i = 0; i < GDT_ENTRY_TLS_ENTRIES; i++)
149 gdt[GDT_ENTRY_TLS_MIN + i] = t->tls_array[i];
152 static inline void _set_gate(int gate, unsigned int type, void *addr, unsigned short seg)
155 pack_gate(&g, (unsigned long)addr, seg, type, 0);
156 write_idt_entry(idt_table, gate, &g);
159 static inline void __set_tss_desc(unsigned int cpu, unsigned int entry, const void *addr)
162 pack_descriptor(&tss, (unsigned long)addr,
163 offsetof(struct tss_struct, __cacheline_filler) - 1,
165 write_gdt_entry(get_cpu_gdt_table(cpu), entry, &tss, DESC_TSS);
169 #define set_tss_desc(cpu,addr) __set_tss_desc(cpu, GDT_ENTRY_TSS, addr)
171 #endif /* !__ASSEMBLY__ */