All of lore.kernel.org
 help / color / mirror / Atom feed
From: James Hogan <james.hogan@imgtec.com>
To: Markos Chandras <markos.chandras@imgtec.com>,
	<linux-mips@linux-mips.org>
Cc: <stable@vger.kernel.org>
Subject: Re: [PATCH 2/3] MIPS: HTW: Prevent accidental HTW start due to nested htw_{start,stop}
Date: Mon, 26 Jan 2015 11:36:44 +0000	[thread overview]
Message-ID: <54C626CC.2070104@imgtec.com> (raw)
In-Reply-To: <1422265236-29290-3-git-send-email-markos.chandras@imgtec.com>

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

Hi Markos,

On 26/01/15 09:40, Markos Chandras wrote:
> activate_mm() and switch_mm() call get_new_mmu_context() which in turn
> can enable the HTW before the entryhi is changed with the new ASID.
> Since the latter will enable the HTW in local_flush_tlb_all(),
> then there is a small timing window where the HTW is running with the
> new ASID but with an old pgd since the TLBMISS_HANDLER_SETUP_PGD
> hasn't assigned a new one yet. In order to prevent that, we introduce a
> simple htw counter to avoid starting HTW accidentally due to nested
> htw_{start,stop}() sequences. Moreover, since various IPI calls can
> enforce TLB flushing operations on a different core, such an operation
> may interrupt another htw_{stop,start} in progress leading inconsistent
> updates of the htw_seq variable. In order to avoid that, we disable the
> interrupts whenever we update that variable.
> 
> Cc: <stable@vger.kernel.org> # 3.17+
> Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
> ---
>  arch/mips/include/asm/cpu-info.h    |  5 +++++
>  arch/mips/include/asm/mmu_context.h |  7 ++++++-
>  arch/mips/include/asm/pgtable.h     | 17 ++++++++++++++---
>  arch/mips/kernel/cpu-probe.c        |  4 +++-
>  4 files changed, 28 insertions(+), 5 deletions(-)
> 
> diff --git a/arch/mips/include/asm/cpu-info.h b/arch/mips/include/asm/cpu-info.h
> index a6c9ccb33c5c..c3f4f2d2e108 100644
> --- a/arch/mips/include/asm/cpu-info.h
> +++ b/arch/mips/include/asm/cpu-info.h
> @@ -84,6 +84,11 @@ struct cpuinfo_mips {
>  	 * (shifted by _CACHE_SHIFT)
>  	 */
>  	unsigned int		writecombine;
> +	/*
> +	 * Simple counter to prevent enabling HTW in nested
> +	 * htw_start/htw_stop calls
> +	 */
> +	unsigned int		htw_seq;
>  } __attribute__((aligned(SMP_CACHE_BYTES)));
>  
>  extern struct cpuinfo_mips cpu_data[];
> diff --git a/arch/mips/include/asm/mmu_context.h b/arch/mips/include/asm/mmu_context.h
> index 2f82568a3ee4..bc01579a907a 100644
> --- a/arch/mips/include/asm/mmu_context.h
> +++ b/arch/mips/include/asm/mmu_context.h
> @@ -25,7 +25,6 @@ do {									\
>  	if (cpu_has_htw) {						\
>  		write_c0_pwbase(pgd);					\
>  		back_to_back_c0_hazard();				\
> -		htw_reset();						\
>  	}								\
>  } while (0)
>  
> @@ -142,6 +141,7 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
>  	unsigned long flags;
>  	local_irq_save(flags);
>  
> +	htw_stop();
>  	/* Check if our ASID is of an older version and thus invalid */
>  	if ((cpu_context(cpu, next) ^ asid_cache(cpu)) & ASID_VERSION_MASK)
>  		get_new_mmu_context(next, cpu);
> @@ -154,6 +154,7 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
>  	 */
>  	cpumask_clear_cpu(cpu, mm_cpumask(prev));
>  	cpumask_set_cpu(cpu, mm_cpumask(next));
> +	htw_start();
>  
>  	local_irq_restore(flags);
>  }
> @@ -180,6 +181,7 @@ activate_mm(struct mm_struct *prev, struct mm_struct *next)
>  
>  	local_irq_save(flags);
>  
> +	htw_stop();
>  	/* Unconditionally get a new ASID.  */
>  	get_new_mmu_context(next, cpu);
>  
> @@ -189,6 +191,7 @@ activate_mm(struct mm_struct *prev, struct mm_struct *next)
>  	/* mark mmu ownership change */
>  	cpumask_clear_cpu(cpu, mm_cpumask(prev));
>  	cpumask_set_cpu(cpu, mm_cpumask(next));
> +	htw_start();
>  
>  	local_irq_restore(flags);
>  }
> @@ -203,6 +206,7 @@ drop_mmu_context(struct mm_struct *mm, unsigned cpu)
>  	unsigned long flags;
>  
>  	local_irq_save(flags);
> +	htw_stop();
>  
>  	if (cpumask_test_cpu(cpu, mm_cpumask(mm)))  {
>  		get_new_mmu_context(mm, cpu);
> @@ -211,6 +215,7 @@ drop_mmu_context(struct mm_struct *mm, unsigned cpu)
>  		/* will get a new context next time */
>  		cpu_context(cpu, mm) = 0;
>  	}
> +	htw_start();
>  	local_irq_restore(flags);
>  }
>  
> diff --git a/arch/mips/include/asm/pgtable.h b/arch/mips/include/asm/pgtable.h
> index 7f7c558de9fc..d2c7e9e7447e 100644
> --- a/arch/mips/include/asm/pgtable.h
> +++ b/arch/mips/include/asm/pgtable.h
> @@ -99,19 +99,30 @@ extern void paging_init(void);
>  
>  #define htw_stop()							\
>  do {									\
> +	unsigned long flags;						\
> +									\
>  	if (cpu_has_htw) {						\
> +		local_irq_save(flags);					\

duplicate?

> +		raw_current_cpu_data.htw_seq++;				\

not "if (!raw_current_cpu_data.htw_seq++)) {"?

>  		write_c0_pwctl(read_c0_pwctl() &			\
>  			       ~(1 << MIPS_PWCTL_PWEN_SHIFT));		\
>  		back_to_back_c0_hazard();				\
> +		local_irq_restore(flags);				\
>  	}								\
>  } while(0)
>  
>  #define htw_start()							\
>  do {									\
> +	unsigned long flags;						\
> +									\
>  	if (cpu_has_htw) {						\
> -		write_c0_pwctl(read_c0_pwctl() |			\
> -			       (1 << MIPS_PWCTL_PWEN_SHIFT));		\
> -		back_to_back_c0_hazard();				\
> +		local_irq_save(flags);					\
> +		if (!--raw_current_cpu_data.htw_seq) {			\
> +			write_c0_pwctl(read_c0_pwctl() |		\
> +				       (1 << MIPS_PWCTL_PWEN_SHIFT));	\
> +			back_to_back_c0_hazard();			\
> +		}							\
> +		local_irq_restore(flags);				\
>  	}								\
>  } while(0)
>  
> diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
> index dc49cf30c2db..5d6e59f20750 100644
> --- a/arch/mips/kernel/cpu-probe.c
> +++ b/arch/mips/kernel/cpu-probe.c
> @@ -367,8 +367,10 @@ static inline unsigned int decode_config3(struct cpuinfo_mips *c)
>  	if (config3 & MIPS_CONF3_MSA)
>  		c->ases |= MIPS_ASE_MSA;
>  	/* Only tested on 32-bit cores */
> -	if ((config3 & MIPS_CONF3_PW) && config_enabled(CONFIG_32BIT))
> +	if ((config3 & MIPS_CONF3_PW) && config_enabled(CONFIG_32BIT)) {
> +		c->htw_seq = 0;

is that necessary, since cpu_data[] is global?

>  		c->options |= MIPS_CPU_HTW;
> +	}
>  
>  	return config3 & MIPS_CONF_M;
>  }
> 

