]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge branch 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 11 Apr 2014 18:58:33 +0000 (11:58 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 11 Apr 2014 18:58:33 +0000 (11:58 -0700)
Pull x86 fixes from Peter Anvin:
 "This is a collection of minor fixes for x86, plus the IRET information
  leak fix (forbid the use of 16-bit segments in 64-bit mode)"

NOTE! We may have to relax the "forbid the use of 16-bit segments in
64-bit mode" part, since there may be people who still run and depend on
16-bit Windows binaries under Wine.

But I'm taking this in the current unconditional form for now to see who
(if anybody) screams bloody murder.  Maybe nobody cares.  And maybe
we'll have to update it with some kind of runtime enablement (like our
vm.mmap_min_addr tunable that people who run dosemu/qemu/wine already
need to tweak).

* 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86-64, modify_ldt: Ban 16-bit segments on 64-bit kernels
  efi: Pass correct file handle to efi_file_{read,close}
  x86/efi: Correct EFI boot stub use of code32_start
  x86/efi: Fix boot failure with EFI stub
  x86/platform/hyperv: Handle VMBUS driver being a module
  x86/apic: Reinstate error IRQ Pentium erratum 3AP workaround
  x86, CMCI: Add proper detection of end of CMCI storms

arch/x86/boot/compressed/eboot.c
arch/x86/boot/compressed/head_32.S
arch/x86/boot/compressed/head_64.S
arch/x86/kernel/apic/apic.c
arch/x86/kernel/cpu/mcheck/mce.c
arch/x86/kernel/cpu/mcheck/mce_intel.c
arch/x86/kernel/irq.c
arch/x86/kernel/ldt.c
drivers/firmware/efi/efi-stub-helper.c

index 1e6146137f8e56753aab7d68b0e0b45af3c5fed9..4703a6c4b8e315050a38533438a27228ddc4758c 100644 (file)
@@ -112,7 +112,7 @@ __file_size64(void *__fh, efi_char16_t *filename_16,
        efi_file_info_t *info;
        efi_status_t status;
        efi_guid_t info_guid = EFI_FILE_INFO_ID;
-       u32 info_sz;
+       u64 info_sz;
 
        status = efi_early->call((unsigned long)fh->open, fh, &h, filename_16,
                                 EFI_FILE_MODE_READ, (u64)0);
@@ -167,31 +167,31 @@ efi_file_size(efi_system_table_t *sys_table, void *__fh,
 }
 
 static inline efi_status_t
-efi_file_read(void *__fh, void *handle, unsigned long *size, void *addr)
+efi_file_read(void *handle, unsigned long *size, void *addr)
 {
        unsigned long func;
 
        if (efi_early->is64) {
-               efi_file_handle_64_t *fh = __fh;
+               efi_file_handle_64_t *fh = handle;
 
                func = (unsigned long)fh->read;
                return efi_early->call(func, handle, size, addr);
        } else {
-               efi_file_handle_32_t *fh = __fh;
+               efi_file_handle_32_t *fh = handle;
 
                func = (unsigned long)fh->read;
                return efi_early->call(func, handle, size, addr);
        }
 }
 
-static inline efi_status_t efi_file_close(void *__fh, void *handle)
+static inline efi_status_t efi_file_close(void *handle)
 {
        if (efi_early->is64) {
-               efi_file_handle_64_t *fh = __fh;
+               efi_file_handle_64_t *fh = handle;
 
                return efi_early->call((unsigned long)fh->close, handle);
        } else {
-               efi_file_handle_32_t *fh = __fh;
+               efi_file_handle_32_t *fh = handle;
 
                return efi_early->call((unsigned long)fh->close, handle);
        }
@@ -1016,6 +1016,9 @@ void setup_graphics(struct boot_params *boot_params)
  * Because the x86 boot code expects to be passed a boot_params we
  * need to create one ourselves (usually the bootloader would create
  * one for us).
+ *
+ * The caller is responsible for filling out ->code32_start in the
+ * returned boot_params.
  */
 struct boot_params *make_boot_params(struct efi_config *c)
 {
@@ -1081,8 +1084,6 @@ struct boot_params *make_boot_params(struct efi_config *c)
        hdr->vid_mode = 0xffff;
        hdr->boot_flag = 0xAA55;
 
-       hdr->code32_start = (__u64)(unsigned long)image->image_base;
-
        hdr->type_of_loader = 0x21;
 
        /* Convert unicode cmdline to ascii */
index de9d4200d305ba86eb48bb60f3a852b210fb2649..cbed1407a5cdb7ead8fa0cae90d2e7902133aaa7 100644 (file)
@@ -59,6 +59,7 @@ ENTRY(efi_pe_entry)
        call    make_boot_params
        cmpl    $0, %eax
        je      fail
+       movl    %esi, BP_code32_start(%eax)
        popl    %ecx
        pushl   %eax
        pushl   %ecx
@@ -90,12 +91,7 @@ fail:
        hlt
        jmp     fail
 2:
-       call    3f
-3:
-       popl    %eax
-       subl    $3b, %eax
-       subl    BP_pref_address(%esi), %eax
-       add     BP_code32_start(%esi), %eax
+       movl    BP_code32_start(%esi), %eax
        leal    preferred_addr(%eax), %eax
        jmp     *%eax
 
index 57e58a5fa21073de1c86f4ceee6b76e674d87399..0d558ee899aec85cf3fce7f69691441691a41f93 100644 (file)
@@ -261,6 +261,8 @@ ENTRY(efi_pe_entry)
        cmpq    $0,%rax
        je      fail
        mov     %rax, %rsi
+       leaq    startup_32(%rip), %rax
+       movl    %eax, BP_code32_start(%rsi)
        jmp     2f              /* Skip the relocation */
 
 handover_entry:
@@ -284,12 +286,7 @@ fail:
        hlt
        jmp     fail
 2:
-       call    3f
-3:
-       popq    %rax
-       subq    $3b, %rax
-       subq    BP_pref_address(%rsi), %rax
-       add     BP_code32_start(%esi), %eax
+       movl    BP_code32_start(%esi), %eax
        leaq    preferred_addr(%rax), %rax
        jmp     *%rax
 
index 481ae38f6a44f5ac240fdd39b06f8708f66522d5..ad28db7e6bdea3594a4bfad1d70d0c975ded7021 100644 (file)
@@ -1996,7 +1996,8 @@ static inline void __smp_error_interrupt(struct pt_regs *regs)
        };
 
        /* First tickle the hardware, only then report what went on. -- REW */
-       apic_write(APIC_ESR, 0);
+       if (lapic_get_maxlvt() > 3)     /* Due to the Pentium erratum 3AP. */
+               apic_write(APIC_ESR, 0);
        v = apic_read(APIC_ESR);
        ack_APIC_irq();
        atomic_inc(&irq_err_count);
index 9b7734b1f975a4c0cfc9776749aecc83ace1cd10..eeee23ff75ef8ddb28a002d26b5bee98b21e03ca 100644 (file)
@@ -89,6 +89,9 @@ static DECLARE_WAIT_QUEUE_HEAD(mce_chrdev_wait);
 static DEFINE_PER_CPU(struct mce, mces_seen);
 static int                     cpu_missing;
 
+/* CMCI storm detection filter */
+static DEFINE_PER_CPU(unsigned long, mce_polled_error);
+
 /*
  * MCA banks polled by the period polling timer for corrected events.
  * With Intel CMCI, this only has MCA banks which do not support CMCI (if any).
@@ -595,6 +598,7 @@ void machine_check_poll(enum mcp_flags flags, mce_banks_t *b)
 {
        struct mce m;
        int i;
+       unsigned long *v;
 
        this_cpu_inc(mce_poll_count);
 
@@ -614,6 +618,8 @@ void machine_check_poll(enum mcp_flags flags, mce_banks_t *b)
                if (!(m.status & MCI_STATUS_VAL))
                        continue;
 
+               v = &get_cpu_var(mce_polled_error);
+               set_bit(0, v);
                /*
                 * Uncorrected or signalled events are handled by the exception
                 * handler when it is enabled, so don't process those here.
@@ -1278,10 +1284,18 @@ static unsigned long mce_adjust_timer_default(unsigned long interval)
 static unsigned long (*mce_adjust_timer)(unsigned long interval) =
        mce_adjust_timer_default;
 
+static int cmc_error_seen(void)
+{
+       unsigned long *v = &__get_cpu_var(mce_polled_error);
+
+       return test_and_clear_bit(0, v);
+}
+
 static void mce_timer_fn(unsigned long data)
 {
        struct timer_list *t = &__get_cpu_var(mce_timer);
        unsigned long iv;
+       int notify;
 
        WARN_ON(smp_processor_id() != data);
 
@@ -1296,7 +1310,9 @@ static void mce_timer_fn(unsigned long data)
         * polling interval, otherwise increase the polling interval.
         */
        iv = __this_cpu_read(mce_next_interval);
-       if (mce_notify_irq()) {
+       notify = mce_notify_irq();
+       notify |= cmc_error_seen();
+       if (notify) {
                iv = max(iv / 2, (unsigned long) HZ/100);
        } else {
                iv = min(iv * 2, round_jiffies_relative(check_interval * HZ));
index fb6156fee6f79dcc07559a9765f3702d7365506d..3bdb95ae8c430fa8bacc76a9f644c4abce8ec35e 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/interrupt.h>
 #include <linux/percpu.h>
 #include <linux/sched.h>
+#include <linux/cpumask.h>
 #include <asm/apic.h>
 #include <asm/processor.h>
 #include <asm/msr.h>
@@ -137,6 +138,22 @@ unsigned long mce_intel_adjust_timer(unsigned long interval)
        }
 }
 
+static void cmci_storm_disable_banks(void)
+{
+       unsigned long flags, *owned;
+       int bank;
+       u64 val;
+
+       raw_spin_lock_irqsave(&cmci_discover_lock, flags);
+       owned = __get_cpu_var(mce_banks_owned);
+       for_each_set_bit(bank, owned, MAX_NR_BANKS) {
+               rdmsrl(MSR_IA32_MCx_CTL2(bank), val);
+               val &= ~MCI_CTL2_CMCI_EN;
+               wrmsrl(MSR_IA32_MCx_CTL2(bank), val);
+       }
+       raw_spin_unlock_irqrestore(&cmci_discover_lock, flags);
+}
+
 static bool cmci_storm_detect(void)
 {
        unsigned int cnt = __this_cpu_read(cmci_storm_cnt);
@@ -158,7 +175,7 @@ static bool cmci_storm_detect(void)
        if (cnt <= CMCI_STORM_THRESHOLD)
                return false;
 
-       cmci_clear();
+       cmci_storm_disable_banks();
        __this_cpu_write(cmci_storm_state, CMCI_STORM_ACTIVE);
        r = atomic_add_return(1, &cmci_storm_on_cpus);
        mce_timer_kick(CMCI_POLL_INTERVAL);
index 42805fac009215ac5c70bdd71fdc2ad5d72dfa89..283a76a9cc4099427b8d8b7dcc595cfdddb880a1 100644 (file)
@@ -125,7 +125,7 @@ int arch_show_interrupts(struct seq_file *p, int prec)
                seq_printf(p, "%10u ", per_cpu(mce_poll_count, j));
        seq_printf(p, "  Machine check polls\n");
 #endif
-#if defined(CONFIG_HYPERV) || defined(CONFIG_XEN)
+#if IS_ENABLED(CONFIG_HYPERV) || defined(CONFIG_XEN)
        seq_printf(p, "%*s: ", prec, "THR");
        for_each_online_cpu(j)
                seq_printf(p, "%10u ", irq_stats(j)->irq_hv_callback_count);
index ebc9873989233dcba13d1fa1af14e3e921959a85..af1d14a9ebdae1ac2fddace4c15271babd1613a3 100644 (file)
@@ -229,6 +229,17 @@ static int write_ldt(void __user *ptr, unsigned long bytecount, int oldmode)
                }
        }
 
+       /*
+        * On x86-64 we do not support 16-bit segments due to
+        * IRET leaking the high bits of the kernel stack address.
+        */
+#ifdef CONFIG_X86_64
+       if (!ldt_info.seg_32bit) {
+               error = -EINVAL;
+               goto out_unlock;
+       }
+#endif
+
        fill_ldt(&ldt, &ldt_info);
        if (oldmode)
                ldt.avl = 0;
index ff50aeebf0d98828072eea4b40944ebfa7594c77..2c41eaece2c17370008efeffdbe4986050e55adf 100644 (file)
@@ -397,7 +397,7 @@ static efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg,
                                else
                                        chunksize = size;
 
-                               status = efi_file_read(fh, files[j].handle,
+                               status = efi_file_read(files[j].handle,
                                                       &chunksize,
                                                       (void *)addr);
                                if (status != EFI_SUCCESS) {
@@ -408,7 +408,7 @@ static efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg,
                                size -= chunksize;
                        }
 
-                       efi_file_close(fh, files[j].handle);
+                       efi_file_close(files[j].handle);
                }
 
        }
@@ -425,7 +425,7 @@ free_file_total:
 
 close_handles:
        for (k = j; k < i; k++)
-               efi_file_close(fh, files[k].handle);
+               efi_file_close(files[k].handle);
 free_files:
        efi_call_early(free_pool, files);
 fail: