Patches contributed by Eötvös Lorand University


commit 0ebb26e7a4e2c5337502e98b2221e037fda911b9
Author: Ingo Molnar <mingo@elte.hu>
Date:   Fri Dec 12 11:26:39 2008 +0100

    sparse irqs: handle !GENIRQ platforms
    
    Impact: build fix
    
    fix:
    
     In file included from /home/mingo/tip/arch/m68k/amiga/amiints.c:39:
     /home/mingo/tip/include/linux/interrupt.h:21: error: expected identifier or '('
     /home/mingo/tip/arch/m68k/amiga/amiints.c: In function 'amiga_init_IRQ':
    
    Signed-off-by: Ingo Molnar <mingo@elte.hu>

diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index 79e915e7e8a5..777f89e00b4a 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -14,12 +14,12 @@
 #include <linux/irqflags.h>
 #include <linux/smp.h>
 #include <linux/percpu.h>
+#include <linux/irqnr.h>
+
 #include <asm/atomic.h>
 #include <asm/ptrace.h>
 #include <asm/system.h>
 
-extern int nr_irqs;
-
 /*
  * These correspond to the IORESOURCE_IRQ_* defines in
  * linux/ioport.h to select the interrupt line behaviour.  When
diff --git a/include/linux/irqnr.h b/include/linux/irqnr.h
index 13754f813589..95d2b74641f5 100644
--- a/include/linux/irqnr.h
+++ b/include/linux/irqnr.h
@@ -1,6 +1,11 @@
 #ifndef _LINUX_IRQNR_H
 #define _LINUX_IRQNR_H
 
+/*
+ * Generic irq_desc iterators:
+ */
+#ifdef __KERNEL__
+
 #ifndef CONFIG_GENERIC_HARDIRQS
 #include <asm/irq.h>
 # define nr_irqs		NR_IRQS
@@ -11,10 +16,12 @@
 # define for_each_irq_desc_reverse(irq, desc)                          \
 	for (irq = nr_irqs - 1; irq >= 0; irq--)
 #else
+
+extern int nr_irqs;
+
 #ifndef CONFIG_SPARSE_IRQ
 
 struct irq_desc;
-extern int nr_irqs;
 # define for_each_irq_desc(irq, desc)		\
 	for (irq = 0, desc = irq_desc; irq < nr_irqs; irq++, desc++)
 # define for_each_irq_desc_reverse(irq, desc)                          \
@@ -26,4 +33,6 @@ extern int nr_irqs;
 #define for_each_irq_nr(irq)                   \
        for (irq = 0; irq < nr_irqs; irq++)
 
+#endif /* __KERNEL__ */
+
 #endif
diff --git a/include/linux/random.h b/include/linux/random.h
index ad9daa2374d5..adbf3bd3c6b3 100644
--- a/include/linux/random.h
+++ b/include/linux/random.h
@@ -8,6 +8,7 @@
 #define _LINUX_RANDOM_H
 
 #include <linux/ioctl.h>
+#include <linux/irqnr.h>
 
 /* ioctl()'s for the random number generator */
 
@@ -49,7 +50,6 @@ struct timer_rand_state;
 
 extern struct timer_rand_state *irq_timer_state[];
 
-extern int nr_irqs;
 static inline struct timer_rand_state *get_timer_rand_state(unsigned int irq)
 {
 	if (irq >= nr_irqs)

commit 2bed8446819a7c5033aa1da138d9f230ae212edc
Author: Ingo Molnar <mingo@elte.hu>
Date:   Fri Dec 12 12:13:36 2008 +0100

    tracing/function-graph-tracer: add a new .irqentry.text section, fix
    
    Impact: build fix
    
    32-bit x86 needs this section too.
    
    Signed-off-by: Ingo Molnar <mingo@elte.hu>

diff --git a/arch/x86/kernel/vmlinux_32.lds.S b/arch/x86/kernel/vmlinux_32.lds.S
index a9b8560adbc2..82c67559dde7 100644
--- a/arch/x86/kernel/vmlinux_32.lds.S
+++ b/arch/x86/kernel/vmlinux_32.lds.S
@@ -44,6 +44,7 @@ SECTIONS
 	SCHED_TEXT
 	LOCK_TEXT
 	KPROBES_TEXT
+	IRQENTRY_TEXT
 	*(.fixup)
 	*(.gnu.warning)
   	_etext = .;			/* End of text section */

commit 92bf73e90a35d40ebc1446488218f03833b36f86
Merge: 447557ac7ce1 915b0d0104b7
Author: Ingo Molnar <mingo@elte.hu>
Date:   Fri Dec 12 12:00:02 2008 +0100

    Merge branch 'x86/irq' into perfcounters/core
    
    ( with manual semantic merge of arch/x86/kernel/cpu/perf_counter.c )

diff --cc arch/x86/kernel/cpu/perf_counter.c
index 4854cca7fffd,000000000000..b903f8df72bb
mode 100644,000000..100644
--- a/arch/x86/kernel/cpu/perf_counter.c
+++ b/arch/x86/kernel/cpu/perf_counter.c
@@@ -1,563 -1,0 +1,559 @@@
 +/*
 + * Performance counter x86 architecture code
 + *
 + *  Copyright(C) 2008 Thomas Gleixner <tglx@linutronix.de>
 + *  Copyright(C) 2008 Red Hat, Inc., Ingo Molnar
 + *
 + *  For licencing details see kernel-base/COPYING
 + */
 +
 +#include <linux/perf_counter.h>
 +#include <linux/capability.h>
 +#include <linux/notifier.h>
 +#include <linux/hardirq.h>
 +#include <linux/kprobes.h>
 +#include <linux/module.h>
 +#include <linux/kdebug.h>
 +#include <linux/sched.h>
 +
 +#include <asm/intel_arch_perfmon.h>
 +#include <asm/apic.h>
 +
 +static bool perf_counters_initialized __read_mostly;
 +
 +/*
 + * Number of (generic) HW counters:
 + */
 +static int nr_hw_counters __read_mostly;
 +static u32 perf_counter_mask __read_mostly;
 +
 +/* No support for fixed function counters yet */
 +
 +#define MAX_HW_COUNTERS		8
 +
 +struct cpu_hw_counters {
 +	struct perf_counter	*counters[MAX_HW_COUNTERS];
 +	unsigned long		used[BITS_TO_LONGS(MAX_HW_COUNTERS)];
 +};
 +
 +/*
 + * Intel PerfMon v3. Used on Core2 and later.
 + */
 +static DEFINE_PER_CPU(struct cpu_hw_counters, cpu_hw_counters);
 +
 +const int intel_perfmon_event_map[] =
 +{
 +  [PERF_COUNT_CYCLES]			= 0x003c,
 +  [PERF_COUNT_INSTRUCTIONS]		= 0x00c0,
 +  [PERF_COUNT_CACHE_REFERENCES]		= 0x4f2e,
 +  [PERF_COUNT_CACHE_MISSES]		= 0x412e,
 +  [PERF_COUNT_BRANCH_INSTRUCTIONS]	= 0x00c4,
 +  [PERF_COUNT_BRANCH_MISSES]		= 0x00c5,
 +};
 +
 +const int max_intel_perfmon_events = ARRAY_SIZE(intel_perfmon_event_map);
 +
 +/*
 + * Setup the hardware configuration for a given hw_event_type
 + */
 +static int __hw_perf_counter_init(struct perf_counter *counter)
 +{
 +	struct perf_counter_hw_event *hw_event = &counter->hw_event;
 +	struct hw_perf_counter *hwc = &counter->hw;
 +
 +	if (unlikely(!perf_counters_initialized))
 +		return -EINVAL;
 +
 +	/*
 +	 * Count user events, and generate PMC IRQs:
 +	 * (keep 'enabled' bit clear for now)
 +	 */
 +	hwc->config = ARCH_PERFMON_EVENTSEL_USR | ARCH_PERFMON_EVENTSEL_INT;
 +
 +	/*
 +	 * If privileged enough, count OS events too, and allow
 +	 * NMI events as well:
 +	 */
 +	hwc->nmi = 0;
 +	if (capable(CAP_SYS_ADMIN)) {
 +		hwc->config |= ARCH_PERFMON_EVENTSEL_OS;
 +		if (hw_event->nmi)
 +			hwc->nmi = 1;
 +	}
 +
 +	hwc->config_base	= MSR_ARCH_PERFMON_EVENTSEL0;
 +	hwc->counter_base	= MSR_ARCH_PERFMON_PERFCTR0;
 +
 +	hwc->irq_period		= hw_event->irq_period;
 +	/*
 +	 * Intel PMCs cannot be accessed sanely above 32 bit width,
 +	 * so we install an artificial 1<<31 period regardless of
 +	 * the generic counter period:
 +	 */
 +	if (!hwc->irq_period)
 +		hwc->irq_period = 0x7FFFFFFF;
 +
 +	hwc->next_count	= -(s32)hwc->irq_period;
 +
 +	/*
 +	 * Raw event type provide the config in the event structure
 +	 */
 +	if (hw_event->raw) {
 +		hwc->config |= hw_event->type;
 +	} else {
 +		if (hw_event->type >= max_intel_perfmon_events)
 +			return -EINVAL;
 +		/*
 +		 * The generic map:
 +		 */
 +		hwc->config |= intel_perfmon_event_map[hw_event->type];
 +	}
 +	counter->wakeup_pending = 0;
 +
 +	return 0;
 +}
 +
 +void hw_perf_enable_all(void)
 +{
 +	wrmsr(MSR_CORE_PERF_GLOBAL_CTRL, perf_counter_mask, 0);
 +}
 +
 +void hw_perf_restore(u64 ctrl)
 +{
 +	wrmsr(MSR_CORE_PERF_GLOBAL_CTRL, ctrl, 0);
 +}
 +EXPORT_SYMBOL_GPL(hw_perf_restore);
 +
 +u64 hw_perf_save_disable(void)
 +{
 +	u64 ctrl;
 +
 +	rdmsrl(MSR_CORE_PERF_GLOBAL_CTRL, ctrl);
 +	wrmsr(MSR_CORE_PERF_GLOBAL_CTRL, 0, 0);
 +	return ctrl;
 +}
 +EXPORT_SYMBOL_GPL(hw_perf_save_disable);
 +
 +static inline void
 +__x86_perf_counter_disable(struct hw_perf_counter *hwc, unsigned int idx)
 +{
 +	wrmsr(hwc->config_base + idx, hwc->config, 0);
 +}
 +
 +static DEFINE_PER_CPU(u64, prev_next_count[MAX_HW_COUNTERS]);
 +
 +static void __hw_perf_counter_set_period(struct hw_perf_counter *hwc, int idx)
 +{
 +	per_cpu(prev_next_count[idx], smp_processor_id()) = hwc->next_count;
 +
 +	wrmsr(hwc->counter_base + idx, hwc->next_count, 0);
 +}
 +
 +static void __x86_perf_counter_enable(struct hw_perf_counter *hwc, int idx)
 +{
 +	wrmsr(hwc->config_base + idx,
 +	      hwc->config | ARCH_PERFMON_EVENTSEL0_ENABLE, 0);
 +}
 +
 +static void x86_perf_counter_enable(struct perf_counter *counter)
 +{
 +	struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters);
 +	struct hw_perf_counter *hwc = &counter->hw;
 +	int idx = hwc->idx;
 +
 +	/* Try to get the previous counter again */
 +	if (test_and_set_bit(idx, cpuc->used)) {
 +		idx = find_first_zero_bit(cpuc->used, nr_hw_counters);
 +		set_bit(idx, cpuc->used);
 +		hwc->idx = idx;
 +	}
 +
 +	perf_counters_lapic_init(hwc->nmi);
 +
 +	__x86_perf_counter_disable(hwc, idx);
 +
 +	cpuc->counters[idx] = counter;
 +
 +	__hw_perf_counter_set_period(hwc, idx);
 +	__x86_perf_counter_enable(hwc, idx);
 +}
 +
 +static void __hw_perf_save_counter(struct perf_counter *counter,
 +				   struct hw_perf_counter *hwc, int idx)
 +{
 +	s64 raw = -1;
 +	s64 delta;
 +
 +	/*
 +	 * Get the raw hw counter value:
 +	 */
 +	rdmsrl(hwc->counter_base + idx, raw);
 +
 +	/*
 +	 * Rebase it to zero (it started counting at -irq_period),
 +	 * to see the delta since ->prev_count:
 +	 */
 +	delta = (s64)hwc->irq_period + (s64)(s32)raw;
 +
 +	atomic64_counter_set(counter, hwc->prev_count + delta);
 +
 +	/*
 +	 * Adjust the ->prev_count offset - if we went beyond
 +	 * irq_period of units, then we got an IRQ and the counter
 +	 * was set back to -irq_period:
 +	 */
 +	while (delta >= (s64)hwc->irq_period) {
 +		hwc->prev_count += hwc->irq_period;
 +		delta -= (s64)hwc->irq_period;
 +	}
 +
 +	/*
 +	 * Calculate the next raw counter value we'll write into
 +	 * the counter at the next sched-in time:
 +	 */
 +	delta -= (s64)hwc->irq_period;
 +
 +	hwc->next_count = (s32)delta;
 +}
 +
 +void perf_counter_print_debug(void)
 +{
 +	u64 ctrl, status, overflow, pmc_ctrl, pmc_count, next_count;
 +	int cpu, idx;
 +
 +	if (!nr_hw_counters)
 +		return;
 +
 +	local_irq_disable();
 +
 +	cpu = smp_processor_id();
 +
 +	rdmsrl(MSR_CORE_PERF_GLOBAL_CTRL, ctrl);
 +	rdmsrl(MSR_CORE_PERF_GLOBAL_STATUS, status);
 +	rdmsrl(MSR_CORE_PERF_GLOBAL_OVF_CTRL, overflow);
 +
 +	printk(KERN_INFO "\n");
 +	printk(KERN_INFO "CPU#%d: ctrl:       %016llx\n", cpu, ctrl);
 +	printk(KERN_INFO "CPU#%d: status:     %016llx\n", cpu, status);
 +	printk(KERN_INFO "CPU#%d: overflow:   %016llx\n", cpu, overflow);
 +
 +	for (idx = 0; idx < nr_hw_counters; idx++) {
 +		rdmsrl(MSR_ARCH_PERFMON_EVENTSEL0 + idx, pmc_ctrl);
 +		rdmsrl(MSR_ARCH_PERFMON_PERFCTR0  + idx, pmc_count);
 +
 +		next_count = per_cpu(prev_next_count[idx], cpu);
 +
 +		printk(KERN_INFO "CPU#%d: PMC%d ctrl:  %016llx\n",
 +			cpu, idx, pmc_ctrl);
 +		printk(KERN_INFO "CPU#%d: PMC%d count: %016llx\n",
 +			cpu, idx, pmc_count);
 +		printk(KERN_INFO "CPU#%d: PMC%d next:  %016llx\n",
 +			cpu, idx, next_count);
 +	}
 +	local_irq_enable();
 +}
 +
 +static void x86_perf_counter_disable(struct perf_counter *counter)
 +{
 +	struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters);
 +	struct hw_perf_counter *hwc = &counter->hw;
 +	unsigned int idx = hwc->idx;
 +
 +	__x86_perf_counter_disable(hwc, idx);
 +
 +	clear_bit(idx, cpuc->used);
 +	cpuc->counters[idx] = NULL;
 +	__hw_perf_save_counter(counter, hwc, idx);
 +}
 +
 +static void x86_perf_counter_read(struct perf_counter *counter)
 +{
 +	struct hw_perf_counter *hwc = &counter->hw;
 +	unsigned long addr = hwc->counter_base + hwc->idx;
 +	s64 offs, val = -1LL;
 +	s32 val32;
 +
 +	/* Careful: NMI might modify the counter offset */
 +	do {
 +		offs = hwc->prev_count;
 +		rdmsrl(addr, val);
 +	} while (offs != hwc->prev_count);
 +
 +	val32 = (s32) val;
 +	val = (s64)hwc->irq_period + (s64)val32;
 +	atomic64_counter_set(counter, hwc->prev_count + val);
 +}
 +
 +static void perf_store_irq_data(struct perf_counter *counter, u64 data)
 +{
 +	struct perf_data *irqdata = counter->irqdata;
 +
 +	if (irqdata->len > PERF_DATA_BUFLEN - sizeof(u64)) {
 +		irqdata->overrun++;
 +	} else {
 +		u64 *p = (u64 *) &irqdata->data[irqdata->len];
 +
 +		*p = data;
 +		irqdata->len += sizeof(u64);
 +	}
 +}
 +
 +/*
 + * NMI-safe enable method:
 + */
 +static void perf_save_and_restart(struct perf_counter *counter)
 +{
 +	struct hw_perf_counter *hwc = &counter->hw;
 +	int idx = hwc->idx;
 +	u64 pmc_ctrl;
 +
 +	rdmsrl(MSR_ARCH_PERFMON_EVENTSEL0 + idx, pmc_ctrl);
 +
 +	__hw_perf_save_counter(counter, hwc, idx);
 +	__hw_perf_counter_set_period(hwc, idx);
 +
 +	if (pmc_ctrl & ARCH_PERFMON_EVENTSEL0_ENABLE)
 +		__x86_perf_counter_enable(hwc, idx);
 +}
 +
 +static void
 +perf_handle_group(struct perf_counter *sibling, u64 *status, u64 *overflown)
 +{
 +	struct perf_counter *counter, *group_leader = sibling->group_leader;
 +	int bit;
 +
 +	/*
 +	 * Store the counter's own timestamp first:
 +	 */
 +	perf_store_irq_data(sibling, sibling->hw_event.type);
 +	perf_store_irq_data(sibling, atomic64_counter_read(sibling));
 +
 +	/*
 +	 * Then store sibling timestamps (if any):
 +	 */
 +	list_for_each_entry(counter, &group_leader->sibling_list, list_entry) {
 +		if (counter->state != PERF_COUNTER_STATE_ACTIVE) {
 +			/*
 +			 * When counter was not in the overflow mask, we have to
 +			 * read it from hardware. We read it as well, when it
 +			 * has not been read yet and clear the bit in the
 +			 * status mask.
 +			 */
 +			bit = counter->hw.idx;
 +			if (!test_bit(bit, (unsigned long *) overflown) ||
 +			    test_bit(bit, (unsigned long *) status)) {
 +				clear_bit(bit, (unsigned long *) status);
 +				perf_save_and_restart(counter);
 +			}
 +		}
 +		perf_store_irq_data(sibling, counter->hw_event.type);
 +		perf_store_irq_data(sibling, atomic64_counter_read(counter));
 +	}
 +}
 +
 +/*
 + * This handler is triggered by the local APIC, so the APIC IRQ handling
 + * rules apply:
 + */
 +static void __smp_perf_counter_interrupt(struct pt_regs *regs, int nmi)
 +{
 +	int bit, cpu = smp_processor_id();
 +	u64 ack, status, saved_global;
 +	struct cpu_hw_counters *cpuc;
 +
 +	rdmsrl(MSR_CORE_PERF_GLOBAL_CTRL, saved_global);
 +
 +	/* Disable counters globally */
 +	wrmsr(MSR_CORE_PERF_GLOBAL_CTRL, 0, 0);
 +	ack_APIC_irq();
 +
 +	cpuc = &per_cpu(cpu_hw_counters, cpu);
 +
 +	rdmsrl(MSR_CORE_PERF_GLOBAL_STATUS, status);
 +	if (!status)
 +		goto out;
 +
 +again:
 +	ack = status;
 +	for_each_bit(bit, (unsigned long *) &status, nr_hw_counters) {
 +		struct perf_counter *counter = cpuc->counters[bit];
 +
 +		clear_bit(bit, (unsigned long *) &status);
 +		if (!counter)
 +			continue;
 +
 +		perf_save_and_restart(counter);
 +
 +		switch (counter->hw_event.record_type) {
 +		case PERF_RECORD_SIMPLE:
 +			continue;
 +		case PERF_RECORD_IRQ:
 +			perf_store_irq_data(counter, instruction_pointer(regs));
 +			break;
 +		case PERF_RECORD_GROUP:
 +			perf_handle_group(counter, &status, &ack);
 +			break;
 +		}
 +		/*
 +		 * From NMI context we cannot call into the scheduler to
 +		 * do a task wakeup - but we mark these counters as
 +		 * wakeup_pending and initate a wakeup callback:
 +		 */
 +		if (nmi) {
 +			counter->wakeup_pending = 1;
 +			set_tsk_thread_flag(current, TIF_PERF_COUNTERS);
 +		} else {
 +			wake_up(&counter->waitq);
 +		}
 +	}
 +
 +	wrmsr(MSR_CORE_PERF_GLOBAL_OVF_CTRL, ack, 0);
 +
 +	/*
 +	 * Repeat if there is more work to be done:
 +	 */
 +	rdmsrl(MSR_CORE_PERF_GLOBAL_STATUS, status);
 +	if (status)
 +		goto again;
 +out:
 +	/*
 +	 * Restore - do not reenable when global enable is off:
 +	 */
 +	wrmsr(MSR_CORE_PERF_GLOBAL_CTRL, saved_global, 0);
 +}
 +
 +void smp_perf_counter_interrupt(struct pt_regs *regs)
 +{
 +	irq_enter();
- #ifdef CONFIG_X86_64
- 	add_pda(apic_perf_irqs, 1);
- #else
- 	per_cpu(irq_stat, smp_processor_id()).apic_perf_irqs++;
- #endif
++	inc_irq_stat(apic_perf_irqs);
 +	apic_write(APIC_LVTPC, LOCAL_PERF_VECTOR);
 +	__smp_perf_counter_interrupt(regs, 0);
 +
 +	irq_exit();
 +}
 +
 +/*
 + * This handler is triggered by NMI contexts:
 + */
 +void perf_counter_notify(struct pt_regs *regs)
 +{
 +	struct cpu_hw_counters *cpuc;
 +	unsigned long flags;
 +	int bit, cpu;
 +
 +	local_irq_save(flags);
 +	cpu = smp_processor_id();
 +	cpuc = &per_cpu(cpu_hw_counters, cpu);
 +
 +	for_each_bit(bit, cpuc->used, nr_hw_counters) {
 +		struct perf_counter *counter = cpuc->counters[bit];
 +
 +		if (!counter)
 +			continue;
 +
 +		if (counter->wakeup_pending) {
 +			counter->wakeup_pending = 0;
 +			wake_up(&counter->waitq);
 +		}
 +	}
 +
 +	local_irq_restore(flags);
 +}
 +
 +void __cpuinit perf_counters_lapic_init(int nmi)
 +{
 +	u32 apic_val;
 +
 +	if (!perf_counters_initialized)
 +		return;
 +	/*
 +	 * Enable the performance counter vector in the APIC LVT:
 +	 */
 +	apic_val = apic_read(APIC_LVTERR);
 +
 +	apic_write(APIC_LVTERR, apic_val | APIC_LVT_MASKED);
 +	if (nmi)
 +		apic_write(APIC_LVTPC, APIC_DM_NMI);
 +	else
 +		apic_write(APIC_LVTPC, LOCAL_PERF_VECTOR);
 +	apic_write(APIC_LVTERR, apic_val);
 +}
 +
 +static int __kprobes
 +perf_counter_nmi_handler(struct notifier_block *self,
 +			 unsigned long cmd, void *__args)
 +{
 +	struct die_args *args = __args;
 +	struct pt_regs *regs;
 +
 +	if (likely(cmd != DIE_NMI_IPI))
 +		return NOTIFY_DONE;
 +
 +	regs = args->regs;
 +
 +	apic_write(APIC_LVTPC, APIC_DM_NMI);
 +	__smp_perf_counter_interrupt(regs, 1);
 +
 +	return NOTIFY_STOP;
 +}
 +
 +static __read_mostly struct notifier_block perf_counter_nmi_notifier = {
 +	.notifier_call		= perf_counter_nmi_handler
 +};
 +
 +void __init init_hw_perf_counters(void)
 +{
 +	union cpuid10_eax eax;
 +	unsigned int unused;
 +	unsigned int ebx;
 +
 +	if (!cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON))
 +		return;
 +
 +	/*
 +	 * Check whether the Architectural PerfMon supports
 +	 * Branch Misses Retired Event or not.
 +	 */
 +	cpuid(10, &(eax.full), &ebx, &unused, &unused);
 +	if (eax.split.mask_length <= ARCH_PERFMON_BRANCH_MISSES_RETIRED)
 +		return;
 +
 +	printk(KERN_INFO "Intel Performance Monitoring support detected.\n");
 +
 +	printk(KERN_INFO "... version:      %d\n", eax.split.version_id);
 +	printk(KERN_INFO "... num_counters: %d\n", eax.split.num_counters);
 +	nr_hw_counters = eax.split.num_counters;
 +	if (nr_hw_counters > MAX_HW_COUNTERS) {
 +		nr_hw_counters = MAX_HW_COUNTERS;
 +		WARN(1, KERN_ERR "hw perf counters %d > max(%d), clipping!",
 +			nr_hw_counters, MAX_HW_COUNTERS);
 +	}
 +	perf_counter_mask = (1 << nr_hw_counters) - 1;
 +	perf_max_counters = nr_hw_counters;
 +
 +	printk(KERN_INFO "... bit_width:    %d\n", eax.split.bit_width);
 +	printk(KERN_INFO "... mask_length:  %d\n", eax.split.mask_length);
 +
 +	perf_counters_lapic_init(0);
 +	register_die_notifier(&perf_counter_nmi_notifier);
 +
 +	perf_counters_initialized = true;
 +}
 +
 +static const struct hw_perf_counter_ops x86_perf_counter_ops = {
 +	.hw_perf_counter_enable		= x86_perf_counter_enable,
 +	.hw_perf_counter_disable	= x86_perf_counter_disable,
 +	.hw_perf_counter_read		= x86_perf_counter_read,
 +};
 +
 +const struct hw_perf_counter_ops *
 +hw_perf_counter_init(struct perf_counter *counter)
 +{
 +	int err;
 +
 +	err = __hw_perf_counter_init(counter);
 +	if (err)
 +		return NULL;
 +
 +	return &x86_perf_counter_ops;
 +}