Cheers
James


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

WARNING: multiple messages have this Message-ID (diff)
From: James Hogan <james.hogan@imgtec.com>
To: Markos Chandras <markos.chandras@imgtec.com>, linux-mips@linux-mips.org
Cc: stable@vger.kernel.org
Subject: Re: [PATCH 2/3] MIPS: HTW: Prevent accidental HTW start due to nested htw_{start,stop}
Date: Mon, 26 Jan 2015 11:36:44 +0000	[thread overview]
Message-ID: <54C626CC.2070104@imgtec.com> (raw)
Message-ID: <20150126113644.iMQXgH3Zq3kjwTDKpeTiC515uKCHQMdloVOGwbgSToA@z> (raw)
In-Reply-To: <1422265236-29290-3-git-send-email-markos.chandras@imgtec.com>

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

Hi Markos,

On 26/01/15 09:40, Markos Chandras wrote:
> activate_mm() and switch_mm() call get_new_mmu_context() which in turn
> can enable the HTW before the entryhi is changed with the new ASID.
> Since the latter will enable the HTW in local_flush_tlb_all(),
> then there is a small timing window where the HTW is running with the
> new ASID but with an old pgd since the TLBMISS_HANDLER_SETUP_PGD
> hasn't assigned a new one yet. In order to prevent that, we introduce a
> simple htw counter to avoid starting HTW accidentally due to nested
> htw_{start,stop}() sequences. Moreover, since various IPI calls can
> enforce TLB flushing operations on a different core, such an operation
> may interrupt another htw_{stop,start} in progress leading inconsistent
> updates of the htw_seq variable. In order to avoid that, we disable the
> interrupts whenever we update that variable.
> 
> Cc: <stable@vger.kernel.org> # 3.17+
> Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
> ---
>  arch/mips/include/asm/cpu-info.h    |  5 +++++
>  arch/mips/include/asm/mmu_context.h |  7 ++++++-
>  arch/mips/include/asm/pgtable.h     | 17 ++++++++++++++---
>  arch/mips/kernel/cpu-probe.c        |  4 +++-
>  4 files changed, 28 insertions(+), 5 deletions(-)
> 
> diff --git a/arch/mips/include/asm/cpu-info.h b/arch/mips/include/asm/cpu-info.h
> index a6c9ccb33c5c..c3f4f2d2e108 100644
> --- a/arch/mips/include/asm/cpu-info.h
> +++ b/arch/mips/include/asm/cpu-info.h
> @@ -84,6 +84,11 @@ struct cpuinfo_mips {
>  	 * (shifted by _CACHE_SHIFT)
>  	 */
>  	unsigned int		writecombine;
> +	/*
> +	 * Simple counter to prevent enabling HTW in nested
> +	 * htw_start/htw_stop calls
> +	 */
> +	unsigned int		htw_seq;
>  } __attribute__((aligned(SMP_CACHE_BYTES)));
>  
>  extern struct cpuinfo_mips cpu_data[];
> diff --git a/arch/mips/include/asm/mmu_context.h b/arch/mips/include/asm/mmu_context.h
> index 2f82568a3ee4..bc01579a907a 100644
> --- a/arch/mips/include/asm/mmu_context.h
> +++ b/arch/mips/include/asm/mmu_context.h
> @@ -25,7 +25,6 @@ do {									\
>  	if (cpu_has_htw) {						\
>  		write_c0_pwbase(pgd);					\
>  		back_to_back_c0_hazard();				\
> -		htw_reset();						\
>  	}								\
>  } while (0)
>  
> @@ -142,6 +141,7 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
>  	unsigned long flags;
>  	local_irq_save(flags);
>  
> +	htw_stop();
>  	/* Check if our ASID is of an older version and thus invalid */
>  	if ((cpu_context(cpu, next) ^ asid_cache(cpu)) & ASID_VERSION_MASK)
>  		get_new_mmu_context(next, cpu);
> @@ -154,6 +154,7 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
>  	 */
>  	cpumask_clear_cpu(cpu, mm_cpumask(prev));
>  	cpumask_set_cpu(cpu, mm_cpumask(next));
> +	htw_start();
>  
>  	local_irq_restore(flags);
>  }
> @@ -180,6 +181,7 @@ activate_mm(struct mm_struct *prev, struct mm_struct *next)
>  
>  	local_irq_save(flags);
>  
> +	htw_stop();
>  	/* Unconditionally get a new ASID.  */
>  	get_new_mmu_context(next, cpu);
>  
> @@ -189,6 +191,7 @@ activate_mm(struct mm_struct *prev, struct mm_struct *next)
>  	/* mark mmu ownership change */
>  	cpumask_clear_cpu(cpu, mm_cpumask(prev));
>  	cpumask_set_cpu(cpu, mm_cpumask(next));
> +	htw_start();
>  
>  	local_irq_restore(flags);
>  }
> @@ -203,6 +206,7 @@ drop_mmu_context(struct mm_struct *mm, unsigned cpu)
>  	unsigned long flags;
>  
>  	local_irq_save(flags);
> +	htw_stop();
>  
>  	if (cpumask_test_cpu(cpu, mm_cpumask(mm)))  {
>  		get_new_mmu_context(mm, cpu);
> @@ -211,6 +215,7 @@ drop_mmu_context(struct mm_struct *mm, unsigned cpu)
>  		/* will get a new context next time */
>  		cpu_context(cpu, mm) = 0;
>  	}
> +	htw_start();
>  	local_irq_restore(flags);
>  }
>  
> diff --git a/arch/mips/include/asm/pgtable.h b/arch/mips/include/asm/pgtable.h
> index 7f7c558de9fc..d2c7e9e7447e 100644
> --- a/arch/mips/include/asm/pgtable.h
> +++ b/arch/mips/include/asm/pgtable.h
> @@ -99,19 +99,30 @@ extern void paging_init(void);
>  
>  #define htw_stop()							\
>  do {									\
> +	unsigned long flags;						\
> +									\
>  	if (cpu_has_htw) {						\
> +		local_irq_save(flags);					\

duplicate?

> +		raw_current_cpu_data.htw_seq++;				\

not "if (!raw_current_cpu_data.htw_seq++)) {"?

>  		write_c0_pwctl(read_c0_pwctl() &			\
>  			       ~(1 << MIPS_PWCTL_PWEN_SHIFT));		\
>  		back_to_back_c0_hazard();				\
> +		local_irq_restore(flags);				\
>  	}								\
>  } while(0)
>  
>  #define htw_start()							\
>  do {									\
> +	unsigned long flags;						\
> +									\
>  	if (cpu_has_htw) {						\
> -		write_c0_pwctl(read_c0_pwctl() |			\
> -			       (1 << MIPS_PWCTL_PWEN_SHIFT));		\
> -		back_to_back_c0_hazard();				\
> +		local_irq_save(flags);					\
> +		if (!--raw_current_cpu_data.htw_seq) {			\
> +			write_c0_pwctl(read_c0_pwctl() |		\
> +				       (1 << MIPS_PWCTL_PWEN_SHIFT));	\
> +			back_to_back_c0_hazard();			\
> +		}							\
> +		local_irq_restore(flags);				\
>  	}								\
>  } while(0)
>  
> diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
> index dc49cf30c2db..5d6e59f20750 100644
> --- a/arch/mips/kernel/cpu-probe.c
> +++ b/arch/mips/kernel/cpu-probe.c
> @@ -367,8 +367,10 @@ static inline unsigned int decode_config3(struct cpuinfo_mips *c)
>  	if (config3 & MIPS_CONF3_MSA)
>  		c->ases |= MIPS_ASE_MSA;
>  	/* Only tested on 32-bit cores */
> -	if ((config3 & MIPS_CONF3_PW) && config_enabled(CONFIG_32BIT))
> +	if ((config3 & MIPS_CONF3_PW) && config_enabled(CONFIG_32BIT)) {
> +		c->htw_seq = 0;

is that necessary, since cpu_data[] is global?

>  		c->options |= MIPS_CPU_HTW;
> +	}
>  
>  	return config3 & MIPS_CONF_M;
>  }
> 

