diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-10-05 01:18:40 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-10-05 01:18:40 +0000 |
commit | 012bb3e61e5eced6c610f9e036372bf0c8def2d1 (patch) | |
tree | 87efc733f9b164e8c85c0336f92c8fb7eff6d183 /arch/i386 | |
parent | 625a1589d3d6464b5d90b8a0918789e3afffd220 (diff) |
Merge with Linux 2.4.0-test9. Please check DECstation, I had a number
of rejects to fixup while integrating Linus patches. I also found
that this kernel will only boot SMP on Origin; the UP kernel freeze
soon after bootup with SCSI timeout messages. I commit this anyway
since I found that the last CVS versions had the same problem.
Diffstat (limited to 'arch/i386')
-rw-r--r-- | arch/i386/config.in | 3 | ||||
-rw-r--r-- | arch/i386/defconfig | 93 | ||||
-rw-r--r-- | arch/i386/kernel/Makefile | 2 | ||||
-rw-r--r-- | arch/i386/kernel/acpi.c | 60 | ||||
-rw-r--r-- | arch/i386/kernel/apic.c | 2 | ||||
-rw-r--r-- | arch/i386/kernel/bluesmoke.c | 109 | ||||
-rw-r--r-- | arch/i386/kernel/entry.S | 6 | ||||
-rw-r--r-- | arch/i386/kernel/io_apic.c | 62 | ||||
-rw-r--r-- | arch/i386/kernel/microcode.c | 12 | ||||
-rw-r--r-- | arch/i386/kernel/mpparse.c | 23 | ||||
-rw-r--r-- | arch/i386/kernel/mtrr.c | 61 | ||||
-rw-r--r-- | arch/i386/kernel/process.c | 19 | ||||
-rw-r--r-- | arch/i386/kernel/ptrace.c | 1 | ||||
-rw-r--r-- | arch/i386/kernel/setup.c | 36 | ||||
-rw-r--r-- | arch/i386/kernel/signal.c | 9 | ||||
-rw-r--r-- | arch/i386/kernel/smp.c | 9 | ||||
-rw-r--r-- | arch/i386/kernel/smpboot.c | 26 | ||||
-rw-r--r-- | arch/i386/kernel/time.c | 39 | ||||
-rw-r--r-- | arch/i386/kernel/traps.c | 54 | ||||
-rw-r--r-- | arch/i386/kernel/vm86.c | 4 | ||||
-rw-r--r-- | arch/i386/lib/checksum.S | 12 | ||||
-rw-r--r-- | arch/i386/mm/ioremap.c | 2 |
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 *)®_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 *)®_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, ®s); + return do_fork(SIGCHLD, regs.esp, ®s, 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, ®s); + return do_fork(clone_flags, newsp, ®s, 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, ®s); + return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.esp, ®s, 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(¤t->signal, signr); + sigaddset(¤t->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, ®s); + return do_fork(CLONE_VM|CLONE_PID, 0, ®s, 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; } |