~ubuntu-branches/ubuntu/utopic/xen/utopic

« back to all changes in this revision

Viewing changes to xenolinux-2.4.25-sparse/arch/xeno/kernel/traps.c

  • Committer: Bazaar Package Importer
  • Author(s): Bastian Blank
  • Date: 2010-05-06 15:47:38 UTC
  • mto: (1.3.1) (15.1.1 sid) (4.1.1 experimental)
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: james.westby@ubuntu.com-20100506154738-agoz0rlafrh1fnq7
Tags: upstream-4.0.0
ImportĀ upstreamĀ versionĀ 4.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 *  linux/arch/i386/traps.c
3
 
 *
4
 
 *  Copyright (C) 1991, 1992  Linus Torvalds
5
 
 *
6
 
 *  Pentium III FXSR, SSE support
7
 
 *      Gareth Hughes <gareth@valinux.com>, May 2000
8
 
 */
9
 
 
10
 
/*
11
 
 * 'Traps.c' handles hardware traps and faults after we have saved some
12
 
 * state in 'asm.s'.
13
 
 */
14
 
#include <linux/config.h>
15
 
#include <linux/sched.h>
16
 
#include <linux/kernel.h>
17
 
#include <linux/string.h>
18
 
#include <linux/errno.h>
19
 
#include <linux/ptrace.h>
20
 
#include <linux/timer.h>
21
 
#include <linux/mm.h>
22
 
#include <linux/init.h>
23
 
#include <linux/delay.h>
24
 
#include <linux/spinlock.h>
25
 
#include <linux/interrupt.h>
26
 
#include <linux/highmem.h>
27
 
 
28
 
#include <asm/system.h>
29
 
#include <asm/uaccess.h>
30
 
#include <asm/io.h>
31
 
#include <asm/atomic.h>
32
 
#include <asm/debugreg.h>
33
 
#include <asm/desc.h>
34
 
#include <asm/i387.h>
35
 
 
36
 
#include <asm/smp.h>
37
 
#include <asm/pgalloc.h>
38
 
 
39
 
#include <asm/hypervisor.h>
40
 
 
41
 
#include <linux/irq.h>
42
 
#include <linux/module.h>
43
 
 
44
 
asmlinkage int system_call(void);
45
 
asmlinkage void lcall7(void);
46
 
asmlinkage void lcall27(void);
47
 
 
48
 
asmlinkage void divide_error(void);
49
 
asmlinkage void debug(void);
50
 
asmlinkage void int3(void);
51
 
asmlinkage void overflow(void);
52
 
asmlinkage void bounds(void);
53
 
asmlinkage void invalid_op(void);
54
 
asmlinkage void device_not_available(void);
55
 
asmlinkage void double_fault(void);
56
 
asmlinkage void coprocessor_segment_overrun(void);
57
 
asmlinkage void invalid_TSS(void);
58
 
asmlinkage void segment_not_present(void);
59
 
asmlinkage void stack_segment(void);
60
 
asmlinkage void general_protection(void);
61
 
asmlinkage void page_fault(void);
62
 
asmlinkage void safe_page_fault(void);
63
 
asmlinkage void coprocessor_error(void);
64
 
asmlinkage void simd_coprocessor_error(void);
65
 
asmlinkage void alignment_check(void);
66
 
asmlinkage void spurious_interrupt_bug(void);
67
 
asmlinkage void machine_check(void);
68
 
 
69
 
int kstack_depth_to_print = 24;
70
 
 
71
 
 
72
 
/*
73
 
 * If the address is either in the .text section of the
74
 
 * kernel, or in the vmalloc'ed module regions, it *may* 
75
 
 * be the address of a calling routine
76
 
 */
77
 
 
78
 
#ifdef CONFIG_MODULES
79
 
 
80
 
extern struct module *module_list;
81
 
extern struct module kernel_module;
82
 
 
83
 
static inline int kernel_text_address(unsigned long addr)
84
 
{
85
 
        int retval = 0;
86
 
        struct module *mod;
87
 
 
88
 
        if (addr >= (unsigned long) &_stext &&
89
 
            addr <= (unsigned long) &_etext)
90
 
                return 1;
91
 
 
92
 
        for (mod = module_list; mod != &kernel_module; mod = mod->next) {
93
 
                /* mod_bound tests for addr being inside the vmalloc'ed
94
 
                 * module area. Of course it'd be better to test only
95
 
                 * for the .text subset... */
96
 
                if (mod_bound(addr, 0, mod)) {
97
 
                        retval = 1;
98
 
                        break;
99
 
                }
100
 
        }
101
 
 
102
 
        return retval;
103
 
}
104
 
 
105
 
