diff options
Diffstat (limited to 'arch/x86/kernel')
| -rw-r--r-- | arch/x86/kernel/alternative.c | 5 | ||||
| -rw-r--r-- | arch/x86/kernel/apic/apic.c | 7 | ||||
| -rw-r--r-- | arch/x86/kernel/apic/io_apic.c | 5 | ||||
| -rw-r--r-- | arch/x86/kernel/apic/vector.c | 4 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/common.c | 4 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/perf_event_intel.c | 5 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/perf_event_intel_bts.c | 1 | ||||
| -rw-r--r-- | arch/x86/kernel/irq_32.c | 19 | ||||
| -rw-r--r-- | arch/x86/kernel/irq_64.c | 2 | ||||
| -rw-r--r-- | arch/x86/kernel/ldt.c | 4 | ||||
| -rw-r--r-- | arch/x86/kernel/pci-dma.c | 2 | ||||
| -rw-r--r-- | arch/x86/kernel/tsc.c | 17 | ||||
| -rw-r--r-- | arch/x86/kernel/vm86_32.c | 27 | 
13 files changed, 71 insertions, 31 deletions
| diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c index c42827eb86cf..25f909362b7a 100644 --- a/arch/x86/kernel/alternative.c +++ b/arch/x86/kernel/alternative.c @@ -338,10 +338,15 @@ done:  static void __init_or_module optimize_nops(struct alt_instr *a, u8 *instr)  { +	unsigned long flags; +  	if (instr[0] != 0x90)  		return; +	local_irq_save(flags);  	add_nops(instr + (a->instrlen - a->padlen), a->padlen); +	sync_core(); +	local_irq_restore(flags);  	DUMP_BYTES(instr, a->instrlen, "%p: [%d:%d) optimized NOPs: ",  		   instr, a->instrlen - a->padlen, a->padlen); diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 3ca3e46aa405..24e94ce454e2 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -336,6 +336,13 @@ static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen)  	apic_write(APIC_LVTT, lvtt_value);  	if (lvtt_value & APIC_LVT_TIMER_TSCDEADLINE) { +		/* +		 * See Intel SDM: TSC-Deadline Mode chapter. In xAPIC mode, +		 * writing to the APIC LVTT and TSC_DEADLINE MSR isn't serialized. +		 * According to Intel, MFENCE can do the serialization here. +		 */ +		asm volatile("mfence" : : : "memory"); +  		printk_once(KERN_DEBUG "TSC deadline timer enabled\n");  		return;  	} diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 38a76f826530..5c60bb162622 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -2522,6 +2522,7 @@ void __init setup_ioapic_dest(void)  	int pin, ioapic, irq, irq_entry;  	const struct cpumask *mask;  	struct irq_data *idata; +	struct irq_chip *chip;  	if (skip_ioapic_setup == 1)  		return; @@ -2545,9 +2546,9 @@ void __init setup_ioapic_dest(void)  		else  			mask = apic->target_cpus(); -		irq_set_affinity(irq, mask); +		chip = irq_data_get_irq_chip(idata); +		chip->irq_set_affinity(idata, mask, false);  	} -  }  #endif diff --git a/arch/x86/kernel/apic/vector.c b/arch/x86/kernel/apic/vector.c index 1bbd0fe2c806..836d11b92811 100644 --- a/arch/x86/kernel/apic/vector.c +++ b/arch/x86/kernel/apic/vector.c @@ -489,10 +489,8 @@ static int apic_set_affinity(struct irq_data *irq_data,  	err = assign_irq_vector(irq, data, dest);  	if (err) { -		struct irq_data *top = irq_get_irq_data(irq); -  		if (assign_irq_vector(irq, data, -				      irq_data_get_affinity_mask(top))) +				      irq_data_get_affinity_mask(irq_data)))  			pr_err("Failed to recover vector for irq %d\n", irq);  		return err;  	} diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 07ce52c22ec8..de22ea7ff82f 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -1110,10 +1110,10 @@ void print_cpu_info(struct cpuinfo_x86 *c)  	else  		printk(KERN_CONT "%d86", c->x86); -	printk(KERN_CONT " (fam: %02x, model: %02x", c->x86, c->x86_model); +	printk(KERN_CONT " (family: 0x%x, model: 0x%x", c->x86, c->x86_model);  	if (c->x86_mask || c->cpuid_level >= 0) -		printk(KERN_CONT ", stepping: %02x)\n", c->x86_mask); +		printk(KERN_CONT ", stepping: 0x%x)\n", c->x86_mask);  	else  		printk(KERN_CONT ")\n"); diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c index cd9b6d0b10bf..3fefebfbdf4b 100644 --- a/arch/x86/kernel/cpu/perf_event_intel.c +++ b/arch/x86/kernel/cpu/perf_event_intel.c @@ -2316,9 +2316,12 @@ static struct event_constraint *  intel_get_event_constraints(struct cpu_hw_events *cpuc, int idx,  			    struct perf_event *event)  { -	struct event_constraint *c1 = cpuc->event_constraint[idx]; +	struct event_constraint *c1 = NULL;  	struct event_constraint *c2; +	if (idx >= 0) /* fake does < 0 */ +		c1 = cpuc->event_constraint[idx]; +  	/*  	 * first time only  	 * - static constraint: no change across incremental scheduling calls diff --git a/arch/x86/kernel/cpu/perf_event_intel_bts.c b/arch/x86/kernel/cpu/perf_event_intel_bts.c index 54690e885759..d1c0f254afbe 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_bts.c +++ b/arch/x86/kernel/cpu/perf_event_intel_bts.c @@ -222,6 +222,7 @@ static void __bts_event_start(struct perf_event *event)  	if (!buf || bts_buffer_is_full(buf, bts))  		return; +	event->hw.itrace_started = 1;  	event->hw.state = 0;  	if (!buf->snapshot) diff --git a/arch/x86/kernel/irq_32.c b/arch/x86/kernel/irq_32.c index c80cf6699678..38da8f29a9c8 100644 --- a/arch/x86/kernel/irq_32.c +++ b/arch/x86/kernel/irq_32.c @@ -68,11 +68,10 @@ static inline void *current_stack(void)  	return (void *)(current_stack_pointer() & ~(THREAD_SIZE - 1));  } -static inline int -execute_on_irq_stack(int overflow, struct irq_desc *desc, int irq) +static inline int execute_on_irq_stack(int overflow, struct irq_desc *desc)  {  	struct irq_stack *curstk, *irqstk; -	u32 *isp, *prev_esp, arg1, arg2; +	u32 *isp, *prev_esp, arg1;  	curstk = (struct irq_stack *) current_stack();  	irqstk = __this_cpu_read(hardirq_stack); @@ -98,8 +97,8 @@ execute_on_irq_stack(int overflow, struct irq_desc *desc, int irq)  	asm volatile("xchgl	%%ebx,%%esp	\n"  		     "call	*%%edi		\n"  		     "movl	%%ebx,%%esp	\n" -		     : "=a" (arg1), "=d" (arg2), "=b" (isp) -		     :  "0" (irq),   "1" (desc),  "2" (isp), +		     : "=a" (arg1), "=b" (isp) +		     :  "0" (desc),   "1" (isp),  			"D" (desc->handle_irq)  		     : "memory", "cc", "ecx");  	return 1; @@ -150,19 +149,15 @@ void do_softirq_own_stack(void)  bool handle_irq(struct irq_desc *desc, struct pt_regs *regs)  { -	unsigned int irq; -	int overflow; - -	overflow = check_stack_overflow(); +	int overflow = check_stack_overflow();  	if (IS_ERR_OR_NULL(desc))  		return false; -	irq = irq_desc_get_irq(desc); -	if (user_mode(regs) || !execute_on_irq_stack(overflow, desc, irq)) { +	if (user_mode(regs) || !execute_on_irq_stack(overflow, desc)) {  		if (unlikely(overflow))  			print_stack_overflow(); -		generic_handle_irq_desc(irq, desc); +		generic_handle_irq_desc(desc);  	}  	return true; diff --git a/arch/x86/kernel/irq_64.c b/arch/x86/kernel/irq_64.c index ff16ccb918f2..c767cf2bc80a 100644 --- a/arch/x86/kernel/irq_64.c +++ b/arch/x86/kernel/irq_64.c @@ -75,6 +75,6 @@ bool handle_irq(struct irq_desc *desc, struct pt_regs *regs)  	if (unlikely(IS_ERR_OR_NULL(desc)))  		return false; -	generic_handle_irq_desc(irq_desc_get_irq(desc), desc); +	generic_handle_irq_desc(desc);  	return true;  } diff --git a/arch/x86/kernel/ldt.c b/arch/x86/kernel/ldt.c index 2bcc0525f1c1..6acc9dd91f36 100644 --- a/arch/x86/kernel/ldt.c +++ b/arch/x86/kernel/ldt.c @@ -58,7 +58,7 @@ static struct ldt_struct *alloc_ldt_struct(int size)  	if (alloc_size > PAGE_SIZE)  		new_ldt->entries = vzalloc(alloc_size);  	else -		new_ldt->entries = kzalloc(PAGE_SIZE, GFP_KERNEL); +		new_ldt->entries = (void *)get_zeroed_page(GFP_KERNEL);  	if (!new_ldt->entries) {  		kfree(new_ldt); @@ -95,7 +95,7 @@ static void free_ldt_struct(struct ldt_struct *ldt)  	if (ldt->size * LDT_ENTRY_SIZE > PAGE_SIZE)  		vfree(ldt->entries);  	else -		kfree(ldt->entries); +		free_page((unsigned long)ldt->entries);  	kfree(ldt);  } diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c index 84b8ef82a159..1b55de1267cf 100644 --- a/arch/x86/kernel/pci-dma.c +++ b/arch/x86/kernel/pci-dma.c @@ -131,8 +131,8 @@ void dma_generic_free_coherent(struct device *dev, size_t size, void *vaddr,  bool arch_dma_alloc_attrs(struct device **dev, gfp_t *gfp)  { -	*gfp = dma_alloc_coherent_gfp_flags(*dev, *gfp);  	*gfp &= ~(__GFP_DMA | __GFP_HIGHMEM | __GFP_DMA32); +	*gfp = dma_alloc_coherent_gfp_flags(*dev, *gfp);  	if (!*dev)  		*dev = &x86_dma_fallback_dev; diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c index c8d52cb4cb6e..c3f7602cd038 100644 --- a/arch/x86/kernel/tsc.c +++ b/arch/x86/kernel/tsc.c @@ -21,6 +21,7 @@  #include <asm/hypervisor.h>  #include <asm/nmi.h>  #include <asm/x86_init.h> +#include <asm/geode.h>  unsigned int __read_mostly cpu_khz;	/* TSC clocks / usec, not used here */  EXPORT_SYMBOL(cpu_khz); @@ -1013,15 +1014,17 @@ EXPORT_SYMBOL_GPL(mark_tsc_unstable);  static void __init check_system_tsc_reliable(void)  { -#ifdef CONFIG_MGEODE_LX -	/* RTSC counts during suspend */ +#if defined(CONFIG_MGEODEGX1) || defined(CONFIG_MGEODE_LX) || defined(CONFIG_X86_GENERIC) +	if (is_geode_lx()) { +		/* RTSC counts during suspend */  #define RTSC_SUSP 0x100 -	unsigned long res_low, res_high; +		unsigned long res_low, res_high; -	rdmsr_safe(MSR_GEODE_BUSCONT_CONF0, &res_low, &res_high); -	/* Geode_LX - the OLPC CPU has a very reliable TSC */ -	if (res_low & RTSC_SUSP) -		tsc_clocksource_reliable = 1; +		rdmsr_safe(MSR_GEODE_BUSCONT_CONF0, &res_low, &res_high); +		/* Geode_LX - the OLPC CPU has a very reliable TSC */ +		if (res_low & RTSC_SUSP) +			tsc_clocksource_reliable = 1; +	}  #endif  	if (boot_cpu_has(X86_FEATURE_TSC_RELIABLE))  		tsc_clocksource_reliable = 1; diff --git a/arch/x86/kernel/vm86_32.c b/arch/x86/kernel/vm86_32.c index abd8b856bd2b..524619351961 100644 --- a/arch/x86/kernel/vm86_32.c +++ b/arch/x86/kernel/vm86_32.c @@ -45,6 +45,7 @@  #include <linux/audit.h>  #include <linux/stddef.h>  #include <linux/slab.h> +#include <linux/security.h>  #include <asm/uaccess.h>  #include <asm/io.h> @@ -232,6 +233,32 @@ static long do_sys_vm86(struct vm86plus_struct __user *user_vm86, bool plus)  	struct pt_regs *regs = current_pt_regs();  	unsigned long err = 0; +	err = security_mmap_addr(0); +	if (err) { +		/* +		 * vm86 cannot virtualize the address space, so vm86 users +		 * need to manage the low 1MB themselves using mmap.  Given +		 * that BIOS places important data in the first page, vm86 +		 * is essentially useless if mmap_min_addr != 0.  DOSEMU, +		 * for example, won't even bother trying to use vm86 if it +		 * can't map a page at virtual address 0. +		 * +		 * To reduce the available kernel attack surface, simply +		 * disallow vm86(old) for users who cannot mmap at va 0. +		 * +		 * The implementation of security_mmap_addr will allow +		 * suitably privileged users to map va 0 even if +		 * vm.mmap_min_addr is set above 0, and we want this +		 * behavior for vm86 as well, as it ensures that legacy +		 * tools like vbetool will not fail just because of +		 * vm.mmap_min_addr. +		 */ +		pr_info_once("Denied a call to vm86(old) from %s[%d] (uid: %d).  Set the vm.mmap_min_addr sysctl to 0 and/or adjust LSM mmap_min_addr policy to enable vm86 if you are using a vm86-based DOS emulator.\n", +			     current->comm, task_pid_nr(current), +			     from_kuid_munged(&init_user_ns, current_uid())); +		return -EPERM; +	} +  	if (!vm86) {  		if (!(vm86 = kzalloc(sizeof(*vm86), GFP_KERNEL)))  			return -ENOMEM; |