Merge branch 'x86-vdso-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 2 Apr 2014 19:26:43 +0000 (12:26 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 2 Apr 2014 19:26:43 +0000 (12:26 -0700)
Pull x86 vdso changes from Peter Anvin:
 "This is the revamp of the 32-bit vdso and the associated cleanups.

  This adds timekeeping support to the 32-bit vdso that we already have
  in the 64-bit vdso.  Although 32-bit x86 is legacy, it is likely to
  remain in the embedded space for a very long time to come.

  This removes the traditional COMPAT_VDSO support; the configuration
  variable is reused for simply removing the 32-bit vdso, which will
  produce correct results but obviously suffer a performance penalty.
  Only one beta version of glibc was affected, but that version was
  unfortunately included in one OpenSUSE release.

  This is not the end of the vdso cleanups.  Stefani and Andy have
  agreed to continue work for the next kernel cycle; in fact Andy has
  already produced another set of cleanups that came too late for this
  cycle.

  An incidental, but arguably important, change is that this ensures
  that unused space in the VVAR page is properly zeroed.  It wasn't
  before, and would contain whatever garbage was left in memory by BIOS
  or the bootloader.  Since the VVAR page is accessible to user space
  this had the potential of information leaks"

* 'x86-vdso-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (23 commits)
  x86, vdso: Fix the symbol versions on the 32-bit vDSO
  x86, vdso, build: Don't rebuild 32-bit vdsos on every make
  x86, vdso: Actually discard the .discard sections
  x86, vdso: Fix size of get_unmapped_area()
  x86, vdso: Finish removing VDSO32_PRELINK
  x86, vdso: Move more vdso definitions into vdso.h
  x86: Load the 32-bit vdso in place, just like the 64-bit vdsos
  x86, vdso32: handle 32 bit vDSO larger one page
  x86, vdso32: Disable stack protector, adjust optimizations
  x86, vdso: Zero-pad the VVAR page
  x86, vdso: Add 32 bit VDSO time support for 64 bit kernel
  x86, vdso: Add 32 bit VDSO time support for 32 bit kernel
  x86, vdso: Patch alternatives in the 32-bit VDSO
  x86, vdso: Introduce VVAR marco for vdso32
  x86, vdso: Cleanup __vdso_gettimeofday()
  x86, vdso: Replace VVAR(vsyscall_gtod_data) by gtod macro
  x86, vdso: __vdso_clock_gettime() cleanup
  x86, vdso: Revamp vclock_gettime.c
  mm: Add new func _install_special_mapping() to mmap.c
  x86, vdso: Make vsyscall_gtod_data handling x86 generic
  ...

1  2 
Documentation/kernel-parameters.txt
arch/x86/Kconfig
arch/x86/include/asm/pgtable_types.h
arch/x86/kernel/hpet.c
arch/x86/kernel/tsc.c
arch/x86/vdso/Makefile
arch/x86/xen/mmu.c
include/linux/mm.h

index 121d5fcbd94aa200d219ef36d6445169fd24ebd7,86019750e15faa15bc5500738705e3dfcd865e10..2311dad7a57a52f9dcb928d32baf77210e46984a
@@@ -231,14 -231,6 +231,14 @@@ bytes respectively. Such letter suffixe
  
        acpi_no_auto_ssdt       [HW,ACPI] Disable automatic loading of SSDT
  
 +      acpica_no_return_repair [HW, ACPI]
 +                      Disable AML predefined validation mechanism
 +                      This mechanism can repair the evaluation result to make
 +                      the return objects more ACPI specification compliant.
 +                      This option is useful for developers to identify the
 +                      root cause of an AML interpreter issue when the issue
 +                      has something to do with the repair mechanism.
 +
        acpi_os_name=   [HW,ACPI] Tell ACPI BIOS the name of the OS
                        Format: To spoof as Windows 98: ="Microsoft Windows"
  
                        parameter will force ia64_sal_cache_flush to call
                        ia64_pal_cache_flush instead of SAL_CACHE_FLUSH.
  
 +      forcepae [X86-32]
 +                      Forcefully enable Physical Address Extension (PAE).
 +                      Many Pentium M systems disable PAE but may have a
 +                      functionally usable PAE implementation.
 +                      Warning: use of this parameter will taint the kernel
 +                      and may cause unknown problems.
 +
        ftrace=[tracer]
                        [FTRACE] will set and start the specified tracer
                        as early as possible in order to facilitate early
                        IOAPICs that may be present in the system.
  
        nokaslr         [X86]
 -                      Disable kernel base offset ASLR (Address Space
 -                      Layout Randomization) if built into the kernel.
 +                      Disable kernel and module base offset ASLR (Address
 +                      Space Layout Randomization) if built into the kernel.
  
        noautogroup     Disable scheduler automatic task group creation.
  
                                        of CONFIG_HIGHPTE.
  
        vdso=           [X86,SH]
-                       vdso=2: enable compat VDSO (default with COMPAT_VDSO)
-                       vdso=1: enable VDSO (default)
+                       On X86_32, this is an alias for vdso32=.  Otherwise:
+                       vdso=1: enable VDSO (the default)
                        vdso=0: disable VDSO mapping
  
-       vdso32=         [X86]
-                       vdso32=2: enable compat VDSO (default with COMPAT_VDSO)
-                       vdso32=1: enable 32-bit VDSO (default)
-                       vdso32=0: disable 32-bit VDSO mapping
+       vdso32=         [X86] Control the 32-bit vDSO
+                       vdso32=1: enable 32-bit VDSO
+                       vdso32=0 or vdso32=2: disable 32-bit VDSO
+                       See the help text for CONFIG_COMPAT_VDSO for more
+                       details.  If CONFIG_COMPAT_VDSO is set, the default is
+                       vdso32=0; otherwise, the default is vdso32=1.
+                       For compatibility with older kernels, vdso32=2 is an
+                       alias for vdso32=0.
+                       Try vdso32=0 if you encounter an error that says:
+                       dl_main: Assertion `(void *) ph->p_vaddr == _rtld_local._dl_sysinfo_dso' failed!
  
        vector=         [IA-64,SMP]
                        vector=percpu: enable percpu vector domain
diff --combined arch/x86/Kconfig
index 26237934ac87b861fa68d139cd46d3c2cc24d12f,ab3ebc8ba3b9003d949da1075b3fd5a7516b585f..ac04d9804391ada6df9946c86a989cec9777c7cf
@@@ -107,9 -107,9 +107,9 @@@ config X8
        select HAVE_ARCH_SOFT_DIRTY
        select CLOCKSOURCE_WATCHDOG
        select GENERIC_CLOCKEVENTS
-       select ARCH_CLOCKSOURCE_DATA if X86_64
+       select ARCH_CLOCKSOURCE_DATA
        select GENERIC_CLOCKEVENTS_BROADCAST if X86_64 || (X86_32 && X86_LOCAL_APIC)
-       select GENERIC_TIME_VSYSCALL if X86_64
+       select GENERIC_TIME_VSYSCALL
        select KTIME_SCALAR if X86_32
        select GENERIC_STRNCPY_FROM_USER
        select GENERIC_STRNLEN_USER
        select HAVE_DEBUG_STACKOVERFLOW
        select HAVE_IRQ_EXIT_ON_IRQ_STACK if X86_64
        select HAVE_CC_STACKPROTECTOR
 +      select GENERIC_CPU_AUTOPROBE
  
  config INSTRUCTION_DECODER
        def_bool y
@@@ -196,6 -195,9 +196,6 @@@ config ARCH_HAS_CPU_RELA
  config ARCH_HAS_CACHE_LINE_SIZE
        def_bool y
  
 -config ARCH_HAS_CPU_AUTOPROBE
 -      def_bool y
 -
  config HAVE_SETUP_PER_CPU_AREA
        def_bool y
  
@@@ -1583,20 -1585,6 +1583,20 @@@ config EFI_STU
  
          See Documentation/efi-stub.txt for more information.
  
 +config EFI_MIXED
 +      bool "EFI mixed-mode support"
 +      depends on EFI_STUB && X86_64
 +      ---help---
 +         Enabling this feature allows a 64-bit kernel to be booted
 +         on a 32-bit firmware, provided that your CPU supports 64-bit
 +         mode.
 +
 +         Note that it is not possible to boot a mixed-mode enabled
 +         kernel via the EFI boot stub - a bootloader that supports
 +         the EFI handover protocol must be used.
 +
 +         If unsure, say N.
 +
  config SECCOMP
        def_bool y
        prompt "Enable seccomp to safely compute untrusted bytecode"
@@@ -1848,17 -1836,29 +1848,29 @@@ config DEBUG_HOTPLUG_CPU
          If unsure, say N.
  
  config COMPAT_VDSO
-       def_bool y
-       prompt "Compat VDSO support"
+       def_bool n
+       prompt "Disable the 32-bit vDSO (needed for glibc 2.3.3)"
        depends on X86_32 || IA32_EMULATION
        ---help---
-         Map the 32-bit VDSO to the predictable old-style address too.
+         Certain buggy versions of glibc will crash if they are
+         presented with a 32-bit vDSO that is not mapped at the address
+         indicated in its segment table.
  
-         Say N here if you are running a sufficiently recent glibc
-         version (2.3.3 or later), to remove the high-mapped
-         VDSO mapping and to exclusively use the randomized VDSO.
+         The bug was introduced by f866314b89d56845f55e6f365e18b31ec978ec3a
+         and fixed by 3b3ddb4f7db98ec9e912ccdf54d35df4aa30e04a and
+         49ad572a70b8aeb91e57483a11dd1b77e31c4468.  Glibc 2.3.3 is
+         the only released version with the bug, but OpenSUSE 9
+         contains a buggy "glibc 2.3.2".
  
-         If unsure, say Y.
+         The symptom of the bug is that everything crashes on startup, saying:
+         dl_main: Assertion `(void *) ph->p_vaddr == _rtld_local._dl_sysinfo_dso' failed!
+         Saying Y here changes the default value of the vdso32 boot
+         option from 1 to 0, which turns off the 32-bit vDSO entirely.
+         This works around the glibc bug but hurts performance.
+         If unsure, say N: if you are compiling your own kernel, you
+         are unlikely to be using a buggy version of glibc.
  
  config CMDLINE_BOOL
        bool "Built-in kernel command line"
index 708f19fb4fc788ea0a51838e43ea8ea50c9699d0,757f9c40321bbceff8f770a67f788dcb24d09a86..eb3d449451336d64d2321adf3efbd0c6af4b45a4
  #ifdef CONFIG_X86_64
  #define __PAGE_KERNEL_IDENT_LARGE_EXEC        __PAGE_KERNEL_LARGE_EXEC
  #else
- /*
-  * For PDE_IDENT_ATTR include USER bit. As the PDE and PTE protection
-  * bits are combined, this will alow user to access the high address mapped
-  * VDSO in the presence of CONFIG_COMPAT_VDSO
-  */
  #define PTE_IDENT_ATTR         0x003          /* PRESENT+RW */
- #define PDE_IDENT_ATTR         0x067          /* PRESENT+RW+USER+DIRTY+ACCESSED */
+ #define PDE_IDENT_ATTR         0x063          /* PRESENT+RW+DIRTY+ACCESSED */
  #define PGD_IDENT_ATTR         0x001          /* PRESENT (no other attributes) */
  #endif
  
@@@ -382,13 -377,9 +377,13 @@@ static inline void update_page_count(in
   * as a pte too.
   */
  extern pte_t *lookup_address(unsigned long address, unsigned int *level);
 +extern pte_t *lookup_address_in_pgd(pgd_t *pgd, unsigned long address,
 +                                  unsigned int *level);
  extern phys_addr_t slow_virt_to_phys(void *__address);
  extern int kernel_map_pages_in_pgd(pgd_t *pgd, u64 pfn, unsigned long address,
                                   unsigned numpages, unsigned long page_flags);
 +void kernel_unmap_pages_in_pgd(pgd_t *root, unsigned long address,
 +                             unsigned numpages);
  #endif        /* !__ASSEMBLY__ */
  
  #endif /* _ASM_X86_PGTABLE_DEFS_H */
diff --combined arch/x86/kernel/hpet.c
index 014618dbaa7b4df9a925ffdae1d2975b07eca672,e4b86abd08ca116ae124ac3e418782b2e53a2590..93eed15a8fd41aeb4556117a932c9afa591893b3
@@@ -521,7 -521,7 +521,7 @@@ static int hpet_setup_irq(struct hpet_d
  {
  
        if (request_irq(dev->irq, hpet_interrupt_handler,
 -                      IRQF_TIMER | IRQF_DISABLED | IRQF_NOBALANCING,
 +                      IRQF_TIMER | IRQF_NOBALANCING,
                        dev->name, dev))
                return -1;
  
@@@ -699,7 -699,7 +699,7 @@@ static int hpet_cpuhp_notify(struct not
                /* FIXME: add schedule_work_on() */
                schedule_delayed_work_on(cpu, &work.work, 0);
                wait_for_completion(&work.complete);
 -              destroy_timer_on_stack(&work.work.timer);
 +              destroy_delayed_work_on_stack(&work.work);
                break;
        case CPU_DEAD:
                if (hdev) {
@@@ -752,9 -752,7 +752,7 @@@ static struct clocksource clocksource_h
        .mask           = HPET_MASK,
        .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
        .resume         = hpet_resume_counter,
- #ifdef CONFIG_X86_64
        .archdata       = { .vclock_mode = VCLOCK_HPET },
- #endif
  };
  
  static int hpet_clocksource_register(void)
diff --combined arch/x86/kernel/tsc.c
index 7a9296ab88340991436dfb91d6db70e7a17a529e,227dcfc0e5e781c6fa346cd1b1d9f212e9dbbe28..57e5ce126d5af8ca7fdeae2145aae58805852103
@@@ -914,7 -914,8 +914,7 @@@ static int time_cpufreq_notifier(struc
                tsc_khz_ref = tsc_khz;
        }
        if ((val == CPUFREQ_PRECHANGE  && freq->old < freq->new) ||
 -                      (val == CPUFREQ_POSTCHANGE && freq->old > freq->new) ||
 -                      (val == CPUFREQ_RESUMECHANGE)) {
 +                      (val == CPUFREQ_POSTCHANGE && freq->old > freq->new)) {
                *lpj = cpufreq_scale(loops_per_jiffy_ref, ref_freq, freq->new);
  
                tsc_khz = cpufreq_scale(tsc_khz_ref, ref_freq, freq->new);
@@@ -984,9 -985,7 +984,7 @@@ static struct clocksource clocksource_t
        .mask                   = CLOCKSOURCE_MASK(64),
        .flags                  = CLOCK_SOURCE_IS_CONTINUOUS |
                                  CLOCK_SOURCE_MUST_VERIFY,
- #ifdef CONFIG_X86_64
        .archdata               = { .vclock_mode = VCLOCK_TSC },
- #endif
  };
  
  void mark_tsc_unstable(char *reason)
diff --combined arch/x86/vdso/Makefile
index 9206ac7961a596798a1302b808bcf1fd6f119272,6e6361a0173680422069f0eda4232f351545243f..c580d1210ffe98866aa72582a5a56c81089362a8
@@@ -2,8 -2,6 +2,8 @@@
  # Building vDSO images for x86.
  #
  
 +KBUILD_CFLAGS += $(DISABLE_LTO)
 +
  VDSO64-$(CONFIG_X86_64)               := y
  VDSOX32-$(CONFIG_X86_X32_ABI) := y
  VDSO32-$(CONFIG_X86_32)               := y
@@@ -23,7 -21,8 +23,8 @@@ vobjs-$(VDSOX32-y) += $(vobjx32s-compat
  vobj64s := $(filter-out $(vobjx32s-compat),$(vobjs-y))
  
  # files to link into kernel
- obj-$(VDSO64-y)                       += vma.o vdso.o
+ obj-y                         += vma.o
+ obj-$(VDSO64-y)                       += vdso.o
  obj-$(VDSOX32-y)              += vdsox32.o
  obj-$(VDSO32-y)                       += vdso32.o vdso32-setup.o
  
@@@ -37,8 -36,7 +38,8 @@@ export CPPFLAGS_vdso.lds += -P -
  
  VDSO_LDFLAGS_vdso.lds = -m64 -Wl,-soname=linux-vdso.so.1 \
                        -Wl,--no-undefined \
 -                      -Wl,-z,max-page-size=4096 -Wl,-z,common-page-size=4096
 +                      -Wl,-z,max-page-size=4096 -Wl,-z,common-page-size=4096 \
 +                      $(DISABLE_LTO)
  
  $(obj)/vdso.o: $(src)/vdso.S $(obj)/vdso.so
  
@@@ -130,7 -128,7 +131,7 @@@ vdso32.so-$(VDSO32-y)              += sysente
  vdso32-images                 = $(vdso32.so-y:%=vdso32-%.so)
  
  CPPFLAGS_vdso32.lds = $(CPPFLAGS_vdso.lds)
 -VDSO_LDFLAGS_vdso32.lds = -m32 -Wl,-soname=linux-gate.so.1
 +VDSO_LDFLAGS_vdso32.lds = -m32 -Wl,-m,elf_i386 -Wl,-soname=linux-gate.so.1
  
  # This makes sure the $(obj) subdirectory exists even though vdso32/
  # is not a kbuild sub-make subdirectory.
@@@ -138,7 -136,7 +139,7 @@@ override obj-dirs = $(dir $(obj)) $(obj
  
  targets += vdso32/vdso32.lds
  targets += $(vdso32-images) $(vdso32-images:=.dbg)
- targets += vdso32/note.o $(vdso32.so-y:%=vdso32/%.o)
+ targets += vdso32/note.o vdso32/vclock_gettime.o $(vdso32.so-y:%=vdso32/%.o)
  
  extra-y       += $(vdso32-images)
  
@@@ -148,8 -146,19 +149,19 @@@ KBUILD_AFLAGS_32 := $(filter-out -m64,$
  $(vdso32-images:%=$(obj)/%.dbg): KBUILD_AFLAGS = $(KBUILD_AFLAGS_32)
  $(vdso32-images:%=$(obj)/%.dbg): asflags-$(CONFIG_X86_64) += -m32
  
+ KBUILD_CFLAGS_32 := $(filter-out -m64,$(KBUILD_CFLAGS))
+ KBUILD_CFLAGS_32 := $(filter-out -mcmodel=kernel,$(KBUILD_CFLAGS_32))
+ KBUILD_CFLAGS_32 := $(filter-out -fno-pic,$(KBUILD_CFLAGS_32))
+ KBUILD_CFLAGS_32 := $(filter-out -mfentry,$(KBUILD_CFLAGS_32))
+ KBUILD_CFLAGS_32 += -m32 -msoft-float -mregparm=0 -fpic
+ KBUILD_CFLAGS_32 += $(call cc-option, -fno-stack-protector)
+ KBUILD_CFLAGS_32 += $(call cc-option, -foptimize-sibling-calls)
+ KBUILD_CFLAGS_32 += -fno-omit-frame-pointer
+ $(vdso32-images:%=$(obj)/%.dbg): KBUILD_CFLAGS = $(KBUILD_CFLAGS_32)
  $(vdso32-images:%=$(obj)/%.dbg): $(obj)/vdso32-%.so.dbg: FORCE \
                                 $(obj)/vdso32/vdso32.lds \
+                                $(obj)/vdso32/vclock_gettime.o \
                                 $(obj)/vdso32/note.o \
                                 $(obj)/vdso32/%.o
        $(call if_changed,vdso)
@@@ -184,8 -193,7 +196,8 @@@ quiet_cmd_vdso = VDSO    $
                       -Wl,-T,$(filter %.lds,$^) $(filter %.o,$^) && \
                 sh $(srctree)/$(src)/checkundef.sh '$(NM)' '$@'
  
 -VDSO_LDFLAGS = -fPIC -shared $(call cc-ldoption, -Wl$(comma)--hash-style=sysv)
 +VDSO_LDFLAGS = -fPIC -shared $(call cc-ldoption, -Wl$(comma)--hash-style=sysv) \
 +              $(LTO_CFLAGS)
  GCOV_PROFILE := n
  
  #
diff --combined arch/x86/xen/mmu.c
index 2423ef04ffea596fd43eeb918f290003277fbb21,21c6a420e19a72f5cdfb2687d74ff624ea7d264e..86e02eabb640bd889c94ccb563181cd30690ceeb
@@@ -365,7 -365,7 +365,7 @@@ void xen_ptep_modify_prot_commit(struc
  /* Assume pteval_t is equivalent to all the other *val_t types. */
  static pteval_t pte_mfn_to_pfn(pteval_t val)
  {
 -      if (pteval_present(val)) {
 +      if (val & _PAGE_PRESENT) {
                unsigned long mfn = (val & PTE_PFN_MASK) >> PAGE_SHIFT;
                unsigned long pfn = mfn_to_pfn(mfn);
  
  
  static pteval_t pte_pfn_to_mfn(pteval_t val)
  {
 -      if (pteval_present(val)) {
 +      if (val & _PAGE_PRESENT) {
                unsigned long pfn = (val & PTE_PFN_MASK) >> PAGE_SHIFT;
                pteval_t flags = val & PTE_FLAGS_MASK;
                unsigned long mfn;
@@@ -2058,7 -2058,6 +2058,6 @@@ static void xen_set_fixmap(unsigned idx
        case FIX_RO_IDT:
  #ifdef CONFIG_X86_32
        case FIX_WP_TEST:
-       case FIX_VDSO:
  # ifdef CONFIG_HIGHMEM
        case FIX_KMAP_BEGIN ... FIX_KMAP_END:
  # endif
diff --combined include/linux/mm.h
index a0df4295e1717a23463d96d4f973a4330f2349ad,6c7fedf5db2b3359a84fbe3f29db9854683d8a7e..2eec61fe75c9629f0ff77d56f2ec307bcc15f735
@@@ -1487,15 -1487,9 +1487,15 @@@ static inline void pgtable_page_dtor(st
  
  #if USE_SPLIT_PMD_PTLOCKS
  
 +static struct page *pmd_to_page(pmd_t *pmd)
 +{
 +      unsigned long mask = ~(PTRS_PER_PMD * sizeof(pmd_t) - 1);
 +      return virt_to_page((void *)((unsigned long) pmd & mask));
 +}
 +
  static inline spinlock_t *pmd_lockptr(struct mm_struct *mm, pmd_t *pmd)
  {
 -      return ptlock_ptr(virt_to_page(pmd));
 +      return ptlock_ptr(pmd_to_page(pmd));
  }
  
  static inline bool pgtable_pmd_page_ctor(struct page *page)
@@@ -1514,7 -1508,7 +1514,7 @@@ static inline void pgtable_pmd_page_dto
        ptlock_free(page);
  }
  
 -#define pmd_huge_pte(mm, pmd) (virt_to_page(pmd)->pmd_huge_pte)
 +#define pmd_huge_pte(mm, pmd) (pmd_to_page(pmd)->pmd_huge_pte)
  
  #else
  
@@@ -1756,6 -1750,9 +1756,9 @@@ extern void set_mm_exe_file(struct mm_s
  extern struct file *get_mm_exe_file(struct mm_struct *mm);
  
  extern int may_expand_vm(struct mm_struct *mm, unsigned long npages);
+ extern struct vm_area_struct *_install_special_mapping(struct mm_struct *mm,
+                                  unsigned long addr, unsigned long len,
+                                  unsigned long flags, struct page **pages);
  extern int install_special_mapping(struct mm_struct *mm,
                                   unsigned long addr, unsigned long len,
                                   unsigned long flags, struct page **pages);