All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/4] parisc: fixes for CONFIG_PREEMPT
@ 2021-10-08 20:48 Sven Schnelle
  2021-10-08 20:48 ` [PATCH 1/4] parisc: disable preemption during local tlb flush Sven Schnelle
                   ` (3 more replies)
  0 siblings, 4 replies; 7+ messages in thread
From: Sven Schnelle @ 2021-10-08 20:48 UTC (permalink / raw)
  To: deller; +Cc: linux-parisc

Out of curiosity i enabled CONFIG_PREEMPT on my c8000. The kernel didn't
even compile. After fixing compilation i noticed a lot of segmentation
faults - usually a few processes crashed already at boot, with sshd the
most notable one. Most of the time the processes where crashing with a
DTLB or ITLB miss.

With these fixes, i was able to compile a linux kernel on the c8000
with preemption enabled without crashes.

Sven Schnelle (4):
  parisc: disable preemption during local tlb flush
  parisc: fix preempt_count() check in entry.S
  parisc: disable preemption in send_IPI_allbutself()
  parisc: fix warning in flush_tlb_all

 arch/parisc/kernel/cache.c | 3 +++
 arch/parisc/kernel/entry.S | 5 +++--
 arch/parisc/kernel/smp.c   | 3 ++-
 arch/parisc/mm/init.c      | 4 ++--
 4 files changed, 10 insertions(+), 5 deletions(-)

-- 
2.33.0


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 1/4] parisc: disable preemption during local tlb flush
  2021-10-08 20:48 [PATCH 0/4] parisc: fixes for CONFIG_PREEMPT Sven Schnelle
@ 2021-10-08 20:48 ` Sven Schnelle
  2021-10-08 21:35   ` Sven Schnelle
  2021-10-08 20:48 ` [PATCH 2/4] parisc: fix preempt_count() check in entry.S Sven Schnelle
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 7+ messages in thread
From: Sven Schnelle @ 2021-10-08 20:48 UTC (permalink / raw)
  To: deller; +Cc: linux-parisc

flush_cache_mm() fetches %sr3 via mtsp(3). If it matches mm->context,
it flushes caches and the TLB. However, the TLB is cpu-local, so if the
code gets preempted shortly after the mtsp(), and later resumed on another
CPU, the wrong TLB is flushed.

Signed-off-by: Sven Schnelle <svens@stackframe.org>
---
 arch/parisc/kernel/cache.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c
index 39e02227e231..90656c49bc07 100644
--- a/arch/parisc/kernel/cache.c
+++ b/arch/parisc/kernel/cache.c
@@ -558,6 +558,7 @@ void flush_cache_mm(struct mm_struct *mm)
 		return;
 	}
 
+	preempt_disable();
 	if (mm->context == mfsp(3)) {
 		for (vma = mm->mmap; vma; vma = vma->vm_next) {
 			flush_user_dcache_range_asm(vma->vm_start, vma->vm_end);
@@ -565,8 +566,10 @@ void flush_cache_mm(struct mm_struct *mm)
 				flush_user_icache_range_asm(vma->vm_start, vma->vm_end);
 			flush_tlb_range(vma, vma->vm_start, vma->vm_end);
 		}
+		preempt_enable();
 		return;
 	}
+	preempt_enable();
 
 	pgd = mm->pgd;
 	for (vma = mm->mmap; vma; vma = vma->vm_next) {
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 2/4] parisc: fix preempt_count() check in entry.S
  2021-10-08 20:48 [PATCH 0/4] parisc: fixes for CONFIG_PREEMPT Sven Schnelle
  2021-10-08 20:48 ` [PATCH 1/4] parisc: disable preemption during local tlb flush Sven Schnelle
