diff options
Diffstat (limited to 'arch/powerpc/kernel')
| -rw-r--r-- | arch/powerpc/kernel/dma-iommu.c | 9 | ||||
| -rw-r--r-- | arch/powerpc/kernel/exceptions-64s.S | 25 | ||||
| -rw-r--r-- | arch/powerpc/kernel/idle_book3s.S | 10 | ||||
| -rw-r--r-- | arch/powerpc/kernel/irq.c | 6 | ||||
| -rw-r--r-- | arch/powerpc/kernel/security.c | 5 | ||||
| -rw-r--r-- | arch/powerpc/kernel/smp.c | 2 | ||||
| -rw-r--r-- | arch/powerpc/kernel/traps.c | 43 | 
7 files changed, 69 insertions, 31 deletions
| diff --git a/arch/powerpc/kernel/dma-iommu.c b/arch/powerpc/kernel/dma-iommu.c index 111249fd619d..038ce8d9061d 100644 --- a/arch/powerpc/kernel/dma-iommu.c +++ b/arch/powerpc/kernel/dma-iommu.c @@ -184,6 +184,15 @@ u64 dma_iommu_get_required_mask(struct device *dev)  	struct iommu_table *tbl = get_iommu_table_base(dev);  	u64 mask; +	if (dev_is_pci(dev)) { +		u64 bypass_mask = dma_direct_get_required_mask(dev); + +		if (dma_iommu_dma_supported(dev, bypass_mask)) { +			dev_info(dev, "%s: returning bypass mask 0x%llx\n", __func__, bypass_mask); +			return bypass_mask; +		} +	} +  	if (!tbl)  		return 0; diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S index 37859e62a8dc..eaf1f72131a1 100644 --- a/arch/powerpc/kernel/exceptions-64s.S +++ b/arch/powerpc/kernel/exceptions-64s.S @@ -1243,7 +1243,7 @@ EXC_COMMON_BEGIN(machine_check_common)  	li	r10,MSR_RI  	mtmsrd 	r10,1  	addi	r3,r1,STACK_FRAME_OVERHEAD -	bl	machine_check_exception +	bl	machine_check_exception_async  	b	interrupt_return_srr @@ -1303,7 +1303,11 @@ END_FTR_SECTION_IFSET(CPU_FTR_HVMODE)  	subi	r12,r12,1  	sth	r12,PACA_IN_MCE(r13) -	/* Invoke machine_check_exception to print MCE event and panic. */ +	/* +	 * Invoke machine_check_exception to print MCE event and panic. +	 * This is the NMI version of the handler because we are called from +	 * the early handler which is a true NMI. +	 */  	addi	r3,r1,STACK_FRAME_OVERHEAD  	bl	machine_check_exception @@ -1665,27 +1669,30 @@ EXC_COMMON_BEGIN(program_check_common)  	 */  	andi.	r10,r12,MSR_PR -	bne	2f			/* If userspace, go normal path */ +	bne	.Lnormal_stack		/* If userspace, go normal path */  	andis.	r10,r12,(SRR1_PROGTM)@h -	bne	1f			/* If TM, emergency		*/ +	bne	.Lemergency_stack	/* If TM, emergency		*/  	cmpdi	r1,-INT_FRAME_SIZE	/* check if r1 is in userspace	*/ -	blt	2f			/* normal path if not		*/ +	blt	.Lnormal_stack		/* normal path if not		*/  	/* Use the emergency stack					*/ -1:	andi.	r10,r12,MSR_PR		/* Set CR0 correctly for label	*/ +.Lemergency_stack: +	andi.	r10,r12,MSR_PR		/* Set CR0 correctly for label	*/  					/* 3 in EXCEPTION_PROLOG_COMMON	*/  	mr	r10,r1			/* Save r1			*/  	ld	r1,PACAEMERGSP(r13)	/* Use emergency stack		*/  	subi	r1,r1,INT_FRAME_SIZE	/* alloc stack frame		*/  	__ISTACK(program_check)=0  	__GEN_COMMON_BODY program_check -	b 3f -2: +	b .Ldo_program_check + +.Lnormal_stack:  	__ISTACK(program_check)=1  	__GEN_COMMON_BODY program_check -3: + +.Ldo_program_check:  	addi	r3,r1,STACK_FRAME_OVERHEAD  	bl	program_check_exception  	REST_NVGPRS(r1) /* instruction emulation may change GPRs */ diff --git a/arch/powerpc/kernel/idle_book3s.S b/arch/powerpc/kernel/idle_book3s.S index abb719b21cae..3d97fb833834 100644 --- a/arch/powerpc/kernel/idle_book3s.S +++ b/arch/powerpc/kernel/idle_book3s.S @@ -126,14 +126,16 @@ _GLOBAL(idle_return_gpr_loss)  /*   * This is the sequence required to execute idle instructions, as   * specified in ISA v2.07 (and earlier). MSR[IR] and MSR[DR] must be 0. - * - * The 0(r1) slot is used to save r2 in isa206, so use that here. + * We have to store a GPR somewhere, ptesync, then reload it, and create + * a false dependency on the result of the load. It doesn't matter which + * GPR we store, or where we store it. We have already stored r2 to the + * stack at -8(r1) in isa206_idle_insn_mayloss, so use that.   */  #define IDLE_STATE_ENTER_SEQ_NORET(IDLE_INST)			\  	/* Magic NAP/SLEEP/WINKLE mode enter sequence */	\ -	std	r2,0(r1);					\ +	std	r2,-8(r1);					\  	ptesync;						\ -	ld	r2,0(r1);					\ +	ld	r2,-8(r1);					\  236:	cmpd	cr0,r2,r2;					\  	bne	236b;						\  	IDLE_INST;						\ diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index 551b653228c4..c4f1d6b7d992 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c @@ -229,6 +229,9 @@ notrace void arch_local_irq_restore(unsigned long mask)  		return;  	} +	if (IS_ENABLED(CONFIG_PPC_IRQ_SOFT_MASK_DEBUG)) +		WARN_ON_ONCE(in_nmi() || in_hardirq()); +  	/*  	 * After the stb, interrupts are unmasked and there are no interrupts  	 * pending replay. The restart sequence makes this atomic with @@ -321,6 +324,9 @@ notrace void arch_local_irq_restore(unsigned long mask)  	if (mask)  		return; +	if (IS_ENABLED(CONFIG_PPC_IRQ_SOFT_MASK_DEBUG)) +		WARN_ON_ONCE(in_nmi() || in_hardirq()); +  	/*  	 * From this point onward, we can take interrupts, preempt,  	 * etc... unless we got hard-disabled. We check if an event diff --git a/arch/powerpc/kernel/security.c b/arch/powerpc/kernel/security.c index 1a998490fe60..15fb5ea1b9ea 100644 --- a/arch/powerpc/kernel/security.c +++ b/arch/powerpc/kernel/security.c @@ -263,6 +263,11 @@ static int __init handle_no_stf_barrier(char *p)  early_param("no_stf_barrier", handle_no_stf_barrier); +enum stf_barrier_type stf_barrier_type_get(void) +{ +	return stf_enabled_flush_types; +} +  /* This is the generic flag used by other architectures */  static int __init handle_ssbd(char *p)  { diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index 9cc7d3dbf439..605bab448f84 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c @@ -1730,8 +1730,6 @@ void __cpu_die(unsigned int cpu)  void arch_cpu_idle_dead(void)  { -	sched_preempt_enable_no_resched(); -  	/*  	 * Disable on the down path. This will be re-enabled by  	 * start_secondary() via start_secondary_resume() below diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index aac8c0412ff9..11741703d26e 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c @@ -340,10 +340,16 @@ static bool exception_common(int signr, struct pt_regs *regs, int code,  		return false;  	} -	show_signal_msg(signr, regs, code, addr); +	/* +	 * Must not enable interrupts even for user-mode exception, because +	 * this can be called from machine check, which may be a NMI or IRQ +	 * which don't like interrupts being enabled. Could check for +	 * in_hardirq || in_nmi perhaps, but there doesn't seem to be a good +	 * reason why _exception() should enable irqs for an exception handler, +	 * the handlers themselves do that directly. +	 */ -	if (arch_irqs_disabled()) -		interrupt_cond_local_irq_enable(regs); +	show_signal_msg(signr, regs, code, addr);  	current->thread.trap_nr = code; @@ -790,24 +796,22 @@ void die_mce(const char *str, struct pt_regs *regs, long err)  	 * do_exit() checks for in_interrupt() and panics in that case, so  	 * exit the irq/nmi before calling die.  	 */ -	if (IS_ENABLED(CONFIG_PPC_BOOK3S_64)) -		irq_exit(); -	else +	if (in_nmi())  		nmi_exit(); +	else +		irq_exit();  	die(str, regs, err);  }  /* - * BOOK3S_64 does not call this handler as a non-maskable interrupt + * BOOK3S_64 does not usually call this handler as a non-maskable interrupt   * (it uses its own early real-mode handler to handle the MCE proper   * and then raises irq_work to call this handler when interrupts are - * enabled). + * enabled). The only time when this is not true is if the early handler + * is unrecoverable, then it does call this directly to try to get a + * message out.   */ -#ifdef CONFIG_PPC_BOOK3S_64 -DEFINE_INTERRUPT_HANDLER_ASYNC(machine_check_exception) -#else -DEFINE_INTERRUPT_HANDLER_NMI(machine_check_exception) -#endif +static void __machine_check_exception(struct pt_regs *regs)  {  	int recover = 0; @@ -841,12 +845,19 @@ bail:  	/* Must die if the interrupt is not recoverable */  	if (regs_is_unrecoverable(regs))  		die_mce("Unrecoverable Machine check", regs, SIGBUS); +}  #ifdef CONFIG_PPC_BOOK3S_64 -	return; -#else -	return 0; +DEFINE_INTERRUPT_HANDLER_ASYNC(machine_check_exception_async) +{ +	__machine_check_exception(regs); +}  #endif +DEFINE_INTERRUPT_HANDLER_NMI(machine_check_exception) +{ +	__machine_check_exception(regs); + +	return 0;  }  DEFINE_INTERRUPT_HANDLER(SMIException) /* async? */ |