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

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
...@@ -290,6 +290,9 @@ static void __init uv_stringify(int len, char *to, char *from) ...@@ -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 */ /* Relies on 'to' being NULL chars so result will be NULL terminated */
strncpy(to, from, len-1); strncpy(to, from, len-1);
/* Trim trailing spaces */
(void)strim(to);
} }
/* Find UV arch type entry in UVsystab */ /* Find UV arch type entry in UVsystab */
...@@ -366,7 +369,7 @@ static int __init early_get_arch_type(void) ...@@ -366,7 +369,7 @@ static int __init early_get_arch_type(void)
return ret; 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 */ /* Save OEM_ID passed from ACPI MADT */
uv_stringify(sizeof(oem_id), oem_id, _oem_id); uv_stringify(sizeof(oem_id), oem_id, _oem_id);
...@@ -386,13 +389,23 @@ static int __init uv_set_system_type(char *_oem_id) ...@@ -386,13 +389,23 @@ static int __init uv_set_system_type(char *_oem_id)
/* (Not hubless), not a UV */ /* (Not hubless), not a UV */
return 0; 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 */ /* UV4 Hubless: CH */
if (strncmp(uv_archtype, "NSGI4", 5) == 0) else if (strncmp(uv_archtype, "NSGI4", 5) == 0)
uv_hubless_system = 0x11; uv_hubless_system |= 0x10;
/* UV3 Hubless: UV300/MC990X w/o hub */ /* UV3 Hubless: UV300/MC990X w/o hub */
else 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", pr_info("UV: OEM IDs %s/%s, SystemType %d, HUBLESS ID %x\n",
oem_id, oem_table_id, uv_system_type, uv_hubless_system); 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) ...@@ -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; uv_cpu_info->p_uv_hub_info = &uv_hub_info_node0;
/* If not UV, return. */ /* 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; return 0;
/* Save and Decode OEM Table ID */ /* Save and Decode OEM Table ID */
......
...@@ -1254,6 +1254,14 @@ static int ssb_prctl_set(struct task_struct *task, unsigned long ctrl) ...@@ -1254,6 +1254,14 @@ static int ssb_prctl_set(struct task_struct *task, unsigned long ctrl)
return 0; 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) static int ib_prctl_set(struct task_struct *task, unsigned long ctrl)
{ {
switch (ctrl) { switch (ctrl) {
...@@ -1261,16 +1269,26 @@ static int ib_prctl_set(struct task_struct *task, unsigned long 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 && if (spectre_v2_user_ibpb == SPECTRE_V2_USER_NONE &&
spectre_v2_user_stibp == SPECTRE_V2_USER_NONE) spectre_v2_user_stibp == SPECTRE_V2_USER_NONE)
return 0; return 0;
/* /*
* Indirect branch speculation is always disabled in strict * With strict mode for both IBPB and STIBP, the instruction
* mode. It can neither be enabled if it was force-disabled * code paths avoid checking this task flag and instead,
* by a previous prctl call. * 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 || if (!is_spec_ib_user_controlled() ||
spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT ||
spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT_PREFERRED ||
task_spec_ib_force_disable(task)) task_spec_ib_force_disable(task))
return -EPERM; return -EPERM;
task_clear_spec_ib_disable(task); task_clear_spec_ib_disable(task);
task_update_spec_tif(task); task_update_spec_tif(task);
break; break;
...@@ -1283,10 +1301,10 @@ static int ib_prctl_set(struct task_struct *task, unsigned long ctrl) ...@@ -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 && if (spectre_v2_user_ibpb == SPECTRE_V2_USER_NONE &&
spectre_v2_user_stibp == SPECTRE_V2_USER_NONE) spectre_v2_user_stibp == SPECTRE_V2_USER_NONE)
return -EPERM; return -EPERM;
if (spectre_v2_user_ibpb == SPECTRE_V2_USER_STRICT ||
spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT || if (!is_spec_ib_user_controlled())
spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT_PREFERRED)
return 0; return 0;
task_set_spec_ib_disable(task); task_set_spec_ib_disable(task);
if (ctrl == PR_SPEC_FORCE_DISABLE) if (ctrl == PR_SPEC_FORCE_DISABLE)
task_set_spec_ib_force_disable(task); task_set_spec_ib_force_disable(task);
...@@ -1351,20 +1369,17 @@ static int ib_prctl_get(struct task_struct *task) ...@@ -1351,20 +1369,17 @@ static int ib_prctl_get(struct task_struct *task)
if (spectre_v2_user_ibpb == SPECTRE_V2_USER_NONE && if (spectre_v2_user_ibpb == SPECTRE_V2_USER_NONE &&
spectre_v2_user_stibp == SPECTRE_V2_USER_NONE) spectre_v2_user_stibp == SPECTRE_V2_USER_NONE)
return PR_SPEC_ENABLE; return PR_SPEC_ENABLE;
else if (spectre_v2_user_ibpb == SPECTRE_V2_USER_STRICT || else if (is_spec_ib_user_controlled()) {
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) {
if (task_spec_ib_force_disable(task)) if (task_spec_ib_force_disable(task))
return PR_SPEC_PRCTL | PR_SPEC_FORCE_DISABLE; return PR_SPEC_PRCTL | PR_SPEC_FORCE_DISABLE;
if (task_spec_ib_disable(task)) if (task_spec_ib_disable(task))
return PR_SPEC_PRCTL | PR_SPEC_DISABLE; return PR_SPEC_PRCTL | PR_SPEC_DISABLE;
return PR_SPEC_PRCTL | PR_SPEC_ENABLE; 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; return PR_SPEC_NOT_AFFECTED;
} }
......
...@@ -16,8 +16,6 @@ ...@@ -16,8 +16,6 @@
* to a jmp to memcpy_erms which does the REP; MOVSB mem copy. * to a jmp to memcpy_erms which does the REP; MOVSB mem copy.
*/ */
.weak memcpy
/* /*
* memcpy - Copy a memory block. * memcpy - Copy a memory block.
* *
...@@ -30,7 +28,7 @@ ...@@ -30,7 +28,7 @@
* rax original destination * rax original destination
*/ */
SYM_FUNC_START_ALIAS(__memcpy) SYM_FUNC_START_ALIAS(__memcpy)
SYM_FUNC_START_LOCAL(memcpy) SYM_FUNC_START_WEAK(memcpy)
ALTERNATIVE_2 "jmp memcpy_orig", "", X86_FEATURE_REP_GOOD, \ ALTERNATIVE_2 "jmp memcpy_orig", "", X86_FEATURE_REP_GOOD, \
"jmp memcpy_erms", X86_FEATURE_ERMS "jmp memcpy_erms", X86_FEATURE_ERMS
......
...@@ -24,9 +24,7 @@ ...@@ -24,9 +24,7 @@
* Output: * Output:
* rax: dest * rax: dest
*/ */
.weak memmove SYM_FUNC_START_WEAK(memmove)
SYM_FUNC_START_ALIAS(memmove)
SYM_FUNC_START(__memmove) SYM_FUNC_START(__memmove)
mov %rdi, %rax mov %rdi, %rax
......
...@@ -6,8 +6,6 @@ ...@@ -6,8 +6,6 @@
#include <asm/alternative-asm.h> #include <asm/alternative-asm.h>
#include <asm/export.h> #include <asm/export.h>
.weak memset
/* /*
* ISO C memset - set a memory block to a byte value. This function uses fast * 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 * string to get better performance than the original function. The code is
...@@ -19,7 +17,7 @@ ...@@ -19,7 +17,7 @@
* *
* rax original destination * rax original destination
*/ */
SYM_FUNC_START_ALIAS(memset) SYM_FUNC_START_WEAK(memset)
SYM_FUNC_START(__memset) SYM_FUNC_START(__memset)
/* /*
* Some CPUs support enhanced REP MOVSB/STOSB feature. It is recommended * Some CPUs support enhanced REP MOVSB/STOSB feature. It is recommended
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment