summaryrefslogtreecommitdiffstats
path: root/arch/i386
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1997-12-06 23:51:34 +0000
committerRalf Baechle <ralf@linux-mips.org>1997-12-06 23:51:34 +0000
commit230e5ab6a084ed50470f101934782dbf54b0d06b (patch)
tree5dd821c8d33f450470588e7a543f74bf74306e9e /arch/i386
parentc9b1c8a64c6444d189856f1e26bdcb8b4cd0113a (diff)
Merge with Linux 2.1.67.
Diffstat (limited to 'arch/i386')
-rw-r--r--arch/i386/boot/compressed/misc.c9
-rw-r--r--arch/i386/config.in2
-rw-r--r--arch/i386/defconfig26
-rw-r--r--arch/i386/kernel/entry.S3
-rw-r--r--arch/i386/kernel/head.S40
-rw-r--r--arch/i386/kernel/i386_ksyms.c7
-rw-r--r--arch/i386/kernel/ioport.c10
-rw-r--r--arch/i386/kernel/setup.c3
-rw-r--r--arch/i386/kernel/trampoline.S2
-rw-r--r--arch/i386/kernel/traps.c33
-rw-r--r--arch/i386/lib/Makefile2
-rw-r--r--arch/i386/lib/delay.c45
-rw-r--r--arch/i386/mm/fault.c34
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