Excerpts from Christophe Leroy's message of September 6, 2020 5:32 pm: > > > Le 05/09/2020 à 19:43, Nicholas Piggin a écrit : >> There is no need for this to be in asm, use the new intrrupt entry wrapper. >> >> Signed-off-by: Nicholas Piggin <npig...@gmail.com> >> --- >> arch/powerpc/include/asm/interrupt.h | 14 ++++++++ >> arch/powerpc/include/asm/processor.h | 1 + >> arch/powerpc/include/asm/thread_info.h | 6 ++++ >> arch/powerpc/kernel/exceptions-64s.S | 45 -------------------------- >> arch/powerpc/kernel/idle_book3s.S | 4 +++ >> 5 files changed, 25 insertions(+), 45 deletions(-) >> >> diff --git a/arch/powerpc/include/asm/interrupt.h >> b/arch/powerpc/include/asm/interrupt.h >> index 3ae3d2f93b61..acfcc7d5779b 100644 >> --- a/arch/powerpc/include/asm/interrupt.h >> +++ b/arch/powerpc/include/asm/interrupt.h >> @@ -8,6 +8,16 @@ >> #include <asm/ftrace.h> >> #include <asm/runlatch.h> >> >> +static inline void nap_adjust_return(struct pt_regs *regs) >> +{ >> +#ifdef CONFIG_PPC_970_NAP > > Avoid #ifdef, you can use IS_ENABLED(CONFIG_PPC_970_NAP) in the 'if' below
Yeah I guess. >> + if (test_thread_local_flags(_TLF_NAPPING)) { >> + clear_thread_local_flags(_TLF_NAPPING); >> + regs->nip = (unsigned long)power4_idle_nap_return; >> + } >> +#endif >> +} >> + >> #ifdef CONFIG_PPC_BOOK3S_64 >> static inline void interrupt_enter_prepare(struct pt_regs *regs) >> { >> @@ -33,6 +43,8 @@ static inline void interrupt_async_enter_prepare(struct >> pt_regs *regs) >> if (cpu_has_feature(CPU_FTR_CTRL) && >> !test_thread_local_flags(_TLF_RUNLATCH)) >> __ppc64_runlatch_on(); >> + >> + nap_adjust_return(regs); >> } >> >> #else /* CONFIG_PPC_BOOK3S_64 */ >> @@ -72,6 +84,8 @@ static inline void interrupt_nmi_enter_prepare(struct >> pt_regs *regs, struct inte >> >> this_cpu_set_ftrace_enabled(0); >> >> + nap_adjust_return(regs); >> + >> nmi_enter(); >> } >> >> diff --git a/arch/powerpc/include/asm/processor.h >> b/arch/powerpc/include/asm/processor.h >> index ed0d633ab5aa..3da1dba91386 100644 >> --- a/arch/powerpc/include/asm/processor.h >> +++ b/arch/powerpc/include/asm/processor.h >> @@ -424,6 +424,7 @@ extern unsigned long isa300_idle_stop_mayloss(unsigned >> long psscr_val); >> extern unsigned long isa206_idle_insn_mayloss(unsigned long type); >> #ifdef CONFIG_PPC_970_NAP >> extern void power4_idle_nap(void); >> +extern void power4_idle_nap_return(void); > > Please please please, 'extern' keyword is pointless and deprecated for > function prototypes. Don't add new ones. > > Also, put it outside the #ifdef, so that you can use IS_ENABLED() > instead of #ifdef when using it. I just copy paste and forget to remove it. I expect someone will do a "cleanup" patch to get rid of them in one go, I find a random assortment of extern and not extern to be even uglier :( >> #endif >> >> extern unsigned long cpuidle_disable; >> diff --git a/arch/powerpc/include/asm/thread_info.h >> b/arch/powerpc/include/asm/thread_info.h >> index ca6c97025704..9b15f7edb0cb 100644 >> --- a/arch/powerpc/include/asm/thread_info.h >> +++ b/arch/powerpc/include/asm/thread_info.h >> @@ -156,6 +156,12 @@ void arch_setup_new_exec(void); >> >> #ifndef __ASSEMBLY__ >> >> +static inline void clear_thread_local_flags(unsigned int flags) >> +{ >> + struct thread_info *ti = current_thread_info(); >> + ti->local_flags &= ~flags; >> +} >> + >> static inline bool test_thread_local_flags(unsigned int flags) >> { >> struct thread_info *ti = current_thread_info(); >> diff --git a/arch/powerpc/kernel/exceptions-64s.S >> b/arch/powerpc/kernel/exceptions-64s.S >> index 227bad3a586d..1db6b3438c88 100644 >> --- a/arch/powerpc/kernel/exceptions-64s.S >> +++ b/arch/powerpc/kernel/exceptions-64s.S >> @@ -692,25 +692,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_CFAR) >> ld r1,GPR1(r1) >> .endm >> >> -/* >> - * When the idle code in power4_idle puts the CPU into NAP mode, >> - * it has to do so in a loop, and relies on the external interrupt >> - * and decrementer interrupt entry code to get it out of the loop. >> - * It sets the _TLF_NAPPING bit in current_thread_info()->local_flags >> - * to signal that it is in the loop and needs help to get out. >> - */ >> -#ifdef CONFIG_PPC_970_NAP >> -#define FINISH_NAP \ >> -BEGIN_FTR_SECTION \ >> - ld r11, PACA_THREAD_INFO(r13); \ >> - ld r9,TI_LOCAL_FLAGS(r11); \ >> - andi. r10,r9,_TLF_NAPPING; \ >> - bnel power4_fixup_nap; \ >> -END_FTR_SECTION_IFSET(CPU_FTR_CAN_NAP) >> -#else >> -#define FINISH_NAP >> -#endif >> - >> /* >> * There are a few constraints to be concerned with. >> * - Real mode exceptions code/data must be located at their physical >> location. >> @@ -1250,7 +1231,6 @@ EXC_COMMON_BEGIN(machine_check_common) >> */ >> GEN_COMMON machine_check >> >> - FINISH_NAP >> /* Enable MSR_RI when finished with PACA_EXMC */ >> li r10,MSR_RI >> mtmsrd r10,1 >> @@ -1572,7 +1552,6 @@ EXC_VIRT_BEGIN(hardware_interrupt, 0x4500, 0x100) >> EXC_VIRT_END(hardware_interrupt, 0x4500, 0x100) >> EXC_COMMON_BEGIN(hardware_interrupt_common) >> GEN_COMMON hardware_interrupt >> - FINISH_NAP >> addi r3,r1,STACK_FRAME_OVERHEAD >> bl do_IRQ >> b interrupt_return >> @@ -1757,7 +1736,6 @@ EXC_VIRT_BEGIN(decrementer, 0x4900, 0x80) >> EXC_VIRT_END(decrementer, 0x4900, 0x80) >> EXC_COMMON_BEGIN(decrementer_common) >> GEN_COMMON decrementer >> - FINISH_NAP >> addi r3,r1,STACK_FRAME_OVERHEAD >> bl timer_interrupt >> b interrupt_return >> @@ -1842,7 +1820,6 @@ EXC_VIRT_BEGIN(doorbell_super, 0x4a00, 0x100) >> EXC_VIRT_END(doorbell_super, 0x4a00, 0x100) >> EXC_COMMON_BEGIN(doorbell_super_common) >> GEN_COMMON doorbell_super >> - FINISH_NAP >> addi r3,r1,STACK_FRAME_OVERHEAD >> #ifdef CONFIG_PPC_DOORBELL >> bl doorbell_exception >> @@ -2196,7 +2173,6 @@ EXC_COMMON_BEGIN(hmi_exception_early_common) >> >> EXC_COMMON_BEGIN(hmi_exception_common) >> GEN_COMMON hmi_exception >> - FINISH_NAP >> addi r3,r1,STACK_FRAME_OVERHEAD >> bl handle_hmi_exception >> b interrupt_return >> @@ -2225,7 +2201,6 @@ EXC_VIRT_BEGIN(h_doorbell, 0x4e80, 0x20) >> EXC_VIRT_END(h_doorbell, 0x4e80, 0x20) >> EXC_COMMON_BEGIN(h_doorbell_common) >> GEN_COMMON h_doorbell >> - FINISH_NAP >> addi r3,r1,STACK_FRAME_OVERHEAD >> #ifdef CONFIG_PPC_DOORBELL >> bl doorbell_exception >> @@ -2258,7 +2233,6 @@ EXC_VIRT_BEGIN(h_virt_irq, 0x4ea0, 0x20) >> EXC_VIRT_END(h_virt_irq, 0x4ea0, 0x20) >> EXC_COMMON_BEGIN(h_virt_irq_common) >> GEN_COMMON h_virt_irq >> - FINISH_NAP >> addi r3,r1,STACK_FRAME_OVERHEAD >> bl do_IRQ >> b interrupt_return >> @@ -2304,7 +2278,6 @@ EXC_VIRT_BEGIN(performance_monitor, 0x4f00, 0x20) >> EXC_VIRT_END(performance_monitor, 0x4f00, 0x20) >> EXC_COMMON_BEGIN(performance_monitor_common) >> GEN_COMMON performance_monitor >> - FINISH_NAP >> addi r3,r1,STACK_FRAME_OVERHEAD >> bl performance_monitor_exception >> b interrupt_return >> @@ -3032,24 +3005,6 @@ USE_FIXED_SECTION(virt_trampolines) >> __end_interrupts: >> DEFINE_FIXED_SYMBOL(__end_interrupts) >> >> -#ifdef CONFIG_PPC_970_NAP >> - /* >> - * Called by exception entry code if _TLF_NAPPING was set, this clears >> - * the NAPPING flag, and redirects the exception exit to >> - * power4_fixup_nap_return. >> - */ >> - .globl power4_fixup_nap >> -EXC_COMMON_BEGIN(power4_fixup_nap) >> - andc r9,r9,r10 >> - std r9,TI_LOCAL_FLAGS(r11) >> - LOAD_REG_ADDR(r10, power4_idle_nap_return) >> - std r10,_NIP(r1) >> - blr >> - >> -power4_idle_nap_return: >> - blr >> -#endif >> - >> CLOSE_FIXED_SECTION(real_vectors); >> CLOSE_FIXED_SECTION(real_trampolines); >> CLOSE_FIXED_SECTION(virt_vectors); >> diff --git a/arch/powerpc/kernel/idle_book3s.S >> b/arch/powerpc/kernel/idle_book3s.S >> index 22f249b6f58d..27d2e6a72ec9 100644 >> --- a/arch/powerpc/kernel/idle_book3s.S >> +++ b/arch/powerpc/kernel/idle_book3s.S >> @@ -201,4 +201,8 @@ _GLOBAL(power4_idle_nap) >> mtmsrd r7 >> isync >> b 1b >> + >> + .globl power4_idle_nap_return >> +power4_idle_nap_return: >> + blr > > Can't this be written in C somewhere ? Yes I think so if you did the entire power4_idle_nap function in C and used inline asm for the mtmsrd and fixup label (basically the same way as copy user exceptions return to a fixup location). You have to return to the same C function of course because you can't control the stack otherwise. But I don't care too much about avoiding an extra function call/return here, all the important stuff is in C now. Thanks, Nick