commit fd10902797fc9d6abaf55d9c2e3c6698c90b10c7
Merge: 5b3eec0c8003 8b1fae4e4200
Author: Ingo Molnar <mingo@elte.hu>
Date:   Fri Dec 12 11:59:39 2008 +0100

    Merge commit 'v2.6.28-rc8' into x86/irq

commit e18d7af85296cb6999aae171e8a9f8612bea5ae0
Merge: 3555105333ae 8b1fae4e4200
Author: Ingo Molnar <mingo@elte.hu>
Date:   Fri Dec 12 11:53:43 2008 +0100

    Merge commit 'v2.6.28-rc8' into x86/mm

commit 85072bd55219231b8ca5d9d3fa3492eb4fa6635f
Author: Ingo Molnar <mingo@elte.hu>
Date:   Fri Dec 12 11:08:42 2008 +0100

    x86, debug: remove EBDA debug printk
    
    Remove leftover EBDA debug message.
    
    Reported-by: Andrew Morton <akpm@linux-foundation.org>
    Signed-off-by: Ingo Molnar <mingo@elte.hu>

diff --git a/arch/x86/kernel/head.c b/arch/x86/kernel/head.c
index 1dcb0f13897e..3e66bd364a9d 100644
--- a/arch/x86/kernel/head.c
+++ b/arch/x86/kernel/head.c
@@ -35,7 +35,6 @@ void __init reserve_ebda_region(void)
 
 	/* start of EBDA area */
 	ebda_addr = get_bios_ebda();
-	printk(KERN_INFO "BIOS EBDA/lowmem at: %08x/%08x\n", ebda_addr, lowmem);
 
 	/* Fixup: bios puts an EBDA in the top 64K segment */
 	/* of conventional memory, but does not adjust lowmem. */

commit c1dfdc7597d051b09555d4ae2acb90403e238746
Merge: efbe027e95dc 8b1fae4e4200
Author: Ingo Molnar <mingo@elte.hu>
Date:   Fri Dec 12 10:29:35 2008 +0100

    Merge commit 'v2.6.28-rc8' into sched/core

commit d69d59f49763e6bd047c591c6c1f84c8e13da931
Author: Ingo Molnar <mingo@elte.hu>
Date:   Fri Dec 12 09:38:57 2008 +0100

    oprofile: select RING_BUFFER
    
    Impact: build fix
    
    OProfile now depends on the ring buffer infrastructure:
    
     arch/x86/oprofile/built-in.o: In function `oprofile_add_ibs_sample':
     : undefined reference to `ring_buffer_unlock_commit'
    
    Select TRACING and RING_BUFFER when oprofile is enabled.
    
    Signed-off-by: Ingo Molnar <mingo@elte.hu>

diff --git a/arch/Kconfig b/arch/Kconfig
index 471e72dbaf8b..2e13aa261929 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -6,6 +6,8 @@ config OPROFILE
 	tristate "OProfile system profiling (EXPERIMENTAL)"
 	depends on PROFILING
 	depends on HAVE_OPROFILE
