]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Merge tag 'v3.10' into next
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>
Mon, 1 Jul 2013 07:57:25 +0000 (17:57 +1000)
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>
Mon, 1 Jul 2013 07:57:25 +0000 (17:57 +1000)
Merge 3.10 in order to get some of the last minute powerpc
changes, resolve conflicts and add additional fixes on top
of them.

1  2 
MAINTAINERS
arch/powerpc/include/asm/exception-64s.h
arch/powerpc/kernel/eeh_cache.c
arch/powerpc/kernel/exceptions-64s.S
arch/powerpc/kernel/irq.c
arch/powerpc/kernel/process.c
arch/powerpc/kernel/traps.c
arch/powerpc/mm/hugetlbpage.c
arch/sparc/mm/tlb.c

diff --combined MAINTAINERS
index ebeceeb9dfab4667a5855167133ee8c14c304c9f,ad7e322ad17b8bb985c73617407792fdc92eb33d..b888b1a4d247c5564e2cbb132a692078ca5e6f4f
@@@ -3103,13 -3103,6 +3103,13 @@@ M:    Maxim Levitsky <maximlevitsky@gmail.
  S:    Maintained
  F:    drivers/media/rc/ene_ir.*
  
 +ENHANCED ERROR HANDLING (EEH)
 +M:    Gavin Shan <shangw@linux.vnet.ibm.com>
 +L:    linuxppc-dev@lists.ozlabs.org
 +S:    Supported
 +F:    Documentation/powerpc/eeh-pci-error-recovery.txt
 +F:    arch/powerpc/kernel/eeh*.c
 +
  EPSON S1D13XXX FRAMEBUFFER DRIVER
  M:    Kristoffer Ericson <kristoffer.ericson@gmail.com>
  S:    Maintained
@@@ -3227,7 -3220,7 +3227,7 @@@ F:      lib/fault-inject.
  
  FCOE SUBSYSTEM (libfc, libfcoe, fcoe)
  M:    Robert Love <robert.w.love@intel.com>
- L:    devel@open-fcoe.org
+ L:    fcoe-devel@open-fcoe.org
  W:    www.Open-FCoE.org
  S:    Supported
  F:    drivers/scsi/libfc/
@@@ -6156,6 -6149,7 +6156,6 @@@ M:      Linas Vepstas <linasvepstas@gmail.co
  L:    linux-pci@vger.kernel.org
  S:    Supported
  F:    Documentation/PCI/pci-error-recovery.txt
 -F:    Documentation/powerpc/eeh-pci-error-recovery.txt
  
  PCI SUBSYSTEM
  M:    Bjorn Helgaas <bhelgaas@google.com>
index 484cb094ad42ddfeed906838c6cc93742504adb0,46793b58a761d549d7bf69814530c128352f26a5..07ca627e52c0b25ed45fb61128b3dc2210a4f541
@@@ -358,12 -358,12 +358,12 @@@ label##_relon_pSeries:                                  
        /* No guest interrupts come through here */     \
        SET_SCRATCH0(r13);              /* save r13 */  \
        EXCEPTION_RELON_PROLOG_PSERIES(PACA_EXGEN, label##_common, \
 -                                     EXC_STD, KVMTEST_PR, vec)
 +                                     EXC_STD, NOTEST, vec)
  
  #define STD_RELON_EXCEPTION_PSERIES_OOL(vec, label)           \
        .globl label##_relon_pSeries;                           \
  label##_relon_pSeries:                                                \
 -      EXCEPTION_PROLOG_1(PACA_EXGEN, KVMTEST_PR, vec);        \
 +      EXCEPTION_PROLOG_1(PACA_EXGEN, NOTEST, vec);            \
        EXCEPTION_RELON_PROLOG_PSERIES_1(label##_common, EXC_STD)
  
  #define STD_RELON_EXCEPTION_HV(loc, vec, label)               \
@@@ -374,12 -374,12 +374,12 @@@ label##_relon_hv:                                       
        /* No guest interrupts come through here */     \
        SET_SCRATCH0(r13);      /* save r13 */          \
        EXCEPTION_RELON_PROLOG_PSERIES(PACA_EXGEN, label##_common, \
 -                                     EXC_HV, KVMTEST, vec)
 +                                     EXC_HV, NOTEST, vec)
  
  #define STD_RELON_EXCEPTION_HV_OOL(vec, label)                        \
        .globl label##_relon_hv;                                \
  label##_relon_hv:                                             \
 -      EXCEPTION_PROLOG_1(PACA_EXGEN, KVMTEST, vec);           \
 +      EXCEPTION_PROLOG_1(PACA_EXGEN, NOTEST, vec);            \
        EXCEPTION_RELON_PROLOG_PSERIES_1(label##_common, EXC_HV)
  
  /* This associate vector numbers with bits in paca->irq_happened */
@@@ -513,7 -513,7 +513,7 @@@ label##_common:                                                    
   */
  #define STD_EXCEPTION_COMMON_ASYNC(trap, label, hdlr)           \
        EXCEPTION_COMMON(trap, label, hdlr, ret_from_except_lite, \
-                        FINISH_NAP;RUNLATCH_ON;DISABLE_INTS)
+                        FINISH_NAP;DISABLE_INTS;RUNLATCH_ON)
  
  /*
   * When the idle code in power4_idle puts the CPU into NAP mode,
index ea9a94cc97d231ec6aa529769f6547ebbbf01130,5ce3ba7ad1372a6de232692e23b3c411bc1ed33f..f9ac1232a746c595d696ef7b66469a093070c877
@@@ -194,7 -194,7 +194,7 @@@ static void __eeh_addr_cache_insert_dev
        }
  
        /* Skip any devices for which EEH is not enabled. */
 -      if (!edev->pe) {
 +      if (!eeh_probe_mode_dev() && !edev->pe) {
  #ifdef DEBUG
                pr_info("PCI: skip building address cache for=%s - %s\n",
                        pci_name(dev), dn->full_name);
@@@ -285,7 -285,7 +285,7 @@@ void eeh_addr_cache_rmv_dev(struct pci_
   * Must be run late in boot process, after the pci controllers
   * have been scanned for devices (after all device resources are known).
   */
 -void __init eeh_addr_cache_build(void)
 +void eeh_addr_cache_build(void)
  {
        struct device_node *dn;
        struct eeh_dev *edev;
        spin_lock_init(&pci_io_addr_cache_root.piar_lock);
  
        for_each_pci_dev(dev) {
-               eeh_addr_cache_insert_dev(dev);
                dn = pci_device_to_OF_node(dev);
                if (!dn)
                        continue;
                dev->dev.archdata.edev = edev;
                edev->pdev = dev;
  
+               eeh_addr_cache_insert_dev(dev);
                eeh_sysfs_add_device(dev);
        }
  
        eeh_addr_cache_print(&pci_io_addr_cache_root);
  #endif
  }
 -
index 359d949f4a4be0898fef50948f0c7c972d4c8b2c,40e4a17c8ba0f249e2b65d85d4014fe7aa47f7a7..4e00d223b2e30924dba5e82370d5bae09e7b56dc
@@@ -341,17 -341,10 +341,17 @@@ vsx_unavailable_pSeries_1
        EXCEPTION_PROLOG_0(PACA_EXGEN)
        b       vsx_unavailable_pSeries
  
 +facility_unavailable_trampoline:
        . = 0xf60
        SET_SCRATCH0(r13)
        EXCEPTION_PROLOG_0(PACA_EXGEN)
 -      b       tm_unavailable_pSeries
 +      b       facility_unavailable_pSeries
 +
 +hv_facility_unavailable_trampoline:
 +      . = 0xf80
 +      SET_SCRATCH0(r13)
 +      EXCEPTION_PROLOG_0(PACA_EXGEN)
 +      b       facility_unavailable_hv
  
  #ifdef CONFIG_CBE_RAS
        STD_EXCEPTION_HV(0x1200, 0x1202, cbe_system_error)
@@@ -529,10 -522,8 +529,10 @@@ denorm_done
        KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0xf20)
        STD_EXCEPTION_PSERIES_OOL(0xf40, vsx_unavailable)
        KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0xf40)
 -      STD_EXCEPTION_PSERIES_OOL(0xf60, tm_unavailable)
 +      STD_EXCEPTION_PSERIES_OOL(0xf60, facility_unavailable)
        KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0xf60)
 +      STD_EXCEPTION_HV_OOL(0xf82, facility_unavailable)
 +      KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xf82)
  
  /*
   * An interrupt came in while soft-disabled. We set paca->irq_happened, then:
@@@ -692,7 -683,7 +692,7 @@@ machine_check_common
        STD_EXCEPTION_COMMON(0xb00, trap_0b, .unknown_exception)
        STD_EXCEPTION_COMMON(0xd00, single_step, .single_step_exception)
        STD_EXCEPTION_COMMON(0xe00, trap_0e, .unknown_exception)
-       STD_EXCEPTION_COMMON(0xe40, emulation_assist, .program_check_exception)
+       STD_EXCEPTION_COMMON(0xe40, emulation_assist, .emulation_assist_interrupt)
        STD_EXCEPTION_COMMON(0xe60, hmi_exception, .unknown_exception)
  #ifdef CONFIG_PPC_DOORBELL
        STD_EXCEPTION_COMMON_ASYNC(0xe80, h_doorbell, .doorbell_exception)
@@@ -802,10 -793,14 +802,10 @@@ system_call_relon_pSeries
        STD_RELON_EXCEPTION_PSERIES(0x4d00, 0xd00, single_step)
  
        . = 0x4e00
 -      SET_SCRATCH0(r13)
 -      EXCEPTION_PROLOG_0(PACA_EXGEN)
 -      b       h_data_storage_relon_hv
 +      b       .       /* Can't happen, see v2.07 Book III-S section 6.5 */
  
        . = 0x4e20
 -      SET_SCRATCH0(r13)
 -      EXCEPTION_PROLOG_0(PACA_EXGEN)
 -      b       h_instr_storage_relon_hv
 +      b       .       /* Can't happen, see v2.07 Book III-S section 6.5 */
  
        . = 0x4e40
        SET_SCRATCH0(r13)
        b       emulation_assist_relon_hv
  
        . = 0x4e60
 -      SET_SCRATCH0(r13)
 -      EXCEPTION_PROLOG_0(PACA_EXGEN)
 -      b       hmi_exception_relon_hv
 +      b       .       /* Can't happen, see v2.07 Book III-S section 6.5 */
  
        . = 0x4e80
        SET_SCRATCH0(r13)
