All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] MIPS: Fix ejtag handler on SMP
@ 2018-06-08  5:51 r
  2018-06-08 22:37   ` Paul Burton
  0 siblings, 1 reply; 5+ messages in thread
From: r @ 2018-06-08  5:51 UTC (permalink / raw)
  To: linux-mips, paul.burton; +Cc: jhogan, ralf, Heiher

From: Heiher <r@hev.cc>

On SMP systems, the shared ejtag debug buffer may be overwritten by
other cores, because every cores can generate ejtag exception at
same time.

Unfortunately, in that context, it's difficult to relax more registers
to access per cpu buffers. so use ll/sc to serialize the access.

Signed-off-by: Heiher <r@hev.cc>
---
 arch/mips/kernel/genex.S | 46 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 46 insertions(+)

diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S
index 37b9383eacd3..3804afd878f8 100644
--- a/arch/mips/kernel/genex.S
+++ b/arch/mips/kernel/genex.S
@@ -354,16 +354,56 @@ NESTED(ejtag_debug_handler, PT_SIZE, sp)
 	sll	k0, k0, 30	# Check for SDBBP.
 	bgez	k0, ejtag_return
 
+#ifdef CONFIG_SMP
+1:	PTR_LA	k0, ejtag_debug_buffer_spinlock
+	ll	k0, 0(k0)
+	bnez	k0, 1b
+	PTR_LA	k0, ejtag_debug_buffer_spinlock
+	sc	k0, 0(k0)
+	beqz	k0, 1b
+# ifdef CONFIG_WEAK_REORDERING_BEYOND_LLSC
+	sync
+# endif
+
+	PTR_LA	k0, ejtag_debug_buffer
+	LONG_S	k1, 0(k0)
+
+	mfc0	k1, CP0_EBASE
+	andi	k1, MIPS_EBASE_CPUNUM
+	PTR_SLL	k1, LONGLOG
+	PTR_LA	k0, ejtag_debug_buffer_per_cpu
+	PTR_ADDU k0, k1
+
+	PTR_LA	k1, ejtag_debug_buffer
+	LONG_L	k1, 0(k1)
+	LONG_S	k1, 0(k0)
+
+	PTR_LA	k0, ejtag_debug_buffer_spinlock
+	sw	zero, 0(k0)
+#else
 	PTR_LA	k0, ejtag_debug_buffer
 	LONG_S	k1, 0(k0)
+#endif
+
 	SAVE_ALL
 	move	a0, sp
 	jal	ejtag_exception_handler
 	RESTORE_ALL
+
+#ifdef CONFIG_SMP
+	mfc0	k1, CP0_EBASE
+	andi	k1, MIPS_EBASE_CPUNUM
+	PTR_SLL	k1, LONGLOG
+	PTR_LA	k0, ejtag_debug_buffer_per_cpu
+	PTR_ADDU k0, k1
+	LONG_L	k1, 0(k0)
+#else
 	PTR_LA	k0, ejtag_debug_buffer
 	LONG_L	k1, 0(k0)
+#endif
 
 ejtag_return:
+	back_to_back_c0_hazard
 	MFC0	k0, CP0_DESAVE
 	.set	mips32
 	deret
@@ -377,6 +417,12 @@ ejtag_return:
 	.data
 EXPORT(ejtag_debug_buffer)
 	.fill	LONGSIZE
+#ifdef CONFIG_SMP
+EXPORT(ejtag_debug_buffer_spinlock)
+	.fill	LONGSIZE
+EXPORT(ejtag_debug_buffer_per_cpu)
+	.fill	LONGSIZE * NR_CPUS
+#endif
 	.previous
 
 	__INIT
-- 
2.17.1

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

* Re: [PATCH] MIPS: Fix ejtag handler on SMP
@ 2018-06-08 22:37   ` Paul Burton
  0 siblings, 0 replies; 5+ messages in thread
From: Paul Burton @ 2018-06-08 22:37 UTC (permalink / raw)
  To: r; +Cc: linux-mips, jhogan, ralf

Hi Heiher,

