0001
0002
0003
0004 #include <linux/jump_label.h>
0005 #include <linux/uaccess.h>
0006 #include <linux/export.h>
0007 #include <linux/string.h>
0008 #include <linux/types.h>
0009
0010 #include <asm/mce.h>
0011
0012 #ifdef CONFIG_X86_MCE
0013 static DEFINE_STATIC_KEY_FALSE(copy_mc_fragile_key);
0014
0015 void enable_copy_mc_fragile(void)
0016 {
0017 static_branch_inc(©_mc_fragile_key);
0018 }
0019 #define copy_mc_fragile_enabled (static_branch_unlikely(©_mc_fragile_key))
0020
0021
0022
0023
0024
0025 __visible notrace unsigned long
0026 copy_mc_fragile_handle_tail(char *to, char *from, unsigned len)
0027 {
0028 for (; len; --len, to++, from++)
0029 if (copy_mc_fragile(to, from, 1))
0030 break;
0031 return len;
0032 }
0033 #else
0034
0035
0036
0037
0038 void enable_copy_mc_fragile(void)
0039 {
0040 }
0041 #define copy_mc_fragile_enabled (0)
0042 #endif
0043
0044 unsigned long copy_mc_enhanced_fast_string(void *dst, const void *src, unsigned len);
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062 unsigned long __must_check copy_mc_to_kernel(void *dst, const void *src, unsigned len)
0063 {
0064 if (copy_mc_fragile_enabled)
0065 return copy_mc_fragile(dst, src, len);
0066 if (static_cpu_has(X86_FEATURE_ERMS))
0067 return copy_mc_enhanced_fast_string(dst, src, len);
0068 memcpy(dst, src, len);
0069 return 0;
0070 }
0071 EXPORT_SYMBOL_GPL(copy_mc_to_kernel);
0072
0073 unsigned long __must_check copy_mc_to_user(void *dst, const void *src, unsigned len)
0074 {
0075 unsigned long ret;
0076
0077 if (copy_mc_fragile_enabled) {
0078 __uaccess_begin();
0079 ret = copy_mc_fragile(dst, src, len);
0080 __uaccess_end();
0081 return ret;
0082 }
0083
0084 if (static_cpu_has(X86_FEATURE_ERMS)) {
0085 __uaccess_begin();
0086 ret = copy_mc_enhanced_fast_string(dst, src, len);
0087 __uaccess_end();
0088 return ret;
0089 }
0090
0091 return copy_user_generic(dst, src, len);
0092 }