Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

powerpc/64: Refactor interrupt exit irq disabling sequence

The same complicated sequence for juggling EE, RI, soft mask, and
irq tracing is repeated 3 times, tidy these up into one function.

This differs qiute a bit between sub architectures, so this makes
the ppc32 port cleaner as well.

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20200429062421.1675400-1-npiggin@gmail.com

authored by

Nicholas Piggin and committed by
Michael Ellerman
0bdad33d 18594f9b

+28 -30
+28 -30
arch/powerpc/kernel/syscall_64.c
··· 102 102 } 103 103 104 104 /* 105 + * local irqs must be disabled. Returns false if the caller must re-enable 106 + * them, check for new work, and try again. 107 + */ 108 + static notrace inline bool prep_irq_for_enabled_exit(void) 109 + { 110 + /* This must be done with RI=1 because tracing may touch vmaps */ 111 + trace_hardirqs_on(); 112 + 113 + /* This pattern matches prep_irq_for_idle */ 114 + __hard_EE_RI_disable(); 115 + if (unlikely(lazy_irq_pending_nocheck())) { 116 + /* Took an interrupt, may have more exit work to do. */ 117 + __hard_RI_enable(); 118 + trace_hardirqs_off(); 119 + local_paca->irq_happened |= PACA_IRQ_HARD_DIS; 120 + 121 + return false; 122 + } 123 + local_paca->irq_happened = 0; 124 + irq_soft_mask_set(IRQS_ENABLED); 125 + 126 + return true; 127 + } 128 + 129 + /* 105 130 * This should be called after a syscall returns, with r3 the return value 106 131 * from the syscall. If this function returns non-zero, the system call 107 132 * exit assembly should additionally load all GPR registers and CTR and XER ··· 211 186 } 212 187 } 213 188 214 - /* This must be done with RI=1 because tracing may touch vmaps */ 215 - trace_hardirqs_on(); 216 - 217 - /* This pattern matches prep_irq_for_idle */ 218 - __hard_EE_RI_disable(); 219 - if (unlikely(lazy_irq_pending_nocheck())) { 220 - __hard_RI_enable(); 221 - trace_hardirqs_off(); 222 - local_paca->irq_happened |= PACA_IRQ_HARD_DIS; 189 + if (unlikely(!prep_irq_for_enabled_exit())) { 223 190 local_irq_enable(); 224 - /* Took an interrupt, may have more exit work to do. */ 225 191 goto again; 226 192 } 227 - local_paca->irq_happened = 0; 228 - irq_soft_mask_set(IRQS_ENABLED); 229 193 230 194 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM 231 195 local_paca->tm_scratch = regs->msr; ··· 278 264 } 279 265 } 280 266 281 - trace_hardirqs_on(); 282 - __hard_EE_RI_disable(); 283 - if (unlikely(lazy_irq_pending_nocheck())) { 284 - __hard_RI_enable(); 285 - trace_hardirqs_off(); 286 - local_paca->irq_happened |= PACA_IRQ_HARD_DIS; 267 + if (unlikely(!prep_irq_for_enabled_exit())) { 287 268 local_irq_enable(); 288 269 local_irq_disable(); 289 - /* Took an interrupt, may have more exit work to do. */ 290 270 goto again; 291 271 } 292 - local_paca->irq_happened = 0; 293 - irq_soft_mask_set(IRQS_ENABLED); 294 272 295 273 #ifdef CONFIG_PPC_BOOK3E 296 274 if (unlikely(ts->debug.dbcr0 & DBCR0_IDM)) { ··· 340 334 } 341 335 } 342 336 343 - trace_hardirqs_on(); 344 - __hard_EE_RI_disable(); 345 - if (unlikely(lazy_irq_pending_nocheck())) { 346 - __hard_RI_enable(); 347 - irq_soft_mask_set(IRQS_ALL_DISABLED); 348 - trace_hardirqs_off(); 349 - local_paca->irq_happened |= PACA_IRQ_HARD_DIS; 337 + if (unlikely(!prep_irq_for_enabled_exit())) { 350 338 /* 351 339 * Can't local_irq_restore to replay if we were in 352 340 * interrupt context. Must replay directly. ··· 354 354 /* Took an interrupt, may have more exit work to do. */ 355 355 goto again; 356 356 } 357 - local_paca->irq_happened = 0; 358 - irq_soft_mask_set(IRQS_ENABLED); 359 357 } else { 360 358 /* Returning to a kernel context with local irqs disabled. */ 361 359 __hard_EE_RI_disable();