On Fri, Jun 08, 2018 at 01:51:09PM +0800, r@hev.cc wrote:
> diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S
> index 37b9383eacd3..3804afd878f8 100644
> --- a/arch/mips/kernel/genex.S
> +++ b/arch/mips/kernel/genex.S
> @@ -354,16 +354,56 @@ NESTED(ejtag_debug_handler, PT_SIZE, sp)
>  	sll	k0, k0, 30	# Check for SDBBP.
>  	bgez	k0, ejtag_return
>  
> +#ifdef CONFIG_SMP
> +1:	PTR_LA	k0, ejtag_debug_buffer_spinlock
> +	ll	k0, 0(k0)
> +	bnez	k0, 1b
> +	PTR_LA	k0, ejtag_debug_buffer_spinlock
> +	sc	k0, 0(k0)
> +	beqz	k0, 1b
> +# ifdef CONFIG_WEAK_REORDERING_BEYOND_LLSC
> +	sync
> +# endif
> +
> +	PTR_LA	k0, ejtag_debug_buffer
> +	LONG_S	k1, 0(k0)
> +
> +	mfc0	k1, CP0_EBASE
> +	andi	k1, MIPS_EBASE_CPUNUM
> +	PTR_SLL	k1, LONGLOG
> +	PTR_LA	k0, ejtag_debug_buffer_per_cpu
> +	PTR_ADDU k0, k1

Neat - I like the concept of using the spinlock for just a short window
to free up k1, then using a per-CPU buffer.

Unfortunately it's not going to be as simple as using EBase.CPUNum, for
at least 2 reasons:

  - EBase.CPUNum doesn't always equal the Linux CPU number. For example
    in many systems which implement multi-threading ASE CPUNum is
    actually just a concatenation of some fixed number of bits
    specifying the core number and some fixed number of bits specifying
    the VP(E) number. So for example we might have a system with 2 cores
    each of which have 2 threads, but whose numbering looks like this:

      Linux CPU Number | Core Number | VP(E) Number | EBase.CPUNum
      -----------------|-------------|--------------|-------------
                     0 |  0b00 / 0x0 |   0b00 / 0x0 | 0b0000 / 0x0
		     1 |  0b00 / 0x0 |   0b01 / 0x1 | 0b0001 / 0x1
		     2 |  0b01 / 0x1 |   0b00 / 0x0 | 0b0100 / 0x4
		     3 |  0b01 / 0x1 |   0b01 / 0x1 | 0b0101 / 0x5

    This means that it might be the case that EBase.CPUNum >= NR_CPUS,
    which would result in a buffer overflow here.

    There are other ways this could happen too, for example if the
    kernel is configured with CONFIG_NR_CPUS=2 and run on a system which
    actually has more than 2 CPUs we'd have problems if the kernel was
    actually running on CPUs besides the ones CPUNum refers to as 0 & 1.

  - Some newer MIPS CPUs such as the I6500 introduce the concept of
    clusters, which are a layer of CPU topology beyond cores. In these
    systems EBase.CPUNum may not be aware of clusters at all, so for
    example the first CPU in each cluster may both have EBase.CPUNum
    equal to zero. MIPSr6 introduced the GlobalNumber register to
    resolve this problem.

One option would be to load the CPU number the same way
smp_processor_id() does with:

    lw	k1, TI_CPU(gp)

This has the disadvantage that things may go wrong if we take an EJTAG
exception before the gp register has been setup when a CPU is onlined,
but that should hopefully be a very small window of time. I think that
may be our best option.

Thanks,
    Paul

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

