All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/5] MIPS: Add feature probing ready for KVM/VZ
@ 2016-05-11 12:50 James Hogan
  2016-05-11 12:50 ` [PATCH v2 1/5] MIPS: Define & use CP0_EBase bit definitions James Hogan
                   ` (4 more replies)
  0 siblings, 5 replies; 16+ messages in thread
From: James Hogan @ 2016-05-11 12:50 UTC (permalink / raw)
  To: Ralf Baechle
  Cc: James Hogan, Jayachandran C, Paolo Bonzini,
	Radim Krčmář,
	Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Alexander Shishkin, Robert Richter, linux-mips, kvm,
	oprofile-list

This patchset adds probing of various architectural features which will
be useful for supporting KVM with VZ (MIPS hardware assisted
virtualisation extensions).

Changes in v2:
- Patch 2 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).

It is based on the mips-for-linux-next~ of the day (commit
0fc44314a7d).

James Hogan (5):
  MIPS: Define & use CP0_EBase bit definitions
  MIPS: Add defs & probing of extended CP0_EBase
  MIPS: Add defs & probing of BadInstr[P] registers
  MIPS: Add defs & probing of [X]ContextConfig
  MIPS: Add perf counter feature

 arch/mips/include/asm/cpu-features.h | 20 ++++++++++++++++
 arch/mips/include/asm/cpu.h          |  5 ++++
 arch/mips/include/asm/mipsregs.h     | 22 +++++++++++++++++-
 arch/mips/kernel/cpu-probe.c         | 45 +++++++++++++++++++++++++++++++++++-
 arch/mips/kernel/perf_event_mipsxx.c |  4 +---
 arch/mips/kvm/trap_emul.c            |  3 ++-
 arch/mips/netlogic/xlp/nlm_hal.c     |  2 +-
 arch/mips/netlogic/xlr/setup.c       |  2 +-
 arch/mips/oprofile/op_model_mipsxx.c |  4 +---
 9 files changed, 96 insertions(+), 11 deletions(-)

Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: Jayachandran C <jchandra@broadcom.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Radim Krčmář <rkrcmar@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Robert Richter <rric@kernel.org>
Cc: linux-mips@linux-mips.org
Cc: kvm@vger.kernel.org
Cc: oprofile-list@lists.sf.net
-- 
2.4.10

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

* [PATCH v2 1/5] MIPS: Define & use CP0_EBase bit definitions
  2016-05-11 12:50 [PATCH v2 0/5] MIPS: Add feature probing ready for KVM/VZ James Hogan
@ 2016-05-11 12:50 ` James Hogan
  2016-05-11 12:50   ` James Hogan
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 16+ messages in thread
From: James Hogan @ 2016-05-11 12:50 UTC (permalink / raw)
  To: Ralf Baechle
  Cc: James Hogan, Jayachandran C, Paolo Bonzini,
	Radim Krčmář,
	linux-mips, kvm

Add definitions for the bits & fields in the CP0_EBase register, and use
them from a few different places in arch/mips which hardcoded these
values.

Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: Jayachandran C <jchandra@broadcom.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Radim Krčmář <rkrcmar@redhat.com>
Cc: linux-mips@linux-mips.org
Cc: kvm@vger.kernel.org
---
 arch/mips/include/asm/mipsregs.h | 10 +++++++++-
 arch/mips/kvm/trap_emul.c        |  3 ++-
 arch/mips/netlogic/xlp/nlm_hal.c |  2 +-
 arch/mips/netlogic/xlr/setup.c   |  2 +-
 4 files changed, 13 insertions(+), 4 deletions(-)

diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h
index b7705ef09df2..57d72f2bf745 100644
--- a/arch/mips/include/asm/mipsregs.h
+++ b/arch/mips/include/asm/mipsregs.h
@@ -676,6 +676,14 @@
 #define MIPS_MAAR_S		(_ULCAST_(1) << 1)
 #define MIPS_MAAR_V		(_ULCAST_(1) << 0)
 
+/* EBase bit definitions */
+#define MIPS_EBASE_CPUNUM_SHIFT	0
+#define MIPS_EBASE_CPUNUM	(_ULCAST_(0x3ff) << 0)
+#define MIPS_EBASE_WG_SHIFT	11
+#define MIPS_EBASE_WG		(_ULCAST_(1) << 11)
+#define MIPS_EBASE_BASE_SHIFT	12
+#define MIPS_EBASE_BASE		(~_ULCAST_((1 << MIPS_EBASE_BASE_SHIFT) - 1))
+
 /* CMGCRBase bit definitions */
 #define MIPS_CMGCRB_BASE	11
 #define MIPS_CMGCRF_BASE	(~_ULCAST_((1 << MIPS_CMGCRB_BASE) - 1))
@@ -2104,7 +2112,7 @@ __BUILD_SET_C0(brcm_mode)
  */
 static inline unsigned int get_ebase_cpunum(void)
 {
-	return read_c0_ebase() & 0x3ff;
+	return read_c0_ebase() & MIPS_EBASE_CPUNUM;
 }
 
 #endif /* !__ASSEMBLY__ */
diff --git a/arch/mips/kvm/trap_emul.c b/arch/mips/kvm/trap_emul.c
index c4038d2a724c..fd43f0afdb9f 100644
--- a/arch/mips/kvm/trap_emul.c
+++ b/arch/mips/kvm/trap_emul.c
@@ -505,7 +505,8 @@ static int kvm_trap_emul_vcpu_setup(struct kvm_vcpu *vcpu)
 	kvm_write_c0_guest_intctl(cop0, 0xFC000000);
 
 	/* Put in vcpu id as CPUNum into Ebase Reg to handle SMP Guests */
-	kvm_write_c0_guest_ebase(cop0, KVM_GUEST_KSEG0 | (vcpu_id & 0xFF));
+	kvm_write_c0_guest_ebase(cop0, KVM_GUEST_KSEG0 |
+				       (vcpu_id & MIPS_EBASE_CPUNUM));
 
 	return 0;
 }
diff --git a/arch/mips/netlogic/xlp/nlm_hal.c b/arch/mips/netlogic/xlp/nlm_hal.c
index 80ec929747c3..25ee69489e5e 100644
--- a/arch/mips/netlogic/xlp/nlm_hal.c
+++ b/arch/mips/netlogic/xlp/nlm_hal.c
@@ -58,7 +58,7 @@ void nlm_node_init(int node)
 		nodep->coremask = 1;	/* node 0, boot cpu */
 	nodep->sysbase = nlm_get_sys_regbase(node);
 	nodep->picbase = nlm_get_pic_regbase(node);
-	nodep->ebase = read_c0_ebase() & (~((1 << 12) - 1));
+	nodep->ebase = read_c0_ebase() & MIPS_EBASE_BASE;
 	if (cpu_is_xlp9xx())
 		nodep->socbus = xlp9xx_get_socbus(node);
 	else
diff --git a/arch/mips/netlogic/xlr/setup.c b/arch/mips/netlogic/xlr/setup.c
index d118b9aa7647..72ceddc9a03f 100644
--- a/arch/mips/netlogic/xlr/setup.c
+++ b/arch/mips/netlogic/xlr/setup.c
@@ -168,7 +168,7 @@ static void nlm_init_node(void)
 
 	nodep = nlm_current_node();
 	nodep->picbase = nlm_mmio_base(NETLOGIC_IO_PIC_OFFSET);
-	nodep->ebase = read_c0_ebase() & (~((1 << 12) - 1));
+	nodep->ebase = read_c0_ebase() & MIPS_EBASE_BASE;
 	spin_lock_init(&nodep->piclock);
 }
 
-- 
2.4.10

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

* [PATCH v2 2/5] MIPS: Add defs & probing of extended CP0_EBase
@ 2016-05-11 12:50   ` James Hogan
  0 siblings, 0 replies; 16+ messages in thread
From: James Hogan @ 2016-05-11 12:50 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: James Hogan, Matt Redfearn, linux-mips

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
-- 
2.4.10

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

* [PATCH v2 2/5] MIPS: Add defs & probing of extended CP0_EBase
@ 2016-05-11 12:50   ` James Hogan
  0 siblings, 0 replies; 16+ messages in thread
From: James Hogan @ 2016-05-11 12:50 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: James Hogan, Matt Redfearn, linux-mips

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
-- 
2.4.10

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

* [PATCH v2 3/5] MIPS: Add defs & probing of BadInstr[P] registers
@ 2016-05-11 12:50   ` James Hogan
  0 siblings, 0 replies; 16+ messages in thread
From: James Hogan @ 2016-05-11 12:50 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: James Hogan, linux-mips

The optional CP0_BadInstr and CP0_BadInstrP registers are written with
the encoding of the instruction that caused a synchronous exception to
occur, and the prior branch instruction if in a delay slot.

These will be useful for instruction emulation in KVM, and especially
for VZ support where reading guest virtual memory is a bit more awkward.

Add CPU option numbers and cpu_has_* definitions to indicate the
presence of each registers, and add code to probe for them using bits in
the CP0_Config3 register.

Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: linux-mips@linux-mips.org
---
 arch/mips/include/asm/cpu-features.h | 8 ++++++++
 arch/mips/include/asm/cpu.h          | 2 ++
 arch/mips/include/asm/mipsregs.h     | 3 +++
 arch/mips/kernel/cpu-probe.c         | 4 ++++
 4 files changed, 17 insertions(+)

diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h
index 3d82a4043e80..f901bc35f9a4 100644
--- a/arch/mips/include/asm/cpu-features.h
+++ b/arch/mips/include/asm/cpu-features.h
@@ -436,4 +436,12 @@
 # define cpu_has_ebase_wg	(cpu_data[0].options & MIPS_CPU_EBASE_WG)
 #endif
 
+#ifndef cpu_has_badinstr
+# define cpu_has_badinstr	(cpu_data[0].options & MIPS_CPU_BADINSTR)
+#endif
+
+#ifndef cpu_has_badinstrp
+# define cpu_has_badinstrp	(cpu_data[0].options & MIPS_CPU_BADINSTRP)
+#endif
+
 #endif /* __ASM_CPU_FEATURES_H */
diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h
index 379beefefb5c..8a8b029c545a 100644
--- a/arch/mips/include/asm/cpu.h
+++ b/arch/mips/include/asm/cpu.h
@@ -404,6 +404,8 @@ enum cpu_type_enum {
 #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 */
+#define MIPS_CPU_BADINSTR	MBIT_ULL(43)	/* CPU has BadInstr register */
+#define MIPS_CPU_BADINSTRP	MBIT_ULL(44)	/* CPU has BadInstrP register */
 
 /*
  * CPU ASE encodings
diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h
index 4e8ad9d6038a..b1f8f8436fd1 100644
--- a/arch/mips/include/asm/mipsregs.h
+++ b/arch/mips/include/asm/mipsregs.h
@@ -1248,6 +1248,9 @@ do {									\
 #define read_c0_badvaddr()	__read_ulong_c0_register($8, 0)
 #define write_c0_badvaddr(val)	__write_ulong_c0_register($8, 0, val)
 
+#define read_c0_badinstr()	__read_32bit_c0_register($8, 1)
+#define read_c0_badinstrp()	__read_32bit_c0_register($8, 2)
+
 #define read_c0_count()		__read_32bit_c0_register($9, 0)
 #define write_c0_count(val)	__write_32bit_c0_register($9, 0, val)
 
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index c4795568c1f2..83c7f3d0fcd2 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -712,6 +712,10 @@ static inline unsigned int decode_config3(struct cpuinfo_mips *c)
 		c->ases |= MIPS_ASE_VZ;
 	if (config3 & MIPS_CONF3_SC)
 		c->options |= MIPS_CPU_SEGMENTS;
+	if (config3 & MIPS_CONF3_BI)
+		c->options |= MIPS_CPU_BADINSTR;
+	if (config3 & MIPS_CONF3_BP)
+		c->options |= MIPS_CPU_BADINSTRP;
 	if (config3 & MIPS_CONF3_MSA)
 		c->ases |= MIPS_ASE_MSA;
 	if (config3 & MIPS_CONF3_PW) {
-- 
2.4.10

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

* [PATCH v2 3/5] MIPS: Add defs & probing of BadInstr[P] registers
@ 2016-05-11 12:50   ` James Hogan
  0 siblings, 0 replies; 16+ messages in thread
From: James Hogan @ 2016-05-11 12:50 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: James Hogan, linux-mips

The optional CP0_BadInstr and CP0_BadInstrP registers are written with
the encoding of the instruction that caused a synchronous exception to
occur, and the prior branch instruction if in a delay slot.

These will be useful for instruction emulation in KVM, and especially
for VZ support where reading guest virtual memory is a bit more awkward.

Add CPU option numbers and cpu_has_* definitions to indicate the
presence of each registers, and add code to probe for them using bits in
the CP0_Config3 register.

Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: linux-mips@linux-mips.org
---
 arch/mips/include/asm/cpu-features.h | 8 ++++++++
 arch/mips/include/asm/cpu.h          | 2 ++
 arch/mips/include/asm/mipsregs.h     | 3 +++
 arch/mips/kernel/cpu-probe.c         | 4 ++++
 4 files changed, 17 insertions(+)

diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h
index 3d82a4043e80..f901bc35f9a4 100644
--- a/arch/mips/include/asm/cpu-features.h
+++ b/arch/mips/include/asm/cpu-features.h
@@ -436,4 +436,12 @@
 # define cpu_has_ebase_wg	(cpu_data[0].options & MIPS_CPU_EBASE_WG)
 #endif
 
+#ifndef cpu_has_badinstr
+# define cpu_has_badinstr	(cpu_data[0].options & MIPS_CPU_BADINSTR)
+#endif
+
+#ifndef cpu_has_badinstrp
+# define cpu_has_badinstrp	(cpu_data[0].options & MIPS_CPU_BADINSTRP)
+#endif
+
 #endif /* __ASM_CPU_FEATURES_H */
diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h
index 379beefefb5c..8a8b029c545a 100644
--- a/arch/mips/include/asm/cpu.h
+++ b/arch/mips/include/asm/cpu.h
@@ -404,6 +404,8 @@ enum cpu_type_enum {
 #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 */
+#define MIPS_CPU_BADINSTR	MBIT_ULL(43)	/* CPU has BadInstr register */
+#define MIPS_CPU_BADINSTRP	MBIT_ULL(44)	/* CPU has BadInstrP register */
 
 /*
  * CPU ASE encodings
diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h
index 4e8ad9d6038a..b1f8f8436fd1 100644
--- a/arch/mips/include/asm/mipsregs.h
+++ b/arch/mips/include/asm/mipsregs.h
@@ -1248,6 +1248,9 @@ do {									\
 #define read_c0_badvaddr()	__read_ulong_c0_register($8, 0)
 #define write_c0_badvaddr(val)	__write_ulong_c0_register($8, 0, val)
 
+#define read_c0_badinstr()	__read_32bit_c0_register($8, 1)
+#define read_c0_badinstrp()	__read_32bit_c0_register($8, 2)
+
 #define read_c0_count()		__read_32bit_c0_register($9, 0)
 #define write_c0_count(val)	__write_32bit_c0_register($9, 0, val)
 
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index c4795568c1f2..83c7f3d0fcd2 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -712,6 +712,10 @@ static inline unsigned int decode_config3(struct cpuinfo_mips *c)
 		c->ases |= MIPS_ASE_VZ;
 	if (config3 & MIPS_CONF3_SC)
 		c->options |= MIPS_CPU_SEGMENTS;
+	if (config3 & MIPS_CONF3_BI)
+		c->options |= MIPS_CPU_BADINSTR;
+	if (config3 & MIPS_CONF3_BP)
+		c->options |= MIPS_CPU_BADINSTRP;
 	if (config3 & MIPS_CONF3_MSA)
 		c->ases |= MIPS_ASE_MSA;
 	if (config3 & MIPS_CONF3_PW) {
-- 
2.4.10

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

* [PATCH v2 4/5] MIPS: Add defs & probing of [X]ContextConfig
@ 2016-05-11 12:50   ` James Hogan
  0 siblings, 0 replies; 16+ messages in thread
From: James Hogan @ 2016-05-11 12:50 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: James Hogan, linux-mips

The CP0_[X]ContextConfig registers are present if CP0_Config3.CTXTC or
CP0_Config3.SM are set, and provide more control over which bits of
CP0_[X]Context are set to the faulting virtual address on a TLB
exception.

KVM/VZ will need to be able to save and restore these registers in the
guest context, so add the relevant definitions and probing of the
ContextConfig feature in the root context first.

Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: linux-mips@linux-mips.org
---
 arch/mips/include/asm/cpu-features.h | 4 ++++
 arch/mips/include/asm/cpu.h          | 1 +
 arch/mips/include/asm/mipsregs.h     | 6 ++++++
 arch/mips/kernel/cpu-probe.c         | 4 +++-
 4 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h
index f901bc35f9a4..04b91d624c81 100644
--- a/arch/mips/include/asm/cpu-features.h
+++ b/arch/mips/include/asm/cpu-features.h
@@ -444,4 +444,8 @@
 # define cpu_has_badinstrp	(cpu_data[0].options & MIPS_CPU_BADINSTRP)
 #endif
 
+#ifndef cpu_has_contextconfig
+# define cpu_has_contextconfig	(cpu_data[0].options & MIPS_CPU_CTXTC)
+#endif
+
 #endif /* __ASM_CPU_FEATURES_H */
diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h
index 8a8b029c545a..3a3848e2f481 100644
--- a/arch/mips/include/asm/cpu.h
+++ b/arch/mips/include/asm/cpu.h
@@ -406,6 +406,7 @@ enum cpu_type_enum {
 #define MIPS_CPU_EBASE_WG	MBIT_ULL(42)	/* CPU has EBase.WG */
 #define MIPS_CPU_BADINSTR	MBIT_ULL(43)	/* CPU has BadInstr register */
 #define MIPS_CPU_BADINSTRP	MBIT_ULL(44)	/* CPU has BadInstrP register */
+#define MIPS_CPU_CTXTC		MBIT_ULL(45)	/* CPU has [X]ConfigContext registers */
 
 /*
  * CPU ASE encodings
diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h
index b1f8f8436fd1..08864cbbb27b 100644
--- a/arch/mips/include/asm/mipsregs.h
+++ b/arch/mips/include/asm/mipsregs.h
@@ -1228,9 +1228,15 @@ do {									\
 #define read_c0_context()	__read_ulong_c0_register($4, 0)
 #define write_c0_context(val)	__write_ulong_c0_register($4, 0, val)
 
+#define read_c0_contextconfig()		__read_32bit_c0_register($4, 1)
+#define write_c0_contextconfig(val)	__write_32bit_c0_register($4, 1, val)
+
 #define read_c0_userlocal()	__read_ulong_c0_register($4, 2)
 #define write_c0_userlocal(val) __write_ulong_c0_register($4, 2, val)
 
+#define read_c0_xcontextconfig()	__read_ulong_c0_register($4, 3)
+#define write_c0_xcontextconfig(val)	__write_ulong_c0_register($4, 3, val)
+
 #define read_c0_pagemask()	__read_32bit_c0_register($5, 0)
 #define write_c0_pagemask(val)	__write_32bit_c0_register($5, 0, val)
 
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index 83c7f3d0fcd2..e9bbb0a18168 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -687,10 +687,12 @@ static inline unsigned int decode_config3(struct cpuinfo_mips *c)
 
 	if (config3 & MIPS_CONF3_SM) {
 		c->ases |= MIPS_ASE_SMARTMIPS;
-		c->options |= MIPS_CPU_RIXI;
+		c->options |= MIPS_CPU_RIXI | MIPS_CPU_CTXTC;
 	}
 	if (config3 & MIPS_CONF3_RXI)
 		c->options |= MIPS_CPU_RIXI;
+	if (config3 & MIPS_CONF3_CTXTC)
+		c->options |= MIPS_CPU_CTXTC;
 	if (config3 & MIPS_CONF3_DSP)
 		c->ases |= MIPS_ASE_DSP;
 	if (config3 & MIPS_CONF3_DSP2P) {
-- 
2.4.10

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

* [PATCH v2 4/5] MIPS: Add defs & probing of [X]ContextConfig
@ 2016-05-11 12:50   ` James Hogan
  0 siblings, 0 replies; 16+ messages in thread
From: James Hogan @ 2016-05-11 12:50 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: James Hogan, linux-mips

The CP0_[X]ContextConfig registers are present if CP0_Config3.CTXTC or
CP0_Config3.SM are set, and provide more control over which bits of
CP0_[X]Context are set to the faulting virtual address on a TLB
exception.

KVM/VZ will need to be able to save and restore these registers in the
guest context, so add the relevant definitions and probing of the
ContextConfig feature in the root context first.

Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: linux-mips@linux-mips.org
---
 arch/mips/include/asm/cpu-features.h | 4 ++++
 arch/mips/include/asm/cpu.h          | 1 +
 arch/mips/include/asm/mipsregs.h     | 6 ++++++
 arch/mips/kernel/cpu-probe.c         | 4 +++-
 4 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h
index f901bc35f9a4..04b91d624c81 100644
--- a/arch/mips/include/asm/cpu-features.h
+++ b/arch/mips/include/asm/cpu-features.h
@@ -444,4 +444,8 @@
 # define cpu_has_badinstrp	(cpu_data[0].options & MIPS_CPU_BADINSTRP)
 #endif
 
+#ifndef cpu_has_contextconfig
+# define cpu_has_contextconfig	(cpu_data[0].options & MIPS_CPU_CTXTC)
+#endif
+
 #endif /* __ASM_CPU_FEATURES_H */
diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h
index 8a8b029c545a..3a3848e2f481 100644
--- a/arch/mips/include/asm/cpu.h
+++ b/arch/mips/include/asm/cpu.h
@@ -406,6 +406,7 @@ enum cpu_type_enum {
 #define MIPS_CPU_EBASE_WG	MBIT_ULL(42)	/* CPU has EBase.WG */
 #define MIPS_CPU_BADINSTR	MBIT_ULL(43)	/* CPU has BadInstr register */
 #define MIPS_CPU_BADINSTRP	MBIT_ULL(44)	/* CPU has BadInstrP register */
+#define MIPS_CPU_CTXTC		MBIT_ULL(45)	/* CPU has [X]ConfigContext registers */
 
 /*
  * CPU ASE encodings
diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h
index b1f8f8436fd1..08864cbbb27b 100644
--- a/arch/mips/include/asm/mipsregs.h
+++ b/arch/mips/include/asm/mipsregs.h
@@ -1228,9 +1228,15 @@ do {									\
 #define read_c0_context()	__read_ulong_c0_register($4, 0)
 #define write_c0_context(val)	__write_ulong_c0_register($4, 0, val)
 
+#define read_c0_contextconfig()		__read_32bit_c0_register($4, 1)
+#define write_c0_contextconfig(val)	__write_32bit_c0_register($4, 1, val)
+
 #define read_c0_userlocal()	__read_ulong_c0_register($4, 2)
 #define write_c0_userlocal(val) __write_ulong_c0_register($4, 2, val)
 
+#define read_c0_xcontextconfig()	__read_ulong_c0_register($4, 3)
+#define write_c0_xcontextconfig(val)	__write_ulong_c0_register($4, 3, val)
+
 #define read_c0_pagemask()	__read_32bit_c0_register($5, 0)
 #define write_c0_pagemask(val)	__write_32bit_c0_register($5, 0, val)
 
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index 83c7f3d0fcd2..e9bbb0a18168 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -687,10 +687,12 @@ static inline unsigned int decode_config3(struct cpuinfo_mips *c)
 
 	if (config3 & MIPS_CONF3_SM) {
 		c->ases |= MIPS_ASE_SMARTMIPS;
-		c->options |= MIPS_CPU_RIXI;
+		c->options |= MIPS_CPU_RIXI | MIPS_CPU_CTXTC;
 	}
 	if (config3 & MIPS_CONF3_RXI)
 		c->options |= MIPS_CPU_RIXI;
+	if (config3 & MIPS_CONF3_CTXTC)
+		c->options |= MIPS_CPU_CTXTC;
 	if (config3 & MIPS_CONF3_DSP)
 		c->ases |= MIPS_ASE_DSP;
 	if (config3 & MIPS_CONF3_DSP2P) {
-- 
2.4.10

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

* [PATCH v2 5/5] MIPS: Add perf counter feature
@ 2016-05-11 12:50   ` James Hogan
  0 siblings, 0 replies; 16+ messages in thread
From: James Hogan @ 2016-05-11 12:50 UTC (permalink / raw)
  To: Ralf Baechle
  Cc: James Hogan, Peter Zijlstra, Ingo Molnar,
	Arnaldo Carvalho de Melo, Alexander Shishkin, Robert Richter,
	linux-mips, oprofile-list

Add CPU feature for standard MIPS r2 performance counters, as determined
by the Config1.PC bit. Both perf_events and oprofile probe this bit, so
lets combine the probing and change both to use cpu_has_perf.

This will also be used for VZ support in KVM to know whether performance
counters exist which can be exposed to guests.

Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Robert Richter <rric@kernel.org>
Cc: linux-mips@linux-mips.org
Cc: oprofile-list@lists.sf.net
---
 arch/mips/include/asm/cpu-features.h | 4 ++++
 arch/mips/include/asm/cpu.h          | 1 +
 arch/mips/kernel/cpu-probe.c         | 2 ++
 arch/mips/kernel/perf_event_mipsxx.c | 4 +---
 arch/mips/oprofile/op_model_mipsxx.c | 4 +---
 5 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h
index 04b91d624c81..7cf708b52349 100644
--- a/arch/mips/include/asm/cpu-features.h
+++ b/arch/mips/include/asm/cpu-features.h
@@ -448,4 +448,8 @@
 # define cpu_has_contextconfig	(cpu_data[0].options & MIPS_CPU_CTXTC)
 #endif
 
+#ifndef cpu_has_perf
+# define cpu_has_perf		(cpu_data[0].options & MIPS_CPU_PERF)
+#endif
+
 #endif /* __ASM_CPU_FEATURES_H */
diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h
index 3a3848e2f481..3a4499660416 100644
--- a/arch/mips/include/asm/cpu.h
+++ b/arch/mips/include/asm/cpu.h
@@ -407,6 +407,7 @@ enum cpu_type_enum {
 #define MIPS_CPU_BADINSTR	MBIT_ULL(43)	/* CPU has BadInstr register */
 #define MIPS_CPU_BADINSTRP	MBIT_ULL(44)	/* CPU has BadInstrP register */
 #define MIPS_CPU_CTXTC		MBIT_ULL(45)	/* CPU has [X]ConfigContext registers */
+#define MIPS_CPU_PERF		MBIT_ULL(46)	/* CPU has MIPS performance counters */
 
 /*
  * CPU ASE encodings
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index e9bbb0a18168..316c4d7dd7ae 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -648,6 +648,8 @@ static inline unsigned int decode_config1(struct cpuinfo_mips *c)
 
 	if (config1 & MIPS_CONF1_MD)
 		c->ases |= MIPS_ASE_MDMX;
+	if (config1 & MIPS_CONF1_PC)
+		c->options |= MIPS_CPU_PERF;
 	if (config1 & MIPS_CONF1_WR)
 		c->options |= MIPS_CPU_WATCH;
 	if (config1 & MIPS_CONF1_CA)
diff --git a/arch/mips/kernel/perf_event_mipsxx.c b/arch/mips/kernel/perf_event_mipsxx.c
index 656769c166fc..302af8c975df 100644
--- a/arch/mips/kernel/perf_event_mipsxx.c
+++ b/arch/mips/kernel/perf_event_mipsxx.c
@@ -101,8 +101,6 @@ struct mips_pmu {
 
 static struct mips_pmu mipspmu;
 
-#define M_CONFIG1_PC	(1 << 4)
-
 #define M_PERFCTL_EXL			(1	<<  0)
 #define M_PERFCTL_KERNEL		(1	<<  1)
 #define M_PERFCTL_SUPERVISOR		(1	<<  2)
@@ -754,7 +752,7 @@ static void handle_associated_event(struct cpu_hw_events *cpuc,
 
 static int __n_counters(void)
 {
-	if (!(read_c0_config1() & M_CONFIG1_PC))
+	if (!cpu_has_perf)
 		return 0;
 	if (!(read_c0_perfctrl0() & M_PERFCTL_MORE))
 		return 1;
diff --git a/arch/mips/oprofile/op_model_mipsxx.c b/arch/mips/oprofile/op_model_mipsxx.c
index 8f988a61b7a8..45cb27469fba 100644
--- a/arch/mips/oprofile/op_model_mipsxx.c
+++ b/arch/mips/oprofile/op_model_mipsxx.c
@@ -269,11 +269,9 @@ static int mipsxx_perfcount_handler(void)
 	return handled;
 }
 
-#define M_CONFIG1_PC	(1 << 4)
-
 static inline int __n_counters(void)
 {
-	if (!(read_c0_config1() & M_CONFIG1_PC))
+	if (!cpu_has_perf)
 		return 0;
 	if (!(read_c0_perfctrl0() & M_PERFCTL_MORE))
 		return 1;
-- 
2.4.10

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

* [PATCH v2 5/5] MIPS: Add perf counter feature
@ 2016-05-11 12:50   ` James Hogan
  0 siblings, 0 replies; 16+ messages in thread
From: James Hogan @ 2016-05-11 12:50 UTC (permalink / raw)
  To: Ralf Baechle
  Cc: James Hogan, Peter Zijlstra, Ingo Molnar,
	Arnaldo Carvalho de Melo, Alexander Shishkin, Robert Richter,
	linux-mips, oprofile-list

Add CPU feature for standard MIPS r2 performance counters, as determined
by the Config1.PC bit. Both perf_events and oprofile probe this bit, so
lets combine the probing and change both to use cpu_has_perf.

This will also be used for VZ support in KVM to know whether performance
counters exist which can be exposed to guests.

Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Robert Richter <rric@kernel.org>
Cc: linux-mips@linux-mips.org
Cc: oprofile-list@lists.sf.net
---
 arch/mips/include/asm/cpu-features.h | 4 ++++
 arch/mips/include/asm/cpu.h          | 1 +
 arch/mips/kernel/cpu-probe.c         | 2 ++
 arch/mips/kernel/perf_event_mipsxx.c | 4 +---
 arch/mips/oprofile/op_model_mipsxx.c | 4 +---
 5 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h
index 04b91d624c81..7cf708b52349 100644
--- a/arch/mips/include/asm/cpu-features.h
+++ b/arch/mips/include/asm/cpu-features.h
@@ -448,4 +448,8 @@
 # define cpu_has_contextconfig	(cpu_data[0].options & MIPS_CPU_CTXTC)
 #endif
 
+#ifndef cpu_has_perf
+# define cpu_has_perf		(cpu_data[0].options & MIPS_CPU_PERF)
+#endif
+
 #endif /* __ASM_CPU_FEATURES_H */
diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h
index 3a3848e2f481..3a4499660416 100644
--- a/arch/mips/include/asm/cpu.h
+++ b/arch/mips/include/asm/cpu.h
@@ -407,6 +407,7 @@ enum cpu_type_enum {
 #define MIPS_CPU_BADINSTR	MBIT_ULL(43)	/* CPU has BadInstr register */
 #define MIPS_CPU_BADINSTRP	MBIT_ULL(44)	/* CPU has BadInstrP register */
 #define MIPS_CPU_CTXTC		MBIT_ULL(45)	/* CPU has [X]ConfigContext registers */
+#define MIPS_CPU_PERF		MBIT_ULL(46)	/* CPU has MIPS performance counters */
 
 /*
  * CPU ASE encodings
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index e9bbb0a18168..316c4d7dd7ae 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -648,6 +648,8 @@ static inline unsigned int decode_config1(struct cpuinfo_mips *c)
 
 	if (config1 & MIPS_CONF1_MD)
 		c->ases |= MIPS_ASE_MDMX;
+	if (config1 & MIPS_CONF1_PC)
+		c->options |= MIPS_CPU_PERF;
 	if (config1 & MIPS_CONF1_WR)
 		c->options |= MIPS_CPU_WATCH;
 	if (config1 & MIPS_CONF1_CA)
diff --git a/arch/mips/kernel/perf_event_mipsxx.c b/arch/mips/kernel/perf_event_mipsxx.c
index 656769c166fc..302af8c975df 100644
--- a/arch/mips/kernel/perf_event_mipsxx.c
+++ b/arch/mips/kernel/perf_event_mipsxx.c
@@ -101,8 +101,6 @@ struct mips_pmu {
 
 static struct mips_pmu mipspmu;
 
-#define M_CONFIG1_PC	(1 << 4)
-
 #define M_PERFCTL_EXL			(1	<<  0)
 #define M_PERFCTL_KERNEL		(1	<<  1)
 #define M_PERFCTL_SUPERVISOR		(1	<<  2)
@@ -754,7 +752,7 @@ static void handle_associated_event(struct cpu_hw_events *cpuc,
 
 static int __n_counters(void)
 {
-	if (!(read_c0_config1() & M_CONFIG1_PC))
+	if (!cpu_has_perf)
 		return 0;
 	if (!(read_c0_perfctrl0() & M_PERFCTL_MORE))
 		return 1;
diff --git a/arch/mips/oprofile/op_model_mipsxx.c b/arch/mips/oprofile/op_model_mipsxx.c
index 8f988a61b7a8..45cb27469fba 100644
--- a/arch/mips/oprofile/op_model_mipsxx.c
+++ b/arch/mips/oprofile/op_model_mipsxx.c
@@ -269,11 +269,9 @@ static int mipsxx_perfcount_handler(void)
 	return handled;
 }
 
-#define M_CONFIG1_PC	(1 << 4)
-
 static inline int __n_counters(void)
 {
-	if (!(read_c0_config1() & M_CONFIG1_PC))
+	if (!cpu_has_perf)
 		return 0;
 	if (!(read_c0_perfctrl0() & M_PERFCTL_MORE))
 		return 1;
-- 
2.4.10

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

* Re: [PATCH v2 2/5] MIPS: Add defs & probing of extended CP0_EBase
@ 2016-05-11 12:56     ` Matt Redfearn
  0 siblings, 0 replies; 16+ messages in thread
From: Matt Redfearn @ 2016-05-11 12:56 UTC (permalink / raw)
  To: James Hogan, Ralf Baechle; +Cc: linux-mips



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>

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

* Re: [PATCH v2 2/5] MIPS: Add defs & probing of extended CP0_EBase
@ 2016-05-11 12:56     ` Matt Redfearn
  0 siblings, 0 replies; 16+ messages in thread
From: Matt Redfearn @ 2016-05-11 12:56 UTC (permalink / raw)
  To: James Hogan, Ralf Baechle; +Cc: linux-mips



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>

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

* Re: [PATCH v2 2/5] MIPS: Add defs & probing of extended CP0_EBase
@ 2016-05-12  1:10     ` Maciej W. Rozycki
  0 siblings, 0 replies; 16+ messages in thread
From: Maciej W. Rozycki @ 2016-05-12  1:10 UTC (permalink / raw)
  To: James Hogan; +Cc: Ralf Baechle, Matt Redfearn, linux-mips

Hi James,

> 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;

 You may additionally check for bits 31:30 != 0b10 as a satisfactory 
condition for WG's presence, under the assumption that 0b10 is not very 
likely if a truly 64-bit exception base has been loaded.  E.g.:

#define MIPS_EBASE_SEG_MASK (3 << 30)
		s32 mask;

		/* Avoid the clumsy probe if contents indicate 64 bits.  */
		mask = MIPS_EBASE_SEG_MASK | MIPS_CPU_EBASE_WG;
		if ((ebase & mask) != CKSEG0) {
			c->options |= MIPS_CPU_EBASE_WG;

or so.

 NB I find the current description of EBase questionable to say the least.  
This statement:

"The addition of the base address and the exception offset is performed 
inhibiting a carry between bits 29 and 30 of the final exception address." 

is repeated twice as if a leftover from the days before WG support.  I 
think this needs to be clarified in the case of bits 31:30 != 0b10.  Also 
I think the effect on the Cache Error exception vector in this case has to 
be better specified.  Can you please raise it with the architecture 
documentation maintainers?

 Also the description of DMFC0 is inconsistent with the corresponding 
pseudo code.  As from r6.04 of the instruction set document the pseudo 
code has been updated to take into account the R6 semantics for 32-bit 
registers you rely on here, however the description still claims such 
operation is UNDEFINED.  Can you please raise it with the architecture 
documentation maintainers as well?

  Maciej

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

* Re: [PATCH v2 2/5] MIPS: Add defs & probing of extended CP0_EBase
@ 2016-05-12  1:10     ` Maciej W. Rozycki
  0 siblings, 0 replies; 16+ messages in thread
From: Maciej W. Rozycki @ 2016-05-12  1:10 UTC (permalink / raw)
  To: James Hogan; +Cc: Ralf Baechle, Matt Redfearn, linux-mips

Hi James,

> 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;

 You may additionally check for bits 31:30 != 0b10 as a satisfactory 
condition for WG's presence, under the assumption that 0b10 is not very 
likely if a truly 64-bit exception base has been loaded.  E.g.:

#define MIPS_EBASE_SEG_MASK (3 << 30)
		s32 mask;

		/* Avoid the clumsy probe if contents indicate 64 bits.  */
		mask = MIPS_EBASE_SEG_MASK | MIPS_CPU_EBASE_WG;
		if ((ebase & mask) != CKSEG0) {
			c->options |= MIPS_CPU_EBASE_WG;

or so.

 NB I find the current description of EBase questionable to say the least.  
This statement:

"The addition of the base address and the exception offset is performed 
inhibiting a carry between bits 29 and 30 of the final exception address." 

is repeated twice as if a leftover from the days before WG support.  I 
think this needs to be clarified in the case of bits 31:30 != 0b10.  Also 
I think the effect on the Cache Error exception vector in this case has to 
be better specified.  Can you please raise it with the architecture 
documentation maintainers?

 Also the description of DMFC0 is inconsistent with the corresponding 
pseudo code.  As from r6.04 of the instruction set document the pseudo 
code has been updated to take into account the R6 semantics for 32-bit 
registers you rely on here, however the description still claims such 
operation is UNDEFINED.  Can you please raise it with the architecture 
documentation maintainers as well?

  Maciej

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

* Re: [PATCH v2 2/5] MIPS: Add defs & probing of extended CP0_EBase
@ 2016-05-12 16:12       ` James Hogan
  0 siblings, 0 replies; 16+ messages in thread
From: James Hogan @ 2016-05-12 16:12 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: Ralf Baechle, Matt Redfearn, linux-mips

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

On Thu, May 12, 2016 at 02:10:41AM +0100, Maciej W. Rozycki wrote:
> Hi James,
> 
> > 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;
> 
>  You may additionally check for bits 31:30 != 0b10 as a satisfactory 
> condition for WG's presence, under the assumption that 0b10 is not very 
> likely if a truly 64-bit exception base has been loaded.  E.g.:
> 
> #define MIPS_EBASE_SEG_MASK (3 << 30)
> 		s32 mask;
> 
> 		/* Avoid the clumsy probe if contents indicate 64 bits.  */
> 		mask = MIPS_EBASE_SEG_MASK | MIPS_CPU_EBASE_WG;
> 		if ((ebase & mask) != CKSEG0) {
> 			c->options |= MIPS_CPU_EBASE_WG;
> 
> or so.

Yep, good idea (I was originally working under the mistaken assumption
MIPS32 wouldn't have WG :-) ).

> 
>  NB I find the current description of EBase questionable to say the least.  
> This statement:
> 
> "The addition of the base address and the exception offset is performed 
> inhibiting a carry between bits 29 and 30 of the final exception address." 
> 
> is repeated twice as if a leftover from the days before WG support.  I 
> think this needs to be clarified in the case of bits 31:30 != 0b10.  Also 
> I think the effect on the Cache Error exception vector in this case has to 
> be better specified.  Can you please raise it with the architecture 
> documentation maintainers?

I agree, and ISTR its also stated that it must be set such that the
vectored interrupt spacing doesn't make it cross that boundary either,
in which case the inhibited carry is redundant. How it is supposed to
behave in the presence of cache error exceptions is indeed also
confusing, can it even ensure it gets handled from uncached memory? I
did raise this a while back, but will chase it up.

> 
>  Also the description of DMFC0 is inconsistent with the corresponding 
> pseudo code.  As from r6.04 of the instruction set document the pseudo 
> code has been updated to take into account the R6 semantics for 32-bit 
> registers you rely on here, however the description still claims such 
> operation is UNDEFINED.  Can you please raise it with the architecture 
> documentation maintainers as well?

Yes, I'll chase this up too.

Thanks
James

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

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

* Re: [PATCH v2 2/5] MIPS: Add defs & probing of extended CP0_EBase
@ 2016-05-12 16:12       ` James Hogan
  0 siblings, 0 replies; 16+ messages in thread
From: James Hogan @ 2016-05-12 16:12 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: Ralf Baechle, Matt Redfearn, linux-mips

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

On Thu, May 12, 2016 at 02:10:41AM +0100, Maciej W. Rozycki wrote:
> Hi James,
> 
> > 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;
> 
>  You may additionally check for bits 31:30 != 0b10 as a satisfactory 
> condition for WG's presence, under the assumption that 0b10 is not very 
> likely if a truly 64-bit exception base has been loaded.  E.g.:
> 
> #define MIPS_EBASE_SEG_MASK (3 << 30)
> 		s32 mask;
> 
> 		/* Avoid the clumsy probe if contents indicate 64 bits.  */
> 		mask = MIPS_EBASE_SEG_MASK | MIPS_CPU_EBASE_WG;
> 		if ((ebase & mask) != CKSEG0) {
> 			c->options |= MIPS_CPU_EBASE_WG;
> 
> or so.

Yep, good idea (I was originally working under the mistaken assumption
MIPS32 wouldn't have WG :-) ).

> 
>  NB I find the current description of EBase questionable to say the least.  
> This statement:
> 
> "The addition of the base address and the exception offset is performed 
> inhibiting a carry between bits 29 and 30 of the final exception address." 
> 
> is repeated twice as if a leftover from the days before WG support.  I 
> think this needs to be clarified in the case of bits 31:30 != 0b10.  Also 
> I think the effect on the Cache Error exception vector in this case has to 
> be better specified.  Can you please raise it with the architecture 
> documentation maintainers?

I agree, and ISTR its also stated that it must be set such that the
vectored interrupt spacing doesn't make it cross that boundary either,
in which case the inhibited carry is redundant. How it is supposed to
behave in the presence of cache error exceptions is indeed also
confusing, can it even ensure it gets handled from uncached memory? I
did raise this a while back, but will chase it up.

> 
>  Also the description of DMFC0 is inconsistent with the corresponding 
> pseudo code.  As from r6.04 of the instruction set document the pseudo 
> code has been updated to take into account the R6 semantics for 32-bit 
> registers you rely on here, however the description still claims such 
> operation is UNDEFINED.  Can you please raise it with the architecture 
> documentation maintainers as well?

Yes, I'll chase this up too.

Thanks
James

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

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

end of thread, other threads:[~2016-05-12 16:12 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
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
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

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.