arch/i386/kernel/traps.c
6091 /*
6092 * linux/arch/i386/traps.c
6093 *
6094 * Copyright (C) 1991, 1992 Linus Torvalds
6095 */
6096
6097 /* 'Traps.c' handles hardware traps and faults after we
6098 * have saved some state in 'asm.s'. */
6099 #include <linux/config.h>
6100 #include <linux/sched.h>
6101 #include <linux/kernel.h>
6102 #include <linux/string.h>
6103 #include <linux/errno.h>
6104 #include <linux/ptrace.h>
6105 #include <linux/timer.h>
6106 #include <linux/mm.h>
6107 #include <linux/smp.h>
6108 #include <linux/smp_lock.h>
6109 #include <linux/init.h>
6110 #include <linux/delay.h>
6111
6112 #ifdef CONFIG_MCA
6113 #include <linux/mca.h>
6114 #include <asm/processor.h>
6115 #endif
6116
6117 #include <asm/system.h>
6118 #include <asm/uaccess.h>
6119 #include <asm/io.h>
6120 #include <asm/spinlock.h>
6121 #include <asm/atomic.h>
6122 #include <asm/debugreg.h>
6123 #include <asm/desc.h>
6124
6125 #include <asm/smp.h>
6126
6127 #ifdef CONFIG_X86_VISWS_APIC
6128 #include <asm/fixmap.h>
6129 #include <asm/cobalt.h>
6130 #include <asm/lithium.h>
6131 #endif
6132
6133 #include "irq.h"
6134
6135 asmlinkage int system_call(void);
6136 asmlinkage void lcall7(void);
6137
6138 struct desc_struct default_ldt = { 0, 0 };
6139
6140 /* The IDT has to be page-aligned to simplify the Pentium
6141 * F0 0F bug workaround.. We have a special link segment
6142 * for this. */
6143 struct desc_struct idt_table[256]
6144 __attribute__((__section__(".data.idt"))) = { {0, 0}, };
6145
6146 static inline void console_verbose(void)
6147 {
6148 extern int console_loglevel;
6149 console_loglevel = 15;
6150 }
6151
6152 #define DO_ERROR(trapnr, signr, str, name, tsk) \
6153 asmlinkage void do_##name(struct pt_regs * regs, \
6154 long error_code) \
6155 { \
6156 tsk->tss.error_code = error_code; \
6157 tsk->tss.trap_no = trapnr; \
6158 force_sig(signr, tsk); \
6159 die_if_no_fixup(str,regs,error_code); \
6160 }
6161
6162 #define DO_VM86_ERROR(trapnr, signr, str, name, tsk) \
6163 asmlinkage void do_##name(struct pt_regs * regs, \
6164 long error_code) \
6165 { \
6166 lock_kernel(); \
6167 if (regs->eflags & VM_MASK) { \
6168 if (!handle_vm86_trap((struct kernel_vm86_regs *) \
6169 regs, error_code, trapnr)) \
6170 goto out; \
6171 /* else fall through */ \
6172 } \
6173 tsk->tss.error_code = error_code; \
6174 tsk->tss.trap_no = trapnr; \
6175 force_sig(signr, tsk); \
6176 die_if_kernel(str,regs,error_code); \
6177 out: \
6178 unlock_kernel();
6179 }
6180
6181 void page_exception(void);
6182
6183 asmlinkage void divide_error(void);
6184 asmlinkage void debug(void);
6185 asmlinkage void nmi(void);
6186 asmlinkage void int3(void);
6187 asmlinkage void overflow(void);
6188 asmlinkage void bounds(void);
6189 asmlinkage void invalid_op(void);
6190 asmlinkage void device_not_available(void);
6191 asmlinkage void double_fault(void);
6192 asmlinkage void coprocessor_segment_overrun(void);
6193 asmlinkage void invalid_TSS(void);
6194 asmlinkage void segment_not_present(void);
6195 asmlinkage void stack_segment(void);
6196 asmlinkage void general_protection(void);
6197 asmlinkage void page_fault(void);
6198 asmlinkage void coprocessor_error(void);
6199 asmlinkage void reserved(void);
6200 asmlinkage void alignment_check(void);
6201 asmlinkage void spurious_interrupt_bug(void);
6202
6203 int kstack_depth_to_print = 24;
6204
6205 /* These constants are for searching for possible module
6206 * text segments. VMALLOC_OFFSET comes from
6207 * mm/vmalloc.c; MODULE_RANGE is a guess of how much
6208 * space is likely to be vmalloced. */
6209 #define VMALLOC_OFFSET (8*1024*1024)
6210 #define MODULE_RANGE (8*1024*1024)
6211
6212 static void show_registers(struct pt_regs *regs)
6213 {
6214 int i;
6215 int in_kernel = 1;
6216 unsigned long esp;
6217 unsigned short ss;
6218 unsigned long *stack, addr, module_start, module_end;
6219
6220 esp = (unsigned long) (1+regs);
6221 ss = __KERNEL_DS;
6222 if (regs->xcs & 3) {
6223 in_kernel = 0;
6224 esp = regs->esp;
6225 ss = regs->xss & 0xffff;
6226 }
6227 printk("CPU: %d\nEIP: %04x:[<%08lx>]"
6228 "\nEFLAGS: %08lx\n", smp_processor_id(),
6229 0xffff & regs->xcs, regs->eip, regs->eflags);
6230 printk("eax: %08lx ebx: %08lx ecx: %08lx "
6231 "edx: %08lx\n",
6232 regs->eax, regs->ebx, regs->ecx, regs->edx);
6233 printk("esi: %08lx edi: %08lx ebp: %08lx "
6234 "esp: %08lx\n",
6235 regs->esi, regs->edi, regs->ebp, esp);
6236 printk("ds: %04x es: %04x ss: %04x\n",
6237 regs->xds & 0xffff, regs->xes & 0xffff, ss);
6238 store_TR(i);
6239 printk("Process %s (pid: %d, process nr: %d, "
6240 "stackpage=%08lx)", current->comm, current->pid,
6241 0xffff & i, 4096+(unsigned long)current);
6242
6243 /* When in-kernel, we also print out the stack and code
6244 * at the time of the fault.. */
6245 if (in_kernel) {
6246 printk("\nStack: ");
6247 stack = (unsigned long *) esp;
6248 for(i=0; i < kstack_depth_to_print; i++) {
6249 if (((long) stack & 4095) == 0)
6250 break;
6251 if (i && ((i % 8) == 0))
6252 printk("\n ");
6253 printk("%08lx ", *stack++);
6254 }
6255 printk("\nCall Trace: ");
6256 stack = (unsigned long *) esp;
6257 i = 1;
6258 module_start = PAGE_OFFSET + (max_mapnr<<PAGE_SHIFT);
6259 module_start = ((module_start + VMALLOC_OFFSET) &
6260 ~(VMALLOC_OFFSET-1));
6261 module_end = module_start + MODULE_RANGE;
6262 while (((long) stack & 4095) != 0) {
6263 addr = *stack++;
6264 /* If the address is either in the text segment of
6265 * the kernel, or in the region which contains
6266 * vmalloc'ed memory, it *may* be the address of a
6267 * calling routine; if so, print it so that someone
6268 * tracing down the cause of the crash will be able
6269 * to figure out the call path that was taken. */
6270 if (((addr >= (unsigned long) &_stext) &&
6271 (addr <= (unsigned long) &_etext)) ||
6272 ((addr >= module_start) &&
6273 (addr <= module_end))) {
6274 if (i && ((i % 8) == 0))
6275 printk("\n ");
6276 printk("[<%08lx>] ", addr);
6277 i++;
6278 }
6279 }
6280 printk("\nCode: ");
6281 for(i=0;i<20;i++)
6282 printk("%02x ", ((unsigned char *)regs->eip)[i]);
6283 }
6284 printk("\n");
6285 }
6286
6287 spinlock_t die_lock;
6288
6289 void die(const char * str, struct pt_regs * regs,
6290 long err)
6291 {
6292 console_verbose();
6293 spin_lock_irq(&die_lock);
6294 printk("%s: %04lx\n", str, err & 0xffff);
6295 show_registers(regs);
6296 spin_unlock_irq(&die_lock);
6297 do_exit(SIGSEGV);
6298 }
6299
6300 static inline void die_if_kernel(const char * str,
6301 struct pt_regs * regs, long err)
6302 {
6303 if (!(regs->eflags & VM_MASK) && !(3 & regs->xcs))
6304 die(str, regs, err);
6305 }
6306
6307 static void die_if_no_fixup(const char * str,
6308 struct pt_regs * regs, long err)
6309 {
6310 if (!(regs->eflags & VM_MASK) && !(3 & regs->xcs))
6311 {
6312 unsigned long fixup;
6313 fixup = search_exception_table(regs->eip);
6314 if (fixup) {
6315 regs->eip = fixup;
6316 return;
6317 }
6318 die(str, regs, err);
6319 }
6320 }
6321
6322 DO_VM86_ERROR( 0, SIGFPE, "divide error", divide_error,
6323 current)
6324 DO_VM86_ERROR( 3, SIGTRAP, "int3", int3, current)
6325 DO_VM86_ERROR( 4, SIGSEGV, "overflow", overflow, current)
6326 DO_VM86_ERROR( 5, SIGSEGV, "bounds", bounds, current)
6327 DO_ERROR( 6, SIGILL, "invalid operand", invalid_op,
6328 current)
6329 DO_VM86_ERROR( 7, SIGSEGV, "device not available",
6330 device_not_available, current)
6331 DO_ERROR( 8, SIGSEGV, "double fault", double_fault,
6332 current)
6333 DO_ERROR( 9, SIGFPE, "coprocessor segment overrun",
6334 coprocessor_segment_overrun, current)
6335 DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS,
6336 current)
6337 DO_ERROR(11, SIGBUS, "segment not present",
6338 segment_not_present, current)
6339 DO_ERROR(12, SIGBUS, "stack segment", stack_segment,
6340 current)
6341 DO_ERROR(17, SIGSEGV, "alignment check", alignment_check,
6342 current)
6343 DO_ERROR(18, SIGSEGV, "reserved", reserved, current)
6344 /* I don't have documents for this but it does seem to
6345 * cover the cache flush from user space exception some
6346 * people get. */
6347 DO_ERROR(19, SIGSEGV, "cache flush denied",
6348 cache_flush_denied, current)
6349
6350 asmlinkage void cache_flush_denied(struct pt_regs * regs,
6351 long error_code)
6352 {
6353 if (regs->eflags & VM_MASK) {
6354 handle_vm86_fault((struct kernel_vm86_regs *) regs,
6355 error_code);
6356 return;
6357 }
6358 die_if_kernel("cache flush denied",regs,error_code);
6359 current->tss.error_code = error_code;
6360 current->tss.trap_no = 19;
6361 force_sig(SIGSEGV, current);
6362 }
6363
6364 asmlinkage void do_general_protection(
6365 struct pt_regs * regs, long error_code)
6366 {
6367 if (regs->eflags & VM_MASK)
6368 goto gp_in_vm86;
6369
6370 if (!(regs->xcs & 3))
6371 goto gp_in_kernel;
6372
6373 current->tss.error_code = error_code;
6374 current->tss.trap_no = 13;
6375 force_sig(SIGSEGV, current);
6376 return;
6377
6378 gp_in_vm86:
6379 lock_kernel();
6380 handle_vm86_fault((struct kernel_vm86_regs *) regs,
6381 error_code);
6382 unlock_kernel();
6383 return;
6384
6385 gp_in_kernel:
6386 {
6387 unsigned long fixup;
6388 fixup = search_exception_table(regs->eip);
6389 if (fixup) {
6390 regs->eip = fixup;
6391 return;
6392 }
6393 die("general protection fault", regs, error_code);
6394 }
6395 }
6396
6397 static void mem_parity_error(unsigned char reason,
6398 struct pt_regs * regs)
6399 {
6400 printk("Uhhuh. NMI received. Dazed and confused, "
6401 "but trying to continue\n");
6402 printk("You probably have a hardware problem with "
6403 "your RAM chips\n");
6404 }
6405
6406 static void io_check_error(unsigned char reason,
6407 struct pt_regs * regs)
6408 {
6409 unsigned long i;
6410
6411 printk("NMI: IOCK error (debug interrupt?)\n");
6412 show_registers(regs);
6413
6414 /* Re-enable the IOCK line, wait for a few seconds */
6415 reason |= 8;
6416 outb(reason, 0x61);
6417 i = 2000;
6418 while (--i) udelay(1000);
6419 reason &= ~8;
6420 outb(reason, 0x61);
6421 }
6422
6423 static void unknown_nmi_error(unsigned char reason,
6424 struct pt_regs * regs)
6425 {
6426 #ifdef CONFIG_MCA
6427 /* Might actually be able to figure out what the guilty
6428 * party is. */
6429 if( MCA_bus ) {
6430 mca_handle_nmi();
6431 return;
6432 }
6433 #endif
6434 printk("Uhhuh. NMI received for unknown reason %02x.\n"
6435 , reason);
6436 printk("Dazed and confused, but trying to continue\n");
6437 printk("Do you have a strange power saving mode "
6438 "enabled?\n");
6439 }
6440
6441 asmlinkage void do_nmi(struct pt_regs * regs,
6442 long error_code)
6443 {
6444 unsigned char reason = inb(0x61);
6445 extern atomic_t nmi_counter;
6446
6447 atomic_inc(&nmi_counter);
6448 if (reason & 0x80)
6449 mem_parity_error(reason, regs);
6450 if (reason & 0x40)
6451 io_check_error(reason, regs);
6452 if (!(reason & 0xc0))
6453 unknown_nmi_error(reason, regs);
6454 }
6455
6456 /* Careful - we must not do a lock-kernel until we have
6457 * checked that the debug fault happened in user
6458 * mode. Getting debug exceptions while in the kernel has
6459 * to be handled without locking, to avoid deadlocks..
6460 *
6461 * Being careful here means that we don't have to be as
6462 * careful in a lot of more complicated places (task
6463 * switching can be a bit lazy about restoring all the
6464 * debug state, and ptrace doesn't have to find every
6465 * occurrence of the TF bit that could be saved away even
6466 * by user code - and we don't have to be careful about
6467 * what values can be written to the debug registers
6468 * because there are no really bad cases). */
6469 asmlinkage void do_debug(struct pt_regs * regs,
6470 long error_code)
6471 {
6472 unsigned int condition;
6473 struct task_struct *tsk = current;
6474
6475 if (regs->eflags & VM_MASK)
6476 goto debug_vm86;
6477
6478 __asm__ __volatile__("movl %%db6,%0" : "=r"
6479 (condition));
6480
6481 /* Mask out spurious TF errors due to lazy TF
6482 * clearing */
6483 if (condition & DR_STEP) {
6484 /* The TF error should be masked out only if the
6485 * current process is not traced and if the TRAP flag
6486 * has been set previously by a tracing process
6487 * (condition detected by the PF_DTRACE flag);
6488 * remember that the i386 TRAP flag can be modified
6489 * by the process itself in user mode, allowing
6490 * programs to debug themselves without the ptrace()
6491 * interface. */
6492 if ((tsk->flags & (PF_DTRACE|PF_PTRACED)) ==
6493 PF_DTRACE)
6494 goto clear_TF;
6495 }
6496
6497 /* Mask out spurious debug traps due to lazy DR7
6498 * setting */
6499 if (condition & (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)){
6500 if (!tsk->tss.debugreg[7])
6501 goto clear_dr7;
6502 }
6503
6504 /* If this is a kernel mode trap, we need to reset db7
6505 * to allow us to continue sanely */
6506 if ((regs->xcs & 3) == 0)
6507 goto clear_dr7;
6508
6509 /* Ok, finally something we can handle */
6510 tsk->tss.trap_no = 1;
6511 tsk->tss.error_code = error_code;
6512 force_sig(SIGTRAP, tsk);
6513 return;
6514
6515 debug_vm86:
6516 lock_kernel();
6517 handle_vm86_trap((struct kernel_vm86_regs *) regs,
6518 error_code, 1);
6519 unlock_kernel();
6520 return;
6521
6522 clear_dr7:
6523 __asm__("movl %0,%%db7"
6524 : /* no output */
6525 : "r" (0));
6526 return;
6527
6528 clear_TF:
6529 regs->eflags &= ~TF_MASK;
6530 return;
6531 }
6532
6533 /* Note that we play around with the 'TS' bit in an
6534 * attempt to get the correct behaviour even in the
6535 * presence of the asynchronous IRQ13 behaviour */
6536 void math_error(void)
6537 {
6538 struct task_struct * task;
6539
6540 /* Save the info for the exception handler (this will
6541 * also clear the error) */
6542 task = current;
6543 save_fpu(task);
6544 task->tss.trap_no = 16;
6545 task->tss.error_code = 0;
6546 force_sig(SIGFPE, task);
6547 }
6548
6549 asmlinkage void do_coprocessor_error(
6550 struct pt_regs * regs, long error_code)
6551 {
6552 ignore_irq13 = 1;
6553 math_error();
6554 }
6555
6556 asmlinkage void do_spurious_interrupt_bug(
6557 struct pt_regs * regs, long error_code)
6558 {
6559 #if 0
6560 /* No need to warn about this any longer. */
6561 printk("Ignoring P6 Local APIC Spurious Interrupt "
6562 "Bug...\n");
6563 #endif
6564 }
6565
6566 /* 'math_state_restore()' saves the current math
6567 * information in the old math state array, and gets the
6568 * new ones from the current task
6569 *
6570 * Careful.. There are problems with IBM-designed IRQ13
6571 * behaviour. Don't touch unless you *really* know how
6572 * it works. */
6573 asmlinkage void math_state_restore(struct pt_regs regs)
6574 {
6575 /* Allow maths ops (or we recurse) */
6576 __asm__ __volatile__("clts");
6577 if(current->used_math)
6578 __asm__("frstor %0": :"m" (current->tss.i387));
6579 else
6580 {
6581 /* Our first FPU usage, clean the chip. */
6582 __asm__("fninit");
6583 current->used_math = 1;
6584 }
6585 /* So we fnsave on switch_to() */
6586 current->flags|=PF_USEDFPU;
6587 }
6588
6589 #ifndef CONFIG_MATH_EMULATION
6590
6591 asmlinkage void math_emulate(long arg)
6592 {
6593 lock_kernel();
6594 printk("math-emulation not enabled and no coprocessor "
6595 "found.\n");
6596 printk("killing %s.\n",current->comm);
6597 force_sig(SIGFPE,current);
6598 schedule();
6599 unlock_kernel();
6600 }
6601
6602 #endif /* CONFIG_MATH_EMULATION */
6603
6604 __initfunc(void trap_init_f00f_bug(void))
6605 {
6606 unsigned long page;
6607 pgd_t * pgd;
6608 pmd_t * pmd;
6609 pte_t * pte;
6610
6611 /* Allocate a new page in virtual address space, move
6612 * the IDT into it and write protect this page. */
6613 page = (unsigned long) vmalloc(PAGE_SIZE);
6614 pgd = pgd_offset(&init_mm, page);
6615 pmd = pmd_offset(pgd, page);
6616 pte = pte_offset(pmd, page);
6617 free_page(pte_page(*pte));
6618 *pte = mk_pte(&idt_table, PAGE_KERNEL_RO);
6619 local_flush_tlb();
6620
6621 /* "idt" is magic - it overlaps the idt_descr variable
6622 * so that updating idt will automatically update the
6623 * idt descriptor.. */
6624 idt = (struct desc_struct *)page;
6625 __asm__ __volatile__("lidt %0": "=m" (idt_descr));
6626 }
6627
6628 #define _set_gate(gate_addr,type,dpl,addr) \
6629 do { \
6630 int __d0, __d1; \
6631 __asm__ __volatile__ ("movw %%dx,%%ax\n\t" \
6632 "movw %4,%%dx\n\t" \
6633 "movl %%eax,%0\n\t" \
6634 "movl %%edx,%1" \
6635 :"=m" (*((long *) (gate_addr))), \
6636 "=m" (*(1+(long *) (gate_addr))), "=&a" (__d0), \
6637 "=&d" (__d1) \
6638 :"i" ((short) (0x8000+(dpl<<13)+(type<<8))), \
6639 "3" ((char *) (addr)),"2" (__KERNEL_CS << 16));
6640 } while (0)
6641
6642
6643 /* This needs to use 'idt_table' rather than 'idt', and
6644 * thus use the _nonmapped_ version of the IDT, as the
6645 * Pentium F0 0F bugfix can have resulted in the mapped
6646 * IDT being write-protected. */
6647 void set_intr_gate(unsigned int n, void *addr)
6648 {
6649 _set_gate(idt_table+n,14,0,addr);
6650 }
6651
6652 static void __init set_trap_gate(unsigned int n,
6653 void *addr)
6654 {
6655 _set_gate(idt_table+n,15,0,addr);
6656 }
6657
6658 static void __init set_system_gate(unsigned int n,
6659 void *addr)
6660 {
6661 _set_gate(idt_table+n,15,3,addr);
6662 }
6663
6664 static void __init set_call_gate(void *a, void *addr)
6665 {
6666 _set_gate(a,12,3,addr);
6667 }
6668
6669 #define _set_seg_desc(gate_addr,type,dpl,base,limit) { \
6670 *((gate_addr)+1) = ((base) & 0xff000000) | \
6671 (((base) & 0x00ff0000)>>16) | \
6672 ((limit) & 0xf0000) | \
6673 ((dpl)<<13) | \
6674 (0x00408000) | \
6675 ((type)<<8); \
6676 *(gate_addr) = (((base) & 0x0000ffff)<<16) | \
6677 ((limit) & 0x0ffff); }
6678
6679 #define _set_tssldt_desc(n,addr,limit,type) \
6680 __asm__ __volatile__ ("movw %3,0(%2)\n\t" \
6681 "movw %%ax,2(%2)\n\t" \
6682 "rorl $16,%%eax\n\t" \
6683 "movb %%al,4(%2)\n\t" \
6684 "movb %4,5(%2)\n\t" \
6685 "movb $0,6(%2)\n\t" \
6686 "movb %%ah,7(%2)\n\t" \
6687 "rorl $16,%%eax" \
6688 : "=m"(*(n)) : "a" (addr), "r"(n), "ir"(limit), \
6689 "i"(type))
6690
6691 void set_tss_desc(unsigned int n, void *addr)
6692 {
6693 _set_tssldt_desc(gdt_table+FIRST_TSS_ENTRY+(n<<1),
6694 (int)addr, 235, 0x89);
6695 }
6696
6697 void set_ldt_desc(unsigned int n, void *addr,
6698 unsigned int size)
6699 {
6700 _set_tssldt_desc(gdt_table+FIRST_LDT_ENTRY+(n<<1),
6701 (int)addr, ((size << 3) - 1), 0x82);
6702 }
6703
6704 #ifdef CONFIG_X86_VISWS_APIC
6705
6706 /* On Rev 005 motherboards legacy device interrupt lines
6707 * are wired directly to Lithium from the 307. But the
6708 * PROM leaves the interrupt type of each 307 logical
6709 * device set appropriate for the 8259. Later we'll
6710 * actually use the 8259, but for now we have to flip the
6711 * interrupt types to level triggered, active lo as
6712 * required by Lithium. */
6713 #define REG 0x2e /* The register to read/write */
6714 #define DEV 0x07 /* Register: Logical device select */
6715 #define VAL 0x2f /* The value to read/write */
6716
6717 static void
6718 superio_outb(int dev, int reg, int val)
6719 {
6720 outb(DEV, REG);
6721 outb(dev, VAL);
6722 outb(reg, REG);
6723 outb(val, VAL);
6724 }
6725
6726 static int __attribute__ ((unused))
6727 superio_inb(int dev, int reg)
6728 {
6729 outb(DEV, REG);
6730 outb(dev, VAL);
6731 outb(reg, REG);
6732 return inb(VAL);
6733 }
6734
6735 #define FLOP 3 /* floppy logical device */
6736 #define PPORT 4 /* parallel logical device */
6737 #define UART5 5 /* uart2 logical device (not wired up) */
6738 #define UART6 6 /* uart1 logical device
6739 * (THIS is the serial port!) */
6740 #define IDEST 0x70 /* int. destination
6741 * (which 307 IRQ line) reg. */
6742 #define ITYPE 0x71 /* interrupt type register */
6743
6744 /* interrupt type bits */
6745 #define LEVEL 0x01 /* bit 0, 0 == edge triggered */
6746 #define ACTHI 0x02 /* bit 1, 0 == active lo */
6747
6748 static void
6749 superio_init(void)
6750 {
6751 if (visws_board_type == VISWS_320 &&
6752 visws_board_rev == 5) {
6753 /* 0 means no intr propagated */
6754 superio_outb(UART6, IDEST, 0);
6755 printk("SGI 320 rev 5: "
6756 "disabling 307 uart1 interrupt\n");
6757 }
6758 }
6759
6760 static void
6761 lithium_init(void)
6762 {
6763 set_fixmap(FIX_LI_PCIA, LI_PCI_A_PHYS);
6764 printk("Lithium PCI Bridge A, Bus Number: %d\n",
6765 li_pcia_read16(LI_PCI_BUSNUM) & 0xff);
6766 set_fixmap(FIX_LI_PCIB, LI_PCI_B_PHYS);
6767 printk("Lithium PCI Bridge B (PIIX4), Bus Number: "
6768 "%d\n", li_pcib_read16(LI_PCI_BUSNUM) & 0xff);
6769
6770 /* XXX blindly enables all interrupts */
6771 li_pcia_write16(LI_PCI_INTEN, 0xffff);
6772 li_pcib_write16(LI_PCI_INTEN, 0xffff);
6773 }
6774
6775 static void
6776 cobalt_init(void)
6777 {
6778 /* On normal SMP PC this is used only with SMP, but we
6779 * have to use it and set it up here to start the
6780 * Cobalt clock */
6781 set_fixmap(FIX_APIC_BASE, APIC_PHYS_BASE);
6782 printk("Local APIC ID %lx\n", apic_read(APIC_ID));
6783 printk("Local APIC Version %lx\n",
6784 apic_read(APIC_VERSION));
6785
6786 set_fixmap(FIX_CO_CPU, CO_CPU_PHYS);
6787 printk("Cobalt Revision %lx\n",
6788 co_cpu_read(CO_CPU_REV));
6789
6790 set_fixmap(FIX_CO_APIC, CO_APIC_PHYS);
6791 printk("Cobalt APIC ID %lx\n",
6792 co_apic_read(CO_APIC_ID));
6793
6794 /* Enable Cobalt APIC being careful to NOT change the
6795 * ID! */
6796 co_apic_write(CO_APIC_ID,
6797 co_apic_read(CO_APIC_ID)|CO_APIC_ENABLE);
6798
6799 printk("Cobalt APIC enabled: ID reg %lx\n",
6800 co_apic_read(CO_APIC_ID));
6801 }
6802 #endif
6803 void __init trap_init(void)
6804 {
6805 if (readl(0x0FFFD9) ==
6806 'E' + ('I' << 8) + ('S' << 16) + ('A' << 24))
6807 EISA_bus = 1;
6808 set_call_gate(&default_ldt,lcall7);
6809 set_trap_gate(0,÷_error);
6810 set_trap_gate(1,&debug);
6811 set_trap_gate(2,&nmi);
6812 /* int3-5 can be called from all */
6813 set_system_gate(3,&int3);
6814 set_system_gate(4,&overflow);
6815 set_system_gate(5,&bounds);
6816 set_trap_gate(6,&invalid_op);
6817 set_trap_gate(7,&device_not_available);
6818 set_trap_gate(8,&double_fault);
6819 set_trap_gate(9,&coprocessor_segment_overrun);
6820 set_trap_gate(10,&invalid_TSS);
6821 set_trap_gate(11,&segment_not_present);
6822 set_trap_gate(12,&stack_segment);
6823 set_trap_gate(13,&general_protection);
6824 set_trap_gate(14,&page_fault);
6825 set_trap_gate(15,&spurious_interrupt_bug);
6826 set_trap_gate(16,&coprocessor_error);
6827 set_trap_gate(17,&alignment_check);
6828 set_system_gate(SYSCALL_VECTOR,&system_call);
6829
6830 /* set up GDT task & ldt entries */
6831 set_tss_desc(0, &init_task.tss);
6832 set_ldt_desc(0, &default_ldt, 1);
6833
6834 /* Clear NT, so that we won't have troubles with that
6835 * later on */
6836 __asm__("pushfl ; andl $0xffffbfff,(%esp) ; popfl");
6837 load_TR(0);
6838 load_ldt(0);
6839 #ifdef CONFIG_X86_VISWS_APIC
6840 superio_init();
6841 lithium_init();
6842 cobalt_init();
6843 #endif
6844 }
Сайт управляется системой
uCoz