#else
106
 
 
107
 
static inline int kernel_text_address(unsigned long addr)
108
 
{
109
 
        return (addr >= (unsigned long) &_stext &&
110
 
                addr <= (unsigned long) &_etext);
111
 
}
112
 
 
113
 
#endif
114
 
 
115
 
void show_trace(unsigned long * stack)
116
 
{
117
 
        int i;
118
 
        unsigned long addr;
119
 
 
120
 
        if (!stack)
121
 
                stack = (unsigned long*)&stack;
122
 
 
123
 
        printk("Call Trace: ");
124
 
        i = 1;
125
 
        while (((long) stack & (THREAD_SIZE-1)) != 0) {
126
 
                addr = *stack++;
127
 
                if (kernel_text_address(addr)) {
128
 
                        if (i && ((i % 6) == 0))
129
 
                                printk("\n   ");
130
 
                        printk("[<%08lx>] ", addr);
131
 
                        i++;
132
 
                }
133
 
        }
134
 
        printk("\n");
135
 
}
136
 
 
137
 
void show_trace_task(struct task_struct *tsk)
138
 
{
139
 
        unsigned long esp = tsk->thread.esp;
140
 
 
141
 
        /* User space on another CPU? */
142
 
        if ((esp ^ (unsigned long)tsk) & (PAGE_MASK<<1))
143
 
                return;
144
 
        show_trace((unsigned long *)esp);
145
 
}
146
 
 
147
 
void show_stack(unsigned long * esp)
148
 
{
149
 
        unsigned long *stack;
150
 
        int i;
151
 
 
152
 
        // debugging aid: "show_stack(NULL);" prints the
153
 
        // back trace for this cpu.
154
 
 
155
 
        if(esp==NULL)
156
 
                esp=(unsigned long*)&esp;
157
 
 
158
 
        stack = esp;
159
 
        for(i=0; i < kstack_depth_to_print; i++) {
160
 
                if (((long) stack & (THREAD_SIZE-1)) == 0)
161
 
                        break;
162
 
                if (i && ((i % 8) == 0))
163
 
                        printk("\n       ");
164
 
                printk("%08lx ", *stack++);
165
 
        }
166
 
        printk("\n");
167
 
        show_trace(esp);
168
 
}
169
 
 
170
 
void show_registers(struct pt_regs *regs)
171
 
{
172
 
        int in_kernel = 1;
173
 
        unsigned long esp;
174
 
        unsigned short ss;
175
 
 
176
 
        esp = (unsigned long) (&regs->esp);
177
 
        ss = __KERNEL_DS;
178
 
        if (regs->xcs & 2) {
179
 
                in_kernel = 0;
180
 
                esp = regs->esp;
181
 
                ss = regs->xss & 0xffff;
182
 
        }
183
 
        printk(KERN_ALERT "CPU:    %d\n", smp_processor_id() );
184
 
        printk(KERN_ALERT "EIP:    %04x:[<%08lx>]    %s\n",
185
 
               0xffff & regs->xcs, regs->eip, print_tainted());
186
 
        printk(KERN_ALERT "EFLAGS: %08lx\n",regs->eflags);
187
 
        printk(KERN_ALERT "eax: %08lx   ebx: %08lx   ecx: %08lx   edx: %08lx\n",
188
 
                regs->eax, regs->ebx, regs->ecx, regs->edx);
189
 
        printk(KERN_ALERT "esi: %08lx   edi: %08lx   ebp: %08lx   esp: %08lx\n",
190
 
                regs->esi, regs->edi, regs->ebp, esp);
191
 
        printk(KERN_ALERT "ds: %04x   es: %04x   ss: %04x\n",
192
 
                regs->xds & 0xffff, regs->xes & 0xffff, ss);
193
 
        printk(KERN_ALERT "Process %s (pid: %d, stackpage=%08lx)",
194
 
                current->comm, current->pid, 4096+(unsigned long)current);
195
 
        /*
196
 
         * When in-kernel, we also print out the stack and code at the
197
 
         * time of the fault..
198
 
         */
199
 
        if (in_kernel) {
200
 
 
201
 
                printk(KERN_ALERT "\nStack: ");
202
 
                show_stack((unsigned long*)esp);
203
 
 
204
 
#if 0
205
 
                {
206
 
                        int i;
207
 
                        printk(KERN_ALERT "\nCode: ");
208
 
                        if(regs->eip < PAGE_OFFSET)
209
 
                                goto bad;
210
 
 
211
 
                        for(i=0;i<20;i++)
212
 
                        {
213
 
                                unsigned char c;
214
 
                                if(__get_user(c, &((unsigned char*)regs->eip)[i])) {
215
 
bad:
216
 
                                        printk(KERN_ALERT " Bad EIP value.");
217
 
                                        break;
218
 
                                }
219
 
                                printk("%02x ", c);
220
 
                        }
221
 
                }
222
 
#endif
223
 
        }
224
 
        printk(KERN_ALERT "\n");
225
 
}       
226
 
 
227
 
