diff options
Diffstat (limited to 'arch/x86/kernel')
| -rw-r--r-- | arch/x86/kernel/acpi/sleep.c | 5 | ||||
| -rw-r--r-- | arch/x86/kernel/apic/io_apic.c | 10 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/amd.c | 2 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/perf_event.c | 16 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/perf_event_intel.c | 116 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/perf_event_p4.c | 17 | ||||
| -rw-r--r-- | arch/x86/kernel/devicetree.c | 2 | ||||
| -rw-r--r-- | arch/x86/kernel/ptrace.c | 36 | ||||
| -rw-r--r-- | arch/x86/kernel/reboot_32.S | 12 | ||||
| -rw-r--r-- | arch/x86/kernel/x86_init.c | 4 | 
10 files changed, 147 insertions, 73 deletions
diff --git a/arch/x86/kernel/acpi/sleep.c b/arch/x86/kernel/acpi/sleep.c index ff93bc1b09c..18a857ba7a2 100644 --- a/arch/x86/kernel/acpi/sleep.c +++ b/arch/x86/kernel/acpi/sleep.c @@ -112,11 +112,6 @@ static int __init acpi_sleep_setup(char *str)  #ifdef CONFIG_HIBERNATION  		if (strncmp(str, "s4_nohwsig", 10) == 0)  			acpi_no_s4_hw_signature(); -		if (strncmp(str, "s4_nonvs", 8) == 0) { -			pr_warning("ACPI: acpi_sleep=s4_nonvs is deprecated, " -					"please use acpi_sleep=nonvs instead"); -			acpi_nvs_nosave(); -		}  #endif  		if (strncmp(str, "nonvs", 5) == 0)  			acpi_nvs_nosave(); diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 68df09bba92..45fd33d1fd3 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -128,8 +128,8 @@ static int __init parse_noapic(char *str)  }  early_param("noapic", parse_noapic); -static int io_apic_setup_irq_pin_once(unsigned int irq, int node, -				      struct io_apic_irq_attr *attr); +static int io_apic_setup_irq_pin(unsigned int irq, int node, +				 struct io_apic_irq_attr *attr);  /* Will be called in mpparse/acpi/sfi codes for saving IRQ info */  void mp_save_irq(struct mpc_intsrc *m) @@ -3570,7 +3570,7 @@ int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev)  }  #endif /* CONFIG_HT_IRQ */ -int +static int  io_apic_setup_irq_pin(unsigned int irq, int node, struct io_apic_irq_attr *attr)  {  	struct irq_cfg *cfg = alloc_irq_and_cfg_at(irq, node); @@ -3585,8 +3585,8 @@ io_apic_setup_irq_pin(unsigned int irq, int node, struct io_apic_irq_attr *attr)  	return ret;  } -static int io_apic_setup_irq_pin_once(unsigned int irq, int node, -				      struct io_apic_irq_attr *attr) +int io_apic_setup_irq_pin_once(unsigned int irq, int node, +			       struct io_apic_irq_attr *attr)  {  	unsigned int id = attr->ioapic, pin = attr->ioapic_pin;  	int ret; diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index 3532d3bf810..bb9eb29a52d 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -698,7 +698,7 @@ cpu_dev_register(amd_cpu_dev);   */  const int amd_erratum_400[] = -	AMD_OSVW_ERRATUM(1, AMD_MODEL_RANGE(0xf, 0x41, 0x2, 0xff, 0xf), +	AMD_OSVW_ERRATUM(1, AMD_MODEL_RANGE(0x0f, 0x4, 0x2, 0xff, 0xf),  			    AMD_MODEL_RANGE(0x10, 0x2, 0x1, 0xff, 0xf));  EXPORT_SYMBOL_GPL(amd_erratum_400); diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 632e5dc9c9c..e638689279d 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -613,8 +613,8 @@ static int x86_setup_perfctr(struct perf_event *event)  	/*  	 * Branch tracing:  	 */ -	if ((attr->config == PERF_COUNT_HW_BRANCH_INSTRUCTIONS) && -	    (hwc->sample_period == 1)) { +	if (attr->config == PERF_COUNT_HW_BRANCH_INSTRUCTIONS && +	    !attr->freq && hwc->sample_period == 1) {  		/* BTS is not supported by this architecture. */  		if (!x86_pmu.bts_active)  			return -EOPNOTSUPP; @@ -1288,6 +1288,16 @@ static int x86_pmu_handle_irq(struct pt_regs *regs)  	cpuc = &__get_cpu_var(cpu_hw_events); +	/* +	 * Some chipsets need to unmask the LVTPC in a particular spot +	 * inside the nmi handler.  As a result, the unmasking was pushed +	 * into all the nmi handlers. +	 * +	 * This generic handler doesn't seem to have any issues where the +	 * unmasking occurs so it was left at the top. +	 */ +	apic_write(APIC_LVTPC, APIC_DM_NMI); +  	for (idx = 0; idx < x86_pmu.num_counters; idx++) {  		if (!test_bit(idx, cpuc->active_mask)) {  			/* @@ -1374,8 +1384,6 @@ perf_event_nmi_handler(struct notifier_block *self,  		return NOTIFY_DONE;  	} -	apic_write(APIC_LVTPC, APIC_DM_NMI); -  	handled = x86_pmu.handle_irq(args->regs);  	if (!handled)  		return NOTIFY_DONE; diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c index 43fa20b1381..447a28de6f0 100644 --- a/arch/x86/kernel/cpu/perf_event_intel.c +++ b/arch/x86/kernel/cpu/perf_event_intel.c @@ -25,7 +25,7 @@ struct intel_percore {  /*   * Intel PerfMon, used on Core and later.   */ -static const u64 intel_perfmon_event_map[] = +static u64 intel_perfmon_event_map[PERF_COUNT_HW_MAX] __read_mostly =  {    [PERF_COUNT_HW_CPU_CYCLES]		= 0x003c,    [PERF_COUNT_HW_INSTRUCTIONS]		= 0x00c0, @@ -184,26 +184,23 @@ static __initconst const u64 snb_hw_cache_event_ids  	},   },   [ C(LL  ) ] = { -	/* -	 * TBD: Need Off-core Response Performance Monitoring support -	 */  	[ C(OP_READ) ] = { -		/* OFFCORE_RESPONSE_0.ANY_DATA.LOCAL_CACHE */ +		/* OFFCORE_RESPONSE.ANY_DATA.LOCAL_CACHE */  		[ C(RESULT_ACCESS) ] = 0x01b7, -		/* OFFCORE_RESPONSE_1.ANY_DATA.ANY_LLC_MISS */ -		[ C(RESULT_MISS)   ] = 0x01bb, +		/* OFFCORE_RESPONSE.ANY_DATA.ANY_LLC_MISS */ +		[ C(RESULT_MISS)   ] = 0x01b7,  	},  	[ C(OP_WRITE) ] = { -		/* OFFCORE_RESPONSE_0.ANY_RFO.LOCAL_CACHE */ +		/* OFFCORE_RESPONSE.ANY_RFO.LOCAL_CACHE */  		[ C(RESULT_ACCESS) ] = 0x01b7, -		/* OFFCORE_RESPONSE_1.ANY_RFO.ANY_LLC_MISS */ -		[ C(RESULT_MISS)   ] = 0x01bb, +		/* OFFCORE_RESPONSE.ANY_RFO.ANY_LLC_MISS */ +		[ C(RESULT_MISS)   ] = 0x01b7,  	},  	[ C(OP_PREFETCH) ] = { -		/* OFFCORE_RESPONSE_0.PREFETCH.LOCAL_CACHE */ +		/* OFFCORE_RESPONSE.PREFETCH.LOCAL_CACHE */  		[ C(RESULT_ACCESS) ] = 0x01b7, -		/* OFFCORE_RESPONSE_1.PREFETCH.ANY_LLC_MISS */ -		[ C(RESULT_MISS)   ] = 0x01bb, +		/* OFFCORE_RESPONSE.PREFETCH.ANY_LLC_MISS */ +		[ C(RESULT_MISS)   ] = 0x01b7,  	},   },   [ C(DTLB) ] = { @@ -285,26 +282,26 @@ static __initconst const u64 westmere_hw_cache_event_ids   },   [ C(LL  ) ] = {  	[ C(OP_READ) ] = { -		/* OFFCORE_RESPONSE_0.ANY_DATA.LOCAL_CACHE */ +		/* OFFCORE_RESPONSE.ANY_DATA.LOCAL_CACHE */  		[ C(RESULT_ACCESS) ] = 0x01b7, -		/* OFFCORE_RESPONSE_1.ANY_DATA.ANY_LLC_MISS */ -		[ C(RESULT_MISS)   ] = 0x01bb, +		/* OFFCORE_RESPONSE.ANY_DATA.ANY_LLC_MISS */ +		[ C(RESULT_MISS)   ] = 0x01b7,  	},  	/*  	 * Use RFO, not WRITEBACK, because a write miss would typically occur  	 * on RFO.  	 */  	[ C(OP_WRITE) ] = { -		/* OFFCORE_RESPONSE_1.ANY_RFO.LOCAL_CACHE */ -		[ C(RESULT_ACCESS) ] = 0x01bb, -		/* OFFCORE_RESPONSE_0.ANY_RFO.ANY_LLC_MISS */ +		/* OFFCORE_RESPONSE.ANY_RFO.LOCAL_CACHE */ +		[ C(RESULT_ACCESS) ] = 0x01b7, +		/* OFFCORE_RESPONSE.ANY_RFO.ANY_LLC_MISS */  		[ C(RESULT_MISS)   ] = 0x01b7,  	},  	[ C(OP_PREFETCH) ] = { -		/* OFFCORE_RESPONSE_0.PREFETCH.LOCAL_CACHE */ +		/* OFFCORE_RESPONSE.PREFETCH.LOCAL_CACHE */  		[ C(RESULT_ACCESS) ] = 0x01b7, -		/* OFFCORE_RESPONSE_1.PREFETCH.ANY_LLC_MISS */ -		[ C(RESULT_MISS)   ] = 0x01bb, +		/* OFFCORE_RESPONSE.PREFETCH.ANY_LLC_MISS */ +		[ C(RESULT_MISS)   ] = 0x01b7,  	},   },   [ C(DTLB) ] = { @@ -352,16 +349,36 @@ static __initconst const u64 westmere_hw_cache_event_ids  };  /* - * OFFCORE_RESPONSE MSR bits (subset), See IA32 SDM Vol 3 30.6.1.3 + * Nehalem/Westmere MSR_OFFCORE_RESPONSE bits; + * See IA32 SDM Vol 3B 30.6.1.3   */ -#define DMND_DATA_RD     (1 << 0) -#define DMND_RFO         (1 << 1) -#define DMND_WB          (1 << 3) -#define PF_DATA_RD       (1 << 4) -#define PF_DATA_RFO      (1 << 5) -#define RESP_UNCORE_HIT  (1 << 8) -#define RESP_MISS        (0xf600) /* non uncore hit */ +#define NHM_DMND_DATA_RD	(1 << 0) +#define NHM_DMND_RFO		(1 << 1) +#define NHM_DMND_IFETCH		(1 << 2) +#define NHM_DMND_WB		(1 << 3) +#define NHM_PF_DATA_RD		(1 << 4) +#define NHM_PF_DATA_RFO		(1 << 5) +#define NHM_PF_IFETCH		(1 << 6) +#define NHM_OFFCORE_OTHER	(1 << 7) +#define NHM_UNCORE_HIT		(1 << 8) +#define NHM_OTHER_CORE_HIT_SNP	(1 << 9) +#define NHM_OTHER_CORE_HITM	(1 << 10) +        			/* reserved */ +#define NHM_REMOTE_CACHE_FWD	(1 << 12) +#define NHM_REMOTE_DRAM		(1 << 13) +#define NHM_LOCAL_DRAM		(1 << 14) +#define NHM_NON_DRAM		(1 << 15) + +#define NHM_ALL_DRAM		(NHM_REMOTE_DRAM|NHM_LOCAL_DRAM) + +#define NHM_DMND_READ		(NHM_DMND_DATA_RD) +#define NHM_DMND_WRITE		(NHM_DMND_RFO|NHM_DMND_WB) +#define NHM_DMND_PREFETCH	(NHM_PF_DATA_RD|NHM_PF_DATA_RFO) + +#define NHM_L3_HIT	(NHM_UNCORE_HIT|NHM_OTHER_CORE_HIT_SNP|NHM_OTHER_CORE_HITM) +#define NHM_L3_MISS	(NHM_NON_DRAM|NHM_ALL_DRAM|NHM_REMOTE_CACHE_FWD) +#define NHM_L3_ACCESS	(NHM_L3_HIT|NHM_L3_MISS)  static __initconst const u64 nehalem_hw_cache_extra_regs  				[PERF_COUNT_HW_CACHE_MAX] @@ -370,16 +387,16 @@ static __initconst const u64 nehalem_hw_cache_extra_regs  {   [ C(LL  ) ] = {  	[ C(OP_READ) ] = { -		[ C(RESULT_ACCESS) ] = DMND_DATA_RD|RESP_UNCORE_HIT, -		[ C(RESULT_MISS)   ] = DMND_DATA_RD|RESP_MISS, +		[ C(RESULT_ACCESS) ] = NHM_DMND_READ|NHM_L3_ACCESS, +		[ C(RESULT_MISS)   ] = NHM_DMND_READ|NHM_L3_MISS,  	},  	[ C(OP_WRITE) ] = { -		[ C(RESULT_ACCESS) ] = DMND_RFO|DMND_WB|RESP_UNCORE_HIT, -		[ C(RESULT_MISS)   ] = DMND_RFO|DMND_WB|RESP_MISS, +		[ C(RESULT_ACCESS) ] = NHM_DMND_WRITE|NHM_L3_ACCESS, +		[ C(RESULT_MISS)   ] = NHM_DMND_WRITE|NHM_L3_MISS,  	},  	[ C(OP_PREFETCH) ] = { -		[ C(RESULT_ACCESS) ] = PF_DATA_RD|PF_DATA_RFO|RESP_UNCORE_HIT, -		[ C(RESULT_MISS)   ] = PF_DATA_RD|PF_DATA_RFO|RESP_MISS, +		[ C(RESULT_ACCESS) ] = NHM_DMND_PREFETCH|NHM_L3_ACCESS, +		[ C(RESULT_MISS)   ] = NHM_DMND_PREFETCH|NHM_L3_MISS,  	},   }  }; @@ -933,6 +950,16 @@ static int intel_pmu_handle_irq(struct pt_regs *regs)  	cpuc = &__get_cpu_var(cpu_hw_events); +	/* +	 * Some chipsets need to unmask the LVTPC in a particular spot +	 * inside the nmi handler.  As a result, the unmasking was pushed +	 * into all the nmi handlers. +	 * +	 * This handler doesn't seem to have any issues with the unmasking +	 * so it was left at the top. +	 */ +	apic_write(APIC_LVTPC, APIC_DM_NMI); +  	intel_pmu_disable_all();  	handled = intel_pmu_drain_bts_buffer();  	status = intel_pmu_get_status(); @@ -998,6 +1025,9 @@ intel_bts_constraints(struct perf_event *event)  	struct hw_perf_event *hwc = &event->hw;  	unsigned int hw_event, bts_event; +	if (event->attr.freq) +		return NULL; +  	hw_event = hwc->config & INTEL_ARCH_EVENT_MASK;  	bts_event = x86_pmu.event_map(PERF_COUNT_HW_BRANCH_INSTRUCTIONS); @@ -1305,7 +1335,7 @@ static void intel_clovertown_quirks(void)  	 * AJ106 could possibly be worked around by not allowing LBR  	 *       usage from PEBS, including the fixup.  	 * AJ68  could possibly be worked around by always programming -	 * 	 a pebs_event_reset[0] value and coping with the lost events. +	 *	 a pebs_event_reset[0] value and coping with the lost events.  	 *  	 * But taken together it might just make sense to not enable PEBS on  	 * these chips. @@ -1409,6 +1439,18 @@ static __init int intel_pmu_init(void)  		x86_pmu.percore_constraints = intel_nehalem_percore_constraints;  		x86_pmu.enable_all = intel_pmu_nhm_enable_all;  		x86_pmu.extra_regs = intel_nehalem_extra_regs; + +		if (ebx & 0x40) { +			/* +			 * Erratum AAJ80 detected, we work it around by using +			 * the BR_MISP_EXEC.ANY event. This will over-count +			 * branch-misses, but it's still much better than the +			 * architectural event which is often completely bogus: +			 */ +			intel_perfmon_event_map[PERF_COUNT_HW_BRANCH_MISSES] = 0x7f89; + +			pr_cont("erratum AAJ80 worked around, "); +		}  		pr_cont("Nehalem events, ");  		break; diff --git a/arch/x86/kernel/cpu/perf_event_p4.c b/arch/x86/kernel/cpu/perf_event_p4.c index d1f77e2934a..e93fcd55fae 100644 --- a/arch/x86/kernel/cpu/perf_event_p4.c +++ b/arch/x86/kernel/cpu/perf_event_p4.c @@ -950,11 +950,20 @@ static int p4_pmu_handle_irq(struct pt_regs *regs)  			x86_pmu_stop(event, 0);  	} -	if (handled) { -		/* p4 quirk: unmask it again */ -		apic_write(APIC_LVTPC, apic_read(APIC_LVTPC) & ~APIC_LVT_MASKED); +	if (handled)  		inc_irq_stat(apic_perf_irqs); -	} + +	/* +	 * When dealing with the unmasking of the LVTPC on P4 perf hw, it has +	 * been observed that the OVF bit flag has to be cleared first _before_ +	 * the LVTPC can be unmasked. +	 * +	 * The reason is the NMI line will continue to be asserted while the OVF +	 * bit is set.  This causes a second NMI to generate if the LVTPC is +	 * unmasked before the OVF bit is cleared, leading to unknown NMI +	 * messages. +	 */ +	apic_write(APIC_LVTPC, APIC_DM_NMI);  	return handled;  } diff --git a/arch/x86/kernel/devicetree.c b/arch/x86/kernel/devicetree.c index 706a9fb46a5..e90f08458e6 100644 --- a/arch/x86/kernel/devicetree.c +++ b/arch/x86/kernel/devicetree.c @@ -391,7 +391,7 @@ static int ioapic_xlate(struct irq_domain *id, const u32 *intspec, u32 intsize,  	set_io_apic_irq_attr(&attr, idx, line, it->trigger, it->polarity); -	return io_apic_setup_irq_pin(*out_hwirq, cpu_to_node(0), &attr); +	return io_apic_setup_irq_pin_once(*out_hwirq, cpu_to_node(0), &attr);  }  static void __init ioapic_add_ofnode(struct device_node *np) diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c index 45892dc4b72..f65e5b521db 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c @@ -608,6 +608,9 @@ static int ptrace_write_dr7(struct task_struct *tsk, unsigned long data)  	unsigned len, type;  	struct perf_event *bp; +	if (ptrace_get_breakpoints(tsk) < 0) +		return -ESRCH; +  	data &= ~DR_CONTROL_RESERVED;  	old_dr7 = ptrace_get_dr7(thread->ptrace_bps);  restore: @@ -655,6 +658,9 @@ restore:  		}  		goto restore;  	} + +	ptrace_put_breakpoints(tsk); +  	return ((orig_ret < 0) ? orig_ret : rc);  } @@ -668,10 +674,17 @@ static unsigned long ptrace_get_debugreg(struct task_struct *tsk, int n)  	if (n < HBP_NUM) {  		struct perf_event *bp; + +		if (ptrace_get_breakpoints(tsk) < 0) +			return -ESRCH; +  		bp = thread->ptrace_bps[n];  		if (!bp) -			return 0; -		val = bp->hw.info.address; +			val = 0; +		else +			val = bp->hw.info.address; + +		ptrace_put_breakpoints(tsk);  	} else if (n == 6) {  		val = thread->debugreg6;  	 } else if (n == 7) { @@ -686,6 +699,10 @@ static int ptrace_set_breakpoint_addr(struct task_struct *tsk, int nr,  	struct perf_event *bp;  	struct thread_struct *t = &tsk->thread;  	struct perf_event_attr attr; +	int err = 0; + +	if (ptrace_get_breakpoints(tsk) < 0) +		return -ESRCH;  	if (!t->ptrace_bps[nr]) {  		ptrace_breakpoint_init(&attr); @@ -709,24 +726,23 @@ static int ptrace_set_breakpoint_addr(struct task_struct *tsk, int nr,  		 * writing for the user. And anyway this is the previous  		 * behaviour.  		 */ -		if (IS_ERR(bp)) -			return PTR_ERR(bp); +		if (IS_ERR(bp)) { +			err = PTR_ERR(bp); +			goto put; +		}  		t->ptrace_bps[nr] = bp;  	} else { -		int err; -  		bp = t->ptrace_bps[nr];  		attr = bp->attr;  		attr.bp_addr = addr;  		err = modify_user_hw_breakpoint(bp, &attr); -		if (err) -			return err;  	} - -	return 0; +put: +	ptrace_put_breakpoints(tsk); +	return err;  }  /* diff --git a/arch/x86/kernel/reboot_32.S b/arch/x86/kernel/reboot_32.S index 29092b38d81..1d5c46df0d7 100644 --- a/arch/x86/kernel/reboot_32.S +++ b/arch/x86/kernel/reboot_32.S @@ -21,26 +21,26 @@ r_base = .  	/* Get our own relocated address */  	call	1f  1:	popl	%ebx -	subl	$1b, %ebx +	subl	$(1b - r_base), %ebx  	/* Compute the equivalent real-mode segment */  	movl	%ebx, %ecx  	shrl	$4, %ecx  	/* Patch post-real-mode segment jump */ -	movw	dispatch_table(%ebx,%eax,2),%ax -	movw	%ax, 101f(%ebx) -	movw	%cx, 102f(%ebx) +	movw	(dispatch_table - r_base)(%ebx,%eax,2),%ax +	movw	%ax, (101f - r_base)(%ebx) +	movw	%cx, (102f - r_base)(%ebx)  	/* Set up the IDT for real mode. */ -	lidtl	machine_real_restart_idt(%ebx) +	lidtl	(machine_real_restart_idt - r_base)(%ebx)  	/*  	 * Set up a GDT from which we can load segment descriptors for real  	 * mode.  The GDT is not used in real mode; it is just needed here to  	 * prepare the descriptors.  	 */ -	lgdtl	machine_real_restart_gdt(%ebx) +	lgdtl	(machine_real_restart_gdt - r_base)(%ebx)  	/*  	 * Load the data segment registers with 16-bit compatible values diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c index c11514e9128..75ef4b18e9b 100644 --- a/arch/x86/kernel/x86_init.c +++ b/arch/x86/kernel/x86_init.c @@ -61,6 +61,10 @@ struct x86_init_ops x86_init __initdata = {  		.banner			= default_banner,  	}, +	.mapping = { +		.pagetable_reserve		= native_pagetable_reserve, +	}, +  	.paging = {  		.pagetable_setup_start	= native_pagetable_setup_start,  		.pagetable_setup_done	= native_pagetable_setup_done,  |