enable floppy module generation for boot cd
[linux-2.6.git] / arch / i386 / kernel / ldt.c
1 /*
2  * linux/kernel/ldt.c
3  *
4  * Copyright (C) 1992 Krishna Balasubramanian and Linus Torvalds
5  * Copyright (C) 1999, 2003 Ingo Molnar <mingo@redhat.com>
6  */
7
8 #include <linux/errno.h>
9 #include <linux/sched.h>
10 #include <linux/string.h>
11 #include <linux/mm.h>
12 #include <linux/smp.h>
13 #include <linux/smp_lock.h>
14 #include <linux/vmalloc.h>
15 #include <linux/slab.h>
16
17 #include <asm/uaccess.h>
18 #include <asm/system.h>
19 #include <asm/ldt.h>
20 #include <asm/desc.h>
21 #include <linux/highmem.h>
22 #include <asm/atomic_kmap.h>
23
24 #ifdef CONFIG_SMP /* avoids "defined but not used" warnig */
25 static void flush_ldt(void *null)
26 {
27         if (current->active_mm)
28                 load_LDT(&current->active_mm->context);
29 }
30 #endif
31
32 static int alloc_ldt(mm_context_t *pc, int mincount, int reload)
33 {
34         int oldsize, newsize, i;
35
36         if (mincount <= pc->size)
37                 return 0;
38         /*
39          * LDT got larger - reallocate if necessary.
40          */
41         oldsize = pc->size;
42         mincount = (mincount+511)&(~511);
43         newsize = mincount*LDT_ENTRY_SIZE;
44         for (i = 0; i < newsize; i += PAGE_SIZE) {
45                 int nr = i/PAGE_SIZE;
46                 BUG_ON(i >= 64*1024);
47                 if (!pc->ldt_pages[nr]) {
48                         pc->ldt_pages[nr] = alloc_page(GFP_HIGHUSER);
49                         if (!pc->ldt_pages[nr])
50                                 return -ENOMEM;
51                         clear_highpage(pc->ldt_pages[nr]);
52                 }
53         }
54         pc->size = mincount;
55         if (reload) {
56 #ifdef CONFIG_SMP
57                 cpumask_t mask;
58
59                 preempt_disable();
60                 load_LDT(pc);
61                 mask = cpumask_of_cpu(smp_processor_id());
62                 if (!cpus_equal(current->mm->cpu_vm_mask, mask))
63                         smp_call_function(flush_ldt, NULL, 1, 1);
64                 preempt_enable();
65 #else
66                 load_LDT(pc);
67 #endif
68         }
69         return 0;
70 }
71
72 static inline int copy_ldt(mm_context_t *new, mm_context_t *old)
73 {
74         int i, err, size = old->size, nr_pages = (size*LDT_ENTRY_SIZE + PAGE_SIZE-1)/PAGE_SIZE;
75
76         err = alloc_ldt(new, size, 0);
77         if (err < 0) {
78                 new->size = 0;
79                 return err;
80         }
81         for (i = 0; i < nr_pages; i++)
82                 copy_user_highpage(new->ldt_pages[i], old->ldt_pages[i], 0);
83         return 0;
84 }
85
86 /*
87  * we do not have to muck with descriptors here, that is
88  * done in switch_mm() as needed.
89  */
90 int init_new_context(struct task_struct *tsk, struct mm_struct *mm)
91 {
92         struct mm_struct * old_mm;
93         int retval = 0;
94
95         init_MUTEX(&mm->context.sem);
96         mm->context.size = 0;
97         memset(mm->context.ldt_pages, 0, sizeof(struct page *) * MAX_LDT_PAGES);
98         old_mm = current->mm;
99         if (old_mm && old_mm->context.size > 0) {
100                 down(&old_mm->context.sem);
101                 retval = copy_ldt(&mm->context, &old_mm->context);
102                 up(&old_mm->context.sem);
103         }
104         return retval;
105 }
106
107 /*
108  * No need to lock the MM as we are the last user
109  * Do not touch the ldt register, we are already
110  * in the next thread.
111  */
112 void destroy_context(struct mm_struct *mm)
113 {
114         int i, nr_pages = (mm->context.size*LDT_ENTRY_SIZE + PAGE_SIZE-1) / PAGE_SIZE;
115
116         for (i = 0; i < nr_pages; i++)
117                 __free_page(mm->context.ldt_pages[i]);
118         mm->context.size = 0;
119 }
120
121 static int read_ldt(void __user * ptr, unsigned long bytecount)
122 {
123         int err, i;
124         unsigned long size;
125         struct mm_struct * mm = current->mm;
126
127         if (!mm->context.size)
128                 return 0;
129         if (bytecount > LDT_ENTRY_SIZE*LDT_ENTRIES)
130                 bytecount = LDT_ENTRY_SIZE*LDT_ENTRIES;
131
132         down(&mm->context.sem);
133         size = mm->context.size*LDT_ENTRY_SIZE;
134         if (size > bytecount)
135                 size = bytecount;
136
137         err = 0;
138         /*
139          * This is necessary just in case we got here straight from a
140          * context-switch where the ptes were set but no tlb flush
141          * was done yet. We rather avoid doing a TLB flush in the
142          * context-switch path and do it here instead.
143          */
144         __flush_tlb_global();
145
146         for (i = 0; i < size; i += PAGE_SIZE) {
147                 int nr = i / PAGE_SIZE, bytes;
148                 char *kaddr = kmap(mm->context.ldt_pages[nr]);
149
150                 bytes = size - i;
151                 if (bytes > PAGE_SIZE)
152                         bytes = PAGE_SIZE;
153                 if (copy_to_user(ptr + i, kaddr, bytes))
154                         err = -EFAULT;
155                 kunmap(mm->context.ldt_pages[nr]);
156         }
157         up(&mm->context.sem);
158         if (err < 0)
159                 return err;
160         if (size != bytecount) {
161                 /* zero-fill the rest */
162                 clear_user(ptr+size, bytecount-size);
163         }
164         return bytecount;
165 }
166
167 static int read_default_ldt(void __user * ptr, unsigned long bytecount)
168 {
169         int err;
170         unsigned long size;
171         void *address;
172
173         err = 0;
174         address = &default_ldt[0];
175         size = 5*LDT_ENTRY_SIZE;
176         if (size > bytecount)
177                 size = bytecount;
178
179         err = size;
180         if (copy_to_user(ptr, address, size))
181                 err = -EFAULT;
182
183         return err;
184 }
185
186 static int write_ldt(void __user * ptr, unsigned long bytecount, int oldmode)
187 {
188         struct mm_struct * mm = current->mm;
189         __u32 entry_1, entry_2, *lp;
190         int error;
191         struct user_desc ldt_info;
192
193         error = -EINVAL;
194         if (bytecount != sizeof(ldt_info))
195                 goto out;
196         error = -EFAULT;        
197         if (copy_from_user(&ldt_info, ptr, sizeof(ldt_info)))
198                 goto out;
199
200         error = -EINVAL;
201         if (ldt_info.entry_number >= LDT_ENTRIES)
202                 goto out;
203         if (ldt_info.contents == 3) {
204                 if (oldmode)
205                         goto out;
206                 if (ldt_info.seg_not_present == 0)
207                         goto out;
208         }
209
210         down(&mm->context.sem);
211         if (ldt_info.entry_number >= mm->context.size) {
212                 error = alloc_ldt(&current->mm->context, ldt_info.entry_number+1, 1);
213                 if (error < 0)
214                         goto out_unlock;
215         }
216
217         /*
218          * No rescheduling allowed from this point to the install.
219          *
220          * We do a TLB flush for the same reason as in the read_ldt() path.
221          */
222         preempt_disable();
223         __flush_tlb_global();
224         lp = (__u32 *) ((ldt_info.entry_number << 3) +
225                         (char *) __kmap_atomic_vaddr(KM_LDT_PAGE0));
226
227         /* Allow LDTs to be cleared by the user. */
228         if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
229                 if (oldmode || LDT_empty(&ldt_info)) {
230                         entry_1 = 0;
231                         entry_2 = 0;
232                         goto install;
233                 }
234         }
235
236         entry_1 = LDT_entry_a(&ldt_info);
237         entry_2 = LDT_entry_b(&ldt_info);
238         if (oldmode)
239                 entry_2 &= ~(1 << 20);
240
241         /* Install the new entry ...  */
242 install:
243         *lp     = entry_1;
244         *(lp+1) = entry_2;
245         error = 0;
246         preempt_enable();
247
248 out_unlock:
249         up(&mm->context.sem);
250 out:
251         return error;
252 }
253
254 asmlinkage int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount)
255 {
256         int ret = -ENOSYS;
257
258         switch (func) {
259         case 0:
260                 ret = read_ldt(ptr, bytecount);
261                 break;
262         case 1:
263                 ret = write_ldt(ptr, bytecount, 1);
264                 break;
265         case 2:
266                 ret = read_default_ldt(ptr, bytecount);
267                 break;
268         case 0x11:
269                 ret = write_ldt(ptr, bytecount, 0);
270                 break;
271         }
272         return ret;
273 }
274
275 /*
276  * load one particular LDT into the current CPU
277  */
278 void load_LDT_nolock(mm_context_t *pc, int cpu)
279 {
280         struct page **pages = pc->ldt_pages;
281         int count = pc->size;
282         int nr_pages, i;
283
284         if (likely(!count)) {
285                 pages = &default_ldt_page;
286                 count = 5;
287         }
288         nr_pages = (count*LDT_ENTRY_SIZE + PAGE_SIZE-1) / PAGE_SIZE;
289
290         for (i = 0; i < nr_pages; i++) {
291                 __kunmap_atomic_type(KM_LDT_PAGE0 - i);
292                 __kmap_atomic(pages[i], KM_LDT_PAGE0 - i);
293         }
294         set_ldt_desc(cpu, (void *)__kmap_atomic_vaddr(KM_LDT_PAGE0), count);
295         load_LDT_desc();
296 }