Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Merge branch 'devel'
[palacios.git] / kitten / include / arch-x86_64 / desc.h
1 /* Written 2000 by Andi Kleen */ 
2 #ifndef _ARCH_DESC_H
3 #define _ARCH_DESC_H
4
5 #include <arch/ldt.h>
6
7 #ifndef __ASSEMBLY__
8
9 #include <lwk/string.h>
10 #include <lwk/smp.h>
11
12 #include <arch/segment.h>
13 #include <arch/mmu.h>
14
15 // 8 byte segment descriptor
16 struct desc_struct { 
17         u16 limit0;
18         u16 base0;
19         unsigned base1 : 8, type : 4, s : 1, dpl : 2, p : 1;
20         unsigned limit : 4, avl : 1, l : 1, d : 1, g : 1, base2 : 8;
21 } __attribute__((packed)); 
22
23 struct n_desc_struct { 
24         unsigned int a,b;
25 };      
26
27 extern struct desc_struct cpu_gdt_table[GDT_ENTRIES];
28
29 enum { 
30         GATE_INTERRUPT = 0xE, 
31         GATE_TRAP = 0xF,        
32         GATE_CALL = 0xC,
33 };      
34
35 /**
36  * Long-Mode Gate Descriptor (16-bytes)
37  */
38 struct gate_struct {          
39         uint16_t offset_low;    /* [15-0] of target code segment offset */
40         uint16_t segment;       /* Target code segment selector */
41         unsigned ist    : 3;    /* Interrupt-Stack-Table index into TSS */
42         unsigned zero0  : 5;
43         unsigned type   : 5;    /* Gate descriptor type */
44         unsigned dpl    : 2;    /* Privilege level */
45         unsigned p      : 1;    /* Present bit... in use? */
46         uint16_t offset_middle; /* [31-24] of target code segment offset */
47         uint32_t offset_high;   /* [63-32] of target code segment offset */
48         uint32_t zero1;
49 } __attribute__((packed));
50
51 #define PTR_LOW(x) ((unsigned long)(x) & 0xFFFF) 
52 #define PTR_MIDDLE(x) (((unsigned long)(x) >> 16) & 0xFFFF)
53 #define PTR_HIGH(x) ((unsigned long)(x) >> 32)
54
55 enum { 
56         DESC_TSS = 0x9,
57         DESC_LDT = 0x2,
58 }; 
59
60 // LDT or TSS descriptor in the GDT. 16 bytes.
61 struct ldttss_desc { 
62         u16 limit0;
63         u16 base0;
64         unsigned base1 : 8, type : 5, dpl : 2, p : 1;
65         unsigned limit1 : 4, zero0 : 3, g : 1, base2 : 8;
66         u32 base3;
67         u32 zero1; 
68 } __attribute__((packed)); 
69
70 struct desc_ptr {
71         unsigned short size;
72         unsigned long address;
73 } __attribute__((packed)) ;
74
75 #define load_TR_desc() asm volatile("ltr %w0"::"r" (GDT_ENTRY_TSS*8))
76 #define load_LDT_desc() asm volatile("lldt %w0"::"r" (GDT_ENTRY_LDT*8))
77 #define clear_LDT()  asm volatile("lldt %w0"::"r" (0))
78
79 /*
80  * This is the ldt that every process will get unless we need
81  * something other than this.
82  */
83 extern struct desc_struct default_ldt[];
84 extern struct gate_struct idt_table[]; 
85 extern struct desc_ptr cpu_gdt_descr[];
86
87 /* the cpu gdt accessor */
88 #define cpu_gdt(_cpu) ((struct desc_struct *)cpu_gdt_descr[_cpu].address)
89
90 /**
91  * Installs a Long-Mode gate descriptor.
92  */
93 static inline void
94 _set_gate(
95         void *        adr,      /* Address to install gate descriptor at */
96         unsigned      type,     /* Type of gate */
97         unsigned long func,     /* The handler function for the gate */
98         unsigned      dpl,      /* Privilege level */
99         unsigned      ist       /* Interupt-Stack-Table index */
100 )  
101 {
102         struct gate_struct s;   
103         s.offset_low = PTR_LOW(func); 
104         s.segment = __KERNEL_CS;
105         s.ist = ist; 
106         s.p = 1;
107         s.dpl = dpl; 
108         s.zero0 = 0;
109         s.zero1 = 0; 
110         s.type = type; 
111         s.offset_middle = PTR_MIDDLE(func); 
112         s.offset_high = PTR_HIGH(func); 
113         /* does not need to be atomic because it is only done once at setup time */ 
114         memcpy(adr, &s, 16); 
115
116
117 /**
118  * Installs an interrupt gate.
119  * The interrupt will execute on the normal kernel stack.
120  */
121 static inline void
122 set_intr_gate(int nr, void *func) 
123
124         BUG_ON((unsigned)nr > 0xFF);
125         _set_gate(&idt_table[nr], GATE_INTERRUPT, (unsigned long) func, 0, 0); 
126
127
128 /**
129  * Installs an interrupt gate.
130  * The interrupt will execute on the stack specified by the 'ist' argument.
131  */
132 static inline void set_intr_gate_ist(int nr, void *func, unsigned ist) 
133
134         BUG_ON((unsigned)nr > 0xFF);
135         _set_gate(&idt_table[nr], GATE_INTERRUPT, (unsigned long) func, 0, ist); 
136
137
138 /**
139  * Installs a system interrupt gate.
140  * The privilege level is set to 3, meaning that user-mode can trigger it.
141  */
142 static inline void set_system_gate(int nr, void *func) 
143
144         BUG_ON((unsigned)nr > 0xFF);
145         _set_gate(&idt_table[nr], GATE_INTERRUPT, (unsigned long) func, 3, 0); 
146
147
148 /**
149  * Installs a system interrupt gate.
150  * The privilege level is set to 3, meaning that user-mode can trigger it.
151  * The interrupt will execute on the stack specified by the 'ist' argument.
152  */
153 static inline void set_system_gate_ist(int nr, void *func, unsigned ist)
154 {
155         _set_gate(&idt_table[nr], GATE_INTERRUPT, (unsigned long) func, 3, ist);
156 }
157
158 static inline void set_tssldt_descriptor(void *ptr, unsigned long tss, unsigned type, 
159                                          unsigned size) 
160
161         struct ldttss_desc d;
162         memset(&d,0,sizeof(d)); 
163         d.limit0 = size & 0xFFFF;
164         d.base0 = PTR_LOW(tss); 
165         d.base1 = PTR_MIDDLE(tss) & 0xFF; 
166         d.type = type;
167         d.p = 1; 
168         d.limit1 = (size >> 16) & 0xF;
169         d.base2 = (PTR_MIDDLE(tss) >> 8) & 0xFF; 
170         d.base3 = PTR_HIGH(tss); 
171         memcpy(ptr, &d, 16); 
172 }
173
174 static inline void set_tss_desc(unsigned cpu, void *addr)
175
176         /*
177          * sizeof(unsigned long) coming from an extra "long" at the end
178          * of the iobitmap. See tss_struct definition in processor.h
179          *
180          * -1? seg base+limit should be pointing to the address of the
181          * last valid byte
182          */
183         set_tssldt_descriptor(&cpu_gdt(cpu)[GDT_ENTRY_TSS],
184                 (unsigned long)addr, DESC_TSS,
185                 IO_BITMAP_OFFSET + IO_BITMAP_BYTES + sizeof(unsigned long) - 1);
186
187
188 static inline void set_ldt_desc(unsigned cpu, void *addr, int size)
189
190         set_tssldt_descriptor(&cpu_gdt(cpu)[GDT_ENTRY_LDT], (unsigned long)addr,
191                               DESC_LDT, size * 8 - 1);
192 }
193
194 static inline void set_seg_base(unsigned cpu, int entry, void *base)
195
196         struct desc_struct *d = &cpu_gdt(cpu)[entry];
197         u32 addr = (u32)(u64)base;
198         BUG_ON((u64)base >> 32); 
199         d->base0 = addr & 0xffff;
200         d->base1 = (addr >> 16) & 0xff;
201         d->base2 = (addr >> 24) & 0xff;
202
203
204 #define LDT_entry_a(info) \
205         ((((info)->base_addr & 0x0000ffff) << 16) | ((info)->limit & 0x0ffff))
206 /* Don't allow setting of the lm bit. It is useless anyways because 
207    64bit system calls require __USER_CS. */ 
208 #define LDT_entry_b(info) \
209         (((info)->base_addr & 0xff000000) | \
210         (((info)->base_addr & 0x00ff0000) >> 16) | \
211         ((info)->limit & 0xf0000) | \
212         (((info)->read_exec_only ^ 1) << 9) | \
213         ((info)->contents << 10) | \
214         (((info)->seg_not_present ^ 1) << 15) | \
215         ((info)->seg_32bit << 22) | \
216         ((info)->limit_in_pages << 23) | \
217         ((info)->useable << 20) | \
218         /* ((info)->lm << 21) | */ \
219         0x7000)
220
221 #define LDT_empty(info) (\
222         (info)->base_addr       == 0    && \
223         (info)->limit           == 0    && \
224         (info)->contents        == 0    && \
225         (info)->read_exec_only  == 1    && \
226         (info)->seg_32bit       == 0    && \
227         (info)->limit_in_pages  == 0    && \
228         (info)->seg_not_present == 1    && \
229         (info)->useable         == 0    && \
230         (info)->lm              == 0)
231
232 #if TLS_SIZE != 24
233 # error update this code.
234 #endif
235
236 static inline void load_TLS(struct thread_struct *t, unsigned int cpu)
237 {
238         u64 *gdt = (u64 *)(cpu_gdt(cpu) + GDT_ENTRY_TLS_MIN);
239         gdt[0] = t->tls_array[0];
240         gdt[1] = t->tls_array[1];
241         gdt[2] = t->tls_array[2];
242
243
244 /*
245  * load one particular LDT into the current CPU
246  */
247 static inline void load_LDT_nolock (mm_context_t *pc, int cpu)
248 {
249         int count = pc->size;
250
251         if (likely(!count)) {
252                 clear_LDT();
253                 return;
254         }
255                 
256         set_ldt_desc(cpu, pc->ldt, count);
257         load_LDT_desc();
258 }
259
260 static inline void load_LDT(mm_context_t *pc)
261 {
262         int cpu = get_cpu();
263         load_LDT_nolock(pc, cpu);
264         put_cpu();
265 }
266
267 extern struct desc_ptr idt_descr;
268
269 #endif /* !__ASSEMBLY__ */
270
271 #endif