Commit 484b002e authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86 fixes from Peter Anvin:

 - Three EFI-related fixes

 - Two early memory initialization fixes

 - build fix for older binutils

 - fix for an eager FPU performance regression -- currently we don't
   allow the use of the FPU at interrupt time *at all* in eager mode,
   which is clearly wrong.

* 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86: Allow FPU to be used at interrupt time even with eagerfpu
  x86, crc32-pclmul: Fix build with older binutils
  x86-64, init: Fix a possible wraparound bug in switchover in head_64.S
  x86, range: fix missing merge during add range
  x86, efi: initial the local variable of DataSize to zero
  efivar: fix oops in efivar_update_sysfs_entries() caused by memory reuse
  efivarfs: Never return ENOENT from firmware again
parents 3655b22d 5187b28f
...@@ -240,7 +240,7 @@ fold_64: ...@@ -240,7 +240,7 @@ fold_64:
pand %xmm3, %xmm1 pand %xmm3, %xmm1
PCLMULQDQ 0x00, CONSTANT, %xmm1 PCLMULQDQ 0x00, CONSTANT, %xmm1
pxor %xmm2, %xmm1 pxor %xmm2, %xmm1
pextrd $0x01, %xmm1, %eax PEXTRD 0x01, %xmm1, %eax
ret ret
ENDPROC(crc32_pclmul_le_16) ENDPROC(crc32_pclmul_le_16)
...@@ -9,12 +9,68 @@ ...@@ -9,12 +9,68 @@
#define REG_NUM_INVALID 100 #define REG_NUM_INVALID 100
#define REG_TYPE_R64 0 #define REG_TYPE_R32 0
#define REG_TYPE_XMM 1 #define REG_TYPE_R64 1
#define REG_TYPE_XMM 2
#define REG_TYPE_INVALID 100 #define REG_TYPE_INVALID 100
.macro R32_NUM opd r32
\opd = REG_NUM_INVALID
.ifc \r32,%eax
\opd = 0
.endif
.ifc \r32,%ecx
\opd = 1
.endif
.ifc \r32,%edx
\opd = 2
.endif
.ifc \r32,%ebx
\opd = 3
.endif
.ifc \r32,%esp
\opd = 4
.endif
.ifc \r32,%ebp
\opd = 5
.endif
.ifc \r32,%esi
\opd = 6
.endif
.ifc \r32,%edi
\opd = 7
.endif
#ifdef CONFIG_X86_64
.ifc \r32,%r8d
\opd = 8
.endif
.ifc \r32,%r9d
\opd = 9
.endif
.ifc \r32,%r10d
\opd = 10
.endif
.ifc \r32,%r11d
\opd = 11
.endif
.ifc \r32,%r12d
\opd = 12
.endif
.ifc \r32,%r13d
\opd = 13
.endif
.ifc \r32,%r14d
\opd = 14
.endif
.ifc \r32,%r15d
\opd = 15
.endif
#endif
.endm
.macro R64_NUM opd r64 .macro R64_NUM opd r64
\opd = REG_NUM_INVALID \opd = REG_NUM_INVALID
#ifdef CONFIG_X86_64
.ifc \r64,%rax .ifc \r64,%rax
\opd = 0 \opd = 0
.endif .endif
...@@ -63,6 +119,7 @@ ...@@ -63,6 +119,7 @@
.ifc \r64,%r15 .ifc \r64,%r15
\opd = 15 \opd = 15
.endif .endif
#endif
.endm .endm
.macro XMM_NUM opd xmm .macro XMM_NUM opd xmm
...@@ -118,10 +175,13 @@ ...@@ -118,10 +175,13 @@
.endm .endm
.macro REG_TYPE type reg .macro REG_TYPE type reg
R32_NUM reg_type_r32 \reg
R64_NUM reg_type_r64 \reg R64_NUM reg_type_r64 \reg
XMM_NUM reg_type_xmm \reg XMM_NUM reg_type_xmm \reg
.if reg_type_r64 <> REG_NUM_INVALID .if reg_type_r64 <> REG_NUM_INVALID
\type = REG_TYPE_R64 \type = REG_TYPE_R64
.elseif reg_type_r32 <> REG_NUM_INVALID
\type = REG_TYPE_R32
.elseif reg_type_xmm <> REG_NUM_INVALID .elseif reg_type_xmm <> REG_NUM_INVALID
\type = REG_TYPE_XMM \type = REG_TYPE_XMM
.else .else
...@@ -162,6 +222,16 @@ ...@@ -162,6 +222,16 @@
.byte \imm8 .byte \imm8
.endm .endm
.macro PEXTRD imm8 xmm gpr
R32_NUM extrd_opd1 \gpr
XMM_NUM extrd_opd2 \xmm
PFX_OPD_SIZE
PFX_REX extrd_opd1 extrd_opd2
.byte 0x0f, 0x3a, 0x16
MODRM 0xc0 extrd_opd1 extrd_opd2
.byte \imm8
.endm
.macro AESKEYGENASSIST rcon xmm1 xmm2 .macro AESKEYGENASSIST rcon xmm1 xmm2
XMM_NUM aeskeygen_opd1 \xmm1 XMM_NUM aeskeygen_opd1 \xmm1
XMM_NUM aeskeygen_opd2 \xmm2 XMM_NUM aeskeygen_opd2 \xmm2
......
...@@ -115,8 +115,10 @@ startup_64: ...@@ -115,8 +115,10 @@ startup_64:
movq %rdi, %rax movq %rdi, %rax
shrq $PUD_SHIFT, %rax shrq $PUD_SHIFT, %rax
andl $(PTRS_PER_PUD-1), %eax andl $(PTRS_PER_PUD-1), %eax
movq %rdx, (4096+0)(%rbx,%rax,8) movq %rdx, 4096(%rbx,%rax,8)
movq %rdx, (4096+8)(%rbx,%rax,8) incl %eax
andl $(PTRS_PER_PUD-1), %eax
movq %rdx, 4096(%rbx,%rax,8)
addq $8192, %rbx addq $8192, %rbx
movq %rdi, %rax movq %rdi, %rax
......
...@@ -22,23 +22,19 @@ ...@@ -22,23 +22,19 @@
/* /*
* Were we in an interrupt that interrupted kernel mode? * Were we in an interrupt that interrupted kernel mode?
* *
* For now, with eagerfpu we will return interrupted kernel FPU
* state as not-idle. TBD: Ideally we can change the return value
* to something like __thread_has_fpu(current). But we need to
* be careful of doing __thread_clear_has_fpu() before saving
* the FPU etc for supporting nested uses etc. For now, take
* the simple route!
*
* On others, we can do a kernel_fpu_begin/end() pair *ONLY* if that * On others, we can do a kernel_fpu_begin/end() pair *ONLY* if that
* pair does nothing at all: the thread must not have fpu (so * pair does nothing at all: the thread must not have fpu (so
* that we don't try to save the FPU state), and TS must * that we don't try to save the FPU state), and TS must
* be set (so that the clts/stts pair does nothing that is * be set (so that the clts/stts pair does nothing that is
* visible in the interrupted kernel thread). * visible in the interrupted kernel thread).
*
* Except for the eagerfpu case when we return 1 unless we've already
* been eager and saved the state in kernel_fpu_begin().
*/ */
static inline bool interrupted_kernel_fpu_idle(void) static inline bool interrupted_kernel_fpu_idle(void)
{ {
if (use_eager_fpu()) if (use_eager_fpu())
return 0; return __thread_has_fpu(current);
return !__thread_has_fpu(current) && return !__thread_has_fpu(current) &&
(read_cr0() & X86_CR0_TS); (read_cr0() & X86_CR0_TS);
...@@ -78,8 +74,8 @@ void __kernel_fpu_begin(void) ...@@ -78,8 +74,8 @@ void __kernel_fpu_begin(void)
struct task_struct *me = current; struct task_struct *me = current;
if (__thread_has_fpu(me)) { if (__thread_has_fpu(me)) {
__save_init_fpu(me);
__thread_clear_has_fpu(me); __thread_clear_has_fpu(me);
__save_init_fpu(me);
/* We do 'stts()' in __kernel_fpu_end() */ /* We do 'stts()' in __kernel_fpu_end() */
} else if (!use_eager_fpu()) { } else if (!use_eager_fpu()) {
this_cpu_write(fpu_owner_task, NULL); this_cpu_write(fpu_owner_task, NULL);
......
...@@ -206,7 +206,7 @@ static efi_status_t virt_efi_get_next_variable(unsigned long *name_size, ...@@ -206,7 +206,7 @@ static efi_status_t virt_efi_get_next_variable(unsigned long *name_size,
} }
if (boot_used_size && !finished) { if (boot_used_size && !finished) {
unsigned long size; unsigned long size = 0;
u32 attr; u32 attr;
efi_status_t s; efi_status_t s;
void *tmp; void *tmp;
......
...@@ -523,13 +523,11 @@ static void efivar_update_sysfs_entries(struct work_struct *work) ...@@ -523,13 +523,11 @@ static void efivar_update_sysfs_entries(struct work_struct *work)
struct efivar_entry *entry; struct efivar_entry *entry;
int err; int err;
entry = kzalloc(sizeof(*entry), GFP_KERNEL);
if (!entry)
return;
/* Add new sysfs entries */ /* Add new sysfs entries */
while (1) { while (1) {
memset(entry, 0, sizeof(*entry)); entry = kzalloc(sizeof(*entry), GFP_KERNEL);
if (!entry)
return;
err = efivar_init(efivar_update_sysfs_entry, entry, err = efivar_init(efivar_update_sysfs_entry, entry,
true, false, &efivar_sysfs_list); true, false, &efivar_sysfs_list);
......
...@@ -44,8 +44,11 @@ static ssize_t efivarfs_file_write(struct file *file, ...@@ -44,8 +44,11 @@ static ssize_t efivarfs_file_write(struct file *file,
bytes = efivar_entry_set_get_size(var, attributes, &datasize, bytes = efivar_entry_set_get_size(var, attributes, &datasize,
data, &set); data, &set);
if (!set && bytes) if (!set && bytes) {
if (bytes == -ENOENT)
bytes = -EIO;
goto out; goto out;
}
if (bytes == -ENOENT) { if (bytes == -ENOENT) {
drop_nlink(inode); drop_nlink(inode);
...@@ -76,7 +79,14 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf, ...@@ -76,7 +79,14 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf,
int err; int err;
err = efivar_entry_size(var, &datasize); err = efivar_entry_size(var, &datasize);
if (err)
/*
* efivarfs represents uncommitted variables with
* zero-length files. Reading them should return EOF.
*/
if (err == -ENOENT)
return 0;
else if (err)
return err; return err;
data = kmalloc(datasize + sizeof(attributes), GFP_KERNEL); data = kmalloc(datasize + sizeof(attributes), GFP_KERNEL);
......
...@@ -48,9 +48,11 @@ int add_range_with_merge(struct range *range, int az, int nr_range, ...@@ -48,9 +48,11 @@ int add_range_with_merge(struct range *range, int az, int nr_range,
final_start = min(range[i].start, start); final_start = min(range[i].start, start);
final_end = max(range[i].end, end); final_end = max(range[i].end, end);
range[i].start = final_start; /* clear it and add it back for further merge */
range[i].end = final_end; range[i].start = 0;
return nr_range; range[i].end = 0;
return add_range_with_merge(range, az, nr_range,
final_start, final_end);
} }
/* Need to add it: */ /* Need to add it: */
......
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