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