Cheers
James


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

  reply	other threads:[~2015-01-26 11:36 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-01-26  9:40 [PATCH 0/3 3.19] HTW fixes Markos Chandras
2015-01-26  9:40 ` Markos Chandras
2015-01-26  9:40 ` [PATCH 1/3] MIPS: asm: pgtable: Add c0 hazards on HTW start/stop sequences Markos Chandras
2015-01-26  9:40   ` Markos Chandras
2015-01-26  9:40 ` [PATCH 2/3] MIPS: HTW: Prevent accidental HTW start due to nested htw_{start,stop} Markos Chandras
2015-01-26  9:40   ` Markos Chandras
2015-01-26 11:36   ` James Hogan [this message]
2015-01-26 11:36     ` James Hogan
2015-01-26 11:38     ` James Hogan
2015-01-26 11:38       ` James Hogan
2015-01-26 11:47     ` Markos Chandras
2015-01-26 11:47       ` Markos Chandras
2015-01-26 12:03       ` Markos Chandras
2015-01-26 12:03         ` Markos Chandras
2015-01-26 12:03       ` James Hogan
2015-01-26 12:03         ` James Hogan
2015-01-26 12:04         ` Markos Chandras
2015-01-26 12:04           ` Markos Chandras
2015-01-26 13:04   ` [PATCH v2 " Markos Chandras
2015-01-26 13:04     ` Markos Chandras
2015-01-26  9:40 ` [PATCH 3/3] MIPS: asm: pgtable: Prevent HTW race when updating PTEs Markos Chandras
2015-01-26  9:40   ` Markos Chandras

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=54C626CC.2070104@imgtec.com \
    --to=james.hogan@imgtec.com \
    --cc=linux-mips@linux-mips.org \
    --cc=markos.chandras@imgtec.com \
    --cc=stable@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.