diff options
Diffstat (limited to 'arch/x86/kernel')
| -rw-r--r-- | arch/x86/kernel/acpi/sleep.c | 4 | ||||
| -rw-r--r-- | arch/x86/kernel/acpi/sleep.h | 2 | ||||
| -rw-r--r-- | arch/x86/kernel/acpi/wakeup_32.S | 4 | ||||
| -rw-r--r-- | arch/x86/kernel/acpi/wakeup_64.S | 4 | ||||
| -rw-r--r-- | arch/x86/kernel/alternative.c | 4 | ||||
| -rw-r--r-- | arch/x86/kernel/apic/io_apic.c | 14 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/common.c | 2 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/mcheck/mce-severity.c | 7 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/mcheck/mce.c | 43 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/perf_event.c | 89 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/perf_event.h | 20 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/perf_event_amd_ibs.c | 4 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/perf_event_intel.c | 10 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/perf_event_intel_ds.c | 7 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/perf_event_intel_uncore.c | 253 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/perf_event_intel_uncore.h | 48 | ||||
| -rw-r--r-- | arch/x86/kernel/irq.c | 3 | ||||
| -rw-r--r-- | arch/x86/kernel/kdebugfs.c | 6 | ||||
| -rw-r--r-- | arch/x86/kernel/microcode_amd.c | 7 | 
19 files changed, 344 insertions, 187 deletions
diff --git a/arch/x86/kernel/acpi/sleep.c b/arch/x86/kernel/acpi/sleep.c index 95bf99de905..1b8e5a03d94 100644 --- a/arch/x86/kernel/acpi/sleep.c +++ b/arch/x86/kernel/acpi/sleep.c @@ -25,10 +25,6 @@ unsigned long acpi_realmode_flags;  static char temp_stack[4096];  #endif -asmlinkage void acpi_enter_s3(void) -{ -	acpi_enter_sleep_state(3, wake_sleep_flags); -}  /**   * acpi_suspend_lowlevel - save kernel state   * diff --git a/arch/x86/kernel/acpi/sleep.h b/arch/x86/kernel/acpi/sleep.h index 5653a5791ec..67f59f8c695 100644 --- a/arch/x86/kernel/acpi/sleep.h +++ b/arch/x86/kernel/acpi/sleep.h @@ -2,7 +2,6 @@   *	Variables and functions used by the code in sleep.c   */ -#include <linux/linkage.h>  #include <asm/realmode.h>  extern unsigned long saved_video_mode; @@ -11,7 +10,6 @@ extern long saved_magic;  extern int wakeup_pmode_return;  extern u8 wake_sleep_flags; -extern asmlinkage void acpi_enter_s3(void);  extern unsigned long acpi_copy_wakeup_routine(unsigned long);  extern void wakeup_long64(void); diff --git a/arch/x86/kernel/acpi/wakeup_32.S b/arch/x86/kernel/acpi/wakeup_32.S index 72610839f03..13ab720573e 100644 --- a/arch/x86/kernel/acpi/wakeup_32.S +++ b/arch/x86/kernel/acpi/wakeup_32.S @@ -74,7 +74,9 @@ restore_registers:  ENTRY(do_suspend_lowlevel)  	call	save_processor_state  	call	save_registers -	call	acpi_enter_s3 +	pushl	$3 +	call	acpi_enter_sleep_state +	addl	$4, %esp  #	In case of S3 failure, we'll emerge here.  Jump  # 	to ret_point to recover diff --git a/arch/x86/kernel/acpi/wakeup_64.S b/arch/x86/kernel/acpi/wakeup_64.S index 014d1d28c39..8ea5164cbd0 100644 --- a/arch/x86/kernel/acpi/wakeup_64.S +++ b/arch/x86/kernel/acpi/wakeup_64.S @@ -71,7 +71,9 @@ ENTRY(do_suspend_lowlevel)  	movq	%rsi, saved_rsi  	addq	$8, %rsp -	call	acpi_enter_s3 +	movl	$3, %edi +	xorl	%eax, %eax +	call	acpi_enter_sleep_state  	/* in case something went wrong, restore the machine status and go on */  	jmp	resume_point diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c index 931280ff829..ced4534baed 100644 --- a/arch/x86/kernel/alternative.c +++ b/arch/x86/kernel/alternative.c @@ -165,7 +165,7 @@ static const unsigned char * const k7_nops[ASM_NOP_MAX+2] =  #endif  #ifdef P6_NOP1 -static const unsigned char  __initconst_or_module p6nops[] = +static const unsigned char p6nops[] =  {  	P6_NOP1,  	P6_NOP2, @@ -224,7 +224,7 @@ void __init arch_init_ideal_nops(void)  			ideal_nops = intel_nops;  #endif  		} - +		break;  	default:  #ifdef CONFIG_X86_64  		ideal_nops = k8_nops; diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 406eee78468..c265593ec2c 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -1204,7 +1204,7 @@ static void __clear_irq_vector(int irq, struct irq_cfg *cfg)  	BUG_ON(!cfg->vector);  	vector = cfg->vector; -	for_each_cpu(cpu, cfg->domain) +	for_each_cpu_and(cpu, cfg->domain, cpu_online_mask)  		per_cpu(vector_irq, cpu)[vector] = -1;  	cfg->vector = 0; @@ -1212,7 +1212,7 @@ static void __clear_irq_vector(int irq, struct irq_cfg *cfg)  	if (likely(!cfg->move_in_progress))  		return; -	for_each_cpu(cpu, cfg->old_domain) { +	for_each_cpu_and(cpu, cfg->old_domain, cpu_online_mask) {  		for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS;  								vector++) {  			if (per_cpu(vector_irq, cpu)[vector] != irq) @@ -1356,6 +1356,16 @@ static void setup_ioapic_irq(unsigned int irq, struct irq_cfg *cfg,  	if (!IO_APIC_IRQ(irq))  		return; +	/* +	 * For legacy irqs, cfg->domain starts with cpu 0. Now that IO-APIC +	 * can handle this irq and the apic driver is finialized at this point, +	 * update the cfg->domain. +	 */ +	if (irq < legacy_pic->nr_legacy_irqs && +	    cpumask_equal(cfg->domain, cpumask_of(0))) +		apic->vector_allocation_domain(0, cfg->domain, +					       apic->target_cpus()); +  	if (assign_irq_vector(irq, cfg, apic->target_cpus()))  		return; diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 46d8786d655..a5fbc3c5fcc 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -144,6 +144,8 @@ static int __init x86_xsave_setup(char *s)  {  	setup_clear_cpu_cap(X86_FEATURE_XSAVE);  	setup_clear_cpu_cap(X86_FEATURE_XSAVEOPT); +	setup_clear_cpu_cap(X86_FEATURE_AVX); +	setup_clear_cpu_cap(X86_FEATURE_AVX2);  	return 1;  }  __setup("noxsave", x86_xsave_setup); diff --git a/arch/x86/kernel/cpu/mcheck/mce-severity.c b/arch/x86/kernel/cpu/mcheck/mce-severity.c index 413c2ced887..13017626f9a 100644 --- a/arch/x86/kernel/cpu/mcheck/mce-severity.c +++ b/arch/x86/kernel/cpu/mcheck/mce-severity.c @@ -55,13 +55,6 @@ static struct severity {  #define MCI_UC_S (MCI_STATUS_UC|MCI_STATUS_S)  #define MCI_UC_SAR (MCI_STATUS_UC|MCI_STATUS_S|MCI_STATUS_AR)  #define	MCI_ADDR (MCI_STATUS_ADDRV|MCI_STATUS_MISCV) -#define MCACOD 0xffff -/* Architecturally defined codes from SDM Vol. 3B Chapter 15 */ -#define MCACOD_SCRUB	0x00C0	/* 0xC0-0xCF Memory Scrubbing */ -#define MCACOD_SCRUBMSK	0xfff0 -#define MCACOD_L3WB	0x017A	/* L3 Explicit Writeback */ -#define MCACOD_DATA	0x0134	/* Data Load */ -#define MCACOD_INSTR	0x0150	/* Instruction Fetch */  	MCESEV(  		NO, "Invalid", diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index 5e095f873e3..292d0258311 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c @@ -103,6 +103,8 @@ DEFINE_PER_CPU(mce_banks_t, mce_poll_banks) = {  static DEFINE_PER_CPU(struct work_struct, mce_work); +static void (*quirk_no_way_out)(int bank, struct mce *m, struct pt_regs *regs); +  /*   * CPU/chipset specific EDAC code can register a notifier call here to print   * MCE errors in a human-readable form. @@ -650,14 +652,18 @@ EXPORT_SYMBOL_GPL(machine_check_poll);   * Do a quick check if any of the events requires a panic.   * This decides if we keep the events around or clear them.   */ -static int mce_no_way_out(struct mce *m, char **msg, unsigned long *validp) +static int mce_no_way_out(struct mce *m, char **msg, unsigned long *validp, +			  struct pt_regs *regs)  {  	int i, ret = 0;  	for (i = 0; i < banks; i++) {  		m->status = mce_rdmsrl(MSR_IA32_MCx_STATUS(i)); -		if (m->status & MCI_STATUS_VAL) +		if (m->status & MCI_STATUS_VAL) {  			__set_bit(i, validp); +			if (quirk_no_way_out) +				quirk_no_way_out(i, m, regs); +		}  		if (mce_severity(m, tolerant, msg) >= MCE_PANIC_SEVERITY)  			ret = 1;  	} @@ -1040,7 +1046,7 @@ void do_machine_check(struct pt_regs *regs, long error_code)  	*final = m;  	memset(valid_banks, 0, sizeof(valid_banks)); -	no_way_out = mce_no_way_out(&m, &msg, valid_banks); +	no_way_out = mce_no_way_out(&m, &msg, valid_banks, regs);  	barrier(); @@ -1418,6 +1424,34 @@ static void __mcheck_cpu_init_generic(void)  	}  } +/* + * During IFU recovery Sandy Bridge -EP4S processors set the RIPV and + * EIPV bits in MCG_STATUS to zero on the affected logical processor (SDM + * Vol 3B Table 15-20). But this confuses both the code that determines + * whether the machine check occurred in kernel or user mode, and also + * the severity assessment code. Pretend that EIPV was set, and take the + * ip/cs values from the pt_regs that mce_gather_info() ignored earlier. + */ +static void quirk_sandybridge_ifu(int bank, struct mce *m, struct pt_regs *regs) +{ +	if (bank != 0) +		return; +	if ((m->mcgstatus & (MCG_STATUS_EIPV|MCG_STATUS_RIPV)) != 0) +		return; +	if ((m->status & (MCI_STATUS_OVER|MCI_STATUS_UC| +		          MCI_STATUS_EN|MCI_STATUS_MISCV|MCI_STATUS_ADDRV| +			  MCI_STATUS_PCC|MCI_STATUS_S|MCI_STATUS_AR| +			  MCACOD)) != +			 (MCI_STATUS_UC|MCI_STATUS_EN| +			  MCI_STATUS_MISCV|MCI_STATUS_ADDRV|MCI_STATUS_S| +			  MCI_STATUS_AR|MCACOD_INSTR)) +		return; + +	m->mcgstatus |= MCG_STATUS_EIPV; +	m->ip = regs->ip; +	m->cs = regs->cs; +} +  /* Add per CPU specific workarounds here */  static int __cpuinit __mcheck_cpu_apply_quirks(struct cpuinfo_x86 *c)  { @@ -1515,6 +1549,9 @@ static int __cpuinit __mcheck_cpu_apply_quirks(struct cpuinfo_x86 *c)  		 */  		if (c->x86 == 6 && c->x86_model <= 13 && mce_bootlog < 0)  			mce_bootlog = 0; + +		if (c->x86 == 6 && c->x86_model == 45) +			quirk_no_way_out = quirk_sandybridge_ifu;  	}  	if (monarch_timeout < 0)  		monarch_timeout = 0; diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 29557aa06dd..915b876edd1 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -32,6 +32,8 @@  #include <asm/smp.h>  #include <asm/alternative.h>  #include <asm/timer.h> +#include <asm/desc.h> +#include <asm/ldt.h>  #include "perf_event.h" @@ -1738,6 +1740,29 @@ valid_user_frame(const void __user *fp, unsigned long size)  	return (__range_not_ok(fp, size, TASK_SIZE) == 0);  } +static unsigned long get_segment_base(unsigned int segment) +{ +	struct desc_struct *desc; +	int idx = segment >> 3; + +	if ((segment & SEGMENT_TI_MASK) == SEGMENT_LDT) { +		if (idx > LDT_ENTRIES) +			return 0; + +		if (idx > current->active_mm->context.size) +			return 0; + +		desc = current->active_mm->context.ldt; +	} else { +		if (idx > GDT_ENTRIES) +			return 0; + +		desc = __this_cpu_ptr(&gdt_page.gdt[0]); +	} + +	return get_desc_base(desc + idx); +} +  #ifdef CONFIG_COMPAT  #include <asm/compat.h> @@ -1746,13 +1771,17 @@ static inline int  perf_callchain_user32(struct pt_regs *regs, struct perf_callchain_entry *entry)  {  	/* 32-bit process in 64-bit kernel. */ +	unsigned long ss_base, cs_base;  	struct stack_frame_ia32 frame;  	const void __user *fp;  	if (!test_thread_flag(TIF_IA32))  		return 0; -	fp = compat_ptr(regs->bp); +	cs_base = get_segment_base(regs->cs); +	ss_base = get_segment_base(regs->ss); + +	fp = compat_ptr(ss_base + regs->bp);  	while (entry->nr < PERF_MAX_STACK_DEPTH) {  		unsigned long bytes;  		frame.next_frame     = 0; @@ -1765,8 +1794,8 @@ perf_callchain_user32(struct pt_regs *regs, struct perf_callchain_entry *entry)  		if (!valid_user_frame(fp, sizeof(frame)))  			break; -		perf_callchain_store(entry, frame.return_address); -		fp = compat_ptr(frame.next_frame); +		perf_callchain_store(entry, cs_base + frame.return_address); +		fp = compat_ptr(ss_base + frame.next_frame);  	}  	return 1;  } @@ -1789,6 +1818,12 @@ perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs)  		return;  	} +	/* +	 * We don't know what to do with VM86 stacks.. ignore them for now. +	 */ +	if (regs->flags & (X86_VM_MASK | PERF_EFLAGS_VM)) +		return; +  	fp = (void __user *)regs->bp;  	perf_callchain_store(entry, regs->ip); @@ -1816,16 +1851,50 @@ perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs)  	}  } -unsigned long perf_instruction_pointer(struct pt_regs *regs) +/* + * Deal with code segment offsets for the various execution modes: + * + *   VM86 - the good olde 16 bit days, where the linear address is + *          20 bits and we use regs->ip + 0x10 * regs->cs. + * + *   IA32 - Where we need to look at GDT/LDT segment descriptor tables + *          to figure out what the 32bit base address is. + * + *    X32 - has TIF_X32 set, but is running in x86_64 + * + * X86_64 - CS,DS,SS,ES are all zero based. + */ +static unsigned long code_segment_base(struct pt_regs *regs)  { -	unsigned long ip; +	/* +	 * If we are in VM86 mode, add the segment offset to convert to a +	 * linear address. +	 */ +	if (regs->flags & X86_VM_MASK) +		return 0x10 * regs->cs; + +	/* +	 * For IA32 we look at the GDT/LDT segment base to convert the +	 * effective IP to a linear address. +	 */ +#ifdef CONFIG_X86_32 +	if (user_mode(regs) && regs->cs != __USER_CS) +		return get_segment_base(regs->cs); +#else +	if (test_thread_flag(TIF_IA32)) { +		if (user_mode(regs) && regs->cs != __USER32_CS) +			return get_segment_base(regs->cs); +	} +#endif +	return 0; +} +unsigned long perf_instruction_pointer(struct pt_regs *regs) +{  	if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) -		ip = perf_guest_cbs->get_guest_ip(); -	else -		ip = instruction_pointer(regs); +		return perf_guest_cbs->get_guest_ip(); -	return ip; +	return regs->ip + code_segment_base(regs);  }  unsigned long perf_misc_flags(struct pt_regs *regs) @@ -1838,7 +1907,7 @@ unsigned long perf_misc_flags(struct pt_regs *regs)  		else  			misc |= PERF_RECORD_MISC_GUEST_KERNEL;  	} else { -		if (!kernel_ip(regs->ip)) +		if (user_mode(regs))  			misc |= PERF_RECORD_MISC_USER;  		else  			misc |= PERF_RECORD_MISC_KERNEL; diff --git a/arch/x86/kernel/cpu/perf_event.h b/arch/x86/kernel/cpu/perf_event.h index 821d53b696d..6605a81ba33 100644 --- a/arch/x86/kernel/cpu/perf_event.h +++ b/arch/x86/kernel/cpu/perf_event.h @@ -516,6 +516,26 @@ static inline bool kernel_ip(unsigned long ip)  #endif  } +/* + * Not all PMUs provide the right context information to place the reported IP + * into full context. Specifically segment registers are typically not + * supplied. + * + * Assuming the address is a linear address (it is for IBS), we fake the CS and + * vm86 mode using the known zero-based code segment and 'fix up' the registers + * to reflect this. + * + * Intel PEBS/LBR appear to typically provide the effective address, nothing + * much we can do about that but pray and treat it like a linear address. + */ +static inline void set_linear_ip(struct pt_regs *regs, unsigned long ip) +{ +	regs->cs = kernel_ip(ip) ? __KERNEL_CS : __USER_CS; +	if (regs->flags & X86_VM_MASK) +		regs->flags ^= (PERF_EFLAGS_VM | X86_VM_MASK); +	regs->ip = ip; +} +  #ifdef CONFIG_CPU_SUP_AMD  int amd_pmu_init(void); diff --git a/arch/x86/kernel/cpu/perf_event_amd_ibs.c b/arch/x86/kernel/cpu/perf_event_amd_ibs.c index da9bcdcd985..7bfb5bec863 100644 --- a/arch/x86/kernel/cpu/perf_event_amd_ibs.c +++ b/arch/x86/kernel/cpu/perf_event_amd_ibs.c @@ -13,6 +13,8 @@  #include <asm/apic.h> +#include "perf_event.h" +  static u32 ibs_caps;  #if defined(CONFIG_PERF_EVENTS) && defined(CONFIG_CPU_SUP_AMD) @@ -536,7 +538,7 @@ static int perf_ibs_handle_irq(struct perf_ibs *perf_ibs, struct pt_regs *iregs)  	if (check_rip && (ibs_data.regs[2] & IBS_RIP_INVALID)) {  		regs.flags &= ~PERF_EFLAGS_EXACT;  	} else { -		instruction_pointer_set(®s, ibs_data.regs[1]); +		set_linear_ip(®s, ibs_data.regs[1]);  		regs.flags |= PERF_EFLAGS_EXACT;  	} diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c index 382366977d4..7f2739e03e7 100644 --- a/arch/x86/kernel/cpu/perf_event_intel.c +++ b/arch/x86/kernel/cpu/perf_event_intel.c @@ -1522,8 +1522,16 @@ static struct perf_guest_switch_msr *intel_guest_get_msrs(int *nr)  	arr[0].msr = MSR_CORE_PERF_GLOBAL_CTRL;  	arr[0].host = x86_pmu.intel_ctrl & ~cpuc->intel_ctrl_guest_mask;  	arr[0].guest = x86_pmu.intel_ctrl & ~cpuc->intel_ctrl_host_mask; +	/* +	 * If PMU counter has PEBS enabled it is not enough to disable counter +	 * on a guest entry since PEBS memory write can overshoot guest entry +	 * and corrupt guest memory. Disabling PEBS solves the problem. +	 */ +	arr[1].msr = MSR_IA32_PEBS_ENABLE; +	arr[1].host = cpuc->pebs_enabled; +	arr[1].guest = 0; -	*nr = 1; +	*nr = 2;  	return arr;  } diff --git a/arch/x86/kernel/cpu/perf_event_intel_ds.c b/arch/x86/kernel/cpu/perf_event_intel_ds.c index 629ae0b7ad9..e38d97bf425 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_ds.c +++ b/arch/x86/kernel/cpu/perf_event_intel_ds.c @@ -499,7 +499,7 @@ static int intel_pmu_pebs_fixup_ip(struct pt_regs *regs)  	 * We sampled a branch insn, rewind using the LBR stack  	 */  	if (ip == to) { -		regs->ip = from; +		set_linear_ip(regs, from);  		return 1;  	} @@ -529,7 +529,7 @@ static int intel_pmu_pebs_fixup_ip(struct pt_regs *regs)  	} while (to < ip);  	if (to == ip) { -		regs->ip = old_to; +		set_linear_ip(regs, old_to);  		return 1;  	} @@ -569,7 +569,8 @@ static void __intel_pmu_pebs_event(struct perf_event *event,  	 * A possible PERF_SAMPLE_REGS will have to transfer all regs.  	 */  	regs = *iregs; -	regs.ip = pebs->ip; +	regs.flags = pebs->flags; +	set_linear_ip(®s, pebs->ip);  	regs.bp = pebs->bp;  	regs.sp = pebs->sp; diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.c b/arch/x86/kernel/cpu/perf_event_intel_uncore.c index 7563fda9f03..0a5571080e7 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_uncore.c +++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.c @@ -796,7 +796,6 @@ static struct intel_uncore_type *nhm_msr_uncores[] = {  DEFINE_UNCORE_FORMAT_ATTR(event5, event, "config:1-5");  DEFINE_UNCORE_FORMAT_ATTR(counter, counter, "config:6-7"); -DEFINE_UNCORE_FORMAT_ATTR(mm_cfg, mm_cfg, "config:63");  DEFINE_UNCORE_FORMAT_ATTR(match, match, "config1:0-63");  DEFINE_UNCORE_FORMAT_ATTR(mask, mask, "config2:0-63"); @@ -902,16 +901,21 @@ static struct attribute_group nhmex_uncore_cbox_format_group = {  	.attrs = nhmex_uncore_cbox_formats_attr,  }; +/* msr offset for each instance of cbox */ +static unsigned nhmex_cbox_msr_offsets[] = { +	0x0, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x240, 0x2c0, +}; +  static struct intel_uncore_type nhmex_uncore_cbox = {  	.name			= "cbox",  	.num_counters		= 6, -	.num_boxes		= 8, +	.num_boxes		= 10,  	.perf_ctr_bits		= 48,  	.event_ctl		= NHMEX_C0_MSR_PMON_EV_SEL0,  	.perf_ctr		= NHMEX_C0_MSR_PMON_CTR0,  	.event_mask		= NHMEX_PMON_RAW_EVENT_MASK,  	.box_ctl		= NHMEX_C0_MSR_PMON_GLOBAL_CTL, -	.msr_offset		= NHMEX_C_MSR_OFFSET, +	.msr_offsets		= nhmex_cbox_msr_offsets,  	.pair_ctr_ctl		= 1,  	.ops			= &nhmex_uncore_ops,  	.format_group		= &nhmex_uncore_cbox_format_group @@ -1032,24 +1036,22 @@ static struct intel_uncore_type nhmex_uncore_bbox = {  static int nhmex_sbox_hw_config(struct intel_uncore_box *box, struct perf_event *event)  { -	struct hw_perf_event_extra *reg1 = &event->hw.extra_reg; -	struct hw_perf_event_extra *reg2 = &event->hw.branch_reg; +	struct hw_perf_event *hwc = &event->hw; +	struct hw_perf_event_extra *reg1 = &hwc->extra_reg; +	struct hw_perf_event_extra *reg2 = &hwc->branch_reg; -	if (event->attr.config & NHMEX_S_PMON_MM_CFG_EN) { -		reg1->config = event->attr.config1; -		reg2->config = event->attr.config2; -	} else { -		reg1->config = ~0ULL; -		reg2->config = ~0ULL; -	} +	/* only TO_R_PROG_EV event uses the match/mask register */ +	if ((hwc->config & NHMEX_PMON_CTL_EV_SEL_MASK) != +	    NHMEX_S_EVENT_TO_R_PROG_EV) +		return 0;  	if (box->pmu->pmu_idx == 0)  		reg1->reg = NHMEX_S0_MSR_MM_CFG;  	else  		reg1->reg = NHMEX_S1_MSR_MM_CFG; -  	reg1->idx = 0; - +	reg1->config = event->attr.config1; +	reg2->config = event->attr.config2;  	return 0;  } @@ -1059,8 +1061,8 @@ static void nhmex_sbox_msr_enable_event(struct intel_uncore_box *box, struct per  	struct hw_perf_event_extra *reg1 = &hwc->extra_reg;  	struct hw_perf_event_extra *reg2 = &hwc->branch_reg; -	wrmsrl(reg1->reg, 0); -	if (reg1->config != ~0ULL || reg2->config != ~0ULL) { +	if (reg1->idx != EXTRA_REG_NONE) { +		wrmsrl(reg1->reg, 0);  		wrmsrl(reg1->reg + 1, reg1->config);  		wrmsrl(reg1->reg + 2, reg2->config);  		wrmsrl(reg1->reg, NHMEX_S_PMON_MM_CFG_EN); @@ -1074,7 +1076,6 @@ static struct attribute *nhmex_uncore_sbox_formats_attr[] = {  	&format_attr_edge.attr,  	&format_attr_inv.attr,  	&format_attr_thresh8.attr, -	&format_attr_mm_cfg.attr,  	&format_attr_match.attr,  	&format_attr_mask.attr,  	NULL, @@ -1142,6 +1143,9 @@ static struct extra_reg nhmex_uncore_mbox_extra_regs[] = {  	EVENT_EXTRA_END  }; +/* Nehalem-EX or Westmere-EX ? */ +bool uncore_nhmex; +  static bool nhmex_mbox_get_shared_reg(struct intel_uncore_box *box, int idx, u64 config)  {  	struct intel_uncore_extra_reg *er; @@ -1171,18 +1175,29 @@ static bool nhmex_mbox_get_shared_reg(struct intel_uncore_box *box, int idx, u64  		return false;  	/* mask of the shared fields */ -	mask = NHMEX_M_PMON_ZDP_CTL_FVC_MASK; +	if (uncore_nhmex) +		mask = NHMEX_M_PMON_ZDP_CTL_FVC_MASK; +	else +		mask = WSMEX_M_PMON_ZDP_CTL_FVC_MASK;  	er = &box->shared_regs[EXTRA_REG_NHMEX_M_ZDP_CTL_FVC];  	raw_spin_lock_irqsave(&er->lock, flags);  	/* add mask of the non-shared field if it's in use */ -	if (__BITS_VALUE(atomic_read(&er->ref), idx, 8)) -		mask |= NHMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx); +	if (__BITS_VALUE(atomic_read(&er->ref), idx, 8)) { +		if (uncore_nhmex) +			mask |= NHMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx); +		else +			mask |= WSMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx); +	}  	if (!atomic_read(&er->ref) || !((er->config ^ config) & mask)) {  		atomic_add(1 << (idx * 8), &er->ref); -		mask = NHMEX_M_PMON_ZDP_CTL_FVC_MASK | -			NHMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx); +		if (uncore_nhmex) +			mask = NHMEX_M_PMON_ZDP_CTL_FVC_MASK | +				NHMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx); +		else +			mask = WSMEX_M_PMON_ZDP_CTL_FVC_MASK | +				WSMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx);  		er->config &= ~mask;  		er->config |= (config & mask);  		ret = true; @@ -1216,7 +1231,10 @@ u64 nhmex_mbox_alter_er(struct perf_event *event, int new_idx, bool modify)  	/* get the non-shared control bits and shift them */  	idx = orig_idx - EXTRA_REG_NHMEX_M_ZDP_CTL_FVC; -	config &= NHMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx); +	if (uncore_nhmex) +		config &= NHMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx); +	else +		config &= WSMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx);  	if (new_idx > orig_idx) {  		idx = new_idx - orig_idx;  		config <<= 3 * idx; @@ -1226,6 +1244,10 @@ u64 nhmex_mbox_alter_er(struct perf_event *event, int new_idx, bool modify)  	}  	/* add the shared control bits back */ +	if (uncore_nhmex) +		config |= NHMEX_M_PMON_ZDP_CTL_FVC_MASK & reg1->config; +	else +		config |= WSMEX_M_PMON_ZDP_CTL_FVC_MASK & reg1->config;  	config |= NHMEX_M_PMON_ZDP_CTL_FVC_MASK & reg1->config;  	if (modify) {  		/* adjust the main event selector */ @@ -1264,7 +1286,8 @@ again:  	}  	/* for the match/mask registers */ -	if ((uncore_box_is_fake(box) || !reg2->alloc) && +	if (reg2->idx != EXTRA_REG_NONE && +	    (uncore_box_is_fake(box) || !reg2->alloc) &&  	    !nhmex_mbox_get_shared_reg(box, reg2->idx, reg2->config))  		goto fail; @@ -1278,7 +1301,8 @@ again:  		if (idx[0] != 0xff && idx[0] != __BITS_VALUE(reg1->idx, 0, 8))  			nhmex_mbox_alter_er(event, idx[0], true);  		reg1->alloc |= alloc; -		reg2->alloc = 1; +		if (reg2->idx != EXTRA_REG_NONE) +			reg2->alloc = 1;  	}  	return NULL;  fail: @@ -1342,9 +1366,6 @@ static int nhmex_mbox_hw_config(struct intel_uncore_box *box, struct perf_event  	struct extra_reg *er;  	unsigned msr;  	int reg_idx = 0; - -	if (WARN_ON_ONCE(reg1->idx != -1)) -		return -EINVAL;  	/*  	 * The mbox events may require 2 extra MSRs at the most. But only  	 * the lower 32 bits in these MSRs are significant, so we can use @@ -1355,11 +1376,6 @@ static int nhmex_mbox_hw_config(struct intel_uncore_box *box, struct perf_event  			continue;  		if (event->attr.config1 & ~er->valid_mask)  			return -EINVAL; -		if (er->idx == __BITS_VALUE(reg1->idx, 0, 8) || -		    er->idx == __BITS_VALUE(reg1->idx, 1, 8)) -			continue; -		if (WARN_ON_ONCE(reg_idx >= 2)) -			return -EINVAL;  		msr = er->msr + type->msr_offset * box->pmu->pmu_idx;  		if (WARN_ON_ONCE(msr >= 0xffff || er->idx >= 0xff)) @@ -1368,6 +1384,8 @@ static int nhmex_mbox_hw_config(struct intel_uncore_box *box, struct perf_event  		/* always use the 32~63 bits to pass the PLD config */  		if (er->idx == EXTRA_REG_NHMEX_M_PLD)  			reg_idx = 1; +		else if (WARN_ON_ONCE(reg_idx > 0)) +			return -EINVAL;  		reg1->idx &= ~(0xff << (reg_idx * 8));  		reg1->reg &= ~(0xffff << (reg_idx * 16)); @@ -1376,17 +1394,21 @@ static int nhmex_mbox_hw_config(struct intel_uncore_box *box, struct perf_event  		reg1->config = event->attr.config1;  		reg_idx++;  	} -	/* use config2 to pass the filter config */ -	reg2->idx = EXTRA_REG_NHMEX_M_FILTER; -	if (event->attr.config2 & NHMEX_M_PMON_MM_CFG_EN) -		reg2->config = event->attr.config2; -	else -		reg2->config = ~0ULL; -	if (box->pmu->pmu_idx == 0) -		reg2->reg = NHMEX_M0_MSR_PMU_MM_CFG; -	else -		reg2->reg = NHMEX_M1_MSR_PMU_MM_CFG; - +	/* +	 * The mbox only provides ability to perform address matching +	 * for the PLD events. +	 */ +	if (reg_idx == 2) { +		reg2->idx = EXTRA_REG_NHMEX_M_FILTER; +		if (event->attr.config2 & NHMEX_M_PMON_MM_CFG_EN) +			reg2->config = event->attr.config2; +		else +			reg2->config = ~0ULL; +		if (box->pmu->pmu_idx == 0) +			reg2->reg = NHMEX_M0_MSR_PMU_MM_CFG; +		else +			reg2->reg = NHMEX_M1_MSR_PMU_MM_CFG; +	}  	return 0;  } @@ -1422,34 +1444,36 @@ static void nhmex_mbox_msr_enable_event(struct intel_uncore_box *box, struct per  		wrmsrl(__BITS_VALUE(reg1->reg, 1, 16),  			nhmex_mbox_shared_reg_config(box, idx)); -	wrmsrl(reg2->reg, 0); -	if (reg2->config != ~0ULL) { -		wrmsrl(reg2->reg + 1, -			reg2->config & NHMEX_M_PMON_ADDR_MATCH_MASK); -		wrmsrl(reg2->reg + 2, NHMEX_M_PMON_ADDR_MASK_MASK & -			(reg2->config >> NHMEX_M_PMON_ADDR_MASK_SHIFT)); -		wrmsrl(reg2->reg, NHMEX_M_PMON_MM_CFG_EN); +	if (reg2->idx != EXTRA_REG_NONE) { +		wrmsrl(reg2->reg, 0); +		if (reg2->config != ~0ULL) { +			wrmsrl(reg2->reg + 1, +				reg2->config & NHMEX_M_PMON_ADDR_MATCH_MASK); +			wrmsrl(reg2->reg + 2, NHMEX_M_PMON_ADDR_MASK_MASK & +				(reg2->config >> NHMEX_M_PMON_ADDR_MASK_SHIFT)); +			wrmsrl(reg2->reg, NHMEX_M_PMON_MM_CFG_EN); +		}  	}  	wrmsrl(hwc->config_base, hwc->config | NHMEX_PMON_CTL_EN_BIT0);  } -DEFINE_UNCORE_FORMAT_ATTR(count_mode,	count_mode,	"config:2-3"); -DEFINE_UNCORE_FORMAT_ATTR(storage_mode, storage_mode,	"config:4-5"); -DEFINE_UNCORE_FORMAT_ATTR(wrap_mode,	wrap_mode,	"config:6"); -DEFINE_UNCORE_FORMAT_ATTR(flag_mode,	flag_mode,	"config:7"); -DEFINE_UNCORE_FORMAT_ATTR(inc_sel,	inc_sel,	"config:9-13"); -DEFINE_UNCORE_FORMAT_ATTR(set_flag_sel,	set_flag_sel,	"config:19-21"); -DEFINE_UNCORE_FORMAT_ATTR(filter_cfg,	filter_cfg,	"config2:63"); -DEFINE_UNCORE_FORMAT_ATTR(filter_match,	filter_match,	"config2:0-33"); -DEFINE_UNCORE_FORMAT_ATTR(filter_mask,	filter_mask,	"config2:34-61"); -DEFINE_UNCORE_FORMAT_ATTR(dsp,		dsp,		"config1:0-31"); -DEFINE_UNCORE_FORMAT_ATTR(thr,		thr,		"config1:0-31"); -DEFINE_UNCORE_FORMAT_ATTR(fvc,		fvc,		"config1:0-31"); -DEFINE_UNCORE_FORMAT_ATTR(pgt,		pgt,		"config1:0-31"); -DEFINE_UNCORE_FORMAT_ATTR(map,		map,		"config1:0-31"); -DEFINE_UNCORE_FORMAT_ATTR(iss,		iss,		"config1:0-31"); -DEFINE_UNCORE_FORMAT_ATTR(pld,		pld,		"config1:32-63"); +DEFINE_UNCORE_FORMAT_ATTR(count_mode,		count_mode,	"config:2-3"); +DEFINE_UNCORE_FORMAT_ATTR(storage_mode,		storage_mode,	"config:4-5"); +DEFINE_UNCORE_FORMAT_ATTR(wrap_mode,		wrap_mode,	"config:6"); +DEFINE_UNCORE_FORMAT_ATTR(flag_mode,		flag_mode,	"config:7"); +DEFINE_UNCORE_FORMAT_ATTR(inc_sel,		inc_sel,	"config:9-13"); +DEFINE_UNCORE_FORMAT_ATTR(set_flag_sel,		set_flag_sel,	"config:19-21"); +DEFINE_UNCORE_FORMAT_ATTR(filter_cfg_en,	filter_cfg_en,	"config2:63"); +DEFINE_UNCORE_FORMAT_ATTR(filter_match,		filter_match,	"config2:0-33"); +DEFINE_UNCORE_FORMAT_ATTR(filter_mask,		filter_mask,	"config2:34-61"); +DEFINE_UNCORE_FORMAT_ATTR(dsp,			dsp,		"config1:0-31"); +DEFINE_UNCORE_FORMAT_ATTR(thr,			thr,		"config1:0-31"); +DEFINE_UNCORE_FORMAT_ATTR(fvc,			fvc,		"config1:0-31"); +DEFINE_UNCORE_FORMAT_ATTR(pgt,			pgt,		"config1:0-31"); +DEFINE_UNCORE_FORMAT_ATTR(map,			map,		"config1:0-31"); +DEFINE_UNCORE_FORMAT_ATTR(iss,			iss,		"config1:0-31"); +DEFINE_UNCORE_FORMAT_ATTR(pld,			pld,		"config1:32-63");  static struct attribute *nhmex_uncore_mbox_formats_attr[] = {  	&format_attr_count_mode.attr, @@ -1458,7 +1482,7 @@ static struct attribute *nhmex_uncore_mbox_formats_attr[] = {  	&format_attr_flag_mode.attr,  	&format_attr_inc_sel.attr,  	&format_attr_set_flag_sel.attr, -	&format_attr_filter_cfg.attr, +	&format_attr_filter_cfg_en.attr,  	&format_attr_filter_match.attr,  	&format_attr_filter_mask.attr,  	&format_attr_dsp.attr, @@ -1482,6 +1506,12 @@ static struct uncore_event_desc nhmex_uncore_mbox_events[] = {  	{ /* end: all zeroes */ },  }; +static struct uncore_event_desc wsmex_uncore_mbox_events[] = { +	INTEL_UNCORE_EVENT_DESC(bbox_cmds_read, "inc_sel=0xd,fvc=0x5000"), +	INTEL_UNCORE_EVENT_DESC(bbox_cmds_write, "inc_sel=0xd,fvc=0x5040"), +	{ /* end: all zeroes */ }, +}; +  static struct intel_uncore_ops nhmex_uncore_mbox_ops = {  	NHMEX_UNCORE_OPS_COMMON_INIT(),  	.enable_event	= nhmex_mbox_msr_enable_event, @@ -1513,7 +1543,7 @@ void nhmex_rbox_alter_er(struct intel_uncore_box *box, struct perf_event *event)  	struct hw_perf_event_extra *reg1 = &hwc->extra_reg;  	int port; -	/* adjust the main event selector */ +	/* adjust the main event selector and extra register index */  	if (reg1->idx % 2) {  		reg1->idx--;  		hwc->config -= 1 << NHMEX_R_PMON_CTL_EV_SEL_SHIFT; @@ -1522,29 +1552,17 @@ void nhmex_rbox_alter_er(struct intel_uncore_box *box, struct perf_event *event)  		hwc->config += 1 << NHMEX_R_PMON_CTL_EV_SEL_SHIFT;  	} -	/* adjust address or config of extra register */ +	/* adjust extra register config */  	port = reg1->idx / 6 + box->pmu->pmu_idx * 4;  	switch (reg1->idx % 6) { -	case 0: -		reg1->reg = NHMEX_R_MSR_PORTN_IPERF_CFG0(port); -		break; -	case 1: -		reg1->reg = NHMEX_R_MSR_PORTN_IPERF_CFG1(port); -		break;  	case 2: -		/* the 8~15 bits to the 0~7 bits */ +		/* shift the 8~15 bits to the 0~7 bits */  		reg1->config >>= 8;  		break;  	case 3: -		/* the 0~7 bits to the 8~15 bits */ +		/* shift the 0~7 bits to the 8~15 bits */  		reg1->config <<= 8;  		break; -	case 4: -		reg1->reg = NHMEX_R_MSR_PORTN_XBR_SET1_MM_CFG(port); -		break; -	case 5: -		reg1->reg = NHMEX_R_MSR_PORTN_XBR_SET2_MM_CFG(port); -		break;  	};  } @@ -1671,7 +1689,7 @@ static int nhmex_rbox_hw_config(struct intel_uncore_box *box, struct perf_event  	struct hw_perf_event *hwc = &event->hw;  	struct hw_perf_event_extra *reg1 = &event->hw.extra_reg;  	struct hw_perf_event_extra *reg2 = &event->hw.branch_reg; -	int port, idx; +	int idx;  	idx = (event->hw.config & NHMEX_R_PMON_CTL_EV_SEL_MASK) >>  		NHMEX_R_PMON_CTL_EV_SEL_SHIFT; @@ -1681,27 +1699,11 @@ static int nhmex_rbox_hw_config(struct intel_uncore_box *box, struct perf_event  	reg1->idx = idx;  	reg1->config = event->attr.config1; -	port = idx / 6 + box->pmu->pmu_idx * 4; -	idx %= 6; -	switch (idx) { -	case 0: -		reg1->reg = NHMEX_R_MSR_PORTN_IPERF_CFG0(port); -		break; -	case 1: -		reg1->reg = NHMEX_R_MSR_PORTN_IPERF_CFG1(port); -		break; -	case 2: -	case 3: -		reg1->reg = NHMEX_R_MSR_PORTN_QLX_CFG(port); -		break; +	switch (idx % 6) {  	case 4:  	case 5: -		if (idx == 4) -			reg1->reg = NHMEX_R_MSR_PORTN_XBR_SET1_MM_CFG(port); -		else -			reg1->reg = NHMEX_R_MSR_PORTN_XBR_SET2_MM_CFG(port); -		reg2->config = event->attr.config2;  		hwc->config |= event->attr.config & (~0ULL << 32); +		reg2->config = event->attr.config2;  		break;  	};  	return 0; @@ -1727,28 +1729,34 @@ static void nhmex_rbox_msr_enable_event(struct intel_uncore_box *box, struct per  	struct hw_perf_event *hwc = &event->hw;  	struct hw_perf_event_extra *reg1 = &hwc->extra_reg;  	struct hw_perf_event_extra *reg2 = &hwc->branch_reg; -	int idx, er_idx; +	int idx, port; -	idx = reg1->idx % 6; -	er_idx = idx; -	if (er_idx > 2) -		er_idx--; -	er_idx += (reg1->idx / 6) * 5; +	idx = reg1->idx; +	port = idx / 6 + box->pmu->pmu_idx * 4; -	switch (idx) { +	switch (idx % 6) {  	case 0: +		wrmsrl(NHMEX_R_MSR_PORTN_IPERF_CFG0(port), reg1->config); +		break;  	case 1: -		wrmsrl(reg1->reg, reg1->config); +		wrmsrl(NHMEX_R_MSR_PORTN_IPERF_CFG1(port), reg1->config);  		break;  	case 2:  	case 3: -		wrmsrl(reg1->reg, nhmex_rbox_shared_reg_config(box, er_idx)); +		wrmsrl(NHMEX_R_MSR_PORTN_QLX_CFG(port), +			nhmex_rbox_shared_reg_config(box, 2 + (idx / 6) * 5));  		break;  	case 4: +		wrmsrl(NHMEX_R_MSR_PORTN_XBR_SET1_MM_CFG(port), +			hwc->config >> 32); +		wrmsrl(NHMEX_R_MSR_PORTN_XBR_SET1_MATCH(port), reg1->config); +		wrmsrl(NHMEX_R_MSR_PORTN_XBR_SET1_MASK(port), reg2->config); +		break;  	case 5: -		wrmsrl(reg1->reg, reg1->config); -		wrmsrl(reg1->reg + 1, hwc->config >> 32); -		wrmsrl(reg1->reg + 2, reg2->config); +		wrmsrl(NHMEX_R_MSR_PORTN_XBR_SET2_MM_CFG(port), +			hwc->config >> 32); +		wrmsrl(NHMEX_R_MSR_PORTN_XBR_SET2_MATCH(port), reg1->config); +		wrmsrl(NHMEX_R_MSR_PORTN_XBR_SET2_MASK(port), reg2->config);  		break;  	}; @@ -1756,8 +1764,8 @@ static void nhmex_rbox_msr_enable_event(struct intel_uncore_box *box, struct per  		(hwc->config & NHMEX_R_PMON_CTL_EV_SEL_MASK));  } -DEFINE_UNCORE_FORMAT_ATTR(xbr_match, xbr_match, "config:32-63"); -DEFINE_UNCORE_FORMAT_ATTR(xbr_mm_cfg, xbr_mm_cfg, "config1:0-63"); +DEFINE_UNCORE_FORMAT_ATTR(xbr_mm_cfg, xbr_mm_cfg, "config:32-63"); +DEFINE_UNCORE_FORMAT_ATTR(xbr_match, xbr_match, "config1:0-63");  DEFINE_UNCORE_FORMAT_ATTR(xbr_mask, xbr_mask, "config2:0-63");  DEFINE_UNCORE_FORMAT_ATTR(qlx_cfg, qlx_cfg, "config1:0-15");  DEFINE_UNCORE_FORMAT_ATTR(iperf_cfg, iperf_cfg, "config1:0-31"); @@ -2303,6 +2311,7 @@ int uncore_pmu_event_init(struct perf_event *event)  	event->hw.idx = -1;  	event->hw.last_tag = ~0ULL;  	event->hw.extra_reg.idx = EXTRA_REG_NONE; +	event->hw.branch_reg.idx = EXTRA_REG_NONE;  	if (event->attr.config == UNCORE_FIXED_EVENT) {  		/* no fixed counter */ @@ -2373,7 +2382,7 @@ static void __init uncore_type_exit(struct intel_uncore_type *type)  	type->attr_groups[1] = NULL;  } -static void uncore_types_exit(struct intel_uncore_type **types) +static void __init uncore_types_exit(struct intel_uncore_type **types)  {  	int i;  	for (i = 0; types[i]; i++) @@ -2814,7 +2823,13 @@ static int __init uncore_cpu_init(void)  			snbep_uncore_cbox.num_boxes = max_cores;  		msr_uncores = snbep_msr_uncores;  		break; -	case 46: +	case 46: /* Nehalem-EX */ +		uncore_nhmex = true; +	case 47: /* Westmere-EX aka. Xeon E7 */ +		if (!uncore_nhmex) +			nhmex_uncore_mbox.event_descs = wsmex_uncore_mbox_events; +		if (nhmex_uncore_cbox.num_boxes > max_cores) +			nhmex_uncore_cbox.num_boxes = max_cores;  		msr_uncores = nhmex_msr_uncores;  		break;  	default: diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.h b/arch/x86/kernel/cpu/perf_event_intel_uncore.h index f3851892e07..5b81c1856aa 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_uncore.h +++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.h @@ -5,7 +5,7 @@  #include "perf_event.h"  #define UNCORE_PMU_NAME_LEN		32 -#define UNCORE_PMU_HRTIMER_INTERVAL	(60 * NSEC_PER_SEC) +#define UNCORE_PMU_HRTIMER_INTERVAL	(60LL * NSEC_PER_SEC)  #define UNCORE_FIXED_EVENT		0xff  #define UNCORE_PMC_IDX_MAX_GENERIC	8 @@ -230,6 +230,7 @@  #define NHMEX_S1_MSR_MASK			0xe5a  #define NHMEX_S_PMON_MM_CFG_EN			(0x1ULL << 63) +#define NHMEX_S_EVENT_TO_R_PROG_EV		0  /* NHM-EX Mbox */  #define NHMEX_M0_MSR_GLOBAL_CTL			0xca0 @@ -275,18 +276,12 @@  		 NHMEX_M_PMON_CTL_INC_SEL_MASK |	\  		 NHMEX_M_PMON_CTL_SET_FLAG_SEL_MASK) - -#define NHMEX_M_PMON_ZDP_CTL_FVC_FVID_MASK	0x1f -#define NHMEX_M_PMON_ZDP_CTL_FVC_BCMD_MASK	(0x7 << 5) -#define NHMEX_M_PMON_ZDP_CTL_FVC_RSP_MASK	(0x7 << 8) -#define NHMEX_M_PMON_ZDP_CTL_FVC_PBOX_INIT_ERR	(1 << 23) -#define NHMEX_M_PMON_ZDP_CTL_FVC_MASK			\ -		(NHMEX_M_PMON_ZDP_CTL_FVC_FVID_MASK |	\ -		 NHMEX_M_PMON_ZDP_CTL_FVC_BCMD_MASK |	\ -		 NHMEX_M_PMON_ZDP_CTL_FVC_RSP_MASK  |	\ -		 NHMEX_M_PMON_ZDP_CTL_FVC_PBOX_INIT_ERR) +#define NHMEX_M_PMON_ZDP_CTL_FVC_MASK		(((1 << 11) - 1) | (1 << 23))  #define NHMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(n)	(0x7 << (11 + 3 * (n))) +#define WSMEX_M_PMON_ZDP_CTL_FVC_MASK		(((1 << 12) - 1) | (1 << 24)) +#define WSMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(n)	(0x7 << (12 + 3 * (n))) +  /*   * use the 9~13 bits to select event If the 7th bit is not set,   * otherwise use the 19~21 bits to select event. @@ -368,6 +363,7 @@ struct intel_uncore_type {  	unsigned num_shared_regs:8;  	unsigned single_fixed:1;  	unsigned pair_ctr_ctl:1; +	unsigned *msr_offsets;  	struct event_constraint unconstrainted;  	struct event_constraint *constraints;  	struct intel_uncore_pmu *pmus; @@ -485,29 +481,31 @@ unsigned uncore_pci_perf_ctr(struct intel_uncore_box *box, int idx)  	return idx * 8 + box->pmu->type->perf_ctr;  } -static inline -unsigned uncore_msr_box_ctl(struct intel_uncore_box *box) +static inline unsigned uncore_msr_box_offset(struct intel_uncore_box *box) +{ +	struct intel_uncore_pmu *pmu = box->pmu; +	return pmu->type->msr_offsets ? +		pmu->type->msr_offsets[pmu->pmu_idx] : +		pmu->type->msr_offset * pmu->pmu_idx; +} + +static inline unsigned uncore_msr_box_ctl(struct intel_uncore_box *box)  {  	if (!box->pmu->type->box_ctl)  		return 0; -	return box->pmu->type->box_ctl + -		box->pmu->type->msr_offset * box->pmu->pmu_idx; +	return box->pmu->type->box_ctl + uncore_msr_box_offset(box);  } -static inline -unsigned uncore_msr_fixed_ctl(struct intel_uncore_box *box) +static inline unsigned uncore_msr_fixed_ctl(struct intel_uncore_box *box)  {  	if (!box->pmu->type->fixed_ctl)  		return 0; -	return box->pmu->type->fixed_ctl + -		box->pmu->type->msr_offset * box->pmu->pmu_idx; +	return box->pmu->type->fixed_ctl + uncore_msr_box_offset(box);  } -static inline -unsigned uncore_msr_fixed_ctr(struct intel_uncore_box *box) +static inline unsigned uncore_msr_fixed_ctr(struct intel_uncore_box *box)  { -	return box->pmu->type->fixed_ctr + -		box->pmu->type->msr_offset * box->pmu->pmu_idx; +	return box->pmu->type->fixed_ctr + uncore_msr_box_offset(box);  }  static inline @@ -515,7 +513,7 @@ unsigned uncore_msr_event_ctl(struct intel_uncore_box *box, int idx)  {  	return box->pmu->type->event_ctl +  		(box->pmu->type->pair_ctr_ctl ? 2 * idx : idx) + -		box->pmu->type->msr_offset * box->pmu->pmu_idx; +		uncore_msr_box_offset(box);  }  static inline @@ -523,7 +521,7 @@ unsigned uncore_msr_perf_ctr(struct intel_uncore_box *box, int idx)  {  	return box->pmu->type->perf_ctr +  		(box->pmu->type->pair_ctr_ctl ? 2 * idx : idx) + -		box->pmu->type->msr_offset * box->pmu->pmu_idx; +		uncore_msr_box_offset(box);  }  static inline diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c index 1f5f1d5d2a0..d44f7829968 100644 --- a/arch/x86/kernel/irq.c +++ b/arch/x86/kernel/irq.c @@ -270,7 +270,7 @@ void fixup_irqs(void)  		if (cpumask_any_and(affinity, cpu_online_mask) >= nr_cpu_ids) {  			break_affinity = 1; -			affinity = cpu_all_mask; +			affinity = cpu_online_mask;  		}  		chip = irq_data_get_irq_chip(data); @@ -328,6 +328,7 @@ void fixup_irqs(void)  				chip->irq_retrigger(data);  			raw_spin_unlock(&desc->lock);  		} +		__this_cpu_write(vector_irq[vector], -1);  	}  }  #endif diff --git a/arch/x86/kernel/kdebugfs.c b/arch/x86/kernel/kdebugfs.c index 1d5d31ea686..dc1404bf8e4 100644 --- a/arch/x86/kernel/kdebugfs.c +++ b/arch/x86/kernel/kdebugfs.c @@ -107,7 +107,7 @@ static int __init create_setup_data_nodes(struct dentry *parent)  {  	struct setup_data_node *node;  	struct setup_data *data; -	int error = -ENOMEM; +	int error;  	struct dentry *d;  	struct page *pg;  	u64 pa_data; @@ -121,8 +121,10 @@ static int __init create_setup_data_nodes(struct dentry *parent)  	while (pa_data) {  		node = kmalloc(sizeof(*node), GFP_KERNEL); -		if (!node) +		if (!node) { +			error = -ENOMEM;  			goto err_dir; +		}  		pg = pfn_to_page((pa_data+sizeof(*data)-1) >> PAGE_SHIFT);  		if (PageHighMem(pg)) { diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c index 8a2ce8fd41c..82746f942cd 100644 --- a/arch/x86/kernel/microcode_amd.c +++ b/arch/x86/kernel/microcode_amd.c @@ -143,11 +143,12 @@ static int get_matching_microcode(int cpu, const u8 *ucode_ptr,  				  unsigned int *current_size)  {  	struct microcode_header_amd *mc_hdr; -	unsigned int actual_size; +	unsigned int actual_size, patch_size;  	u16 equiv_cpu_id;  	/* size of the current patch we're staring at */ -	*current_size = *(u32 *)(ucode_ptr + 4) + SECTION_HDR_SIZE; +	patch_size = *(u32 *)(ucode_ptr + 4); +	*current_size = patch_size + SECTION_HDR_SIZE;  	equiv_cpu_id = find_equiv_id();  	if (!equiv_cpu_id) @@ -174,7 +175,7 @@ static int get_matching_microcode(int cpu, const u8 *ucode_ptr,  	/*  	 * now that the header looks sane, verify its size  	 */ -	actual_size = verify_ucode_size(cpu, *current_size, leftover_size); +	actual_size = verify_ucode_size(cpu, patch_size, leftover_size);  	if (!actual_size)  		return 0;  |