@@@ -838,17 -835,11 +838,17 @@@ vsx_unavailable_relon_pSeries_1
        EXCEPTION_PROLOG_0(PACA_EXGEN)
        b       vsx_unavailable_relon_pSeries
  
 -tm_unavailable_relon_pSeries_1:
 +facility_unavailable_relon_trampoline:
        . = 0x4f60
        SET_SCRATCH0(r13)
        EXCEPTION_PROLOG_0(PACA_EXGEN)
 -      b       tm_unavailable_relon_pSeries
 +      b       facility_unavailable_relon_pSeries
 +
 +hv_facility_unavailable_relon_trampoline:
 +      . = 0x4f80
 +      SET_SCRATCH0(r13)
 +      EXCEPTION_PROLOG_0(PACA_EXGEN)
 +      b       facility_unavailable_relon_hv
  
        STD_RELON_EXCEPTION_PSERIES(0x5300, 0x1300, instruction_breakpoint)
  #ifdef CONFIG_PPC_DENORMALISATION
@@@ -1174,21 -1165,36 +1174,21 @@@ END_FTR_SECTION_IFSET(CPU_FTR_VSX
        bl      .vsx_unavailable_exception
        b       .ret_from_except
  
 -      .align  7
 -      .globl tm_unavailable_common
 -tm_unavailable_common:
 -      EXCEPTION_PROLOG_COMMON(0xf60, PACA_EXGEN)
 -      bl      .save_nvgprs
 -      DISABLE_INTS
 -      addi    r3,r1,STACK_FRAME_OVERHEAD
 -      bl      .tm_unavailable_exception
 -      b       .ret_from_except
 +      STD_EXCEPTION_COMMON(0xf60, facility_unavailable, .facility_unavailable_exception)
  
        .align  7
        .globl  __end_handlers
  __end_handlers:
  
        /* Equivalents to the above handlers for relocation-on interrupt vectors */
 -      STD_RELON_EXCEPTION_HV_OOL(0xe00, h_data_storage)
 -      KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe00)
 -      STD_RELON_EXCEPTION_HV_OOL(0xe20, h_instr_storage)
 -      KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe20)
        STD_RELON_EXCEPTION_HV_OOL(0xe40, emulation_assist)
 -      KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe40)
 -      STD_RELON_EXCEPTION_HV_OOL(0xe60, hmi_exception)
 -      KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe60)
        MASKABLE_RELON_EXCEPTION_HV_OOL(0xe80, h_doorbell)
 -      KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe80)
  
        STD_RELON_EXCEPTION_PSERIES_OOL(0xf00, performance_monitor)
        STD_RELON_EXCEPTION_PSERIES_OOL(0xf20, altivec_unavailable)
        STD_RELON_EXCEPTION_PSERIES_OOL(0xf40, vsx_unavailable)
 -      STD_RELON_EXCEPTION_PSERIES_OOL(0xf60, tm_unavailable)
 +      STD_RELON_EXCEPTION_PSERIES_OOL(0xf60, facility_unavailable)
 +      STD_RELON_EXCEPTION_HV_OOL(0xf80, facility_unavailable)
  
  #if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV)
  /*
index 32fa52e8163fa67ba2e7c9209d264cbf0a06a61f,ea185e0b3cae5800145b0e3ee0388534369f3686..2e51cde616d2de1fc93cdb75547debab72cf66c2
@@@ -116,6 -116,8 +116,6 @@@ static inline notrace int decrementer_c
        u64 now = get_tb_or_rtc();
        u64 *next_tb = &__get_cpu_var(decrementers_next_tb);
   
 -      if (now >= *next_tb)
 -              set_dec(1);
        return now >= *next_tb;
  }
  
@@@ -160,7 -162,7 +160,7 @@@ notrace unsigned int __check_irq_replay
         * in case we also had a rollover while hard disabled
         */
        local_paca->irq_happened &= ~PACA_IRQ_DEC;
