Skip to contentSkip to conversation

x86, UV: Add function retrieving node controller revision number

PATCH In review Jack Steiner 3 participants 9 messages Jan 12, 2010 – Jan 27, 2010

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 x86, UV: Add function retrieving node controller revision number

Add function for determining the revision id of the SGI UV node controller chip (HUB). This function is needed in a subsequent patch.

---
 arch/x86/include/asm/uv/uv_hub.h   |   12 ++++++++++++
 arch/x86/kernel/apic/x2apic_uv_x.c |    6 ++++++
 2 files changed, 18 insertions(+)
arch/x86/include/asm/uv/uv_hub.h +12 -0
Index: linux/arch/x86/include/asm/uv/uv_hub.h
===================================================================
@@ -496,5 +496,17 @@ static inline void uv_hub_send_ipi(int p
 	uv_write_global_mmr64(pnode, UVH_IPI_INT, val);
 }
 
+/*
+ * Get the minimum revision number of the hub chips within the partition.
+ *     1 - initial rev 1.0 silicon
+ *     2 - rev 2.0 production silicon
+ */
+static inline int uv_get_min_hub_revision_id(void)
+{
+	extern int uv_min_hub_revision_id;
+
+	return uv_min_hub_revision_id;
+}
+
 #endif /* CONFIG_X86_64 */
 #endif /* _ASM_X86_UV_UV_HUB_H */
arch/x86/kernel/apic/x2apic_uv_x.c +6 -0
Index: linux/arch/x86/kernel/apic/x2apic_uv_x.c
===================================================================
@@ -36,6 +36,8 @@ DEFINE_PER_CPU(int, x2apic_extra_bits);
 
 static enum uv_system_type uv_system_type;
 static u64 gru_start_paddr, gru_end_paddr;
+int uv_min_hub_revision_id;
+EXPORT_SYMBOL_GPL(uv_min_hub_revision_id);
 
 static inline bool is_GRU_range(u64 start, u64 end)
 {
@@ -55,6 +57,10 @@ static int early_get_nodeid(void)
 	mmr = early_ioremap(UV_LOCAL_MMR_BASE | UVH_NODE_ID, sizeof(*mmr));
 	node_id.v = *mmr;
 	early_iounmap(mmr, sizeof(*mmr));
+
+	/* Currently, all blades have same revision number */
+	uv_min_hub_revision_id = node_id.s.revision;
+
 	return node_id.s.node_id;
 }
 
#1 lore raw
Quoted 10 lines · Jack Steiner

Add function for determining the revision id of the SGI UV node controller chip (HUB). This function is needed in a subsequent patch.

---
 arch/x86/include/asm/uv/uv_hub.h   |   12 ++++++++++++
 arch/x86/kernel/apic/x2apic_uv_x.c |    6 ++++++
 2 files changed, 18 insertions(+)

We'd need to see those two patches together i guess.

Ingo

#2 lore raw

PATCH 1/1 x86, UV: Read RTC using replicated cachelines

For SGI UV node controllers (HUB) rev 2.0 or greater, use replicated cachelines to read the RTC timer. This optimization allows faster simulataneous reads from a given socket.

---

Patch requires "Add function retrieving node controller revision number" patch.

 arch/x86/kernel/uv_time.c |   13 ++++++++++++-
 drivers/char/uv_mmtimer.c |   17 ++++++++++++-----
 2 files changed, 24 insertions(+), 6 deletions(-)
