]> Git Repo - linux.git/commitdiff
Merge tag 'x86-urgent-2020-08-15' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <[email protected]>
Sat, 15 Aug 2020 17:38:03 +0000 (10:38 -0700)
committerLinus Torvalds <[email protected]>
Sat, 15 Aug 2020 17:38:03 +0000 (10:38 -0700)
Pull x86 fixes from Ingo Molnar:
 "Misc fixes and small updates all around the place:

   - Fix mitigation state sysfs output

   - Fix an FPU xstate/sxave code assumption bug triggered by
     Architectural LBR support

   - Fix Lightning Mountain SoC TSC frequency enumeration bug

   - Fix kexec debug output

   - Fix kexec memory range assumption bug

   - Fix a boundary condition in the crash kernel code

   - Optimize porgatory.ro generation a bit

   - Enable ACRN guests to use X2APIC mode

   - Reduce a __text_poke() IRQs-off critical section for the benefit of
     PREEMPT_RT"

* tag 'x86-urgent-2020-08-15' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86/alternatives: Acquire pte lock with interrupts enabled
  x86/bugs/multihit: Fix mitigation reporting when VMX is not in use
  x86/fpu/xstate: Fix an xstate size check warning with architectural LBRs
  x86/purgatory: Don't generate debug info for purgatory.ro
  x86/tsr: Fix tsc frequency enumeration bug on Lightning Mountain SoC
  kexec_file: Correctly output debugging information for the PT_LOAD ELF header
  kexec: Improve & fix crash_exclude_mem_range() to handle overlapping ranges
  x86/crash: Correct the address boundary of function parameters
  x86/acrn: Remove redundant chars from ACRN signature
  x86/acrn: Allow ACRN guest to use X2APIC mode

1  2 
arch/x86/kernel/alternative.c
arch/x86/kernel/fpu/xstate.c
arch/x86/kernel/tsc_msr.c
arch/x86/purgatory/Makefile
kernel/kexec_file.c

index d1175533d125df81d426231fdfaac9cbd8c83d21,34a1b8562c319bd693a67faadcdd1887258b956c..c3daf0aaa0ee6d387a5ff1c2ddafff2bea746fb1
@@@ -7,7 -7,6 +7,7 @@@
  #include <linux/mutex.h>
  #include <linux/list.h>
  #include <linux/stringify.h>
 +#include <linux/highmem.h>
  #include <linux/mm.h>
  #include <linux/vmalloc.h>
  #include <linux/memory.h>
@@@ -875,8 -874,6 +875,6 @@@ static void *__text_poke(void *addr, co
         */
        BUG_ON(!pages[0] || (cross_page_boundary && !pages[1]));
  
-       local_irq_save(flags);
        /*
         * Map the page without the global bit, as TLB flushing is done with
         * flush_tlb_mm_range(), which is intended for non-global PTEs.
         */
        VM_BUG_ON(!ptep);
  
+       local_irq_save(flags);
        pte = mk_pte(pages[0], pgprot);
        set_pte_at(poking_mm, poking_addr, ptep, pte);
  
         */
        BUG_ON(memcmp(addr, opcode, len));
  
-       pte_unmap_unlock(ptep, ptl);
        local_irq_restore(flags);
+       pte_unmap_unlock(ptep, ptl);
        return addr;
  }
  
index 7a2bf884fede741da363c772e11bb4e4b46b13c7,6073e342a1eda8b39e2570b867e8902297acb4c5..038e19c0019ed92156ae329c46da4eeb21b45b18
@@@ -611,6 -611,10 +611,10 @@@ static void check_xstate_against_struct
   * This essentially double-checks what the cpu told us about
   * how large the XSAVE buffer needs to be.  We are recalculating
   * it to be safe.
+  *
+  * Dynamic XSAVE features allocate their own buffers and are not
+  * covered by these checks. Only the size of the buffer for task->fpu
+  * is checked here.
   */
  static void do_extra_xstate_size_checks(void)
  {
@@@ -673,6 -677,33 +677,33 @@@ static unsigned int __init get_xsaves_s
        return ebx;
  }
  
