summaryrefslogtreecommitdiffstats
path: root/arch/i386
diff options
context:
space:
mode:
Diffstat (limited to 'arch/i386')
-rw-r--r--arch/i386/config.in3
-rw-r--r--arch/i386/defconfig93
-rw-r--r--arch/i386/kernel/Makefile2
-rw-r--r--arch/i386/kernel/acpi.c60
-rw-r--r--arch/i386/kernel/apic.c2
-rw-r--r--arch/i386/kernel/bluesmoke.c109
-rw-r--r--arch/i386/kernel/entry.S6
-rw-r--r--arch/i386/kernel/io_apic.c62
-rw-r--r--arch/i386/kernel/microcode.c12
-rw-r--r--arch/i386/kernel/mpparse.c23
-rw-r--r--arch/i386/kernel/mtrr.c61
-rw-r--r--arch/i386/kernel/process.c19
-rw-r--r--arch/i386/kernel/ptrace.c1
-rw-r--r--arch/i386/kernel/setup.c36
-rw-r--r--arch/i386/kernel/signal.c9
-rw-r--r--arch/i386/kernel/smp.c9
-rw-r--r--arch/i386/kernel/smpboot.c26
-rw-r--r--arch/i386/kernel/time.c39
-rw-r--r--arch/i386/kernel/traps.c54
-rw-r--r--arch/i386/kernel/vm86.c4
-rw-r--r--arch/i386/lib/checksum.S12
-rw-r--r--arch/i386/mm/ioremap.c2
22 files changed, 450 insertions, 194 deletions
diff --git a/arch/i386/config.in b/arch/i386/config.in
index 4f41a46f7..6d1279ed7 100644
--- a/arch/i386/config.in
+++ b/arch/i386/config.in
@@ -128,6 +128,7 @@ if [ "$CONFIG_MWINCHIP3D" = "y" ]; then
define_bool CONFIG_X86_USE_PPRO_CHECKSUM y
define_bool CONFIG_X86_USE_3DNOW y
fi
+tristate 'Toshiba Laptop support' CONFIG_TOSHIBA
tristate '/dev/cpu/microcode - Intel P6 CPU microcode support' CONFIG_MICROCODE
tristate '/dev/cpu/*/msr - Model-specific register support' CONFIG_X86_MSR
@@ -248,6 +249,8 @@ source drivers/pnp/Config.in
source drivers/block/Config.in
+source drivers/md/Config.in
+
if [ "$CONFIG_NET" = "y" ]; then
source net/Config.in
fi
diff --git a/arch/i386/defconfig b/arch/i386/defconfig
index ce51570da..7dddf3057 100644
--- a/arch/i386/defconfig
+++ b/arch/i386/defconfig
@@ -26,8 +26,8 @@ CONFIG_KMOD=y
# CONFIG_M586 is not set
# CONFIG_M586TSC is not set
# CONFIG_M586MMX is not set
-CONFIG_M686=y
-# CONFIG_M686FXSR is not set
+# CONFIG_M686 is not set
+CONFIG_M686FXSR=y
# CONFIG_MK6 is not set
# CONFIG_MK7 is not set
# CONFIG_MCRUSOE is not set
@@ -44,13 +44,15 @@ CONFIG_X86_TSC=y
CONFIG_X86_GOOD_APIC=y
CONFIG_X86_PGE=y
CONFIG_X86_USE_PPRO_CHECKSUM=y
+CONFIG_X86_FXSR=y
+CONFIG_X86_XMM=y
+# CONFIG_TOSHIBA is not set
# CONFIG_MICROCODE is not set
# CONFIG_X86_MSR is not set
# CONFIG_X86_CPUID is not set
CONFIG_NOHIGHMEM=y
# CONFIG_HIGHMEM4G is not set
# CONFIG_HIGHMEM64G is not set
-# CONFIG_MATH_EMULATION is not set
# CONFIG_MTRR is not set
CONFIG_SMP=y
CONFIG_HAVE_DEC_LOCK=y
@@ -112,17 +114,24 @@ CONFIG_BLK_DEV_FD=y
# CONFIG_BLK_DEV_XD is not set
# CONFIG_PARIDE is not set
# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
# CONFIG_BLK_DEV_DAC960 is not set
# CONFIG_BLK_DEV_LOOP is not set
# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_LVM is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
# CONFIG_BLK_DEV_MD is not set
# CONFIG_MD_LINEAR is not set
# CONFIG_MD_RAID0 is not set
# CONFIG_MD_RAID1 is not set
# CONFIG_MD_RAID5 is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_BLK_DEV_LVM is not set
+# CONFIG_LVM_PROC_FS is not set
#
# Networking options
@@ -224,7 +233,6 @@ CONFIG_IDEPCI_SHARE_IRQ=y
# CONFIG_BLK_DEV_SIS5513 is not set
# CONFIG_BLK_DEV_TRM290 is not set
# CONFIG_BLK_DEV_VIA82CXXX is not set
-# CONFIG_VIA82CXXX_TUNING is not set
# CONFIG_IDE_CHIPSETS is not set
# CONFIG_IDEDMA_AUTO is not set
# CONFIG_DMA_NONPCI is not set
@@ -262,12 +270,12 @@ CONFIG_SCSI_CONSTANTS=y
# CONFIG_SCSI_AHA1542 is not set
# CONFIG_SCSI_AHA1740 is not set
# CONFIG_SCSI_AIC7XXX is not set
-# CONFIG_SCSI_IPS is not set
# CONFIG_SCSI_ADVANSYS is not set
# CONFIG_SCSI_IN2000 is not set
# CONFIG_SCSI_AM53C974 is not set
# CONFIG_SCSI_MEGARAID is not set
# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_CPQFCTS is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_DTC3280 is not set
# CONFIG_SCSI_EATA is not set
@@ -276,11 +284,10 @@ CONFIG_SCSI_CONSTANTS=y
# CONFIG_SCSI_FUTURE_DOMAIN is not set
# CONFIG_SCSI_GDTH is not set
# CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_IPS is not set
# CONFIG_SCSI_INITIO is not set
# CONFIG_SCSI_INIA100 is not set
# CONFIG_SCSI_NCR53C406A is not set
-# CONFIG_SCSI_SYM53C416 is not set
-# CONFIG_SCSI_SIM710 is not set
# CONFIG_SCSI_NCR53C7xx is not set
# CONFIG_SCSI_NCR53C8XX is not set
CONFIG_SCSI_SYM53C8XX=y
@@ -299,6 +306,8 @@ CONFIG_SCSI_NCR53C8XX_SYNC=20
# CONFIG_SCSI_QLOGIC_FC is not set
# CONFIG_SCSI_QLOGIC_1280 is not set
# CONFIG_SCSI_SEAGATE is not set
+# CONFIG_SCSI_SIM710 is not set
+# CONFIG_SCSI_SYM53C416 is not set
# CONFIG_SCSI_DC390T is not set
# CONFIG_SCSI_T128 is not set
# CONFIG_SCSI_U14_34F is not set
@@ -357,14 +366,18 @@ CONFIG_EEPRO100=y
# CONFIG_NE2K_PCI is not set
# CONFIG_8139TOO is not set
# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
# CONFIG_TLAN is not set
# CONFIG_VIA_RHINE is not set
+# CONFIG_WINBOND_840 is not set
# CONFIG_NET_POCKET is not set
#
# Ethernet (1000 Mbit)
#
# CONFIG_ACENIC is not set
+# CONFIG_HAMACHI is not set
# CONFIG_SK98LIN is not set
# CONFIG_FDDI is not set
# CONFIG_PPP is not set
@@ -501,10 +514,6 @@ CONFIG_PCMCIA_SERIAL=y
#
# Multimedia devices
#
-
-#
-# Video For Linux
-#
# CONFIG_VIDEO_DEV is not set
#
@@ -588,12 +597,64 @@ CONFIG_VGA_CONSOLE=y
#
# Sound
#
-# CONFIG_SOUND is not set
+CONFIG_SOUND=y
+# CONFIG_SOUND_CMPCI is not set
+# CONFIG_SOUND_EMU10K1 is not set
+# CONFIG_SOUND_FUSION is not set
+# CONFIG_SOUND_CS4281 is not set
+# CONFIG_SOUND_ES1370 is not set
+CONFIG_SOUND_ES1371=y
+# CONFIG_SOUND_ESSSOLO1 is not set
+# CONFIG_SOUND_MAESTRO is not set
+# CONFIG_SOUND_SONICVIBES is not set
+# CONFIG_SOUND_TRIDENT is not set
+# CONFIG_SOUND_MSNDCLAS is not set
+# CONFIG_SOUND_MSNDPIN is not set
+# CONFIG_SOUND_VIA82CXXX is not set
+# CONFIG_SOUND_OSS is not set
+# CONFIG_SOUND_TVMIXER is not set
#
# USB support
#
-# CONFIG_USB is not set
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+# CONFIG_USB_DEVICEFS is not set
+# CONFIG_USB_BANDWIDTH is not set
+
+#
+# USB Controllers
+#
+CONFIG_USB_UHCI_ALT=y
+# CONFIG_USB_OHCI is not set
+
+#
+# USB Devices
+#
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_SCANNER is not set
+# CONFIG_USB_AUDIO is not set
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_SERIAL is not set
+# CONFIG_USB_IBMCAM is not set
+# CONFIG_USB_OV511 is not set
+# CONFIG_USB_DC2XX is not set
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_USS720 is not set
+# CONFIG_USB_DABUSB is not set
+
+#
+# USB Human Interface Devices (HID)
+#
+
+#
+# Input core support is needed for USB HID
+#
#
# Kernel hacking
diff --git a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile
index d1388eec3..a8ea61306 100644
--- a/arch/i386/kernel/Makefile
+++ b/arch/i386/kernel/Makefile
@@ -18,7 +18,7 @@ export-objs := mca.o mtrr.o msr.o cpuid.o microcode.o i386_ksyms.o
obj-y := process.o semaphore.o signal.o entry.o traps.o irq.o vm86.o \
ptrace.o i8259.o ioport.o ldt.o setup.o time.o sys_i386.o \
- pci-dma.o i386_ksyms.o i387.o
+ pci-dma.o i386_ksyms.o i387.o bluesmoke.o
ifdef CONFIG_PCI
diff --git a/arch/i386/kernel/acpi.c b/arch/i386/kernel/acpi.c
index 9993d8331..211a6ce50 100644
--- a/arch/i386/kernel/acpi.c
+++ b/arch/i386/kernel/acpi.c
@@ -21,6 +21,12 @@
/*
* See http://www.geocities.com/SiliconValley/Hardware/3165/
* for the user-level ACPI stuff
+ *
+ * Changes:
+ * Arnaldo Carvalho de Melo <acme@conectiva.com.br> - 2000/08/31
+ * - check copy*user return
+ * - get rid of check_region
+ * - get rid of verify_area
*/
#include <linux/config.h>
@@ -135,8 +141,7 @@ static int acpi_do_stat(ctl_table *ctl,
*len = 0;
return 0;
}
- copy_to_user(buffer, str, size);
- return 0;
+ return copy_to_user(buffer, str, size) ? -EFAULT : 0;
}
static void cx_statistics(unsigned int x, unsigned long time)
@@ -1283,11 +1288,9 @@ static void acpi_power_off(void)
*/
static int acpi_claim(unsigned long start, unsigned long size)
{
- if (start && size) {
- if (check_region(start, size))
+ if (start && size)
+ if (!request_region(start, size, "acpi"))
return -EBUSY;
- request_region(start, size, "acpi");
- }
return 0;
}
@@ -1391,7 +1394,8 @@ static int acpi_do_ulong(ctl_table *ctl,
val = *(unsigned long*) ctl->data;
size = sprintf(str, "0x%08lx\n", val);
if (*len >= size) {
- copy_to_user(buffer, str, size);
+ if (copy_to_user(buffer, str, size))
+ return -EFAULT;
*len = size;
}
else
@@ -1404,7 +1408,8 @@ static int acpi_do_ulong(ctl_table *ctl,
size = sizeof(str) - 1;
if (size > *len)
size = *len;
- copy_from_user(str, buffer, size);
+ if (copy_from_user(str, buffer, size))
+ return -EFAULT;
str[size] = '\0';
val = simple_strtoul(str, &strend, 0);
if (strend == str)
@@ -1423,22 +1428,22 @@ static int acpi_verify_table(void *buffer,
size_t size,
struct acpi_table_info *info)
{
+ struct acpi_table hdr;
+ size_t table_size;
+
if (size < sizeof(struct acpi_table))
return -EINVAL;
- else if (verify_area(VERIFY_READ, buffer, size))
+
+ if (copy_from_user(&hdr, buffer, sizeof(hdr)))
return -EFAULT;
- else {
- struct acpi_table hdr;
- size_t table_size;
- copy_from_user(&hdr, buffer, sizeof(hdr));
- table_size = (size_t) hdr.length;
- if (hdr.signature != info->expected_signature
- || table_size < size
- || (info->expected_size
- && table_size != info->expected_size))
- return -EINVAL;
- }
+ table_size = (size_t) hdr.length;
+ if (hdr.signature != info->expected_signature
+ || table_size < size
+ || (info->expected_size
+ && table_size != info->expected_size))
+ return -EINVAL;
+
return 0;
}
@@ -1496,7 +1501,8 @@ static int acpi_do_table(ctl_table *ctl,
error = acpi_verify_table(buffer, *len, info);
if (error)
return error;
- copy_from_user(&hdr, buffer, sizeof(hdr));
+ if (copy_from_user(&hdr, buffer, sizeof(hdr)))
+ return -EFAULT;
table_size = (size_t) hdr.length;
write_lock(&acpi_do_table_lock);
@@ -1517,7 +1523,8 @@ static int acpi_do_table(ctl_table *ctl,
error = -ENOMEM;
}
if (data)
- copy_from_user(data, buffer, size);
+ if (copy_from_user(data, buffer, size))
+ error = -EFAULT;
write_unlock(&acpi_do_table_lock);
}
@@ -1565,7 +1572,8 @@ static int acpi_do_event_reg(ctl_table *ctl,
size = sprintf(str, "0x%08x\n", val);
if (*len >= size) {
- copy_to_user(buffer, str, size);
+ if (copy_to_user(buffer, str, size))
+ return -EFAULT;
*len = size;
}
else
@@ -1580,7 +1588,8 @@ static int acpi_do_event_reg(ctl_table *ctl,
size = sizeof(str) - 1;
if (size > *len)
size = *len;
- copy_from_user(str, buffer, size);
+ if (copy_from_user(str, buffer, size))
+ return -EFAULT;
str[size] = '\0';
val = (u32) simple_strtoul(str, &strend, 0);
if (strend == str)
@@ -1682,7 +1691,8 @@ static int acpi_do_event(ctl_table *ctl,
pm1_status,
gpe_status,
event_state);
- copy_to_user(buffer, str, size);
+ if (copy_to_user(buffer, str, size))
+ return -EFAULT;
*len = size;
file->f_pos += size;
diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c
index 1626761fb..4e5df4681 100644
--- a/arch/i386/kernel/apic.c
+++ b/arch/i386/kernel/apic.c
@@ -695,7 +695,7 @@ inline void smp_local_timer_interrupt(struct pt_regs * regs)
* [ if a single-CPU system runs an SMP kernel then we call the local
* interrupt as well. Thus we cannot inline the local irq ... ]
*/
-unsigned int apic_timer_irqs [NR_CPUS] = { 0, };
+unsigned int apic_timer_irqs [NR_CPUS];
void smp_apic_timer_interrupt(struct pt_regs * regs)
{
diff --git a/arch/i386/kernel/bluesmoke.c b/arch/i386/kernel/bluesmoke.c
new file mode 100644
index 000000000..0fecf5851
--- /dev/null
+++ b/arch/i386/kernel/bluesmoke.c
@@ -0,0 +1,109 @@
+/*
+ * Machine Check Handler For PII/PIII
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <asm/processor.h>
+#include <asm/msr.h>
+
+static int banks = 0;
+
+void mcheck_fault(void)
+{
+ int recover=1;
+ u32 alow, ahigh, high, low;
+ u32 mcgstl, mcgsth;
+ int i;
+
+ rdmsr(0x17a, mcgstl, mcgsth);
+ if(mcgstl&(1<<0)) /* Recoverable ? */
+ recover=0;
+
+ printk(KERN_EMERG "CPU %d: Machine Check Exception: %08x%08x\n", smp_processor_id(), mcgsth, mcgstl);
+
+ for(i=0;i<banks;i++)
+ {
+ rdmsr(0x401+i*4,low, high);
+ if(high&(1<<31))
+ {
+ if(high&(1<<29))
+ recover|=1;
+ if(high&(1<<25))
+ recover|=2;
+ printk(KERN_EMERG "Bank %d: %08x%08x", i, high, low);
+ high&=~(1<<31);
+ if(high&(1<<27))
+ {
+ rdmsr(0x402+i*4, alow, ahigh);
+ printk("[%08x%08x]", alow, ahigh);
+ }
+ if(high&(1<<26))
+ {
+ rdmsr(0x402+i*4, alow, ahigh);
+ printk(" at %08x%08x",
+ high, low);
+ }
+ /* Clear it */
+ wrmsr(0x401+i*4, 0UL, 0UL);
+ /* Serialize */
+ wmb();
+ }
+ }
+
+ if(recover&2)
+ panic("CPU context corrupt");
+ if(recover&1)
+ panic("Unable to continue");
+ printk(KERN_EMERG "Attempting to continue.\n");
+ mcgstl&=~(1<<2);
+ wrmsr(0x17a,mcgstl, mcgsth);
+}
+
+
+/*
+ * This has to be run for each processor
+ */
+
+void mcheck_init(void)
+{
+ u32 l, h;
+ int i;
+ struct cpuinfo_x86 *c;
+ static int done=0;
+
+ c=cpu_data+smp_processor_id();
+
+ if(c->x86_vendor!=X86_VENDOR_INTEL)
+ return;
+
+ if(!(c->x86_capability&X86_FEATURE_MCE))
+ return;
+
+ if(!(c->x86_capability&X86_FEATURE_MCA))
+ return;
+
+ /* Ok machine check is available */
+
+ if(done==0)
+ printk(KERN_INFO "Intel machine check architecture supported.\n");
+ rdmsr(0x179, l, h);
+ if(l&(1<<8))
+ wrmsr(0x17b, 0xffffffff, 0xffffffff);
+ banks = l&0xff;
+ for(i=1;i<banks;i++)
+ {
+ wrmsr(0x400+4*i, 0xffffffff, 0xffffffff);
+ }
+ for(i=0;i<banks;i++)
+ {
+ wrmsr(0x401+4*i, 0x0, 0x0);
+ }
+ __asm__ __volatile__ (
+ "movl %%cr4, %%eax\n\t"
+ "orl $0x40, %%eax\n\t"
+ "movl %%eax, %%cr4\n\t" : : : "eax");
+ printk(KERN_INFO "Intel machine check reporting enabled on CPU#%d.\n", smp_processor_id());
+ done=1;
+}
diff --git a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S
index fb9b7b2ea..57aada831 100644
--- a/arch/i386/kernel/entry.S
+++ b/arch/i386/kernel/entry.S
@@ -414,6 +414,11 @@ ENTRY(page_fault)
pushl $ SYMBOL_NAME(do_page_fault)
jmp error_code
+ENTRY(machine_check)
+ pushl $0
+ pushl $ SYMBOL_NAME(mcheck_fault)
+ jmp error_code
+
ENTRY(spurious_interrupt_bug)
pushl $0
pushl $ SYMBOL_NAME(do_spurious_interrupt_bug)
@@ -643,6 +648,7 @@ ENTRY(sys_call_table)
.long SYMBOL_NAME(sys_madvise)
.long SYMBOL_NAME(sys_getdents64) /* 220 */
.long SYMBOL_NAME(sys_fcntl64)
+ .long SYMBOL_NAME(sys_ni_syscall) /* reserved for TUX */
/*
* NOTE!! This doesn't have to be exact - we just have
diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c
index e1b00a702..c5aece040 100644
--- a/arch/i386/kernel/io_apic.c
+++ b/arch/i386/kernel/io_apic.c
@@ -38,7 +38,7 @@ static spinlock_t ioapic_lock = SPIN_LOCK_UNLOCKED;
/*
* # of IO-APICs and # of IRQ routing registers
*/
-int nr_ioapics = 0;
+int nr_ioapics;
int nr_ioapic_registers[MAX_IO_APICS];
/* I/O APIC entries */
@@ -48,7 +48,7 @@ struct mpc_config_ioapic mp_ioapics[MAX_IO_APICS];
struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES];
/* MP IRQ source entries */
-int mp_irq_entries = 0;
+int mp_irq_entries;
#if CONFIG_SMP
# define TARGET_CPUS cpu_online_map
@@ -172,8 +172,8 @@ static void clear_IO_APIC (void)
#define MAX_PIRQS 8
int pirq_entries [MAX_PIRQS];
-int pirqs_enabled = 0;
-int skip_ioapic_setup = 0;
+int pirqs_enabled;
+int skip_ioapic_setup;
static int __init ioapic_setup(char *str)
{
@@ -219,10 +219,10 @@ static int __init find_irq_entry(int apic, int pin, int type)
int i;
for (i = 0; i < mp_irq_entries; i++)
- if ( (mp_irqs[i].mpc_irqtype == type) &&
- (mp_irqs[i].mpc_dstapic == mp_ioapics[apic].mpc_apicid) &&
- (mp_irqs[i].mpc_dstirq == pin))
-
+ if (mp_irqs[i].mpc_irqtype == type &&
+ (mp_irqs[i].mpc_dstapic == mp_ioapics[apic].mpc_apicid ||
+ mp_irqs[i].mpc_dstapic == MP_APIC_ALL) &&
+ mp_irqs[i].mpc_dstirq == pin)
return i;
return -1;
@@ -262,7 +262,8 @@ int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pci_pin)
int lbus = mp_irqs[i].mpc_srcbus;
for (apic = 0; apic < nr_ioapics; apic++)
- if (mp_ioapics[apic].mpc_apicid == mp_irqs[i].mpc_dstapic)
+ if (mp_ioapics[apic].mpc_apicid == mp_irqs[i].mpc_dstapic ||
+ mp_irqs[i].mpc_dstapic == MP_APIC_ALL)
break;
if ((mp_bus_id_to_type[lbus] == MP_BUS_PCI) &&
@@ -982,7 +983,10 @@ void disable_IO_APIC(void)
static void __init setup_ioapic_ids_from_mpc (void)
{
struct IO_APIC_reg_00 reg_00;
+ unsigned long phys_id_present_map = phys_cpu_present_map;
int apic;
+ int i;
+ unsigned char old_id;
/*
* Set the IOAPIC ID to the value stored in the MPC table.
@@ -992,6 +996,8 @@ static void __init setup_ioapic_ids_from_mpc (void)
/* Read the register 0 value */
*(int *)&reg_00 = io_apic_read(apic, 0);
+ old_id = mp_ioapics[apic].mpc_apicid;
+
if (mp_ioapics[apic].mpc_apicid >= 0xf) {
printk(KERN_ERR "BIOS bug, IO-APIC#%d ID is %d in the MPC table!...\n",
apic, mp_ioapics[apic].mpc_apicid);
@@ -1001,21 +1007,41 @@ static void __init setup_ioapic_ids_from_mpc (void)
}
/*
+ * Sanity check, is the ID really free? Every APIC in a
+ * system must have a unique ID or we get lots of nice
+ * 'stuck on smp_invalidate_needed IPI wait' messages.
+ */
+ if (phys_id_present_map & (1 << mp_ioapics[apic].mpc_apicid)) {
+ printk(KERN_ERR "BIOS bug, IO-APIC#%d ID %d is already used!...\n",
+ apic, mp_ioapics[apic].mpc_apicid);
+ for (i = 0; i < 0xf; i++)
+ if (!(phys_id_present_map & (1 << i)))
+ break;
+ if (i >= 0xf)
+ panic("Max APIC ID exceeded!\n");
+ printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n",
+ i);
+ phys_id_present_map |= 1 << i;
+ mp_ioapics[apic].mpc_apicid = i;
+ }
+
+ /*
+ * We need to adjust the IRQ routing table
+ * if the ID changed.
+ */
+ if (old_id != mp_ioapics[apic].mpc_apicid)
+ for (i = 0; i < mp_irq_entries; i++)
+ if (mp_irqs[i].mpc_dstapic == old_id)
+ mp_irqs[i].mpc_dstapic
+ = mp_ioapics[apic].mpc_apicid;
+
+ /*
* Read the right value from the MPC table and
* write it into the ID register.
*/
printk(KERN_INFO "...changing IO-APIC physical APIC ID to %d ...",
mp_ioapics[apic].mpc_apicid);
- /*
- * Sanity check, is the ID really free? Every APIC in the
- * system must have a unique ID or we get lots of nice
- * 'stuck on smp_invalidate_needed IPI wait' messages.
- */
- if (phys_cpu_present_map & (1<<mp_ioapics[apic].mpc_apicid))
- panic("APIC ID %d already used",
- mp_ioapics[apic].mpc_apicid);
-
reg_00.ID = mp_ioapics[apic].mpc_apicid;
io_apic_write(apic, 0, *(int *)&reg_00);
diff --git a/arch/i386/kernel/microcode.c b/arch/i386/kernel/microcode.c
index 1d5b7b3c8..80536a1c4 100644
--- a/arch/i386/kernel/microcode.c
+++ b/arch/i386/kernel/microcode.c
@@ -37,6 +37,13 @@
* Removed ->release(). Removed exclusive open and status bitmap.
* Added microcode_rwsem to serialize read()/write()/ioctl().
* Removed global kernel lock usage.
+ * 1.07 07 Sep 2000, Tigran Aivazian <tigran@veritas.com>
+ * Write 0 to 0x8B msr and then cpuid before reading revision,
+ * so that it works even if there were no update done by the
+ * BIOS. Otherwise, reading from 0x8B gives junk (which happened
+ * to be 0 on my machine which is why it worked even when I
+ * disabled update by the BIOS)
+ * Thanks to Eric W. Biederman <ebiederman@lnxi.com> for the fix.
*/
#include <linux/init.h>
@@ -51,7 +58,7 @@
#include <asm/uaccess.h>
#include <asm/processor.h>
-#define MICROCODE_VERSION "1.06"
+#define MICROCODE_VERSION "1.07"
MODULE_DESCRIPTION("Intel CPU (P6) microcode update driver");
MODULE_AUTHOR("Tigran Aivazian <tigran@veritas.com>");
@@ -188,7 +195,8 @@ static void do_update_one(void *unused)
microcode[i].ldrver == 1 && microcode[i].hdrver == 1) {
found=1;
-
+ wrmsr(0x8B, 0, 0);
+ __asm__ __volatile__ ("cpuid" : : : "ax", "bx", "cx", "dx");
rdmsr(0x8B, val[0], rev);
if (microcode[i].rev <= rev) {
printk(KERN_ERR
diff --git a/arch/i386/kernel/mpparse.c b/arch/i386/kernel/mpparse.c
index 746bea030..b17c30041 100644
--- a/arch/i386/kernel/mpparse.c
+++ b/arch/i386/kernel/mpparse.c
@@ -28,26 +28,26 @@
#include <asm/pgalloc.h>
/* Have we found an MP table */
-int smp_found_config = 0;
+int smp_found_config;
/*
* Various Linux-internal data structures created from the
* MP-table.
*/
int apic_version [MAX_APICS];
-int mp_bus_id_to_type [MAX_MP_BUSSES] = { -1, };
+int mp_bus_id_to_type [MAX_MP_BUSSES];
int mp_bus_id_to_pci_bus [MAX_MP_BUSSES] = { -1, };
-int mp_current_pci_id = 0;
+int mp_current_pci_id;
int pic_mode;
-unsigned long mp_lapic_addr = 0;
+unsigned long mp_lapic_addr;
/* Processor that is doing the boot up */
unsigned int boot_cpu_id = -1U;
/* Internal processor count */
-static unsigned int num_processors = 0;
+static unsigned int num_processors;
/* Bitmask of physically existing CPUs */
-unsigned long phys_cpu_present_map = 0;
+unsigned long phys_cpu_present_map;
/*
* Intel MP BIOS table parsing routines:
@@ -158,19 +158,18 @@ static void __init MP_bus_info (struct mpc_config_bus *m)
str[6] = 0;
Dprintk("Bus #%d is %s\n", m->mpc_busid, str);
- if (strncmp(str, "ISA", 3) == 0) {
+ if (strncmp(str, BUSTYPE_ISA, sizeof(BUSTYPE_ISA)-1) == 0) {
mp_bus_id_to_type[m->mpc_busid] = MP_BUS_ISA;
- } else if (strncmp(str, "EISA", 4) == 0) {
+ } else if (strncmp(str, BUSTYPE_EISA, sizeof(BUSTYPE_EISA)-1) == 0) {
mp_bus_id_to_type[m->mpc_busid] = MP_BUS_EISA;
- } else if (strncmp(str, "PCI", 3) == 0) {
+ } else if (strncmp(str, BUSTYPE_PCI, sizeof(BUSTYPE_PCI)-1) == 0) {
mp_bus_id_to_type[m->mpc_busid] = MP_BUS_PCI;
mp_bus_id_to_pci_bus[m->mpc_busid] = mp_current_pci_id;
mp_current_pci_id++;
- } else if (strncmp(str, "MCA", 3) == 0) {
+ } else if (strncmp(str, BUSTYPE_MCA, sizeof(BUSTYPE_MCA)-1) == 0) {
mp_bus_id_to_type[m->mpc_busid] = MP_BUS_MCA;
} else {
- printk("Unknown bustype %s\n", str);
- panic("cannot handle bus - mail to linux-smp@vger.kernel.org");
+ printk("Unknown bustype %s - ignoring\n", str);
}
}
diff --git a/arch/i386/kernel/mtrr.c b/arch/i386/kernel/mtrr.c
index 05b57c93a..abe198315 100644
--- a/arch/i386/kernel/mtrr.c
+++ b/arch/i386/kernel/mtrr.c
@@ -319,10 +319,10 @@ typedef u8 mtrr_type;
#endif
#ifdef USERSPACE_INTERFACE
-static char *ascii_buffer = NULL;
-static unsigned int ascii_buf_bytes = 0;
+static char *ascii_buffer;
+static unsigned int ascii_buf_bytes;
#endif
-static unsigned int *usage_table = NULL;
+static unsigned int *usage_table;
static DECLARE_MUTEX(main_lock);
/* Private functions */
@@ -356,7 +356,8 @@ static void set_mtrr_prepare (struct set_mtrr_context *ctxt)
if (boot_cpu_data.x86 >= 6) break; /* Athlon and post-Athlon CPUs */
/* else fall through */
case X86_VENDOR_CENTAUR:
- return;
+ if(boot_cpu_data.x86 != 6)
+ return;
/*break;*/
}
/* Save value of CR4 and clear Page Global Enable (bit 7) */
@@ -380,6 +381,7 @@ static void set_mtrr_prepare (struct set_mtrr_context *ctxt)
{
case X86_VENDOR_AMD:
case X86_VENDOR_INTEL:
+ case X86_VENDOR_CENTAUR:
/* Disable MTRRs, and set the default type to uncached */
rdmsr (MTRRdefType_MSR, ctxt->deftype_lo, ctxt->deftype_hi);
wrmsr (MTRRdefType_MSR, ctxt->deftype_lo & 0xf300UL, ctxt->deftype_hi);
@@ -403,8 +405,11 @@ static void set_mtrr_done (struct set_mtrr_context *ctxt)
if (boot_cpu_data.x86 >= 6) break; /* Athlon and post-Athlon CPUs */
/* else fall through */
case X86_VENDOR_CENTAUR:
- __restore_flags (ctxt->flags);
- return;
+ if(boot_cpu_data.x86 != 6)
+ {
+ __restore_flags (ctxt->flags);
+ return;
+ }
/*break;*/
}
/* Flush caches and TLBs */
@@ -415,6 +420,7 @@ static void set_mtrr_done (struct set_mtrr_context *ctxt)
{
case X86_VENDOR_AMD:
case X86_VENDOR_INTEL:
+ case X86_VENDOR_CENTAUR:
wrmsr (MTRRdefType_MSR, ctxt->deftype_lo, ctxt->deftype_hi);
break;
case X86_VENDOR_CYRIX:
@@ -453,9 +459,17 @@ static unsigned int get_num_var_ranges (void)
/*break;*/
case X86_VENDOR_CYRIX:
/* Cyrix have 8 ARRs */
+ return 8;
case X86_VENDOR_CENTAUR:
/* and Centaur has 8 MCR's */
- return 8;
+ if(boot_cpu_data.x86==5)
+ return 8;
+ /* the cyrix III has intel compatible MTRR */
+ if(boot_cpu_data.x86==6)
+ {
+ rdmsr (MTRRcap_MSR, config, dummy);
+ return (config & 0xff);
+ }
/*break;*/
}
return 0;
@@ -471,12 +485,15 @@ static int have_wrcomb (void)
case X86_VENDOR_AMD:
if (boot_cpu_data.x86 < 6) return 1; /* pre-Athlon CPUs */
/* else fall through */
+ case X86_VENDOR_CENTAUR:
+ if (boot_cpu_data.x86 == 5)
+ return 1; /* C6 */
+ /* CyrixIII is Intel like */
case X86_VENDOR_INTEL:
rdmsr (MTRRcap_MSR, config, dummy);
return (config & (1<<10));
/*break;*/
case X86_VENDOR_CYRIX:
- case X86_VENDOR_CENTAUR:
return 1;
/*break;*/
}
@@ -623,7 +640,7 @@ static void centaur_get_mcr (unsigned int reg, unsigned long *base,
} /* End Function centaur_get_mcr */
static void (*get_mtrr) (unsigned int reg, unsigned long *base,
- unsigned long *size, mtrr_type *type) = NULL;
+ unsigned long *size, mtrr_type *type);
static void intel_set_mtrr_up (unsigned int reg, unsigned long base,
unsigned long size, mtrr_type type, int do_safe)
@@ -766,7 +783,7 @@ static void centaur_set_mcr_up (unsigned int reg, unsigned long base,
static void (*set_mtrr_up) (unsigned int reg, unsigned long base,
unsigned long size, mtrr_type type,
- int do_safe) = NULL;
+ int do_safe);
#ifdef CONFIG_SMP
@@ -1194,7 +1211,7 @@ int mtrr_add(unsigned long base, unsigned long size, unsigned int type, char inc
printk ("mtrr: size: %lx base: %lx\n", size, base);
return -EINVAL;
}
- if (boot_cpu_data.x86_vendor == X86_VENDOR_CENTAUR)
+ if (boot_cpu_data.x86_vendor == X86_VENDOR_CENTAUR && boot_cpu_data.x86 == 5)
{
if (type != MTRR_TYPE_WRCOMB)
{
@@ -1779,8 +1796,16 @@ static void __init mtrr_setup(void)
get_free_region = cyrix_get_free_region;
break;
case X86_VENDOR_CENTAUR:
- get_mtrr = centaur_get_mcr;
- set_mtrr_up = centaur_set_mcr_up;
+ if(boot_cpu_data.x86 == 5)
+ {
+ get_mtrr = centaur_get_mcr;
+ set_mtrr_up = centaur_set_mcr_up;
+ }
+ if(boot_cpu_data.x86 == 6)
+ {
+ get_mtrr = intel_get_mtrr;
+ set_mtrr_up = intel_set_mtrr_up;
+ }
break;
}
} /* End Function mtrr_setup */
@@ -1804,8 +1829,11 @@ void __init mtrr_init_boot_cpu(void)
case X86_VENDOR_CYRIX:
cyrix_arr_init ();
break;
- case X86_VENDOR_CENTAUR:
- centaur_mcr_init ();
+ case X86_VENDOR_CENTAUR: /* C6 and Cyrix III have different ones */
+ if(boot_cpu_data.x86 == 5)
+ centaur_mcr_init ();
+ if(boot_cpu_data.x86 == 6)
+ get_mtrr_state(&smp_mtrr_state);
break;
}
} /* End Function mtrr_init_boot_cpu */
@@ -1877,7 +1905,8 @@ int __init mtrr_init(void)
cyrix_arr_init ();
break;
case X86_VENDOR_CENTAUR:
- centaur_mcr_init ();
+ if(boot_cpu_data.x86 == 5)
+ centaur_mcr_init ();
break;
}
#endif /* !CONFIG_SMP */
diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
index 83ec9d192..6d3cf4d9a 100644
--- a/arch/i386/kernel/process.c
+++ b/arch/i386/kernel/process.c
@@ -50,17 +50,17 @@
asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
-int hlt_counter=0;
+int hlt_counter;
/*
* Powermanagement idle function, if any..
*/
-void (*pm_idle)(void) = NULL;
+void (*pm_idle)(void);
/*
* Power off function, if any
*/
-void (*pm_power_off)(void) = NULL;
+void (*pm_power_off)(void);
void disable_hlt(void)
{
@@ -149,9 +149,9 @@ static int __init idle_setup (char *str)
__setup("idle=", idle_setup);
-static long no_idt[2] = {0, 0};
-static int reboot_mode = 0;
-static int reboot_thru_bios = 0;
+static long no_idt[2];
+static int reboot_mode;
+static int reboot_thru_bios;
static int __init reboot_setup(char *str)
{
@@ -525,6 +525,7 @@ void copy_segments(struct task_struct *p, struct mm_struct *new_mm)
asm volatile("movl %%" #seg ",%0":"=m" (*(int *)&(value)))
int copy_thread(int nr, unsigned long clone_flags, unsigned long esp,
+ unsigned long unused,
struct task_struct * p, struct pt_regs * regs)
{
struct pt_regs * childregs;
@@ -686,7 +687,7 @@ void __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
asmlinkage int sys_fork(struct pt_regs regs)
{
- return do_fork(SIGCHLD, regs.esp, &regs);
+ return do_fork(SIGCHLD, regs.esp, &regs, 0);
}
asmlinkage int sys_clone(struct pt_regs regs)
@@ -698,7 +699,7 @@ asmlinkage int sys_clone(struct pt_regs regs)
newsp = regs.ecx;
if (!newsp)
newsp = regs.esp;
- return do_fork(clone_flags, newsp, &regs);
+ return do_fork(clone_flags, newsp, &regs, 0);
}
/*
@@ -713,7 +714,7 @@ asmlinkage int sys_clone(struct pt_regs regs)
*/
asmlinkage int sys_vfork(struct pt_regs regs)
{
- return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.esp, &regs);
+ return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.esp, &regs, 0);
}
/*
diff --git a/arch/i386/kernel/ptrace.c b/arch/i386/kernel/ptrace.c
index 0bafdc7e2..a9b11561d 100644
--- a/arch/i386/kernel/ptrace.c
+++ b/arch/i386/kernel/ptrace.c
@@ -99,6 +99,7 @@ static int putreg(struct task_struct *child,
case EFL:
value &= FLAG_MASK;
value |= get_stack_long(child, EFL_OFFSET) & ~FLAG_MASK;
+ break;
}
if (regno > GS*4)
regno -= 2*4;
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
index e79572f90..e765a0e94 100644
--- a/arch/i386/kernel/setup.c
+++ b/arch/i386/kernel/setup.c
@@ -95,22 +95,22 @@
* Machine setup..
*/
-char ignore_irq13 = 0; /* set if exception 16 works */
+char ignore_irq13; /* set if exception 16 works */
struct cpuinfo_x86 boot_cpu_data = { 0, 0, 0, 0, -1, 1, 0, 0, -1 };
-unsigned long mmu_cr4_features = 0;
+unsigned long mmu_cr4_features;
/*
* Bus types ..
*/
-int EISA_bus = 0;
-int MCA_bus = 0;
+int EISA_bus;
+int MCA_bus;
/* for MCA, but anyone else can use it if they want */
-unsigned int machine_id = 0;
-unsigned int machine_submodel_id = 0;
-unsigned int BIOS_revision = 0;
-unsigned int mca_pentium_flag = 0;
+unsigned int machine_id;
+unsigned int machine_submodel_id;
+unsigned int BIOS_revision;
+unsigned int mca_pentium_flag;
/*
* Setup options
@@ -123,7 +123,7 @@ struct sys_desc_table_struct {
unsigned char table[0];
};
-struct e820map e820 = { 0 };
+struct e820map e820;
unsigned char aux_device_present;
@@ -135,7 +135,7 @@ extern int rd_image_start; /* starting block # of image */
extern int root_mountflags;
extern char _text, _etext, _edata, _end;
-extern unsigned long cpu_hz;
+extern unsigned long cpu_khz;
/*
* This is set up by the setup-routine at boot-time
@@ -291,7 +291,7 @@ visws_get_board_type_and_rev(void)
#endif
-static char command_line[COMMAND_LINE_SIZE] = { 0, };
+static char command_line[COMMAND_LINE_SIZE];
char saved_command_line[COMMAND_LINE_SIZE];
struct resource standard_io_resources[] = {
@@ -875,7 +875,8 @@ static int __init amd_model(struct cpuinfo_x86 *c)
* Set MTRR capability flag if appropriate
*/
if(boot_cpu_data.x86 == 5) {
- if((boot_cpu_data.x86_model == 9) ||
+ if((boot_cpu_data.x86_model == 13) ||
+ (boot_cpu_data.x86_model == 9) ||
((boot_cpu_data.x86_model == 8) &&
(boot_cpu_data.x86_mask >= 8)))
c->x86_capability |= X86_FEATURE_MTRR;
@@ -916,7 +917,7 @@ static int __init amd_model(struct cpuinfo_x86 *c)
}
break;
}
- if (c->x86_model == 8 || c->x86_model == 9)
+ if (c->x86_model == 8 || c->x86_model == 9 || c->x86_model == 13)
{
/* The more serious chips .. */
@@ -1650,6 +1651,7 @@ int get_cpuinfo(char * buffer)
int i, n;
for (n = 0; n < NR_CPUS; n++, c++) {
+ int fpu_exception;
#ifdef CONFIG_SMP
if (!(cpu_online_map & (1<<n)))
continue;
@@ -1672,7 +1674,7 @@ int get_cpuinfo(char * buffer)
if (c->x86_capability & X86_FEATURE_TSC) {
p += sprintf(p, "cpu MHz\t\t: %lu.%06lu\n",
- cpu_hz / 1000000, (cpu_hz % 1000000));
+ cpu_khz / 1000, (cpu_khz % 1000));
}
/* Cache size */
@@ -1722,7 +1724,9 @@ int get_cpuinfo(char * buffer)
(c->x86_capability & X86_FEATURE_SEP) &&
c->x86_model < 3 &&
c->x86_mask < 3;
-
+
+ /* We use exception 16 if we have hardware math and we've either seen it or the CPU claims it is internal */
+ fpu_exception = c->hard_math && (ignore_irq13 | (c->x86_capability & X86_FEATURE_FPU));
p += sprintf(p, "fdiv_bug\t: %s\n"
"hlt_bug\t\t: %s\n"
"sep_bug\t\t: %s\n"
@@ -1739,7 +1743,7 @@ int get_cpuinfo(char * buffer)
c->f00f_bug ? "yes" : "no",
c->coma_bug ? "yes" : "no",
c->hard_math ? "yes" : "no",
- (c->hard_math && ignore_irq13) ? "yes" : "no",
+ fpu_exception ? "yes" : "no",
c->cpuid_level,
c->wp_works_ok ? "yes" : "no");
diff --git a/arch/i386/kernel/signal.c b/arch/i386/kernel/signal.c
index 116816f1f..2423a8b06 100644
--- a/arch/i386/kernel/signal.c
+++ b/arch/i386/kernel/signal.c
@@ -682,7 +682,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
/* FALLTHRU */
default:
- sigaddset(&current->signal, signr);
+ sigaddset(&current->pending.signal, signr);
recalc_sigpending(current);
current->flags |= PF_SIGNALED;
do_exit(exit_code);
@@ -690,6 +690,13 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
}
}
+ /* Reenable any watchpoints before delivering the
+ * signal to user space. The processor register will
+ * have been cleared if the watchpoint triggered
+ * inside the kernel.
+ */
+ __asm__("movl %0,%%db7" : : "r" (current->thread.debugreg[7]));
+
/* Whee! Actually deliver the signal. */
handle_signal(signr, ka, &info, oldset, regs);
return 1;
diff --git a/arch/i386/kernel/smp.c b/arch/i386/kernel/smp.c
index 4a118ab17..6ce9eb61e 100644
--- a/arch/i386/kernel/smp.c
+++ b/arch/i386/kernel/smp.c
@@ -414,13 +414,15 @@ void smp_send_reschedule(int cpu)
*/
static spinlock_t call_lock = SPIN_LOCK_UNLOCKED;
-static volatile struct call_data_struct {
+struct call_data_struct {
void (*func) (void *info);
void *info;
atomic_t started;
atomic_t finished;
int wait;
-} *call_data = NULL;
+};
+
+static struct call_data_struct * call_data = NULL;
/*
* this function sends a 'generic call function' IPI to all other CPUs
@@ -443,7 +445,7 @@ int smp_call_function (void (*func) (void *info), void *info, int nonatomic,
*/
{
struct call_data_struct data;
- int ret, cpus = smp_num_cpus-1;
+ int cpus = smp_num_cpus-1;
if (!cpus)
return 0;
@@ -464,7 +466,6 @@ int smp_call_function (void (*func) (void *info), void *info, int nonatomic,
while (atomic_read(&data.started) != cpus)
barrier();
- ret = 0;
if (wait)
while (atomic_read(&data.finished) != cpus)
barrier();
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
index 7629bb3d2..6092aec3b 100644
--- a/arch/i386/kernel/smpboot.c
+++ b/arch/i386/kernel/smpboot.c
@@ -46,7 +46,7 @@
#include <asm/pgalloc.h>
/* Set if we find a B stepping CPU */
-static int smp_b_stepping = 0;
+static int smp_b_stepping;
/* Setup configured maximum number of CPUs to activate */
static int max_cpus = -1;
@@ -55,21 +55,21 @@ static int max_cpus = -1;
int smp_num_cpus = 1;
/* Bitmask of currently online CPUs */
-unsigned long cpu_online_map = 0;
+unsigned long cpu_online_map;
/* which CPU (physical APIC ID) maps to which logical CPU number */
volatile int x86_apicid_to_cpu[NR_CPUS];
/* which logical CPU number maps to which CPU (physical APIC ID) */
volatile int x86_cpu_to_apicid[NR_CPUS];
-static volatile unsigned long cpu_callin_map = 0;
-static volatile unsigned long cpu_callout_map = 0;
+static volatile unsigned long cpu_callin_map;
+static volatile unsigned long cpu_callout_map;
/* Per CPU bogomips and other parameters */
struct cpuinfo_x86 cpu_data[NR_CPUS];
/* Set when the idlers are all forked */
-int smp_threads_ready = 0;
+int smp_threads_ready;
/*
* Setup routine for controlling SMP activation
@@ -194,7 +194,7 @@ void __init smp_commence(void)
static atomic_t tsc_start_flag = ATOMIC_INIT(0);
static atomic_t tsc_count_start = ATOMIC_INIT(0);
static atomic_t tsc_count_stop = ATOMIC_INIT(0);
-static unsigned long long tsc_values[NR_CPUS] = { 0, };
+static unsigned long long tsc_values[NR_CPUS];
#define NR_LOOPS 5
@@ -438,7 +438,7 @@ void __init smp_callin(void)
synchronize_tsc_ap();
}
-int cpucount = 0;
+int cpucount;
extern int cpu_idle(void);
@@ -497,7 +497,7 @@ static int __init fork_by_hand(void)
* don't care about the eip and regs settings since
* we'll never reschedule the forked task.
*/
- return do_fork(CLONE_VM|CLONE_PID, 0, &regs);
+ return do_fork(CLONE_VM|CLONE_PID, 0, &regs, 0);
}
#if APIC_DEBUG
@@ -774,7 +774,7 @@ static void __init do_boot_cpu (int apicid)
}
cycles_t cacheflush_time;
-extern unsigned long cpu_hz;
+extern unsigned long cpu_khz;
static void smp_tune_scheduling (void)
{
@@ -791,7 +791,7 @@ static void smp_tune_scheduling (void)
* the cache size)
*/
- if (!cpu_hz) {
+ if (!cpu_khz) {
/*
* this basically disables processor-affinity
* scheduling on SMP without a TSC.
@@ -805,12 +805,12 @@ static void smp_tune_scheduling (void)
bandwidth = 100;
}
- cacheflush_time = (cpu_hz>>20) * (cachesize<<10) / bandwidth;
+ cacheflush_time = (cpu_khz>>10) * (cachesize<<10) / bandwidth;
}
printk("per-CPU timeslice cutoff: %ld.%02ld usecs.\n",
- (long)cacheflush_time/(cpu_hz/1000000),
- ((long)cacheflush_time*100/(cpu_hz/1000000)) % 100);
+ (long)cacheflush_time/(cpu_khz/1000),
+ ((long)cacheflush_time*100/(cpu_khz/1000)) % 100);
}
/*
diff --git a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c
index 4bb184112..3a9df08e7 100644
--- a/arch/i386/kernel/time.c
+++ b/arch/i386/kernel/time.c
@@ -64,7 +64,7 @@
#include <linux/irq.h>
-unsigned long cpu_hz; /* Detected as we calibrate the TSC */
+unsigned long cpu_khz; /* Detected as we calibrate the TSC */
/* Number of usecs that the last interrupt was delayed */
static int delay_at_last_interrupt;
@@ -504,37 +504,6 @@ static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
}
-/* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
- * Assumes input in normal date format, i.e. 1980-12-31 23:59:59
- * => year=1980, mon=12, day=31, hour=23, min=59, sec=59.
- *
- * [For the Julian calendar (which was used in Russia before 1917,
- * Britain & colonies before 1752, anywhere else before 1582,
- * and is still in use by some communities) leave out the
- * -year/100+year/400 terms, and add 10.]
- *
- * This algorithm was first published by Gauss (I think).
- *
- * WARNING: this function will overflow on 2106-02-07 06:28:16 on
- * machines were long is 32-bit! (However, as time_t is signed, we
- * will already get problems at other places on 2038-01-19 03:14:08)
- */
-static inline unsigned long mktime(unsigned int year, unsigned int mon,
- unsigned int day, unsigned int hour,
- unsigned int min, unsigned int sec)
-{
- if (0 >= (int) (mon -= 2)) { /* 1..12 -> 11,12,1..10 */
- mon += 12; /* Puts Feb last since it has leap day */
- year -= 1;
- }
- return (((
- (unsigned long)(year/4 - year/100 + year/400 + 367*mon/12 + day) +
- year*365 - 719499
- )*24 + hour /* now have hours */
- )*60 + min /* now have minutes */
- )*60 + sec; /* finally seconds */
-}
-
/* not static: needed by APM */
unsigned long get_cmos_time(void)
{
@@ -707,12 +676,12 @@ void __init time_init(void)
* The formula is (10^6 * 2^32) / (2^32 * 1 / (clocks/us)) =
* clock/second. Our precision is about 100 ppm.
*/
- { unsigned long eax=0, edx=1000000;
+ { unsigned long eax=0, edx=1000;
__asm__("divl %2"
- :"=a" (cpu_hz), "=d" (edx)
+ :"=a" (cpu_khz), "=d" (edx)
:"r" (tsc_quotient),
"0" (eax), "1" (edx));
- printk("Detected %ld Hz processor.\n", cpu_hz);
+ printk("Detected %lu.%03lu MHz processor.\n", cpu_khz / 1000, cpu_khz % 1000);
}
}
}
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
index 7bd8a04d0..953c23d55 100644
--- a/arch/i386/kernel/traps.c
+++ b/arch/i386/kernel/traps.c
@@ -95,6 +95,7 @@ asmlinkage void simd_coprocessor_error(void);
asmlinkage void reserved(void);
asmlinkage void alignment_check(void);
asmlinkage void spurious_interrupt_bug(void);
+asmlinkage void machine_check(void);
int kstack_depth_to_print = 24;
@@ -415,8 +416,8 @@ inline void nmi_watchdog_tick(struct pt_regs * regs)
* here too!]
*/
- static unsigned int last_irq_sums [NR_CPUS] = { 0, },
- alert_counter [NR_CPUS] = { 0, };
+ static unsigned int last_irq_sums [NR_CPUS],
+ alert_counter [NR_CPUS];
/*
* Since current-> is always on the stack, and we always switch
@@ -491,17 +492,26 @@ asmlinkage void do_nmi(struct pt_regs * regs, long error_code)
}
/*
- * Careful - we must not do a lock-kernel until we have checked that the
- * debug fault happened in user mode. Getting debug exceptions while
- * in the kernel has to be handled without locking, to avoid deadlocks..
+ * Our handling of the processor debug registers is non-trivial.
+ * We do not clear them on entry and exit from the kernel. Therefore
+ * it is possible to get a watchpoint trap here from inside the kernel.
+ * However, the code in ./ptrace.c has ensured that the user can
+ * only set watchpoints on userspace addresses. Therefore the in-kernel
+ * watchpoint trap can only occur in code which is reading/writing
+ * from user space. Such code must not hold kernel locks (since it
+ * can equally take a page fault), therefore it is safe to call
+ * force_sig_info even though that claims and releases locks.
+ *
+ * Code in ./signal.c ensures that the debug control register
+ * is restored before we deliver any signal, and therefore that
+ * user code runs with the correct debug control register even though
+ * we clear it here.
*
* Being careful here means that we don't have to be as careful in a
* lot of more complicated places (task switching can be a bit lazy
* about restoring all the debug state, and ptrace doesn't have to
* find every occurrence of the TF bit that could be saved away even
- * by user code - and we don't have to be careful about what values
- * can be written to the debug registers because there are no really
- * bad cases).
+ * by user code)
*/
asmlinkage void do_debug(struct pt_regs * regs, long error_code)
{
@@ -520,6 +530,9 @@ asmlinkage void do_debug(struct pt_regs * regs, long error_code)
if (regs->eflags & VM_MASK)
goto debug_vm86;
+ /* Save debug status register where ptrace can see it */
+ tsk->thread.debugreg[6] = condition;
+
/* Mask out spurious TF errors due to lazy TF clearing */
if (condition & DR_STEP) {
/*
@@ -535,30 +548,33 @@ asmlinkage void do_debug(struct pt_regs * regs, long error_code)
goto clear_TF;
}
- /* If this is a kernel mode trap, we need to reset db7 to allow us to continue sanely */
- if ((regs->xcs & 3) == 0)
- goto clear_dr7;
-
/* Ok, finally something we can handle */
tsk->thread.trap_no = 1;
tsk->thread.error_code = error_code;
info.si_signo = SIGTRAP;
info.si_errno = 0;
info.si_code = TRAP_BRKPT;
- info.si_addr = (void *)regs->eip;
+
+ /* If this is a kernel mode trap, save the user PC on entry to
+ * the kernel, that's what the debugger can make sense of.
+ */
+ info.si_addr = ((regs->xcs & 3) == 0) ? (void *)tsk->thread.eip :
+ (void *)regs->eip;
force_sig_info(SIGTRAP, &info, tsk);
- return;
-
-debug_vm86:
- handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code, 1);
- return;
+ /* Disable additional traps. They'll be re-enabled when
+ * the signal is delivered.
+ */
clear_dr7:
__asm__("movl %0,%%db7"
: /* no output */
: "r" (0));
return;
+debug_vm86:
+ handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code, 1);
+ return;
+
clear_TF:
regs->eflags &= ~TF_MASK;
return;
@@ -641,7 +657,6 @@ void simd_math_error(void *eip)
*/
task = current;
save_init_fpu(task);
- load_mxcsr(0x1f80);
task->thread.trap_no = 19;
task->thread.error_code = 0;
info.si_signo = SIGFPE;
@@ -964,6 +979,7 @@ void __init trap_init(void)
set_trap_gate(15,&spurious_interrupt_bug);
set_trap_gate(16,&coprocessor_error);
set_trap_gate(17,&alignment_check);
+ set_trap_gate(18,&machine_check);
set_trap_gate(19,&simd_coprocessor_error);
set_system_gate(SYSCALL_VECTOR,&system_call);
diff --git a/arch/i386/kernel/vm86.c b/arch/i386/kernel/vm86.c
index 9875a3bdb..15b20d695 100644
--- a/arch/i386/kernel/vm86.c
+++ b/arch/i386/kernel/vm86.c
@@ -565,8 +565,8 @@ void handle_vm86_fault(struct kernel_vm86_regs * regs, long error_code)
static struct vm86_irqs {
struct task_struct *tsk;
int sig;
-} vm86_irqs[16] = {{0},};
-static int irqbits=0;
+} vm86_irqs[16];
+static int irqbits;
#define ALLOWED_SIGS ( 1 /* 0 = don't send a signal */ \
| (1 << SIGUSR1) | (1 << SIGUSR2) | (1 << SIGIO) | (1 << SIGURG) \
diff --git a/arch/i386/lib/checksum.S b/arch/i386/lib/checksum.S
index 0d66abee0..bfc638953 100644
--- a/arch/i386/lib/checksum.S
+++ b/arch/i386/lib/checksum.S
@@ -394,26 +394,32 @@ csum_partial_copy_generic:
movl ARGBASE+8(%esp),%edi #dst
movl ARGBASE+12(%esp),%ecx #len
movl ARGBASE+16(%esp),%eax #sum
- movl %ecx, %edx
+# movl %ecx, %edx
movl %ecx, %ebx
+ movl %esi, %edx
shrl $6, %ecx
andl $0x3c, %ebx
negl %ebx
subl %ebx, %esi
subl %ebx, %edi
+ lea -1(%esi),%edx
+ andl $-32,%edx
lea 3f(%ebx,%ebx), %ebx
testl %esi, %esi
- jmp *%ebx
+ jmp *%ebx
1: addl $64,%esi
addl $64,%edi
+ SRC(movb -32(%edx),%bl) ; SRC(movb (%edx),%bl)
ROUND1(-64) ROUND(-60) ROUND(-56) ROUND(-52)
ROUND (-48) ROUND(-44) ROUND(-40) ROUND(-36)
ROUND (-32) ROUND(-28) ROUND(-24) ROUND(-20)
ROUND (-16) ROUND(-12) ROUND(-8) ROUND(-4)
3: adcl $0,%eax
+ addl $64, %edx
dec %ecx
jge 1b
-4: andl $3, %edx
+4: movl ARGBASE+12(%esp),%edx #len
+ andl $3, %edx
jz 7f
cmpl $2, %edx
jb 5f
diff --git a/arch/i386/mm/ioremap.c b/arch/i386/mm/ioremap.c
index ba5c2e7ba..66f846925 100644
--- a/arch/i386/mm/ioremap.c
+++ b/arch/i386/mm/ioremap.c
@@ -126,7 +126,7 @@ void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flag
t_addr = __va(phys_addr);
t_end = t_addr + (size - 1);
- for(page = virt_to_page(t_addr); page < virt_to_page(t_end); page++)
+ for(page = virt_to_page(t_addr); page <= virt_to_page(t_end); page++)
if(!PageReserved(page))
return NULL;
}