Skip to content

Commit 1e61f5a

Browse files
mike-travissuryasaimadhu
authored andcommitted
x86/platform/uv: Add and decode Arch Type in UVsystab
When the UV BIOS starts the kernel it passes the UVsystab info struct to the kernel which contains information elements more specific than ACPI, and generally pertinent only to the MMRs. These are read only fields so information is passed one way only. A new field starting with UV5 is the UV architecture type so the ACPI OEM_ID field can be used for other purposes going forward. The UV Arch Type selects the entirety of the MMRs available, with their addresses and fields defined in uv_mmrs.h. Reported-by: kernel test robot <lkp@intel.com> Signed-off-by: Mike Travis <mike.travis@hpe.com> Signed-off-by: Borislav Petkov <bp@suse.de> Reviewed-by: Dimitri Sivanich <dimitri.sivanich@hpe.com> Reviewed-by: Steve Wahl <steve.wahl@hpe.com> Link: https://lkml.kernel.org/r/20201005203929.148656-7-mike.travis@hpe.com
1 parent 6c77944 commit 1e61f5a

3 files changed

Lines changed: 148 additions & 30 deletions

File tree

arch/x86/include/asm/uv/bios.h

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
/*
66
* UV BIOS layer definitions.
77
*
8-
* Copyright (c) 2008-2009 Silicon Graphics, Inc. All Rights Reserved.
9-
* Copyright (c) Russ Anderson <rja@sgi.com>
8+
* Copyright (C) 2007-2017 Silicon Graphics, Inc. All rights reserved.
9+
* Copyright (c) Russ Anderson <rja@sgi.com>
1010
*/
1111

1212
#include <linux/rtc.h>
@@ -71,6 +71,11 @@ struct uv_gam_range_entry {
7171
u32 limit; /* PA bits 56:26 (UV_GAM_RANGE_SHFT) */
7272
};
7373

74+
#define UV_AT_SIZE 8 /* 7 character arch type + NULL char */
75+
struct uv_arch_type_entry {
76+
char archtype[UV_AT_SIZE];
77+
};
78+
7479
#define UV_SYSTAB_SIG "UVST"
7580
#define UV_SYSTAB_VERSION_1 1 /* UV2/3 BIOS version */
7681
#define UV_SYSTAB_VERSION_UV4 0x400 /* UV4 BIOS base version */
@@ -79,10 +84,14 @@ struct uv_gam_range_entry {
7984
#define UV_SYSTAB_VERSION_UV4_3 0x403 /* - GAM Range PXM Value */
8085
#define UV_SYSTAB_VERSION_UV4_LATEST UV_SYSTAB_VERSION_UV4_3
8186

87+
#define UV_SYSTAB_VERSION_UV5 0x500 /* UV5 GAM base version */
88+
#define UV_SYSTAB_VERSION_UV5_LATEST UV_SYSTAB_VERSION_UV5
89+
8290
#define UV_SYSTAB_TYPE_UNUSED 0 /* End of table (offset == 0) */
8391
#define UV_SYSTAB_TYPE_GAM_PARAMS 1 /* GAM PARAM conversions */
8492
#define UV_SYSTAB_TYPE_GAM_RNG_TBL 2 /* GAM entry table */
85-
#define UV_SYSTAB_TYPE_MAX 3
93+
#define UV_SYSTAB_TYPE_ARCH_TYPE 3 /* UV arch type */
94+
#define UV_SYSTAB_TYPE_MAX 4
8695

8796
/*
8897
* The UV system table describes specific firmware
@@ -133,6 +142,7 @@ extern s64 uv_bios_reserved_page_pa(u64, u64 *, u64 *, u64 *);
133142
extern int uv_bios_set_legacy_vga_target(bool decode, int domain, int bus);
134143

135144
extern int uv_bios_init(void);
145+
extern unsigned long get_uv_systab_phys(bool msg);
136146

137147
extern unsigned long sn_rtc_cycles_per_second;
138148
extern int uv_type;

arch/x86/kernel/apic/x2apic_uv_x.c

Lines changed: 116 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ static u64 gru_start_paddr, gru_end_paddr;
3131
static union uvh_apicid uvh_apicid;
3232
static int uv_node_id;
3333

34-
/* Unpack OEM/TABLE ID's to be NULL terminated strings */
34+
/* Unpack AT/OEM/TABLE ID's to be NULL terminated strings */
35+
static u8 uv_archtype[UV_AT_SIZE];
3536
static u8 oem_id[ACPI_OEM_ID_SIZE + 1];
3637
static u8 oem_table_id[ACPI_OEM_TABLE_ID_SIZE + 1];
3738

@@ -284,18 +285,102 @@ static void __init uv_stringify(int len, char *to, char *from)
284285
strncpy(to, from, len-1);
285286
}
286287

