18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 1999 Cort Dougan <cort@cs.nmt.edu> 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci#ifndef _ASM_POWERPC_HW_IRQ_H 68c2ecf20Sopenharmony_ci#define _ASM_POWERPC_HW_IRQ_H 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#ifdef __KERNEL__ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <linux/errno.h> 118c2ecf20Sopenharmony_ci#include <linux/compiler.h> 128c2ecf20Sopenharmony_ci#include <asm/ptrace.h> 138c2ecf20Sopenharmony_ci#include <asm/processor.h> 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC64 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci/* 188c2ecf20Sopenharmony_ci * PACA flags in paca->irq_happened. 198c2ecf20Sopenharmony_ci * 208c2ecf20Sopenharmony_ci * This bits are set when interrupts occur while soft-disabled 218c2ecf20Sopenharmony_ci * and allow a proper replay. Additionally, PACA_IRQ_HARD_DIS 228c2ecf20Sopenharmony_ci * is set whenever we manually hard disable. 238c2ecf20Sopenharmony_ci */ 248c2ecf20Sopenharmony_ci#define PACA_IRQ_HARD_DIS 0x01 258c2ecf20Sopenharmony_ci#define PACA_IRQ_DBELL 0x02 268c2ecf20Sopenharmony_ci#define PACA_IRQ_EE 0x04 278c2ecf20Sopenharmony_ci#define PACA_IRQ_DEC 0x08 /* Or FIT */ 288c2ecf20Sopenharmony_ci#define PACA_IRQ_HMI 0x10 298c2ecf20Sopenharmony_ci#define PACA_IRQ_PMI 0x20 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci/* 328c2ecf20Sopenharmony_ci * Some soft-masked interrupts must be hard masked until they are replayed 338c2ecf20Sopenharmony_ci * (e.g., because the soft-masked handler does not clear the exception). 348c2ecf20Sopenharmony_ci */ 358c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC_BOOK3S 368c2ecf20Sopenharmony_ci#define PACA_IRQ_MUST_HARD_MASK (PACA_IRQ_EE|PACA_IRQ_PMI) 378c2ecf20Sopenharmony_ci#else 388c2ecf20Sopenharmony_ci#define PACA_IRQ_MUST_HARD_MASK (PACA_IRQ_EE) 398c2ecf20Sopenharmony_ci#endif 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci#endif /* CONFIG_PPC64 */ 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci/* 448c2ecf20Sopenharmony_ci * flags for paca->irq_soft_mask 458c2ecf20Sopenharmony_ci */ 468c2ecf20Sopenharmony_ci#define IRQS_ENABLED 0 478c2ecf20Sopenharmony_ci#define IRQS_DISABLED 1 /* local_irq_disable() interrupts */ 488c2ecf20Sopenharmony_ci#define IRQS_PMI_DISABLED 2 498c2ecf20Sopenharmony_ci#define IRQS_ALL_DISABLED (IRQS_DISABLED | IRQS_PMI_DISABLED) 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci#ifndef __ASSEMBLY__ 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ciextern void replay_system_reset(void); 548c2ecf20Sopenharmony_ciextern void replay_soft_interrupts(void); 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ciextern void timer_interrupt(struct pt_regs *); 578c2ecf20Sopenharmony_ciextern void timer_broadcast_interrupt(void); 588c2ecf20Sopenharmony_ciextern void performance_monitor_exception(struct pt_regs *regs); 598c2ecf20Sopenharmony_ciextern void WatchdogException(struct pt_regs *regs); 608c2ecf20Sopenharmony_ciextern void unknown_exception(struct pt_regs *regs); 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC64 638c2ecf20Sopenharmony_ci#include <asm/paca.h> 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_cistatic inline notrace unsigned long irq_soft_mask_return(void) 668c2ecf20Sopenharmony_ci{ 678c2ecf20Sopenharmony_ci unsigned long flags; 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci asm volatile( 708c2ecf20Sopenharmony_ci "lbz %0,%1(13)" 718c2ecf20Sopenharmony_ci : "=r" (flags) 728c2ecf20Sopenharmony_ci : "i" (offsetof(struct paca_struct, irq_soft_mask))); 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci return flags; 758c2ecf20Sopenharmony_ci} 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci/* 788c2ecf20Sopenharmony_ci * The "memory" clobber acts as both a compiler barrier 798c2ecf20Sopenharmony_ci * for the critical section and as a clobber because 808c2ecf20Sopenharmony_ci * we changed paca->irq_soft_mask 818c2ecf20Sopenharmony_ci */ 828c2ecf20Sopenharmony_cistatic inline notrace void irq_soft_mask_set(unsigned long mask) 838c2ecf20Sopenharmony_ci{ 848c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC_IRQ_SOFT_MASK_DEBUG 858c2ecf20Sopenharmony_ci /* 868c2ecf20Sopenharmony_ci * The irq mask must always include the STD bit if any are set. 878c2ecf20Sopenharmony_ci * 888c2ecf20Sopenharmony_ci * and interrupts don't get replayed until the standard 898c2ecf20Sopenharmony_ci * interrupt (local_irq_disable()) is unmasked. 908c2ecf20Sopenharmony_ci * 918c2ecf20Sopenharmony_ci * Other masks must only provide additional masking beyond 928c2ecf20Sopenharmony_ci * the standard, and they are also not replayed until the 938c2ecf20Sopenharmony_ci * standard interrupt becomes unmasked. 948c2ecf20Sopenharmony_ci * 958c2ecf20Sopenharmony_ci * This could be changed, but it will require partial 968c2ecf20Sopenharmony_ci * unmasks to be replayed, among other things. For now, take 978c2ecf20Sopenharmony_ci * the simple approach. 988c2ecf20Sopenharmony_ci */ 998c2ecf20Sopenharmony_ci WARN_ON(mask && !(mask & IRQS_DISABLED)); 1008c2ecf20Sopenharmony_ci#endif 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci asm volatile( 1038c2ecf20Sopenharmony_ci "stb %0,%1(13)" 1048c2ecf20Sopenharmony_ci : 1058c2ecf20Sopenharmony_ci : "r" (mask), 1068c2ecf20Sopenharmony_ci "i" (offsetof(struct paca_struct, irq_soft_mask)) 1078c2ecf20Sopenharmony_ci : "memory"); 1088c2ecf20Sopenharmony_ci} 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_cistatic inline notrace unsigned long irq_soft_mask_set_return(unsigned long mask) 1118c2ecf20Sopenharmony_ci{ 1128c2ecf20Sopenharmony_ci unsigned long flags; 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC_IRQ_SOFT_MASK_DEBUG 1158c2ecf20Sopenharmony_ci WARN_ON(mask && !(mask & IRQS_DISABLED)); 1168c2ecf20Sopenharmony_ci#endif 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci asm volatile( 1198c2ecf20Sopenharmony_ci "lbz %0,%1(13); stb %2,%1(13)" 1208c2ecf20Sopenharmony_ci : "=&r" (flags) 1218c2ecf20Sopenharmony_ci : "i" (offsetof(struct paca_struct, irq_soft_mask)), 1228c2ecf20Sopenharmony_ci "r" (mask) 1238c2ecf20Sopenharmony_ci : "memory"); 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci return flags; 1268c2ecf20Sopenharmony_ci} 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_cistatic inline notrace unsigned long irq_soft_mask_or_return(unsigned long mask) 1298c2ecf20Sopenharmony_ci{ 1308c2ecf20Sopenharmony_ci unsigned long flags, tmp; 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci asm volatile( 1338c2ecf20Sopenharmony_ci "lbz %0,%2(13); or %1,%0,%3; stb %1,%2(13)" 1348c2ecf20Sopenharmony_ci : "=&r" (flags), "=r" (tmp) 1358c2ecf20Sopenharmony_ci : "i" (offsetof(struct paca_struct, irq_soft_mask)), 1368c2ecf20Sopenharmony_ci "r" (mask) 1378c2ecf20Sopenharmony_ci : "memory"); 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC_IRQ_SOFT_MASK_DEBUG 1408c2ecf20Sopenharmony_ci WARN_ON((mask | flags) && !((mask | flags) & IRQS_DISABLED)); 1418c2ecf20Sopenharmony_ci#endif 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci return flags; 1448c2ecf20Sopenharmony_ci} 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_cistatic inline unsigned long arch_local_save_flags(void) 1478c2ecf20Sopenharmony_ci{ 1488c2ecf20Sopenharmony_ci return irq_soft_mask_return(); 1498c2ecf20Sopenharmony_ci} 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_cistatic inline void arch_local_irq_disable(void) 1528c2ecf20Sopenharmony_ci{ 1538c2ecf20Sopenharmony_ci irq_soft_mask_set(IRQS_DISABLED); 1548c2ecf20Sopenharmony_ci} 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ciextern void arch_local_irq_restore(unsigned long); 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_cistatic inline void arch_local_irq_enable(void) 1598c2ecf20Sopenharmony_ci{ 1608c2ecf20Sopenharmony_ci arch_local_irq_restore(IRQS_ENABLED); 1618c2ecf20Sopenharmony_ci} 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_cistatic inline unsigned long arch_local_irq_save(void) 1648c2ecf20Sopenharmony_ci{ 1658c2ecf20Sopenharmony_ci return irq_soft_mask_set_return(IRQS_DISABLED); 1668c2ecf20Sopenharmony_ci} 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_cistatic inline bool arch_irqs_disabled_flags(unsigned long flags) 1698c2ecf20Sopenharmony_ci{ 1708c2ecf20Sopenharmony_ci return flags & IRQS_DISABLED; 1718c2ecf20Sopenharmony_ci} 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_cistatic inline bool arch_irqs_disabled(void) 1748c2ecf20Sopenharmony_ci{ 1758c2ecf20Sopenharmony_ci return arch_irqs_disabled_flags(arch_local_save_flags()); 1768c2ecf20Sopenharmony_ci} 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_cistatic inline void set_pmi_irq_pending(void) 1798c2ecf20Sopenharmony_ci{ 1808c2ecf20Sopenharmony_ci /* 1818c2ecf20Sopenharmony_ci * Invoked from PMU callback functions to set PMI bit in the paca. 1828c2ecf20Sopenharmony_ci * This has to be called with irq's disabled (via hard_irq_disable()). 1838c2ecf20Sopenharmony_ci */ 1848c2ecf20Sopenharmony_ci if (IS_ENABLED(CONFIG_PPC_IRQ_SOFT_MASK_DEBUG)) 1858c2ecf20Sopenharmony_ci WARN_ON_ONCE(mfmsr() & MSR_EE); 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci get_paca()->irq_happened |= PACA_IRQ_PMI; 1888c2ecf20Sopenharmony_ci} 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_cistatic inline void clear_pmi_irq_pending(void) 1918c2ecf20Sopenharmony_ci{ 1928c2ecf20Sopenharmony_ci /* 1938c2ecf20Sopenharmony_ci * Invoked from PMU callback functions to clear the pending PMI bit 1948c2ecf20Sopenharmony_ci * in the paca. 1958c2ecf20Sopenharmony_ci */ 1968c2ecf20Sopenharmony_ci if (IS_ENABLED(CONFIG_PPC_IRQ_SOFT_MASK_DEBUG)) 1978c2ecf20Sopenharmony_ci WARN_ON_ONCE(mfmsr() & MSR_EE); 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_ci get_paca()->irq_happened &= ~PACA_IRQ_PMI; 2008c2ecf20Sopenharmony_ci} 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_cistatic inline bool pmi_irq_pending(void) 2038c2ecf20Sopenharmony_ci{ 2048c2ecf20Sopenharmony_ci /* 2058c2ecf20Sopenharmony_ci * Invoked from PMU callback functions to check if there is a pending 2068c2ecf20Sopenharmony_ci * PMI bit in the paca. 2078c2ecf20Sopenharmony_ci */ 2088c2ecf20Sopenharmony_ci if (get_paca()->irq_happened & PACA_IRQ_PMI) 2098c2ecf20Sopenharmony_ci return true; 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci return false; 2128c2ecf20Sopenharmony_ci} 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC_BOOK3S 2158c2ecf20Sopenharmony_ci/* 2168c2ecf20Sopenharmony_ci * To support disabling and enabling of irq with PMI, set of 2178c2ecf20Sopenharmony_ci * new powerpc_local_irq_pmu_save() and powerpc_local_irq_restore() 2188c2ecf20Sopenharmony_ci * functions are added. These macros are implemented using generic 2198c2ecf20Sopenharmony_ci * linux local_irq_* code from include/linux/irqflags.h. 2208c2ecf20Sopenharmony_ci */ 2218c2ecf20Sopenharmony_ci#define raw_local_irq_pmu_save(flags) \ 2228c2ecf20Sopenharmony_ci do { \ 2238c2ecf20Sopenharmony_ci typecheck(unsigned long, flags); \ 2248c2ecf20Sopenharmony_ci flags = irq_soft_mask_or_return(IRQS_DISABLED | \ 2258c2ecf20Sopenharmony_ci IRQS_PMI_DISABLED); \ 2268c2ecf20Sopenharmony_ci } while(0) 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci#define raw_local_irq_pmu_restore(flags) \ 2298c2ecf20Sopenharmony_ci do { \ 2308c2ecf20Sopenharmony_ci typecheck(unsigned long, flags); \ 2318c2ecf20Sopenharmony_ci arch_local_irq_restore(flags); \ 2328c2ecf20Sopenharmony_ci } while(0) 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ci#ifdef CONFIG_TRACE_IRQFLAGS 2358c2ecf20Sopenharmony_ci#define powerpc_local_irq_pmu_save(flags) \ 2368c2ecf20Sopenharmony_ci do { \ 2378c2ecf20Sopenharmony_ci raw_local_irq_pmu_save(flags); \ 2388c2ecf20Sopenharmony_ci if (!raw_irqs_disabled_flags(flags)) \ 2398c2ecf20Sopenharmony_ci trace_hardirqs_off(); \ 2408c2ecf20Sopenharmony_ci } while(0) 2418c2ecf20Sopenharmony_ci#define powerpc_local_irq_pmu_restore(flags) \ 2428c2ecf20Sopenharmony_ci do { \ 2438c2ecf20Sopenharmony_ci if (!raw_irqs_disabled_flags(flags)) \ 2448c2ecf20Sopenharmony_ci trace_hardirqs_on(); \ 2458c2ecf20Sopenharmony_ci raw_local_irq_pmu_restore(flags); \ 2468c2ecf20Sopenharmony_ci } while(0) 2478c2ecf20Sopenharmony_ci#else 2488c2ecf20Sopenharmony_ci#define powerpc_local_irq_pmu_save(flags) \ 2498c2ecf20Sopenharmony_ci do { \ 2508c2ecf20Sopenharmony_ci raw_local_irq_pmu_save(flags); \ 2518c2ecf20Sopenharmony_ci } while(0) 2528c2ecf20Sopenharmony_ci#define powerpc_local_irq_pmu_restore(flags) \ 2538c2ecf20Sopenharmony_ci do { \ 2548c2ecf20Sopenharmony_ci raw_local_irq_pmu_restore(flags); \ 2558c2ecf20Sopenharmony_ci } while (0) 2568c2ecf20Sopenharmony_ci#endif /* CONFIG_TRACE_IRQFLAGS */ 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci#endif /* CONFIG_PPC_BOOK3S */ 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC_BOOK3E 2618c2ecf20Sopenharmony_ci#define __hard_irq_enable() wrtee(MSR_EE) 2628c2ecf20Sopenharmony_ci#define __hard_irq_disable() wrtee(0) 2638c2ecf20Sopenharmony_ci#define __hard_EE_RI_disable() wrtee(0) 2648c2ecf20Sopenharmony_ci#define __hard_RI_enable() do { } while (0) 2658c2ecf20Sopenharmony_ci#else 2668c2ecf20Sopenharmony_ci#define __hard_irq_enable() __mtmsrd(MSR_EE|MSR_RI, 1) 2678c2ecf20Sopenharmony_ci#define __hard_irq_disable() __mtmsrd(MSR_RI, 1) 2688c2ecf20Sopenharmony_ci#define __hard_EE_RI_disable() __mtmsrd(0, 1) 2698c2ecf20Sopenharmony_ci#define __hard_RI_enable() __mtmsrd(MSR_RI, 1) 2708c2ecf20Sopenharmony_ci#endif 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci#define hard_irq_disable() do { \ 2738c2ecf20Sopenharmony_ci unsigned long flags; \ 2748c2ecf20Sopenharmony_ci __hard_irq_disable(); \ 2758c2ecf20Sopenharmony_ci flags = irq_soft_mask_set_return(IRQS_ALL_DISABLED); \ 2768c2ecf20Sopenharmony_ci local_paca->irq_happened |= PACA_IRQ_HARD_DIS; \ 2778c2ecf20Sopenharmony_ci if (!arch_irqs_disabled_flags(flags)) { \ 2788c2ecf20Sopenharmony_ci asm ("stdx %%r1, 0, %1 ;" \ 2798c2ecf20Sopenharmony_ci : "=m" (local_paca->saved_r1) \ 2808c2ecf20Sopenharmony_ci : "b" (&local_paca->saved_r1)); \ 2818c2ecf20Sopenharmony_ci trace_hardirqs_off(); \ 2828c2ecf20Sopenharmony_ci } \ 2838c2ecf20Sopenharmony_ci} while(0) 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_cistatic inline bool __lazy_irq_pending(u8 irq_happened) 2868c2ecf20Sopenharmony_ci{ 2878c2ecf20Sopenharmony_ci return !!(irq_happened & ~PACA_IRQ_HARD_DIS); 2888c2ecf20Sopenharmony_ci} 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci/* 2918c2ecf20Sopenharmony_ci * Check if a lazy IRQ is pending. Should be called with IRQs hard disabled. 2928c2ecf20Sopenharmony_ci */ 2938c2ecf20Sopenharmony_cistatic inline bool lazy_irq_pending(void) 2948c2ecf20Sopenharmony_ci{ 2958c2ecf20Sopenharmony_ci return __lazy_irq_pending(get_paca()->irq_happened); 2968c2ecf20Sopenharmony_ci} 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci/* 2998c2ecf20Sopenharmony_ci * Check if a lazy IRQ is pending, with no debugging checks. 3008c2ecf20Sopenharmony_ci * Should be called with IRQs hard disabled. 3018c2ecf20Sopenharmony_ci * For use in RI disabled code or other constrained situations. 3028c2ecf20Sopenharmony_ci */ 3038c2ecf20Sopenharmony_cistatic inline bool lazy_irq_pending_nocheck(void) 3048c2ecf20Sopenharmony_ci{ 3058c2ecf20Sopenharmony_ci return __lazy_irq_pending(local_paca->irq_happened); 3068c2ecf20Sopenharmony_ci} 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_ci/* 3098c2ecf20Sopenharmony_ci * This is called by asynchronous interrupts to conditionally 3108c2ecf20Sopenharmony_ci * re-enable hard interrupts after having cleared the source 3118c2ecf20Sopenharmony_ci * of the interrupt. They are kept disabled if there is a different 3128c2ecf20Sopenharmony_ci * soft-masked interrupt pending that requires hard masking. 3138c2ecf20Sopenharmony_ci */ 3148c2ecf20Sopenharmony_cistatic inline void may_hard_irq_enable(void) 3158c2ecf20Sopenharmony_ci{ 3168c2ecf20Sopenharmony_ci if (!(get_paca()->irq_happened & PACA_IRQ_MUST_HARD_MASK)) { 3178c2ecf20Sopenharmony_ci get_paca()->irq_happened &= ~PACA_IRQ_HARD_DIS; 3188c2ecf20Sopenharmony_ci __hard_irq_enable(); 3198c2ecf20Sopenharmony_ci } 3208c2ecf20Sopenharmony_ci} 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_cistatic inline bool arch_irq_disabled_regs(struct pt_regs *regs) 3238c2ecf20Sopenharmony_ci{ 3248c2ecf20Sopenharmony_ci return (regs->softe & IRQS_DISABLED); 3258c2ecf20Sopenharmony_ci} 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ciextern bool prep_irq_for_idle(void); 3288c2ecf20Sopenharmony_ciextern bool prep_irq_for_idle_irqsoff(void); 3298c2ecf20Sopenharmony_ciextern void irq_set_pending_from_srr1(unsigned long srr1); 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_ci#define fini_irq_for_idle_irqsoff() trace_hardirqs_off(); 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_ciextern void force_external_irq_replay(void); 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_cistatic inline void irq_soft_mask_regs_set_state(struct pt_regs *regs, unsigned long val) 3368c2ecf20Sopenharmony_ci{ 3378c2ecf20Sopenharmony_ci regs->softe = val; 3388c2ecf20Sopenharmony_ci} 3398c2ecf20Sopenharmony_ci#else /* CONFIG_PPC64 */ 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_cistatic inline unsigned long arch_local_save_flags(void) 3428c2ecf20Sopenharmony_ci{ 3438c2ecf20Sopenharmony_ci return mfmsr(); 3448c2ecf20Sopenharmony_ci} 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_cistatic inline void arch_local_irq_restore(unsigned long flags) 3478c2ecf20Sopenharmony_ci{ 3488c2ecf20Sopenharmony_ci if (IS_ENABLED(CONFIG_BOOKE)) 3498c2ecf20Sopenharmony_ci wrtee(flags); 3508c2ecf20Sopenharmony_ci else 3518c2ecf20Sopenharmony_ci mtmsr(flags); 3528c2ecf20Sopenharmony_ci} 3538c2ecf20Sopenharmony_ci 3548c2ecf20Sopenharmony_cistatic inline unsigned long arch_local_irq_save(void) 3558c2ecf20Sopenharmony_ci{ 3568c2ecf20Sopenharmony_ci unsigned long flags = arch_local_save_flags(); 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_ci if (IS_ENABLED(CONFIG_BOOKE)) 3598c2ecf20Sopenharmony_ci wrtee(0); 3608c2ecf20Sopenharmony_ci else if (IS_ENABLED(CONFIG_PPC_8xx)) 3618c2ecf20Sopenharmony_ci wrtspr(SPRN_EID); 3628c2ecf20Sopenharmony_ci else 3638c2ecf20Sopenharmony_ci mtmsr(flags & ~MSR_EE); 3648c2ecf20Sopenharmony_ci 3658c2ecf20Sopenharmony_ci return flags; 3668c2ecf20Sopenharmony_ci} 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_cistatic inline void arch_local_irq_disable(void) 3698c2ecf20Sopenharmony_ci{ 3708c2ecf20Sopenharmony_ci if (IS_ENABLED(CONFIG_BOOKE)) 3718c2ecf20Sopenharmony_ci wrtee(0); 3728c2ecf20Sopenharmony_ci else if (IS_ENABLED(CONFIG_PPC_8xx)) 3738c2ecf20Sopenharmony_ci wrtspr(SPRN_EID); 3748c2ecf20Sopenharmony_ci else 3758c2ecf20Sopenharmony_ci mtmsr(mfmsr() & ~MSR_EE); 3768c2ecf20Sopenharmony_ci} 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_cistatic inline void arch_local_irq_enable(void) 3798c2ecf20Sopenharmony_ci{ 3808c2ecf20Sopenharmony_ci if (IS_ENABLED(CONFIG_BOOKE)) 3818c2ecf20Sopenharmony_ci wrtee(MSR_EE); 3828c2ecf20Sopenharmony_ci else if (IS_ENABLED(CONFIG_PPC_8xx)) 3838c2ecf20Sopenharmony_ci wrtspr(SPRN_EIE); 3848c2ecf20Sopenharmony_ci else 3858c2ecf20Sopenharmony_ci mtmsr(mfmsr() | MSR_EE); 3868c2ecf20Sopenharmony_ci} 3878c2ecf20Sopenharmony_ci 3888c2ecf20Sopenharmony_cistatic inline bool arch_irqs_disabled_flags(unsigned long flags) 3898c2ecf20Sopenharmony_ci{ 3908c2ecf20Sopenharmony_ci return (flags & MSR_EE) == 0; 3918c2ecf20Sopenharmony_ci} 3928c2ecf20Sopenharmony_ci 3938c2ecf20Sopenharmony_cistatic inline bool arch_irqs_disabled(void) 3948c2ecf20Sopenharmony_ci{ 3958c2ecf20Sopenharmony_ci return arch_irqs_disabled_flags(arch_local_save_flags()); 3968c2ecf20Sopenharmony_ci} 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_ci#define hard_irq_disable() arch_local_irq_disable() 3998c2ecf20Sopenharmony_ci 4008c2ecf20Sopenharmony_cistatic inline bool arch_irq_disabled_regs(struct pt_regs *regs) 4018c2ecf20Sopenharmony_ci{ 4028c2ecf20Sopenharmony_ci return !(regs->msr & MSR_EE); 4038c2ecf20Sopenharmony_ci} 4048c2ecf20Sopenharmony_ci 4058c2ecf20Sopenharmony_cistatic inline void may_hard_irq_enable(void) { } 4068c2ecf20Sopenharmony_ci 4078c2ecf20Sopenharmony_cistatic inline void clear_pmi_irq_pending(void) { } 4088c2ecf20Sopenharmony_cistatic inline void set_pmi_irq_pending(void) { } 4098c2ecf20Sopenharmony_cistatic inline bool pmi_irq_pending(void) { return false; } 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_cistatic inline void irq_soft_mask_regs_set_state(struct pt_regs *regs, unsigned long val) 4128c2ecf20Sopenharmony_ci{ 4138c2ecf20Sopenharmony_ci} 4148c2ecf20Sopenharmony_ci#endif /* CONFIG_PPC64 */ 4158c2ecf20Sopenharmony_ci 4168c2ecf20Sopenharmony_ci#define ARCH_IRQ_INIT_FLAGS IRQ_NOREQUEST 4178c2ecf20Sopenharmony_ci 4188c2ecf20Sopenharmony_ci#endif /* __ASSEMBLY__ */ 4198c2ecf20Sopenharmony_ci#endif /* __KERNEL__ */ 4208c2ecf20Sopenharmony_ci#endif /* _ASM_POWERPC_HW_IRQ_H */ 421