spinlock_t die_lock = SPIN_LOCK_UNLOCKED;
228
 
 
229
 
void die(const char * str, struct pt_regs * regs, long err)
230
 
{
231
 
        console_verbose();
232
 
        spin_lock_irq(&die_lock);
233
 
        bust_spinlocks(1);
234
 
        printk("%s: %04lx\n", str, err & 0xffff);
235
 
        show_registers(regs);
236
 
        bust_spinlocks(0);
237
 
        spin_unlock_irq(&die_lock);
238
 
        do_exit(SIGSEGV);
239
 
}
240
 
 
241
 
static inline void die_if_kernel(const char * str, struct pt_regs * regs, long err)
242
 
{
243
 
        if (!(2 & regs->xcs))
244
 
                die(str, regs, err);
245
 
}
246
 
 
247
 
 
248
 
static void inline do_trap(int trapnr, int signr, char *str,
249
 
                           struct pt_regs * regs, long error_code,
250
 
                           siginfo_t *info)
251
 
{
252
 
        if (!(regs->xcs & 2))
253
 
                goto kernel_trap;
254
 
 
255
 
        /*trap_signal:*/ {
256
 
                struct task_struct *tsk = current;
257
 
                tsk->thread.error_code = error_code;
258
 
                tsk->thread.trap_no = trapnr;
259
 
                if (info)
260
 
                        force_sig_info(signr, info, tsk);
261
 
                else
262
 
                        force_sig(signr, tsk);
263
 
                return;
264
 
        }
265
 
 
266
 
        kernel_trap: {
267
 
                unsigned long fixup = search_exception_table(regs->eip);
268
 
                if (fixup)
269
 
                        regs->eip = fixup;
270
 
                else    
271
 
                        die(str, regs, error_code);
272
 
                return;
273
 
        }
274
 
}
275
 
 
276
 
#define DO_ERROR(trapnr, signr, str, name) \
277
 
asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
278
 
{ \
279
 
        do_trap(trapnr, signr, str, regs, error_code, NULL); \
280
 
}
281
 
 
282
 
#define DO_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr) \
283
 
asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
284
 
{ \
285
 
        siginfo_t info; \
286
 
        info.si_signo = signr; \
287
 
        info.si_errno = 0; \
288
 
        info.si_code = sicode; \
289
 
        info.si_addr = (void *)siaddr; \
290
 
        do_trap(trapnr, signr, str, regs, error_code, &info); \
291
 
}
292
 
 
293
 
DO_ERROR_INFO( 0, SIGFPE,  "divide error", divide_error, FPE_INTDIV, regs->eip)
294
 
DO_ERROR( 3, SIGTRAP, "int3", int3)
295
 
DO_ERROR( 4, SIGSEGV, "overflow", overflow)
296
 
DO_ERROR( 5, SIGSEGV, "bounds", bounds)
297
 
DO_ERROR_INFO( 6, SIGILL,  "invalid operand", invalid_op, ILL_ILLOPN, regs->eip)
298
 
DO_ERROR( 7, SIGSEGV, "device not available", device_not_available)
299
 
DO_ERROR( 8, SIGSEGV, "double fault", double_fault)
300
 
DO_ERROR( 9, SIGFPE,  "coprocessor segment overrun", coprocessor_segment_overrun)
301
 
DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS)
302
 
DO_ERROR(11, SIGBUS,  "segment not present", segment_not_present)
303
 
DO_ERROR(12, SIGBUS,  "stack segment", stack_segment)
304
 
DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0)
305
 
DO_ERROR(18, SIGBUS, "machine check", machine_check)
306
 
 
307
 
asmlinkage void do_general_protection(struct pt_regs * regs, long error_code)
308
 
{
309
 
        /*
310
 
         * If we trapped on an LDT access then ensure that the default_ldt is
311
 
         * loaded, if nothing else. We load default_ldt lazily because LDT
312
 
         * switching costs time and many applications don't need it.
313
 
         */
314
 
        if ( unlikely((error_code & 6) == 4) )
315
 
        {
316
 
                unsigned long ldt;
317
 
                __asm__ __volatile__ ( "sldt %0" : "=r" (ldt) );
318
 
                if ( ldt == 0 )
319
 
                {
320
 
                        mmu_update_t u;
321
 
                        u.ptr  = MMU_EXTENDED_COMMAND;
322
 
                        u.ptr |= (unsigned long)&default_ldt[0];
323
 
                        u.val  = MMUEXT_SET_LDT | (5 << MMUEXT_CMD_SHIFT);
324
 
                        HYPERVISOR_mmu_update(&u, 1);
325
 
                        return;
326
 
                }
327
 
        }
328
 
 
329
 
        if (!(regs->xcs & 2))
330
 
                goto gp_in_kernel;
331
 
 
332
 
        current->thread.error_code = error_code;
333
 
        current->thread.trap_no = 13;
334
 
        force_sig(SIGSEGV, current);
335
 
        return;
336
 
 
337
 
gp_in_kernel:
338
 
        {
339
 
                unsigned long fixup;
340
 
                fixup = search_exception_table(regs->eip);
341
 
                if (fixup) {
342
 
                        regs->eip = fixup;
343
 
                        return;
344
 
                }
345
 
                die("general protection fault", regs, error_code);
346
 
        }
347
 
}
348
 
 
349
 
 
350
 
asmlinkage void do_debug(struct pt_regs * regs, long error_code)
351
 
{
352
 
    unsigned int condition;
353
 
    struct task_struct *tsk = current;
354
 
    siginfo_t info;
355
 
 
356
 
    condition = HYPERVISOR_get_debugreg(6);
357
 
 
358
 
    /* Mask out spurious debug traps due to lazy DR7 setting */
359
 
    if (condition & (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)) {
360
 
        if (!tsk->thread.debugreg[7])
361
 
            goto clear_dr7;
362
 
    }
363
 
 
364
 
    /* Save debug status register where ptrace can see it */
365
 
    tsk->thread.debugreg[6] = condition;
366
 
 
367
 
    /* Mask out spurious TF errors due to lazy TF clearing */
368
 
    if (condition & DR_STEP) {
369
 
        /*
370
 
         * The TF error should be masked out only if the current
371
 
         * process is not traced and if the TRAP flag has been set
372
 
         * previously by a tracing process (condition detected by
373
 
         * the PT_DTRACE flag); remember that the i386 TRAP flag
374
 
         * can be modified by the process itself in user mode,
375
 
         * allowing programs to debug themselves without the ptrace()
376
 
         * interface.
377
 
         */
378
 
        if ((tsk->ptrace & (PT_DTRACE|PT_PTRACED)) == PT_DTRACE)
379
 
            goto clear_TF;
380
 
    }
381
 
 
382
 
    /* Ok, finally something we can handle */
383
 
    tsk->thread.trap_no = 1;
384
 
    tsk->thread.error_code = error_code;
385
 
    info.si_signo = SIGTRAP;
386
 
    info.si_errno = 0;
387
 
    info.si_code = TRAP_BRKPT;
388
 
        
389
 
    /* If this is a kernel mode trap, save the user PC on entry to 
390
 
     * the kernel, that's what the debugger can make sense of.
391
 
     */
392
 
    info.si_addr = ((regs->xcs & 2) == 0) ? (void *)tsk->thread.eip : 
393
 
                                            (void *)regs->eip;
394
 
    force_sig_info(SIGTRAP, &info, tsk);
395
 
 
396
 
    /* Disable additional traps. They'll be re-enabled when
397
 
     * the signal is delivered.
398
 
     */
399
 
 clear_dr7:
400
 
    HYPERVISOR_set_debugreg(7, 0);
401
 
    return;
402
 
 
403
 
 clear_TF:
404
 
    regs->eflags &= ~TF_MASK;
405
 
    return;
406
 
}
407
 
 
408
 
 
409
 
/*
410
 
 * Note that we play around with the 'TS' bit in an attempt to get
411
 
 * the correct behaviour even in the presence of the asynchronous
412
 
 * IRQ13 behaviour
413
 
 */
414
 
void math_error(void *eip)
415
 
{
416
 
        struct task_struct * task;
417
 
        siginfo_t info;
418
 
        unsigned short cwd, swd;
419
 
 
420
 
        /*
421
 
         * Save the info for the exception handler and clear the error.
422
 
         */
423
 
        task = current;
424
 
        save_init_fpu(task);
425
 
        task->thread.trap_no = 16;
426
 
        task->thread.error_code = 0;
427
 
        info.si_signo = SIGFPE;
428
 
        info.si_errno = 0;
429
 
        info.si_code = __SI_FAULT;
430
 
        info.si_addr = eip;
431
 
        /*
432
 
         * (~cwd & swd) will mask out exceptions that are not set to unmasked
433
 
         * status.  0x3f is the exception bits in these regs, 0x200 is the
434
 
         * C1 reg you need in case of a stack fault, 0x040 is the stack
435
 
         * fault bit.  We should only be taking one exception at a time,
436
 
         * so if this combination doesn't produce any single exception,
437
 
         * then we have a bad program that isn't syncronizing its FPU usage
438
 
         * and it will suffer the consequences since we won't be able to
439
 
         * fully reproduce the context of the exception
440
 
         */
441
 
        cwd = get_fpu_cwd(task);
442
 
        swd = get_fpu_swd(task);
443
 
        switch (((~cwd) & swd & 0x3f) | (swd & 0x240)) {
444
 
                case 0x000:
445
 
                default:
446
 
                        break;
447
 
                case 0x001: /* Invalid Op */
448
 
                case 0x040: /* Stack Fault */
449
 
                case 0x240: /* Stack Fault | Direction */
450
 
                        info.si_code = FPE_FLTINV;
451
 
                        break;
452
 
                case 0x002: /* Denormalize */
453
 
                case 0x010: /* Underflow */
454
 
                        info.si_code = FPE_FLTUND;
455
 
                        break;
456
 
                case 0x004: /* Zero Divide */
457
 
                        info.si_code = FPE_FLTDIV;
458
 
                        break;
459
 
                case 0x008: /* Overflow */
460
 
                        info.si_code = FPE_FLTOVF;
461
 
                        break;
462
 
                case 0x020: /* Precision */
463
 
                        info.si_code = FPE_FLTRES;
464
 
                        break;
465
 
        }
466
 
        force_sig_info(SIGFPE, &info, task);
467
 
}
468
 
 
469
 
asmlinkage void do_coprocessor_error(struct pt_regs * regs, long error_code)
470
 
{
471
 
        ignore_irq13 = 1;
472
 
        math_error((void *)regs->eip);
473
 
}
474
 
 
475
 
void simd_math_error(void *eip)
476
 
{
477
 
        struct task_struct * task;
478
 
        siginfo_t info;
479
 
        unsigned short mxcsr;
480
 
 
481
 
        /*
482
 
         * Save the info for the exception handler and clear the error.
483
 
         */
484
 
        task = current;
485
 
        save_init_fpu(task);
486
 
        task->thread.trap_no = 19;
487
 
        task->thread.error_code = 0;
488
 
        info.si_signo = SIGFPE;
489
 
        info.si_errno = 0;
490
 
        info.si_code = __SI_FAULT;
491
 
        info.si_addr = eip;
492
 
        /*
493
 
         * The SIMD FPU exceptions are handled a little differently, as there
494
 
         * is only a single status/control register.  Thus, to determine which
495
 
         * unmasked exception was caught we must mask the exception mask bits
496
 
         * at 0x1f80, and then use these to mask the exception bits at 0x3f.
497
 
         */
498
 
        mxcsr = get_fpu_mxcsr(task);
499
 
        switch (~((mxcsr & 0x1f80) >> 7) & (mxcsr & 0x3f)) {
500
 
                case 0x000:
501
 
                default:
502
 
                        break;
503
 
                case 0x001: /* Invalid Op */
504
 
                        info.si_code = FPE_FLTINV;
505
 
                        break;
506
 
                case 0x002: /* Denormalize */
507
 
                case 0x010: /* Underflow */
508
 
                        info.si_code = FPE_FLTUND;
509
 
                        break;
510
 
                case 0x004: /* Zero Divide */
511
 
                        info.si_code = FPE_FLTDIV;
512
 
                        break;
513
 
                case 0x008: /* Overflow */
514
 
                        info.si_code = FPE_FLTOVF;
515
 
                        break;
516
 
                case 0x020: /* Precision */
517
 
                        info.si_code = FPE_FLTRES;
518
 
                        break;
519
 
        }
520
 
        force_sig_info(SIGFPE, &info, task);
521
 
}
522
 
 
523
 