288+
/* Find UV arch type entry in UVsystab */
289+
static unsigned long __init early_find_archtype(struct uv_systab *st)
290+
{
291+
int i;
292+
293+
for (i = 0; st->entry[i].type != UV_SYSTAB_TYPE_UNUSED; i++) {
294+
unsigned long ptr = st->entry[i].offset;
295+
296+
if (!ptr)
297+
continue;
298+
ptr += (unsigned long)st;
299+
if (st->entry[i].type == UV_SYSTAB_TYPE_ARCH_TYPE)
300+
return ptr;
301+
}
302+
return 0;
303+
}
304+
305+
/* Validate UV arch type field in UVsystab */
306+
static int __init decode_arch_type(unsigned long ptr)
307+
{
308+
struct uv_arch_type_entry *uv_ate = (struct uv_arch_type_entry *)ptr;
309+
int n = strlen(uv_ate->archtype);
310+
311+
if (n > 0 && n < sizeof(uv_ate->archtype)) {
312+
pr_info("UV: UVarchtype received from BIOS\n");
313+
uv_stringify(UV_AT_SIZE, uv_archtype, uv_ate->archtype);
314+
return 1;
315+
}
316+
return 0;
317+
}
318+
319+
/* Determine if UV arch type entry might exist in UVsystab */
320+
static int __init early_get_arch_type(void)
321+
{
322+
unsigned long uvst_physaddr, uvst_size, ptr;
323+
struct uv_systab *st;
324+
u32 rev;
325+
int ret;
326+
327+
uvst_physaddr = get_uv_systab_phys(0);
328+
if (!uvst_physaddr)
329+
return 0;
330+
331+
st = early_memremap_ro(uvst_physaddr, sizeof(struct uv_systab));
332+
if (!st) {
333+
pr_err("UV: Cannot access UVsystab, remap failed\n");
334+
return 0;
335+
}
336+
337+
rev = st->revision;
338+
if (rev < UV_SYSTAB_VERSION_UV5) {
339+
early_memunmap(st, sizeof(struct uv_systab));
340+
return 0;
341+
}
342+
343+
uvst_size = st->size;
344+
early_memunmap(st, sizeof(struct uv_systab));
345+
st = early_memremap_ro(uvst_physaddr, uvst_size);
346+
if (!st) {
347+
pr_err("UV: Cannot access UVarchtype, remap failed\n");
348+
return 0;
349+
}
350+
351+
ptr = early_find_archtype(st);
352+
if (!ptr) {
353+
early_memunmap(st, uvst_size);
354+
return 0;
355+
}
356+
357+
ret = decode_arch_type(ptr);
358+
early_memunmap(st, uvst_size);
359+
return ret;
360+
}
361+
287362
static int __init uv_set_system_type(char *_oem_id)
288363
{
289-
/* Save OEM ID */
364+
/* Save OEM_ID passed from ACPI MADT */
290365
uv_stringify(sizeof(oem_id), oem_id, _oem_id);
291366

292-
/* Set hubless type if true */
293-
if (strncmp(oem_id, "SGI", 3) != 0) {
294-
if (strncmp(oem_id, "NSGI", 4) != 0)
367+
/* Check if BIOS sent us a UVarchtype */
368+
if (!early_get_arch_type())
369+
370+
/* If not use OEM ID for UVarchtype */
371+
uv_stringify(UV_AT_SIZE, uv_archtype, _oem_id);
372+
373+
/* Check if not hubbed */
374+
if (strncmp(uv_archtype, "SGI", 3) != 0) {
375+
376+
/* (Not hubbed), check if not hubless */
377+
if (strncmp(uv_archtype, "NSGI", 4) != 0)
378+
379+
/* (Not hubless), not a UV */
295380
return 0;
296381

297382
/* UV4 Hubless: CH */
298-
if (strncmp(oem_id, "NSGI4", 5) == 0)
383+
if (strncmp(uv_archtype, "NSGI4", 5) == 0)
299384
uv_hubless_system = 0x11;
300385

301386
/* UV3 Hubless: UV300/MC990X w/o hub */
@@ -314,10 +399,10 @@ static int __init uv_set_system_type(char *_oem_id)
314399

315400
/* Set hubbed type if true */
316401
uv_hub_info->hub_revision =
317-
!strncmp(oem_id, "SGI5", 4) ? UV5_HUB_REVISION_BASE :
318-
!strncmp(oem_id, "SGI4", 4) ? UV4_HUB_REVISION_BASE :
319-
!strncmp(oem_id, "SGI3", 4) ? UV3_HUB_REVISION_BASE :
320-
!strcmp(oem_id, "SGI2") ? UV2_HUB_REVISION_BASE : 0;
402+
!strncmp(uv_archtype, "SGI5", 4) ? UV5_HUB_REVISION_BASE :
403+
!strncmp(uv_archtype, "SGI4", 4) ? UV4_HUB_REVISION_BASE :
404+
!strncmp(uv_archtype, "SGI3", 4) ? UV3_HUB_REVISION_BASE :
405+
!strcmp(uv_archtype, "SGI2") ? UV2_HUB_REVISION_BASE : 0;
321406

322407
switch (uv_hub_info->hub_revision) {
323408
case UV5_HUB_REVISION_BASE:
@@ -388,8 +473,7 @@ static int __init uv_acpi_madt_oem_check(char *_oem_id, char *_oem_table_id)
388473
return 0;
389474

390475
badbios:
391-
pr_err("UV: OEM_ID:%s OEM_TABLE_ID:%s\n", oem_id, oem_table_id);
392-
pr_err("UV: Current UV Type or BIOS not supported\n");
476+
pr_err("UV: UVarchtype:%s not supported\n", uv_archtype);
393477
BUG();
394478
}
395479

@@ -1180,6 +1264,7 @@ static void __init decode_gam_rng_tbl(unsigned long ptr)
11801264
pr_info("UV: GRT: %d entries, sockets(min:%x,max:%x) pnodes(min:%x,max:%x)\n", index, _min_socket, _max_socket, _min_pnode, _max_pnode);
11811265
}
11821266

1267+
/* Walk through UVsystab decoding the fields */
11831268
static int __init decode_uv_systab(void)
11841269
{
11851270
struct uv_systab *st;
@@ -1209,7 +1294,8 @@ static int __init decode_uv_systab(void)
12091294
if (!ptr)
12101295
continue;
12111296

1212-
ptr = ptr + (unsigned long)st;
1297+
/* point to payload */
1298+
ptr += (unsigned long)st;
12131299

12141300
switch (st->entry[i].type) {
12151301
case UV_SYSTAB_TYPE_GAM_PARAMS:
@@ -1219,6 +1305,15 @@ static int __init decode_uv_systab(void)
12191305
case UV_SYSTAB_TYPE_GAM_RNG_TBL:
12201306
decode_gam_rng_tbl(ptr);
12211307
break;
1308+
1309+
case UV_SYSTAB_TYPE_ARCH_TYPE:
1310+
/* already processed in early startup */
1311+
break;
1312+
1313+
default:
1314+
pr_err("UV:%s:Unrecognized UV_SYSTAB_TYPE:%d, skipped\n",
1315+
__func__, st->entry[i].type);
1316+
break;
12221317
}
12231318
}
12241319
return 0;
@@ -1259,7 +1354,7 @@ static void __init build_socket_tables(void)
12591354
pr_info("UV: No UVsystab socket table, ignoring\n");
12601355
return;
12611356
}
1262-
pr_crit("UV: Error: UVsystab address translations not available!\n");
1357+
pr_err("UV: Error: UVsystab address translations not available!\n");
12631358
BUG();
12641359
}
12651360

