Merge tag 'x86-urgent-2020-11-08' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 8 Nov 2020 18:09:36 +0000 (10:09 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 8 Nov 2020 18:09:36 +0000 (10:09 -0800)
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

arch/x86/kernel/apic/x2apic_uv_x.c
arch/x86/kernel/cpu/bugs.c
arch/x86/lib/memcpy_64.S
arch/x86/lib/memmove_64.S
arch/x86/lib/memset_64.S

index 714233c..3115caa 100644 (file)
@@ -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 */
index d3f0db4..581fb72 100644 (file)
@@ -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;
 }
 
index 037faac..1e299ac 100644 (file)
@@ -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
 
index 7ff00ea..41902fe 100644 (file)
@@ -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
index 9ff15ee..0bfd26e 100644 (file)
@@ -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