arch/x86/kernel/uv_time.c +12 -1
Index: linux/arch/x86/kernel/uv_time.c
===================================================================
@@ -282,10 +282,21 @@ static int uv_rtc_unset_timer(int cpu, i
 
 /*
  * Read the RTC.
+ *
+ * Starting with HUB rev 2.0, the UV RTC register is replicated across all
+ * cachelines of it's own page.  This allows faster simultaneous reads
+ * from a given socket.
  */
 static cycle_t uv_read_rtc(struct clocksource *cs)
 {
-	return (cycle_t)uv_read_local_mmr(UVH_RTC);
+	unsigned long offset;
+
+	if (uv_get_min_hub_revision_id() == 1)
+		offset = 0;
+	else
+		offset = (uv_blade_processor_id() * L1_CACHE_BYTES) % PAGE_SIZE;
+
+	return (cycle_t)uv_read_local_mmr(UVH_RTC | offset);
 }
 
 /*
drivers/char/uv_mmtimer.c +12 -5
Index: linux/drivers/char/uv_mmtimer.c
===================================================================
@@ -89,12 +89,19 @@ static long uv_mmtimer_ioctl(struct file
 	switch (cmd) {
 	case MMTIMER_GETOFFSET:	/* offset of the counter */
 		/*
-		 * UV RTC register is on its own page
+		 * Starting with HUB rev 2.0, the UV RTC register is
+		 * replicated across all cachelines of it's own page.
+		 * This allows faster simultaneous reads from a given socket.
+		 *
+		 * The offset returned is in 64 bit units.
 		 */
-		if (PAGE_SIZE <= (1 << 16))
-			ret = ((UV_LOCAL_MMR_BASE | UVH_RTC) & (PAGE_SIZE-1))
-				/ 8;
-		else
+		if (PAGE_SIZE <= (1 << 16)) {
+			if (uv_get_min_hub_revision_id() == 1)
+				ret = 0;
+			else
+				ret = ((uv_blade_processor_id() *
+					L1_CACHE_BYTES) % PAGE_SIZE) / 8;
+		} else
 			ret = -ENOSYS;
 		break;
 
#8 lore raw

[tip:x86/urgent] x86, uv: Add function retrieving node controller revision number

In reply to Jack Steiner
Commit-ID:  7a1110e861b2666ac09f5708d6fbe71d18ce64bb
Gitweb:     http://git.kernel.org/tip/7a1110e861b2666ac09f5708d6fbe71d18ce64bb
Author:     Jack Steiner <[email protected]>
AuthorDate: Tue, 12 Jan 2010 15:09:04 -0600
Committer:  H. Peter Anvin <[email protected]>
CommitDate: Fri, 15 Jan 2010 11:08:55 -0800

x86, uv: Add function retrieving node controller revision number

Add function for determining the revision id of the SGI UV node controller chip (HUB). This function is needed in a subsequent patch.

LKML-Reference: <[email protected]>

---
 arch/x86/include/asm/uv/uv_hub.h   |   12 ++++++++++++
 arch/x86/kernel/apic/x2apic_uv_x.c |    6 ++++++
 2 files changed, 18 insertions(+), 0 deletions(-)
arch/x86/include/asm/uv/uv_hub.h +12 -0
index bc54fa9..40be813 100644
@@ -495,5 +495,17 @@ static inline void uv_hub_send_ipi(int pnode, int apicid, int vector)
 	uv_write_global_mmr64(pnode, UVH_IPI_INT, val);
 }
 
+/*
+ * Get the minimum revision number of the hub chips within the partition.
+ *     1 - initial rev 1.0 silicon
+ *     2 - rev 2.0 production silicon
+ */
+static inline int uv_get_min_hub_revision_id(void)
+{
+	extern int uv_min_hub_revision_id;
+
+	return uv_min_hub_revision_id;
+}
+
 #endif /* CONFIG_X86_64 */
 #endif /* _ASM_X86_UV_UV_HUB_H */
arch/x86/kernel/apic/x2apic_uv_x.c +6 -0
index b8bb869..0e48de9 100644
@@ -36,6 +36,8 @@ DEFINE_PER_CPU(int, x2apic_extra_bits);
 
 static enum uv_system_type uv_system_type;
 static u64 gru_start_paddr, gru_end_paddr;
+int uv_min_hub_revision_id;
+EXPORT_SYMBOL_GPL(uv_min_hub_revision_id);
 
 static inline bool is_GRU_range(u64 start, u64 end)
 {
@@ -55,6 +57,10 @@ static int early_get_nodeid(void)
 	mmr = early_ioremap(UV_LOCAL_MMR_BASE | UVH_NODE_ID, sizeof(*mmr));
 	node_id.v = *mmr;
 	early_iounmap(mmr, sizeof(*mmr));
+
+	/* Currently, all blades have same revision number */
+	uv_min_hub_revision_id = node_id.s.revision;
+
 	return node_id.s.node_id;
 }
 
#3 lore raw

PATCH 1/1 x86, UV: Fix RTC latency bug by reading replicated cachelines

In reply to Dimitri Sivanich

Fix an RTC read latency bug by using replicated cachelines to read the RTC timer on SGI UV node controllers (HUB) rev 2.0 or greater.

---

Patch requires "Add function retrieving node controller revision number" patch.

 arch/x86/kernel/uv_time.c |   13 ++++++++++++-
 drivers/char/uv_mmtimer.c |   17 ++++++++++++-----
 2 files changed, 24 insertions(+), 6 deletions(-)
arch/x86/kernel/uv_time.c +12 -1
Index: linux/arch/x86/kernel/uv_time.c
===================================================================
@@ -282,10 +282,21 @@ static int uv_rtc_unset_timer(int cpu, i
 
 /*
  * Read the RTC.
+ *
+ * Starting with HUB rev 2.0, the UV RTC register is replicated across all
+ * cachelines of it's own page.  This allows faster simultaneous reads
+ * from a given socket.
  */
 static cycle_t uv_read_rtc(struct clocksource *cs)
 {
-	return (cycle_t)uv_read_local_mmr(UVH_RTC);
+	unsigned long offset;
+
+	if (uv_get_min_hub_revision_id() == 1)
+		offset = 0;
+	else
+		offset = (uv_blade_processor_id() * L1_CACHE_BYTES) % PAGE_SIZE;
+
+	return (cycle_t)uv_read_local_mmr(UVH_RTC | offset);
 }
 
 /*
drivers/char/uv_mmtimer.c +12 -5
Index: linux/drivers/char/uv_mmtimer.c
===================================================================
@@ -89,12 +89,19 @@ static long uv_mmtimer_ioctl(struct file
 	switch (cmd) {
 	case MMTIMER_GETOFFSET:	/* offset of the counter */
 		/*
-		 * UV RTC register is on its own page
+		 * Starting with HUB rev 2.0, the UV RTC register is
+		 * replicated across all cachelines of it's own page.
+		 * This allows faster simultaneous reads from a given socket.
+		 *
+		 * The offset returned is in 64 bit units.
 		 */
-		if (PAGE_SIZE <= (1 << 16))
-			ret = ((UV_LOCAL_MMR_BASE | UVH_RTC) & (PAGE_SIZE-1))
-				/ 8;
-		else
+		if (PAGE_SIZE <= (1 << 16)) {
+			if (uv_get_min_hub_revision_id() == 1)
+				ret = 0;
+			else
+				ret = ((uv_blade_processor_id() *
+					L1_CACHE_BYTES) % PAGE_SIZE) / 8;
+		} else
 			ret = -ENOSYS;
 		break;
 
#4 lore raw

Re: [PATCH] x86, UV: Fix RTC latency bug by reading replicated cachelines

Quoted 13 lines · Dimitri Sivanich

+++ linux/drivers/char/uv_mmtimer.c 2010-01-14 11:56:57.000000000 -0600

drivers/char/uv_mmtimer.c +5 -2
@@ -89,12 +89,19 @@ static long uv_mmtimer_ioctl(struct file
 	switch (cmd) {
 	case MMTIMER_GETOFFSET:	/* offset of the counter */
 		/*
-		 * UV RTC register is on its own page
+		 * Starting with HUB rev 2.0, the UV RTC register is
+		 * replicated across all cachelines of it's own page.
+		 * This allows faster simultaneous reads from a given socket.
+		 *
+		 * The offset returned is in 64 bit units.
 		 */
-		if (PAGE_SIZE <= (1 << 16))

drivers/char/uv_mmtimer.c static long uv_mmtimer_ioctl(struct file · line 104

Quoted 10 lines
drivers/char/uv_mmtimer.c +7 -3
-			ret = ((UV_LOCAL_MMR_BASE | UVH_RTC) & (PAGE_SIZE-1))
-				/ 8;
-		else
+		if (PAGE_SIZE <= (1 << 16)) {
+			if (uv_get_min_hub_revision_id() == 1)
+				ret = 0;
+			else
+				ret = ((uv_blade_processor_id() *
+					L1_CACHE_BYTES) % PAGE_SIZE) / 8;
+		} else

That 64K PAGE_SIZE check in the ioctl looks rather weird. What is the purpose of it?

Ingo

#5 lore raw

Re: [PATCH] x86, UV: Fix RTC latency bug by reading replicated cachelines

Quoted 21 lines · Ingo Molnar
Quoted 18 lines · Dimitri Sivanich

+++ linux/drivers/char/uv_mmtimer.c 2010-01-14 11:56:57.000000000 -0600

drivers/char/uv_mmtimer.c +7 -5
@@ -89,12 +89,19 @@ static long uv_mmtimer_ioctl(struct file
 	switch (cmd) {
 	case MMTIMER_GETOFFSET:	/* offset of the counter */
 		/*
-		 * UV RTC register is on its own page
+		 * Starting with HUB rev 2.0, the UV RTC register is
+		 * replicated across all cachelines of it's own page.
+		 * This allows faster simultaneous reads from a given socket.
+		 *
+		 * The offset returned is in 64 bit units.
 		 */
-		if (PAGE_SIZE <= (1 << 16))
-			ret = ((UV_LOCAL_MMR_BASE | UVH_RTC) & (PAGE_SIZE-1))
-				/ 8;
-		else
+		if (PAGE_SIZE <= (1 << 16)) {
+			if (uv_get_min_hub_revision_id() == 1)
Quoted 8 lines

drivers/char/uv_mmtimer.c static long uv_mmtimer_ioctl(struct file · line 104

Quoted 5 lines
drivers/char/uv_mmtimer.c +5 -0
+				ret = 0;
+			else
+				ret = ((uv_blade_processor_id() *
+					L1_CACHE_BYTES) % PAGE_SIZE) / 8;
+		} else

That 64K PAGE_SIZE check in the ioctl looks rather weird. What is the purpose of it?

Checking for > 64k pages is really a holdover from similar code on ia64. I've taken it out with a modified version of this patch that I'll send shortly.

#6 lore raw

Re: [PATCH] x86, UV: Fix RTC latency bug by reading replicated cachelines

In reply to Ingo Molnar

For SGI UV node controllers (HUB) rev 2.0 or greater, use replicated cachelines to read the RTC timer. This optimization allows faster simulataneous reads from a given socket.

---

 arch/x86/kernel/uv_time.c |   13 ++++++++++++-
 drivers/char/uv_mmtimer.c |   18 +++++++++++-------
 2 files changed, 23 insertions(+), 8 deletions(-)
arch/x86/kernel/uv_time.c +12 -1
Index: linux/arch/x86/kernel/uv_time.c
===================================================================
@@ -282,10 +282,21 @@ static int uv_rtc_unset_timer(int cpu, i
 
 /*
  * Read the RTC.
+ *
+ * Starting with HUB rev 2.0, the UV RTC register is replicated across all
+ * cachelines of it's own page.  This allows faster simultaneous reads
+ * from a given socket.
  */
 static cycle_t uv_read_rtc(struct clocksource *cs)
 {
-	return (cycle_t)uv_read_local_mmr(UVH_RTC);
+	unsigned long offset;
+
+	if (uv_get_min_hub_revision_id() == 1)
+		offset = 0;
+	else
+		offset = (uv_blade_processor_id() * L1_CACHE_BYTES) % PAGE_SIZE;
+
+	return (cycle_t)uv_read_local_mmr(UVH_RTC | offset);
 }
 
 /*
drivers/char/uv_mmtimer.c +11 -7
Index: linux/drivers/char/uv_mmtimer.c
===================================================================
@@ -89,13 +89,17 @@ static long uv_mmtimer_ioctl(struct file
 	switch (cmd) {
 	case MMTIMER_GETOFFSET:	/* offset of the counter */
 		/*
-		 * UV RTC register is on its own page
+		 * Starting with HUB rev 2.0, the UV RTC register is
+		 * replicated across all cachelines of it's own page.
+		 * This allows faster simultaneous reads from a given socket.
+		 *
+		 * The offset returned is in 64 bit units.
 		 */
-		if (PAGE_SIZE <= (1 << 16))
-			ret = ((UV_LOCAL_MMR_BASE | UVH_RTC) & (PAGE_SIZE-1))
-				/ 8;
+		if (uv_get_min_hub_revision_id() == 1)
+			ret = 0;
 		else
-			ret = -ENOSYS;
+			ret = ((uv_blade_processor_id() * L1_CACHE_BYTES) %
+					PAGE_SIZE) / 8;
 		break;
 
 	case MMTIMER_GETRES: /* resolution of the clock in 10^-15 s */
@@ -115,8 +119,8 @@ static long uv_mmtimer_ioctl(struct file
 		ret = hweight64(UVH_RTC_REAL_TIME_CLOCK_MASK);
 		break;
 
-	case MMTIMER_MMAPAVAIL: /* can we mmap the clock into userspace? */
-		ret = (PAGE_SIZE <= (1 << 16)) ? 1 : 0;
+	case MMTIMER_MMAPAVAIL:
+		ret = 1;
 		break;
 
 	case MMTIMER_GETCOUNTER:
#7 lore raw

[tip:x86/urgent] x86, UV: Fix RTC latency bug by reading replicated cachelines

Commit-ID:  aca3bb5910119d4cf6c28568a642582efb4cc14a
Gitweb:     http://git.kernel.org/tip/aca3bb5910119d4cf6c28568a642582efb4cc14a
Author:     Dimitri Sivanich <[email protected]>
AuthorDate: Fri, 22 Jan 2010 09:41:40 -0600
Committer:  Ingo Molnar <[email protected]>
CommitDate: Wed, 27 Jan 2010 11:33:53 +0100

x86, UV: Fix RTC latency bug by reading replicated cachelines

For SGI UV node controllers (HUB) rev 2.0 or greater, use replicated cachelines to read the RTC timer. This optimization allows faster simulataneous reads from a given socket.

LKML-Reference: <[email protected]>

---
 arch/x86/kernel/uv_time.c |   13 ++++++++++++-
 drivers/char/uv_mmtimer.c |   18 +++++++++++-------
 2 files changed, 23 insertions(+), 8 deletions(-)
arch/x86/kernel/uv_time.c +12 -1
index 3c84aa0..2b75ef6 100644
@@ -282,10 +282,21 @@ static int uv_rtc_unset_timer(int cpu, int force)
 
 /*
  * Read the RTC.
+ *
+ * Starting with HUB rev 2.0, the UV RTC register is replicated across all
+ * cachelines of it's own page.  This allows faster simultaneous reads
+ * from a given socket.
  */
 static cycle_t uv_read_rtc(struct clocksource *cs)
 {
-	return (cycle_t)uv_read_local_mmr(UVH_RTC);
+	unsigned long offset;
+
+	if (uv_get_min_hub_revision_id() == 1)
+		offset = 0;
+	else
+		offset = (uv_blade_processor_id() * L1_CACHE_BYTES) % PAGE_SIZE;
+
+	return (cycle_t)uv_read_local_mmr(UVH_RTC | offset);
 }
 
 /*
drivers/char/uv_mmtimer.c +11 -7
index 867b67b..c7072ba 100644
@@ -89,13 +89,17 @@ static long uv_mmtimer_ioctl(struct file *file, unsigned int cmd,
 	switch (cmd) {
 	case MMTIMER_GETOFFSET:	/* offset of the counter */
 		/*
-		 * UV RTC register is on its own page
+		 * Starting with HUB rev 2.0, the UV RTC register is
+		 * replicated across all cachelines of it's own page.
+		 * This allows faster simultaneous reads from a given socket.
+		 *
+		 * The offset returned is in 64 bit units.
 		 */
-		if (PAGE_SIZE <= (1 << 16))
-			ret = ((UV_LOCAL_MMR_BASE | UVH_RTC) & (PAGE_SIZE-1))
-				/ 8;
+		if (uv_get_min_hub_revision_id() == 1)
+			ret = 0;
 		else
-			ret = -ENOSYS;
+			ret = ((uv_blade_processor_id() * L1_CACHE_BYTES) %
+					PAGE_SIZE) / 8;
 		break;
 
 	case MMTIMER_GETRES: /* resolution of the clock in 10^-15 s */
@@ -115,8 +119,8 @@ static long uv_mmtimer_ioctl(struct file *file, unsigned int cmd,
 		ret = hweight64(UVH_RTC_REAL_TIME_CLOCK_MASK);
 		break;
 
-	case MMTIMER_MMAPAVAIL: /* can we mmap the clock into userspace? */
-		ret = (PAGE_SIZE <= (1 << 16)) ? 1 : 0;
+	case MMTIMER_MMAPAVAIL:
+		ret = 1;
 		break;
 
 	case MMTIMER_GETCOUNTER: