]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/3.1.1/x86-uv2-workaround-for-uv2-hub-bug-system-global-address-format.patch
4.14-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 3.1.1 / x86-uv2-workaround-for-uv2-hub-bug-system-global-address-format.patch
CommitLineData
df8f408d
GKH
1From 6a469e4665bc158599de55d64388861d0a9f10f4 Mon Sep 17 00:00:00 2001
2From: Jack Steiner <steiner@sgi.com>
3Date: Tue, 20 Sep 2011 13:55:04 -0700
4Subject: x86: uv2: Workaround for UV2 Hub bug (system global address format)
5
6From: Jack Steiner <steiner@sgi.com>
7
8commit 6a469e4665bc158599de55d64388861d0a9f10f4 upstream.
9
10This is a workaround for a UV2 hub bug that affects the format of system
11global addresses.
12
13The GRU API for UV2 was inadvertently broken by a hardware change. The
14format of the physical address used for TLB dropins and for addresses used
15with instructions running in unmapped mode has changed. This change was
16not documented and became apparent only when diags failed running on
17system simulators.
18
19For UV1, TLB and GRU instruction physical addresses are identical to
20socket physical addresses (although high NASID bits must be OR'ed into the
21address).
22
23For UV2, socket physical addresses need to be converted. The NODE portion
24of the physical address needs to be shifted so that the low bit is in bit
2539 or bit 40, depending on an MMR value.
26
27It is not yet clear if this bug will be fixed in a silicon respin. If it
28is fixed, the hub revision will be incremented & the workaround disabled.
29
30Signed-off-by: Jack Steiner <steiner@sgi.com>
31Cc: Ingo Molnar <mingo@elte.hu>
32Cc: "H. Peter Anvin" <hpa@zytor.com>
33Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
34Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
35Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
36
37---
38 arch/x86/include/asm/uv/uv_bau.h | 1 +
39 arch/x86/include/asm/uv/uv_hub.h | 37 ++++++++++++++++++++++++++++++++++---
40 arch/x86/kernel/apic/x2apic_uv_x.c | 7 +++++--
41 arch/x86/platform/uv/tlb_uv.c | 17 ++++++-----------
42 4 files changed, 46 insertions(+), 16 deletions(-)
43
44--- a/arch/x86/include/asm/uv/uv_bau.h
45+++ b/arch/x86/include/asm/uv/uv_bau.h
46@@ -55,6 +55,7 @@
47 #define UV_BAU_TUNABLES_DIR "sgi_uv"
48 #define UV_BAU_TUNABLES_FILE "bau_tunables"
49 #define WHITESPACE " \t\n"
50+#define uv_mmask ((1UL << uv_hub_info->m_val) - 1)
51 #define uv_physnodeaddr(x) ((__pa((unsigned long)(x)) & uv_mmask))
52 #define cpubit_isset(cpu, bau_local_cpumask) \
53 test_bit((cpu), (bau_local_cpumask).bits)
54--- a/arch/x86/include/asm/uv/uv_hub.h
55+++ b/arch/x86/include/asm/uv/uv_hub.h
56@@ -46,6 +46,13 @@
57 * PNODE - the low N bits of the GNODE. The PNODE is the most useful variant
58 * of the nasid for socket usage.
59 *
60+ * GPA - (global physical address) a socket physical address converted
61+ * so that it can be used by the GRU as a global address. Socket
62+ * physical addresses 1) need additional NASID (node) bits added
63+ * to the high end of the address, and 2) unaliased if the
64+ * partition does not have a physical address 0. In addition, on
65+ * UV2 rev 1, GPAs need the gnode left shifted to bits 39 or 40.
66+ *
67 *
68 * NumaLink Global Physical Address Format:
69 * +--------------------------------+---------------------+
70@@ -141,6 +148,8 @@ struct uv_hub_info_s {
71 unsigned int gnode_extra;
72 unsigned char hub_revision;
73 unsigned char apic_pnode_shift;
74+ unsigned char m_shift;
75+ unsigned char n_lshift;
76 unsigned long gnode_upper;
77 unsigned long lowmem_remap_top;
78 unsigned long lowmem_remap_base;
79@@ -177,6 +186,16 @@ static inline int is_uv2_hub(void)
80 return uv_hub_info->hub_revision >= UV2_HUB_REVISION_BASE;
81 }
82
83+static inline int is_uv2_1_hub(void)
84+{
85+ return uv_hub_info->hub_revision == UV2_HUB_REVISION_BASE;
86+}
87+
88+static inline int is_uv2_2_hub(void)
89+{
90+ return uv_hub_info->hub_revision == UV2_HUB_REVISION_BASE + 1;
91+}
92+
93 union uvh_apicid {
94 unsigned long v;
95 struct uvh_apicid_s {
96@@ -276,7 +295,10 @@ static inline unsigned long uv_soc_phys_
97 {
98 if (paddr < uv_hub_info->lowmem_remap_top)
99 paddr |= uv_hub_info->lowmem_remap_base;
100- return paddr | uv_hub_info->gnode_upper;
101+ paddr |= uv_hub_info->gnode_upper;
102+ paddr = ((paddr << uv_hub_info->m_shift) >> uv_hub_info->m_shift) |
103+ ((paddr >> uv_hub_info->m_val) << uv_hub_info->n_lshift);
104+ return paddr;
105 }
106
107
108@@ -300,16 +322,19 @@ static inline unsigned long uv_gpa_to_so
109 unsigned long remap_base = uv_hub_info->lowmem_remap_base;
110 unsigned long remap_top = uv_hub_info->lowmem_remap_top;
111
112+ gpa = ((gpa << uv_hub_info->m_shift) >> uv_hub_info->m_shift) |
113+ ((gpa >> uv_hub_info->n_lshift) << uv_hub_info->m_val);
114+ gpa = gpa & uv_hub_info->gpa_mask;
115 if (paddr >= remap_base && paddr < remap_base + remap_top)
116 paddr -= remap_base;
117 return paddr;
118 }
119
120
121-/* gnode -> pnode */
122+/* gpa -> pnode */
123 static inline unsigned long uv_gpa_to_gnode(unsigned long gpa)
124 {
125- return gpa >> uv_hub_info->m_val;
126+ return gpa >> uv_hub_info->n_lshift;
127 }
128
129 /* gpa -> pnode */
130@@ -320,6 +345,12 @@ static inline int uv_gpa_to_pnode(unsign
131 return uv_gpa_to_gnode(gpa) & n_mask;
132 }
133
134+/* gpa -> node offset*/
135+static inline unsigned long uv_gpa_to_offset(unsigned long gpa)
136+{
137+ return (gpa << uv_hub_info->m_shift) >> uv_hub_info->m_shift;
138+}
139+
140 /* pnode, offset --> socket virtual */
141 static inline void *uv_pnode_offset_to_vaddr(int pnode, unsigned long offset)
142 {
143--- a/arch/x86/kernel/apic/x2apic_uv_x.c
144+++ b/arch/x86/kernel/apic/x2apic_uv_x.c
145@@ -832,6 +832,10 @@ void __init uv_system_init(void)
146 uv_cpu_hub_info(cpu)->apic_pnode_shift = uvh_apicid.s.pnode_shift;
147 uv_cpu_hub_info(cpu)->hub_revision = uv_hub_info->hub_revision;
148
149+ uv_cpu_hub_info(cpu)->m_shift = 64 - m_val;
150+ uv_cpu_hub_info(cpu)->n_lshift = is_uv2_1_hub() ?
151+ (m_val == 40 ? 40 : 39) : m_val;
152+
153 pnode = uv_apicid_to_pnode(apicid);
154 blade = boot_pnode_to_blade(pnode);
155 lcpu = uv_blade_info[blade].nr_possible_cpus;
156@@ -862,8 +866,7 @@ void __init uv_system_init(void)
157 if (uv_node_to_blade[nid] >= 0)
158 continue;
159 paddr = node_start_pfn(nid) << PAGE_SHIFT;
160- paddr = uv_soc_phys_ram_to_gpa(paddr);
161- pnode = (paddr >> m_val) & pnode_mask;
162+ pnode = uv_gpa_to_pnode(uv_soc_phys_ram_to_gpa(paddr));
163 blade = boot_pnode_to_blade(pnode);
164 uv_node_to_blade[nid] = blade;
165 }
166--- a/arch/x86/platform/uv/tlb_uv.c
167+++ b/arch/x86/platform/uv/tlb_uv.c
168@@ -115,9 +115,6 @@ early_param("nobau", setup_nobau);
169
170 /* base pnode in this partition */
171 static int uv_base_pnode __read_mostly;
172-/* position of pnode (which is nasid>>1): */
173-static int uv_nshift __read_mostly;
174-static unsigned long uv_mmask __read_mostly;
175
176 static DEFINE_PER_CPU(struct ptc_stats, ptcstats);
177 static DEFINE_PER_CPU(struct bau_control, bau_control);
178@@ -1435,7 +1432,7 @@ static void activation_descriptor_init(i
179 {
180 int i;
181 int cpu;
182- unsigned long pa;
183+ unsigned long gpa;
184 unsigned long m;
185 unsigned long n;
186 size_t dsize;
187@@ -1451,9 +1448,9 @@ static void activation_descriptor_init(i
188 bau_desc = kmalloc_node(dsize, GFP_KERNEL, node);
189 BUG_ON(!bau_desc);
190
191- pa = uv_gpa(bau_desc); /* need the real nasid*/
192- n = pa >> uv_nshift;
193- m = pa & uv_mmask;
194+ gpa = uv_gpa(bau_desc);
195+ n = uv_gpa_to_gnode(gpa);
196+ m = uv_gpa_to_offset(gpa);
197
198 /* the 14-bit pnode */
199 write_mmr_descriptor_base(pnode, (n << UV_DESC_PSHIFT | m));
200@@ -1525,9 +1522,9 @@ static void pq_init(int node, int pnode)
201 bcp->queue_last = pqp + (DEST_Q_SIZE - 1);
202 }
203 /*
204- * need the pnode of where the memory was really allocated
205+ * need the gnode of where the memory was really allocated
206 */
207- pn = uv_gpa(pqp) >> uv_nshift;
208+ pn = uv_gpa_to_gnode(uv_gpa(pqp));
209 first = uv_physnodeaddr(pqp);
210 pn_first = ((unsigned long)pn << UV_PAYLOADQ_PNODE_SHIFT) | first;
211 last = uv_physnodeaddr(pqp + (DEST_Q_SIZE - 1));
212@@ -1837,8 +1834,6 @@ static int __init uv_bau_init(void)
213 zalloc_cpumask_var_node(mask, GFP_KERNEL, cpu_to_node(cur_cpu));
214 }
215
216- uv_nshift = uv_hub_info->m_val;
217- uv_mmask = (1UL << uv_hub_info->m_val) - 1;
218 nuvhubs = uv_num_possible_blades();
219 spin_lock_init(&disable_lock);
220 congested_cycles = usec_2_cycles(congested_respns_us);