+ /*
+  * Get the total size of the enabled xstates without the dynamic supervisor
+  * features.
+  */
+ static unsigned int __init get_xsaves_size_no_dynamic(void)
+ {
+       u64 mask = xfeatures_mask_dynamic();
+       unsigned int size;
+       if (!mask)
+               return get_xsaves_size();
+       /* Disable dynamic features. */
+       wrmsrl(MSR_IA32_XSS, xfeatures_mask_supervisor());
+       /*
+        * Ask the hardware what size is required of the buffer.
+        * This is the size required for the task->fpu buffer.
+        */
+       size = get_xsaves_size();
+       /* Re-enable dynamic features so XSAVES will work on them again. */
+       wrmsrl(MSR_IA32_XSS, xfeatures_mask_supervisor() | mask);
+       return size;
+ }
  static unsigned int __init get_xsave_size(void)
  {
        unsigned int eax, ebx, ecx, edx;
@@@ -710,7 -741,7 +741,7 @@@ static int __init init_xstate_size(void
        xsave_size = get_xsave_size();
  
        if (boot_cpu_has(X86_FEATURE_XSAVES))
-               possible_xstate_size = get_xsaves_size();
+               possible_xstate_size = get_xsaves_size_no_dynamic();
        else
                possible_xstate_size = xsave_size;
  
@@@ -1014,20 -1045,32 +1045,20 @@@ static inline bool xfeatures_mxcsr_quir
        return true;
  }
  
 -static void fill_gap(unsigned to, void **kbuf, unsigned *pos, unsigned *count)
 +static void fill_gap(struct membuf *to, unsigned *last, unsigned offset)
  {
 -      if (*pos < to) {
 -              unsigned size = to - *pos;
 -
 -              if (size > *count)
 -                      size = *count;
 -              memcpy(*kbuf, (void *)&init_fpstate.xsave + *pos, size);
 -              *kbuf += size;
 -              *pos += size;
 -              *count -= size;
 -      }
 +      if (*last >= offset)
 +              return;
 +      membuf_write(to, (void *)&init_fpstate.xsave + *last, offset - *last);
 +      *last = offset;
  }
  
 -static void copy_part(unsigned offset, unsigned size, void *from,
 -                      void **kbuf, unsigned *pos, unsigned *count)
 +static void copy_part(struct membuf *to, unsigned *last, unsigned offset,
 +                    unsigned size, void *from)
  {
 -      fill_gap(offset, kbuf, pos, count);
 -      if (size > *count)
 -              size = *count;
 -      if (size) {
 -              memcpy(*kbuf, from, size);
 -              *kbuf += size;
 -              *pos += size;
 -              *count -= size;
 -      }
 +      fill_gap(to, last, offset);
 +      membuf_write(to, from, size);
 +      *last = offset + size;
  }
  
  /*
   * It supports partial copy but pos always starts from zero. This is called
   * from xstateregs_get() and there we check the CPU has XSAVES.
   */
 -int copy_xstate_to_kernel(void *kbuf, struct xregs_state *xsave, unsigned int offset_start, unsigned int size_total)
 +void copy_xstate_to_kernel(struct membuf to, struct xregs_state *xsave)
  {
        struct xstate_header header;
        const unsigned off_mxcsr = offsetof(struct fxregs_state, mxcsr);
 -      unsigned count = size_total;
 +      unsigned size = to.left;
 +      unsigned last = 0;
        int i;
  
 -      /*
 -       * Currently copy_regset_to_user() starts from pos 0:
 -       */
 -      if (unlikely(offset_start != 0))
 -              return -EFAULT;
 -
        /*
         * The destination is a ptrace buffer; we put in only user xstates:
         */
        header.xfeatures &= xfeatures_mask_user();
  
        if (header.xfeatures & XFEATURE_MASK_FP)
 -              copy_part(0, off_mxcsr,
 -                        &xsave->i387, &kbuf, &offset_start, &count);
 +              copy_part(&to, &last, 0, off_mxcsr, &xsave->i387);
        if (header.xfeatures & (XFEATURE_MASK_SSE | XFEATURE_MASK_YMM))
 -              copy_part(off_mxcsr, MXCSR_AND_FLAGS_SIZE,
 -                        &xsave->i387.mxcsr, &kbuf, &offset_start, &count);
 +              copy_part(&to, &last, off_mxcsr,
 +                        MXCSR_AND_FLAGS_SIZE, &xsave->i387.mxcsr);
        if (header.xfeatures & XFEATURE_MASK_FP)
 -              copy_part(offsetof(struct fxregs_state, st_space), 128,
 -                        &xsave->i387.st_space, &kbuf, &offset_start, &count);
 +              copy_part(&to, &last, offsetof(struct fxregs_state, st_space),
 +                        128, &xsave->i387.st_space);
        if (header.xfeatures & XFEATURE_MASK_SSE)
 -              copy_part(xstate_offsets[XFEATURE_SSE], 256,
 -                        &xsave->i387.xmm_space, &kbuf, &offset_start, &count);
 +              copy_part(&to, &last, xstate_offsets[XFEATURE_SSE],
 +                        256, &xsave->i387.xmm_space);
        /*
         * Fill xsave->i387.sw_reserved value for ptrace frame:
         */
 -      copy_part(offsetof(struct fxregs_state, sw_reserved), 48,
 -                xstate_fx_sw_bytes, &kbuf, &offset_start, &count);
 +      copy_part(&to, &last, offsetof(struct fxregs_state, sw_reserved),
 +                48, xstate_fx_sw_bytes);
        /*
         * Copy xregs_state->header:
         */
 -      copy_part(offsetof(struct xregs_state, header), sizeof(header),
 -                &header, &kbuf, &offset_start, &count);
 +      copy_part(&to, &last, offsetof(struct xregs_state, header),
 +                sizeof(header), &header);
  
        for (i = FIRST_EXTENDED_XFEATURE; i < XFEATURE_MAX; i++) {
                /*
                if ((header.xfeatures >> i) & 1) {
                        void *src = __raw_xsave_addr(xsave, i);
  
 -                      copy_part(xstate_offsets[i], xstate_sizes[i],
 -                                src, &kbuf, &offset_start, &count);
 +                      copy_part(&to, &last, xstate_offsets[i],
 +                                xstate_sizes[i], src);
                }
  
        }
 -      fill_gap(size_total, &kbuf, &offset_start, &count);
 -
 -      return 0;
 -}
 -
 -static inline int
 -__copy_xstate_to_user(void __user *ubuf, const void *data, unsigned int offset, unsigned int size, unsigned int size_total)
 -{
 -      if (!size)
 -              return 0;
 -
 -      if (offset < size_total) {
 -              unsigned int copy = min(size, size_total - offset);
 -
 -              if (__copy_to_user(ubuf + offset, data, copy))
 -                      return -EFAULT;
 -      }
 -      return 0;
 -}
 -
 -/*
 - * Convert from kernel XSAVES compacted format to standard format and copy
 - * to a user-space buffer. It supports partial copy but pos always starts from
 - * zero. This is called from xstateregs_get() and there we check the CPU
 - * has XSAVES.
 - */
 -int copy_xstate_to_user(void __user *ubuf, struct xregs_state *xsave, unsigned int offset_start, unsigned int size_total)
 -{
 -      unsigned int offset, size;
 -      int ret, i;
 -      struct xstate_header header;
 -
 -      /*
 -       * Currently copy_regset_to_user() starts from pos 0:
 -       */
 -      if (unlikely(offset_start != 0))
 -              return -EFAULT;
 -
 -      /*
 -       * The destination is a ptrace buffer; we put in only user xstates:
 -       */
 -      memset(&header, 0, sizeof(header));
 -      header.xfeatures = xsave->header.xfeatures;
 -      header.xfeatures &= xfeatures_mask_user();
 -
 -      /*
 -       * Copy xregs_state->header:
 -       */
 -      offset = offsetof(struct xregs_state, header);
 -      size = sizeof(header);
 -
 -      ret = __copy_xstate_to_user(ubuf, &header, offset, size, size_total);
 -      if (ret)
 -              return ret;
 -
 -      for (i = 0; i < XFEATURE_MAX; i++) {
 -              /*
 -               * Copy only in-use xstates:
 -               */
 -              if ((header.xfeatures >> i) & 1) {
 -                      void *src = __raw_xsave_addr(xsave, i);
 -
 -                      offset = xstate_offsets[i];
 -                      size = xstate_sizes[i];
 -
 -                      /* The next component has to fit fully into the output buffer: */
 -                      if (offset + size > size_total)
 -                              break;
 -
 -                      ret = __copy_xstate_to_user(ubuf, src, offset, size, size_total);
 -                      if (ret)
 -                              return ret;
 -              }
 -
 -      }
 -
 -      if (xfeatures_mxcsr_quirk(header.xfeatures)) {
 -              offset = offsetof(struct fxregs_state, mxcsr);
 -              size = MXCSR_AND_FLAGS_SIZE;
 -              __copy_xstate_to_user(ubuf, &xsave->i387.mxcsr, offset, size, size_total);
 -      }
 -
 -      /*
 -       * Fill xsave->i387.sw_reserved value for ptrace frame:
 -       */
 -      offset = offsetof(struct fxregs_state, sw_reserved);
 -      size = sizeof(xstate_fx_sw_bytes);
 -
 -      ret = __copy_xstate_to_user(ubuf, xstate_fx_sw_bytes, offset, size, size_total);
 -      if (ret)
 -              return ret;
 -
 -      return 0;
 +      fill_gap(&to, &last, size);
  }
  
  /*
index 46c72f2ec32fa4ad1dc240e93e01f23d4f2b1066,a654a9b4b77c072e3ab06a82264c6b1c3eed1714..6555a857a1e6eade008266329497d9ce48ec651a
@@@ -7,7 -7,6 +7,7 @@@
   */
  
  #include <linux/kernel.h>
 +#include <linux/thread_info.h>
  
  #include <asm/apic.h>
  #include <asm/cpu_device_id.h>
@@@ -134,10 -133,15 +134,15 @@@ static const struct freq_desc freq_desc
        .mask = 0x0f,
  };
  
- /* 24 MHz crystal? : 24 * 13 / 4 = 78 MHz */
+ /*
+  * 24 MHz crystal? : 24 * 13 / 4 = 78 MHz
+  * Frequency step for Lightning Mountain SoC is fixed to 78 MHz,
+  * so all the frequency entries are 78000.
+  */
  static const struct freq_desc freq_desc_lgm = {
        .use_msr_plat = true,
-       .freqs = { 78000, 78000, 78000, 78000, 78000, 78000, 78000, 78000 },
+       .freqs = { 78000, 78000, 78000, 78000, 78000, 78000, 78000, 78000,
+                  78000, 78000, 78000, 78000, 78000, 78000, 78000, 78000 },
        .mask = 0x0f,
  };
  
index 183ac60e59901291c827c43fc4c5c93c0151a08e,d24b43a4451a962e5309bbb60562573608197938..95ea17a9d20cb723ea06b65104b2a9110dace921
@@@ -32,9 -32,9 +32,9 @@@ KCOV_INSTRUMENT := 
  # make up the standalone purgatory.ro
  
  PURGATORY_CFLAGS_REMOVE := -mcmodel=kernel
- PURGATORY_CFLAGS := -mcmodel=large -ffreestanding -fno-zero-initialized-in-bss
+ PURGATORY_CFLAGS := -mcmodel=large -ffreestanding -fno-zero-initialized-in-bss -g0
  PURGATORY_CFLAGS += $(DISABLE_STACKLEAK_PLUGIN) -DDISABLE_BRANCH_PROFILING
 -PURGATORY_CFLAGS += $(call cc-option,-fno-stack-protector)
 +PURGATORY_CFLAGS += -fno-stack-protector
  
  # Default KBUILD_CFLAGS can have -pg option set when FTRACE is enabled. That
  # in turn leaves some undefined symbols like __fentry__ in purgatory and not
@@@ -64,6 -64,9 +64,9 @@@ CFLAGS_sha256.o                       += $(PURGATORY_CFLAGS
  CFLAGS_REMOVE_string.o                += $(PURGATORY_CFLAGS_REMOVE)
  CFLAGS_string.o                       += $(PURGATORY_CFLAGS)
  
+ AFLAGS_REMOVE_setup-x86_$(BITS).o     += -Wa,-gdwarf-2
+ AFLAGS_REMOVE_entry64.o                       += -Wa,-gdwarf-2
  $(obj)/purgatory.ro: $(PURGATORY_OBJS) FORCE
                $(call if_changed,ld)
  
diff --combined kernel/kexec_file.c
index 78c0837bfd7bdbbf753f05323f5a4332623cd50a,3f7867c1820f9f0e06a884dc075ab420111163c2..ca40bef75a6169c5a737be2c5857346c22a9e38e
@@@ -635,19 -635,6 +635,19 @@@ int kexec_locate_mem_hole(struct kexec_
        return ret == 1 ? 0 : -EADDRNOTAVAIL;
  }
  
 +/**
 + * arch_kexec_locate_mem_hole - Find free memory to place the segments.
 + * @kbuf:                       Parameters for the memory search.
 + *
 + * On success, kbuf->mem will have the start address of the memory region found.
 + *
 + * Return: 0 on success, negative errno on error.
 + */
 +int __weak arch_kexec_locate_mem_hole(struct kexec_buf *kbuf)
 +{
 +      return kexec_locate_mem_hole(kbuf);
 +}
 +
  /**
   * kexec_add_buffer - place a buffer in a kexec segment
   * @kbuf:     Buffer contents and memory parameters.
   */
  int kexec_add_buffer(struct kexec_buf *kbuf)
  {
 -
        struct kexec_segment *ksegment;
        int ret;
  
        kbuf->buf_align = max(kbuf->buf_align, PAGE_SIZE);
  
        /* Walk the RAM ranges and allocate a suitable range for the buffer */
 -      ret = kexec_locate_mem_hole(kbuf);
 +      ret = arch_kexec_locate_mem_hole(kbuf);
        if (ret)
                return ret;
  
@@@ -1169,24 -1157,26 +1169,26 @@@ int crash_exclude_mem_range(struct cras
                            unsigned long long mstart, unsigned long long mend)
  {
        int i, j;
-       unsigned long long start, end;
+       unsigned long long start, end, p_start, p_end;
        struct crash_mem_range temp_range = {0, 0};
  
        for (i = 0; i < mem->nr_ranges; i++) {
                start = mem->ranges[i].start;
                end = mem->ranges[i].end;
+               p_start = mstart;
+               p_end = mend;
  
                if (mstart > end || mend < start)
                        continue;
  
                /* Truncate any area outside of range */
                if (mstart < start)
-                       mstart = start;
+                       p_start = start;
                if (mend > end)
-                       mend = end;
+                       p_end = end;
  
                /* Found completely overlapping range */
-               if (mstart == start && mend == end) {
+               if (p_start == start && p_end == end) {
                        mem->ranges[i].start = 0;
                        mem->ranges[i].end = 0;
                        if (i < mem->nr_ranges - 1) {
                                        mem->ranges[j].end =
                                                        mem->ranges[j+1].end;
                                }
+                               /*
+                                * Continue to check if there are another overlapping ranges
+                                * from the current position because of shifting the above
+                                * mem ranges.
+                                */
+                               i--;
+                               mem->nr_ranges--;
+                               continue;
                        }
                        mem->nr_ranges--;
                        return 0;
                }
  
-               if (mstart > start && mend < end) {
+               if (p_start > start && p_end < end) {
                        /* Split original range */
-                       mem->ranges[i].end = mstart - 1;
-                       temp_range.start = mend + 1;
+                       mem->ranges[i].end = p_start - 1;
+                       temp_range.start = p_end + 1;
                        temp_range.end = end;
-               } else if (mstart != start)
-                       mem->ranges[i].end = mstart - 1;
+               } else if (p_start != start)
+                       mem->ranges[i].end = p_start - 1;
                else
-                       mem->ranges[i].start = mend + 1;
+                       mem->ranges[i].start = p_end + 1;
                break;
        }
  
@@@ -1247,7 -1246,7 +1258,7 @@@ int crash_prepare_elf64_headers(struct 
        unsigned long long notes_addr;
        unsigned long mstart, mend;
  
-       /* extra phdr for vmcoreinfo elf note */
+       /* extra phdr for vmcoreinfo ELF note */
        nr_phdr = nr_cpus + 1;
        nr_phdr += mem->nr_ranges;
  
         * kexec-tools creates an extra PT_LOAD phdr for kernel text mapping
         * area (for example, ffffffff80000000 - ffffffffa0000000 on x86_64).
         * I think this is required by tools like gdb. So same physical
-        * memory will be mapped in two elf headers. One will contain kernel
+        * memory will be mapped in two ELF headers. One will contain kernel
         * text virtual addresses and other will have __va(physical) addresses.
         */
  
        ehdr->e_ehsize = sizeof(Elf64_Ehdr);
        ehdr->e_phentsize = sizeof(Elf64_Phdr);
  
-       /* Prepare one phdr of type PT_NOTE for each present cpu */
+       /* Prepare one phdr of type PT_NOTE for each present CPU */
        for_each_present_cpu(cpu) {
                phdr->p_type = PT_NOTE;
                notes_addr = per_cpu_ptr_to_phys(per_cpu_ptr(crash_notes, cpu));
                phdr->p_filesz = phdr->p_memsz = mend - mstart + 1;
                phdr->p_align = 0;
                ehdr->e_phnum++;
-               phdr++;
-               pr_debug("Crash PT_LOAD elf header. phdr=%p vaddr=0x%llx, paddr=0x%llx, sz=0x%llx e_phnum=%d p_offset=0x%llx\n",
+               pr_debug("Crash PT_LOAD ELF header. phdr=%p vaddr=0x%llx, paddr=0x%llx, sz=0x%llx e_phnum=%d p_offset=0x%llx\n",
                        phdr, phdr->p_vaddr, phdr->p_paddr, phdr->p_filesz,
                        ehdr->e_phnum, phdr->p_offset);
+               phdr++;
        }
  
        *addr = buf;
This page took 0.082534 seconds and 4 git commands to generate.