Commit 40be821d authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'x86-urgent-2020-11-08' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86 fixes from Thomas Gleixner:
 "A set of x86 fixes:

   - Use SYM_FUNC_START_WEAK in the mem* ASM functions instead of a
     combination of .weak and SYM_FUNC_START_LOCAL which makes LLVMs
     integrated assembler upset

   - Correct the mitigation selection logic which prevented the related
     prctl to work correctly

   - Make the UV5 hubless system work correctly by fixing up the
     malformed table entries and adding the missing ones"

* tag 'x86-urgent-2020-11-08' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86/platform/uv: Recognize UV5 hubless system identifier
  x86/platform/uv: Remove spaces from OEM IDs
  x86/platform/uv: Fix missing OEM_TABLE_ID
  x86/speculation: Allow IBPB to be conditionally enabled on CPUs with always-on STIBP
  x86/lib: Change .weak to SYM_FUNC_START_WEAK for arch/x86/lib/mem*_64.S
parents 100e3891 801284f9
Loading
Loading
Loading
Loading
+18 −5
Original line number Diff line number Diff line
@@ -290,6 +290,9 @@ static void __init uv_stringify(int len, char *to, char *from)
{
	/* Relies on 'to' being NULL chars so result will be NULL terminated */
	strncpy(to, from, len-1);

	/* Trim trailing spaces */
	(void)strim(to);
}

/* Find UV arch type entry in UVsystab */
@@ -366,7 +369,7 @@ static int __init early_get_arch_type(void)
	return ret;
}

static int __init uv_set_system_type(char *_oem_id)
static int __init uv_set_system_type(char *_oem_id, char *_oem_table_id)
{
	/* Save OEM_ID passed from ACPI MADT */
	uv_stringify(sizeof(oem_id), oem_id, _oem_id);
@@ -386,13 +389,23 @@ static int __init uv_set_system_type(char *_oem_id)
			/* (Not hubless), not a UV */
			return 0;

		/* Is UV hubless system */
		uv_hubless_system = 0x01;

		/* UV5 Hubless */
		if (strncmp(uv_archtype, "NSGI5", 5) == 0)
			uv_hubless_system |= 0x20;

		/* UV4 Hubless: CH */
		if (strncmp(uv_archtype, "NSGI4", 5) == 0)
			uv_hubless_system = 0x11;
		else if (strncmp(uv_archtype, "NSGI4", 5) == 0)
			uv_hubless_system |= 0x10;

		/* UV3 Hubless: UV300/MC990X w/o hub */
		else
			uv_hubless_system = 0x9;
			uv_hubless_system |= 0x8;

		/* Copy APIC type */
		uv_stringify(sizeof(oem_table_id), oem_table_id, _oem_table_id);

		pr_info("UV: OEM IDs %s/%s, SystemType %d, HUBLESS ID %x\n",
			oem_id, oem_table_id, uv_system_type, uv_hubless_system);
@@ -456,7 +469,7 @@ static int __init uv_acpi_madt_oem_check(char *_oem_id, char *_oem_table_id)
	uv_cpu_info->p_uv_hub_info = &uv_hub_info_node0;

	/* If not UV, return. */
	if (likely(uv_set_system_type(_oem_id) == 0))
	if (uv_set_system_type(_oem_id, _oem_table_id) == 0)
		return 0;

	/* Save and Decode OEM Table ID */
+33 −18
Original line number Diff line number Diff line
@@ -1254,6 +1254,14 @@ static int ssb_prctl_set(struct task_struct *task, unsigned long ctrl)
	return 0;
}

static bool is_spec_ib_user_controlled(void)
{
	return spectre_v2_user_ibpb == SPECTRE_V2_USER_PRCTL ||
		spectre_v2_user_ibpb == SPECTRE_V2_USER_SECCOMP ||
		spectre_v2_user_stibp == SPECTRE_V2_USER_PRCTL ||
		spectre_v2_user_stibp == SPECTRE_V2_USER_SECCOMP;
}

static int ib_prctl_set(struct task_struct *task, unsigned long ctrl)
{
	switch (ctrl) {
@@ -1261,16 +1269,26 @@ static int ib_prctl_set(struct task_struct *task, unsigned long ctrl)
		if (spectre_v2_user_ibpb == SPECTRE_V2_USER_NONE &&
		    spectre_v2_user_stibp == SPECTRE_V2_USER_NONE)
			return 0;

		/*
		 * Indirect branch speculation is always disabled in strict
		 * mode. It can neither be enabled if it was force-disabled
		 * by a  previous prctl call.
		 * With strict mode for both IBPB and STIBP, the instruction
		 * code paths avoid checking this task flag and instead,
		 * unconditionally run the instruction. However, STIBP and IBPB
		 * are independent and either can be set to conditionally
		 * enabled regardless of the mode of the other.
		 *
		 * If either is set to conditional, allow the task flag to be
		 * updated, unless it was force-disabled by a previous prctl
		 * call. Currently, this is possible on an AMD CPU which has the
		 * feature X86_FEATURE_AMD_STIBP_ALWAYS_ON. In this case, if the
		 * kernel is booted with 'spectre_v2_user=seccomp', then
		 * spectre_v2_user_ibpb == SPECTRE_V2_USER_SECCOMP and
		 * spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT_PREFERRED.
		 */
		if (spectre_v2_user_ibpb == SPECTRE_V2_USER_STRICT ||
		    spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT ||
		    spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT_PREFERRED ||
		if (!is_spec_ib_user_controlled() ||
		    task_spec_ib_force_disable(task))
			return -EPERM;

		task_clear_spec_ib_disable(task);
		task_update_spec_tif(task);
		break;
@@ -1283,10 +1301,10 @@ static int ib_prctl_set(struct task_struct *task, unsigned long ctrl)
		if (spectre_v2_user_ibpb == SPECTRE_V2_USER_NONE &&
		    spectre_v2_user_stibp == SPECTRE_V2_USER_NONE)
			return -EPERM;
		if (spectre_v2_user_ibpb == SPECTRE_V2_USER_STRICT ||
		    spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT ||
		    spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT_PREFERRED)

		if (!is_spec_ib_user_controlled())
			return 0;

		task_set_spec_ib_disable(task);
		if (ctrl == PR_SPEC_FORCE_DISABLE)
			task_set_spec_ib_force_disable(task);
@@ -1351,20 +1369,17 @@ static int ib_prctl_get(struct task_struct *task)
	if (spectre_v2_user_ibpb == SPECTRE_V2_USER_NONE &&
	    spectre_v2_user_stibp == SPECTRE_V2_USER_NONE)
		return PR_SPEC_ENABLE;
	else if (spectre_v2_user_ibpb == SPECTRE_V2_USER_STRICT ||
	    spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT ||
	    spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT_PREFERRED)
		return PR_SPEC_DISABLE;
	else if (spectre_v2_user_ibpb == SPECTRE_V2_USER_PRCTL ||
	    spectre_v2_user_ibpb == SPECTRE_V2_USER_SECCOMP ||
	    spectre_v2_user_stibp == SPECTRE_V2_USER_PRCTL ||
	    spectre_v2_user_stibp == SPECTRE_V2_USER_SECCOMP) {
	else if (is_spec_ib_user_controlled()) {
		if (task_spec_ib_force_disable(task))
			return PR_SPEC_PRCTL | PR_SPEC_FORCE_DISABLE;
		if (task_spec_ib_disable(task))
			return PR_SPEC_PRCTL | PR_SPEC_DISABLE;
		return PR_SPEC_PRCTL | PR_SPEC_ENABLE;
	} else
	} else if (spectre_v2_user_ibpb == SPECTRE_V2_USER_STRICT ||
	    spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT ||
	    spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT_PREFERRED)
		return PR_SPEC_DISABLE;
	else
		return PR_SPEC_NOT_AFFECTED;
}

+1 −3
Original line number Diff line number Diff line
@@ -16,8 +16,6 @@
 * to a jmp to memcpy_erms which does the REP; MOVSB mem copy.
 */

.weak memcpy

/*
 * memcpy - Copy a memory block.
 *
@@ -30,7 +28,7 @@
 * rax original destination
 */
SYM_FUNC_START_ALIAS(__memcpy)
SYM_FUNC_START_LOCAL(memcpy)
SYM_FUNC_START_WEAK(memcpy)
	ALTERNATIVE_2 "jmp memcpy_orig", "", X86_FEATURE_REP_GOOD, \
		      "jmp memcpy_erms", X86_FEATURE_ERMS

+1 −3
Original line number Diff line number Diff line
@@ -24,9 +24,7 @@
 * Output:
 * rax: dest
 */
.weak memmove

SYM_FUNC_START_ALIAS(memmove)
SYM_FUNC_START_WEAK(memmove)
SYM_FUNC_START(__memmove)

	mov %rdi, %rax
+1 −3
Original line number Diff line number Diff line
@@ -6,8 +6,6 @@
#include <asm/alternative-asm.h>
#include <asm/export.h>

.weak memset

/*
 * ISO C memset - set a memory block to a byte value. This function uses fast
 * string to get better performance than the original function. The code is
@@ -19,7 +17,7 @@
 *
 * rax   original destination
 */
SYM_FUNC_START_ALIAS(memset)
SYM_FUNC_START_WEAK(memset)
SYM_FUNC_START(__memset)
	/*
	 * Some CPUs support enhanced REP MOVSB/STOSB feature. It is recommended