asmlinkage void do_simd_coprocessor_error(struct pt_regs * regs,
524
 
                                          long error_code)
525
 
{
526
 
        if (cpu_has_xmm) {
527
 
                /* Handle SIMD FPU exceptions on PIII+ processors. */
528
 
                ignore_irq13 = 1;
529
 
                simd_math_error((void *)regs->eip);
530
 
        } else {
531
 
                die_if_kernel("cache flush denied", regs, error_code);
532
 
                current->thread.trap_no = 19;
533
 
                current->thread.error_code = error_code;
534
 
                force_sig(SIGSEGV, current);
535
 
        }
536
 
}
537
 
 
538
 
asmlinkage void do_spurious_interrupt_bug(struct pt_regs * regs,
539
 
                                          long error_code)
540
 
{
541
 
}
542
 
 
543
 
/*
544
 
 *  'math_state_restore()' saves the current math information in the
545
 
 * old math state array, and gets the new ones from the current task
546
 
 *
547
 
 * Careful.. There are problems with IBM-designed IRQ13 behaviour.
548
 
 * Don't touch unless you *really* know how it works.
549
 
 */
550
 
asmlinkage void math_state_restore(struct pt_regs regs)
551
 
{
552
 
        if (current->used_math) {
553
 
                restore_fpu(current);
554
 
        } else {
555
 
                init_fpu();
556
 
        }
557
 
        current->flags |= PF_USEDFPU;   /* So we fnsave on switch_to() */
558
 
}
559
 
 
560
 
 
561
 
#define _set_gate(gate_addr,type,dpl,addr) \
562
 
do { \
563
 
  int __d0, __d1; \
564
 
  __asm__ __volatile__ ("movw %%dx,%%ax\n\t" \
565
 
        "movw %4,%%dx\n\t" \
566
 
        "movl %%eax,%0\n\t" \
567
 
        "movl %%edx,%1" \
568
 
        :"=m" (*((long *) (gate_addr))), \
569
 
         "=m" (*(1+(long *) (gate_addr))), "=&a" (__d0), "=&d" (__d1) \
570
 
        :"i" ((short) (0x8000+(dpl<<13)+(type<<8))), \
571
 
         "3" ((char *) (addr)),"2" (__KERNEL_CS << 16)); \
572
 
} while (0)
573
 
 
574
 
static void __init set_call_gate(void *a, void *addr)
575
 
{
576
 
        _set_gate(a,12,3,addr);
577
 
}
578
 
 
579
 
 
580
 
/* NB. All these are "trap gates" (i.e. events_mask isn't cleared). */
581
 
static trap_info_t trap_table[] = {
582
 
    {  0, 0, __KERNEL_CS, (unsigned long)divide_error                },
583
 
    {  1, 0, __KERNEL_CS, (unsigned long)debug                       },
584
 
    {  3, 3, __KERNEL_CS, (unsigned long)int3                        },
585
 
    {  4, 3, __KERNEL_CS, (unsigned long)overflow                    },
586
 
    {  5, 3, __KERNEL_CS, (unsigned long)bounds                      },
587
 
    {  6, 0, __KERNEL_CS, (unsigned long)invalid_op                  },
588
 
    {  7, 0, __KERNEL_CS, (unsigned long)device_not_available        },
589
 
    {  8, 0, __KERNEL_CS, (unsigned long)double_fault                },
590
 
    {  9, 0, __KERNEL_CS, (unsigned long)coprocessor_segment_overrun },
591
 
    { 10, 0, __KERNEL_CS, (unsigned long)invalid_TSS                 },
592
 
    { 11, 0, __KERNEL_CS, (unsigned long)segment_not_present         },
593
 
    { 12, 0, __KERNEL_CS, (unsigned long)stack_segment               },
594
 
    { 13, 0, __KERNEL_CS, (unsigned long)general_protection          },
595
 
    { 14, 0, __KERNEL_CS, (unsigned long)page_fault                  },
596
 
    { 15, 0, __KERNEL_CS, (unsigned long)spurious_interrupt_bug      },
597
 
    { 16, 0, __KERNEL_CS, (unsigned long)coprocessor_error           },
598
 
    { 17, 0, __KERNEL_CS, (unsigned long)alignment_check             },
599
 
    { 18, 0, __KERNEL_CS, (unsigned long)machine_check               },
600
 
    { 19, 0, __KERNEL_CS, (unsigned long)simd_coprocessor_error      },
601
 
    { SYSCALL_VECTOR, 
602
 
          3, __KERNEL_CS, (unsigned long)system_call                 },
603
 
    {  0, 0,           0, 0                           }
604
 
};
605
 
 
606
 
 
607
 