@ 2021-10-08 20:48 ` Sven Schnelle
  2021-10-08 20:48 ` [PATCH 3/4] parisc: disable preemption in send_IPI_allbutself() Sven Schnelle
  2021-10-08 20:48 ` [PATCH 4/4] parisc: fix warning in flush_tlb_all Sven Schnelle
  3 siblings, 0 replies; 7+ messages in thread
From: Sven Schnelle @ 2021-10-08 20:48 UTC (permalink / raw)
  To: deller; +Cc: linux-parisc

preempt_count in struct thread_info is unsigned int,
but the entry.S code used LDREG, which generates a 64 bit
load when compiled for 64 bit. Fix this to use an ldw and
also change the condition in the compare one line below
to only compares 32 bits, although ldw zero extends, and
that should work with a 64 bit compare.

Signed-off-by: Sven Schnelle <svens@stackframe.org>
---
 arch/parisc/kernel/entry.S | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S
index 9f939afe6b88..e9e598c18cb0 100644
--- a/arch/parisc/kernel/entry.S
+++ b/arch/parisc/kernel/entry.S
@@ -974,8 +974,8 @@ intr_do_preempt:
 
 	/* current_thread_info()->preempt_count */
 	mfctl	%cr30, %r1
-	LDREG	TI_PRE_COUNT(%r1), %r19
-	cmpib,COND(<>)	0, %r19, intr_restore	/* if preempt_count > 0 */
+	ldw	TI_PRE_COUNT(%r1), %r19
+	cmpib,<>	0, %r19, intr_restore	/* if preempt_count > 0 */
 	nop				/* prev insn branched backwards */
 
 	/* check if we interrupted a critical path */
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 3/4] parisc: disable preemption in send_IPI_allbutself()
  2021-10-08 20:48 [PATCH 0/4] parisc: fixes for CONFIG_PREEMPT Sven Schnelle
  2021-10-08 20:48 ` [PATCH 1/4] parisc: disable preemption during local tlb flush Sven Schnelle
  2021-10-08 20:48 ` [PATCH 2/4] parisc: fix preempt_count() check in entry.S Sven Schnelle
@ 2021-10-08 20:48 ` Sven Schnelle
  2021-10-08 20:48 ` [PATCH 4/4] parisc: fix warning in flush_tlb_all Sven Schnelle
  3 siblings, 0 replies; 7+ messages in thread
From: Sven Schnelle @ 2021-10-08 20:48 UTC (permalink / raw)
  To: deller; +Cc: linux-parisc

Otherwise we might not stop all other CPUs.

Signed-off-by: Sven Schnelle <svens@stackframe.org>
---
 arch/parisc/kernel/smp.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c
index 1405b603b91b..3413e6949c87 100644
--- a/arch/parisc/kernel/smp.c
+++ b/arch/parisc/kernel/smp.c
@@ -219,11 +219,13 @@ static inline void
 send_IPI_allbutself(enum ipi_message_type op)
 {
 	int i;
-	
+
+	preempt_disable();
 	for_each_online_cpu(i) {
 		if (i != smp_processor_id())
 			send_IPI_single(i, op);
 	}
+	preempt_enable();
 }
 
 
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 4/4] parisc: fix warning in flush_tlb_all
  2021-10-08 20:48 [PATCH 0/4] parisc: fixes for CONFIG_PREEMPT Sven Schnelle
                   ` (2 preceding siblings ...)
  2021-10-08 20:48 ` [PATCH 3/4] parisc: disable preemption in send_IPI_allbutself() Sven Schnelle
@ 2021-10-08 20:48 ` Sven Schnelle
  3 siblings, 0 replies; 7+ messages in thread
From: Sven Schnelle @ 2021-10-08 20:48 UTC (permalink / raw)
  To: deller; +Cc: linux-parisc

I've got the following splat after enabling preemption:

[    3.724721] BUG: using __this_cpu_add() in preemptible [00000000] code: swapper/0/1
[    3.734630] caller is __this_cpu_preempt_check+0x38/0x50
[    3.740635] CPU: 1 PID: 1 Comm: swapper/0 Not tainted 5.15.0-rc4-64bit+ #324
[    3.744605] Hardware name: 9000/785/C8000
[    3.744605] Backtrace:
[    3.744605]  [<00000000401d9d58>] show_stack+0x74/0xb0
[    3.744605]  [<0000000040c27bd4>] dump_stack_lvl+0x10c/0x188
[    3.744605]  [<0000000040c27c84>] dump_stack+0x34/0x48
[    3.744605]  [<0000000040c33438>] check_preemption_disabled+0x178/0x1b0
[    3.744605]  [<0000000040c334f8>] __this_cpu_preempt_check+0x38/0x50
[    3.744605]  [<00000000401d632c>] flush_tlb_all+0x58/0x2e0
[    3.744605]  [<00000000401075c0>] 0x401075c0
[    3.744605]  [<000000004010b8fc>] 0x4010b8fc
[    3.744605]  [<00000000401080fc>] 0x401080fc
[    3.744605]  [<00000000401d5224>] do_one_initcall+0x128/0x378
[    3.744605]  [<0000000040102de8>] 0x40102de8
[    3.744605]  [<0000000040c33864>] kernel_init+0x60/0x3a8
[    3.744605]  [<00000000401d1020>] ret_from_kernel_thread+0x20/0x28
[    3.744605]

Fix this by moving the __inc_irq_stat() into the locked section.

Signed-off-by: Sven Schnelle <svens@stackframe.org>
---
 arch/parisc/mm/init.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c
index 3f7d6d5b56ac..65f50f072a87 100644
--- a/arch/parisc/mm/init.c
+++ b/arch/parisc/mm/init.c
@@ -842,9 +842,9 @@ void flush_tlb_all(void)
 {
 	int do_recycle;
 
-	__inc_irq_stat(irq_tlb_count);
 	do_recycle = 0;
 	spin_lock(&sid_lock);
+	__inc_irq_stat(irq_tlb_count);
 	if (dirty_space_ids > RECYCLE_THRESHOLD) {
 	    BUG_ON(recycle_inuse);  /* FIXME: Use a semaphore/wait queue here */
 	    get_dirty_sids(&recycle_ndirty,recycle_dirty_array);
@@ -863,8 +863,8 @@ void flush_tlb_all(void)
 #else
 void flush_tlb_all(void)
 {
-	__inc_irq_stat(irq_tlb_count);
 	spin_lock(&sid_lock);
+	__inc_irq_stat(irq_tlb_count);
 	flush_tlb_all_local(NULL);
 	recycle_sids();
 	spin_unlock(&sid_lock);
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/4] parisc: disable preemption during local tlb flush
  2021-10-08 20:48 ` [PATCH 1/4] parisc: disable preemption during local tlb flush Sven Schnelle
@ 2021-10-08 21:35   ` Sven Schnelle
  2021-10-09 12:30     ` Helge Deller
  0 siblings, 1 reply; 7+ messages in thread
From: Sven Schnelle @ 2021-10-08 21:35 UTC (permalink / raw)
  To: deller; +Cc: linux-parisc

Sven Schnelle <svens@stackframe.org> writes:

> flush_cache_mm() fetches %sr3 via mtsp(3). If it matches mm->context,
> it flushes caches and the TLB. However, the TLB is cpu-local, so if the
> code gets preempted shortly after the mtsp(), and later resumed on another
> CPU, the wrong TLB is flushed.
>
> Signed-off-by: Sven Schnelle <svens@stackframe.org>
> ---
>  arch/parisc/kernel/cache.c | 3 +++
>  1 file changed, 3 insertions(+)
>
> diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c
> index 39e02227e231..90656c49bc07 100644
> --- a/arch/parisc/kernel/cache.c
> +++ b/arch/parisc/kernel/cache.c
> @@ -558,6 +558,7 @@ void flush_cache_mm(struct mm_struct *mm)
>  		return;
>  	}
>  
> +	preempt_disable();
>  	if (mm->context == mfsp(3)) {
>  		for (vma = mm->mmap; vma; vma = vma->vm_next) {
>  			flush_user_dcache_range_asm(vma->vm_start, vma->vm_end);
> @@ -565,8 +566,10 @@ void flush_cache_mm(struct mm_struct *mm)
>  				flush_user_icache_range_asm(vma->vm_start, vma->vm_end);
>  			flush_tlb_range(vma, vma->vm_start, vma->vm_end);
>  		}
> +		preempt_enable();
>  		return;
>  	}
> +	preempt_enable();
>  
>  	pgd = mm->pgd;
>  	for (vma = mm->mmap; vma; vma = vma->vm_next) {

I noticed that flush_cache_range() has the same problem. Helge, let me
know whether i should send a v2 with an additional patch, or a single
follow up patch. Both functions also look very similar, so i think
best would be to combine the code of these two functions.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/4] parisc: disable preemption during local tlb flush
  2021-10-08 21:35   ` Sven Schnelle
@ 2021-10-09 12:30     ` Helge Deller
  0 siblings, 0 replies; 7+ messages in thread
From: Helge Deller @ 2021-10-09 12:30 UTC (permalink / raw)
  To: Sven Schnelle; +Cc: linux-parisc

On 10/8/21 23:35, Sven Schnelle wrote:
> Sven Schnelle <svens@stackframe.org> writes:
>
>> flush_cache_mm() fetches %sr3 via mtsp(3). If it matches mm->context,
>> it flushes caches and the TLB. However, the TLB is cpu-local, so if the
>> code gets preempted shortly after the mtsp(), and later resumed on another
>> CPU, the wrong TLB is flushed.
>>
>> Signed-off-by: Sven Schnelle <svens@stackframe.org>
>> ---
>>  arch/parisc/kernel/cache.c | 3 +++
>>  1 file changed, 3 insertions(+)
>>
>> diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c
>> index 39e02227e231..90656c49bc07 100644
>> --- a/arch/parisc/kernel/cache.c
>> +++ b/arch/parisc/kernel/cache.c
>> @@ -558,6 +558,7 @@ void flush_cache_mm(struct mm_struct *mm)
>>  		return;
>>  	}
>>
>> +	preempt_disable();
>>  	if (mm->context == mfsp(3)) {
>>  		for (vma = mm->mmap; vma; vma = vma->vm_next) {
>>  			flush_user_dcache_range_asm(vma->vm_start, vma->vm_end);
>> @@ -565,8 +566,10 @@ void flush_cache_mm(struct mm_struct *mm)
>>  				flush_user_icache_range_asm(vma->vm_start, vma->vm_end);
>>  			flush_tlb_range(vma, vma->vm_start, vma->vm_end);
>>  		}
>> +		preempt_enable();
>>  		return;
>>  	}
>> +	preempt_enable();
>>
>>  	pgd = mm->pgd;
>>  	for (vma = mm->mmap; vma; vma = vma->vm_next) {
>
> I noticed that flush_cache_range() has the same problem. Helge, let me
> know whether i should send a v2 with an additional patch, or a single
> follow up patch. Both functions also look very similar, so i think
> best would be to combine the code of these two functions.

I'm fine with either option.

Thanks for your patches!
Helge

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2021-10-09 12:30 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-10-08 20:48 [PATCH 0/4] parisc: fixes for CONFIG_PREEMPT Sven Schnelle
2021-10-08 20:48 ` [PATCH 1/4] parisc: disable preemption during local tlb flush Sven Schnelle
2021-10-08 21:35   ` Sven Schnelle
2021-10-09 12:30     ` Helge Deller
2021-10-08 20:48 ` [PATCH 2/4] parisc: fix preempt_count() check in entry.S Sven Schnelle
2021-10-08 20:48 ` [PATCH 3/4] parisc: disable preemption in send_IPI_allbutself() Sven Schnelle
2021-10-08 20:48 ` [PATCH 4/4] parisc: fix warning in flush_tlb_all Sven Schnelle

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.