+	select TRACING
+	select RING_BUFFER
 	help
 	  OProfile is a profiling system capable of profiling the
 	  whole system, include the kernel, kernel modules, libraries,

commit 8808500f26a61757cb414da76b271bbd09d5958c
Author: Ingo Molnar <mingo@elte.hu>
Date:   Fri Dec 12 09:20:12 2008 +0100

    x86: soften multi-BAR mapping sanity check warning message
    
    Impact: make debug warning less scary
    
    The ioremap() time multi-BAR map warning has been causing false
    positives:
    
      http://lkml.org/lkml/2008/12/10/432
      http://lkml.org/lkml/2008/12/11/136
    
    So make it less scary by making it once-per-boot, by making it KERN_INFO
    and by adding this text:
    
      "Info: mapping multiple BARs. Your kernel is fine."
    
    Signed-off-by: Ingo Molnar <mingo@elte.hu>

diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c
index d4c4307ff3e0..bd85d42819e1 100644
--- a/arch/x86/mm/ioremap.c
+++ b/arch/x86/mm/ioremap.c
@@ -223,7 +223,8 @@ static void __iomem *__ioremap_caller(resource_size_t phys_addr,
 	 * Check if the request spans more than any BAR in the iomem resource
 	 * tree.
 	 */
-	WARN_ON(iomem_map_sanity_check(phys_addr, size));
+	WARN_ONCE(iomem_map_sanity_check(phys_addr, size),
+		  KERN_INFO "Info: mapping multiple BARs. Your kernel is fine.");
 
 	/*
 	 * Don't allow anybody to remap normal RAM that we're using..

commit ffc2238af8431d930d2c15f16feecf1fd6d75642
Author: Ingo Molnar <mingo@elte.hu>
Date:   Fri Dec 12 08:21:19 2008 +0100

    x86, bts: fix build error
    
    Impact: build fix
    
     arch/x86/kernel/ds.c: In function 'ds_request':
     arch/x86/kernel/ds.c:236: sorry, unimplemented: inlining failed in call to 'ds_get_context': recursive inlining
    
    but the recursion here is scary ...
    
    Signed-off-by: Ingo Molnar <mingo@elte.hu>

diff --git a/arch/x86/kernel/ds.c b/arch/x86/kernel/ds.c
index f0583005b75e..dc1e7123ea4e 100644
--- a/arch/x86/kernel/ds.c
+++ b/arch/x86/kernel/ds.c
@@ -232,7 +232,7 @@ static DEFINE_PER_CPU(struct ds_context *, system_context_array);
 
 #define system_context per_cpu(system_context_array, smp_processor_id())
 
-static inline struct ds_context *ds_get_context(struct task_struct *task)
+static struct ds_context *ds_get_context(struct task_struct *task)
 {
 	struct ds_context **p_context =
 		(task ? &task->thread.ds_ctx : &system_context);