Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 97d21003 authored by mike.travis@hpe.com's avatar mike.travis@hpe.com Committed by Thomas Gleixner
Browse files

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: default avatarMike Travis <mike.travis@hpe.com>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Reviewed-by: default avatarDimitri Sivanich <dimitri.sivanich@hpe.com>
Reviewed-by: default avatarRuss Anderson <russ.anderson@hpe.com>
Reviewed-by: default avatarAndrew 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
parent 6c66350d
Loading
Loading
Loading
Loading
+18 −5
Original line number Original line Diff line number Diff line
@@ -776,9 +776,22 @@ static inline int uv_num_possible_blades(void)
extern void uv_nmi_setup(void);
extern void uv_nmi_setup(void);
extern void uv_nmi_setup_hubless(void);
extern void uv_nmi_setup_hubless(void);


/* BIOS/Kernel flags exchange MMR */
#define UVH_BIOS_KERNEL_MMR		UVH_SCRATCH5
#define UVH_BIOS_KERNEL_MMR_ALIAS	UVH_SCRATCH5_ALIAS
#define UVH_BIOS_KERNEL_MMR_ALIAS_2	UVH_SCRATCH5_ALIAS_2

/* TSC sync valid, set by BIOS */
#define UVH_TSC_SYNC_MMR	UVH_BIOS_KERNEL_MMR
#define UVH_TSC_SYNC_SHIFT	10
#define UVH_TSC_SYNC_SHIFT_UV2K	16	/* UV2/3k have different bits */
#define UVH_TSC_SYNC_MASK	3	/* 0011 */
#define UVH_TSC_SYNC_VALID	3	/* 0011 */
#define UVH_TSC_SYNC_INVALID	2	/* 0010 */

/* BMC sets a bit this MMR non-zero before sending an NMI */
/* BMC sets a bit this MMR non-zero before sending an NMI */
#define UVH_NMI_MMR		UVH_SCRATCH5
#define UVH_NMI_MMR		UVH_BIOS_KERNEL_MMR
#define UVH_NMI_MMR_CLEAR	UVH_SCRATCH5_ALIAS
#define UVH_NMI_MMR_CLEAR	UVH_BIOS_KERNEL_MMR_ALIAS
#define UVH_NMI_MMR_SHIFT	63
#define UVH_NMI_MMR_SHIFT	63
#define UVH_NMI_MMR_TYPE	"SCRATCH5"
#define UVH_NMI_MMR_TYPE	"SCRATCH5"


@@ -792,7 +805,7 @@ extern void uv_nmi_setup_hubless(void);
#define UVH_NMI_MMRX_SUPPORTED	UVH_EXTIO_INT0_BROADCAST
#define UVH_NMI_MMRX_SUPPORTED	UVH_EXTIO_INT0_BROADCAST


/* Indicates to BIOS that we want to use the newer SMM NMI handler */
/* Indicates to BIOS that we want to use the newer SMM NMI handler */
#define UVH_NMI_MMRX_REQ	UVH_SCRATCH5_ALIAS_2
#define UVH_NMI_MMRX_REQ	UVH_BIOS_KERNEL_MMR_ALIAS_2
#define UVH_NMI_MMRX_REQ_SHIFT	62
#define UVH_NMI_MMRX_REQ_SHIFT	62


struct uv_hub_nmi_s {
struct uv_hub_nmi_s {
+43 −0
Original line number Original line Diff line number Diff line
@@ -154,6 +154,48 @@ static int __init early_get_pnodeid(void)
	return pnode;
	return pnode;
}
}


static void uv_tsc_check_sync(void)
{
	u64 mmr;
	int sync_state;
	int mmr_shift;
	char *state;
	bool valid;

	/* Accommodate different UV arch BIOSes */
	mmr = uv_early_read_mmr(UVH_TSC_SYNC_MMR);
	mmr_shift =
		is_uv1_hub() ? 0 :
		is_uv2_hub() ? UVH_TSC_SYNC_SHIFT_UV2K : UVH_TSC_SYNC_SHIFT;
	if (mmr_shift)
		sync_state = (mmr >> mmr_shift) & UVH_TSC_SYNC_MASK;
	else
		sync_state = 0;

	switch (sync_state) {
	case UVH_TSC_SYNC_VALID:
		state = "in sync";
		valid = true;
		break;

	case UVH_TSC_SYNC_INVALID:
		state = "unstable";
		valid = false;
		break;
	default:
		state = "unknown: assuming valid";
		valid = true;
		break;
	}
	pr_info("UV: TSC sync state from BIOS:0%d(%s)\n", sync_state, state);

	/* Mark flag that says TSC != 0 is valid for socket 0 */
	if (valid)
		mark_tsc_async_resets("UV BIOS");
	else
		mark_tsc_unstable("UV BIOS");
}

/* [Copied from arch/x86/kernel/cpu/topology.c:detect_extended_topology()] */
/* [Copied from arch/x86/kernel/cpu/topology.c:detect_extended_topology()] */


#define SMT_LEVEL			0	/* Leaf 0xb SMT level */
#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)
	}
	}


	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);
	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);
	uv_tsc_check_sync();


	return uv_apic;
	return uv_apic;