diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1997-12-06 23:51:34 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1997-12-06 23:51:34 +0000 |
commit | 230e5ab6a084ed50470f101934782dbf54b0d06b (patch) | |
tree | 5dd821c8d33f450470588e7a543f74bf74306e9e /arch/i386 | |
parent | c9b1c8a64c6444d189856f1e26bdcb8b4cd0113a (diff) |
Merge with Linux 2.1.67.
Diffstat (limited to 'arch/i386')
-rw-r--r-- | arch/i386/boot/compressed/misc.c | 9 | ||||
-rw-r--r-- | arch/i386/config.in | 2 | ||||
-rw-r--r-- | arch/i386/defconfig | 26 | ||||
-rw-r--r-- | arch/i386/kernel/entry.S | 3 | ||||
-rw-r--r-- | arch/i386/kernel/head.S | 40 | ||||
-rw-r--r-- | arch/i386/kernel/i386_ksyms.c | 7 | ||||
-rw-r--r-- | arch/i386/kernel/ioport.c | 10 | ||||
-rw-r--r-- | arch/i386/kernel/setup.c | 3 | ||||
-rw-r--r-- | arch/i386/kernel/trampoline.S | 2 | ||||
-rw-r--r-- | arch/i386/kernel/traps.c | 33 | ||||
-rw-r--r-- | arch/i386/lib/Makefile | 2 | ||||
-rw-r--r-- | arch/i386/lib/delay.c | 45 | ||||
-rw-r--r-- | arch/i386/mm/fault.c | 34 |
13 files changed, 180 insertions, 36 deletions
diff --git a/arch/i386/boot/compressed/misc.c b/arch/i386/boot/compressed/misc.c index fd835f5c0..9a556baf4 100644 --- a/arch/i386/boot/compressed/misc.c +++ b/arch/i386/boot/compressed/misc.c @@ -75,6 +75,9 @@ static void gzip_release(void **); * This is set up by the setup-routine at boot-time */ #define EXT_MEM_K (*(unsigned short *)0x90002) +#ifndef STANDARD_MEMORY_BIOS_CALL +#define ALT_MEM_K (*(unsigned long *) 0x901e0) +#endif #define SCREEN_INFO (*(struct screen_info *)0x90000) extern char input_data[]; @@ -287,9 +290,9 @@ struct { void setup_normal_output_buffer() { #ifdef STANDARD_MEMORY_BIOS_CALL - if (EXT_MEM_K < 1024) error("<2M of mem\n"); + if (EXT_MEM_K < 1024) error("Less than 2MB of memory.\n"); #else - if (EXT_MEM_K*64 < 1024) error("<2M of mem\n"); + if ((ALT_MEM_K > EXT_MEM_K ? ALT_MEM_K : EXT_MEM_K) < 1024) error("Less than 2MB of memory.\n"); #endif output_data = (char *)0x100000; /* Points to 1M */ } @@ -305,7 +308,7 @@ void setup_output_buffer_if_we_run_high(struct moveparams *mv) #ifdef STANDARD_MEMORY_BIOS_CALL if (EXT_MEM_K < (3*1024)) error("Less than 4MB of memory.\n"); #else - if (EXT_MEM_K*64 < (3*1024)) error("Less than 4MB of memory.\n"); + if ((ALT_MEM_K > EXT_MEM_K ? ALT_MEM_K : EXT_MEM_K) < (3*1024)) error("Less than 4MB of memory.\n"); #endif mv->low_buffer_start = output_data = (char *)LOW_BUFFER_START; high_loaded = 1; diff --git a/arch/i386/config.in b/arch/i386/config.in index 50d9de2a7..f7042fa33 100644 --- a/arch/i386/config.in +++ b/arch/i386/config.in @@ -104,6 +104,8 @@ endmenu source fs/Config.in +source fs/nls/Config.in + source drivers/char/Config.in mainmenu_option next_comment diff --git a/arch/i386/defconfig b/arch/i386/defconfig index d4118f63f..bd100e08d 100644 --- a/arch/i386/defconfig +++ b/arch/i386/defconfig @@ -137,11 +137,15 @@ CONFIG_SCSI_OMIT_FLASHPOINT=y # CONFIG_SCSI_EATA_PIO is not set # CONFIG_SCSI_EATA is not set # CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_GDTH is not set # CONFIG_SCSI_GENERIC_NCR5380 is not set # CONFIG_SCSI_NCR53C406A is not set # CONFIG_SCSI_NCR53C7xx is not set # CONFIG_SCSI_NCR53C8XX is not set # CONFIG_SCSI_PAS16 is not set +# CONFIG_SCSI_PCI2000 is not set +# CONFIG_SCSI_PCI2220I is not set +# CONFIG_SCSI_PSI240I is not set # CONFIG_SCSI_QLOGIC_FAS is not set # CONFIG_SCSI_QLOGIC_ISP is not set # CONFIG_SCSI_SEAGATE is not set @@ -198,18 +202,19 @@ CONFIG_EEXPRESS_PRO100=y # CONFIG_QUOTA is not set # CONFIG_MINIX_FS is not set CONFIG_EXT2_FS=y +CONFIG_ISO9660_FS=y +# CONFIG_JOLIET is not set # CONFIG_FAT_FS is not set # CONFIG_MSDOS_FS is not set -# CONFIG_VFAT_FS is not set # CONFIG_UMSDOS_FS is not set +# CONFIG_VFAT_FS is not set CONFIG_PROC_FS=y CONFIG_NFS_FS=y # CONFIG_ROOT_NFS is not set -# CONFIG_NFSD is not set +CONFIG_NFSD=y CONFIG_SUNRPC=y CONFIG_LOCKD=y # CONFIG_SMB_FS is not set -CONFIG_ISO9660_FS=y # CONFIG_HPFS_FS is not set # CONFIG_SYSV_FS is not set # CONFIG_AFFS_FS is not set @@ -219,6 +224,11 @@ CONFIG_AUTOFS_FS=y # CONFIG_MAC_PARTITION is not set # +# Native Language Support +# +# CONFIG_NLS is not set + +# # Character devices # CONFIG_VT=y @@ -235,12 +245,20 @@ CONFIG_82C710_MOUSE=y # CONFIG_PC110_PAD is not set # CONFIG_UMISC is not set # CONFIG_QIC02_TAPE is not set -# CONFIG_FTAPE is not set # CONFIG_APM is not set # CONFIG_WATCHDOG is not set # CONFIG_RTC is not set +# CONFIG_VIDEO_DEV is not set +# CONFIG_VIDEO_BT848 is not set +# CONFIG_VIDEO_PMS is not set # CONFIG_NVRAM is not set # CONFIG_JOYSTICK is not set +# CONFIG_MISC_RADIO is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set # # Sound diff --git a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S index 21bf04709..dffc13795 100644 --- a/arch/i386/kernel/entry.S +++ b/arch/i386/kernel/entry.S @@ -528,6 +528,7 @@ ENTRY(sys_call_table) .long SYMBOL_NAME(sys_nfsservctl) .long SYMBOL_NAME(sys_setresgid) /* 170 */ .long SYMBOL_NAME(sys_getresgid) - .rept NR_syscalls-171 + .long SYMBOL_NAME(sys_prctl) + .rept NR_syscalls-172 .long SYMBOL_NAME(sys_ni_syscall) .endr diff --git a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S index ef2cfa9a2..00a8e122e 100644 --- a/arch/i386/kernel/head.S +++ b/arch/i386/kernel/head.S @@ -289,7 +289,7 @@ setup_idt: movw %dx,%ax /* selector = 0x0010 = cs */ movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ - lea SYMBOL_NAME(idt),%edi + lea SYMBOL_NAME(idt_table),%edi mov $256,%ecx rp_sidt: movl %eax,(%edi) @@ -328,23 +328,33 @@ ignore_int: iret /* - * The interrupt descriptor table has room for 256 idt's + * The interrupt descriptor table has room for 256 idt's, + * the global descriptor table is dependent on the number + * of tasks we can have.. */ +#define IDT_ENTRIES 256 +#ifdef CONFIG_APM +#define GDT_ENTRIES (11+2*NR_TASKS) +#else +#define GDT_ENTRIES (8+2*NR_TASKS) +#endif + + +.globl SYMBOL_NAME(idt) +.globl SYMBOL_NAME(gdt) + ALIGN -.word 0 + .word 0 idt_descr: - .word 256*8-1 # idt contains 256 entries - .long SYMBOL_NAME(idt) + .word IDT_ENTRIES*8-1 # idt contains 256 entries +SYMBOL_NAME(idt): + .long SYMBOL_NAME(idt_table) - ALIGN -.word 0 + .word 0 gdt_descr: -#ifdef CONFIG_APM - .word (11+2*NR_TASKS)*8-1 -#else - .word (8+2*NR_TASKS)*8-1 -#endif - .long SYMBOL_NAME(gdt) + .word GDT_ENTRIES*8-1 +SYMBOL_NAME(gdt): + .long SYMBOL_NAME(gdt_table) /* * This is initialized to create a identity-mapping at 0-4M (for bootup @@ -515,7 +525,7 @@ ENTRY(this_must_match_init_task) ALIGN /* 256 quadwords - 2048 bytes of idt */ -ENTRY(idt) +ENTRY(idt_table) .fill 256,8,0 # idt is uninitialized /* @@ -528,7 +538,7 @@ ENTRY(idt) * NOTE! Make sure the gdt descriptor in head.S matches this if you * change anything. */ -ENTRY(gdt) +ENTRY(gdt_table) .quad 0x0000000000000000 /* NULL descriptor */ .quad 0x0000000000000000 /* not used */ .quad 0x00cf9a000000ffff /* 0x10 kernel 4GB code at 0x00000000 */ diff --git a/arch/i386/kernel/i386_ksyms.c b/arch/i386/kernel/i386_ksyms.c index b740eb0ce..e71177c3c 100644 --- a/arch/i386/kernel/i386_ksyms.c +++ b/arch/i386/kernel/i386_ksyms.c @@ -15,6 +15,7 @@ #include <asm/checksum.h> #include <asm/io.h> #include <asm/hardirq.h> +#include <asm/delay.h> extern void dump_thread(struct pt_regs *, struct user *); extern int dump_fpu(elf_fpregset_t *); @@ -42,6 +43,11 @@ EXPORT_SYMBOL_NOVERS(__up_wakeup); EXPORT_SYMBOL(__intel_bh_counter); /* Networking helper routines. */ EXPORT_SYMBOL(csum_partial_copy); +/* Delay loops */ +EXPORT_SYMBOL(__udelay); +EXPORT_SYMBOL(__delay); +EXPORT_SYMBOL(__const_udelay); + #ifdef __SMP__ EXPORT_SYMBOL(apic_reg); /* Needed internally for the I386 inlines */ @@ -63,6 +69,7 @@ EXPORT_SYMBOL(__global_restore_flags); #ifdef CONFIG_MCA /* Adapter probing and info methods. */ +EXPORT_SYMBOL(machine_id); EXPORT_SYMBOL(mca_find_adapter); EXPORT_SYMBOL(mca_write_pos); EXPORT_SYMBOL(mca_read_pos); diff --git a/arch/i386/kernel/ioport.c b/arch/i386/kernel/ioport.c index 8f929f603..9bb150075 100644 --- a/arch/i386/kernel/ioport.c +++ b/arch/i386/kernel/ioport.c @@ -75,17 +75,15 @@ unsigned int *stack; * code. */ -asmlinkage int sys_iopl(long ebx,long ecx,long edx, - long esi, long edi, long ebp, long eax, long ds, - long es, long orig_eax, long eip, long cs, - long eflags, long esp, long ss) +asmlinkage int sys_iopl(unsigned long unused) { - unsigned int level = ebx; + struct pt_regs * regs = (struct pt_regs *) &unused; + unsigned int level = regs->ebx; if (level > 3) return -EINVAL; if (!suser()) return -EPERM; - *(&eflags) = (eflags & 0xffffcfff) | (level << 12); + regs->eflags = (regs->eflags & 0xffffcfff) | (level << 12); return 0; } diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c index 590b69c38..9868811a6 100644 --- a/arch/i386/kernel/setup.c +++ b/arch/i386/kernel/setup.c @@ -42,6 +42,7 @@ char x86_model = 0; /* set by kernel/head.S */ char x86_mask = 0; /* set by kernel/head.S */ int x86_capability = 0; /* set by kernel/head.S */ int fdiv_bug = 0; /* set if Pentium(TM) with FP bug */ +int pentium_f00f_bug = 0; /* set if Pentium(TM) with F00F bug */ int have_cpuid = 0; /* set if CPUID instruction works */ char x86_vendor_id[13] = "unknown"; @@ -359,6 +360,7 @@ int get_cpuinfo(char * buffer) "fdiv_bug\t: %s\n" "hlt_bug\t\t: %s\n" "sep_bug\t\t: %s\n" + "f00f_bug\t: %s\n" "fpu\t\t: %s\n" "fpu_exception\t: %s\n" "cpuid\t\t: %s\n" @@ -367,6 +369,7 @@ int get_cpuinfo(char * buffer) CD(fdiv_bug) ? "yes" : "no", CD(hlt_works_ok) ? "no" : "yes", sep_bug ? "yes" : "no", + pentium_f00f_bug ? "yes" : "no", CD(hard_math) ? "yes" : "no", (CD(hard_math) && ignore_irq13) ? "yes" : "no", diff --git a/arch/i386/kernel/trampoline.S b/arch/i386/kernel/trampoline.S index d0a726f6b..f44b9abde 100644 --- a/arch/i386/kernel/trampoline.S +++ b/arch/i386/kernel/trampoline.S @@ -62,7 +62,7 @@ idt_48: gdt_48: .word 0x0800 # gdt limit = 2048, 256 GDT entries - .long gdt-0xc0000000 # gdt base = gdt (first SMP CPU) + .long gdt_table-0xc0000000 # gdt base = gdt (first SMP CPU) .globl SYMBOL_NAME(trampoline_end) SYMBOL_NAME_LABEL(trampoline_end) diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index 6fb18dc35..f08b7de6b 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c @@ -413,6 +413,39 @@ asmlinkage void math_emulate(long arg) #endif /* CONFIG_MATH_EMULATION */ +__initfunc(void trap_init_f00f_bug(void)) +{ + unsigned long page; + pgd_t * pgd; + pmd_t * pmd; + pte_t * pte; + + /* + * Allocate a new page in virtual address space, + * and move the IDT to have entry #7 starting at + * the beginning of the page. We'll force a page + * fault for IDT entries #0-#6.. + */ + page = (unsigned long) vmalloc(PAGE_SIZE); + memcpy((void *) page, idt_table, 256*8); + + pgd = pgd_offset(&init_mm, page); + pmd = pmd_offset(pgd, page); + pte = pte_offset(pmd, page); + *pte = pte_wrprotect(*pte); + local_flush_tlb(); + + /* + * "idt" is magic - it overlaps the idt_descr + * variable so that updating idt will automatically + * update the idt descriptor.. + */ + idt = (struct desc_struct *)page; + __asm__ __volatile__("lidt %0": "=m" (idt_descr)); +} + + + __initfunc(void trap_init(void)) { int i; diff --git a/arch/i386/lib/Makefile b/arch/i386/lib/Makefile index 7ea3f1e29..6b76e32d6 100644 --- a/arch/i386/lib/Makefile +++ b/arch/i386/lib/Makefile @@ -11,6 +11,6 @@ else endif L_TARGET = lib.a -L_OBJS = checksum.o semaphore.o locks.o +L_OBJS = checksum.o semaphore.o locks.o delay.o include $(TOPDIR)/Rules.make diff --git a/arch/i386/lib/delay.c b/arch/i386/lib/delay.c new file mode 100644 index 000000000..c3c29a7d9 --- /dev/null +++ b/arch/i386/lib/delay.c @@ -0,0 +1,45 @@ +/* + * Precise Delay Loops for i386 + * + * Copyright (C) 1993 Linus Torvalds + * Copyright (C) 1997 Martin Mares <mj@atrey.karlin.mff.cuni.cz> + * + * The __delay function must _NOT_ be inlined as its execution time + * depends wildly on alignment on many x86 processors. + */ + +#include <linux/sched.h> +#include <asm/delay.h> + +#ifdef __SMP__ +#include <asm/smp.h> +#endif + +#ifdef __SMP__ +#define __udelay_val cpu_data[smp_processor_id()].udelay_val +#else +#define __udelay_val loops_per_sec +#endif + +void __delay(unsigned long loops) +{ + __asm__ __volatile__( + "1:\tdecl %0\n\tjns 1b" + :/* no outputs */ + :"a" (loops) + :"ax"); +} + +inline void __const_udelay(unsigned long xloops) +{ + __asm__("mull %0" + :"=d" (xloops) + :"a" (xloops),"0" (__udelay_val) + :"ax"); + __delay(xloops); +} + +void __udelay(unsigned long usecs) +{ + __const_udelay(usecs * 0x000010c6); /* 2**32 / 1000000 */ +} diff --git a/arch/i386/mm/fault.c b/arch/i386/mm/fault.c index 8181fd6c7..beb9f91a4 100644 --- a/arch/i386/mm/fault.c +++ b/arch/i386/mm/fault.c @@ -74,6 +74,10 @@ bad_area: return 0; } +asmlinkage void do_invalid_op (struct pt_regs *, unsigned long); + +extern int pentium_f00f_bug; + /* * This routine handles page faults. It determines the address, * and the problem, and then passes it off to one of the appropriate @@ -86,18 +90,21 @@ bad_area: */ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code) { - struct task_struct *tsk = current; - struct mm_struct *mm = tsk->mm; + struct task_struct *tsk; + struct mm_struct *mm; struct vm_area_struct * vma; unsigned long address; unsigned long page; unsigned long fixup; int write; - lock_kernel(); - /* get the address */ __asm__("movl %%cr2,%0":"=r" (address)); + + lock_kernel(); + tsk = current; + mm = tsk->mm; + down(&mm->mmap_sem); vma = find_vma(mm, address); if (!vma) @@ -170,11 +177,27 @@ bad_area: goto out; } + /* + * Pentium F0 0F C7 C8 bug workaround. + */ + if (pentium_f00f_bug) { + unsigned long nr; + + nr = (address - (unsigned long) idt) >> 3; + + if (nr == 6) { + unlock_kernel(); + do_invalid_op(regs, 0); + return; + } + } + /* Are we prepared to handle this kernel fault? */ if ((fixup = search_exception_table(regs->eip)) != 0) { - printk(KERN_DEBUG "%s: Exception at [<%lx>] (%lx)\n", + printk(KERN_DEBUG "%s: Exception at [<%lx>] cr2=%lx (fixup: %lx)\n", tsk->comm, regs->eip, + address, fixup); regs->eip = fixup; goto out; @@ -192,6 +215,7 @@ bad_area: flush_tlb(); goto out; } + if (address < PAGE_SIZE) printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference"); else |