@@ -1385,9 +1480,9 @@ static int __maybe_unused proc_hubless_show(struct seq_file *file, void *data)
13851480
return 0;
13861481
}
13871482

1388-
static int __maybe_unused proc_oemid_show(struct seq_file *file, void *data)
1483+
static int __maybe_unused proc_archtype_show(struct seq_file *file, void *data)
13891484
{
1390-
seq_printf(file, "%s/%s\n", oem_id, oem_table_id);
1485+
seq_printf(file, "%s/%s\n", uv_archtype, oem_table_id);
13911486
return 0;
13921487
}
13931488

@@ -1396,7 +1491,7 @@ static __init void uv_setup_proc_files(int hubless)
13961491
struct proc_dir_entry *pde;
13971492

13981493
pde = proc_mkdir(UV_PROC_NODE, NULL);
1399-
proc_create_single("oemid", 0, pde, proc_oemid_show);
1494+
proc_create_single("archtype", 0, pde, proc_archtype_show);
14001495
if (hubless)
14011496
proc_create_single("hubless", 0, pde, proc_hubless_show);
14021497
else
@@ -1448,12 +1543,14 @@ static void __init uv_system_init_hub(void)
14481543

14491544
map_low_mmrs();
14501545

1451-
/* Get uv_systab for decoding: */
1546+
/* Get uv_systab for decoding, setup UV BIOS calls */
14521547
uv_bios_init();
14531548

