1#ifndef __ARCH_DESC_H 2#define __ARCH_DESC_H 3 4#include <asm/ldt.h> 5 6/* 7 * The layout of the GDT under Linux: 8 * 9 * 0 - null 10 * 1 - not used 11 * 2 - kernel code segment 12 * 3 - kernel data segment 13 * 4 - user code segment <-- new cacheline 14 * 5 - user data segment 15 * 6 - not used 16 * 7 - not used 17 * 8 - APM BIOS support <-- new cacheline 18 * 9 - APM BIOS support 19 * 10 - APM BIOS support 20 * 11 - APM BIOS support 21 * 22 * The TSS+LDT descriptors are spread out a bit so that every CPU 23 * has an exclusive cacheline for the per-CPU TSS and LDT: 24 * 25 * 12 - CPU#0 TSS <-- new cacheline 26 * 13 - CPU#0 LDT 27 * 14 - not used 28 * 15 - not used 29 * 16 - CPU#1 TSS <-- new cacheline 30 * 17 - CPU#1 LDT 31 * 18 - not used 32 * 19 - not used 33 * ... NR_CPUS per-CPU TSS+LDT's if on SMP 34 * 35 * Entry into gdt where to find first TSS. 36 */ 37#define __FIRST_TSS_ENTRY 12 38#define __FIRST_LDT_ENTRY (__FIRST_TSS_ENTRY+1) 39 40#define __TSS(n) (((n)<<2) + __FIRST_TSS_ENTRY) 41#define __LDT(n) (((n)<<2) + __FIRST_LDT_ENTRY) 42 43#ifndef __ASSEMBLY__ 44struct desc_struct { 45 unsigned long a,b; 46}; 47 48extern struct desc_struct gdt_table[]; 49extern struct desc_struct *idt, *gdt; 50 51struct Xgt_desc_struct { 52 unsigned short size; 53 unsigned long address __attribute__((packed)); 54}; 55 56#define idt_descr (*(struct Xgt_desc_struct *)((char *)&idt - 2)) 57#define gdt_descr (*(struct Xgt_desc_struct *)((char *)&gdt - 2)) 58 59#define load_TR(n) __asm__ __volatile__("ltr %%ax"::"a" (__TSS(n)<<3)) 60 61#define __load_LDT(n) __asm__ __volatile__("lldt %%ax"::"a" (__LDT(n)<<3)) 62 63/* 64 * This is the ldt that every process will get unless we need 65 * something other than this. 66 */ 67extern struct desc_struct default_ldt[]; 68extern void set_intr_gate(unsigned int irq, void * addr); 69extern void set_ldt_desc(unsigned int n, void *addr, unsigned int size); 70extern void set_tss_desc(unsigned int n, void *addr); 71 72static inline void clear_LDT(void) 73{ 74 int cpu = smp_processor_id(); 75 set_ldt_desc(cpu, &default_ldt[0], 5); 76 __load_LDT(cpu); 77} 78 79/* 80 * load one particular LDT into the current CPU 81 */ 82static inline void load_LDT (struct mm_struct *mm) 83{ 84 int cpu = smp_processor_id(); 85 void *segments = mm->context.segments; 86 int count = LDT_ENTRIES; 87 88 if (!segments) { 89 segments = &default_ldt[0]; 90 count = 5; 91 } 92 93 set_ldt_desc(cpu, segments, count); 94 __load_LDT(cpu); 95} 96 97#endif /* !__ASSEMBLY__ */ 98 99#endif 100