* [PATCH 10/14] powerpc/64: use interrupt restart table to speed up return from interrupt
From: Nicholas Piggin @ 2021-03-15 22:03 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Nicholas Piggin
In-Reply-To: <20210315220402.260594-1-npiggin@gmail.com>
The restart table facility is used to return from interrupt without
disabling MSR EE or RI.
Interrupt return code is put into the low soft-masked region.
Critical code that has no exit work, SRRs set, soft-masked state set to
return state, saves r1 in the PACA and then begins to run instructions
that have an alternate return handler.
In this region, pending interrupts are checked, and if any exist then
it branches directly to the restart handler.
If it does not branch, then no masked interrupts are pending, and if any
interrupts do hit, we will go out the restart handler.
The restart handler re-loads the saved r1, and from there we can find
regs, and reload critical state before setting things up to replay
interrupts and go around the exit prepare sequence again.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/include/asm/paca.h | 1 +
arch/powerpc/include/asm/ptrace.h | 4 +-
arch/powerpc/kernel/asm-offsets.c | 1 +
arch/powerpc/kernel/interrupt.c | 282 ++++++++++++++++-------------
arch/powerpc/kernel/interrupt_64.S | 118 +++++++++++-
5 files changed, 270 insertions(+), 136 deletions(-)
diff --git a/arch/powerpc/include/asm/paca.h b/arch/powerpc/include/asm/paca.h
index 4cbfaa09950a..039ccedcfcdb 100644
--- a/arch/powerpc/include/asm/paca.h
+++ b/arch/powerpc/include/asm/paca.h
@@ -167,6 +167,7 @@ struct paca_struct {
u64 kstack; /* Saved Kernel stack addr */
u64 saved_r1; /* r1 save for RTAS calls or PM or EE=0 */
u64 saved_msr; /* MSR saved here by enter_rtas */
+ u64 exit_save_r1; /* Syscall/interrupt R1 save */
#ifdef CONFIG_PPC_BOOK3E
u16 trap_save; /* Used when bad stack is encountered */
#endif
diff --git a/arch/powerpc/include/asm/ptrace.h b/arch/powerpc/include/asm/ptrace.h
index 77c86ce01f20..d37787a74342 100644
--- a/arch/powerpc/include/asm/ptrace.h
+++ b/arch/powerpc/include/asm/ptrace.h
@@ -52,6 +52,7 @@ struct pt_regs
struct {
#ifdef CONFIG_PPC64
unsigned long ppr;
+ unsigned long exit_result;
#endif
union {
#ifdef CONFIG_PPC_KUAP
@@ -65,7 +66,8 @@ struct pt_regs
unsigned long iamr;
#endif
};
- unsigned long __pad[4]; /* Maintain 16 byte interrupt stack alignment */
+ /* Maintain 16 byte interrupt stack alignment */
+ unsigned long __pad[4];
};
};
#endif
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index 35ce6e36f593..44d557dacc77 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -288,6 +288,7 @@ int main(void)
OFFSET(ACCOUNT_STARTTIME_USER, paca_struct, accounting.starttime_user);
OFFSET(ACCOUNT_USER_TIME, paca_struct, accounting.utime);
OFFSET(ACCOUNT_SYSTEM_TIME, paca_struct, accounting.stime);
+ OFFSET(PACA_EXIT_SAVE_R1, paca_struct, exit_save_r1);
#ifdef CONFIG_PPC_BOOK3E
OFFSET(PACA_TRAP_SAVE, paca_struct, trap_save);
#endif
diff --git a/arch/powerpc/kernel/interrupt.c b/arch/powerpc/kernel/interrupt.c
index efeeefe6ee8f..09cf699d0e2e 100644
--- a/arch/powerpc/kernel/interrupt.c
+++ b/arch/powerpc/kernel/interrupt.c
@@ -147,71 +147,6 @@ notrace long system_call_exception(long r3, long r4, long r5,
return f(r3, r4, r5, r6, r7, r8);
}
-/*
- * local irqs must be disabled. Returns false if the caller must re-enable
- * them, check for new work, and try again.
- *
- * This should be called with local irqs disabled, but if they were previously
- * enabled when the interrupt handler returns (indicating a process-context /
- * synchronous interrupt) then irqs_enabled should be true.
- */
-static notrace __always_inline bool __prep_irq_for_enabled_exit(bool clear_ri)
-{
- /* This must be done with RI=1 because tracing may touch vmaps */
- trace_hardirqs_on();
-
- /* This pattern matches prep_irq_for_idle */
- if (clear_ri)
- __hard_EE_RI_disable();
- else
- __hard_irq_disable();
-#ifdef CONFIG_PPC64
- if (unlikely(lazy_irq_pending_nocheck())) {
- /* Took an interrupt, may have more exit work to do. */
- if (clear_ri)
- __hard_RI_enable();
- trace_hardirqs_off();
- local_paca->irq_happened |= PACA_IRQ_HARD_DIS;
-
- return false;
- }
- local_paca->irq_happened = 0;
- irq_soft_mask_set(IRQS_ENABLED);
-#endif
- return true;
-}
-
-static notrace inline bool prep_irq_for_enabled_exit(bool clear_ri, bool irqs_enabled)
-{
- if (__prep_irq_for_enabled_exit(clear_ri))
- return true;
-
- /*
- * Must replay pending soft-masked interrupts now. Don't just
- * local_irq_enabe(); local_irq_disable(); because if we are
- * returning from an asynchronous interrupt here, another one
- * might hit after irqs are enabled, and it would exit via this
- * same path allowing another to fire, and so on unbounded.
- *
- * If interrupts were enabled when this interrupt exited,
- * indicating a process context (synchronous) interrupt,
- * local_irq_enable/disable can be used, which will enable
- * interrupts rather than keeping them masked (unclear how
- * much benefit this is over just replaying for all cases,
- * because we immediately disable again, so all we're really
- * doing is allowing hard interrupts to execute directly for
- * a very small time, rather than being masked and replayed).
- */
- if (irqs_enabled) {
- local_irq_enable();
- local_irq_disable();
- } else {
- replay_soft_interrupts();
- }
-
- return false;
-}
-
static notrace void booke_load_dbcr0(void)
{
#ifdef CONFIG_PPC_ADV_DEBUG_REGS
@@ -234,57 +169,11 @@ static notrace void booke_load_dbcr0(void)
#endif
}
-/*
- * This should be called after a syscall returns, with r3 the return value
- * from the syscall. If this function returns non-zero, the system call
- * exit assembly should additionally load all GPR registers and CTR and XER
- * from the interrupt frame.
- *
- * The function graph tracer can not trace the return side of this function,
- * because RI=0 and soft mask state is "unreconciled", so it is marked notrace.
- */
-notrace unsigned long syscall_exit_prepare(unsigned long r3,
- struct pt_regs *regs,
- long scv)
+notrace unsigned long syscall_exit_prepare_main(unsigned long r3,
+ struct pt_regs *regs)
{
unsigned long ti_flags;
unsigned long ret = 0;
- bool is_not_scv = !IS_ENABLED(CONFIG_PPC_BOOK3S_64) || !scv;
-
- CT_WARN_ON(ct_state() == CONTEXT_USER);
-
- kuap_assert_locked();
-
- regs->result = r3;
-
- /* Check whether the syscall is issued inside a restartable sequence */
- rseq_syscall(regs);
-
- ti_flags = current_thread_info()->flags;
-
- if (unlikely(r3 >= (unsigned long)-MAX_ERRNO) && is_not_scv) {
- if (likely(!(ti_flags & (_TIF_NOERROR | _TIF_RESTOREALL)))) {
- r3 = -r3;
- regs->ccr |= 0x10000000; /* Set SO bit in CR */
- }
- }
-
- if (unlikely(ti_flags & _TIF_PERSYSCALL_MASK)) {
- if (ti_flags & _TIF_RESTOREALL)
- ret = _TIF_RESTOREALL;
- else
- regs->gpr[3] = r3;
- clear_bits(_TIF_PERSYSCALL_MASK, ¤t_thread_info()->flags);
- } else {
- regs->gpr[3] = r3;
- }
-
- if (unlikely(ti_flags & _TIF_SYSCALL_DOTRACE)) {
- do_syscall_trace_leave(regs);
- ret |= _TIF_RESTOREALL;
- }
-
- local_irq_disable();
again:
ti_flags = READ_ONCE(current_thread_info()->flags);
@@ -330,16 +219,16 @@ notrace unsigned long syscall_exit_prepare(unsigned long r3,
}
}
- user_enter_irqoff();
-
/* scv need not set RI=0 because SRRs are not used */
- if (unlikely(!__prep_irq_for_enabled_exit(is_not_scv))) {
- user_exit_irqoff();
+ if (unlikely(lazy_irq_pending_nocheck())) {
local_irq_enable();
local_irq_disable();
goto again;
}
+ user_enter_irqoff();
+ trace_hardirqs_on();
+
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
local_paca->tm_scratch = regs->msr;
#endif
@@ -359,6 +248,84 @@ notrace unsigned long syscall_exit_prepare(unsigned long r3,
return ret;
}
+/*
+ * This should be called after a syscall returns, with r3 the return value
+ * from the syscall. If this function returns non-zero, the system call
+ * exit assembly should additionally load all GPR registers and CTR and XER
+ * from the interrupt frame.
+ *
+ * The function graph tracer can not trace the return side of this function,
+ * because RI=0 and soft mask state is "unreconciled", so it is marked notrace.
+ */
+notrace unsigned long syscall_exit_prepare(unsigned long r3,
+ struct pt_regs *regs,
+ long scv)
+{
+ unsigned long ti_flags;
+ unsigned long ret = 0;
+ bool is_not_scv = !IS_ENABLED(CONFIG_PPC_BOOK3S_64) || !scv;
+
+ CT_WARN_ON(ct_state() == CONTEXT_USER);
+
+ kuap_assert_locked();
+
+ regs->result = r3;
+
+ /* Check whether the syscall is issued inside a restartable sequence */
+ rseq_syscall(regs);
+
+ ti_flags = current_thread_info()->flags;
+
+ if (unlikely(r3 >= (unsigned long)-MAX_ERRNO) && is_not_scv) {
+ if (likely(!(ti_flags & (_TIF_NOERROR | _TIF_RESTOREALL)))) {
+ r3 = -r3;
+ regs->ccr |= 0x10000000; /* Set SO bit in CR */
+ }
+ }
+
+ if (unlikely(ti_flags & _TIF_PERSYSCALL_MASK)) {
+ if (ti_flags & _TIF_RESTOREALL)
+ ret = _TIF_RESTOREALL;
+ else
+ regs->gpr[3] = r3;
+ clear_bits(_TIF_PERSYSCALL_MASK, ¤t_thread_info()->flags);
+ } else {
+ regs->gpr[3] = r3;
+ }
+
+ if (unlikely(ti_flags & _TIF_SYSCALL_DOTRACE)) {
+ do_syscall_trace_leave(regs);
+ ret |= _TIF_RESTOREALL;
+ }
+
+ local_irq_disable();
+ ret |= syscall_exit_prepare_main(r3, regs);
+
+ regs->exit_result = ret;
+
+ return ret;
+}
+
+notrace unsigned long syscall_exit_restart(unsigned long r3, struct pt_regs *regs)
+{
+ /* This is called in when detecting a soft-pending interrupt as well,
+ * so can't just have restart table returns clear SRR1[MSR] and set
+ * PACA_IRQ_HARD_DIS here (unless the soft-pending case were to clear
+ * MSR[EE] too).
+ */
+ hard_irq_disable();
+
+ trace_hardirqs_off();
+ user_exit_irqoff();
+ account_cpu_user_entry();
+
+ BUG_ON(!user_mode(regs));
+
+ regs->exit_result |= syscall_exit_prepare_main(r3, regs);
+
+ return regs->exit_result;
+}
+
notrace unsigned long interrupt_exit_user_prepare(struct pt_regs *regs)
{
unsigned long ti_flags;
@@ -414,15 +381,15 @@ notrace unsigned long interrupt_exit_user_prepare(struct pt_regs *regs)
}
}
- user_enter_irqoff();
-
- if (unlikely(!__prep_irq_for_enabled_exit(true))) {
- user_exit_irqoff();
+ if (unlikely(lazy_irq_pending_nocheck())) {
local_irq_enable();
local_irq_disable();
goto again;
}
+ user_enter_irqoff();
+ trace_hardirqs_on();
+
booke_load_dbcr0();
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
@@ -437,6 +404,7 @@ notrace unsigned long interrupt_exit_user_prepare(struct pt_regs *regs)
#ifndef CONFIG_PPC_BOOK3E_64
kuap_user_restore(regs);
#endif
+ regs->exit_result = ret;
return ret;
}
@@ -466,11 +434,6 @@ notrace unsigned long interrupt_exit_kernel_prepare(struct pt_regs *regs)
kuap = kuap_get_and_assert_locked();
#endif
- if (unlikely(current_thread_info()->flags & _TIF_EMULATE_STACK_STORE)) {
- clear_bits(_TIF_EMULATE_STACK_STORE, ¤t_thread_info()->flags);
- ret = 1;
- }
-
local_irq_save(flags);
if (!arch_irq_disabled_regs(regs)) {
@@ -485,17 +448,42 @@ notrace unsigned long interrupt_exit_kernel_prepare(struct pt_regs *regs)
}
}
- if (unlikely(!prep_irq_for_enabled_exit(true, !irqs_disabled_flags(flags))))
+ /*
+ * May replay pending soft-masked interrupts now. Don't just
+ * local_irq_enabe(); local_irq_disable(); because if we are
+ * returning from an asynchronous interrupt here, another one
+ * might hit after irqs are enabled, and it would exit via this
+ * same path allowing another to fire, and so on unbounded.
+ */
+ if (unlikely(lazy_irq_pending_nocheck())) {
+ hard_irq_disable();
+ replay_soft_interrupts();
+ /* Took an interrupt, may have more exit work to do. */
goto again;
+ }
+ local_paca->irq_happened &= ~PACA_IRQ_HARD_DIS;
+
+ trace_hardirqs_on();
} else {
- /* Returning to a kernel context with local irqs disabled. */
- __hard_EE_RI_disable();
#ifdef CONFIG_PPC64
+ /* Returning to a kernel context with local irqs disabled. */
if (regs->msr & MSR_EE)
local_paca->irq_happened &= ~PACA_IRQ_HARD_DIS;
#endif
}
+ if (unlikely(current_thread_info()->flags & _TIF_EMULATE_STACK_STORE)) {
+ /* Stack store can't be restarted (stack might have been clobbered) */
+ __hard_EE_RI_disable();
+ if (unlikely(lazy_irq_pending_nocheck()) && !arch_irq_disabled_regs(regs)) {
+ local_paca->irq_happened |= PACA_IRQ_HARD_DIS;
+ __hard_RI_enable();
+ goto again;
+ }
+
+ clear_bits(_TIF_EMULATE_STACK_STORE, ¤t_thread_info()->flags);
+ ret = 1;
+ }
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
local_paca->tm_scratch = regs->msr;
@@ -512,3 +500,39 @@ notrace unsigned long interrupt_exit_kernel_prepare(struct pt_regs *regs)
return ret;
}
+
+#ifdef CONFIG_PPC64
+notrace unsigned long interrupt_exit_user_restart(struct pt_regs *regs)
+{
+ hard_irq_disable();
+
+ trace_hardirqs_off();
+ user_exit_irqoff();
+ account_cpu_user_entry();
+
+ BUG_ON(!user_mode(regs));
+
+ regs->exit_result |= interrupt_exit_user_prepare(regs);
+
+ return regs->exit_result;
+}
+
+/* No real need to return a value here because the stack store can't be
+ * restarted
+ */
+notrace unsigned long interrupt_exit_kernel_restart(struct pt_regs *regs)
+{
+ hard_irq_disable();
+
+#ifndef CONFIG_PPC_BOOK3E_64
+ set_kuap(AMR_KUAP_BLOCKED);
+#endif
+
+ if (regs->softe == IRQS_ENABLED)
+ trace_hardirqs_off();
+
+ BUG_ON(user_mode(regs));
+
+ return interrupt_exit_kernel_prepare(regs);
+}
+#endif
diff --git a/arch/powerpc/kernel/interrupt_64.S b/arch/powerpc/kernel/interrupt_64.S
index c6a0349dde59..2b68b1dea8bf 100644
--- a/arch/powerpc/kernel/interrupt_64.S
+++ b/arch/powerpc/kernel/interrupt_64.S
@@ -119,9 +119,18 @@ END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
bl system_call_exception
.Lsyscall_vectored_\name\()_exit:
- addi r4,r1,STACK_FRAME_OVERHEAD
+ addi r4,r1,STACK_FRAME_OVERHEAD
li r5,1 /* scv */
bl syscall_exit_prepare
+ std r1,PACA_EXIT_SAVE_R1(r13) /* save r1 for restart */
+.Lsyscall_vectored_\name\()_rst_start:
+ lbz r11,PACAIRQHAPPENED(r13)
+ andi. r11,r11,(~PACA_IRQ_HARD_DIS)@l
+ bne- .Lsyscall_vectored_\name\()_restart
+ li r11,IRQS_ENABLED
+ stb r11,PACAIRQSOFTMASK(r13)
+ li r11,0
+ stb r11,PACAIRQHAPPENED(r13) # clear out possible HARD_DIS
EXIT_KERNEL_SECURITY_FALLBACK
@@ -173,8 +182,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
b . /* prevent speculative execution */
.Lsyscall_vectored_\name\()_restore_regs:
- li r3,0
- mtmsrd r3,1
mtspr SPRN_SRR0,r4
mtspr SPRN_SRR1,r5
@@ -192,9 +199,26 @@ END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
REST_2GPRS(12, r1)
ld r1,GPR1(r1)
RFI_TO_USER
+.Lsyscall_vectored_\name\()_rst_end:
+
+.Lsyscall_vectored_\name\()_restart:
+ GET_PACA(r13)
+ ld r1,PACA_EXIT_SAVE_R1(r13)
+ ld r2,PACATOC(r13)
+ ld r3,RESULT(r1)
+ addi r4,r1,STACK_FRAME_OVERHEAD
+ li r11,IRQS_ALL_DISABLED
+ stb r11,PACAIRQSOFTMASK(r13)
+ bl syscall_exit_restart
+ std r1,PACA_EXIT_SAVE_R1(r13) /* save r1 for restart */
+ b .Lsyscall_vectored_\name\()_rst_start
+
+RESTART_TABLE(.Lsyscall_vectored_\name\()_rst_start, .Lsyscall_vectored_\name\()_rst_end, .Lsyscall_vectored_\name\()_restart)
+
.endm
system_call_vectored common 0x3000
+
/*
* We instantiate another entry copy for the SIGILL variant, with TRAP=0x7ff0
* which is tested by system_call_exception when r0 is -1 (as set by vector
@@ -299,9 +323,18 @@ END_BTB_FLUSH_SECTION
bl system_call_exception
.Lsyscall_exit:
- addi r4,r1,STACK_FRAME_OVERHEAD
+ addi r4,r1,STACK_FRAME_OVERHEAD
li r5,0 /* !scv */
bl syscall_exit_prepare
+ std r1,PACA_EXIT_SAVE_R1(r13) /* save r1 for restart */
+.Lsyscall_rst_start:
+ lbz r11,PACAIRQHAPPENED(r13)
+ andi. r11,r11,(~PACA_IRQ_HARD_DIS)@l
+ bne- .Lsyscall_restart
+ li r11,IRQS_ENABLED
+ stb r11,PACAIRQSOFTMASK(r13)
+ li r11,0
+ stb r11,PACAIRQHAPPENED(r13) # clear out possible HARD_DIS
EXIT_KERNEL_SECURITY_FALLBACK
@@ -370,6 +403,21 @@ END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
REST_8GPRS(4, r1)
ld r12,GPR12(r1)
b .Lsyscall_restore_regs_cont
+.Lsyscall_rst_end:
+
+.Lsyscall_restart:
+ GET_PACA(r13)
+ ld r1,PACA_EXIT_SAVE_R1(r13)
+ ld r2,PACATOC(r13)
+ ld r3,RESULT(r1)
+ addi r4,r1,STACK_FRAME_OVERHEAD
+ li r11,IRQS_ALL_DISABLED
+ stb r11,PACAIRQSOFTMASK(r13)
+ bl syscall_exit_restart
+ std r1,PACA_EXIT_SAVE_R1(r13) /* save r1 for restart */
+ b .Lsyscall_rst_start
+
+RESTART_TABLE(.Lsyscall_rst_start, .Lsyscall_rst_end, .Lsyscall_restart)
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
.Ltabort_syscall:
@@ -462,13 +510,28 @@ _ASM_NOKPROBE_SYMBOL(interrupt_return_\srr\())
ld r4,_MSR(r1)
andi. r0,r4,MSR_PR
beq .Lkernel_interrupt_return_\srr
+.Linterrupt_return_\srr\()_user:
addi r3,r1,STACK_FRAME_OVERHEAD
bl interrupt_exit_user_prepare
cmpdi r3,0
bne- .Lrestore_nvgprs_\srr
-.Lfast_user_interrupt_return_\srr\():
+.Lrestore_nvgprs_\srr\()_cont:
EXIT_KERNEL_SECURITY_FALLBACK
+ std r1,PACA_EXIT_SAVE_R1(r13) /* save r1 for restart */
+.Linterrupt_return_\srr\()_user_rst_start:
+ lbz r11,PACAIRQHAPPENED(r13)
+ andi. r11,r11,(~PACA_IRQ_HARD_DIS)@l
+ bne- .Linterrupt_return_\srr\()_user_restart
+ li r11,IRQS_ENABLED
+ stb r11,PACAIRQSOFTMASK(r13)
+ li r11,0
+ stb r11,PACAIRQHAPPENED(r13) # clear out possible HARD_DIS
+
+.Lfast_user_interrupt_return_\srr\():
+ lbz r4,PACAIRQSOFTMASK(r13)
+ tdnei r4,IRQS_ENABLED
+
BEGIN_FTR_SECTION
ld r10,_PPR(r1)
mtspr SPRN_PPR,r10
@@ -534,16 +597,44 @@ ALT_FTR_SECTION_END_IFCLR(CPU_FTR_STCX_CHECKS_ADDRESS)
HRFI_TO_USER
.endif
b . /* prevent speculative execution */
+.Linterrupt_return_\srr\()_user_rst_end:
.Lrestore_nvgprs_\srr\():
REST_NVGPRS(r1)
- b .Lfast_user_interrupt_return_\srr
+ b .Lrestore_nvgprs_\srr\()_cont
+
+.Linterrupt_return_\srr\()_user_restart:
+ GET_PACA(r13)
+ ld r1,PACA_EXIT_SAVE_R1(r13)
+ ld r2,PACATOC(r13)
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ li r11,IRQS_ALL_DISABLED
+ stb r11,PACAIRQSOFTMASK(r13)
+ bl interrupt_exit_user_restart
+ std r1,PACA_EXIT_SAVE_R1(r13) /* save r1 for restart */
+ b .Linterrupt_return_\srr\()_user_rst_start
+
+RESTART_TABLE(.Linterrupt_return_\srr\()_user_rst_start, .Linterrupt_return_\srr\()_user_rst_end, .Linterrupt_return_\srr\()_user_restart)
.balign IFETCH_ALIGN_BYTES
.Lkernel_interrupt_return_\srr\():
+.Linterrupt_return_\srr\()_kernel:
addi r3,r1,STACK_FRAME_OVERHEAD
bl interrupt_exit_kernel_prepare
+ std r1,PACA_EXIT_SAVE_R1(r13) /* save r1 for restart */
+.Linterrupt_return_\srr\()_kernel_rst_start:
+ lbz r11,SOFTE(r1)
+ cmpwi r11,IRQS_ENABLED
+ stb r11,PACAIRQSOFTMASK(r13)
+ bne 1f
+ lbz r11,PACAIRQHAPPENED(r13)
+ andi. r11,r11,(~PACA_IRQ_HARD_DIS)@l
+ bne- .Linterrupt_return_\srr\()_kernel_restart
+ li r11,0
+ stb r11,PACAIRQHAPPENED(r13) # clear out possible HARD_DIS
+1:
+
.Lfast_kernel_interrupt_return_\srr\():
cmpdi cr1,r3,0
#ifdef CONFIG_PPC_BOOK3S
@@ -637,6 +728,21 @@ ALT_FTR_SECTION_END_IFCLR(CPU_FTR_STCX_CHECKS_ADDRESS)
HRFI_TO_KERNEL
.endif
b . /* prevent speculative execution */
+.Linterrupt_return_\srr\()_kernel_rst_end:
+
+.Linterrupt_return_\srr\()_kernel_restart:
+ GET_PACA(r13)
+ ld r1,PACA_EXIT_SAVE_R1(r13)
+ ld r2,PACATOC(r13)
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ li r11,IRQS_ALL_DISABLED
+ stb r11,PACAIRQSOFTMASK(r13)
+ bl interrupt_exit_kernel_restart
+ std r1,PACA_EXIT_SAVE_R1(r13) /* save r1 for restart */
+ b .Linterrupt_return_\srr\()_kernel_rst_start
+
+RESTART_TABLE(.Linterrupt_return_\srr\()_kernel_rst_start, .Linterrupt_return_\srr\()_kernel_rst_end, .Linterrupt_return_\srr\()_kernel_restart)
+
.endm
interrupt_return_macro srr
--
2.23.0
^ permalink raw reply related
* [PATCH 11/14] powerpc/64e: Remove PPR from pt_regs
From: Nicholas Piggin @ 2021-03-15 22:03 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Nicholas Piggin
In-Reply-To: <20210315220402.260594-1-npiggin@gmail.com>
64e does not have a PPR register.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/include/asm/ptrace.h | 4 +++-
arch/powerpc/kernel/asm-offsets.c | 2 ++
arch/powerpc/kernel/interrupt_64.S | 2 +-
3 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/include/asm/ptrace.h b/arch/powerpc/include/asm/ptrace.h
index d37787a74342..a59bdc020195 100644
--- a/arch/powerpc/include/asm/ptrace.h
+++ b/arch/powerpc/include/asm/ptrace.h
@@ -50,8 +50,10 @@ struct pt_regs
union {
struct {
-#ifdef CONFIG_PPC64
+#ifdef CONFIG_PPC_BOOK3S_64
unsigned long ppr;
+#endif
+#ifdef CONFIG_PPC64
unsigned long exit_result;
#endif
union {
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index 44d557dacc77..0b7828eff7ff 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -352,7 +352,9 @@ int main(void)
STACK_PT_REGS_OFFSET(_ESR, dsisr);
#else /* CONFIG_PPC64 */
STACK_PT_REGS_OFFSET(SOFTE, softe);
+#ifdef CONFIG_PPC_BOOK3S_64
STACK_PT_REGS_OFFSET(_PPR, ppr);
+#endif
#endif /* CONFIG_PPC64 */
#ifdef CONFIG_PPC_PKEY
diff --git a/arch/powerpc/kernel/interrupt_64.S b/arch/powerpc/kernel/interrupt_64.S
index 2b68b1dea8bf..f28f41a1a85a 100644
--- a/arch/powerpc/kernel/interrupt_64.S
+++ b/arch/powerpc/kernel/interrupt_64.S
@@ -532,12 +532,12 @@ _ASM_NOKPROBE_SYMBOL(interrupt_return_\srr\())
lbz r4,PACAIRQSOFTMASK(r13)
tdnei r4,IRQS_ENABLED
+#ifdef CONFIG_PPC_BOOK3S
BEGIN_FTR_SECTION
ld r10,_PPR(r1)
mtspr SPRN_PPR,r10
END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
-#ifdef CONFIG_PPC_BOOK3S
.ifc \srr,srr
lbz r4,PACASRR_VALID(r13)
.else
--
2.23.0
^ permalink raw reply related
* [PATCH 12/14] powerpc/64s: system call avoid setting MSR[RI] until we set MSR[EE]
From: Nicholas Piggin @ 2021-03-15 22:04 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Nicholas Piggin
In-Reply-To: <20210315220402.260594-1-npiggin@gmail.com>
This extends the MSR[RI]=0 window a little further into the system
call in order to pair RI and EE enabling with a single mtmsrd.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/kernel/exceptions-64s.S | 2 --
arch/powerpc/kernel/interrupt_64.S | 6 +++---
2 files changed, 3 insertions(+), 5 deletions(-)
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index bd0c82ac9de5..2f14ac3c377c 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -1999,8 +1999,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_REAL_LE)
mtctr r10
bctr
.else
- li r10,MSR_RI
- mtmsrd r10,1 /* Set RI (EE=0) */
#ifdef CONFIG_RELOCATABLE
__LOAD_HANDLER(r10, system_call_common)
mtctr r10
diff --git a/arch/powerpc/kernel/interrupt_64.S b/arch/powerpc/kernel/interrupt_64.S
index f28f41a1a85a..eef61800f734 100644
--- a/arch/powerpc/kernel/interrupt_64.S
+++ b/arch/powerpc/kernel/interrupt_64.S
@@ -311,10 +311,10 @@ END_BTB_FLUSH_SECTION
* nothing pending. system_call_exception() will call
* trace_hardirqs_off().
*/
- li r11,IRQS_ALL_DISABLED
- li r12,PACA_IRQ_HARD_DIS
+ li r11,IRQS_DISABLED
+ li r12,-1 /* Set MSR_EE and MSR_RI */
stb r11,PACAIRQSOFTMASK(r13)
- stb r12,PACAIRQHAPPENED(r13)
+ mtmsrd r12,1
ENTER_KERNEL_SECURITY_FALLBACK
--
2.23.0
^ permalink raw reply related
* [PATCH 13/14] powerpc/64: handle MSR EE and RI in interrupt entry wrapper
From: Nicholas Piggin @ 2021-03-15 22:04 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Nicholas Piggin
In-Reply-To: <20210315220402.260594-1-npiggin@gmail.com>
Similarly to the system call change in the previous patch, the mtmsrd to
enable RI can be combined with the mtmsrd to enable EE for interrupts
which enable the latter, which tends to be the important synchronous
interrupts (i.e., page faults).
Do this by enabling EE and RI together at the beginning of the entry
wrapper if PACA_IRQ_HARD_DIS is clear, and just enabling RI if it is set
(which means something wanted EE=0).
Asynchronous interrupts set PACA_IRQ_HARD_DIS, but synchronous ones
leave it unchanged, so by default they always get EE=1 unless they
interrupt a caller that has hard disabled. When the sync interrupt
later calls interrupt_cond_local_irq_enable(), that will not require
another mtmsrd because we already enabled here.
This tends to save one mtmsrd L=1 for synchronous interrupts on 64s.
64e is conceptually unchanged, but it also sets MSR[EE]=1 now in the
interrupt wrapper for synchronous interrupts with the same code.
From: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/include/asm/interrupt.h | 18 +++++++++++++++--
arch/powerpc/kernel/exceptions-64s.S | 30 ----------------------------
2 files changed, 16 insertions(+), 32 deletions(-)
diff --git a/arch/powerpc/include/asm/interrupt.h b/arch/powerpc/include/asm/interrupt.h
index 8796eb4630c9..d6d54bbcba2f 100644
--- a/arch/powerpc/include/asm/interrupt.h
+++ b/arch/powerpc/include/asm/interrupt.h
@@ -55,9 +55,20 @@ static inline void interrupt_enter_prepare(struct pt_regs *regs, struct interrup
#endif
#ifdef CONFIG_PPC64
- if (irq_soft_mask_set_return(IRQS_ALL_DISABLED) == IRQS_ENABLED)
+ bool trace_enable = false;
+
+ if (IS_ENABLED(CONFIG_TRACE_IRQFLAGS)) {
+ if (irq_soft_mask_set_return(IRQS_DISABLED) == IRQS_ENABLED)
+ trace_enable = true;
+ } else {
+ irq_soft_mask_set(IRQS_DISABLED);
+ }
+ if (local_paca->irq_happened & PACA_IRQ_HARD_DIS)
+ __hard_RI_enable();
+ else
+ __hard_irq_enable();
+ if (trace_enable)
trace_hardirqs_off();
- local_paca->irq_happened |= PACA_IRQ_HARD_DIS;
if (user_mode(regs)) {
CT_WARN_ON(ct_state() != CONTEXT_USER);
@@ -110,6 +121,7 @@ static inline void interrupt_async_enter_prepare(struct pt_regs *regs, struct in
__ppc64_runlatch_on();
#endif
+ local_paca->irq_happened |= PACA_IRQ_HARD_DIS;
interrupt_enter_prepare(regs, state);
irq_enter();
}
@@ -166,6 +178,8 @@ static inline void interrupt_nmi_enter_prepare(struct pt_regs *regs, struct inte
local_paca->irq_soft_mask = IRQS_ALL_DISABLED;
local_paca->irq_happened |= PACA_IRQ_HARD_DIS;
+ __hard_RI_enable();
+
/* Don't do any per-CPU operations until interrupt state is fixed */
if (nmi_disables_ftrace(regs)) {
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index 2f14ac3c377c..75cee7cdf887 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -129,7 +129,6 @@ name:
#define IISIDE .L_IISIDE_\name\() /* Uses SRR0/1 not DAR/DSISR */
#define IDAR .L_IDAR_\name\() /* Uses DAR (or SRR0) */
#define IDSISR .L_IDSISR_\name\() /* Uses DSISR (or SRR1) */
-#define ISET_RI .L_ISET_RI_\name\() /* Run common code w/ MSR[RI]=1 */
#define IBRANCH_TO_COMMON .L_IBRANCH_TO_COMMON_\name\() /* ENTRY branch to common */
#define IREALMODE_COMMON .L_IREALMODE_COMMON_\name\() /* Common runs in realmode */
#define IMASK .L_IMASK_\name\() /* IRQ soft-mask bit */
@@ -174,9 +173,6 @@ do_define_int n
.ifndef IDSISR
IDSISR=0
.endif
- .ifndef ISET_RI
- ISET_RI=1
- .endif
.ifndef IBRANCH_TO_COMMON
IBRANCH_TO_COMMON=1
.endif
@@ -582,11 +578,6 @@ DEFINE_FIXED_SYMBOL(\name\()_common_real)
stb r10,PACASRR_VALID(r13)
.endif
- .if ISET_RI
- li r10,MSR_RI
- mtmsrd r10,1 /* Set MSR_RI */
- .endif
-
.if ISTACK
.if IKUAP
kuap_save_amr_and_lock r9, r10, cr1, cr0
@@ -931,11 +922,6 @@ INT_DEFINE_BEGIN(system_reset)
IVEC=0x100
IAREA=PACA_EXNMI
IVIRT=0 /* no virt entry point */
- /*
- * MSR_RI is not enabled, because PACA_EXNMI and nmi stack is
- * being used, so a nested NMI exception would corrupt it.
- */
- ISET_RI=0
ISTACK=0
IKVM_REAL=1
INT_DEFINE_END(system_reset)
@@ -1016,8 +1002,6 @@ EXC_COMMON_BEGIN(system_reset_common)
lhz r10,PACA_IN_NMI(r13)
addi r10,r10,1
sth r10,PACA_IN_NMI(r13)
- li r10,MSR_RI
- mtmsrd r10,1
mr r10,r1
ld r1,PACA_NMI_EMERG_SP(r13)
@@ -1095,12 +1079,6 @@ INT_DEFINE_BEGIN(machine_check_early)
IAREA=PACA_EXMC
IVIRT=0 /* no virt entry point */
IREALMODE_COMMON=1
- /*
- * MSR_RI is not enabled, because PACA_EXMC is being used, so a
- * nested machine check corrupts it. machine_check_common enables
- * MSR_RI.
- */
- ISET_RI=0
ISTACK=0
IDAR=1
IDSISR=1
@@ -1111,7 +1089,6 @@ INT_DEFINE_BEGIN(machine_check)
IVEC=0x200
IAREA=PACA_EXMC
IVIRT=0 /* no virt entry point */
- ISET_RI=0
IDAR=1
IDSISR=1
IKVM_SKIP=1
@@ -1182,9 +1159,6 @@ EXC_COMMON_BEGIN(machine_check_early_common)
BEGIN_FTR_SECTION
bl enable_machine_check
END_FTR_SECTION_IFSET(CPU_FTR_HVMODE)
- li r10,MSR_RI
- mtmsrd r10,1
-
addi r3,r1,STACK_FRAME_OVERHEAD
bl machine_check_early
std r3,RESULT(r1) /* Save result */
@@ -1272,10 +1246,6 @@ EXC_COMMON_BEGIN(machine_check_common)
* save area: PACA_EXMC instead of PACA_EXGEN.
*/
GEN_COMMON machine_check
-
- /* Enable MSR_RI when finished with PACA_EXMC */
- li r10,MSR_RI
- mtmsrd r10,1
addi r3,r1,STACK_FRAME_OVERHEAD
bl machine_check_exception
b interrupt_return_srr
--
2.23.0
^ permalink raw reply related
* [PATCH 14/14] powerpc/64s: use the same default PPR for user and kernel
From: Nicholas Piggin @ 2021-03-15 22:04 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Nicholas Piggin
In-Reply-To: <20210315220402.260594-1-npiggin@gmail.com>
Change the default PPR to userspace to 4 (medium), matching the
normal kernel PPR.
This allows system calls and user interrupts to avoid setting PPR on
entry and exit, providing a significant speedup.
This is a change to the user environment. The problem with changing
the kernel to match userspace at 3 (medium-low), is that userspace
can then boost priority above the kernel which is also undesirable.
glibc does not seem to change PPR anywhere, so the decision is to
go with this.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/include/asm/interrupt.h | 2 ++
arch/powerpc/include/asm/processor.h | 4 ++--
arch/powerpc/kernel/exceptions-64s.S | 3 ---
arch/powerpc/kernel/interrupt.c | 33 ++++++++++++++++++++++++++++
arch/powerpc/kernel/interrupt_64.S | 17 --------------
5 files changed, 37 insertions(+), 22 deletions(-)
diff --git a/arch/powerpc/include/asm/interrupt.h b/arch/powerpc/include/asm/interrupt.h
index d6d54bbcba2f..293e6be9fd71 100644
--- a/arch/powerpc/include/asm/interrupt.h
+++ b/arch/powerpc/include/asm/interrupt.h
@@ -57,6 +57,8 @@ static inline void interrupt_enter_prepare(struct pt_regs *regs, struct interrup
#ifdef CONFIG_PPC64
bool trace_enable = false;
+ if (unlikely(regs->ppr != DEFAULT_PPR))
+ mtspr(SPRN_PPR, DEFAULT_PPR);
if (IS_ENABLED(CONFIG_TRACE_IRQFLAGS)) {
if (irq_soft_mask_set_return(IRQS_DISABLED) == IRQS_ENABLED)
trace_enable = true;
diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h
index cb1edf21a82e..5ff589042103 100644
--- a/arch/powerpc/include/asm/processor.h
+++ b/arch/powerpc/include/asm/processor.h
@@ -27,8 +27,8 @@
#endif
#ifdef CONFIG_PPC64
-/* Default SMT priority is set to 3. Use 11- 13bits to save priority. */
-#define PPR_PRIORITY 3
+/* Default SMT priority is set to 4. Use 11- 13bits to save priority. */
+#define PPR_PRIORITY 4
#ifdef __ASSEMBLY__
#define DEFAULT_PPR (PPR_PRIORITY << 50)
#else
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index 75cee7cdf887..0d40614d13e0 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -367,7 +367,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
BEGIN_FTR_SECTION
mfspr r9,SPRN_PPR
END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
- HMT_MEDIUM
std r10,IAREA+EX_R10(r13) /* save r10 - r12 */
BEGIN_FTR_SECTION
mfspr r10,SPRN_CFAR
@@ -1962,8 +1961,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_REAL_LE)
mfspr r11,SPRN_SRR0
mfspr r12,SPRN_SRR1
- HMT_MEDIUM
-
.if ! \virt
__LOAD_HANDLER(r10, system_call_common_real)
mtctr r10
diff --git a/arch/powerpc/kernel/interrupt.c b/arch/powerpc/kernel/interrupt.c
index 09cf699d0e2e..a6e0595da0dd 100644
--- a/arch/powerpc/kernel/interrupt.c
+++ b/arch/powerpc/kernel/interrupt.c
@@ -40,6 +40,11 @@ notrace long system_call_exception(long r3, long r4, long r5,
regs->orig_gpr3 = r3;
+#ifdef CONFIG_PPC_BOOK3S_64
+ if (unlikely(regs->ppr != DEFAULT_PPR))
+ mtspr(SPRN_PPR, DEFAULT_PPR);
+#endif
+
if (IS_ENABLED(CONFIG_PPC_IRQ_SOFT_MASK_DEBUG))
BUG_ON(irq_soft_mask_return() != IRQS_ALL_DISABLED);
@@ -237,6 +242,11 @@ notrace unsigned long syscall_exit_prepare_main(unsigned long r3,
account_cpu_user_exit();
+#ifdef CONFIG_PPC_BOOK3S_64
+ if (unlikely(regs->ppr != DEFAULT_PPR))
+ mtspr(SPRN_PPR, regs->ppr);
+#endif
+
#ifndef CONFIG_PPC_BOOK3E_64 /* BOOK3E not using this */
/*
* We do this at the end so that we do context switch with KERNEL AMR
@@ -315,6 +325,11 @@ notrace unsigned long syscall_exit_restart(unsigned long r3, struct pt_regs *reg
*/
hard_irq_disable();
+#ifdef CONFIG_PPC_BOOK3S_64
+ if (unlikely(regs->ppr != DEFAULT_PPR))
+ mtspr(SPRN_PPR, DEFAULT_PPR);
+#endif
+
trace_hardirqs_off();
user_exit_irqoff();
account_cpu_user_entry();
@@ -398,6 +413,11 @@ notrace unsigned long interrupt_exit_user_prepare(struct pt_regs *regs)
account_cpu_user_exit();
+#ifdef CONFIG_PPC_BOOK3S_64
+ if (unlikely(regs->ppr != DEFAULT_PPR))
+ mtspr(SPRN_PPR, regs->ppr);
+#endif
+
/*
* We do this at the end so that we do context switch with KERNEL AMR
*/
@@ -489,6 +509,11 @@ notrace unsigned long interrupt_exit_kernel_prepare(struct pt_regs *regs)
local_paca->tm_scratch = regs->msr;
#endif
+#ifdef CONFIG_PPC_BOOK3S_64
+ if (unlikely(regs->ppr != DEFAULT_PPR))
+ mtspr(SPRN_PPR, regs->ppr);
+#endif
+
/*
* Don't want to mfspr(SPRN_AMR) here, because this comes after mtmsr,
* which would cause Read-After-Write stalls. Hence, we take the AMR
@@ -505,6 +530,10 @@ notrace unsigned long interrupt_exit_kernel_prepare(struct pt_regs *regs)
notrace unsigned long interrupt_exit_user_restart(struct pt_regs *regs)
{
hard_irq_disable();
+#ifdef CONFIG_PPC_BOOK3S_64
+ if (unlikely(regs->ppr != DEFAULT_PPR))
+ mtspr(SPRN_PPR, DEFAULT_PPR);
+#endif
trace_hardirqs_off();
user_exit_irqoff();
@@ -523,6 +552,10 @@ notrace unsigned long interrupt_exit_user_restart(struct pt_regs *regs)
notrace unsigned long interrupt_exit_kernel_restart(struct pt_regs *regs)
{
hard_irq_disable();
+#ifdef CONFIG_PPC_BOOK3S_64
+ if (unlikely(regs->ppr != DEFAULT_PPR))
+ mtspr(SPRN_PPR, DEFAULT_PPR);
+#endif
#ifndef CONFIG_PPC_BOOK3E_64
set_kuap(AMR_KUAP_BLOCKED);
diff --git a/arch/powerpc/kernel/interrupt_64.S b/arch/powerpc/kernel/interrupt_64.S
index eef61800f734..53fc446dcbeb 100644
--- a/arch/powerpc/kernel/interrupt_64.S
+++ b/arch/powerpc/kernel/interrupt_64.S
@@ -99,10 +99,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_TM)
ld r11,exception_marker@toc(r2)
std r11,-16(r10) /* "regshere" marker */
-BEGIN_FTR_SECTION
- HMT_MEDIUM
-END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
-
ENTER_KERNEL_SECURITY_FALLBACK
/*
@@ -142,10 +138,6 @@ BEGIN_FTR_SECTION
stdcx. r0,0,r1 /* to clear the reservation */
END_FTR_SECTION_IFCLR(CPU_FTR_STCX_CHECKS_ADDRESS)
-BEGIN_FTR_SECTION
- HMT_MEDIUM_LOW
-END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
-
cmpdi r3,0
bne .Lsyscall_vectored_\name\()_restore_regs
@@ -377,10 +369,6 @@ END_FTR_SECTION_IFCLR(CPU_FTR_STCX_CHECKS_ADDRESS)
mtspr SPRN_XER,r0
.Lsyscall_restore_regs_cont:
-BEGIN_FTR_SECTION
- HMT_MEDIUM_LOW
-END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
-
/*
* We don't need to restore AMR on the way back to userspace for KUAP.
* The value of AMR only matters while we're in the kernel.
@@ -533,11 +521,6 @@ _ASM_NOKPROBE_SYMBOL(interrupt_return_\srr\())
tdnei r4,IRQS_ENABLED
#ifdef CONFIG_PPC_BOOK3S
-BEGIN_FTR_SECTION
- ld r10,_PPR(r1)
- mtspr SPRN_PPR,r10
-END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
-
.ifc \srr,srr
lbz r4,PACASRR_VALID(r13)
.else
--
2.23.0
^ permalink raw reply related
* Re: [PATCH 4/4] tools/perf: Support pipeline stage cycles for powerpc
From: Jiri Olsa @ 2021-03-15 23:18 UTC (permalink / raw)
To: Athira Rajeev
Cc: Ravi Bangoria, Madhavan Srinivasan, Peter Zijlstra, kjain,
linux-kernel, acme, linux-perf-users, jolsa, linuxppc-dev,
kan.liang
In-Reply-To: <FD9505E3-8CDE-4073-88A0-BCA4B92F276E@linux.vnet.ibm.com>
On Mon, Mar 15, 2021 at 01:22:09PM +0530, Athira Rajeev wrote:
SNIP
> +
> +static char *setup_dynamic_sort_keys(char *str)
> +{
> + unsigned int j;
> +
> + if (sort__mode == SORT_MODE__MEMORY)
> + for (j = 0; j < ARRAY_SIZE(dynamic_sort_keys_mem); j++)
> + if (arch_support_dynamic_key(dynamic_sort_keys_mem[j])) {
> + str = suffix_if_not_in(dynamic_sort_keys_mem[j], str);
> + if (str == NULL)
> + return str;
> + }
> +
> + return str;
> +}
> +
> static int __setup_sorting(struct evlist *evlist)
> {
> char *str;
> @@ -3050,6 +3085,12 @@ static int __setup_sorting(struct evlist *evlist)
> }
> }
>
> + str = setup_dynamic_sort_keys(str);
> + if (str == NULL) {
> + pr_err("Not enough memory to setup dynamic sort keys");
> + return -ENOMEM;
> + }
hum, so this is basicaly overloading the default_mem_sort_order for
architecture, right?
then I think it'd be easier just overload default_mem_sort_order directly
I was thinking more about adding extra (arch specific) loop to
sort_dimension__add or somehow add arch's specific stuff to
memory_sort_dimensions
jirka
^ permalink raw reply
* Re: [PATCH] powerpc/vdso32: Add missing _restgpr_31_x to fix build failure
From: Segher Boessenkool @ 2021-03-15 23:47 UTC (permalink / raw)
To: Rasmus Villemoes; +Cc: linux-kernel, Paul Mackerras, linuxppc-dev
In-Reply-To: <023afd0c-dc61-5891-5145-5bcdce8227be@prevas.dk>
On Mon, Mar 15, 2021 at 05:23:44PM +0100, Rasmus Villemoes wrote:
> On 12/03/2021 03.29, Segher Boessenkool wrote:
> > On Tue, Mar 09, 2021 at 06:19:30AM +0000, Christophe Leroy wrote:
> >> With some defconfig including CONFIG_CC_OPTIMIZE_FOR_SIZE,
> >> (for instance mvme5100_defconfig and ps3_defconfig), gcc 5
> >> generates a call to _restgpr_31_x.
> >
> >> I don't know if there is a way to tell GCC not to emit that call, because at the end we get more instructions than needed.
> >
> > The function is required by the ABI, you need to have it.
> >
> > You get *fewer* insns statically, and that is what -Os is about: reduce
> > the size of the binaries.
>
> Is there any reason to not just always build the vdso with -O2? It's one
> page/one VMA either way, and the vdso is about making certain system
> calls cheaper, so if unconditional -O2 could save a few cycles compared
> to -Os, why not? (And if, as it seems, there's only one user within the
> DSO of _restgpr_31_x, yes, the overall size of the .text segment
> probably increases slightly).
You can use exactly the same reasoning for using -O2 instead of -Os
anywhere else.
-Os doesn't mean "smaller code, but only where that is reasonable". It
means "smaller code".
Segher
^ permalink raw reply
* Re: [PATCH] powerpc/vdso32: Add missing _restgpr_31_x to fix build failure
From: Segher Boessenkool @ 2021-03-15 23:59 UTC (permalink / raw)
To: David Laight
Cc: Paul Mackerras, linuxppc-dev@lists.ozlabs.org,
linux-kernel@vger.kernel.org, 'Rasmus Villemoes'
In-Reply-To: <14e2cfb8c3f141aaba8fe0fb2d8f1885@AcuMS.aculab.com>
On Mon, Mar 15, 2021 at 04:38:52PM +0000, David Laight wrote:
> From: Rasmus Villemoes
> > Sent: 15 March 2021 16:24
> > On 12/03/2021 03.29, Segher Boessenkool wrote:
> > > On Tue, Mar 09, 2021 at 06:19:30AM +0000, Christophe Leroy wrote:
> > >> With some defconfig including CONFIG_CC_OPTIMIZE_FOR_SIZE,
> > >> (for instance mvme5100_defconfig and ps3_defconfig), gcc 5
> > >> generates a call to _restgpr_31_x.
> > >
> > >> I don't know if there is a way to tell GCC not to emit that call, because at the end we get more
> > instructions than needed.
> > >
> > > The function is required by the ABI, you need to have it.
> > >
> > > You get *fewer* insns statically, and that is what -Os is about: reduce
> > > the size of the binaries.
> >
> > Is there any reason to not just always build the vdso with -O2? It's one
> > page/one VMA either way, and the vdso is about making certain system
> > calls cheaper, so if unconditional -O2 could save a few cycles compared
> > to -Os, why not? (And if, as it seems, there's only one user within the
> > DSO of _restgpr_31_x, yes, the overall size of the .text segment
> > probably increases slightly).
>
> Sometimes -Os generates such horrid code you really never want to use it.
> A classic is on x86 where it replaces 'load register with byte constant'
> with 'push byte' 'pop register'.
> The code is actually smaller but the execution time is horrid.
>
> There are also cases where -O2 actually generates smaller code.
Yes, as with all heuristics it doesn't always work out. But usually -Os
is smaller.
> Although you may need to disable loop unrolling (often dubious at best)
> and either force or disable some function inlining.
The cases where GCC does loop unrolling at -O2 always help quite a lot.
Or, do you have a counter-example? We'd love to see one.
And yup, inlining is hard. GCC's heuristics there are very good
nowadays, but any single decision has big effects. Doing the important
spots manually (always_inline or noinline) has good payoff.
Segher
^ permalink raw reply
* [PATCH] powerpc/pseries: Only register vio drivers if vio bus exists
From: Michael Ellerman @ 2021-03-16 1:09 UTC (permalink / raw)
To: linuxppc-dev; +Cc: pmenzel
The vio bus is a fake bus, which we use on pseries LPARs (guests) to
discover devices provided by the hypervisor. There's no need or sense
in creating the vio bus on bare metal systems.
Which is why commit 4336b9337824 ("powerpc/pseries: Make vio and
ibmebus initcalls pseries specific") made the initialisation of the
vio bus only happen in LPARs.
However as a result of that commit we now see errors at boot on bare
metal systems:
Driver 'hvc_console' was unable to register with bus_type 'vio' because the bus was not initialized.
Driver 'tpm_ibmvtpm' was unable to register with bus_type 'vio' because the bus was not initialized.
This happens because those drivers are built-in, and are calling
vio_register_driver(). It in turn calls driver_register() with a
reference to vio_bus_type, but we haven't registered vio_bus_type with
the driver core.
Fix it by also guarding vio_register_driver() with a check to see if
we are on pseries.
Fixes: 4336b9337824 ("powerpc/pseries: Make vio and ibmebus initcalls pseries specific")
Reported-by: Paul Menzel <pmenzel@molgen.mpg.de>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
---
arch/powerpc/platforms/pseries/vio.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/arch/powerpc/platforms/pseries/vio.c b/arch/powerpc/platforms/pseries/vio.c
index 9cb4fc839fd5..429053d0402a 100644
--- a/arch/powerpc/platforms/pseries/vio.c
+++ b/arch/powerpc/platforms/pseries/vio.c
@@ -1285,6 +1285,10 @@ static int vio_bus_remove(struct device *dev)
int __vio_register_driver(struct vio_driver *viodrv, struct module *owner,
const char *mod_name)
{
+ // vio_bus_type is only initialised for pseries
+ if (!machine_is(pseries))
+ return -ENODEV;
+
pr_debug("%s: driver %s registering\n", __func__, viodrv->name);
/* fill in 'struct driver' fields */
--
2.25.1
^ permalink raw reply related
* Re: VIO bus not initialized
From: Michael Ellerman @ 2021-03-16 1:10 UTC (permalink / raw)
To: Paul Menzel, Benjamin Herrenschmidt, Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <90e6a559-0908-684c-9156-5f3da2b02e38@molgen.mpg.de>
Paul Menzel <pmenzel@molgen.mpg.de> writes:
> Am 15.03.21 um 08:53 schrieb Michael Ellerman:
>> Paul Menzel writes:
>
>>> On the POWER8 system IBM S822LC, Linux 5.12-rc2+ logs the errors below.
>>
>> That's a bare metal system, you can see that from the line "Using
>> PowerNV machine description" in the boot log.
>>
>>> $ dmesg --level=err
>>> [ 1.555668] Driver 'hvc_console' was unable to register with bus_type 'vio' because the bus was not initialized.
>>> [ 1.558434] Driver 'tpm_ibmvtpm' was unable to register with bus_type 'vio' because the bus was not initialized.
>>> $ grep VIO /boot/config-5.12.0-rc2+
>>> CONFIG_IBMVIO=y
>>
>> The "vio" bus is not a real bus, it's a fake bus we use for hypervisor
>> provided devices in LPARs (guests).
>>
>> So on bare metal machines there is no vio bus, the devices that would
>> appear on the vio bus are found via other mechanisms.
>
> Thank you for the explanation. Two questions:
>
> 1. Could a bare metal system be detected, and the VIO “be skipped”?
Yeah, in fact we are already skipping the registration of the bus,
that's why we're seeing these messages. We need to also skip the
registration of the drivers to avoid those warnings.
See the patch I just sent.
cheers
^ permalink raw reply
* Re: [PATCH] powerpc: Fix missing prototype problems for "arch/powerpc/kernel/setup_64.c"
From: heying (H) @ 2021-03-16 2:04 UTC (permalink / raw)
To: Cédric Le Goater, Christophe Leroy, mpe, benh, paulus,
npiggin, dja, akpm, rppt, aneesh.kumar
Cc: johnny.chenyi, linuxppc-dev
In-Reply-To: <eb78b1b0-03f9-2b20-02a7-74dbeea81493@kaod.org>
Dear Cédric Le Goater and Christophe Leroy,
Thanks for all your suggestions! I'll pick them in my patch and resent
it soon.
Thanks again.
在 2021/3/15 21:14, Cédric Le Goater 写道:
> On 3/15/21 2:01 PM, Christophe Leroy wrote:
>>
>> Le 15/03/2021 à 13:57, Cédric Le Goater a écrit :
>>> On 3/15/21 1:48 PM, heying (H) wrote:
>>>> 在 2021/3/15 20:17, Christophe Leroy 写道:
>>>>> You subject doesn't match the content of the patch.
>>>> OK. I'll adapt that.
>>>>> Le 15/03/2021 à 13:04, He Ying a écrit :
>>>>>> The variables 'uaccess_fulsh' and 'entry_flush' are not referenced
>>>>>> outside the file. So define them as static to avoid the warnings.
>>>>>>
>>>>>> And add a prototype for the function 'panic_smp_self_stop' for the
>>>>>> same purpose.
>>>>>>
>>>>>> Sparse also warns that 'rfi_flush' should be static. However, it's
>>>>>> referenced outside the file.
>>>>> To clear that warning, you have to include asm/security_features.h, rfi_flush is declared there.
>>>> Do you mean that I should include this header in arch/powerpc/kernel/setup_64.c?
>>> yes.
>>>
>>>>>> The warnings about the file reported by sparse are as follows:
>>>>>> arch/powerpc/kernel/setup_64.c:422:6: warning: symbol 'panic_smp_self_stop' was not declared. Should it be static?
>>>>>> arch/powerpc/kernel/setup_64.c:951:6: warning: symbol 'rfi_flush' was not declared. Should it be static?
>>>>>> arch/powerpc/kernel/setup_64.c:952:6: warning: symbol 'entry_flush' was not declared. Should it be static?
>>>>>> arch/powerpc/kernel/setup_64.c:953:6: warning: symbol 'uaccess_flush' was not declared. Should it be static?
>>>>>>
>>>>>> Reported-by: Hulk Robot <hulkci@huawei.com>
>>>>>> Signed-off-by: He Ying <heying24@huawei.com>
>>>>>> ---
>>>>>> arch/powerpc/kernel/setup_64.c | 6 ++++--
>>>>>> 1 file changed, 4 insertions(+), 2 deletions(-)
>>>>>>
>>>>>> diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
>>>>>> index 560ed8b975e7..603aacd8527b 100644
>>>>>> --- a/arch/powerpc/kernel/setup_64.c
>>>>>> +++ b/arch/powerpc/kernel/setup_64.c
>>>>>> @@ -71,6 +71,8 @@
>>>>>> #include "setup.h"
>>>>>> +extern void panic_smp_self_stop(void);
>>>>>> +
>>>>> For function prototypes 'extern' is unneeded and deprecated.
>>>>>
>>>>> And function prototypes should go in an header file.
>>>>>
>>>>> panic_smp_self_stop() is called from kernel/panic.c , it should be declared in one of the generic linux header files I think.
>>>> Yes, you're right. But I have no idea which header it should be declared in. May I have your suggestions?
>>> arch/powerpc/include/asm/bug.h looks like a good place.
>> Why declaring it in a powerpc header ?
>>
>> It's a weak function defined in core part of kernel (kernel/panic.c).
>>
>> I think it should go in a common header, just like for instance arch_thaw_secondary_cpus_begin()
> Indeed. include/linux/smp.h is a better place for a common routine.
>
> C.
>
> .
^ permalink raw reply
* Re: [PATCH 0/2] handle premature return from H_JOIN in pseries mobility code
From: Nicholas Piggin @ 2021-03-16 2:37 UTC (permalink / raw)
To: linuxppc-dev, Nathan Lynch; +Cc: brking, tyreld
In-Reply-To: <20210315080045.460331-1-nathanl@linux.ibm.com>
Excerpts from Nathan Lynch's message of March 15, 2021 6:00 pm:
> pseries VMs in shared processor mode are susceptible to failed
> migrations becasue stray H_PRODs from the paravirt spinlock
> implementation can bump threads out of joining state before the
> suspend has occurred. Fix this by adding a small amount of shared
> state and ordering accesses to it with respect to H_PROD and H_JOIN.
Oh, tricky problem. Nice work on finding and fixing it.
The patches seem okay to me.
Thanks,
Nick
^ permalink raw reply
* Re: [PATCH] powerpc/kexec: Don't use .machine ppc64 in trampoline_64.S
From: Segher Boessenkool @ 2021-03-16 2:44 UTC (permalink / raw)
To: Michael Ellerman; +Cc: linuxppc-dev, dja
In-Reply-To: <20210315034159.315675-1-mpe@ellerman.id.au>
Hi!
On Mon, Mar 15, 2021 at 02:41:59PM +1100, Michael Ellerman wrote:
> The ".machine" directive allows changing the machine for which code is
> being generated. It's equivalent to passing an -mcpu option on the
> command line.
>
> Although it can be useful, it's generally a bad idea because it adds
> another way to influence code generation separate from the flags
> passed via the build system. ie. if we need to build different pieces
> of code with different flags we should do that via our Makefiles, not
> using ".machine".
It does not influence code generation. It says which instructions are
valid, instead. There are a few cases where the same mnemonic will
generate a different binary encoding depending on machine selected,
maybe you mean that?
It is *normal* to use .machine push/pop and a specific .machine around
instructions that require a machine other than what you are building
for. The compiler does this itself, and it is the recommended way to
use "foreign" instructions in inline assembler.
That said...
> However as best as I can tell the ".machine" directive in
> trampoline_64.S is not necessary at all.
>
> It was added in commit 0d97631392c2 ("powerpc: Add purgatory for
> kexec_file_load() implementation."), which created the file based on
> the kexec-tools purgatory. It may be/have-been necessary in the
> kexec-tools version, but we have a completely different build system,
> and we already pass the desired CPU flags, eg:
>
> gcc ... -m64 -Wl,-a64 -mabi=elfv2 -Wa,-maltivec -Wa,-mpower4 -Wa,-many
> ... arch/powerpc/purgatory/trampoline_64.S
>
> So drop the ".machine" directive and rely on the assembler flags.
> - .machine ppc64
Please make sure to test this on a big endian config.
A ppc64le-linux assembler defaults to power8. A ppc64-linux assembler
defaults to power3 (that is the same as .machine ppc64). Or maybe it
makes it power4? I get lost :-)
It certainly *should* work, but, test please :-)
(And with a *default* powerpc64-linux config, not one that defaults to
power7 or power8 or similar! Arnd's toolchains at
<https://mirrors.edge.kernel.org/pub/tools/crosstool/>
are fine for this.)
Reviewed-by: Segher Boessenkool <segher@kernel.crashing.org>
Segher
^ permalink raw reply
* [powerpc:merge] BUILD SUCCESS 0512161accb8b6f6dacc85d165350b1812ddcc33
From: kernel test robot @ 2021-03-16 2:54 UTC (permalink / raw)
To: Michael Ellerman; +Cc: linuxppc-dev
tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git merge
branch HEAD: 0512161accb8b6f6dacc85d165350b1812ddcc33 Automatic merge of 'fixes' into merge (2021-03-16 00:24)
elapsed time: 741m
configs tested: 137
configs skipped: 3
The following configs have been built successfully.
More configs may be tested in the coming days.
gcc tested configs:
arm defconfig
arm64 allyesconfig
arm64 defconfig
arm allyesconfig
arm allmodconfig
x86_64 allyesconfig
riscv allmodconfig
h8300 edosk2674_defconfig
powerpc amigaone_defconfig
powerpc linkstation_defconfig
m68k m5407c3_defconfig
arc nsimosci_hs_smp_defconfig
openrisc simple_smp_defconfig
mips malta_kvm_defconfig
arm exynos_defconfig
ia64 bigsur_defconfig
arm dove_defconfig
openrisc alldefconfig
sparc64 defconfig
m68k mac_defconfig
arm orion5x_defconfig
mips bcm63xx_defconfig
arm zeus_defconfig
powerpc socrates_defconfig
m68k mvme16x_defconfig
riscv nommu_virt_defconfig
arc tb10x_defconfig
s390 alldefconfig
xtensa virt_defconfig
ia64 defconfig
mips cu1000-neo_defconfig
sparc alldefconfig
mips rs90_defconfig
mips ip32_defconfig
sh ap325rxa_defconfig
mips xway_defconfig
arm versatile_defconfig
arm lpc32xx_defconfig
sh shmin_defconfig
powerpc tqm8xx_defconfig
sh se7722_defconfig
arm eseries_pxa_defconfig
m68k bvme6000_defconfig
powerpc rainier_defconfig
parisc generic-32bit_defconfig
arm mini2440_defconfig
i386 defconfig
h8300 allyesconfig
h8300 h8s-sim_defconfig
sh r7785rp_defconfig
mips maltaup_defconfig
sh apsh4ad0a_defconfig
sh se7721_defconfig
powerpc mpc5200_defconfig
mips fuloong2e_defconfig
parisc generic-64bit_defconfig
arm hisi_defconfig
powerpc mpc836x_mds_defconfig
mips rt305x_defconfig
arc haps_hs_smp_defconfig
sh se7712_defconfig
powerpc mpc512x_defconfig
ia64 alldefconfig
csky defconfig
arm colibri_pxa300_defconfig
sh se7751_defconfig
m68k m5208evb_defconfig
arm aspeed_g5_defconfig
arm netwinder_defconfig
parisc allyesconfig
powerpc motionpro_defconfig
arm h3600_defconfig
powerpc mpc8313_rdb_defconfig
powerpc g5_defconfig
powerpc mpc837x_rdb_defconfig
ia64 allmodconfig
ia64 allyesconfig
m68k allmodconfig
m68k defconfig
m68k allyesconfig
nios2 defconfig
arc allyesconfig
nds32 allnoconfig
nds32 defconfig
nios2 allyesconfig
alpha defconfig
alpha allyesconfig
xtensa allyesconfig
arc defconfig
sh allmodconfig
parisc defconfig
s390 allyesconfig
s390 allmodconfig
s390 defconfig
i386 allyesconfig
sparc allyesconfig
sparc defconfig
i386 tinyconfig
mips allyesconfig
mips allmodconfig
powerpc allyesconfig
powerpc allmodconfig
powerpc allnoconfig
x86_64 randconfig-a006-20210315
x86_64 randconfig-a001-20210315
x86_64 randconfig-a005-20210315
x86_64 randconfig-a004-20210315
x86_64 randconfig-a002-20210315
x86_64 randconfig-a003-20210315
i386 randconfig-a001-20210315
i386 randconfig-a005-20210315
i386 randconfig-a003-20210315
i386 randconfig-a002-20210315
i386 randconfig-a004-20210315
i386 randconfig-a006-20210315
i386 randconfig-a013-20210315
i386 randconfig-a016-20210315
i386 randconfig-a011-20210315
i386 randconfig-a012-20210315
i386 randconfig-a014-20210315
i386 randconfig-a015-20210315
riscv nommu_k210_defconfig
riscv allyesconfig
riscv allnoconfig
riscv defconfig
riscv rv32_defconfig
x86_64 rhel-7.6-kselftests
x86_64 defconfig
x86_64 rhel-8.3
x86_64 rhel-8.3-kbuiltin
x86_64 kexec
clang tested configs:
x86_64 randconfig-a011-20210315
x86_64 randconfig-a016-20210315
x86_64 randconfig-a013-20210315
x86_64 randconfig-a015-20210315
x86_64 randconfig-a014-20210315
x86_64 randconfig-a012-20210315
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
^ permalink raw reply
* [powerpc:next-test] BUILD SUCCESS 1e97f67cc191d74dfacb2a6f4a4ad1db2682a036
From: kernel test robot @ 2021-03-16 2:54 UTC (permalink / raw)
To: Michael Ellerman; +Cc: linuxppc-dev
tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git next-test
branch HEAD: 1e97f67cc191d74dfacb2a6f4a4ad1db2682a036 powerpc/fsl-pci: Fix section mismatch warning
elapsed time: 739m
configs tested: 135
configs skipped: 3
The following configs have been built successfully.
More configs may be tested in the coming days.
gcc tested configs:
arm defconfig
arm64 allyesconfig
arm64 defconfig
arm allyesconfig
arm allmodconfig
x86_64 allyesconfig
riscv allmodconfig
h8300 edosk2674_defconfig
powerpc amigaone_defconfig
powerpc linkstation_defconfig
m68k m5407c3_defconfig
arc nsimosci_hs_smp_defconfig
openrisc simple_smp_defconfig
mips malta_kvm_defconfig
arm exynos_defconfig
ia64 bigsur_defconfig
arm dove_defconfig
openrisc alldefconfig
sparc64 defconfig
m68k mac_defconfig
arm orion5x_defconfig
mips bcm63xx_defconfig
nds32 alldefconfig
arc axs103_smp_defconfig
arm u8500_defconfig
powerpc ppc6xx_defconfig
powerpc mpc7448_hpc2_defconfig
sh ap325rxa_defconfig
mips cu1000-neo_defconfig
mips xway_defconfig
arm versatile_defconfig
arm lpc32xx_defconfig
sh shmin_defconfig
mips ip32_defconfig
parisc alldefconfig
ia64 defconfig
sh se7712_defconfig
arm lubbock_defconfig
x86_64 defconfig
sh rts7751r2dplus_defconfig
powerpc tqm8xx_defconfig
xtensa virt_defconfig
sh se7722_defconfig
arm eseries_pxa_defconfig
m68k bvme6000_defconfig
powerpc rainier_defconfig
parisc generic-32bit_defconfig
arm mini2440_defconfig
powerpc mpc5200_defconfig
mips fuloong2e_defconfig
parisc generic-64bit_defconfig
arm hisi_defconfig
powerpc mpc836x_mds_defconfig
mips rt305x_defconfig
arc haps_hs_smp_defconfig
csky defconfig
powerpc mpc512x_defconfig
ia64 alldefconfig
powerpc sam440ep_defconfig
sh sh7763rdp_defconfig
um i386_defconfig
ia64 allyesconfig
sh sh7757lcr_defconfig
arm s3c6400_defconfig
arc tb10x_defconfig
mips e55_defconfig
m68k defconfig
powerpc motionpro_defconfig
arm h3600_defconfig
powerpc mpc8313_rdb_defconfig
powerpc g5_defconfig
powerpc mpc837x_rdb_defconfig
ia64 allmodconfig
m68k allmodconfig
m68k allyesconfig
nios2 defconfig
arc allyesconfig
nds32 allnoconfig
nds32 defconfig
nios2 allyesconfig
alpha defconfig
alpha allyesconfig
xtensa allyesconfig
h8300 allyesconfig
arc defconfig
sh allmodconfig
parisc defconfig
s390 allyesconfig
s390 allmodconfig
parisc allyesconfig
s390 defconfig
i386 allyesconfig
sparc allyesconfig
sparc defconfig
i386 tinyconfig
i386 defconfig
mips allyesconfig
mips allmodconfig
powerpc allyesconfig
powerpc allmodconfig
powerpc allnoconfig
x86_64 randconfig-a006-20210315
x86_64 randconfig-a001-20210315
x86_64 randconfig-a005-20210315
x86_64 randconfig-a004-20210315
x86_64 randconfig-a002-20210315
x86_64 randconfig-a003-20210315
i386 randconfig-a001-20210315
i386 randconfig-a005-20210315
i386 randconfig-a003-20210315
i386 randconfig-a002-20210315
i386 randconfig-a004-20210315
i386 randconfig-a006-20210315
i386 randconfig-a013-20210315
i386 randconfig-a016-20210315
i386 randconfig-a011-20210315
i386 randconfig-a012-20210315
i386 randconfig-a014-20210315
i386 randconfig-a015-20210315
riscv nommu_k210_defconfig
riscv allyesconfig
riscv nommu_virt_defconfig
riscv allnoconfig
riscv defconfig
riscv rv32_defconfig
x86_64 rhel-7.6-kselftests
x86_64 rhel-8.3
x86_64 rhel-8.3-kbuiltin
x86_64 kexec
clang tested configs:
x86_64 randconfig-a011-20210315
x86_64 randconfig-a016-20210315
x86_64 randconfig-a013-20210315
x86_64 randconfig-a015-20210315
x86_64 randconfig-a014-20210315
x86_64 randconfig-a012-20210315
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
^ permalink raw reply
* [powerpc:fixes-test] BUILD SUCCESS eed5fae00593ab9d261a0c1ffc1bdb786a87a55a
From: kernel test robot @ 2021-03-16 2:54 UTC (permalink / raw)
To: Michael Ellerman; +Cc: linuxppc-dev
tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git fixes-test
branch HEAD: eed5fae00593ab9d261a0c1ffc1bdb786a87a55a powerpc: Force inlining of cpu_has_feature() to avoid build failure
elapsed time: 2398m
configs tested: 187
configs skipped: 97
The following configs have been built successfully.
More configs may be tested in the coming days.
gcc tested configs:
arm defconfig
arm64 allyesconfig
arm64 defconfig
arm allyesconfig
arm allmodconfig
x86_64 allyesconfig
riscv allmodconfig
h8300 edosk2674_defconfig
powerpc amigaone_defconfig
powerpc linkstation_defconfig
m68k m5407c3_defconfig
arc nsimosci_hs_smp_defconfig
openrisc simple_smp_defconfig
sh defconfig
sh alldefconfig
powerpc taishan_defconfig
riscv nommu_k210_sdcard_defconfig
mips loongson3_defconfig
openrisc alldefconfig
sparc64 defconfig
m68k mac_defconfig
arm orion5x_defconfig
mips bcm63xx_defconfig
sh se7705_defconfig
powerpc bluestone_defconfig
sh rsk7264_defconfig
xtensa common_defconfig
arm zeus_defconfig
powerpc socrates_defconfig
m68k mvme16x_defconfig
riscv nommu_virt_defconfig
arc tb10x_defconfig
s390 alldefconfig
sh se7722_defconfig
powerpc cm5200_defconfig
h8300 alldefconfig
mips maltaaprp_defconfig
mips rt305x_defconfig
mips xway_defconfig
powerpc ppc6xx_defconfig
powerpc tqm8555_defconfig
powerpc tqm8541_defconfig
sh polaris_defconfig
sh espt_defconfig
arm stm32_defconfig
arm s5pv210_defconfig
arm aspeed_g4_defconfig
mips workpad_defconfig
mips rm200_defconfig
powerpc ppc44x_defconfig
sh titan_defconfig
m68k sun3x_defconfig
mips jmr3927_defconfig
sh ecovec24_defconfig
sh ap325rxa_defconfig
mips cu1000-neo_defconfig
arm versatile_defconfig
arm lpc32xx_defconfig
sh shmin_defconfig
mips ip32_defconfig
arm qcom_defconfig
ia64 defconfig
mips gpr_defconfig
mips decstation_64_defconfig
powerpc tqm8xx_defconfig
xtensa virt_defconfig
arm eseries_pxa_defconfig
m68k bvme6000_defconfig
powerpc rainier_defconfig
parisc generic-32bit_defconfig
arm mini2440_defconfig
i386 defconfig
powerpc kmeter1_defconfig
powerpc mpc5200_defconfig
mips fuloong2e_defconfig
parisc generic-64bit_defconfig
arm hisi_defconfig
powerpc mpc836x_mds_defconfig
arc haps_hs_smp_defconfig
sh se7712_defconfig
powerpc mpc512x_defconfig
ia64 alldefconfig
csky defconfig
arc alldefconfig
arm viper_defconfig
mips lemote2f_defconfig
arc nsimosci_defconfig
powerpc mpc837x_rdb_defconfig
parisc defconfig
openrisc defconfig
powerpc storcenter_defconfig
microblaze mmu_defconfig
mips ip22_defconfig
sh edosk7760_defconfig
arc vdk_hs38_smp_defconfig
arm s3c2410_defconfig
powerpc motionpro_defconfig
arm h3600_defconfig
powerpc mpc8313_rdb_defconfig
powerpc g5_defconfig
ia64 allmodconfig
ia64 allyesconfig
m68k allmodconfig
m68k defconfig
m68k allyesconfig
nios2 defconfig
arc allyesconfig
nds32 allnoconfig
nds32 defconfig
nios2 allyesconfig
alpha defconfig
alpha allyesconfig
xtensa allyesconfig
h8300 allyesconfig
arc defconfig
sh allmodconfig
s390 allyesconfig
s390 allmodconfig
parisc allyesconfig
s390 defconfig
i386 allyesconfig
sparc allyesconfig
sparc defconfig
i386 tinyconfig
mips allyesconfig
mips allmodconfig
powerpc allyesconfig
powerpc allmodconfig
powerpc allnoconfig
x86_64 randconfig-a006-20210315
x86_64 randconfig-a001-20210315
x86_64 randconfig-a005-20210315
x86_64 randconfig-a004-20210315
x86_64 randconfig-a002-20210315
x86_64 randconfig-a003-20210315
i386 randconfig-a001-20210314
i386 randconfig-a005-20210314
i386 randconfig-a003-20210314
i386 randconfig-a002-20210314
i386 randconfig-a004-20210314
i386 randconfig-a006-20210314
i386 randconfig-a001-20210315
i386 randconfig-a005-20210315
i386 randconfig-a003-20210315
i386 randconfig-a002-20210315
i386 randconfig-a004-20210315
i386 randconfig-a006-20210315
x86_64 randconfig-a011-20210314
x86_64 randconfig-a016-20210314
x86_64 randconfig-a013-20210314
x86_64 randconfig-a015-20210314
x86_64 randconfig-a014-20210314
x86_64 randconfig-a012-20210314
i386 randconfig-a013-20210314
i386 randconfig-a016-20210314
i386 randconfig-a011-20210314
i386 randconfig-a012-20210314
i386 randconfig-a014-20210314
i386 randconfig-a015-20210314
i386 randconfig-a013-20210315
i386 randconfig-a016-20210315
i386 randconfig-a011-20210315
i386 randconfig-a012-20210315
i386 randconfig-a014-20210315
i386 randconfig-a015-20210315
riscv nommu_k210_defconfig
riscv allyesconfig
riscv allnoconfig
riscv defconfig
riscv rv32_defconfig
x86_64 rhel-7.6-kselftests
x86_64 defconfig
x86_64 rhel-8.3
x86_64 rhel-8.3-kbuiltin
x86_64 kexec
clang tested configs:
x86_64 randconfig-a006-20210314
x86_64 randconfig-a001-20210314
x86_64 randconfig-a005-20210314
x86_64 randconfig-a004-20210314
x86_64 randconfig-a002-20210314
x86_64 randconfig-a003-20210314
x86_64 randconfig-a016-20210315
x86_64 randconfig-a015-20210315
x86_64 randconfig-a014-20210315
x86_64 randconfig-a011-20210315
x86_64 randconfig-a013-20210315
x86_64 randconfig-a012-20210315
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
^ permalink raw reply
* Re: [PATCH] ibmvfc: free channel_setup_buf during device tear down
From: Martin K. Petersen @ 2021-03-16 3:13 UTC (permalink / raw)
To: james.bottomley, Tyrel Datwyler
Cc: brking, linuxppc-dev, linux-kernel, Martin K . Petersen,
linux-scsi
In-Reply-To: <20210311012212.428068-1-tyreld@linux.ibm.com>
On Wed, 10 Mar 2021 19:22:12 -0600, Tyrel Datwyler wrote:
> The buffer for negotiating channel setup is DMA allocated at device
> probe time. However, the remove path fails to free this allocation which
> will prevent the hypervisor from releasing the virtual device in the
> case of a hotplug remove.
>
> Fix this issue by freeing the buffer allocation in ibmvfc_free_mem().
Applied to 5.12/scsi-fixes, thanks!
[1/1] ibmvfc: free channel_setup_buf during device tear down
https://git.kernel.org/mkp/scsi/c/febb0cc847e7
--
Martin K. Petersen Oracle Linux Engineering
^ permalink raw reply
* [PATCH v9 1/8] powerpc/mm: Implement set_memory() routines
From: Jordan Niethe @ 2021-03-16 3:17 UTC (permalink / raw)
To: linuxppc-dev
Cc: christophe.leroy, ajd, npiggin, naveen.n.rao, Jordan Niethe, dja
From: Russell Currey <ruscur@russell.cc>
The set_memory_{ro/rw/nx/x}() functions are required for STRICT_MODULE_RWX,
and are generally useful primitives to have. This implementation is
designed to be completely generic across powerpc's many MMUs.
It's possible that this could be optimised to be faster for specific
MMUs, but the focus is on having a generic and safe implementation for
now.
This implementation does not handle cases where the caller is attempting
to change the mapping of the page it is executing from, or if another
CPU is concurrently using the page being altered. These cases likely
shouldn't happen, but a more complex implementation with MMU-specific code
could safely handle them, so that is left as a TODO for now.
These functions do nothing if STRICT_KERNEL_RWX is not enabled.
Reviewed-by: Daniel Axtens <dja@axtens.net>
Signed-off-by: Russell Currey <ruscur@russell.cc>
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
[jpn: rebase on next plus "powerpc/mm/64s: Allow STRICT_KERNEL_RWX again"]
Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
---
arch/powerpc/Kconfig | 1 +
arch/powerpc/include/asm/set_memory.h | 32 +++++++++++
arch/powerpc/mm/Makefile | 2 +-
arch/powerpc/mm/pageattr.c | 81 +++++++++++++++++++++++++++
4 files changed, 115 insertions(+), 1 deletion(-)
create mode 100644 arch/powerpc/include/asm/set_memory.h
create mode 100644 arch/powerpc/mm/pageattr.c
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index fc7f5c5933e6..4498a27ac9db 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -135,6 +135,7 @@ config PPC
select ARCH_HAS_MEMBARRIER_CALLBACKS
select ARCH_HAS_MEMBARRIER_SYNC_CORE
select ARCH_HAS_SCALED_CPUTIME if VIRT_CPU_ACCOUNTING_NATIVE && PPC_BOOK3S_64
+ select ARCH_HAS_SET_MEMORY
select ARCH_HAS_STRICT_KERNEL_RWX if ((PPC_BOOK3S_64 || PPC32) && !HIBERNATION)
select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
select ARCH_HAS_UACCESS_FLUSHCACHE
diff --git a/arch/powerpc/include/asm/set_memory.h b/arch/powerpc/include/asm/set_memory.h
new file mode 100644
index 000000000000..64011ea444b4
--- /dev/null
+++ b/arch/powerpc/include/asm/set_memory.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_POWERPC_SET_MEMORY_H
+#define _ASM_POWERPC_SET_MEMORY_H
+
+#define SET_MEMORY_RO 0
+#define SET_MEMORY_RW 1
+#define SET_MEMORY_NX 2
+#define SET_MEMORY_X 3
+
+int change_memory_attr(unsigned long addr, int numpages, long action);
+
+static inline int set_memory_ro(unsigned long addr, int numpages)
+{
+ return change_memory_attr(addr, numpages, SET_MEMORY_RO);
+}
+
+static inline int set_memory_rw(unsigned long addr, int numpages)
+{
+ return change_memory_attr(addr, numpages, SET_MEMORY_RW);
+}
+
+static inline int set_memory_nx(unsigned long addr, int numpages)
+{
+ return change_memory_attr(addr, numpages, SET_MEMORY_NX);
+}
+
+static inline int set_memory_x(unsigned long addr, int numpages)
+{
+ return change_memory_attr(addr, numpages, SET_MEMORY_X);
+}
+
+#endif
diff --git a/arch/powerpc/mm/Makefile b/arch/powerpc/mm/Makefile
index 3b4e9e4e25ea..d8a08abde1ae 100644
--- a/arch/powerpc/mm/Makefile
+++ b/arch/powerpc/mm/Makefile
@@ -5,7 +5,7 @@
ccflags-$(CONFIG_PPC64) := $(NO_MINIMAL_TOC)
-obj-y := fault.o mem.o pgtable.o mmap.o maccess.o \
+obj-y := fault.o mem.o pgtable.o mmap.o maccess.o pageattr.o \
init_$(BITS).o pgtable_$(BITS).o \
pgtable-frag.o ioremap.o ioremap_$(BITS).o \
init-common.o mmu_context.o drmem.o
diff --git a/arch/powerpc/mm/pageattr.c b/arch/powerpc/mm/pageattr.c
new file mode 100644
index 000000000000..2da3fbab6ff7
--- /dev/null
+++ b/arch/powerpc/mm/pageattr.c
@@ -0,0 +1,81 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * MMU-generic set_memory implementation for powerpc
+ *
+ * Copyright 2019, IBM Corporation.
+ */
+
+#include <linux/mm.h>
+#include <linux/set_memory.h>
+
+#include <asm/mmu.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+
+
+/*
+ * Updates the attributes of a page in three steps:
+ *
+ * 1. invalidate the page table entry
+ * 2. flush the TLB
+ * 3. install the new entry with the updated attributes
+ *
+ * This is unsafe if the caller is attempting to change the mapping of the
+ * page it is executing from, or if another CPU is concurrently using the
+ * page being altered.
+ *
+ * TODO make the implementation resistant to this.
+ *
+ * NOTE: can be dangerous to call without STRICT_KERNEL_RWX
+ */
+static int change_page_attr(pte_t *ptep, unsigned long addr, void *data)
+{
+ long action = (long)data;
+ pte_t pte;
+
+ spin_lock(&init_mm.page_table_lock);
+
+ /* invalidate the PTE so it's safe to modify */
+ pte = ptep_get_and_clear(&init_mm, addr, ptep);
+ flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
+
+ /* modify the PTE bits as desired, then apply */
+ switch (action) {
+ case SET_MEMORY_RO:
+ pte = pte_wrprotect(pte);
+ break;
+ case SET_MEMORY_RW:
+ pte = pte_mkwrite(pte);
+ break;
+ case SET_MEMORY_NX:
+ pte = pte_exprotect(pte);
+ break;
+ case SET_MEMORY_X:
+ pte = pte_mkexec(pte);
+ break;
+ default:
+ WARN_ON_ONCE(1);
+ break;
+ }
+
+ set_pte_at(&init_mm, addr, ptep, pte);
+ spin_unlock(&init_mm.page_table_lock);
+
+ return 0;
+}
+
+int change_memory_attr(unsigned long addr, int numpages, long action)
+{
+ unsigned long start = ALIGN_DOWN(addr, PAGE_SIZE);
+ unsigned long sz = numpages * PAGE_SIZE;
+
+ if (!IS_ENABLED(CONFIG_STRICT_KERNEL_RWX))
+ return 0;
+
+ if (numpages <= 0)
+ return 0;
+
+ return apply_to_existing_page_range(&init_mm, start, sz,
+ change_page_attr, (void *)action);
+}
--
2.25.1
^ permalink raw reply related
* [PATCH v9 2/8] powerpc/lib/code-patching: Set up Strict RWX patching earlier
From: Jordan Niethe @ 2021-03-16 3:17 UTC (permalink / raw)
To: linuxppc-dev
Cc: christophe.leroy, ajd, npiggin, Jordan Niethe, naveen.n.rao, dja
In-Reply-To: <20210316031741.1004850-1-jniethe5@gmail.com>
setup_text_poke_area() is a late init call so it runs before
mark_rodata_ro() and after the init calls. This lets all the init code
patching simply write to their locations. In the future, kprobes is
going to allocate its instruction pages RO which means they will need
setup_text__poke_area() to have been already called for their code
patching. However, init_kprobes() (which allocates and patches some
instruction pages) is an early init call so it happens before
setup_text__poke_area().
start_kernel() calls poking_init() before any of the init calls. On
powerpc, poking_init() is currently a nop. setup_text_poke_area() relies
on kernel virtual memory, cpu hotplug and per_cpu_areas being setup.
setup_per_cpu_areas(), boot_cpu_hotplug_init() and mm_init() are called
before poking_init().
Turn setup_text_poke_area() into poking_init().
Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
---
v9: New to series
---
arch/powerpc/lib/code-patching.c | 12 ++++--------
1 file changed, 4 insertions(+), 8 deletions(-)
diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-patching.c
index 2333625b5e31..b28afa1133db 100644
--- a/arch/powerpc/lib/code-patching.c
+++ b/arch/powerpc/lib/code-patching.c
@@ -65,14 +65,11 @@ static int text_area_cpu_down(unsigned int cpu)
}
/*
- * Run as a late init call. This allows all the boot time patching to be done
- * simply by patching the code, and then we're called here prior to
- * mark_rodata_ro(), which happens after all init calls are run. Although
- * BUG_ON() is rude, in this case it should only happen if ENOMEM, and we judge
- * it as being preferable to a kernel that will crash later when someone tries
- * to use patch_instruction().
+ * Although BUG_ON() is rude, in this case it should only happen if ENOMEM, and
+ * we judge it as being preferable to a kernel that will crash later when
+ * someone tries to use patch_instruction().
*/
-static int __init setup_text_poke_area(void)
+int __init poking_init(void)
{
BUG_ON(!cpuhp_setup_state(CPUHP_AP_ONLINE_DYN,
"powerpc/text_poke:online", text_area_cpu_up,
@@ -80,7 +77,6 @@ static int __init setup_text_poke_area(void)
return 0;
}
-late_initcall(setup_text_poke_area);
/*
* This can be called for kernel text or a module.
--
2.25.1
^ permalink raw reply related
* [PATCH v9 3/8] powerpc/kprobes: Mark newly allocated probes as RO
From: Jordan Niethe @ 2021-03-16 3:17 UTC (permalink / raw)
To: linuxppc-dev
Cc: christophe.leroy, ajd, npiggin, naveen.n.rao, Jordan Niethe, dja
In-Reply-To: <20210316031741.1004850-1-jniethe5@gmail.com>
From: Russell Currey <ruscur@russell.cc>
With CONFIG_STRICT_KERNEL_RWX=y and CONFIG_KPROBES=y, there will be one
W+X page at boot by default. This can be tested with
CONFIG_PPC_PTDUMP=y and CONFIG_PPC_DEBUG_WX=y set, and checking the
kernel log during boot.
Add an arch specific insn page allocator which returns RO pages if
STRICT_KERNEL_RWX is enabled. This page is only written to with
patch_instruction() which is able to write RO pages.
Reviewed-by: Daniel Axtens <dja@axtens.net>
Signed-off-by: Russell Currey <ruscur@russell.cc>
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
[jpn: Reword commit message, switch from vmalloc_exec(), add
free_insn_page()]
Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
---
v9: - vmalloc_exec() no longer exists
- Set the page to RW before freeing it
---
arch/powerpc/kernel/kprobes.c | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c
index 01ab2163659e..bb7e4d321988 100644
--- a/arch/powerpc/kernel/kprobes.c
+++ b/arch/powerpc/kernel/kprobes.c
@@ -25,6 +25,8 @@
#include <asm/sections.h>
#include <asm/inst.h>
#include <linux/uaccess.h>
+#include <linux/set_memory.h>
+#include <linux/vmalloc.h>
DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
@@ -103,6 +105,26 @@ kprobe_opcode_t *kprobe_lookup_name(const char *name, unsigned int offset)
return addr;
}
+void *alloc_insn_page(void)
+{
+ void *page = vmalloc(PAGE_SIZE);
+
+ if (!page)
+ return NULL;
+
+ set_memory_ro((unsigned long)page, 1);
+ set_memory_x((unsigned long)page, 1);
+
+ return page;
+}
+
+void free_insn_page(void *page)
+{
+ set_memory_nx((unsigned long)page, 1);
+ set_memory_rw((unsigned long)page, 1);
+ vfree(page);
+}
+
int arch_prepare_kprobe(struct kprobe *p)
{
int ret = 0;
--
2.25.1
^ permalink raw reply related
* [PATCH v9 4/8] powerpc/mm/ptdump: debugfs handler for W+X checks at runtime
From: Jordan Niethe @ 2021-03-16 3:17 UTC (permalink / raw)
To: linuxppc-dev
Cc: christophe.leroy, ajd, Kees Cook, npiggin, naveen.n.rao,
Jordan Niethe, dja
In-Reply-To: <20210316031741.1004850-1-jniethe5@gmail.com>
From: Russell Currey <ruscur@russell.cc>
Very rudimentary, just
echo 1 > [debugfs]/check_wx_pages
and check the kernel log. Useful for testing strict module RWX.
Updated the Kconfig entry to reflect this.
Also fixed a typo.
Reviewed-by: Kees Cook <keescook@chromium.org>
Signed-off-by: Russell Currey <ruscur@russell.cc>
Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
---
arch/powerpc/Kconfig.debug | 6 ++++--
arch/powerpc/mm/ptdump/ptdump.c | 21 ++++++++++++++++++++-
2 files changed, 24 insertions(+), 3 deletions(-)
diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug
index ae084357994e..56e99e9a30d9 100644
--- a/arch/powerpc/Kconfig.debug
+++ b/arch/powerpc/Kconfig.debug
@@ -371,7 +371,7 @@ config PPC_PTDUMP
If you are unsure, say N.
config PPC_DEBUG_WX
- bool "Warn on W+X mappings at boot"
+ bool "Warn on W+X mappings at boot & enable manual checks at runtime"
depends on PPC_PTDUMP && STRICT_KERNEL_RWX
help
Generate a warning if any W+X mappings are found at boot.
@@ -385,7 +385,9 @@ config PPC_DEBUG_WX
of other unfixed kernel bugs easier.
There is no runtime or memory usage effect of this option
- once the kernel has booted up - it's a one time check.
+ once the kernel has booted up, it only automatically checks once.
+
+ Enables the "check_wx_pages" debugfs entry for checking at runtime.
If in doubt, say "Y".
diff --git a/arch/powerpc/mm/ptdump/ptdump.c b/arch/powerpc/mm/ptdump/ptdump.c
index aca354fb670b..78497d57b66b 100644
--- a/arch/powerpc/mm/ptdump/ptdump.c
+++ b/arch/powerpc/mm/ptdump/ptdump.c
@@ -4,7 +4,7 @@
*
* This traverses the kernel pagetables and dumps the
* information about the used sections of memory to
- * /sys/kernel/debug/kernel_pagetables.
+ * /sys/kernel/debug/kernel_page_tables.
*
* Derived from the arm64 implementation:
* Copyright (c) 2014, The Linux Foundation, Laura Abbott.
@@ -459,6 +459,25 @@ void ptdump_check_wx(void)
else
pr_info("Checked W+X mappings: passed, no W+X pages found\n");
}
+
+static int check_wx_debugfs_set(void *data, u64 val)
+{
+ if (val != 1ULL)
+ return -EINVAL;
+
+ ptdump_check_wx();
+
+ return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(check_wx_fops, NULL, check_wx_debugfs_set, "%llu\n");
+
+static int ptdump_check_wx_init(void)
+{
+ return debugfs_create_file("check_wx_pages", 0200, NULL,
+ NULL, &check_wx_fops) ? 0 : -ENOMEM;
+}
+device_initcall(ptdump_check_wx_init);
#endif
static int ptdump_init(void)
--
2.25.1
^ permalink raw reply related
* [PATCH v9 5/8] powerpc: Set ARCH_HAS_STRICT_MODULE_RWX
From: Jordan Niethe @ 2021-03-16 3:17 UTC (permalink / raw)
To: linuxppc-dev
Cc: christophe.leroy, ajd, npiggin, naveen.n.rao, Jordan Niethe, dja
In-Reply-To: <20210316031741.1004850-1-jniethe5@gmail.com>
From: Russell Currey <ruscur@russell.cc>
To enable strict module RWX on powerpc, set:
CONFIG_STRICT_MODULE_RWX=y
You should also have CONFIG_STRICT_KERNEL_RWX=y set to have any real
security benefit.
ARCH_HAS_STRICT_MODULE_RWX is set to require ARCH_HAS_STRICT_KERNEL_RWX.
This is due to a quirk in arch/Kconfig and arch/powerpc/Kconfig that
makes STRICT_MODULE_RWX *on by default* in configurations where
STRICT_KERNEL_RWX is *unavailable*.
Since this doesn't make much sense, and module RWX without kernel RWX
doesn't make much sense, having the same dependencies as kernel RWX
works around this problem.
Signed-off-by: Russell Currey <ruscur@russell.cc>
Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
---
arch/powerpc/Kconfig | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 4498a27ac9db..d9cadc4212d0 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -137,6 +137,7 @@ config PPC
select ARCH_HAS_SCALED_CPUTIME if VIRT_CPU_ACCOUNTING_NATIVE && PPC_BOOK3S_64
select ARCH_HAS_SET_MEMORY
select ARCH_HAS_STRICT_KERNEL_RWX if ((PPC_BOOK3S_64 || PPC32) && !HIBERNATION)
+ select ARCH_HAS_STRICT_MODULE_RWX if ARCH_HAS_STRICT_KERNEL_RWX
select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
select ARCH_HAS_UACCESS_FLUSHCACHE
select ARCH_HAS_COPY_MC if PPC64
--
2.25.1
^ permalink raw reply related
* [PATCH v9 6/8] powerpc/configs: Enable STRICT_MODULE_RWX in skiroot_defconfig
From: Jordan Niethe @ 2021-03-16 3:17 UTC (permalink / raw)
To: linuxppc-dev
Cc: christophe.leroy, ajd, Joel Stanley, npiggin, naveen.n.rao,
Jordan Niethe, dja
In-Reply-To: <20210316031741.1004850-1-jniethe5@gmail.com>
From: Russell Currey <ruscur@russell.cc>
skiroot_defconfig is the only powerpc defconfig with STRICT_KERNEL_RWX
enabled, and if you want memory protection for kernel text you'd want it
for modules too, so enable STRICT_MODULE_RWX there.
Acked-by: Joel Stanley <joel@joel.id.au>
Signed-off-by: Russell Currey <ruscur@russell.cc>
Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
---
arch/powerpc/configs/skiroot_defconfig | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/powerpc/configs/skiroot_defconfig b/arch/powerpc/configs/skiroot_defconfig
index b806a5d3a695..50fe06cb3a31 100644
--- a/arch/powerpc/configs/skiroot_defconfig
+++ b/arch/powerpc/configs/skiroot_defconfig
@@ -50,6 +50,7 @@ CONFIG_CMDLINE="console=tty0 console=hvc0 ipr.fast_reboot=1 quiet"
# CONFIG_PPC_MEM_KEYS is not set
CONFIG_JUMP_LABEL=y
CONFIG_STRICT_KERNEL_RWX=y
+CONFIG_STRICT_MODULE_RWX=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
CONFIG_MODULE_SIG_FORCE=y
--
2.25.1
^ permalink raw reply related
* [PATCH v9 7/8] powerpc/mm: implement set_memory_attr()
From: Jordan Niethe @ 2021-03-16 3:17 UTC (permalink / raw)
To: linuxppc-dev
Cc: christophe.leroy, ajd, npiggin, kbuild test robot, naveen.n.rao,
Jordan Niethe, dja
In-Reply-To: <20210316031741.1004850-1-jniethe5@gmail.com>
From: Christophe Leroy <christophe.leroy@c-s.fr>
In addition to the set_memory_xx() functions which allows to change
the memory attributes of not (yet) used memory regions, implement a
set_memory_attr() function to:
- set the final memory protection after init on currently used
kernel regions.
- enable/disable kernel memory regions in the scope of DEBUG_PAGEALLOC.
Unlike the set_memory_xx() which can act in three step as the regions
are unused, this function must modify 'on the fly' as the kernel is
executing from them. At the moment only PPC32 will use it and changing
page attributes on the fly is not an issue.
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
Reported-by: kbuild test robot <lkp@intel.com>
[ruscur: cast "data" to unsigned long instead of int]
Signed-off-by: Russell Currey <ruscur@russell.cc>
Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
---
arch/powerpc/include/asm/set_memory.h | 2 ++
arch/powerpc/mm/pageattr.c | 33 +++++++++++++++++++++++++++
2 files changed, 35 insertions(+)
diff --git a/arch/powerpc/include/asm/set_memory.h b/arch/powerpc/include/asm/set_memory.h
index 64011ea444b4..b040094f7920 100644
--- a/arch/powerpc/include/asm/set_memory.h
+++ b/arch/powerpc/include/asm/set_memory.h
@@ -29,4 +29,6 @@ static inline int set_memory_x(unsigned long addr, int numpages)
return change_memory_attr(addr, numpages, SET_MEMORY_X);
}
+int set_memory_attr(unsigned long addr, int numpages, pgprot_t prot);
+
#endif
diff --git a/arch/powerpc/mm/pageattr.c b/arch/powerpc/mm/pageattr.c
index 2da3fbab6ff7..2fde1b195c85 100644
--- a/arch/powerpc/mm/pageattr.c
+++ b/arch/powerpc/mm/pageattr.c
@@ -79,3 +79,36 @@ int change_memory_attr(unsigned long addr, int numpages, long action)
return apply_to_existing_page_range(&init_mm, start, sz,
change_page_attr, (void *)action);
}
+
+/*
+ * Set the attributes of a page:
+ *
+ * This function is used by PPC32 at the end of init to set final kernel memory
+ * protection. It includes changing the maping of the page it is executing from
+ * and data pages it is using.
+ */
+static int set_page_attr(pte_t *ptep, unsigned long addr, void *data)
+{
+ pgprot_t prot = __pgprot((unsigned long)data);
+
+ spin_lock(&init_mm.page_table_lock);
+
+ set_pte_at(&init_mm, addr, ptep, pte_modify(*ptep, prot));
+ flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
+
+ spin_unlock(&init_mm.page_table_lock);
+
+ return 0;
+}
+
+int set_memory_attr(unsigned long addr, int numpages, pgprot_t prot)
+{
+ unsigned long start = ALIGN_DOWN(addr, PAGE_SIZE);
+ unsigned long sz = numpages * PAGE_SIZE;
+
+ if (numpages <= 0)
+ return 0;
+
+ return apply_to_existing_page_range(&init_mm, start, sz, set_page_attr,
+ (void *)pgprot_val(prot));
+}
--
2.25.1
^ permalink raw reply related
* [PATCH v9 8/8] powerpc/32: use set_memory_attr()
From: Jordan Niethe @ 2021-03-16 3:17 UTC (permalink / raw)
To: linuxppc-dev
Cc: christophe.leroy, ajd, npiggin, naveen.n.rao, Jordan Niethe, dja
In-Reply-To: <20210316031741.1004850-1-jniethe5@gmail.com>
From: Christophe Leroy <christophe.leroy@c-s.fr>
Use set_memory_attr() instead of the PPC32 specific change_page_attr()
change_page_attr() was checking that the address was not mapped by
blocks and was handling highmem, but that's unneeded because the
affected pages can't be in highmem and block mapping verification
is already done by the callers.
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
[ruscur: rebase on powerpc/merge with Christophe's new patches]
Signed-off-by: Russell Currey <ruscur@russell.cc>
Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
---
arch/powerpc/mm/pgtable_32.c | 60 ++++++------------------------------
1 file changed, 10 insertions(+), 50 deletions(-)
diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c
index e0ec67a16887..dcf5ecca19d9 100644
--- a/arch/powerpc/mm/pgtable_32.c
+++ b/arch/powerpc/mm/pgtable_32.c
@@ -23,6 +23,7 @@
#include <linux/highmem.h>
#include <linux/memblock.h>
#include <linux/slab.h>
+#include <linux/set_memory.h>
#include <asm/pgalloc.h>
#include <asm/fixmap.h>
@@ -132,64 +133,20 @@ void __init mapin_ram(void)
}
}
-static int __change_page_attr_noflush(struct page *page, pgprot_t prot)
-{
- pte_t *kpte;
- unsigned long address;
-
- BUG_ON(PageHighMem(page));
- address = (unsigned long)page_address(page);
-
- if (v_block_mapped(address))
- return 0;
- kpte = virt_to_kpte(address);
- if (!kpte)
- return -EINVAL;
- __set_pte_at(&init_mm, address, kpte, mk_pte(page, prot), 0);
-
- return 0;
-}
-
-/*
- * Change the page attributes of an page in the linear mapping.
- *
- * THIS DOES NOTHING WITH BAT MAPPINGS, DEBUG USE ONLY
- */
-static int change_page_attr(struct page *page, int numpages, pgprot_t prot)
-{
- int i, err = 0;
- unsigned long flags;
- struct page *start = page;
-
- local_irq_save(flags);
- for (i = 0; i < numpages; i++, page++) {
- err = __change_page_attr_noflush(page, prot);
- if (err)
- break;
- }
- wmb();
- local_irq_restore(flags);
- flush_tlb_kernel_range((unsigned long)page_address(start),
- (unsigned long)page_address(page));
- return err;
-}
-
void mark_initmem_nx(void)
{
- struct page *page = virt_to_page(_sinittext);
unsigned long numpages = PFN_UP((unsigned long)_einittext) -
PFN_DOWN((unsigned long)_sinittext);
if (v_block_mapped((unsigned long)_sinittext))
mmu_mark_initmem_nx();
else
- change_page_attr(page, numpages, PAGE_KERNEL);
+ set_memory_attr((unsigned long)_sinittext, numpages, PAGE_KERNEL);
}
#ifdef CONFIG_STRICT_KERNEL_RWX
void mark_rodata_ro(void)
{
- struct page *page;
unsigned long numpages;
if (v_block_mapped((unsigned long)_stext + 1)) {
@@ -198,20 +155,18 @@ void mark_rodata_ro(void)
return;
}
- page = virt_to_page(_stext);
numpages = PFN_UP((unsigned long)_etext) -
PFN_DOWN((unsigned long)_stext);
- change_page_attr(page, numpages, PAGE_KERNEL_ROX);
+ set_memory_attr((unsigned long)_stext, numpages, PAGE_KERNEL_ROX);
/*
* mark .rodata as read only. Use __init_begin rather than __end_rodata
* to cover NOTES and EXCEPTION_TABLE.
*/
- page = virt_to_page(__start_rodata);
numpages = PFN_UP((unsigned long)__init_begin) -
PFN_DOWN((unsigned long)__start_rodata);
- change_page_attr(page, numpages, PAGE_KERNEL_RO);
+ set_memory_attr((unsigned long)__start_rodata, numpages, PAGE_KERNEL_RO);
// mark_initmem_nx() should have already run by now
ptdump_check_wx();
@@ -221,9 +176,14 @@ void mark_rodata_ro(void)
#ifdef CONFIG_DEBUG_PAGEALLOC
void __kernel_map_pages(struct page *page, int numpages, int enable)
{
+ unsigned long addr = (unsigned long)page_address(page);
+
if (PageHighMem(page))
return;
- change_page_attr(page, numpages, enable ? PAGE_KERNEL : __pgprot(0));
+ if (enable)
+ set_memory_attr(addr, numpages, PAGE_KERNEL);
+ else
+ set_memory_attr(addr, numpages, __pgprot(0));
}
#endif /* CONFIG_DEBUG_PAGEALLOC */
--
2.25.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox