aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormike.travis@hpe.com <mike.travis@hpe.com>2017-10-12 12:32:06 -0400
committerThomas Gleixner <tglx@linutronix.de>2017-10-16 16:50:37 -0400
commit97d21003df3e7504c899b1701546f18ff475966f (patch)
tree1bd10a532ea407916df6a73033a686451c6e2b81
parent6c66350d0a482892793b888b07c1177fc6d4b344 (diff)
x86/platform/UV: Add check of TSC state set by UV BIOS
Insert a check early in UV system startup that checks whether BIOS was able to obtain satisfactory TSC Sync stability. If not, it usually is caused by an error in the external TSC clock generation source. In this case the best fallback is to use the builtin hardware RTC as the kernel will not be able to set an accurate TSC sync either. Signed-off-by: Mike Travis <mike.travis@hpe.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Reviewed-by: Dimitri Sivanich <dimitri.sivanich@hpe.com> Reviewed-by: Russ Anderson <russ.anderson@hpe.com> Reviewed-by: Andrew Banman <andrew.abanman@hpe.com> Cc: Prarit Bhargava <prarit@redhat.com> Cc: Andrew Banman <andrew.banman@hpe.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Bin Gao <bin.gao@linux.intel.com> Link: https://lkml.kernel.org/r/20171012163202.406294490@stormcage.americas.sgi.com
-rw-r--r--arch/x86/include/asm/uv/uv_hub.h23
-rw-r--r--arch/x86/kernel/apic/x2apic_uv_x.c43
2 files changed, 61 insertions, 5 deletions
diff --git a/arch/x86/include/asm/uv/uv_hub.h b/arch/x86/include/asm/uv/uv_hub.h
index 9cffb44a3cf5..036e26d63d9a 100644
--- a/arch/x86/include/asm/uv/uv_hub.h
+++ b/arch/x86/include/asm/uv/uv_hub.h
@@ -776,23 +776,36 @@ static inline int uv_num_possible_blades(void)
776extern void uv_nmi_setup(void); 776extern void uv_nmi_setup(void);
777extern void uv_nmi_setup_hubless(void); 777extern void uv_nmi_setup_hubless(void);
778 778
779/* BIOS/Kernel flags exchange MMR */
780#define UVH_BIOS_KERNEL_MMR UVH_SCRATCH5
781#define UVH_BIOS_KERNEL_MMR_ALIAS UVH_SCRATCH5_ALIAS
782#define UVH_BIOS_KERNEL_MMR_ALIAS_2 UVH_SCRATCH5_ALIAS_2
783
784/* TSC sync valid, set by BIOS */
785#define UVH_TSC_SYNC_MMR UVH_BIOS_KERNEL_MMR
786#define UVH_TSC_SYNC_SHIFT 10
787#define UVH_TSC_SYNC_SHIFT_UV2K 16 /* UV2/3k have different bits */
788#define UVH_TSC_SYNC_MASK 3 /* 0011 */
789#define UVH_TSC_SYNC_VALID 3 /* 0011 */
790#define UVH_TSC_SYNC_INVALID 2 /* 0010 */
791
779/* BMC sets a bit this MMR non-zero before sending an NMI */ 792/* BMC sets a bit this MMR non-zero before sending an NMI */
780#define UVH_NMI_MMR UVH_SCRATCH5 793#define UVH_NMI_MMR UVH_BIOS_KERNEL_MMR
781#define UVH_NMI_MMR_CLEAR UVH_SCRATCH5_ALIAS 794#define UVH_NMI_MMR_CLEAR UVH_BIOS_KERNEL_MMR_ALIAS
782#define UVH_NMI_MMR_SHIFT 63 795#define UVH_NMI_MMR_SHIFT 63
783#define UVH_NMI_MMR_TYPE "SCRATCH5" 796#define UVH_NMI_MMR_TYPE "SCRATCH5"
784 797
785/* Newer SMM NMI handler, not present in all systems */ 798/* Newer SMM NMI handler, not present in all systems */
786#define UVH_NMI_MMRX UVH_EVENT_OCCURRED0 799#define UVH_NMI_MMRX UVH_EVENT_OCCURRED0
787#define UVH_NMI_MMRX_CLEAR UVH_EVENT_OCCURRED0_ALIAS 800#define UVH_NMI_MMRX_CLEAR UVH_EVENT_OCCURRED0_ALIAS
788#define UVH_NMI_MMRX_SHIFT UVH_EVENT_OCCURRED0_EXTIO_INT0_SHFT 801#define UVH_NMI_MMRX_SHIFT UVH_EVENT_OCCURRED0_EXTIO_INT0_SHFT
789#define UVH_NMI_MMRX_TYPE "EXTIO_INT0" 802#define UVH_NMI_MMRX_TYPE "EXTIO_INT0"
790 803
791/* Non-zero indicates newer SMM NMI handler present */ 804/* Non-zero indicates newer SMM NMI handler present */
792#define UVH_NMI_MMRX_SUPPORTED UVH_EXTIO_INT0_BROADCAST 805#define UVH_NMI_MMRX_SUPPORTED UVH_EXTIO_INT0_BROADCAST
793 806
794/* Indicates to BIOS that we want to use the newer SMM NMI handler */ 807/* Indicates to BIOS that we want to use the newer SMM NMI handler */
795#define UVH_NMI_MMRX_REQ UVH_SCRATCH5_ALIAS_2 808#define UVH_NMI_MMRX_REQ UVH_BIOS_KERNEL_MMR_ALIAS_2
796#define UVH_NMI_MMRX_REQ_SHIFT 62 809#define UVH_NMI_MMRX_REQ_SHIFT 62
797 810
798struct uv_hub_nmi_s { 811struct uv_hub_nmi_s {
diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c
index 0d57bb9079c9..440825478bbd 100644
--- a/arch/x86/kernel/apic/x2apic_uv_x.c
+++ b/arch/x86/kernel/apic/x2apic_uv_x.c
@@ -154,6 +154,48 @@ static int __init early_get_pnodeid(void)
154 return pnode; 154 return pnode;
155} 155}
156 156
157static void uv_tsc_check_sync(void)
158{
159 u64 mmr;
160 int sync_state;
161 int mmr_shift;
162 char *state;
163 bool valid;
164
165 /* Accommodate different UV arch BIOSes */
166 mmr = uv_early_read_mmr(UVH_TSC_SYNC_MMR);
167 mmr_shift =
168 is_uv1_hub() ? 0 :
169 is_uv2_hub() ? UVH_TSC_SYNC_SHIFT_UV2K : UVH_TSC_SYNC_SHIFT;
170 if (mmr_shift)
171 sync_state = (mmr >> mmr_shift) & UVH_TSC_SYNC_MASK;
172 else
173 sync_state = 0;
174
175 switch (sync_state) {
176 case UVH_TSC_SYNC_VALID:
177 state = "in sync";
178 valid = true;
179 break;
180
181 case UVH_TSC_SYNC_INVALID:
182 state = "unstable";
183 valid = false;
184 break;
185 default:
186 state = "unknown: assuming valid";
187 valid = true;
188 break;
189 }
190 pr_info("UV: TSC sync state from BIOS:0%d(%s)\n", sync_state, state);
191
192 /* Mark flag that says TSC != 0 is valid for socket 0 */
193 if (valid)
194 mark_tsc_async_resets("UV BIOS");
195 else
196 mark_tsc_unstable("UV BIOS");
197}
198
157/* [Copied from arch/x86/kernel/cpu/topology.c:detect_extended_topology()] */ 199/* [Copied from arch/x86/kernel/cpu/topology.c:detect_extended_topology()] */
158 200
159#define SMT_LEVEL 0 /* Leaf 0xb SMT level */ 201#define SMT_LEVEL 0 /* Leaf 0xb SMT level */
@@ -288,6 +330,7 @@ static int __init uv_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
288 } 330 }
289 331
290 pr_info("UV: OEM IDs %s/%s, System/HUB Types %d/%d, uv_apic %d\n", oem_id, oem_table_id, uv_system_type, uv_min_hub_revision_id, uv_apic); 332 pr_info("UV: OEM IDs %s/%s, System/HUB Types %d/%d, uv_apic %d\n", oem_id, oem_table_id, uv_system_type, uv_min_hub_revision_id, uv_apic);
333 uv_tsc_check_sync();
291 334
292 return uv_apic; 335 return uv_apic;
293 336