diff options
Diffstat (limited to 'arch/powerpc/kernel')
| -rw-r--r-- | arch/powerpc/kernel/asm-offsets.c | 1 | ||||
| -rw-r--r-- | arch/powerpc/kernel/dbell.c | 2 | ||||
| -rw-r--r-- | arch/powerpc/kernel/dma-iommu.c | 9 | ||||
| -rw-r--r-- | arch/powerpc/kernel/entry_64.S | 23 | ||||
| -rw-r--r-- | arch/powerpc/kernel/exceptions-64s.S | 3 | ||||
| -rw-r--r-- | arch/powerpc/kernel/hw_breakpoint.c | 2 | ||||
| -rw-r--r-- | arch/powerpc/kernel/idle_power7.S | 2 | ||||
| -rw-r--r-- | arch/powerpc/kernel/kgdb.c | 27 | ||||
| -rw-r--r-- | arch/powerpc/kernel/process.c | 12 | ||||
| -rw-r--r-- | arch/powerpc/kernel/smp.c | 11 | ||||
| -rw-r--r-- | arch/powerpc/kernel/syscalls.c | 8 | ||||
| -rw-r--r-- | arch/powerpc/kernel/sysfs.c | 10 | ||||
| -rw-r--r-- | arch/powerpc/kernel/time.c | 9 | ||||
| -rw-r--r-- | arch/powerpc/kernel/traps.c | 3 | 
14 files changed, 89 insertions, 33 deletions
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index 85b05c463fa..e8995727b1c 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c @@ -76,6 +76,7 @@ int main(void)  	DEFINE(SIGSEGV, SIGSEGV);  	DEFINE(NMI_MASK, NMI_MASK);  	DEFINE(THREAD_DSCR, offsetof(struct thread_struct, dscr)); +	DEFINE(THREAD_DSCR_INHERIT, offsetof(struct thread_struct, dscr_inherit));  #else  	DEFINE(THREAD_INFO, offsetof(struct task_struct, stack));  #endif /* CONFIG_PPC64 */ diff --git a/arch/powerpc/kernel/dbell.c b/arch/powerpc/kernel/dbell.c index 5b25c8060fd..a892680668d 100644 --- a/arch/powerpc/kernel/dbell.c +++ b/arch/powerpc/kernel/dbell.c @@ -28,6 +28,8 @@ void doorbell_setup_this_cpu(void)  void doorbell_cause_ipi(int cpu, unsigned long data)  { +	/* Order previous accesses vs. msgsnd, which is treated as a store */ +	mb();  	ppc_msgsnd(PPC_DBELL, 0, data);  } diff --git a/arch/powerpc/kernel/dma-iommu.c b/arch/powerpc/kernel/dma-iommu.c index 2d7bb8ced13..e4897523de4 100644 --- a/arch/powerpc/kernel/dma-iommu.c +++ b/arch/powerpc/kernel/dma-iommu.c @@ -83,11 +83,10 @@ static int dma_iommu_dma_supported(struct device *dev, u64 mask)  		return 0;  	} -	if ((tbl->it_offset + tbl->it_size) > (mask >> IOMMU_PAGE_SHIFT)) { -		dev_info(dev, "Warning: IOMMU window too big for device mask\n"); -		dev_info(dev, "mask: 0x%08llx, table end: 0x%08lx\n", -				mask, (tbl->it_offset + tbl->it_size) << -				IOMMU_PAGE_SHIFT); +	if (tbl->it_offset > (mask >> IOMMU_PAGE_SHIFT)) { +		dev_info(dev, "Warning: IOMMU offset too big for device mask\n"); +		dev_info(dev, "mask: 0x%08llx, table offset: 0x%08lx\n", +				mask, tbl->it_offset << IOMMU_PAGE_SHIFT);  		return 0;  	} else  		return 1; diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index 4b01a25e29e..b40e0b4815b 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S @@ -370,6 +370,12 @@ _GLOBAL(ret_from_fork)  	li	r3,0  	b	syscall_exit +	.section	".toc","aw" +DSCR_DEFAULT: +	.tc dscr_default[TC],dscr_default + +	.section	".text" +  /*   * This routine switches between two different tasks.  The process   * state of one is saved on its kernel stack.  Then the state @@ -509,9 +515,6 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)  	mr	r1,r8		/* start using new stack pointer */  	std	r7,PACAKSAVE(r13) -	ld	r6,_CCR(r1) -	mtcrf	0xFF,r6 -  #ifdef CONFIG_ALTIVEC  BEGIN_FTR_SECTION  	ld	r0,THREAD_VRSAVE(r4) @@ -520,14 +523,22 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)  #endif /* CONFIG_ALTIVEC */  #ifdef CONFIG_PPC64  BEGIN_FTR_SECTION +	lwz	r6,THREAD_DSCR_INHERIT(r4) +	ld	r7,DSCR_DEFAULT@toc(2)  	ld	r0,THREAD_DSCR(r4) -	cmpd	r0,r25 -	beq	1f +	cmpwi	r6,0 +	bne	1f +	ld	r0,0(r7) +1:	cmpd	r0,r25 +	beq	2f  	mtspr	SPRN_DSCR,r0 -1:	 +2:  END_FTR_SECTION_IFSET(CPU_FTR_DSCR)  #endif +	ld	r6,_CCR(r1) +	mtcrf	0xFF,r6 +  	/* r3-r13 are destroyed -- Cort */  	REST_8GPRS(14, r1)  	REST_10GPRS(22, r1) diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S index e894515e77b..39aa97d3ff8 100644 --- a/arch/powerpc/kernel/exceptions-64s.S +++ b/arch/powerpc/kernel/exceptions-64s.S @@ -186,7 +186,7 @@ hardware_interrupt_hv:  	KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0x800)  	MASKABLE_EXCEPTION_PSERIES(0x900, 0x900, decrementer) -	MASKABLE_EXCEPTION_HV(0x980, 0x982, decrementer) +	STD_EXCEPTION_HV(0x980, 0x982, hdecrementer)  	STD_EXCEPTION_PSERIES(0xa00, 0xa00, trap_0a)  	KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0xa00) @@ -486,6 +486,7 @@ machine_check_common:  	STD_EXCEPTION_COMMON_ASYNC(0x500, hardware_interrupt, do_IRQ)  	STD_EXCEPTION_COMMON_ASYNC(0x900, decrementer, .timer_interrupt) +	STD_EXCEPTION_COMMON(0x980, hdecrementer, .hdec_interrupt)  	STD_EXCEPTION_COMMON(0xa00, trap_0a, .unknown_exception)  	STD_EXCEPTION_COMMON(0xb00, trap_0b, .unknown_exception)  	STD_EXCEPTION_COMMON(0xd00, single_step, .single_step_exception) diff --git a/arch/powerpc/kernel/hw_breakpoint.c b/arch/powerpc/kernel/hw_breakpoint.c index f3a82dde61d..956a4c496de 100644 --- a/arch/powerpc/kernel/hw_breakpoint.c +++ b/arch/powerpc/kernel/hw_breakpoint.c @@ -253,7 +253,7 @@ int __kprobes hw_breakpoint_handler(struct die_args *args)  	/* Do not emulate user-space instructions, instead single-step them */  	if (user_mode(regs)) { -		bp->ctx->task->thread.last_hit_ubp = bp; +		current->thread.last_hit_ubp = bp;  		regs->msr |= MSR_SE;  		goto out;  	} diff --git a/arch/powerpc/kernel/idle_power7.S b/arch/powerpc/kernel/idle_power7.S index 7140d838339..e11863f4e59 100644 --- a/arch/powerpc/kernel/idle_power7.S +++ b/arch/powerpc/kernel/idle_power7.S @@ -28,7 +28,9 @@ _GLOBAL(power7_idle)  	lwz	r4,ADDROFF(powersave_nap)(r3)  	cmpwi	0,r4,0  	beqlr +	/* fall through */ +_GLOBAL(power7_nap)  	/* NAP is a state loss, we create a regs frame on the  	 * stack, fill it up with the state we care about and  	 * stick a pointer to it in PACAR1. We really only diff --git a/arch/powerpc/kernel/kgdb.c b/arch/powerpc/kernel/kgdb.c index 782bd0a3c2f..c470a40b29f 100644 --- a/arch/powerpc/kernel/kgdb.c +++ b/arch/powerpc/kernel/kgdb.c @@ -25,6 +25,7 @@  #include <asm/processor.h>  #include <asm/machdep.h>  #include <asm/debug.h> +#include <linux/slab.h>  /*   * This table contains the mapping between PowerPC hardware trap types, and @@ -101,6 +102,21 @@ static int computeSignal(unsigned int tt)  	return SIGHUP;		/* default for things we don't know about */  } +/** + * + *	kgdb_skipexception - Bail out of KGDB when we've been triggered. + *	@exception: Exception vector number + *	@regs: Current &struct pt_regs. + * + *	On some architectures we need to skip a breakpoint exception when + *	it occurs after a breakpoint has been removed. + * + */ +int kgdb_skipexception(int exception, struct pt_regs *regs) +{ +	return kgdb_isremovedbreak(regs->nip); +} +  static int kgdb_call_nmi_hook(struct pt_regs *regs)  {  	kgdb_nmicallback(raw_smp_processor_id(), regs); @@ -138,6 +154,8 @@ static int kgdb_handle_breakpoint(struct pt_regs *regs)  static int kgdb_singlestep(struct pt_regs *regs)  {  	struct thread_info *thread_info, *exception_thread_info; +	struct thread_info *backup_current_thread_info = \ +		(struct thread_info *)kmalloc(sizeof(struct thread_info), GFP_KERNEL);  	if (user_mode(regs))  		return 0; @@ -155,13 +173,17 @@ static int kgdb_singlestep(struct pt_regs *regs)  	thread_info = (struct thread_info *)(regs->gpr[1] & ~(THREAD_SIZE-1));  	exception_thread_info = current_thread_info(); -	if (thread_info != exception_thread_info) +	if (thread_info != exception_thread_info) { +		/* Save the original current_thread_info. */ +		memcpy(backup_current_thread_info, exception_thread_info, sizeof *thread_info);  		memcpy(exception_thread_info, thread_info, sizeof *thread_info); +	}  	kgdb_handle_exception(0, SIGTRAP, 0, regs);  	if (thread_info != exception_thread_info) -		memcpy(thread_info, exception_thread_info, sizeof *thread_info); +		/* Restore current_thread_info lastly. */ +		memcpy(exception_thread_info, backup_current_thread_info, sizeof *thread_info);  	return 1;  } @@ -410,7 +432,6 @@ int kgdb_arch_handle_exception(int vector, int signo, int err_code,  #else  			linux_regs->msr |= MSR_SE;  #endif -			kgdb_single_step = 1;  			atomic_set(&kgdb_cpu_doing_single_step,  				   raw_smp_processor_id());  		} diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 710f400476d..1a1f2ddfb58 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -802,16 +802,8 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,  #endif /* CONFIG_PPC_STD_MMU_64 */  #ifdef CONFIG_PPC64   	if (cpu_has_feature(CPU_FTR_DSCR)) { -		if (current->thread.dscr_inherit) { -			p->thread.dscr_inherit = 1; -			p->thread.dscr = current->thread.dscr; -		} else if (0 != dscr_default) { -			p->thread.dscr_inherit = 1; -			p->thread.dscr = dscr_default; -		} else { -			p->thread.dscr_inherit = 0; -			p->thread.dscr = 0; -		} +		p->thread.dscr_inherit = current->thread.dscr_inherit; +		p->thread.dscr = current->thread.dscr;  	}  #endif diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index 0321007086f..8d4214afc21 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c @@ -198,8 +198,15 @@ void smp_muxed_ipi_message_pass(int cpu, int msg)  	struct cpu_messages *info = &per_cpu(ipi_message, cpu);  	char *message = (char *)&info->messages; +	/* +	 * Order previous accesses before accesses in the IPI handler. +	 */ +	smp_mb();  	message[msg] = 1; -	mb(); +	/* +	 * cause_ipi functions are required to include a full barrier +	 * before doing whatever causes the IPI. +	 */  	smp_ops->cause_ipi(cpu, info->data);  } @@ -211,7 +218,7 @@ irqreturn_t smp_ipi_demux(void)  	mb();	/* order any irq clear */  	do { -		all = xchg_local(&info->messages, 0); +		all = xchg(&info->messages, 0);  #ifdef __BIG_ENDIAN  		if (all & (1 << (24 - 8 * PPC_MSG_CALL_FUNCTION))) diff --git a/arch/powerpc/kernel/syscalls.c b/arch/powerpc/kernel/syscalls.c index f2496f2faec..4e3cc47f26b 100644 --- a/arch/powerpc/kernel/syscalls.c +++ b/arch/powerpc/kernel/syscalls.c @@ -107,11 +107,11 @@ long ppc64_personality(unsigned long personality)  	long ret;  	if (personality(current->personality) == PER_LINUX32 -	    && personality == PER_LINUX) -		personality = PER_LINUX32; +	    && personality(personality) == PER_LINUX) +		personality = (personality & ~PER_MASK) | PER_LINUX32;  	ret = sys_personality(personality); -	if (ret == PER_LINUX32) -		ret = PER_LINUX; +	if (personality(ret) == PER_LINUX32) +		ret = (ret & ~PER_MASK) | PER_LINUX;  	return ret;  }  #endif diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c index 3529446c2ab..8302af64921 100644 --- a/arch/powerpc/kernel/sysfs.c +++ b/arch/powerpc/kernel/sysfs.c @@ -194,6 +194,14 @@ static ssize_t show_dscr_default(struct device *dev,  	return sprintf(buf, "%lx\n", dscr_default);  } +static void update_dscr(void *dummy) +{ +	if (!current->thread.dscr_inherit) { +		current->thread.dscr = dscr_default; +		mtspr(SPRN_DSCR, dscr_default); +	} +} +  static ssize_t __used store_dscr_default(struct device *dev,  		struct device_attribute *attr, const char *buf,  		size_t count) @@ -206,6 +214,8 @@ static ssize_t __used store_dscr_default(struct device *dev,  		return -EINVAL;  	dscr_default = val; +	on_each_cpu(update_dscr, NULL, 1); +  	return count;  } diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index be171ee73bf..e49e93191b6 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c @@ -535,6 +535,15 @@ void timer_interrupt(struct pt_regs * regs)  	trace_timer_interrupt_exit(regs);  } +/* + * Hypervisor decrementer interrupts shouldn't occur but are sometimes + * left pending on exit from a KVM guest.  We don't need to do anything + * to clear them, as they are edge-triggered. + */ +void hdec_interrupt(struct pt_regs *regs) +{ +} +  #ifdef CONFIG_SUSPEND  static void generic_suspend_disable_irqs(void)  { diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 158972341a2..ae0843fa7a6 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c @@ -972,8 +972,9 @@ static int emulate_instruction(struct pt_regs *regs)  			cpu_has_feature(CPU_FTR_DSCR)) {  		PPC_WARN_EMULATED(mtdscr, regs);  		rd = (instword >> 21) & 0x1f; -		mtspr(SPRN_DSCR, regs->gpr[rd]); +		current->thread.dscr = regs->gpr[rd];  		current->thread.dscr_inherit = 1; +		mtspr(SPRN_DSCR, current->thread.dscr);  		return 0;  	}  #endif  |