diff options
Diffstat (limited to 'arch/i386')
28 files changed, 229 insertions, 139 deletions
diff --git a/arch/i386/boot/boot.h b/arch/i386/boot/boot.h index dec70c9b605..20bab9431ac 100644 --- a/arch/i386/boot/boot.h +++ b/arch/i386/boot/boot.h @@ -87,7 +87,7 @@ static inline void set_fs(u16 seg) static inline u16 fs(void) { u16 seg; - asm("movw %%fs,%0" : "=rm" (seg)); + asm volatile("movw %%fs,%0" : "=rm" (seg)); return seg; } @@ -98,7 +98,7 @@ static inline void set_gs(u16 seg) static inline u16 gs(void) { u16 seg; - asm("movw %%gs,%0" : "=rm" (seg)); + asm volatile("movw %%gs,%0" : "=rm" (seg)); return seg; } @@ -107,19 +107,19 @@ typedef unsigned int addr_t; static inline u8 rdfs8(addr_t addr) { u8 v; - asm("movb %%fs:%1,%0" : "=r" (v) : "m" (*(u8 *)addr)); + asm volatile("movb %%fs:%1,%0" : "=r" (v) : "m" (*(u8 *)addr)); return v; } static inline u16 rdfs16(addr_t addr) { u16 v; - asm("movw %%fs:%1,%0" : "=r" (v) : "m" (*(u16 *)addr)); + asm volatile("movw %%fs:%1,%0" : "=r" (v) : "m" (*(u16 *)addr)); return v; } static inline u32 rdfs32(addr_t addr) { u32 v; - asm("movl %%fs:%1,%0" : "=r" (v) : "m" (*(u32 *)addr)); + asm volatile("movl %%fs:%1,%0" : "=r" (v) : "m" (*(u32 *)addr)); return v; } @@ -139,19 +139,19 @@ static inline void wrfs32(u32 v, addr_t addr) static inline u8 rdgs8(addr_t addr) { u8 v; - asm("movb %%gs:%1,%0" : "=r" (v) : "m" (*(u8 *)addr)); + asm volatile("movb %%gs:%1,%0" : "=r" (v) : "m" (*(u8 *)addr)); return v; } static inline u16 rdgs16(addr_t addr) { u16 v; - asm("movw %%gs:%1,%0" : "=r" (v) : "m" (*(u16 *)addr)); + asm volatile("movw %%gs:%1,%0" : "=r" (v) : "m" (*(u16 *)addr)); return v; } static inline u32 rdgs32(addr_t addr) { u32 v; - asm("movl %%gs:%1,%0" : "=r" (v) : "m" (*(u32 *)addr)); + asm volatile("movl %%gs:%1,%0" : "=r" (v) : "m" (*(u32 *)addr)); return v; } @@ -180,15 +180,15 @@ static inline int memcmp(const void *s1, const void *s2, size_t len) static inline int memcmp_fs(const void *s1, addr_t s2, size_t len) { u8 diff; - asm("fs; repe; cmpsb; setnz %0" - : "=qm" (diff), "+D" (s1), "+S" (s2), "+c" (len)); + asm volatile("fs; repe; cmpsb; setnz %0" + : "=qm" (diff), "+D" (s1), "+S" (s2), "+c" (len)); return diff; } static inline int memcmp_gs(const void *s1, addr_t s2, size_t len) { u8 diff; - asm("gs; repe; cmpsb; setnz %0" - : "=qm" (diff), "+D" (s1), "+S" (s2), "+c" (len)); + asm volatile("gs; repe; cmpsb; setnz %0" + : "=qm" (diff), "+D" (s1), "+S" (s2), "+c" (len)); return diff; } diff --git a/arch/i386/boot/cpucheck.c b/arch/i386/boot/cpucheck.c index 991e8ceae1d..e655a89c551 100644 --- a/arch/i386/boot/cpucheck.c +++ b/arch/i386/boot/cpucheck.c @@ -96,7 +96,8 @@ static int has_fpu(void) asm volatile("movl %0,%%cr0" : : "r" (cr0)); } - asm("fninit ; fnstsw %0 ; fnstcw %1" : "+m" (fsw), "+m" (fcw)); + asm volatile("fninit ; fnstsw %0 ; fnstcw %1" + : "+m" (fsw), "+m" (fcw)); return fsw == 0 && (fcw & 0x103f) == 0x003f; } diff --git a/arch/i386/boot/edd.c b/arch/i386/boot/edd.c index 82b5c846a19..bd138e442ec 100644 --- a/arch/i386/boot/edd.c +++ b/arch/i386/boot/edd.c @@ -30,9 +30,9 @@ static int read_mbr(u8 devno, void *buf) cx = 0x0001; /* Sector 0-0-1 */ dx = devno; bx = (size_t)buf; - asm("pushfl; stc; int $0x13; setc %%al; popfl" - : "+a" (ax), "+c" (cx), "+d" (dx), "+b" (bx) - : : "esi", "edi", "memory"); + asm volatile("pushfl; stc; int $0x13; setc %%al; popfl" + : "+a" (ax), "+c" (cx), "+d" (dx), "+b" (bx) + : : "esi", "edi", "memory"); return -(u8)ax; /* 0 or -1 */ } diff --git a/arch/i386/boot/header.S b/arch/i386/boot/header.S index 7f4a2c53bd7..f3140e596d4 100644 --- a/arch/i386/boot/header.S +++ b/arch/i386/boot/header.S @@ -275,7 +275,7 @@ die: hlt jmp die - .size die, .-due + .size die, .-die .section ".initdata", "a" setup_corrupt: diff --git a/arch/i386/boot/memory.c b/arch/i386/boot/memory.c index 1a2e62db8be..378353956b5 100644 --- a/arch/i386/boot/memory.c +++ b/arch/i386/boot/memory.c @@ -20,6 +20,7 @@ static int detect_memory_e820(void) { + int count = 0; u32 next = 0; u32 size, id; u8 err; @@ -27,20 +28,33 @@ static int detect_memory_e820(void) do { size = sizeof(struct e820entry); - id = SMAP; + + /* Important: %edx is clobbered by some BIOSes, + so it must be either used for the error output + or explicitly marked clobbered. */ asm("int $0x15; setc %0" - : "=am" (err), "+b" (next), "+d" (id), "+c" (size), + : "=d" (err), "+b" (next), "=a" (id), "+c" (size), "=m" (*desc) - : "D" (desc), "a" (0xe820)); + : "D" (desc), "d" (SMAP), "a" (0xe820)); + + /* Some BIOSes stop returning SMAP in the middle of + the search loop. We don't know exactly how the BIOS + screwed up the map at that point, we might have a + partial map, the full map, or complete garbage, so + just return failure. */ + if (id != SMAP) { + count = 0; + break; + } - if (err || id != SMAP) + if (err) break; - boot_params.e820_entries++; + count++; desc++; - } while (next && boot_params.e820_entries < E820MAX); + } while (next && count < E820MAX); - return boot_params.e820_entries; + return boot_params.e820_entries = count; } static int detect_memory_e801(void) @@ -89,11 +103,16 @@ static int detect_memory_88(void) int detect_memory(void) { + int err = -1; + if (detect_memory_e820() > 0) - return 0; + err = 0; if (!detect_memory_e801()) - return 0; + err = 0; + + if (!detect_memory_88()) + err = 0; - return detect_memory_88(); + return err; } diff --git a/arch/i386/boot/pm.c b/arch/i386/boot/pm.c index 6be9ca811d1..09fb342cc62 100644 --- a/arch/i386/boot/pm.c +++ b/arch/i386/boot/pm.c @@ -122,7 +122,11 @@ static void setup_gdt(void) /* DS: data, read/write, 4 GB, base 0 */ [GDT_ENTRY_BOOT_DS] = GDT_ENTRY(0xc093, 0, 0xfffff), }; - struct gdt_ptr gdt; + /* Xen HVM incorrectly stores a pointer to the gdt_ptr, instead + of the gdt_ptr contents. Thus, make it static so it will + stay in memory, at least long enough that we switch to the + proper kernel GDT. */ + static struct gdt_ptr gdt; gdt.len = sizeof(boot_gdt)-1; gdt.ptr = (u32)&boot_gdt + (ds() << 4); diff --git a/arch/i386/boot/tty.c b/arch/i386/boot/tty.c index 9c668aad351..f3f14bd2637 100644 --- a/arch/i386/boot/tty.c +++ b/arch/i386/boot/tty.c @@ -54,9 +54,9 @@ static u8 gettime(void) u16 ax = 0x0200; u16 cx, dx; - asm("int $0x1a" - : "+a" (ax), "=c" (cx), "=d" (dx) - : : "ebx", "esi", "edi"); + asm volatile("int $0x1a" + : "+a" (ax), "=c" (cx), "=d" (dx) + : : "ebx", "esi", "edi"); return dx >> 8; } @@ -67,7 +67,7 @@ static u8 gettime(void) int getchar(void) { u16 ax = 0; - asm("int $0x16" : "+a" (ax)); + asm volatile("int $0x16" : "+a" (ax)); return ax & 0xff; } @@ -75,9 +75,9 @@ int getchar(void) static int kbd_pending(void) { u8 pending; - asm("int $0x16; setnz %0" - : "=rm" (pending) - : "a" (0x0100)); + asm volatile("int $0x16; setnz %0" + : "=rm" (pending) + : "a" (0x0100)); return pending; } diff --git a/arch/i386/boot/video-vesa.c b/arch/i386/boot/video-vesa.c index f1bc71e948c..19219071071 100644 --- a/arch/i386/boot/video-vesa.c +++ b/arch/i386/boot/video-vesa.c @@ -29,7 +29,7 @@ static void vesa_store_mode_params_graphics(void); static int vesa_probe(void) { #if defined(CONFIG_VIDEO_VESA) || defined(CONFIG_FIRMWARE_EDID) - u16 ax; + u16 ax, cx, di; u16 mode; addr_t mode_ptr; struct mode_info *mi; @@ -39,9 +39,11 @@ static int vesa_probe(void) vginfo.signature = VBE2_MAGIC; - /* Optimistically assume a VESA BIOS is register-clean... */ ax = 0x4f00; - asm("int $0x10" : "+a" (ax), "=m" (vginfo) : "D" (&vginfo)); + di = (size_t)&vginfo; + asm(INT10 + : "+a" (ax), "+D" (di), "=m" (vginfo) + : : "ebx", "ecx", "edx", "esi"); if (ax != 0x004f || vginfo.signature != VESA_MAGIC || @@ -64,9 +66,11 @@ static int vesa_probe(void) memset(&vminfo, 0, sizeof vminfo); /* Just in case... */ ax = 0x4f01; - asm("int $0x10" - : "+a" (ax), "=m" (vminfo) - : "c" (mode), "D" (&vminfo)); + cx = mode; + di = (size_t)&vminfo; + asm(INT10 + : "+a" (ax), "+c" (cx), "+D" (di), "=m" (vminfo) + : : "ebx", "edx", "esi"); if (ax != 0x004f) continue; @@ -102,16 +106,18 @@ static int vesa_probe(void) static int vesa_set_mode(struct mode_info *mode) { - u16 ax; + u16 ax, bx, cx, di; int is_graphic; u16 vesa_mode = mode->mode - VIDEO_FIRST_VESA; memset(&vminfo, 0, sizeof vminfo); /* Just in case... */ ax = 0x4f01; - asm("int $0x10" - : "+a" (ax), "=m" (vminfo) - : "c" (vesa_mode), "D" (&vminfo)); + cx = vesa_mode; + di = (size_t)&vminfo; + asm(INT10 + : "+a" (ax), "+c" (cx), "+D" (di), "=m" (vminfo) + : : "ebx", "edx", "esi"); if (ax != 0x004f) return -1; @@ -129,9 +135,11 @@ static int vesa_set_mode(struct mode_info *mode) ax = 0x4f02; - asm volatile("int $0x10" - : "+a" (ax) - : "b" (vesa_mode), "D" (0)); + bx = vesa_mode; + di = 0; + asm volatile(INT10 + : "+a" (ax), "+b" (bx), "+D" (di) + : : "ecx", "edx", "esi"); if (ax != 0x004f) return -1; diff --git a/arch/i386/boot/video-vga.c b/arch/i386/boot/video-vga.c index 700d09a9c9b..aef02f9ec0c 100644 --- a/arch/i386/boot/video-vga.c +++ b/arch/i386/boot/video-vga.c @@ -47,16 +47,16 @@ static u8 vga_set_basic_mode(void) #ifdef CONFIG_VIDEO_400_HACK if (adapter >= ADAPTER_VGA) { - asm(INT10 - : : "a" (0x1202), "b" (0x0030) - : "ecx", "edx", "esi", "edi"); + asm volatile(INT10 + : : "a" (0x1202), "b" (0x0030) + : "ecx", "edx", "esi", "edi"); } #endif ax = 0x0f00; - asm(INT10 - : "+a" (ax) - : : "ebx", "ecx", "edx", "esi", "edi"); + asm volatile(INT10 + : "+a" (ax) + : : "ebx", "ecx", "edx", "esi", "edi"); mode = (u8)ax; @@ -73,9 +73,10 @@ static u8 vga_set_basic_mode(void) mode = 3; /* Set the mode */ + ax = mode; asm volatile(INT10 - : : "a" (mode) - : "ebx", "ecx", "edx", "esi", "edi"); + : "+a" (ax) + : : "ebx", "ecx", "edx", "esi", "edi"); do_restore = 1; return mode; } diff --git a/arch/i386/boot/video.c b/arch/i386/boot/video.c index 693f20d3102..e4ba897bf9a 100644 --- a/arch/i386/boot/video.c +++ b/arch/i386/boot/video.c @@ -147,7 +147,7 @@ int mode_defined(u16 mode) } /* Set mode (without recalc) */ -static int raw_set_mode(u16 mode) +static int raw_set_mode(u16 mode, u16 *real_mode) { int nmode, i; struct card_info *card; @@ -165,8 +165,10 @@ static int raw_set_mode(u16 mode) if ((mode == nmode && visible) || mode == mi->mode || - mode == (mi->y << 8)+mi->x) + mode == (mi->y << 8)+mi->x) { + *real_mode = mi->mode; return card->set_mode(mi); + } if (visible) nmode++; @@ -178,7 +180,7 @@ static int raw_set_mode(u16 mode) if (mode >= card->xmode_first && mode < card->xmode_first+card->xmode_n) { struct mode_info mix; - mix.mode = mode; + *real_mode = mix.mode = mode; mix.x = mix.y = 0; return card->set_mode(&mix); } @@ -223,6 +225,7 @@ static void vga_recalc_vertical(void) static int set_mode(u16 mode) { int rv; + u16 real_mode; /* Very special mode numbers... */ if (mode == VIDEO_CURRENT_MODE) @@ -232,13 +235,16 @@ static int set_mode(u16 mode) else if (mode == EXTENDED_VGA) mode = VIDEO_8POINT; - rv = raw_set_mode(mode); + rv = raw_set_mode(mode, &real_mode); if (rv) return rv; if (mode & VIDEO_RECALC) vga_recalc_vertical(); + /* Save the canonical mode number for the kernel, not + an alias, size specification or menu position */ + boot_params.hdr.vid_mode = real_mode; return 0; } diff --git a/arch/i386/kernel/acpi/wakeup.S b/arch/i386/kernel/acpi/wakeup.S index ed0a0f2c159..f22ba8534d2 100644 --- a/arch/i386/kernel/acpi/wakeup.S +++ b/arch/i386/kernel/acpi/wakeup.S @@ -151,51 +151,30 @@ bogus_real_magic: #define VIDEO_FIRST_V7 0x0900 # Setting of user mode (AX=mode ID) => CF=success + +# For now, we only handle VESA modes (0x0200..0x03ff). To handle other +# modes, we should probably compile in the video code from the boot +# directory. mode_set: movw %ax, %bx -#if 0 - cmpb $0xff, %ah - jz setalias - - testb $VIDEO_RECALC>>8, %ah - jnz _setrec - - cmpb $VIDEO_FIRST_RESOLUTION>>8, %ah - jnc setres - - cmpb $VIDEO_FIRST_SPECIAL>>8, %ah - jz setspc - - cmpb $VIDEO_FIRST_V7>>8, %ah - jz setv7 -#endif - - cmpb $VIDEO_FIRST_VESA>>8, %ah - jnc check_vesa -#if 0 - orb %ah, %ah - jz setmenu -#endif - - decb %ah -# jz setbios Add bios modes later + subb $VIDEO_FIRST_VESA>>8, %bh + cmpb $2, %bh + jb check_vesa -setbad: clc +setbad: + clc ret check_vesa: - subb $VIDEO_FIRST_VESA>>8, %bh orw $0x4000, %bx # Use linear frame buffer movw $0x4f02, %ax # VESA BIOS mode set call int $0x10 cmpw $0x004f, %ax # AL=4f if implemented - jnz _setbad # AH=0 if OK + jnz setbad # AH=0 if OK stc ret -_setbad: jmp setbad - .code32 ALIGN diff --git a/arch/i386/kernel/alternative.c b/arch/i386/kernel/alternative.c index 9f4ac8b02de..bd72d94e713 100644 --- a/arch/i386/kernel/alternative.c +++ b/arch/i386/kernel/alternative.c @@ -445,8 +445,6 @@ void __kprobes text_poke(void *addr, unsigned char *opcode, int len) { memcpy(addr, opcode, len); sync_core(); - /* Not strictly needed, but can speed CPU recovery up. Ignore cross cacheline - case. */ - if (cpu_has_clflush) - asm("clflush (%0) " :: "r" (addr) : "memory"); + /* Could also do a CLFLUSH here to speed up CPU recovery; but + that causes hangs on some VIA CPUs. */ } diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c index ef8f0bc3fc7..f0cce3c2dc3 100644 --- a/arch/i386/kernel/cpu/cpufreq/longhaul.c +++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c @@ -76,6 +76,7 @@ static unsigned int longhaul_index; /* Module parameters */ static int scale_voltage; static int disable_acpi_c3; +static int revid_errata; #define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "longhaul", msg) @@ -168,7 +169,10 @@ static void do_powersaver(int cx_address, unsigned int clock_ratio_index, rdmsrl(MSR_VIA_LONGHAUL, longhaul.val); /* Setup new frequency */ - longhaul.bits.RevisionKey = longhaul.bits.RevisionID; + if (!revid_errata) + longhaul.bits.RevisionKey = longhaul.bits.RevisionID; + else + longhaul.bits.RevisionKey = 0; longhaul.bits.SoftBusRatio = clock_ratio_index & 0xf; longhaul.bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4; /* Setup new voltage */ @@ -272,7 +276,7 @@ static void longhaul_setstate(unsigned int table_index) dprintk ("Setting to FSB:%dMHz Mult:%d.%dx (%s)\n", fsb, mult/10, mult%10, print_speed(speed/1000)); - +retry_loop: preempt_disable(); local_irq_save(flags); @@ -344,6 +348,47 @@ static void longhaul_setstate(unsigned int table_index) preempt_enable(); freqs.new = calc_speed(longhaul_get_cpu_mult()); + /* Check if requested frequency is set. */ + if (unlikely(freqs.new != speed)) { + printk(KERN_INFO PFX "Failed to set requested frequency!\n"); + /* Revision ID = 1 but processor is expecting revision key + * equal to 0. Jumpers at the bottom of processor will change + * multiplier and FSB, but will not change bits in Longhaul + * MSR nor enable voltage scaling. */ + if (!revid_errata) { + printk(KERN_INFO PFX "Enabling \"Ignore Revision ID\" " + "option.\n"); + revid_errata = 1; + msleep(200); + goto retry_loop; + } + /* Why ACPI C3 sometimes doesn't work is a mystery for me. + * But it does happen. Processor is entering ACPI C3 state, + * but it doesn't change frequency. I tried poking various + * bits in northbridge registers, but without success. */ + if (longhaul_flags & USE_ACPI_C3) { + printk(KERN_INFO PFX "Disabling ACPI C3 support.\n"); + longhaul_flags &= ~USE_ACPI_C3; + if (revid_errata) { + printk(KERN_INFO PFX "Disabling \"Ignore " + "Revision ID\" option.\n"); + revid_errata = 0; + } + msleep(200); + goto retry_loop; + } + /* This shouldn't happen. Longhaul ver. 2 was reported not + * working on processors without voltage scaling, but with + * RevID = 1. RevID errata will make things right. Just + * to be 100% sure. */ + if (longhaul_version == TYPE_LONGHAUL_V2) { + printk(KERN_INFO PFX "Switching to Longhaul ver. 1\n"); + longhaul_version = TYPE_LONGHAUL_V1; + msleep(200); + goto retry_loop; + } + } + /* Report true CPU frequency */ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); if (!bm_timeout) @@ -956,11 +1001,20 @@ static void __exit longhaul_exit(void) kfree(longhaul_table); } +/* Even if BIOS is exporting ACPI C3 state, and it is used + * with success when CPU is idle, this state doesn't + * trigger frequency transition in some cases. */ module_param (disable_acpi_c3, int, 0644); MODULE_PARM_DESC(disable_acpi_c3, "Don't use ACPI C3 support"); - +/* Change CPU voltage with frequency. Very usefull to save + * power, but most VIA C3 processors aren't supporting it. */ module_param (scale_voltage, int, 0644); MODULE_PARM_DESC(scale_voltage, "Scale voltage of processor"); +/* Force revision key to 0 for processors which doesn't + * support voltage scaling, but are introducing itself as + * such. */ +module_param(revid_errata, int, 0644); +MODULE_PARM_DESC(revid_errata, "Ignore CPU Revision ID"); MODULE_AUTHOR ("Dave Jones <davej@codemonkey.org.uk>"); MODULE_DESCRIPTION ("Longhaul driver for VIA Cyrix processors."); diff --git a/arch/i386/kernel/cpu/intel_cacheinfo.c b/arch/i386/kernel/cpu/intel_cacheinfo.c index d5a456d27d8..db6c25aa577 100644 --- a/arch/i386/kernel/cpu/intel_cacheinfo.c +++ b/arch/i386/kernel/cpu/intel_cacheinfo.c @@ -515,7 +515,7 @@ static int __cpuinit detect_cache_attributes(unsigned int cpu) cpuid4_info[cpu] = kzalloc( sizeof(struct _cpuid4_info) * num_cache_leaves, GFP_KERNEL); - if (unlikely(cpuid4_info[cpu] == NULL)) + if (cpuid4_info[cpu] == NULL) return -ENOMEM; oldmask = current->cpus_allowed; @@ -748,6 +748,8 @@ static void __cpuinit cache_remove_dev(struct sys_device * sys_dev) unsigned int cpu = sys_dev->id; unsigned long i; + if (cpuid4_info[cpu] == NULL) + return; for (i = 0; i < num_cache_leaves; i++) { cache_remove_shared_cpu_map(cpu, i); kobject_unregister(&(INDEX_KOBJECT_PTR(cpu,i)->kobj)); diff --git a/arch/i386/kernel/cpu/perfctr-watchdog.c b/arch/i386/kernel/cpu/perfctr-watchdog.c index 4be488e73be..93fecd4b03d 100644 --- a/arch/i386/kernel/cpu/perfctr-watchdog.c +++ b/arch/i386/kernel/cpu/perfctr-watchdog.c @@ -263,8 +263,8 @@ static int setup_k7_watchdog(unsigned nmi_hz) unsigned int evntsel; struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk); - perfctr_msr = MSR_K7_PERFCTR0; - evntsel_msr = MSR_K7_EVNTSEL0; + perfctr_msr = wd_ops->perfctr; + evntsel_msr = wd_ops->evntsel; wrmsrl(perfctr_msr, 0UL); @@ -343,8 +343,8 @@ static int setup_p6_watchdog(unsigned nmi_hz) unsigned int evntsel; struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk); - perfctr_msr = MSR_P6_PERFCTR0; - evntsel_msr = MSR_P6_EVNTSEL0; + perfctr_msr = wd_ops->perfctr; + evntsel_msr = wd_ops->evntsel; /* KVM doesn't implement this MSR */ if (wrmsr_safe(perfctr_msr, 0, 0) < 0) @@ -569,8 +569,8 @@ static int setup_intel_arch_watchdog(unsigned nmi_hz) (ebx & ARCH_PERFMON_UNHALTED_CORE_CYCLES_PRESENT)) return 0; - perfctr_msr = MSR_ARCH_PERFMON_PERFCTR1; - evntsel_msr = MSR_ARCH_PERFMON_EVENTSEL1; + perfctr_msr = wd_ops->perfctr; + evntsel_msr = wd_ops->evntsel; wrmsrl(perfctr_msr, 0UL); @@ -605,6 +605,16 @@ static struct wd_ops intel_arch_wd_ops = { .evntsel = MSR_ARCH_PERFMON_EVENTSEL1, }; +static struct wd_ops coreduo_wd_ops = { + .reserve = single_msr_reserve, + .unreserve = single_msr_unreserve, + .setup = setup_intel_arch_watchdog, + .rearm = p6_rearm, + .stop = single_msr_stop_watchdog, + .perfctr = MSR_ARCH_PERFMON_PERFCTR0, + .evntsel = MSR_ARCH_PERFMON_EVENTSEL0, +}; + static void probe_nmi_watchdog(void) { switch (boot_cpu_data.x86_vendor) { @@ -615,6 +625,12 @@ static void probe_nmi_watchdog(void) wd_ops = &k7_wd_ops; break; case X86_VENDOR_INTEL: + /* Work around Core Duo (Yonah) errata AE49 where perfctr1 + doesn't have a working enable bit. */ + if (boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model == 14) { + wd_ops = &coreduo_wd_ops; + break; + } if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) { wd_ops = &intel_arch_wd_ops; break; diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c index 4b8a8da4b2e..e2f4a1c6854 100644 --- a/arch/i386/kernel/io_apic.c +++ b/arch/i386/kernel/io_apic.c @@ -754,14 +754,6 @@ static int pirq_entries [MAX_PIRQS]; static int pirqs_enabled; int skip_ioapic_setup; -static int __init ioapic_setup(char *str) -{ - skip_ioapic_setup = 1; - return 1; -} - -__setup("noapic", ioapic_setup); - static int __init ioapic_pirq_setup(char *str) { int i, max; diff --git a/arch/i386/kernel/nmi.c b/arch/i386/kernel/nmi.c index 8c1c965eb2a..c7227e2180f 100644 --- a/arch/i386/kernel/nmi.c +++ b/arch/i386/kernel/nmi.c @@ -115,12 +115,12 @@ static int __init check_nmi_watchdog(void) atomic_dec(&nmi_active); } } + endflag = 1; if (!atomic_read(&nmi_active)) { kfree(prev_nmi_count); atomic_set(&nmi_active, -1); return -1; } - endflag = 1; printk("OK.\n"); /* now that we know it works we can reduce NMI frequency to diff --git a/arch/i386/kernel/ptrace.c b/arch/i386/kernel/ptrace.c index 0c8f00e69c4..7c1b92522e9 100644 --- a/arch/i386/kernel/ptrace.c +++ b/arch/i386/kernel/ptrace.c @@ -274,7 +274,6 @@ static void clear_singlestep(struct task_struct *child) void ptrace_disable(struct task_struct *child) { clear_singlestep(child); - clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); clear_tsk_thread_flag(child, TIF_SYSCALL_EMU); } diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index cfffe3dd9e8..47b0bef335b 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c @@ -100,36 +100,45 @@ asmlinkage void machine_check(void); int kstack_depth_to_print = 24; static unsigned int code_bytes = 64; -static inline int valid_stack_ptr(struct thread_info *tinfo, void *p) +static inline int valid_stack_ptr(struct thread_info *tinfo, void *p, unsigned size) { return p > (void *)tinfo && - p < (void *)tinfo + THREAD_SIZE - 3; + p <= (void *)tinfo + THREAD_SIZE - size; } +/* The form of the top of the frame on the stack */ +struct stack_frame { + struct stack_frame *next_frame; + unsigned long return_address; +}; + static inline unsigned long print_context_stack(struct thread_info *tinfo, unsigned long *stack, unsigned long ebp, struct stacktrace_ops *ops, void *data) { - unsigned long addr; - #ifdef CONFIG_FRAME_POINTER - while (valid_stack_ptr(tinfo, (void *)ebp)) { - unsigned long new_ebp; - addr = *(unsigned long *)(ebp + 4); + struct stack_frame *frame = (struct stack_frame *)ebp; + while (valid_stack_ptr(tinfo, frame, sizeof(*frame))) { + struct stack_frame *next; + unsigned long addr; + + addr = frame->return_address; ops->address(data, addr); /* * break out of recursive entries (such as * end_of_stack_stop_unwind_function). Also, * we can never allow a frame pointer to * move downwards! - */ - new_ebp = *(unsigned long *)ebp; - if (new_ebp <= ebp) + */ + next = frame->next_frame; + if (next <= frame) break; - ebp = new_ebp; + frame = next; } #else - while (valid_stack_ptr(tinfo, stack)) { + while (valid_stack_ptr(tinfo, stack, sizeof(*stack))) { + unsigned long addr; + addr = *stack++; if (__kernel_text_address(addr)) ops->address(data, addr); diff --git a/arch/i386/kernel/tsc.c b/arch/i386/kernel/tsc.c index debd7dbb415..a39280b4dd3 100644 --- a/arch/i386/kernel/tsc.c +++ b/arch/i386/kernel/tsc.c @@ -292,7 +292,6 @@ static struct clocksource clocksource_tsc = { void mark_tsc_unstable(char *reason) { - sched_clock_unstable_event(); if (!tsc_unstable) { tsc_unstable = 1; tsc_enabled = 0; diff --git a/arch/i386/mach-generic/Makefile b/arch/i386/mach-generic/Makefile index 77fbc9f64fb..6914485c0d8 100644 --- a/arch/i386/mach-generic/Makefile +++ b/arch/i386/mach-generic/Makefile @@ -2,6 +2,6 @@ # Makefile for the generic architecture # -EXTRA_CFLAGS += -I../kernel +EXTRA_CFLAGS := -Iarch/i386/kernel obj-y := probe.o summit.o bigsmp.o es7000.o default.o ../mach-es7000/ diff --git a/arch/i386/mach-voyager/Makefile b/arch/i386/mach-voyager/Makefile index f24d2965131..33b74cf0dd2 100644 --- a/arch/i386/mach-voyager/Makefile +++ b/arch/i386/mach-voyager/Makefile @@ -2,7 +2,7 @@ # Makefile for the linux kernel. # -EXTRA_CFLAGS += -I../kernel +EXTRA_CFLAGS := -Iarch/i386/kernel obj-y := setup.o voyager_basic.o voyager_thread.o obj-$(CONFIG_SMP) += voyager_smp.o voyager_cat.o diff --git a/arch/i386/mm/highmem.c b/arch/i386/mm/highmem.c index ad8d86cc683..1c3bf95f735 100644 --- a/arch/i386/mm/highmem.c +++ b/arch/i386/mm/highmem.c @@ -34,17 +34,16 @@ void *kmap_atomic_prot(struct page *page, enum km_type type, pgprot_t prot) /* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */ pagefault_disable(); - idx = type + KM_TYPE_NR*smp_processor_id(); - BUG_ON(!pte_none(*(kmap_pte-idx))); - if (!PageHighMem(page)) return page_address(page); + idx = type + KM_TYPE_NR*smp_processor_id(); vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); + BUG_ON(!pte_none(*(kmap_pte-idx))); set_pte(kmap_pte-idx, mk_pte(page, prot)); arch_flush_lazy_mmu_mode(); - return (void*) vaddr; + return (void *)vaddr; } void *kmap_atomic(struct page *page, enum km_type type) diff --git a/arch/i386/mm/hugetlbpage.c b/arch/i386/mm/hugetlbpage.c index efdf95ac803..6c06d9c0488 100644 --- a/arch/i386/mm/hugetlbpage.c +++ b/arch/i386/mm/hugetlbpage.c @@ -367,7 +367,7 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr, return -ENOMEM; if (flags & MAP_FIXED) { - if (prepare_hugepage_range(addr, len, pgoff)) + if (prepare_hugepage_range(addr, len)) return -EINVAL; return addr; } diff --git a/arch/i386/pci/irq.c b/arch/i386/pci/irq.c index 665db063a40..8434f2323b8 100644 --- a/arch/i386/pci/irq.c +++ b/arch/i386/pci/irq.c @@ -550,6 +550,7 @@ static __init int intel_router_probe(struct irq_router *r, struct pci_dev *route case PCI_DEVICE_ID_INTEL_ICH9_3: case PCI_DEVICE_ID_INTEL_ICH9_4: case PCI_DEVICE_ID_INTEL_ICH9_5: + case PCI_DEVICE_ID_INTEL_TOLAPAI_0: r->name = "PIIX/ICH"; r->get = pirq_piix_get; r->set = pirq_piix_set; diff --git a/arch/i386/pci/pcbios.c b/arch/i386/pci/pcbios.c index 5f5193401be..10ac8c316c4 100644 --- a/arch/i386/pci/pcbios.c +++ b/arch/i386/pci/pcbios.c @@ -412,7 +412,7 @@ struct irq_routing_options { u16 segment; } __attribute__((packed)); -struct irq_routing_table * __devinit pcibios_get_irq_routing_table(void) +struct irq_routing_table * pcibios_get_irq_routing_table(void) { struct irq_routing_options opt; struct irq_routing_table *rt = NULL; diff --git a/arch/i386/xen/enlighten.c b/arch/i386/xen/enlighten.c index f0c37511d8d..f01bfcd4bde 100644 --- a/arch/i386/xen/enlighten.c +++ b/arch/i386/xen/enlighten.c @@ -623,8 +623,8 @@ static unsigned long xen_read_cr2_direct(void) static void xen_write_cr4(unsigned long cr4) { - /* never allow TSC to be disabled */ - native_write_cr4(cr4 & ~X86_CR4_TSD); + /* Just ignore cr4 changes; Xen doesn't allow us to do + anything anyway. */ } static unsigned long xen_read_cr3(void) diff --git a/arch/i386/xen/mmu.c b/arch/i386/xen/mmu.c index 4ae038aa6c2..874db0cd1d2 100644 --- a/arch/i386/xen/mmu.c +++ b/arch/i386/xen/mmu.c @@ -559,6 +559,9 @@ void xen_exit_mmap(struct mm_struct *mm) put_cpu(); spin_lock(&mm->page_table_lock); - xen_pgd_unpin(mm->pgd); + + /* pgd may not be pinned in the error exit path of execve */ + if (PagePinned(virt_to_page(mm->pgd))) + xen_pgd_unpin(mm->pgd); spin_unlock(&mm->page_table_lock); } |