Commit 098c7938 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'x86_urgent_for_5.8_rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86 fixes from Borislav Petkov:

 - AMD Memory bandwidth counter width fix, by Babu Moger.

 - Use the proper length type in the 32-bit truncate() syscall variant,
   by Jiri Slaby.

 - Reinit IA32_FEAT_CTL during wakeup to fix the case where after
   resume, VMXON would #GP due to VMX not being properly enabled, by
   Sean Christopherson.

 - Fix a static checker warning in the resctrl code, by Dan Carpenter.

 - Add a CR4 pinning mask for bits which cannot change after boot, by
   Kees Cook.

 - Align the start of the loop of __clear_user() to 16 bytes, to improve
   performance on AMD zen1 and zen2 microarchitectures, by Matt Fleming.

* tag 'x86_urgent_for_5.8_rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86/asm/64: Align start of __clear_user() loop to 16-bytes
  x86/cpu: Use pinning mask for CR4 bits needing to be 0
  x86/resctrl: Fix a NULL vs IS_ERR() static checker warning in rdt_cdp_peer_get()
  x86/cpu: Reinitialize IA32_FEAT_CTL MSR on BSP during wakeup
  syscalls: Fix offset type of ksys_ftruncate()
  x86/resctrl: Fix memory bandwidth counter width for AMD
parents c141b30e bb5570ad
...@@ -58,4 +58,9 @@ static inline bool handle_guest_split_lock(unsigned long ip) ...@@ -58,4 +58,9 @@ static inline bool handle_guest_split_lock(unsigned long ip)
return false; return false;
} }
#endif #endif
#ifdef CONFIG_IA32_FEAT_CTL
void init_ia32_feat_ctl(struct cpuinfo_x86 *c);
#else
static inline void init_ia32_feat_ctl(struct cpuinfo_x86 *c) {}
#endif
#endif /* _ASM_X86_CPU_H */ #endif /* _ASM_X86_CPU_H */
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/sched/clock.h> #include <linux/sched/clock.h>
#include <asm/cpu.h>
#include <asm/cpufeature.h> #include <asm/cpufeature.h>
#include <asm/e820/api.h> #include <asm/e820/api.h>
#include <asm/mtrr.h> #include <asm/mtrr.h>
......
...@@ -347,6 +347,9 @@ static __always_inline void setup_umip(struct cpuinfo_x86 *c) ...@@ -347,6 +347,9 @@ static __always_inline void setup_umip(struct cpuinfo_x86 *c)
cr4_clear_bits(X86_CR4_UMIP); cr4_clear_bits(X86_CR4_UMIP);
} }
/* These bits should not change their value after CPU init is finished. */
static const unsigned long cr4_pinned_mask =
X86_CR4_SMEP | X86_CR4_SMAP | X86_CR4_UMIP | X86_CR4_FSGSBASE;
static DEFINE_STATIC_KEY_FALSE_RO(cr_pinning); static DEFINE_STATIC_KEY_FALSE_RO(cr_pinning);
static unsigned long cr4_pinned_bits __ro_after_init; static unsigned long cr4_pinned_bits __ro_after_init;
...@@ -371,20 +374,20 @@ EXPORT_SYMBOL(native_write_cr0); ...@@ -371,20 +374,20 @@ EXPORT_SYMBOL(native_write_cr0);
void native_write_cr4(unsigned long val) void native_write_cr4(unsigned long val)
{ {
unsigned long bits_missing = 0; unsigned long bits_changed = 0;
set_register: set_register:
asm volatile("mov %0,%%cr4": "+r" (val), "+m" (cr4_pinned_bits)); asm volatile("mov %0,%%cr4": "+r" (val), "+m" (cr4_pinned_bits));
if (static_branch_likely(&cr_pinning)) { if (static_branch_likely(&cr_pinning)) {
if (unlikely((val & cr4_pinned_bits) != cr4_pinned_bits)) { if (unlikely((val & cr4_pinned_mask) != cr4_pinned_bits)) {
bits_missing = ~val & cr4_pinned_bits; bits_changed = (val & cr4_pinned_mask) ^ cr4_pinned_bits;
val |= bits_missing; val = (val & ~cr4_pinned_mask) | cr4_pinned_bits;
goto set_register; goto set_register;
} }
/* Warn after we've set the missing bits. */ /* Warn after we've corrected the changed bits. */
WARN_ONCE(bits_missing, "CR4 bits went missing: %lx!?\n", WARN_ONCE(bits_changed, "pinned CR4 bits changed: 0x%lx!?\n",
bits_missing); bits_changed);
} }
} }
#if IS_MODULE(CONFIG_LKDTM) #if IS_MODULE(CONFIG_LKDTM)
...@@ -419,7 +422,7 @@ void cr4_init(void) ...@@ -419,7 +422,7 @@ void cr4_init(void)
if (boot_cpu_has(X86_FEATURE_PCID)) if (boot_cpu_has(X86_FEATURE_PCID))
cr4 |= X86_CR4_PCIDE; cr4 |= X86_CR4_PCIDE;
if (static_branch_likely(&cr_pinning)) if (static_branch_likely(&cr_pinning))
cr4 |= cr4_pinned_bits; cr4 = (cr4 & ~cr4_pinned_mask) | cr4_pinned_bits;
__write_cr4(cr4); __write_cr4(cr4);
...@@ -434,10 +437,7 @@ void cr4_init(void) ...@@ -434,10 +437,7 @@ void cr4_init(void)
*/ */
static void __init setup_cr_pinning(void) static void __init setup_cr_pinning(void)
{ {
unsigned long mask; cr4_pinned_bits = this_cpu_read(cpu_tlbstate.cr4) & cr4_pinned_mask;
mask = (X86_CR4_SMEP | X86_CR4_SMAP | X86_CR4_UMIP);
cr4_pinned_bits = this_cpu_read(cpu_tlbstate.cr4) & mask;
static_key_enable(&cr_pinning.key); static_key_enable(&cr_pinning.key);
} }
......
...@@ -81,8 +81,4 @@ extern void update_srbds_msr(void); ...@@ -81,8 +81,4 @@ extern void update_srbds_msr(void);
extern u64 x86_read_arch_cap_msr(void); extern u64 x86_read_arch_cap_msr(void);
#ifdef CONFIG_IA32_FEAT_CTL
void init_ia32_feat_ctl(struct cpuinfo_x86 *c);
#endif
#endif /* ARCH_X86_CPU_H */ #endif /* ARCH_X86_CPU_H */
...@@ -981,10 +981,10 @@ void resctrl_cpu_detect(struct cpuinfo_x86 *c) ...@@ -981,10 +981,10 @@ void resctrl_cpu_detect(struct cpuinfo_x86 *c)
c->x86_cache_max_rmid = ecx; c->x86_cache_max_rmid = ecx;
c->x86_cache_occ_scale = ebx; c->x86_cache_occ_scale = ebx;
if (c->x86_vendor == X86_VENDOR_INTEL)
c->x86_cache_mbm_width_offset = eax & 0xff; c->x86_cache_mbm_width_offset = eax & 0xff;
else
c->x86_cache_mbm_width_offset = -1; if (c->x86_vendor == X86_VENDOR_AMD && !c->x86_cache_mbm_width_offset)
c->x86_cache_mbm_width_offset = MBM_CNTR_WIDTH_OFFSET_AMD;
} }
} }
......
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
#define MBA_IS_LINEAR 0x4 #define MBA_IS_LINEAR 0x4
#define MBA_MAX_MBPS U32_MAX #define MBA_MAX_MBPS U32_MAX
#define MAX_MBA_BW_AMD 0x800 #define MAX_MBA_BW_AMD 0x800
#define MBM_CNTR_WIDTH_OFFSET_AMD 20
#define RMID_VAL_ERROR BIT_ULL(63) #define RMID_VAL_ERROR BIT_ULL(63)
#define RMID_VAL_UNAVAIL BIT_ULL(62) #define RMID_VAL_UNAVAIL BIT_ULL(62)
......
...@@ -1117,6 +1117,7 @@ static int rdt_cdp_peer_get(struct rdt_resource *r, struct rdt_domain *d, ...@@ -1117,6 +1117,7 @@ static int rdt_cdp_peer_get(struct rdt_resource *r, struct rdt_domain *d,
_d_cdp = rdt_find_domain(_r_cdp, d->id, NULL); _d_cdp = rdt_find_domain(_r_cdp, d->id, NULL);
if (WARN_ON(IS_ERR_OR_NULL(_d_cdp))) { if (WARN_ON(IS_ERR_OR_NULL(_d_cdp))) {
_r_cdp = NULL; _r_cdp = NULL;
_d_cdp = NULL;
ret = -EINVAL; ret = -EINVAL;
} }
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/sched/clock.h> #include <linux/sched/clock.h>
#include <asm/cpu.h>
#include <asm/cpufeature.h> #include <asm/cpufeature.h>
#include "cpu.h" #include "cpu.h"
......
...@@ -24,6 +24,7 @@ unsigned long __clear_user(void __user *addr, unsigned long size) ...@@ -24,6 +24,7 @@ unsigned long __clear_user(void __user *addr, unsigned long size)
asm volatile( asm volatile(
" testq %[size8],%[size8]\n" " testq %[size8],%[size8]\n"
" jz 4f\n" " jz 4f\n"
" .align 16\n"
"0: movq $0,(%[dst])\n" "0: movq $0,(%[dst])\n"
" addq $8,%[dst]\n" " addq $8,%[dst]\n"
" decl %%ecx ; jnz 0b\n" " decl %%ecx ; jnz 0b\n"
......
...@@ -193,6 +193,8 @@ static void fix_processor_context(void) ...@@ -193,6 +193,8 @@ static void fix_processor_context(void)
*/ */
static void notrace __restore_processor_state(struct saved_context *ctxt) static void notrace __restore_processor_state(struct saved_context *ctxt)
{ {
struct cpuinfo_x86 *c;
if (ctxt->misc_enable_saved) if (ctxt->misc_enable_saved)
wrmsrl(MSR_IA32_MISC_ENABLE, ctxt->misc_enable); wrmsrl(MSR_IA32_MISC_ENABLE, ctxt->misc_enable);
/* /*
...@@ -263,6 +265,10 @@ static void notrace __restore_processor_state(struct saved_context *ctxt) ...@@ -263,6 +265,10 @@ static void notrace __restore_processor_state(struct saved_context *ctxt)
mtrr_bp_restore(); mtrr_bp_restore();
perf_restore_debug_store(); perf_restore_debug_store();
msr_restore_context(ctxt); msr_restore_context(ctxt);
c = &cpu_data(smp_processor_id());
if (cpu_has(c, X86_FEATURE_MSR_IA32_FEAT_CTL))
init_ia32_feat_ctl(c);
} }
/* Needed by apm.c */ /* Needed by apm.c */
......
...@@ -1360,7 +1360,7 @@ static inline long ksys_lchown(const char __user *filename, uid_t user, ...@@ -1360,7 +1360,7 @@ static inline long ksys_lchown(const char __user *filename, uid_t user,
extern long do_sys_ftruncate(unsigned int fd, loff_t length, int small); extern long do_sys_ftruncate(unsigned int fd, loff_t length, int small);
static inline long ksys_ftruncate(unsigned int fd, unsigned long length) static inline long ksys_ftruncate(unsigned int fd, loff_t length)
{ {
return do_sys_ftruncate(fd, length, 1); return do_sys_ftruncate(fd, length, 1);
} }
......
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