All of lore.kernel.org
 help / color / mirror / Atom feed
From: Matt Redfearn <matt.redfearn@imgtec.com>
To: James Hogan <james.hogan@imgtec.com>, Ralf Baechle <ralf@linux-mips.org>
Cc: <linux-mips@linux-mips.org>
Subject: Re: [PATCH v2 2/5] MIPS: Add defs & probing of extended CP0_EBase
Date: Wed, 11 May 2016 13:56:15 +0100	[thread overview]
Message-ID: <57332BEF.8030406@imgtec.com> (raw)
In-Reply-To: <1462971053-25622-3-git-send-email-james.hogan@imgtec.com>



On 11/05/16 13:50, James Hogan wrote:
> The CP0_EBase register may optionally have a write gate (WG) bit to
> allow the upper bits to be written, i.e. bits 31:30 on MIPS32 since r3
> (to allow for an exception base outside of KSeg0/KSeg1 when segmentation
> control is in use) and bits 63:30 on MIPS64 (which also implies the
> extension of CP0_EBase to 64 bits long).
>
> The presence of this feature will need to be known about for VZ support
> in order to correctly save and restore all the bits of the guest
> CP0_EBase register, so add CPU feature definition and probing for this
> feature.
>
> Probing the WG bit on MIPS64 can be a bit fiddly, since 64-bit COP0
> register access instructions were UNDEFINED for 32-bit registers prior
> to MIPS r6, and it'd be nice to be able to probe without clobbering the
> existing state, so there are 3 potential paths:
>
> - If we do a 32-bit read of CP0_EBase and the WG bit is already set, the
>    register must be 64-bit.
>
> - On MIPS r6 we can do a 64-bit read-modify-write to set CP0_EBase.WG,
>    since the upper bits will read 0 and be ignored on write if the
>    register is 32-bit.
>
> - On pre-r6 cores, we do a 32-bit read-modify-write of CP0_EBase. This
>    avoids the potentially UNDEFINED behaviour, but will clobber the upper
>    32-bits of CP0_EBase if it isn't a simple sign extension (which also
>    requires us to ensure BEV=1 or modifying the exception base would be
>    UNDEFINED too). It is hopefully unlikely a bootloader would set up
>    CP0_EBase to a 64-bit segment and leave WG=0.
>
> Signed-off-by: James Hogan <james.hogan@imgtec.com>
> Cc: Ralf Baechle <ralf@linux-mips.org>
> Cc: Matt Redfearn <matt.redfearn@imgtec.com>
> Cc: linux-mips@linux-mips.org
> ---
> Changes in v2:
> - Changed to handle MIPS32r3+, which can also have a WG bit to allow
>    bits 31:30 to be written. The feature provided is now just the
>    presence of the WG bit rather than the extension of CP0_EBase to
>    64-bits (which is implied if WG is present on MIPS64).
> ---
>   arch/mips/include/asm/cpu-features.h |  4 ++++
>   arch/mips/include/asm/cpu.h          |  1 +
>   arch/mips/include/asm/mipsregs.h     |  3 +++
>   arch/mips/kernel/cpu-probe.c         | 35 +++++++++++++++++++++++++++++++++++
>   4 files changed, 43 insertions(+)
>
> diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h
> index da92d513a395..3d82a4043e80 100644
> --- a/arch/mips/include/asm/cpu-features.h
> +++ b/arch/mips/include/asm/cpu-features.h
> @@ -432,4 +432,8 @@
>   #define cpu_has_nan_2008	(cpu_data[0].options & MIPS_CPU_NAN_2008)
>   #endif
>   
> +#ifndef cpu_has_ebase_wg
> +# define cpu_has_ebase_wg	(cpu_data[0].options & MIPS_CPU_EBASE_WG)
> +#endif
> +
>   #endif /* __ASM_CPU_FEATURES_H */
> diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h
> index 79ce9ae0a3c7..379beefefb5c 100644
> --- a/arch/mips/include/asm/cpu.h
> +++ b/arch/mips/include/asm/cpu.h
> @@ -403,6 +403,7 @@ enum cpu_type_enum {
>   #define MIPS_CPU_NAN_2008	MBIT_ULL(39)	/* 2008 NaN implemented */
>   #define MIPS_CPU_VP		MBIT_ULL(40)	/* MIPSr6 Virtual Processors (multi-threading) */
>   #define MIPS_CPU_LDPTE		MBIT_ULL(41)	 /* CPU has ldpte/lddir instructions */
> +#define MIPS_CPU_EBASE_WG	MBIT_ULL(42)	/* CPU has EBase.WG */
>   
>   /*
>    * CPU ASE encodings
> diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h
> index 57d72f2bf745..4e8ad9d6038a 100644
> --- a/arch/mips/include/asm/mipsregs.h
> +++ b/arch/mips/include/asm/mipsregs.h
> @@ -1458,6 +1458,9 @@ do {									\
>   #define read_c0_ebase()		__read_32bit_c0_register($15, 1)
>   #define write_c0_ebase(val)	__write_32bit_c0_register($15, 1, val)
>   
> +#define read_c0_ebase_64()	__read_64bit_c0_register($15, 1)
> +#define write_c0_ebase_64(val)	__write_64bit_c0_register($15, 1, val)
> +
>   #define read_c0_cdmmbase()	__read_ulong_c0_register($15, 2)
>   #define write_c0_cdmmbase(val)	__write_ulong_c0_register($15, 2, val)
>   
> diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
> index a6ce1db191aa..c4795568c1f2 100644
> --- a/arch/mips/kernel/cpu-probe.c
> +++ b/arch/mips/kernel/cpu-probe.c
> @@ -858,6 +858,41 @@ static void decode_configs(struct cpuinfo_mips *c)
>   	if (ok)
>   		ok = decode_config5(c);
>   
> +	/* Probe the EBase.WG bit */
> +	if (cpu_has_mips_r2_r6) {
> +		u64 ebase;
> +		unsigned int status;
> +
> +		/* {read,write}_c0_ebase_64() may be UNDEFINED prior to r6 */
> +		ebase = cpu_has_mips64r6 ? read_c0_ebase_64()
> +					 : (s32)read_c0_ebase();
> +		if (ebase & MIPS_EBASE_WG) {
> +			/* WG bit already set, we can avoid the clumsy probe */
> +			c->options |= MIPS_CPU_EBASE_WG;
> +		} else {
> +			/* Its UNDEFINED to change EBase while BEV=0 */
> +			status = read_c0_status();
> +			write_c0_status(status | ST0_BEV);
> +			irq_enable_hazard();
> +			/*
> +			 * On pre-r6 cores, this may well clobber the upper bits
> +			 * of EBase. This is hard to avoid without potentially
> +			 * hitting UNDEFINED dm*c0 behaviour if EBase is 32-bit.
> +			 */
> +			if (cpu_has_mips64r6)
> +				write_c0_ebase_64(ebase | MIPS_EBASE_WG);
> +			else
> +				write_c0_ebase(ebase | MIPS_EBASE_WG);
> +			back_to_back_c0_hazard();
> +			/* Restore BEV */
> +			write_c0_status(status);
> +			if (read_c0_ebase() & MIPS_EBASE_WG) {
> +				c->options |= MIPS_CPU_EBASE_WG;
> +				write_c0_ebase(ebase);
> +			}
> +		}
> +	}
> +
>   	mips_probe_watch_registers(c);
>   
>   #ifndef CONFIG_MIPS_CPS

With this change the kernel correctly detects presence of the WG bit on 
32bit Interaptiv.

Tested-by: Matt Redfearn <matt.redfearn@imgtec.com>

WARNING: multiple messages have this Message-ID (diff)
From: Matt Redfearn <matt.redfearn@imgtec.com>
To: James Hogan <james.hogan@imgtec.com>, Ralf Baechle <ralf@linux-mips.org>
Cc: linux-mips@linux-mips.org
Subject: Re: [PATCH v2 2/5] MIPS: Add defs & probing of extended CP0_EBase
Date: Wed, 11 May 2016 13:56:15 +0100	[thread overview]
Message-ID: <57332BEF.8030406@imgtec.com> (raw)
Message-ID: <20160511125615.vo52ahhqyHHscqD42lvS9KIwlFI82lMHvtVkHuBHV08@z> (raw)
In-Reply-To: <1462971053-25622-3-git-send-email-james.hogan@imgtec.com>



On 11/05/16 13:50, James Hogan wrote:
> The CP0_EBase register may optionally have a write gate (WG) bit to
> allow the upper bits to be written, i.e. bits 31:30 on MIPS32 since r3
> (to allow for an exception base outside of KSeg0/KSeg1 when segmentation
> control is in use) and bits 63:30 on MIPS64 (which also implies the
> extension of CP0_EBase to 64 bits long).
>
> The presence of this feature will need to be known about for VZ support
> in order to correctly save and restore all the bits of the guest
> CP0_EBase register, so add CPU feature definition and probing for this
> feature.
>
> Probing the WG bit on MIPS64 can be a bit fiddly, since 64-bit COP0
> register access instructions were UNDEFINED for 32-bit registers prior
> to MIPS r6, and it'd be nice to be able to probe without clobbering the
> existing state, so there are 3 potential paths:
>
> - If we do a 32-bit read of CP0_EBase and the WG bit is already set, the
>    register must be 64-bit.
>
> - On MIPS r6 we can do a 64-bit read-modify-write to set CP0_EBase.WG,
>    since the upper bits will read 0 and be ignored on write if the
>    register is 32-bit.
>
> - On pre-r6 cores, we do a 32-bit read-modify-write of CP0_EBase. This
>    avoids the potentially UNDEFINED behaviour, but will clobber the upper
>    32-bits of CP0_EBase if it isn't a simple sign extension (which also
>    requires us to ensure BEV=1 or modifying the exception base would be
>    UNDEFINED too). It is hopefully unlikely a bootloader would set up
>    CP0_EBase to a 64-bit segment and leave WG=0.
>
> Signed-off-by: James Hogan <james.hogan@imgtec.com>
> Cc: Ralf Baechle <ralf@linux-mips.org>
> Cc: Matt Redfearn <matt.redfearn@imgtec.com>
> Cc: linux-mips@linux-mips.org
> ---
> Changes in v2:
> - Changed to handle MIPS32r3+, which can also have a WG bit to allow
>    bits 31:30 to be written. The feature provided is now just the
>    presence of the WG bit rather than the extension of CP0_EBase to
>    64-bits (which is implied if WG is present on MIPS64).
> ---
>   arch/mips/include/asm/cpu-features.h |  4 ++++
>   arch/mips/include/asm/cpu.h          |  1 +
>   arch/mips/include/asm/mipsregs.h     |  3 +++
>   arch/mips/kernel/cpu-probe.c         | 35 +++++++++++++++++++++++++++++++++++
>   4 files changed, 43 insertions(+)
>
> diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h
> index da92d513a395..3d82a4043e80 100644
> --- a/arch/mips/include/asm/cpu-features.h
> +++ b/arch/mips/include/asm/cpu-features.h
> @@ -432,4 +432,8 @@
>   #define cpu_has_nan_2008	(cpu_data[0].options & MIPS_CPU_NAN_2008)
>   #endif
>   
> +#ifndef cpu_has_ebase_wg
> +# define cpu_has_ebase_wg	(cpu_data[0].options & MIPS_CPU_EBASE_WG)
> +#endif
> +
>   #endif /* __ASM_CPU_FEATURES_H */
> diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h
> index 79ce9ae0a3c7..379beefefb5c 100644
> --- a/arch/mips/include/asm/cpu.h
> +++ b/arch/mips/include/asm/cpu.h
> @@ -403,6 +403,7 @@ enum cpu_type_enum {
>   #define MIPS_CPU_NAN_2008	MBIT_ULL(39)	/* 2008 NaN implemented */
>   #define MIPS_CPU_VP		MBIT_ULL(40)	/* MIPSr6 Virtual Processors (multi-threading) */
>   #define MIPS_CPU_LDPTE		MBIT_ULL(41)	 /* CPU has ldpte/lddir instructions */
> +#define MIPS_CPU_EBASE_WG	MBIT_ULL(42)	/* CPU has EBase.WG */
>   
>   /*
>    * CPU ASE encodings
> diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h
> index 57d72f2bf745..4e8ad9d6038a 100644
> --- a/arch/mips/include/asm/mipsregs.h
> +++ b/arch/mips/include/asm/mipsregs.h
> @@ -1458,6 +1458,9 @@ do {									\
>   #define read_c0_ebase()		__read_32bit_c0_register($15, 1)
>   #define write_c0_ebase(val)	__write_32bit_c0_register($15, 1, val)
>   
> +#define read_c0_ebase_64()	__read_64bit_c0_register($15, 1)
> +#define write_c0_ebase_64(val)	__write_64bit_c0_register($15, 1, val)
> +
>   #define read_c0_cdmmbase()	__read_ulong_c0_register($15, 2)
>   #define write_c0_cdmmbase(val)	__write_ulong_c0_register($15, 2, val)
>   
> diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
> index a6ce1db191aa..c4795568c1f2 100644
> --- a/arch/mips/kernel/cpu-probe.c
> +++ b/arch/mips/kernel/cpu-probe.c
> @@ -858,6 +858,41 @@ static void decode_configs(struct cpuinfo_mips *c)
>   	if (ok)
>   		ok = decode_config5(c);
>   
> +	/* Probe the EBase.WG bit */
> +	if (cpu_has_mips_r2_r6) {
> +		u64 ebase;
> +		unsigned int status;
> +
> +		/* {read,write}_c0_ebase_64() may be UNDEFINED prior to r6 */
> +		ebase = cpu_has_mips64r6 ? read_c0_ebase_64()
> +					 : (s32)read_c0_ebase();
> +		if (ebase & MIPS_EBASE_WG) {
> +			/* WG bit already set, we can avoid the clumsy probe */
> +			c->options |= MIPS_CPU_EBASE_WG;
> +		} else {
> +			/* Its UNDEFINED to change EBase while BEV=0 */
> +			status = read_c0_status();
> +			write_c0_status(status | ST0_BEV);
> +			irq_enable_hazard();
> +			/*
> +			 * On pre-r6 cores, this may well clobber the upper bits
> +			 * of EBase. This is hard to avoid without potentially
> +			 * hitting UNDEFINED dm*c0 behaviour if EBase is 32-bit.
> +			 */
> +			if (cpu_has_mips64r6)
> +				write_c0_ebase_64(ebase | MIPS_EBASE_WG);
> +			else
> +				write_c0_ebase(ebase | MIPS_EBASE_WG);
> +			back_to_back_c0_hazard();
> +			/* Restore BEV */
> +			write_c0_status(status);
> +			if (read_c0_ebase() & MIPS_EBASE_WG) {
> +				c->options |= MIPS_CPU_EBASE_WG;
> +				write_c0_ebase(ebase);
> +			}
> +		}
> +	}
> +
>   	mips_probe_watch_registers(c);
>   
>   #ifndef CONFIG_MIPS_CPS

With this change the kernel correctly detects presence of the WG bit on 
32bit Interaptiv.

Tested-by: Matt Redfearn <matt.redfearn@imgtec.com>

  reply	other threads:[~2016-05-11 12:56 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-05-11 12:50 [PATCH v2 0/5] MIPS: Add feature probing ready for KVM/VZ James Hogan
2016-05-11 12:50 ` [PATCH v2 1/5] MIPS: Define & use CP0_EBase bit definitions James Hogan
2016-05-11 12:50 ` [PATCH v2 2/5] MIPS: Add defs & probing of extended CP0_EBase James Hogan
2016-05-11 12:50   ` James Hogan
2016-05-11 12:56   ` Matt Redfearn [this message]
2016-05-11 12:56     ` Matt Redfearn
2016-05-12  1:10   ` Maciej W. Rozycki
2016-05-12  1:10     ` Maciej W. Rozycki
2016-05-12 16:12     ` James Hogan
2016-05-12 16:12       ` James Hogan
2016-05-11 12:50 ` [PATCH v2 3/5] MIPS: Add defs & probing of BadInstr[P] registers James Hogan
2016-05-11 12:50   ` James Hogan
2016-05-11 12:50 ` [PATCH v2 4/5] MIPS: Add defs & probing of [X]ContextConfig James Hogan
2016-05-11 12:50   ` James Hogan
2016-05-11 12:50 ` [PATCH v2 5/5] MIPS: Add perf counter feature James Hogan
2016-05-11 12:50   ` James Hogan

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=57332BEF.8030406@imgtec.com \
    --to=matt.redfearn@imgtec.com \
    --cc=james.hogan@imgtec.com \
    --cc=linux-mips@linux-mips.org \
    --cc=ralf@linux-mips.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.