aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Travis <travis@sgi.com>2016-04-29 17:54:18 -0400
committerIngo Molnar <mingo@kernel.org>2016-05-04 02:48:50 -0400
commitef93bf803999445985acb25f4ed8772e1aa81221 (patch)
tree15b47854d6b4c726ef616d0e38ec3bdd8b157561
parent405422d88c686e88b4241c0201fd96b61ab8bd77 (diff)
x86/platform/UV: Add obtaining GAM Range Table from UV BIOS
UV4 uses a GAM (globally addressed memory) architecture that supports variable sized memory per node. This replaces the old "M" value (number of address bits per node) with a range table for conversions between addresses and physical node (pnode) id's. This table is obtained from UV BIOS via the EFI UVsystab table. Support for older EFI UVsystab tables is maintained. Tested-by: Dimitri Sivanich <sivanich@sgi.com> Tested-by: John Estabrook <estabrook@sgi.com> Tested-by: Gary Kroening <gfk@sgi.com> Tested-by: Nathan Zimmer <nzimmer@sgi.com> Signed-off-by: Mike Travis <travis@sgi.com> Cc: Andrew Banman <abanman@sgi.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Andy Lutomirski <luto@amacapital.net> Cc: Borislav Petkov <bp@alien8.de> Cc: Brian Gerst <brgerst@gmail.com> Cc: Denys Vlasenko <dvlasenk@redhat.com> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Len Brown <len.brown@intel.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Russ Anderson <rja@sgi.com> Cc: Thomas Gleixner <tglx@linutronix.de> Link: http://lkml.kernel.org/r/20160429215405.329827545@asylum.americas.sgi.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--arch/x86/include/asm/uv/bios.h59
-rw-r--r--arch/x86/platform/uv/bios_uv.c48
-rw-r--r--arch/x86/platform/uv/uv_sysfs.c2
3 files changed, 81 insertions, 28 deletions
diff --git a/arch/x86/include/asm/uv/bios.h b/arch/x86/include/asm/uv/bios.h
index 71605c7d5c5c..c852590254d5 100644
--- a/arch/x86/include/asm/uv/bios.h
+++ b/arch/x86/include/asm/uv/bios.h
@@ -51,15 +51,66 @@ enum {
51 BIOS_STATUS_UNAVAIL = -EBUSY 51 BIOS_STATUS_UNAVAIL = -EBUSY
52}; 52};
53 53
54/* Address map parameters */
55struct uv_gam_parameters {
56 u64 mmr_base;
57 u64 gru_base;
58 u8 mmr_shift; /* Convert PNode to MMR space offset */
59 u8 gru_shift; /* Convert PNode to GRU space offset */
60 u8 gpa_shift; /* Size of offset field in GRU phys addr */
61 u8 unused1;
62};
63
64/* UV_TABLE_GAM_RANGE_ENTRY values */
65#define UV_GAM_RANGE_TYPE_UNUSED 0 /* End of table */
66#define UV_GAM_RANGE_TYPE_RAM 1 /* Normal RAM */
67#define UV_GAM_RANGE_TYPE_NVRAM 2 /* Non-volatile memory */
68#define UV_GAM_RANGE_TYPE_NV_WINDOW 3 /* NVMDIMM block window */
69#define UV_GAM_RANGE_TYPE_NV_MAILBOX 4 /* NVMDIMM mailbox */
70#define UV_GAM_RANGE_TYPE_HOLE 5 /* Unused address range */
71#define UV_GAM_RANGE_TYPE_MAX 6
72
73/* The structure stores PA bits 56:26, for 64MB granularity */
74#define UV_GAM_RANGE_SHFT 26 /* 64MB */
75
76struct uv_gam_range_entry {
77 char type; /* Entry type: GAM_RANGE_TYPE_UNUSED, etc. */
78 char unused1;
79 u16 nasid; /* HNasid */
80 u16 sockid; /* Socket ID, high bits of APIC ID */
81 u16 pnode; /* Index to MMR and GRU spaces */
82 u32 pxm; /* ACPI proximity domain number */
83 u32 limit; /* PA bits 56:26 (UV_GAM_RANGE_SHFT) */
84};
85
86#define UV_SYSTAB_SIG "UVST"
87#define UV_SYSTAB_VERSION_1 1 /* UV1/2/3 BIOS version */
88#define UV_SYSTAB_VERSION_UV4 0x400 /* UV4 BIOS base version */
89#define UV_SYSTAB_VERSION_UV4_1 0x401 /* + gpa_shift */
90#define UV_SYSTAB_VERSION_UV4_2 0x402 /* + TYPE_NVRAM/WINDOW/MBOX */
91#define UV_SYSTAB_VERSION_UV4_LATEST UV_SYSTAB_VERSION_UV4_2
92
93#define UV_SYSTAB_TYPE_UNUSED 0 /* End of table (offset == 0) */
94#define UV_SYSTAB_TYPE_GAM_PARAMS 1 /* GAM PARAM conversions */
95#define UV_SYSTAB_TYPE_GAM_RNG_TBL 2 /* GAM entry table */
96#define UV_SYSTAB_TYPE_MAX 3
97
54/* 98/*
55 * The UV system table describes specific firmware 99 * The UV system table describes specific firmware
56 * capabilities available to the Linux kernel at runtime. 100 * capabilities available to the Linux kernel at runtime.
57 */ 101 */
58struct uv_systab { 102struct uv_systab {
59 char signature[4]; /* must be "UVST" */ 103 char signature[4]; /* must be UV_SYSTAB_SIG */
60 u32 revision; /* distinguish different firmware revs */ 104 u32 revision; /* distinguish different firmware revs */
61 u64 function; /* BIOS runtime callback function ptr */ 105 u64 function; /* BIOS runtime callback function ptr */
106 u32 size; /* systab size (starting with _VERSION_UV4) */
107 struct {
108 u32 type:8; /* type of entry */
109 u32 offset:24; /* byte offset from struct start to entry */
110 } entry[1]; /* additional entries follow */
62}; 111};
112extern struct uv_systab *uv_systab;
113/* (... end of definitions from UV BIOS ...) */
63 114
64enum { 115enum {
65 BIOS_FREQ_BASE_PLATFORM = 0, 116 BIOS_FREQ_BASE_PLATFORM = 0,
@@ -99,7 +150,11 @@ extern s64 uv_bios_change_memprotect(u64, u64, enum uv_memprotect);
99extern s64 uv_bios_reserved_page_pa(u64, u64 *, u64 *, u64 *); 150extern s64 uv_bios_reserved_page_pa(u64, u64 *, u64 *, u64 *);
100extern int uv_bios_set_legacy_vga_target(bool decode, int domain, int bus); 151extern int uv_bios_set_legacy_vga_target(bool decode, int domain, int bus);
101 152
153#ifdef CONFIG_EFI
102extern void uv_bios_init(void); 154extern void uv_bios_init(void);
155#else
156void uv_bios_init(void) { }
157#endif
103 158
104extern unsigned long sn_rtc_cycles_per_second; 159extern unsigned long sn_rtc_cycles_per_second;
105extern int uv_type; 160extern int uv_type;
@@ -107,7 +162,7 @@ extern long sn_partition_id;
107extern long sn_coherency_id; 162extern long sn_coherency_id;
108extern long sn_region_size; 163extern long sn_region_size;
109extern long system_serial_number; 164extern long system_serial_number;
110#define partition_coherence_id() (sn_coherency_id) 165#define uv_partition_coherence_id() (sn_coherency_id)
111 166
112extern struct kobject *sgi_uv_kobj; /* /sys/firmware/sgi_uv */ 167extern struct kobject *sgi_uv_kobj; /* /sys/firmware/sgi_uv */
113 168
diff --git a/arch/x86/platform/uv/bios_uv.c b/arch/x86/platform/uv/bios_uv.c
index 1584cbed0dce..815fec6e05e2 100644
--- a/arch/x86/platform/uv/bios_uv.c
+++ b/arch/x86/platform/uv/bios_uv.c
@@ -21,19 +21,20 @@
21 21
22#include <linux/efi.h> 22#include <linux/efi.h>
23#include <linux/export.h> 23#include <linux/export.h>
24#include <linux/slab.h>
24#include <asm/efi.h> 25#include <asm/efi.h>
25#include <linux/io.h> 26#include <linux/io.h>
26#include <asm/uv/bios.h> 27#include <asm/uv/bios.h>
27#include <asm/uv/uv_hub.h> 28#include <asm/uv/uv_hub.h>
28 29
29static struct uv_systab uv_systab; 30struct uv_systab *uv_systab;
30 31
31s64 uv_bios_call(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3, u64 a4, u64 a5) 32s64 uv_bios_call(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3, u64 a4, u64 a5)
32{ 33{
33 struct uv_systab *tab = &uv_systab; 34 struct uv_systab *tab = uv_systab;
34 s64 ret; 35 s64 ret;
35 36
36 if (!tab->function) 37 if (!tab || !tab->function)
37 /* 38 /*
38 * BIOS does not support UV systab 39 * BIOS does not support UV systab
39 */ 40 */
@@ -183,34 +184,31 @@ int uv_bios_set_legacy_vga_target(bool decode, int domain, int bus)
183} 184}
184EXPORT_SYMBOL_GPL(uv_bios_set_legacy_vga_target); 185EXPORT_SYMBOL_GPL(uv_bios_set_legacy_vga_target);
185 186
186
187#ifdef CONFIG_EFI 187#ifdef CONFIG_EFI
188void uv_bios_init(void) 188void uv_bios_init(void)
189{ 189{
190 struct uv_systab *tab; 190 uv_systab = NULL;
191 191 if ((efi.uv_systab == EFI_INVALID_TABLE_ADDR) || !efi.uv_systab) {
192 if ((efi.uv_systab == EFI_INVALID_TABLE_ADDR) || 192 pr_crit("UV: UVsystab: missing\n");
193 (efi.uv_systab == (unsigned long)NULL)) {
194 printk(KERN_CRIT "No EFI UV System Table.\n");
195 uv_systab.function = (unsigned long)NULL;
196 return; 193 return;
197 } 194 }
198 195
199 tab = (struct uv_systab *)ioremap(efi.uv_systab, 196 uv_systab = ioremap(efi.uv_systab, sizeof(struct uv_systab));
200 sizeof(struct uv_systab)); 197 if (!uv_systab || strncmp(uv_systab->signature, UV_SYSTAB_SIG, 4)) {
201 if (strncmp(tab->signature, "UVST", 4) != 0) 198 pr_err("UV: UVsystab: bad signature!\n");
202 printk(KERN_ERR "bad signature in UV system table!"); 199 iounmap(uv_systab);
203 200 return;
204 /* 201 }
205 * Copy table to permanent spot for later use.
206 */
207 memcpy(&uv_systab, tab, sizeof(struct uv_systab));
208 iounmap(tab);
209 202
210 printk(KERN_INFO "EFI UV System Table Revision %d\n", 203 if (uv_systab->revision >= UV_SYSTAB_VERSION_UV4) {
211 uv_systab.revision); 204 iounmap(uv_systab);
205 uv_systab = ioremap(efi.uv_systab, uv_systab->size);
206 if (!uv_systab) {
207 pr_err("UV: UVsystab: ioremap(%d) failed!\n",
208 uv_systab->size);
209 return;
210 }
211 }
212 pr_info("UV: UVsystab: Revision:%x\n", uv_systab->revision);
212} 213}
213#else /* !CONFIG_EFI */
214
215void uv_bios_init(void) { }
216#endif 214#endif
diff --git a/arch/x86/platform/uv/uv_sysfs.c b/arch/x86/platform/uv/uv_sysfs.c
index 5d4ba301e776..e9da9ebd924a 100644
--- a/arch/x86/platform/uv/uv_sysfs.c
+++ b/arch/x86/platform/uv/uv_sysfs.c
@@ -34,7 +34,7 @@ static ssize_t partition_id_show(struct kobject *kobj,
34static ssize_t coherence_id_show(struct kobject *kobj, 34static ssize_t coherence_id_show(struct kobject *kobj,
35 struct kobj_attribute *attr, char *buf) 35 struct kobj_attribute *attr, char *buf)
36{ 36{
37 return snprintf(buf, PAGE_SIZE, "%ld\n", partition_coherence_id()); 37 return snprintf(buf, PAGE_SIZE, "%ld\n", uv_partition_coherence_id());
38} 38}
39 39
40static struct kobj_attribute partition_id_attr = 40static struct kobj_attribute partition_id_attr =