diff options
author | Kumar Gala <galak@kernel.crashing.org> | 2006-02-28 11:25:22 -0600 |
---|---|---|
committer | Kumar Gala <galak@kernel.crashing.org> | 2006-02-28 11:25:22 -0600 |
commit | 9585da3729e7e27bf22818625c10ac6c64ebb609 (patch) | |
tree | 8c8d46f7f2cc933fdf75a6a75cf593a63f7b8717 /arch/i386 | |
parent | 8080d5497146d5d27d9e8e78229d1adc7fe280cf (diff) | |
parent | 6749c5507388f3fc3719f57a54b540ee83f6661a (diff) | |
download | op-kernel-dev-9585da3729e7e27bf22818625c10ac6c64ebb609.zip op-kernel-dev-9585da3729e7e27bf22818625c10ac6c64ebb609.tar.gz |
Merge branch 'master' of git+ssh://galak@master.kernel.org/pub/scm/linux/kernel/git/galak/powerpc
Diffstat (limited to 'arch/i386')
-rw-r--r-- | arch/i386/Kconfig | 3 | ||||
-rw-r--r-- | arch/i386/boot/.gitignore | 3 | ||||
-rw-r--r-- | arch/i386/boot/tools/.gitignore | 1 | ||||
-rw-r--r-- | arch/i386/kernel/.gitignore | 1 | ||||
-rw-r--r-- | arch/i386/kernel/Makefile | 2 | ||||
-rw-r--r-- | arch/i386/kernel/cpu/common.c | 32 | ||||
-rw-r--r-- | arch/i386/kernel/cpu/transmeta.c | 1 | ||||
-rw-r--r-- | arch/i386/kernel/efi.c | 12 | ||||
-rw-r--r-- | arch/i386/kernel/head.S | 6 | ||||
-rw-r--r-- | arch/i386/kernel/i386_ksyms.c | 2 | ||||
-rw-r--r-- | arch/i386/kernel/io_apic.c | 6 | ||||
-rw-r--r-- | arch/i386/kernel/kprobes.c | 16 | ||||
-rw-r--r-- | arch/i386/kernel/mpparse.c | 12 | ||||
-rw-r--r-- | arch/i386/kernel/smpboot.c | 10 | ||||
-rw-r--r-- | arch/i386/kernel/syscall_table.S | 2 | ||||
-rw-r--r-- | arch/i386/kernel/timers/timer_tsc.c | 5 | ||||
-rw-r--r-- | arch/i386/kernel/topology.c (renamed from arch/i386/mach-default/topology.c) | 6 | ||||
-rw-r--r-- | arch/i386/kernel/vsyscall-sysenter.S | 15 | ||||
-rw-r--r-- | arch/i386/mach-default/Makefile | 2 | ||||
-rw-r--r-- | arch/i386/mach-voyager/voyager_basic.c | 3 | ||||
-rw-r--r-- | arch/i386/mach-voyager/voyager_smp.c | 3 | ||||
-rw-r--r-- | arch/i386/oprofile/backtrace.c | 19 |
22 files changed, 120 insertions, 42 deletions
diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig index 0afec85..5b1a7d4 100644 --- a/arch/i386/Kconfig +++ b/arch/i386/Kconfig @@ -733,7 +733,7 @@ config PHYSICAL_START config HOTPLUG_CPU bool "Support for hot-pluggable CPUs (EXPERIMENTAL)" - depends on SMP && HOTPLUG && EXPERIMENTAL + depends on SMP && HOTPLUG && EXPERIMENTAL && !X86_VOYAGER ---help--- Say Y here to experiment with turning CPUs off and on. CPUs can be controlled through /sys/devices/system/cpu. @@ -1060,6 +1060,7 @@ source "arch/i386/oprofile/Kconfig" config KPROBES bool "Kprobes (EXPERIMENTAL)" + depends on EXPERIMENTAL && MODULES help Kprobes allows you to trap at almost any kernel address and execute a callback function. register_kprobe() establishes diff --git a/arch/i386/boot/.gitignore b/arch/i386/boot/.gitignore new file mode 100644 index 0000000..495f20c --- /dev/null +++ b/arch/i386/boot/.gitignore @@ -0,0 +1,3 @@ +bootsect +bzImage +setup diff --git a/arch/i386/boot/tools/.gitignore b/arch/i386/boot/tools/.gitignore new file mode 100644 index 0000000..378eac2 --- /dev/null +++ b/arch/i386/boot/tools/.gitignore @@ -0,0 +1 @@ +build diff --git a/arch/i386/kernel/.gitignore b/arch/i386/kernel/.gitignore new file mode 100644 index 0000000..40836ad --- /dev/null +++ b/arch/i386/kernel/.gitignore @@ -0,0 +1 @@ +vsyscall.lds diff --git a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile index 60c3f76..53bb9a7 100644 --- a/arch/i386/kernel/Makefile +++ b/arch/i386/kernel/Makefile @@ -7,7 +7,7 @@ extra-y := head.o init_task.o vmlinux.lds obj-y := process.o semaphore.o signal.o entry.o traps.o irq.o \ ptrace.o time.o ioport.o ldt.o setup.o i8259.o sys_i386.o \ pci-dma.o i386_ksyms.o i387.o dmi_scan.o bootflag.o \ - quirks.o i8237.o + quirks.o i8237.o topology.o obj-y += cpu/ obj-y += timers/ diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c index 7eb9213..4ecd4b3 100644 --- a/arch/i386/kernel/cpu/common.c +++ b/arch/i386/kernel/cpu/common.c @@ -4,6 +4,7 @@ #include <linux/smp.h> #include <linux/module.h> #include <linux/percpu.h> +#include <linux/bootmem.h> #include <asm/semaphore.h> #include <asm/processor.h> #include <asm/i387.h> @@ -18,6 +19,9 @@ #include "cpu.h" +DEFINE_PER_CPU(struct Xgt_desc_struct, cpu_gdt_descr); +EXPORT_PER_CPU_SYMBOL(cpu_gdt_descr); + DEFINE_PER_CPU(unsigned char, cpu_16bit_stack[CPU_16BIT_STACK_SIZE]); EXPORT_PER_CPU_SYMBOL(cpu_16bit_stack); @@ -571,8 +575,9 @@ void __devinit cpu_init(void) int cpu = smp_processor_id(); struct tss_struct * t = &per_cpu(init_tss, cpu); struct thread_struct *thread = ¤t->thread; - struct desc_struct *gdt = get_cpu_gdt_table(cpu); + struct desc_struct *gdt; __u32 stk16_off = (__u32)&per_cpu(cpu_16bit_stack, cpu); + struct Xgt_desc_struct *cpu_gdt_descr = &per_cpu(cpu_gdt_descr, cpu); if (cpu_test_and_set(cpu, cpu_initialized)) { printk(KERN_WARNING "CPU#%d already initialized!\n", cpu); @@ -590,6 +595,25 @@ void __devinit cpu_init(void) } /* + * This is a horrible hack to allocate the GDT. The problem + * is that cpu_init() is called really early for the boot CPU + * (and hence needs bootmem) but much later for the secondary + * CPUs, when bootmem will have gone away + */ + if (NODE_DATA(0)->bdata->node_bootmem_map) { + gdt = (struct desc_struct *)alloc_bootmem_pages(PAGE_SIZE); + /* alloc_bootmem_pages panics on failure, so no check */ + memset(gdt, 0, PAGE_SIZE); + } else { + gdt = (struct desc_struct *)get_zeroed_page(GFP_KERNEL); + if (unlikely(!gdt)) { + printk(KERN_CRIT "CPU%d failed to allocate GDT\n", cpu); + for (;;) + local_irq_enable(); + } + } + + /* * Initialize the per-CPU GDT with the boot GDT, * and set up the GDT descriptor: */ @@ -601,10 +625,10 @@ void __devinit cpu_init(void) ((((__u64)stk16_off) << 32) & 0xff00000000000000ULL) | (CPU_16BIT_STACK_SIZE - 1); - cpu_gdt_descr[cpu].size = GDT_SIZE - 1; - cpu_gdt_descr[cpu].address = (unsigned long)gdt; + cpu_gdt_descr->size = GDT_SIZE - 1; + cpu_gdt_descr->address = (unsigned long)gdt; - load_gdt(&cpu_gdt_descr[cpu]); + load_gdt(cpu_gdt_descr); load_idt(&idt_descr); /* diff --git a/arch/i386/kernel/cpu/transmeta.c b/arch/i386/kernel/cpu/transmeta.c index bdbeb77..7214c9b 100644 --- a/arch/i386/kernel/cpu/transmeta.c +++ b/arch/i386/kernel/cpu/transmeta.c @@ -1,4 +1,5 @@ #include <linux/kernel.h> +#include <linux/mm.h> #include <linux/init.h> #include <asm/processor.h> #include <asm/msr.h> diff --git a/arch/i386/kernel/efi.c b/arch/i386/kernel/efi.c index ecad519..e3e42fd 100644 --- a/arch/i386/kernel/efi.c +++ b/arch/i386/kernel/efi.c @@ -103,17 +103,19 @@ static void efi_call_phys_prelog(void) */ local_flush_tlb(); - cpu_gdt_descr[0].address = __pa(cpu_gdt_descr[0].address); - load_gdt((struct Xgt_desc_struct *) __pa(&cpu_gdt_descr[0])); + per_cpu(cpu_gdt_descr, 0).address = + __pa(per_cpu(cpu_gdt_descr, 0).address); + load_gdt((struct Xgt_desc_struct *)__pa(&per_cpu(cpu_gdt_descr, 0))); } static void efi_call_phys_epilog(void) { unsigned long cr4; - cpu_gdt_descr[0].address = - (unsigned long) __va(cpu_gdt_descr[0].address); - load_gdt(&cpu_gdt_descr[0]); + per_cpu(cpu_gdt_descr, 0).address = + (unsigned long)__va(per_cpu(cpu_gdt_descr, 0).address); + load_gdt((struct Xgt_desc_struct *)__va(&per_cpu(cpu_gdt_descr, 0))); + cr4 = read_cr4(); if (cr4 & X86_CR4_PSE) { diff --git a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S index 5884469..e0b7c63 100644 --- a/arch/i386/kernel/head.S +++ b/arch/i386/kernel/head.S @@ -398,7 +398,11 @@ ignore_int: pushl 32(%esp) pushl 40(%esp) pushl $int_msg +#ifdef CONFIG_EARLY_PRINTK + call early_printk +#else call printk +#endif addl $(5*4),%esp popl %ds popl %es @@ -530,5 +534,3 @@ ENTRY(cpu_gdt_table) .quad 0x0000000000000000 /* 0xf0 - unused */ .quad 0x0000000000000000 /* 0xf8 - GDT entry 31: double-fault TSS */ - /* Be sure this is zeroed to avoid false validations in Xen */ - .fill PAGE_SIZE_asm / 8 - GDT_ENTRIES,8,0 diff --git a/arch/i386/kernel/i386_ksyms.c b/arch/i386/kernel/i386_ksyms.c index 3999bec..0553250 100644 --- a/arch/i386/kernel/i386_ksyms.c +++ b/arch/i386/kernel/i386_ksyms.c @@ -3,8 +3,6 @@ #include <asm/checksum.h> #include <asm/desc.h> -EXPORT_SYMBOL_GPL(cpu_gdt_descr); - EXPORT_SYMBOL(__down_failed); EXPORT_SYMBOL(__down_failed_interruptible); EXPORT_SYMBOL(__down_failed_trylock); diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c index f2dd218..235822b 100644 --- a/arch/i386/kernel/io_apic.c +++ b/arch/i386/kernel/io_apic.c @@ -2566,8 +2566,10 @@ int __init io_apic_get_unique_id (int ioapic, int apic_id) spin_unlock_irqrestore(&ioapic_lock, flags); /* Sanity check */ - if (reg_00.bits.ID != apic_id) - panic("IOAPIC[%d]: Unable change apic_id!\n", ioapic); + if (reg_00.bits.ID != apic_id) { + printk("IOAPIC[%d]: Unable to change apic_id!\n", ioapic); + return -1; + } } apic_printk(APIC_VERBOSE, KERN_INFO diff --git a/arch/i386/kernel/kprobes.c b/arch/i386/kernel/kprobes.c index 6483eeb..694a139 100644 --- a/arch/i386/kernel/kprobes.c +++ b/arch/i386/kernel/kprobes.c @@ -58,6 +58,11 @@ static inline int is_IF_modifier(kprobe_opcode_t opcode) int __kprobes arch_prepare_kprobe(struct kprobe *p) { + /* insn: must be on special executable page on i386. */ + p->ainsn.insn = get_insn_slot(); + if (!p->ainsn.insn) + return -ENOMEM; + memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t)); p->opcode = *p->addr; return 0; @@ -77,6 +82,13 @@ void __kprobes arch_disarm_kprobe(struct kprobe *p) (unsigned long) p->addr + sizeof(kprobe_opcode_t)); } +void __kprobes arch_remove_kprobe(struct kprobe *p) +{ + down(&kprobe_mutex); + free_insn_slot(p->ainsn.insn); + up(&kprobe_mutex); +} + static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb) { kcb->prev_kprobe.kp = kprobe_running(); @@ -111,7 +123,7 @@ static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs) if (p->opcode == BREAKPOINT_INSTRUCTION) regs->eip = (unsigned long)p->addr; else - regs->eip = (unsigned long)&p->ainsn.insn; + regs->eip = (unsigned long)p->ainsn.insn; } /* Called with kretprobe_lock held */ @@ -351,7 +363,7 @@ static void __kprobes resume_execution(struct kprobe *p, { unsigned long *tos = (unsigned long *)®s->esp; unsigned long next_eip = 0; - unsigned long copy_eip = (unsigned long)&p->ainsn.insn; + unsigned long copy_eip = (unsigned long)p->ainsn.insn; unsigned long orig_eip = (unsigned long)p->addr; switch (p->ainsn.insn[0]) { diff --git a/arch/i386/kernel/mpparse.c b/arch/i386/kernel/mpparse.c index 0102f3d..e6e2f43 100644 --- a/arch/i386/kernel/mpparse.c +++ b/arch/i386/kernel/mpparse.c @@ -710,7 +710,7 @@ void __init get_smp_config (void) * Read the physical hardware table. Anything here will * override the defaults. */ - if (!smp_read_mpc((void *)mpf->mpf_physptr)) { + if (!smp_read_mpc(phys_to_virt(mpf->mpf_physptr))) { smp_found_config = 0; printk(KERN_ERR "BIOS bug, MP table errors detected!...\n"); printk(KERN_ERR "... disabling SMP support. (tell your hw vendor)\n"); @@ -915,6 +915,7 @@ void __init mp_register_ioapic ( u32 gsi_base) { int idx = 0; + int tmpid; if (nr_ioapics >= MAX_IO_APICS) { printk(KERN_ERR "ERROR: Max # of I/O APICs (%d) exceeded " @@ -935,9 +936,14 @@ void __init mp_register_ioapic ( set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address); if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) && (boot_cpu_data.x86 < 15)) - mp_ioapics[idx].mpc_apicid = io_apic_get_unique_id(idx, id); + tmpid = io_apic_get_unique_id(idx, id); else - mp_ioapics[idx].mpc_apicid = id; + tmpid = id; + if (tmpid == -1) { + nr_ioapics--; + return; + } + mp_ioapics[idx].mpc_apicid = tmpid; mp_ioapics[idx].mpc_apicver = io_apic_get_version(idx); /* diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c index 255adb4..eba7f53 100644 --- a/arch/i386/kernel/smpboot.c +++ b/arch/i386/kernel/smpboot.c @@ -87,11 +87,7 @@ EXPORT_SYMBOL(cpu_online_map); cpumask_t cpu_callin_map; cpumask_t cpu_callout_map; EXPORT_SYMBOL(cpu_callout_map); -#ifdef CONFIG_HOTPLUG_CPU -cpumask_t cpu_possible_map = CPU_MASK_ALL; -#else cpumask_t cpu_possible_map; -#endif EXPORT_SYMBOL(cpu_possible_map); static cpumask_t smp_commenced_mask; @@ -902,12 +898,6 @@ static int __devinit do_boot_cpu(int apicid, int cpu) unsigned long start_eip; unsigned short nmi_high = 0, nmi_low = 0; - if (!cpu_gdt_descr[cpu].address && - !(cpu_gdt_descr[cpu].address = get_zeroed_page(GFP_KERNEL))) { - printk("Failed to allocate GDT for CPU %d\n", cpu); - return 1; - } - ++cpucount; /* diff --git a/arch/i386/kernel/syscall_table.S b/arch/i386/kernel/syscall_table.S index 5a8b3fb..ac687d0 100644 --- a/arch/i386/kernel/syscall_table.S +++ b/arch/i386/kernel/syscall_table.S @@ -299,7 +299,7 @@ ENTRY(sys_call_table) .long sys_mknodat .long sys_fchownat .long sys_futimesat - .long sys_newfstatat /* 300 */ + .long sys_fstatat64 /* 300 */ .long sys_unlinkat .long sys_renameat .long sys_linkat diff --git a/arch/i386/kernel/timers/timer_tsc.c b/arch/i386/kernel/timers/timer_tsc.c index 7c86e3c..a7f5a2a 100644 --- a/arch/i386/kernel/timers/timer_tsc.c +++ b/arch/i386/kernel/timers/timer_tsc.c @@ -282,6 +282,10 @@ time_cpufreq_notifier(struct notifier_block *nb, unsigned long val, if (val != CPUFREQ_RESUMECHANGE) write_seqlock_irq(&xtime_lock); if (!ref_freq) { + if (!freq->old){ + ref_freq = freq->new; + goto end; + } ref_freq = freq->old; loops_per_jiffy_ref = cpu_data[freq->cpu].loops_per_jiffy; #ifndef CONFIG_SMP @@ -307,6 +311,7 @@ time_cpufreq_notifier(struct notifier_block *nb, unsigned long val, #endif } +end: if (val != CPUFREQ_RESUMECHANGE) write_sequnlock_irq(&xtime_lock); diff --git a/arch/i386/mach-default/topology.c b/arch/i386/kernel/topology.c index b643140..67a0e1b 100644 --- a/arch/i386/mach-default/topology.c +++ b/arch/i386/kernel/topology.c @@ -1,12 +1,12 @@ /* - * arch/i386/mach-generic/topology.c - Populate driverfs with topology information + * arch/i386/kernel/topology.c - Populate driverfs with topology information * * Written by: Matthew Dobson, IBM Corporation * Original Code: Paul Dorwin, IBM Corporation, Patrick Mochel, OSDL * * Copyright (C) 2002, IBM Corp. * - * All rights reserved. + * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -34,7 +34,7 @@ static struct i386_cpu cpu_devices[NR_CPUS]; int arch_register_cpu(int num){ struct node *parent = NULL; - + #ifdef CONFIG_NUMA int node = cpu_to_node(num); if (node_online(node)) diff --git a/arch/i386/kernel/vsyscall-sysenter.S b/arch/i386/kernel/vsyscall-sysenter.S index 4daefb2..76b7281 100644 --- a/arch/i386/kernel/vsyscall-sysenter.S +++ b/arch/i386/kernel/vsyscall-sysenter.S @@ -7,6 +7,21 @@ * for details. */ +/* + * The caller puts arg2 in %ecx, which gets pushed. The kernel will use + * %ecx itself for arg2. The pushing is because the sysexit instruction + * (found in entry.S) requires that we clobber %ecx with the desired %esp. + * User code might expect that %ecx is unclobbered though, as it would be + * for returning via the iret instruction, so we must push and pop. + * + * The caller puts arg3 in %edx, which the sysexit instruction requires + * for %eip. Thus, exactly as for arg2, we must push and pop. + * + * Arg6 is different. The caller puts arg6 in %ebp. Since the sysenter + * instruction clobbers %esp, the user's %esp won't even survive entry + * into the kernel. We store %esp in %ebp. Code in entry.S must fetch + * arg6 from the stack. + */ .text .globl __kernel_vsyscall .type __kernel_vsyscall,@function diff --git a/arch/i386/mach-default/Makefile b/arch/i386/mach-default/Makefile index e95bb02..012fe34 100644 --- a/arch/i386/mach-default/Makefile +++ b/arch/i386/mach-default/Makefile @@ -2,4 +2,4 @@ # Makefile for the linux kernel. # -obj-y := setup.o topology.o +obj-y := setup.o diff --git a/arch/i386/mach-voyager/voyager_basic.c b/arch/i386/mach-voyager/voyager_basic.c index aa49a33..b584060 100644 --- a/arch/i386/mach-voyager/voyager_basic.c +++ b/arch/i386/mach-voyager/voyager_basic.c @@ -23,6 +23,8 @@ #include <linux/delay.h> #include <linux/reboot.h> #include <linux/sysrq.h> +#include <linux/smp.h> +#include <linux/nodemask.h> #include <asm/io.h> #include <asm/voyager.h> #include <asm/vic.h> @@ -328,4 +330,3 @@ void machine_power_off(void) if (pm_power_off) pm_power_off(); } - diff --git a/arch/i386/mach-voyager/voyager_smp.c b/arch/i386/mach-voyager/voyager_smp.c index 72a1b9c..8165626 100644 --- a/arch/i386/mach-voyager/voyager_smp.c +++ b/arch/i386/mach-voyager/voyager_smp.c @@ -240,7 +240,7 @@ static cpumask_t smp_commenced_mask = CPU_MASK_NONE; cpumask_t cpu_callin_map = CPU_MASK_NONE; cpumask_t cpu_callout_map = CPU_MASK_NONE; EXPORT_SYMBOL(cpu_callout_map); -cpumask_t cpu_possible_map = CPU_MASK_ALL; +cpumask_t cpu_possible_map = CPU_MASK_NONE; EXPORT_SYMBOL(cpu_possible_map); /* The per processor IRQ masks (these are usually kept in sync) */ @@ -402,6 +402,7 @@ find_smp_config(void) cpus_addr(phys_cpu_present_map)[0] |= voyager_extended_cmos_read(VOYAGER_PROCESSOR_PRESENT_MASK + 1) << 8; cpus_addr(phys_cpu_present_map)[0] |= voyager_extended_cmos_read(VOYAGER_PROCESSOR_PRESENT_MASK + 2) << 16; cpus_addr(phys_cpu_present_map)[0] |= voyager_extended_cmos_read(VOYAGER_PROCESSOR_PRESENT_MASK + 3) << 24; + cpu_possible_map = phys_cpu_present_map; printk("VOYAGER SMP: phys_cpu_present_map = 0x%lx\n", cpus_addr(phys_cpu_present_map)[0]); /* Here we set up the VIC to enable SMP */ /* enable the CPIs by writing the base vector to their register */ diff --git a/arch/i386/oprofile/backtrace.c b/arch/i386/oprofile/backtrace.c index acc1813..c049ce4 100644 --- a/arch/i386/oprofile/backtrace.c +++ b/arch/i386/oprofile/backtrace.c @@ -20,7 +20,20 @@ struct frame_head { } __attribute__((packed)); static struct frame_head * -dump_backtrace(struct frame_head * head) +dump_kernel_backtrace(struct frame_head * head) +{ + oprofile_add_trace(head->ret); + + /* frame pointers should strictly progress back up the stack + * (towards higher addresses) */ + if (head >= head->ebp) + return NULL; + + return head->ebp; +} + +static struct frame_head * +dump_user_backtrace(struct frame_head * head) { struct frame_head bufhead[2]; @@ -105,10 +118,10 @@ x86_backtrace(struct pt_regs * const regs, unsigned int depth) if (!user_mode_vm(regs)) { while (depth-- && valid_kernel_stack(head, regs)) - head = dump_backtrace(head); + head = dump_kernel_backtrace(head); return; } while (depth-- && head) - head = dump_backtrace(head); + head = dump_user_backtrace(head); } |