aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authormike.travis@hpe.com <mike.travis@hpe.com>2018-05-24 16:17:13 -0400
committerIngo Molnar <mingo@kernel.org>2018-06-21 10:14:45 -0400
commitbbbd2b51a2aa0d76b3676271e216cf3647773397 (patch)
tree894cf28238bb7409c13ea77d09d9e3f15449bd5b /arch
parentf642fb5864a6e3645edce6f85ffe7b44d5e9b990 (diff)
x86/platform/UV: Use new set memory block size function
Add a call to the new function to "adjust" the current fixed UV memory block size of 2GB so it can be changed to a different physical boundary. This accommodates changes in the Intel BIOS, and therefore UV BIOS, which now can align boundaries different than the previous UV standard of 2GB. It also flags any UV Global Address boundaries from BIOS that cause a change in the mem block size (boundary). The current boundary of 2GB has been used on UV since the first system release in 2009 with Linux 2.6 and has worked fine. But the new NVDIMM persistent memory modules (PMEM), along with the Intel BIOS changes to support these modules caused the memory block size boundary to be set to a lower limit. Intel only guarantees that this minimum boundary at 64MB though the current Linux limit is 128MB. Note that the default remains 2GB if no changes occur. Signed-off-by: Mike Travis <mike.travis@hpe.com> Reviewed-by: Andrew Banman <andrew.banman@hpe.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Dimitri Sivanich <dimitri.sivanich@hpe.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Russ Anderson <russ.anderson@hpe.com> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: dan.j.williams@intel.com Cc: jgross@suse.com Cc: kirill.shutemov@linux.intel.com Cc: mhocko@suse.com Cc: stable@vger.kernel.org Link: https://lkml.kernel.org/lkml/20180524201711.732785782@stormcage.americas.sgi.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/kernel/apic/x2apic_uv_x.c49
1 files changed, 46 insertions, 3 deletions
diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c
index efaf2d4f9c3c..2270a777d647 100644
--- a/arch/x86/kernel/apic/x2apic_uv_x.c
+++ b/arch/x86/kernel/apic/x2apic_uv_x.c
@@ -26,6 +26,7 @@
26#include <linux/delay.h> 26#include <linux/delay.h>
27#include <linux/crash_dump.h> 27#include <linux/crash_dump.h>
28#include <linux/reboot.h> 28#include <linux/reboot.h>
29#include <linux/memory.h>
29 30
30#include <asm/uv/uv_mmrs.h> 31#include <asm/uv/uv_mmrs.h>
31#include <asm/uv/uv_hub.h> 32#include <asm/uv/uv_hub.h>
@@ -392,6 +393,40 @@ extern int uv_hub_info_version(void)
392} 393}
393EXPORT_SYMBOL(uv_hub_info_version); 394EXPORT_SYMBOL(uv_hub_info_version);
394 395
396/* Default UV memory block size is 2GB */
397static unsigned long mem_block_size = (2UL << 30);
398
399static __init int adj_blksize(u32 lgre)
400{
401 unsigned long base = (unsigned long)lgre << UV_GAM_RANGE_SHFT;
402 unsigned long size;
403
404 for (size = mem_block_size; size > MIN_MEMORY_BLOCK_SIZE; size >>= 1)
405 if (IS_ALIGNED(base, size))
406 break;
407
408 if (size >= mem_block_size)
409 return 0;
410
411 mem_block_size = size;
412 return 1;
413}
414
415static __init void set_block_size(void)
416{
417 unsigned int order = ffs(mem_block_size);
418
419 if (order) {
420 /* adjust for ffs return of 1..64 */
421 set_memory_block_size_order(order - 1);
422 pr_info("UV: mem_block_size set to 0x%lx\n", mem_block_size);
423 } else {
424 /* bad or zero value, default to 1UL << 31 (2GB) */
425 pr_err("UV: mem_block_size error with 0x%lx\n", mem_block_size);
426 set_memory_block_size_order(31);
427 }
428}
429
395/* Build GAM range lookup table: */ 430/* Build GAM range lookup table: */
396static __init void build_uv_gr_table(void) 431static __init void build_uv_gr_table(void)
397{ 432{
@@ -1180,23 +1215,30 @@ static void __init decode_gam_rng_tbl(unsigned long ptr)
1180 << UV_GAM_RANGE_SHFT); 1215 << UV_GAM_RANGE_SHFT);
1181 int order = 0; 1216 int order = 0;
1182 char suffix[] = " KMGTPE"; 1217 char suffix[] = " KMGTPE";
1218 int flag = ' ';
1183 1219
1184 while (size > 9999 && order < sizeof(suffix)) { 1220 while (size > 9999 && order < sizeof(suffix)) {
1185 size /= 1024; 1221 size /= 1024;
1186 order++; 1222 order++;
1187 } 1223 }
1188 1224
1225 /* adjust max block size to current range start */
1226 if (gre->type == 1 || gre->type == 2)
1227 if (adj_blksize(lgre))
1228 flag = '*';
1229
1189 if (!index) { 1230 if (!index) {
1190 pr_info("UV: GAM Range Table...\n"); 1231 pr_info("UV: GAM Range Table...\n");
1191 pr_info("UV: # %20s %14s %5s %4s %5s %3s %2s\n", "Range", "", "Size", "Type", "NASID", "SID", "PN"); 1232 pr_info("UV: # %20s %14s %6s %4s %5s %3s %2s\n", "Range", "", "Size", "Type", "NASID", "SID", "PN");
1192 } 1233 }
1193 pr_info("UV: %2d: 0x%014lx-0x%014lx %5lu%c %3d %04x %02x %02x\n", 1234 pr_info("UV: %2d: 0x%014lx-0x%014lx%c %5lu%c %3d %04x %02x %02x\n",
1194 index++, 1235 index++,
1195 (unsigned long)lgre << UV_GAM_RANGE_SHFT, 1236 (unsigned long)lgre << UV_GAM_RANGE_SHFT,
1196 (unsigned long)gre->limit << UV_GAM_RANGE_SHFT, 1237 (unsigned long)gre->limit << UV_GAM_RANGE_SHFT,
1197 size, suffix[order], 1238 flag, size, suffix[order],
1198 gre->type, gre->nasid, gre->sockid, gre->pnode); 1239 gre->type, gre->nasid, gre->sockid, gre->pnode);
1199 1240
1241 /* update to next range start */
1200 lgre = gre->limit; 1242 lgre = gre->limit;
1201 if (sock_min > gre->sockid) 1243 if (sock_min > gre->sockid)
1202 sock_min = gre->sockid; 1244 sock_min = gre->sockid;
@@ -1427,6 +1469,7 @@ static void __init uv_system_init_hub(void)
1427 1469
1428 build_socket_tables(); 1470 build_socket_tables();
1429 build_uv_gr_table(); 1471 build_uv_gr_table();
1472 set_block_size();
1430 uv_init_hub_info(&hub_info); 1473 uv_init_hub_info(&hub_info);
1431 uv_possible_blades = num_possible_nodes(); 1474 uv_possible_blades = num_possible_nodes();
1432 if (!_node_to_pnode) 1475 if (!_node_to_pnode)