* Re: [PATCH] MIPS: Fix ejtag handler on SMP
@ 2018-06-08 22:37   ` Paul Burton
  0 siblings, 0 replies; 5+ messages in thread
From: Paul Burton @ 2018-06-08 22:37 UTC (permalink / raw)
  To: r; +Cc: linux-mips, jhogan, ralf

Hi Heiher,

On Fri, Jun 08, 2018 at 01:51:09PM +0800, r@hev.cc wrote:
> diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S
> index 37b9383eacd3..3804afd878f8 100644
> --- a/arch/mips/kernel/genex.S
> +++ b/arch/mips/kernel/genex.S
> @@ -354,16 +354,56 @@ NESTED(ejtag_debug_handler, PT_SIZE, sp)
>  	sll	k0, k0, 30	# Check for SDBBP.
>  	bgez	k0, ejtag_return
>  
> +#ifdef CONFIG_SMP
> +1:	PTR_LA	k0, ejtag_debug_buffer_spinlock
> +	ll	k0, 0(k0)
> +	bnez	k0, 1b
> +	PTR_LA	k0, ejtag_debug_buffer_spinlock
> +	sc	k0, 0(k0)
> +	beqz	k0, 1b
> +# ifdef CONFIG_WEAK_REORDERING_BEYOND_LLSC
> +	sync
> +# endif
> +
> +	PTR_LA	k0, ejtag_debug_buffer
> +	LONG_S	k1, 0(k0)
> +
> +	mfc0	k1, CP0_EBASE
> +	andi	k1, MIPS_EBASE_CPUNUM
> +	PTR_SLL	k1, LONGLOG
> +	PTR_LA	k0, ejtag_debug_buffer_per_cpu
> +	PTR_ADDU k0, k1

Neat - I like the concept of using the spinlock for just a short window
to free up k1, then using a per-CPU buffer.

Unfortunately it's not going to be as simple as using EBase.CPUNum, for
at least 2 reasons:

  - EBase.CPUNum doesn't always equal the Linux CPU number. For example
    in many systems which implement multi-threading ASE CPUNum is
    actually just a concatenation of some fixed number of bits
    specifying the core number and some fixed number of bits specifying
    the VP(E) number. So for example we might have a system with 2 cores
    each of which have 2 threads, but whose numbering looks like this:

      Linux CPU Number | Core Number | VP(E) Number | EBase.CPUNum
      -----------------|-------------|--------------|-------------
                     0 |  0b00 / 0x0 |   0b00 / 0x0 | 0b0000 / 0x0
		     1 |  0b00 / 0x0 |   0b01 / 0x1 | 0b0001 / 0x1
		     2 |  0b01 / 0x1 |   0b00 / 0x0 | 0b0100 / 0x4
		     3 |  0b01 / 0x1 |   0b01 / 0x1 | 0b0101 / 0x5

    This means that it might be the case that EBase.CPUNum >= NR_CPUS,
    which would result in a buffer overflow here.

    There are other ways this could happen too, for example if the
    kernel is configured with CONFIG_NR_CPUS=2 and run on a system which
    actually has more than 2 CPUs we'd have problems if the kernel was
    actually running on CPUs besides the ones CPUNum refers to as 0 & 1.

  - Some newer MIPS CPUs such as the I6500 introduce the concept of
    clusters, which are a layer of CPU topology beyond cores. In these
    systems EBase.CPUNum may not be aware of clusters at all, so for
    example the first CPU in each cluster may both have EBase.CPUNum
    equal to zero. MIPSr6 introduced the GlobalNumber register to
    resolve this problem.

One option would be to load the CPU number the same way
smp_processor_id() does with:

    lw	k1, TI_CPU(gp)

This has the disadvantage that things may go wrong if we take an EJTAG
exception before the gp register has been setup when a CPU is onlined,
but that should hopefully be a very small window of time. I think that
may be our best option.

Thanks,
    Paul

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

* Re: [PATCH] MIPS: Fix ejtag handler on SMP
  2018-03-30  9:05 r
@ 2018-04-03  8:42 ` James Hogan
  0 siblings, 0 replies; 5+ messages in thread
From: James Hogan @ 2018-04-03  8:42 UTC (permalink / raw)
  To: r; +Cc: ralf, linux-mips

[-- Attachment #1: Type: text/plain, Size: 1502 bytes --]

On Fri, Mar 30, 2018 at 05:05:15PM +0800, r@hev.cc wrote:
> From: Heiher <r@hev.cc>

Please can you add a proper commit description, explaining the problem
and what your patch does to fix it.

> 
> Signed-off-by: Heiher <r@hev.cc>
> ---
>  arch/mips/kernel/genex.S | 19 +++++++++++++++++++
>  1 file changed, 19 insertions(+)
> 
> diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S
> index 37b9383eacd3..9e0857fbe281 100644
> --- a/arch/mips/kernel/genex.S
> +++ b/arch/mips/kernel/genex.S
> @@ -354,6 +354,17 @@ NESTED(ejtag_debug_handler, PT_SIZE, sp)
>  	sll	k0, k0, 30	# Check for SDBBP.
>  	bgez	k0, ejtag_return
>  
> +#ifdef CONFIG_SMP
> +	PTR_LA	k0, ejtag_debug_buffer
> +1:	sync

Is the sync necessary? Or is that one of those platform specific
workarounds?

> +	ll	k0, LONGSIZE(k0)
> +	bnez	k0, 1b
> +	PTR_LA	k0, ejtag_debug_buffer
> +	sc	k0, LONGSIZE(k0)
> +	beqz	k0, 1b
> +	sync
> +#endif
> +
>  	PTR_LA	k0, ejtag_debug_buffer
>  	LONG_S	k1, 0(k0)
>  	SAVE_ALL
> @@ -363,6 +374,11 @@ NESTED(ejtag_debug_handler, PT_SIZE, sp)
>  	PTR_LA	k0, ejtag_debug_buffer
>  	LONG_L	k1, 0(k0)
>  
> +#ifdef CONFIG_SMP
> +	sw	zero, LONGSIZE(k0)
> +	sync

Same question. Its about to deret anyway which should cover that I
think?

> +#endif
> +
>  ejtag_return:
>  	MFC0	k0, CP0_DESAVE

Not specific to your patch, but I wonder whether there should be a
back_to_back_c0_hazard (ehb on r2+) somewhere before this MFC0.

Cheers
James

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* [PATCH] MIPS: Fix ejtag handler on SMP
@ 2018-03-30  9:05 r
  2018-04-03  8:42 ` James Hogan
  0 siblings, 1 reply; 5+ messages in thread
From: r @ 2018-03-30  9:05 UTC (permalink / raw)
  To: ralf, linux-mips; +Cc: Heiher

From: Heiher <r@hev.cc>

Signed-off-by: Heiher <r@hev.cc>
---
 arch/mips/kernel/genex.S | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S
index 37b9383eacd3..9e0857fbe281 100644
--- a/arch/mips/kernel/genex.S
+++ b/arch/mips/kernel/genex.S
@@ -354,6 +354,17 @@ NESTED(ejtag_debug_handler, PT_SIZE, sp)
 	sll	k0, k0, 30	# Check for SDBBP.
 	bgez	k0, ejtag_return
 
+#ifdef CONFIG_SMP
+	PTR_LA	k0, ejtag_debug_buffer
+1:	sync
+	ll	k0, LONGSIZE(k0)
+	bnez	k0, 1b
+	PTR_LA	k0, ejtag_debug_buffer
+	sc	k0, LONGSIZE(k0)
+	beqz	k0, 1b
+	sync
+#endif
+
 	PTR_LA	k0, ejtag_debug_buffer
 	LONG_S	k1, 0(k0)
 	SAVE_ALL
@@ -363,6 +374,11 @@ NESTED(ejtag_debug_handler, PT_SIZE, sp)
 	PTR_LA	k0, ejtag_debug_buffer
 	LONG_L	k1, 0(k0)
 
+#ifdef CONFIG_SMP
+	sw	zero, LONGSIZE(k0)
+	sync
+#endif
+
 ejtag_return:
 	MFC0	k0, CP0_DESAVE
 	.set	mips32
@@ -377,6 +393,9 @@ ejtag_return:
 	.data
 EXPORT(ejtag_debug_buffer)
 	.fill	LONGSIZE
+#ifdef CONFIG_SMP
+	.fill	LONGSIZE
+#endif
 	.previous
 
 	__INIT
-- 
2.16.3

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

end of thread, other threads:[~2018-06-08 22:37 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-06-08  5:51 [PATCH] MIPS: Fix ejtag handler on SMP r
2018-06-08 22:37 ` Paul Burton
2018-06-08 22:37   ` Paul Burton
  -- strict thread matches above, loose matches on Subject: below --
2018-03-30  9:05 r
2018-04-03  8:42 ` James Hogan

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.