14541549
/* If there's an UVsystab problem then abort UV init: */
1455-
if (decode_uv_systab() < 0)
1550+
if (decode_uv_systab() < 0) {
1551+
pr_err("UV: Mangled UVsystab format\n");
14561552
return;
1553+
}
14571554

14581555
build_socket_tables();
14591556
build_uv_gr_table();

arch/x86/platform/uv/bios_uv.c

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
/*
33
* BIOS run time interface routines.
44
*
5-
* Copyright (c) 2008-2009 Silicon Graphics, Inc. All Rights Reserved.
6-
* Copyright (c) Russ Anderson <rja@sgi.com>
5+
* Copyright (C) 2007-2017 Silicon Graphics, Inc. All rights reserved.
6+
* Copyright (c) Russ Anderson <rja@sgi.com>
77
*/
88

99
#include <linux/efi.h>
@@ -170,16 +170,27 @@ int uv_bios_set_legacy_vga_target(bool decode, int domain, int bus)
170170
(u64)decode, (u64)domain, (u64)bus, 0, 0);
171171
}
172172

173-
int uv_bios_init(void)
173+
unsigned long get_uv_systab_phys(bool msg)
174174
{
175-
uv_systab = NULL;
176175
if ((uv_systab_phys == EFI_INVALID_TABLE_ADDR) ||
177176
!uv_systab_phys || efi_runtime_disabled()) {
178-
pr_crit("UV: UVsystab: missing\n");
179-
return -EEXIST;
177+
if (msg)
178+
pr_crit("UV: UVsystab: missing\n");
179+
return 0;
180180
}
181+
return uv_systab_phys;
182+
}
183+
184+
int uv_bios_init(void)
185+
{
186+
unsigned long uv_systab_phys_addr;
187+
188+
uv_systab = NULL;
189+
uv_systab_phys_addr = get_uv_systab_phys(1);
190+
if (!uv_systab_phys_addr)
191+
return -EEXIST;
181192

182-
uv_systab = ioremap(uv_systab_phys, sizeof(struct uv_systab));
193+
uv_systab = ioremap(uv_systab_phys_addr, sizeof(struct uv_systab));
183194
if (!uv_systab || strncmp(uv_systab->signature, UV_SYSTAB_SIG, 4)) {
184195
pr_err("UV: UVsystab: bad signature!\n");
185196
iounmap(uv_systab);
@@ -191,7 +202,7 @@ int uv_bios_init(void)
191202
int size = uv_systab->size;
192203

193204
iounmap(uv_systab);
194-
uv_systab = ioremap(uv_systab_phys, size);
205+
uv_systab = ioremap(uv_systab_phys_addr, size);
195206
if (!uv_systab) {
196207
pr_err("UV: UVsystab: ioremap(%d) failed!\n", size);
197208
return -EFAULT;

0 commit comments

Comments
 (0)