-       if (decrementer_check_overflow())
+       if ((happened & PACA_IRQ_DEC) || decrementer_check_overflow())
                return 0x900;
  
        /* Finally check if an external interrupt happened */
index f8a76e6207bd2490f3978a0b796ef857062043f7,076d1242507a7fdcf32c374b66b3b005eb4e0db9..c517dbe705fdd5fd5944ae693c04aaaf52510e85
@@@ -916,11 -916,7 +916,11 @@@ int arch_dup_task_struct(struct task_st
        flush_altivec_to_thread(src);
        flush_vsx_to_thread(src);
        flush_spe_to_thread(src);
 +
        *dst = *src;
 +
 +      clear_task_ebb(dst);
 +
        return 0;
  }
  
@@@ -1373,7 -1369,7 +1373,7 @@@ void show_stack(struct task_struct *tsk
  
  #ifdef CONFIG_PPC64
  /* Called with hard IRQs off */
- void __ppc64_runlatch_on(void)
+ void notrace __ppc64_runlatch_on(void)
  {
        struct thread_info *ti = current_thread_info();
        unsigned long ctrl;
  }
  
  /* Called with hard IRQs off */
- void __ppc64_runlatch_off(void)
+ void notrace __ppc64_runlatch_off(void)
  {
        struct thread_info *ti = current_thread_info();
        unsigned long ctrl;
index 4a87fcbe3ba9fcae0ff3fba300698928fe81146f,c0e5caf8ccc72c0f7624b1e7dc9c3f7ecfe4b242..bf33c22e38a40848221762497ca1a7b704a27f9f
@@@ -866,10 -866,6 +866,10 @@@ static int emulate_string_inst(struct p
                u8 val;
                u32 shift = 8 * (3 - (pos & 0x3));
  
 +              /* if process is 32-bit, clear upper 32 bits of EA */
 +              if ((regs->msr & MSR_64BIT) == 0)
 +                      EA &= 0xFFFFFFFF;
 +
                switch ((instword & PPC_INST_STRING_MASK)) {
                        case PPC_INST_LSWX:
                        case PPC_INST_LSWI:
@@@ -1129,17 -1125,7 +1129,17 @@@ void __kprobes program_check_exception(
         * ESR_DST (!?) or 0.  In the process of chasing this with the
         * hardware people - not sure if it can happen on any illegal
         * instruction or only on FP instructions, whether there is a
 -       * pattern to occurrences etc. -dgibson 31/Mar/2003 */
 +       * pattern to occurrences etc. -dgibson 31/Mar/2003
 +       */
 +
 +      /*
 +       * If we support a HW FPU, we need to ensure the FP state
 +       * if flushed into the thread_struct before attempting
 +       * emulation
 +       */
 +#ifdef CONFIG_PPC_FPU
 +      flush_fp_to_thread(current);
 +#endif
        switch (do_mathemu(regs)) {
        case 0:
                emulate_single_step(regs);
@@@ -1179,6 -1165,16 +1179,16 @@@ bail
        exception_exit(prev_state);
  }
  
+ /*
+  * This occurs when running in hypervisor mode on POWER6 or later
+  * and an illegal instruction is encountered.
+  */
+ void __kprobes emulation_assist_interrupt(struct pt_regs *regs)
+ {
+       regs->msr |= REASON_ILLEGAL;
+       program_check_exception(regs);
+ }
  void alignment_exception(struct pt_regs *regs)
  {
        enum ctx_state prev_state = exception_enter();
@@@ -1286,50 -1282,25 +1296,50 @@@ void vsx_unavailable_exception(struct p
        die("Unrecoverable VSX Unavailable Exception", regs, SIGABRT);
  }
  
 -void tm_unavailable_exception(struct pt_regs *regs)
 +void facility_unavailable_exception(struct pt_regs *regs)
  {
 +      static char *facility_strings[] = {
 +              "FPU",
 +              "VMX/VSX",
 +              "DSCR",
 +              "PMU SPRs",
 +              "BHRB",
 +              "TM",
 +              "AT",
 +              "EBB",
 +              "TAR",
 +      };
 +      char *facility, *prefix;
 +      u64 value;
 +
 +      if (regs->trap == 0xf60) {
 +              value = mfspr(SPRN_FSCR);
 +              prefix = "";
 +      } else {
 +              value = mfspr(SPRN_HFSCR);
 +              prefix = "Hypervisor ";
 +      }
 +
 +      value = value >> 56;
 +
        /* We restore the interrupt state now */
        if (!arch_irq_disabled_regs(regs))
                local_irq_enable();
  
 -      /* Currently we never expect a TMU exception.  Catch
 -       * this and kill the process!
 -       */
 -      printk(KERN_EMERG "Unexpected TM unavailable exception at %lx "
 -             "(msr %lx)\n",
 -             regs->nip, regs->msr);
 +      if (value < ARRAY_SIZE(facility_strings))
 +              facility = facility_strings[value];
 +      else
 +              facility = "unknown";
 +
 +      pr_err("%sFacility '%s' unavailable, exception at 0x%lx, MSR=%lx\n",
 +              prefix, facility, regs->nip, regs->msr);
  
        if (user_mode(regs)) {
                _exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
                return;
        }
  
 -      die("Unexpected TM unavailable exception", regs, SIGABRT);
 +      die("Unexpected facility unavailable exception", regs, SIGABRT);
  }
  
  #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
@@@ -1425,7 -1396,8 +1435,7 @@@ void performance_monitor_exception(stru
  void SoftwareEmulation(struct pt_regs *regs)
  {
        extern int do_mathemu(struct pt_regs *);
 -      extern int Soft_emulate_8xx(struct pt_regs *);
 -#if defined(CONFIG_MATH_EMULATION) || defined(CONFIG_8XX_MINIMAL_FPEMU)
 +#if defined(CONFIG_MATH_EMULATION)
        int errcode;
  #endif
  
                _exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
                return;
        }
 -
 -#elif defined(CONFIG_8XX_MINIMAL_FPEMU)
 -      errcode = Soft_emulate_8xx(regs);
 -      if (errcode >= 0)
 -              PPC_WARN_EMULATED(8xx, regs);
 -
 -      switch (errcode) {
 -      case 0:
 -              emulate_single_step(regs);
 -              return;
 -      case 1:
 -              _exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
 -              return;
 -      case -EFAULT:
 -              _exception(SIGSEGV, regs, SEGV_MAPERR, regs->nip);
 -              return;
 -      }
  #else
        _exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
  #endif
@@@ -1807,6 -1796,8 +1817,6 @@@ struct ppc_emulated ppc_emulated = 
        WARN_EMULATED_SETUP(unaligned),
  #ifdef CONFIG_MATH_EMULATION
        WARN_EMULATED_SETUP(math),
 -#elif defined(CONFIG_8XX_MINIMAL_FPEMU)
 -      WARN_EMULATED_SETUP(8xx),
  #endif
  #ifdef CONFIG_VSX
        WARN_EMULATED_SETUP(vsx),
index f2f01fd3ec68f8ff39269419f42b1fb3a4343fce,77fdd2cef33b5a2c18ac40c442645d9dc38365ad..5555778b94fcbe3e7e935310b9c5048079199f3b
@@@ -21,9 -21,6 +21,9 @@@
  #include <asm/pgalloc.h>
  #include <asm/tlb.h>
  #include <asm/setup.h>
 +#include <asm/hugetlb.h>
 +
 +#ifdef CONFIG_HUGETLB_PAGE
  
  #define PAGE_SHIFT_64K        16
  #define PAGE_SHIFT_16M        24
@@@ -103,9 -100,68 +103,9 @@@ int pgd_huge(pgd_t pgd
  }
  #endif
  
 -/*
 - * We have 4 cases for pgds and pmds:
 - * (1) invalid (all zeroes)
 - * (2) pointer to next table, as normal; bottom 6 bits == 0
 - * (3) leaf pte for huge page, bottom two bits != 00
 - * (4) hugepd pointer, bottom two bits == 00, next 4 bits indicate size of table
 - */
 -pte_t *find_linux_pte_or_hugepte(pgd_t *pgdir, unsigned long ea, unsigned *shift)
 -{
 -      pgd_t *pg;
 -      pud_t *pu;
 -      pmd_t *pm;
 -      pte_t *ret_pte;
 -      hugepd_t *hpdp = NULL;
 -      unsigned pdshift = PGDIR_SHIFT;
 -
 -      if (shift)
 -              *shift = 0;
 -
 -      pg = pgdir + pgd_index(ea);
 -
 -      if (pgd_huge(*pg)) {
 -              ret_pte = (pte_t *) pg;
 -              goto out;
 -      } else if (is_hugepd(pg))
 -              hpdp = (hugepd_t *)pg;
 -      else if (!pgd_none(*pg)) {
 -              pdshift = PUD_SHIFT;
 -              pu = pud_offset(pg, ea);
 -
 -              if (pud_huge(*pu)) {
 -                      ret_pte = (pte_t *) pu;
 -                      goto out;
 -              } else if (is_hugepd(pu))
 -                      hpdp = (hugepd_t *)pu;
 -              else if (!pud_none(*pu)) {
 -                      pdshift = PMD_SHIFT;
 -                      pm = pmd_offset(pu, ea);
 -
 -                      if (pmd_huge(*pm)) {
 -                              ret_pte = (pte_t *) pm;
 -                              goto out;
 -                      } else if (is_hugepd(pm))
 -                              hpdp = (hugepd_t *)pm;
 -                      else if (!pmd_none(*pm))
 -                              return pte_offset_kernel(pm, ea);
 -              }
 -      }
 -      if (!hpdp)
 -              return NULL;
 -
 -      ret_pte = hugepte_offset(hpdp, ea, pdshift);
 -      pdshift = hugepd_shift(*hpdp);
 -out:
 -      if (shift)
 -              *shift = pdshift;
 -      return ret_pte;
 -}
 -EXPORT_SYMBOL_GPL(find_linux_pte_or_hugepte);
 -
  pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
  {
 +      /* Only called for hugetlbfs pages, hence can ignore THP */
        return find_linux_pte_or_hugepte(mm->pgd, addr, NULL);
  }
  
@@@ -536,8 -592,14 +536,14 @@@ static void hugetlb_free_pmd_range(stru
        do {
                pmd = pmd_offset(pud, addr);
                next = pmd_addr_end(addr, end);
-               if (pmd_none_or_clear_bad(pmd))
+               if (!is_hugepd(pmd)) {
+                       /*
+                        * if it is not hugepd pointer, we should already find
+                        * it cleared.
+                        */
+                       WARN_ON(!pmd_none_or_clear_bad(pmd));
                        continue;
+               }
  #ifdef CONFIG_PPC_FSL_BOOK3E
                /*
                 * Increment next by the size of the huge mapping since
@@@ -674,14 -736,11 +680,14 @@@ follow_huge_addr(struct mm_struct *mm, 
        struct page *page;
        unsigned shift;
        unsigned long mask;
 -
 +      /*
 +       * Transparent hugepages are handled by generic code. We can skip them
 +       * here.
 +       */
        ptep = find_linux_pte_or_hugepte(mm->pgd, address, &shift);
  
        /* Verify it is a huge page else bail. */
 -      if (!ptep || !shift)
 +      if (!ptep || !shift || pmd_trans_huge(*(pmd_t *)ptep))
                return ERR_PTR(-EINVAL);
  
        mask = (1UL << shift) - 1;
@@@ -700,6 -759,69 +706,6 @@@ follow_huge_pmd(struct mm_struct *mm, u
        return NULL;
  }
  
 -int gup_hugepte(pte_t *ptep, unsigned long sz, unsigned long addr,
 -              unsigned long end, int write, struct page **pages, int *nr)
 -{
 -      unsigned long mask;
 -      unsigned long pte_end;
 -      struct page *head, *page, *tail;
 -      pte_t pte;
 -      int refs;
 -
 -      pte_end = (addr + sz) & ~(sz-1);
 -      if (pte_end < end)
 -              end = pte_end;
 -
 -      pte = *ptep;
 -      mask = _PAGE_PRESENT | _PAGE_USER;
 -      if (write)
 -              mask |= _PAGE_RW;
 -
 -      if ((pte_val(pte) & mask) != mask)
 -              return 0;
 -
 -      /* hugepages are never "special" */
 -      VM_BUG_ON(!pfn_valid(pte_pfn(pte)));
 -
 -      refs = 0;
 -      head = pte_page(pte);
 -
 -      page = head + ((addr & (sz-1)) >> PAGE_SHIFT);
 -      tail = page;
 -      do {
 -              VM_BUG_ON(compound_head(page) != head);
 -              pages[*nr] = page;
 -              (*nr)++;
 -              page++;
 -              refs++;
 -      } while (addr += PAGE_SIZE, addr != end);
 -
 -      if (!page_cache_add_speculative(head, refs)) {
 -              *nr -= refs;
 -              return 0;
 -      }
 -
 -      if (unlikely(pte_val(pte) != pte_val(*ptep))) {
 -              /* Could be optimized better */
 -              *nr -= refs;
 -              while (refs--)
 -                      put_page(head);
 -              return 0;
 -      }
 -
 -      /*
 -       * Any tail page need their mapcount reference taken before we
 -       * return.
 -       */
 -      while (refs--) {
 -              if (PageTail(tail))
 -                      get_huge_page_tail(tail);
 -              tail++;
 -      }
 -
 -      return 1;
 -}
 -
  static unsigned long hugepte_addr_end(unsigned long addr, unsigned long end,
                                      unsigned long sz)
  {
@@@ -916,168 -1038,3 +922,168 @@@ void flush_dcache_icache_hugepage(struc
                }
        }
  }
 +
 +#endif /* CONFIG_HUGETLB_PAGE */
 +
 +/*
 + * We have 4 cases for pgds and pmds:
 + * (1) invalid (all zeroes)
 + * (2) pointer to next table, as normal; bottom 6 bits == 0
 + * (3) leaf pte for huge page, bottom two bits != 00
 + * (4) hugepd pointer, bottom two bits == 00, next 4 bits indicate size of table
 + *
 + * So long as we atomically load page table pointers we are safe against teardown,
 + * we can follow the address down to the the page and take a ref on it.
 + */
 +
 +pte_t *find_linux_pte_or_hugepte(pgd_t *pgdir, unsigned long ea, unsigned *shift)
 +{
 +      pgd_t pgd, *pgdp;
 +      pud_t pud, *pudp;
 +      pmd_t pmd, *pmdp;
 +      pte_t *ret_pte;
 +      hugepd_t *hpdp = NULL;
 +      unsigned pdshift = PGDIR_SHIFT;
 +
 +      if (shift)
 +              *shift = 0;
 +
 +      pgdp = pgdir + pgd_index(ea);
 +      pgd  = ACCESS_ONCE(*pgdp);
 +      /*
 +       * Always operate on the local stack value. This make sure the
 +       * value don't get updated by a parallel THP split/collapse,
 +       * page fault or a page unmap. The return pte_t * is still not
 +       * stable. So should be checked there for above conditions.
 +       */
 +      if (pgd_none(pgd))
 +              return NULL;
 +      else if (pgd_huge(pgd)) {
 +              ret_pte = (pte_t *) pgdp;
 +              goto out;
 +      } else if (is_hugepd(&pgd))
 +              hpdp = (hugepd_t *)&pgd;
 +      else {
 +              /*
 +               * Even if we end up with an unmap, the pgtable will not
 +               * be freed, because we do an rcu free and here we are
 +               * irq disabled
 +               */
 +              pdshift = PUD_SHIFT;
 +              pudp = pud_offset(&pgd, ea);
 +              pud  = ACCESS_ONCE(*pudp);
 +
 +              if (pud_none(pud))
 +                      return NULL;
 +              else if (pud_huge(pud)) {
 +                      ret_pte = (pte_t *) pudp;
 +                      goto out;
 +              } else if (is_hugepd(&pud))
 +                      hpdp = (hugepd_t *)&pud;
 +              else {
 +                      pdshift = PMD_SHIFT;
 +                      pmdp = pmd_offset(&pud, ea);
 +                      pmd  = ACCESS_ONCE(*pmdp);
 +                      /*
 +                       * A hugepage collapse is captured by pmd_none, because
 +                       * it mark the pmd none and do a hpte invalidate.
 +                       *
 +                       * A hugepage split is captured by pmd_trans_splitting
 +                       * because we mark the pmd trans splitting and do a
 +                       * hpte invalidate
 +                       *
 +                       */
 +                      if (pmd_none(pmd) || pmd_trans_splitting(pmd))
 +                              return NULL;
 +
 +                      if (pmd_huge(pmd) || pmd_large(pmd)) {
 +                              ret_pte = (pte_t *) pmdp;
 +                              goto out;
 +                      } else if (is_hugepd(&pmd))
 +                              hpdp = (hugepd_t *)&pmd;
 +                      else
 +                              return pte_offset_kernel(&pmd, ea);
 +              }
 +      }
 +      if (!hpdp)
 +              return NULL;
 +
 +      ret_pte = hugepte_offset(hpdp, ea, pdshift);
 +      pdshift = hugepd_shift(*hpdp);
 +out:
 +      if (shift)
 +              *shift = pdshift;
 +      return ret_pte;
 +}
 +EXPORT_SYMBOL_GPL(find_linux_pte_or_hugepte);
 +
 +int gup_hugepte(pte_t *ptep, unsigned long sz, unsigned long addr,
 +              unsigned long end, int write, struct page **pages, int *nr)
 +{
 +      unsigned long mask;
 +      unsigned long pte_end;
 +      struct page *head, *page, *tail;
 +      pte_t pte;
 +      int refs;
 +
 +      pte_end = (addr + sz) & ~(sz-1);
 +      if (pte_end < end)
 +              end = pte_end;
 +
 +      pte = ACCESS_ONCE(*ptep);
 +      mask = _PAGE_PRESENT | _PAGE_USER;
 +      if (write)
 +              mask |= _PAGE_RW;
 +
 +      if ((pte_val(pte) & mask) != mask)
 +              return 0;
 +
 +#ifdef CONFIG_TRANSPARENT_HUGEPAGE
 +      /*
 +       * check for splitting here
 +       */
 +      if (pmd_trans_splitting(pte_pmd(pte)))
 +              return 0;
 +#endif
 +
 +      /* hugepages are never "special" */
 +      VM_BUG_ON(!pfn_valid(pte_pfn(pte)));
 +
 +      refs = 0;
 +      head = pte_page(pte);
 +
 +      page = head + ((addr & (sz-1)) >> PAGE_SHIFT);
 +      tail = page;
 +      do {
 +              VM_BUG_ON(compound_head(page) != head);
 +              pages[*nr] = page;
 +              (*nr)++;
 +              page++;
 +              refs++;
 +      } while (addr += PAGE_SIZE, addr != end);
 +
 +      if (!page_cache_add_speculative(head, refs)) {
 +              *nr -= refs;
 +              return 0;
 +      }
 +
 +      if (unlikely(pte_val(pte) != pte_val(*ptep))) {
 +              /* Could be optimized better */
 +              *nr -= refs;
 +              while (refs--)
 +                      put_page(head);
 +              return 0;
 +      }
 +
 +      /*
 +       * Any tail page need their mapcount reference taken before we
 +       * return.
 +       */
 +      while (refs--) {
 +              if (PageTail(tail))
 +                      get_huge_page_tail(tail);
 +              tail++;
 +      }
 +
 +      return 1;
 +}
diff --combined arch/sparc/mm/tlb.c
index f828dd33551c8e56bdd5f285ba1cab8d0c92f846,37e7bc4c95b373aad3c9dbac1f16fe172b205890..7a91f288c7081229a6c2d2a4a1385a9673c58fc5
@@@ -85,8 -85,8 +85,8 @@@ static void tlb_batch_add_one(struct mm
        }
  
        if (!tb->active) {
-               global_flush_tlb_page(mm, vaddr);
                flush_tsb_user_page(mm, vaddr);
+               global_flush_tlb_page(mm, vaddr);
                goto out;
        }
  
@@@ -188,8 -188,7 +188,8 @@@ void set_pmd_at(struct mm_struct *mm, u
        }
  }
  
 -void pgtable_trans_huge_deposit(struct mm_struct *mm, pgtable_t pgtable)
 +void pgtable_trans_huge_deposit(struct mm_struct *mm, pmd_t *pmdp,
 +                              pgtable_t pgtable)
  {
        struct list_head *lh = (struct list_head *) pgtable;
  
        mm->pmd_huge_pte = pgtable;
  }
  
 -pgtable_t pgtable_trans_huge_withdraw(struct mm_struct *mm)
 +pgtable_t pgtable_trans_huge_withdraw(struct mm_struct *mm, pmd_t *pmdp)
  {
        struct list_head *lh;
        pgtable_t pgtable;