void __init trap_init(void)
608
 
{
609
 
    HYPERVISOR_set_trap_table(trap_table);    
610
 
    HYPERVISOR_set_fast_trap(SYSCALL_VECTOR);
611
 
 
612
 
    /*
613
 
     * The default LDT is a single-entry callgate to lcall7 for iBCS and a
614
 
     * callgate to lcall27 for Solaris/x86 binaries.
615
 
     */
616
 
    clear_page(&default_ldt[0]);
617
 
    set_call_gate(&default_ldt[0],lcall7);
618
 
    set_call_gate(&default_ldt[4],lcall27);
619
 
    __make_page_readonly(&default_ldt[0]);
620
 
 
621
 
    cpu_init();
622
 
}
623
 
 
624
 
 
625
 
/*
626
 
 * install_safe_pf_handler / install_normal_pf_handler:
627
 
 * 
628
 
 * These are used within the failsafe_callback handler in entry.S to avoid
629
 
 * taking a full page fault when reloading FS and GS. This is because FS and 
630
 
 * GS could be invalid at pretty much any point while Xenolinux executes (we 
631
 
 * don't set them to safe values on entry to the kernel). At *any* point Xen 
632
 
 * may be entered due to a hardware interrupt --- on exit from Xen an invalid 
633
 
 * FS/GS will cause our failsafe_callback to be executed. This could occur, 
634
 
 * for example, while the mmmu_update_queue is in an inconsistent state. This
635
 
 * is disastrous because the normal page-fault handler touches the update
636
 
 * queue!
637
 
 * 
638
 
 * Fortunately, within the failsafe handler it is safe to force DS/ES/FS/GS
639
 
 * to zero if they cannot be reloaded -- at this point executing a normal
640
 
 * page fault would not change this effect. The safe page-fault handler
641
 
 * ensures this end result (blow away the selector value) without the dangers
642
 
 * of the normal page-fault handler.
643
 
 * 
644
 
 * NB. Perhaps this can all go away after we have implemented writeable
645
 
 * page tables. :-)
646
 
 */
647
 
 
648
 
asmlinkage void do_safe_page_fault(struct pt_regs *regs, 
649
 
                                   unsigned long error_code,
650
 
                                   unsigned long address)
651
 
{
652
 
    unsigned long fixup;
653
 
 
654
 
    if ( (fixup = search_exception_table(regs->eip)) != 0 )
655
 
    {
656
 
        regs->eip = fixup;
657
 
        return;
658
 
    }
659
 
 
660
 
    die("Unhandleable 'safe' page fault!", regs, error_code);
661
 
}
662
 
 
663
 
unsigned long install_safe_pf_handler(void)
664
 
{
665
 
    static trap_info_t safe_pf[] = { 
666
 
        { 14, 0, __KERNEL_CS, (unsigned long)safe_page_fault },
667
 
        {  0, 0,           0, 0                              }
668
 
    };
669
 
    unsigned long flags;
670
 
    local_irq_save(flags);
671
 
    HYPERVISOR_set_trap_table(safe_pf);
672
 
    return flags; /* This is returned in %%eax */
673
 
}
674
 
 
675
 
__attribute__((regparm(3))) /* This function take its arg in %%eax */
676
 
void install_normal_pf_handler(unsigned long flags)
677
 
{
678
 
    static trap_info_t normal_pf[] = { 
679
 
        { 14, 0, __KERNEL_CS, (unsigned long)page_fault },
680
 
        {  0, 0,           0, 0                         }
681
 
    };
682
 
    HYPERVISOR_set_trap_table(normal_pf);
683
 
    local_irq_restore(flags);
684
 
}