Merge tag 'arm64-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64...
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 28 Jun 2021 21:04:24 +0000 (14:04 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 28 Jun 2021 21:04:24 +0000 (14:04 -0700)
Pull arm64 updates from Will Deacon:
 "There's a reasonable amount here and the juicy details are all below.

  It's worth noting that the MTE/KASAN changes strayed outside of our
  usual directories due to core mm changes and some associated changes
  to some other architectures; Andrew asked for us to carry these [1]
  rather that take them via the -mm tree.

  Summary:

   - Optimise SVE switching for CPUs with 128-bit implementations.

   - Fix output format from SVE selftest.

   - Add support for versions v1.2 and 1.3 of the SMC calling
     convention.

   - Allow Pointer Authentication to be configured independently for
     kernel and userspace.

   - PMU driver cleanups for managing IRQ affinity and exposing event
     attributes via sysfs.

   - KASAN optimisations for both hardware tagging (MTE) and out-of-line
     software tagging implementations.

   - Relax frame record alignment requirements to facilitate 8-byte
     alignment with KASAN and Clang.

   - Cleanup of page-table definitions and removal of unused memory
     types.

   - Reduction of ARCH_DMA_MINALIGN back to 64 bytes.

   - Refactoring of our instruction decoding routines and addition of
     some missing encodings.

   - Move entry code moved into C and hardened against harmful compiler
     instrumentation.

   - Update booting requirements for the FEAT_HCX feature, added to v8.7
     of the architecture.

   - Fix resume from idle when pNMI is being used.

   - Additional CPU sanity checks for MTE and preparatory changes for
     systems where not all of the CPUs support 32-bit EL0.

   - Update our kernel string routines to the latest Cortex Strings
     implementation.

   - Big cleanup of our cache maintenance routines, which were
     confusingly named and inconsistent in their implementations.

   - Tweak linker flags so that GDB can understand vmlinux when using
     RELR relocations.

   - Boot path cleanups to enable early initialisation of per-cpu
     operations needed by KCSAN.

   - Non-critical fixes and miscellaneous cleanup"

* tag 'arm64-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux: (150 commits)
  arm64: tlb: fix the TTL value of tlb_get_level
  arm64: Restrict undef hook for cpufeature registers
  arm64/mm: Rename ARM64_SWAPPER_USES_SECTION_MAPS
  arm64: insn: avoid circular include dependency
  arm64: smp: Bump debugging information print down to KERN_DEBUG
  drivers/perf: fix the missed ida_simple_remove() in ddr_perf_probe()
  perf/arm-cmn: Fix invalid pointer when access dtc object sharing the same IRQ number
  arm64: suspend: Use cpuidle context helpers in cpu_suspend()
  PSCI: Use cpuidle context helpers in psci_cpu_suspend_enter()
  arm64: Convert cpu_do_idle() to using cpuidle context helpers
  arm64: Add cpuidle context save/restore helpers
  arm64: head: fix code comments in set_cpu_boot_mode_flag
  arm64: mm: drop unused __pa(__idmap_text_start)
  arm64: mm: fix the count comments in compute_indices
  arm64/mm: Fix ttbr0 values stored in struct thread_info for software-pan
  arm64: mm: Pass original fault address to handle_mm_fault()
  arm64/mm: Drop SECTION_[SHIFT|SIZE|MASK]
  arm64/mm: Use CONT_PMD_SHIFT for ARM64_MEMSTART_SHIFT
  arm64/mm: Drop SWAPPER_INIT_MAP_SIZE
  arm64: Conditionally configure PTR_AUTH key of the kernel.
  ...

1  2 
Makefile
arch/arm/include/asm/cpuidle.h
arch/arm64/include/asm/kvm_asm.h
arch/arm64/kernel/probes/kprobes.c
arch/arm64/kernel/process.c
arch/arm64/kernel/smp.c
arch/arm64/kvm/arm.c
arch/arm64/kvm/hyp/nvhe/setup.c
arch/arm64/mm/mmu.c
mm/page_alloc.c

diff --combined Makefile
+++ b/Makefile
@@@ -2,8 -2,8 +2,8 @@@
  VERSION = 5
  PATCHLEVEL = 13
  SUBLEVEL = 0
 -EXTRAVERSION = -rc3
 -NAME = Frozen Wasteland
 +EXTRAVERSION =
 +NAME = Opossums on Parade
  
  # *DOCUMENTATION*
  # To see a list of typical targets execute "make help"
@@@ -928,14 -928,6 +928,14 @@@ CC_FLAGS_LTO     += -fvisibility=hidde
  
  # Limit inlining across translation units to reduce binary size
  KBUILD_LDFLAGS += -mllvm -import-instr-limit=5
 +
 +# Check for frame size exceeding threshold during prolog/epilog insertion
 +# when using lld < 13.0.0.
 +ifneq ($(CONFIG_FRAME_WARN),0)
 +ifeq ($(shell test $(CONFIG_LLD_VERSION) -lt 130000; echo $$?),0)
 +KBUILD_LDFLAGS        += -plugin-opt=-warn-stack-size=$(CONFIG_FRAME_WARN)
 +endif
 +endif
  endif
  
  ifdef CONFIG_LTO
@@@ -1039,7 -1031,7 +1039,7 @@@ LDFLAGS_vmlinux += $(call ld-option, -X
  endif
  
  ifeq ($(CONFIG_RELR),y)
- LDFLAGS_vmlinux       += --pack-dyn-relocs=relr
+ LDFLAGS_vmlinux       += --pack-dyn-relocs=relr --use-android-relr-tags
  endif
  
  # We never want expected sections to be placed heuristically by the
@@@ -7,11 -7,9 +7,11 @@@
  #ifdef CONFIG_CPU_IDLE
  extern int arm_cpuidle_simple_enter(struct cpuidle_device *dev,
                struct cpuidle_driver *drv, int index);
 +#define __cpuidle_method_section __used __section("__cpuidle_method_of_table")
  #else
  static inline int arm_cpuidle_simple_enter(struct cpuidle_device *dev,
                struct cpuidle_driver *drv, int index) { return -ENODEV; }
 +#define __cpuidle_method_section __maybe_unused /* drop silently */
  #endif
  
  /* Common ARM WFI state */
@@@ -44,10 -42,16 +44,15 @@@ struct of_cpuidle_method 
  
  #define CPUIDLE_METHOD_OF_DECLARE(name, _method, _ops)                        \
        static const struct of_cpuidle_method __cpuidle_method_of_table_##name \
 -      __used __section("__cpuidle_method_of_table")                   \
 -      = { .method = _method, .ops = _ops }
 +      __cpuidle_method_section = { .method = _method, .ops = _ops }
  
  extern int arm_cpuidle_suspend(int index);
  
  extern int arm_cpuidle_init(int cpu);
  
+ struct arm_cpuidle_irq_context { };
+ #define arm_cpuidle_save_irq_context(c)               (void)c
+ #define arm_cpuidle_restore_irq_context(c)    (void)c
  #endif
@@@ -8,6 -8,7 +8,7 @@@
  #define __ARM_KVM_ASM_H__
  
  #include <asm/hyp_image.h>
+ #include <asm/insn.h>
  #include <asm/virt.h>
  
  #define ARM_EXIT_WITH_SERROR_BIT  31
@@@ -63,7 -64,6 +64,7 @@@
  #define __KVM_HOST_SMCCC_FUNC___pkvm_cpu_set_vector           18
  #define __KVM_HOST_SMCCC_FUNC___pkvm_prot_finalize            19
  #define __KVM_HOST_SMCCC_FUNC___pkvm_mark_hyp                 20
 +#define __KVM_HOST_SMCCC_FUNC___kvm_adjust_pc                 21
  
  #ifndef __ASSEMBLY__
  
@@@ -202,8 -202,6 +203,8 @@@ extern void __kvm_timer_set_cntvoff(u6
  
  extern int __kvm_vcpu_run(struct kvm_vcpu *vcpu);
  
 +extern void __kvm_adjust_pc(struct kvm_vcpu *vcpu);
 +
  extern u64 __vgic_v3_get_gic_config(void);
  extern u64 __vgic_v3_read_vmcr(void);
  extern void __vgic_v3_write_vmcr(u32 vmcr);
@@@ -7,26 -7,28 +7,28 @@@
   * Copyright (C) 2013 Linaro Limited.
   * Author: Sandeepa Prabhu <sandeepa.prabhu@linaro.org>
   */
+ #include <linux/extable.h>
  #include <linux/kasan.h>
  #include <linux/kernel.h>
  #include <linux/kprobes.h>
- #include <linux/extable.h>
- #include <linux/slab.h>
- #include <linux/stop_machine.h>
  #include <linux/sched/debug.h>
  #include <linux/set_memory.h>
+ #include <linux/slab.h>
+ #include <linux/stop_machine.h>
  #include <linux/stringify.h>
+ #include <linux/uaccess.h>
  #include <linux/vmalloc.h>
- #include <asm/traps.h>
- #include <asm/ptrace.h>
  #include <asm/cacheflush.h>
- #include <asm/debug-monitors.h>
  #include <asm/daifflags.h>
- #include <asm/system_misc.h>
+ #include <asm/debug-monitors.h>
  #include <asm/insn.h>
- #include <linux/uaccess.h>
  #include <asm/irq.h>
+ #include <asm/patching.h>
+ #include <asm/ptrace.h>
  #include <asm/sections.h>
+ #include <asm/system_misc.h>
+ #include <asm/traps.h>
  
  #include "decode-insn.h"
  
@@@ -277,6 -279,23 +279,6 @@@ int __kprobes kprobe_fault_handler(stru
        case KPROBE_HIT_ACTIVE:
        case KPROBE_HIT_SSDONE:
                /*
 -               * We increment the nmissed count for accounting,
 -               * we can also use npre/npostfault count for accounting
 -               * these specific fault cases.
 -               */
 -              kprobes_inc_nmissed_count(cur);
 -
 -              /*
 -               * We come here because instructions in the pre/post
 -               * handler caused the page_fault, this could happen
 -               * if handler tries to access user space by
 -               * copy_from_user(), get_user() etc. Let the
 -               * user-specified handler try to fix it first.
 -               */
 -              if (cur->fault_handler && cur->fault_handler(cur, regs, fsr))
 -                      return 1;
 -
 -              /*
                 * In case the user-specified fault handler returned
                 * zero, try to fix up.
                 */
@@@ -18,7 -18,6 +18,6 @@@
  #include <linux/sched/task.h>
  #include <linux/sched/task_stack.h>
  #include <linux/kernel.h>
- #include <linux/lockdep.h>
  #include <linux/mman.h>
  #include <linux/mm.h>
  #include <linux/nospec.h>
@@@ -46,7 -45,6 +45,6 @@@
  #include <linux/prctl.h>
  
  #include <asm/alternative.h>
- #include <asm/arch_gicv3.h>
  #include <asm/compat.h>
  #include <asm/cpufeature.h>
  #include <asm/cacheflush.h>
@@@ -74,63 -72,6 +72,6 @@@ EXPORT_SYMBOL_GPL(pm_power_off)
  
  void (*arm_pm_restart)(enum reboot_mode reboot_mode, const char *cmd);
  
- static void noinstr __cpu_do_idle(void)
- {
-       dsb(sy);
-       wfi();
- }
- static void noinstr __cpu_do_idle_irqprio(void)
- {
-       unsigned long pmr;
-       unsigned long daif_bits;
-       daif_bits = read_sysreg(daif);
-       write_sysreg(daif_bits | PSR_I_BIT | PSR_F_BIT, daif);
-       /*
-        * Unmask PMR before going idle to make sure interrupts can
-        * be raised.
-        */
-       pmr = gic_read_pmr();
-       gic_write_pmr(GIC_PRIO_IRQON | GIC_PRIO_PSR_I_SET);
-       __cpu_do_idle();
-       gic_write_pmr(pmr);
-       write_sysreg(daif_bits, daif);
- }
- /*
-  *    cpu_do_idle()
-  *
-  *    Idle the processor (wait for interrupt).
-  *
-  *    If the CPU supports priority masking we must do additional work to
-  *    ensure that interrupts are not masked at the PMR (because the core will
-  *    not wake up if we block the wake up signal in the interrupt controller).
-  */
- void noinstr cpu_do_idle(void)
- {
-       if (system_uses_irq_prio_masking())
-               __cpu_do_idle_irqprio();
-       else
-               __cpu_do_idle();
- }
- /*
-  * This is our default idle handler.
-  */
- void noinstr arch_cpu_idle(void)
- {
-       /*
-        * This should do all the clock switching and wait for interrupt
-        * tricks
-        */
-       cpu_do_idle();
-       raw_local_irq_enable();
- }
  #ifdef CONFIG_HOTPLUG_CPU
  void arch_cpu_idle_dead(void)
  {
@@@ -435,6 -376,11 +376,11 @@@ int copy_thread(unsigned long clone_fla
        }
        p->thread.cpu_context.pc = (unsigned long)ret_from_fork;
        p->thread.cpu_context.sp = (unsigned long)childregs;
+       /*
+        * For the benefit of the unwinder, set up childregs->stackframe
+        * as the final frame for the new task.
+        */
+       p->thread.cpu_context.fp = (unsigned long)childregs->stackframe;
  
        ptrace_hw_copy_thread(p);
  
@@@ -527,6 -473,15 +473,15 @@@ static void erratum_1418040_thread_swit
        write_sysreg(val, cntkctl_el1);
  }
  
+ static void compat_thread_switch(struct task_struct *next)
+ {
+       if (!is_compat_thread(task_thread_info(next)))
+               return;
+       if (static_branch_unlikely(&arm64_mismatched_32bit_el0))
+               set_tsk_thread_flag(next, TIF_NOTIFY_RESUME);
+ }
  static void update_sctlr_el1(u64 sctlr)
  {
        /*
@@@ -568,6 -523,7 +523,7 @@@ __notrace_funcgraph struct task_struct 
        ssbs_thread_switch(next);
        erratum_1418040_thread_switch(prev, next);
        ptrauth_thread_switch_user(next);
+       compat_thread_switch(next);
  
        /*
         * Complete any pending TLB or cache maintenance on this CPU in case
@@@ -598,7 -554,7 +554,7 @@@ unsigned long get_wchan(struct task_str
        struct stackframe frame;
        unsigned long stack_page, ret = 0;
        int count = 0;
 -      if (!p || p == current || p->state == TASK_RUNNING)
 +      if (!p || p == current || task_is_running(p))
                return 0;
  
        stack_page = (unsigned long)try_get_task_stack(p);
@@@ -633,8 -589,15 +589,15 @@@ unsigned long arch_align_stack(unsigne
   */
  void arch_setup_new_exec(void)
  {
-       current->mm->context.flags = is_compat_task() ? MMCF_AARCH32 : 0;
+       unsigned long mmflags = 0;
+       if (is_compat_task()) {
+               mmflags = MMCF_AARCH32;
+               if (static_branch_unlikely(&arm64_mismatched_32bit_el0))
+                       set_tsk_thread_flag(current, TIF_NOTIFY_RESUME);
+       }
  
+       current->mm->context.flags = mmflags;
        ptrauth_thread_init_user();
        mte_thread_init_user();
  
@@@ -724,22 -687,6 +687,6 @@@ static int __init tagged_addr_init(void
  core_initcall(tagged_addr_init);
  #endif        /* CONFIG_ARM64_TAGGED_ADDR_ABI */
  
- asmlinkage void __sched arm64_preempt_schedule_irq(void)
- {
-       lockdep_assert_irqs_disabled();
-       /*
-        * Preempting a task from an IRQ means we leave copies of PSTATE
-        * on the stack. cpufeature's enable calls may modify PSTATE, but
-        * resuming one of these preempted tasks would undo those changes.
-        *
-        * Only allow a task to be preempted once cpufeatures have been
-        * enabled.
-        */
-       if (system_capabilities_finalized())
-               preempt_schedule_irq();
- }
  #ifdef CONFIG_BINFMT_ELF
  int arch_elf_adjust_prot(int prot, const struct arch_elf_state *state,
                         bool has_interp, bool is_interp)
diff --combined arch/arm64/kernel/smp.c
@@@ -120,9 -120,7 +120,7 @@@ int __cpu_up(unsigned int cpu, struct t
         * page tables.
         */
        secondary_data.task = idle;
-       secondary_data.stack = task_stack_page(idle) + THREAD_SIZE;
        update_cpu_boot_status(CPU_MMU_OFF);
-       __flush_dcache_area(&secondary_data, sizeof(secondary_data));
  
        /* Now bring the CPU into our world */
        ret = boot_secondary(cpu, idle);
  
        pr_crit("CPU%u: failed to come online\n", cpu);
        secondary_data.task = NULL;
-       secondary_data.stack = NULL;
-       __flush_dcache_area(&secondary_data, sizeof(secondary_data));
        status = READ_ONCE(secondary_data.status);
        if (status == CPU_MMU_OFF)
                status = READ_ONCE(__early_cpu_boot_status);
@@@ -202,10 -198,7 +198,7 @@@ asmlinkage notrace void secondary_start
        u64 mpidr = read_cpuid_mpidr() & MPIDR_HWID_BITMASK;
        struct mm_struct *mm = &init_mm;
        const struct cpu_operations *ops;
-       unsigned int cpu;
-       cpu = task_cpu(current);
-       set_my_cpu_offset(per_cpu_offset(cpu));
+       unsigned int cpu = smp_processor_id();
  
        /*
         * All kernel threads share the same mm context; grab a
                init_gic_priority_masking();
  
        rcu_cpu_starting(cpu);
 -      preempt_disable();
        trace_hardirqs_off();
  
        /*
@@@ -351,7 -345,7 +344,7 @@@ void __cpu_die(unsigned int cpu
                pr_crit("CPU%u: cpu didn't die\n", cpu);
                return;
        }
-       pr_notice("CPU%u: shutdown\n", cpu);
+       pr_debug("CPU%u: shutdown\n", cpu);
  
        /*
         * Now that the dying CPU is beyond the point of no return w.r.t.
@@@ -451,6 -445,11 +444,11 @@@ void __init smp_cpus_done(unsigned int 
  
  void __init smp_prepare_boot_cpu(void)
  {
+       /*
+        * The runtime per-cpu areas have been allocated by
+        * setup_per_cpu_areas(), and CPU0's boot time per-cpu area will be
+        * freed shortly, so we must move over to the runtime per-cpu area.
+        */
        set_my_cpu_offset(per_cpu_offset(smp_processor_id()));
        cpuinfo_store_boot_cpu();
  
diff --combined arch/arm64/kvm/arm.c
@@@ -692,6 -692,15 +692,15 @@@ static void check_vcpu_requests(struct 
        }
  }
  
+ static bool vcpu_mode_is_bad_32bit(struct kvm_vcpu *vcpu)
+ {
+       if (likely(!vcpu_mode_is_32bit(vcpu)))
+               return false;
+       return !system_supports_32bit_el0() ||
+               static_branch_unlikely(&arm64_mismatched_32bit_el0);
+ }
  /**
   * kvm_arch_vcpu_ioctl_run - the main VCPU run function to execute guest code
   * @vcpu:     The VCPU pointer
@@@ -720,13 -729,11 +729,13 @@@ int kvm_arch_vcpu_ioctl_run(struct kvm_
                        return ret;
        }
  
 -      if (run->immediate_exit)
 -              return -EINTR;
 -
        vcpu_load(vcpu);
  
 +      if (run->immediate_exit) {
 +              ret = -EINTR;
 +              goto out;
 +      }
 +
        kvm_sigset_activate(vcpu);
  
        ret = 1;
                 * with the asymmetric AArch32 case), return to userspace with
                 * a fatal error.
                 */
-               if (!system_supports_32bit_el0() && vcpu_mode_is_32bit(vcpu)) {
+               if (vcpu_mode_is_bad_32bit(vcpu)) {
                        /*
                         * As we have caught the guest red-handed, decide that
                         * it isn't fit for purpose anymore by making the vcpu
        }
  
        kvm_sigset_deactivate(vcpu);
 +
 +out:
 +      /*
 +       * In the unlikely event that we are returning to userspace
 +       * with pending exceptions or PC adjustment, commit these
 +       * adjustments in order to give userspace a consistent view of
 +       * the vcpu state. Note that this relies on __kvm_adjust_pc()
 +       * being preempt-safe on VHE.
 +       */
 +      if (unlikely(vcpu->arch.flags & (KVM_ARM64_PENDING_EXCEPTION |
 +                                       KVM_ARM64_INCREMENT_PC)))
 +              kvm_call_hyp(__kvm_adjust_pc, vcpu);
  
        vcpu_put(vcpu);
        return ret;
@@@ -1078,7 -1073,7 +1087,7 @@@ static int kvm_arch_vcpu_ioctl_vcpu_ini
                if (!cpus_have_final_cap(ARM64_HAS_STAGE2_FWB))
                        stage2_unmap_vm(vcpu->kvm);
                else
-                       __flush_icache_all();
+                       icache_inval_all_pou();
        }
  
        vcpu_reset_hcr(vcpu);
@@@ -17,6 -17,7 +17,6 @@@
  #include <nvhe/trap_handler.h>
  
  struct hyp_pool hpool;
 -struct kvm_pgtable_mm_ops pkvm_pgtable_mm_ops;
  unsigned long hyp_nr_cpus;
  
  #define hyp_percpu_size ((unsigned long)__per_cpu_end - \
@@@ -26,7 -27,6 +26,7 @@@ static void *vmemmap_base
  static void *hyp_pgt_base;
  static void *host_s2_mem_pgt_base;
  static void *host_s2_dev_pgt_base;
 +static struct kvm_pgtable_mm_ops pkvm_pgtable_mm_ops;
  
  static int divide_memory_pool(void *virt, unsigned long size)
  {
@@@ -134,7 -134,8 +134,8 @@@ static void update_nvhe_init_params(voi
        for (i = 0; i < hyp_nr_cpus; i++) {
                params = per_cpu_ptr(&kvm_init_params, i);
                params->pgd_pa = __hyp_pa(pkvm_pgtable.pgd);
-               __flush_dcache_area(params, sizeof(*params));
+               dcache_clean_inval_poc((unsigned long)params,
+                                   (unsigned long)params + sizeof(*params));
        }
  }
  
diff --combined arch/arm64/mm/mmu.c
@@@ -228,7 -228,7 +228,7 @@@ static void init_pmd(pud_t *pudp, unsig
                next = pmd_addr_end(addr, end);
  
                /* try section mapping first */
-               if (((addr | next | phys) & ~SECTION_MASK) == 0 &&
+               if (((addr | next | phys) & ~PMD_MASK) == 0 &&
                    (flags & NO_BLOCK_MAPPINGS) == 0) {
                        pmd_set_huge(pmdp, phys, prot);
  
@@@ -515,8 -515,7 +515,8 @@@ static void __init map_mem(pgd_t *pgdp
         */
        BUILD_BUG_ON(pgd_index(direct_map_end - 1) == pgd_index(direct_map_end));
  
 -      if (rodata_full || crash_mem_map || debug_pagealloc_enabled())
 +      if (rodata_full || crash_mem_map || debug_pagealloc_enabled() ||
 +          IS_ENABLED(CONFIG_KFENCE))
                flags |= NO_BLOCK_MAPPINGS | NO_CONT_MAPPINGS;
  
        /*
@@@ -1114,14 -1113,14 +1114,14 @@@ static void free_empty_tables(unsigned 
  }
  #endif
  
- #if !ARM64_SWAPPER_USES_SECTION_MAPS
+ #if !ARM64_KERNEL_USES_PMD_MAPS
  int __meminit vmemmap_populate(unsigned long start, unsigned long end, int node,
                struct vmem_altmap *altmap)
  {
        WARN_ON((start < VMEMMAP_START) || (end > VMEMMAP_END));
        return vmemmap_populate_basepages(start, end, node, altmap);
  }
- #else /* !ARM64_SWAPPER_USES_SECTION_MAPS */
+ #else /* !ARM64_KERNEL_USES_PMD_MAPS */
  int __meminit vmemmap_populate(unsigned long start, unsigned long end, int node,
                struct vmem_altmap *altmap)
  {
  
        return 0;
  }
- #endif        /* !ARM64_SWAPPER_USES_SECTION_MAPS */
+ #endif        /* !ARM64_KERNEL_USES_PMD_MAPS */
+ #ifdef CONFIG_MEMORY_HOTPLUG
  void vmemmap_free(unsigned long start, unsigned long end,
                struct vmem_altmap *altmap)
  {
- #ifdef CONFIG_MEMORY_HOTPLUG
        WARN_ON((start < VMEMMAP_START) || (end > VMEMMAP_END));
  
        unmap_hotplug_range(start, end, true, altmap);
        free_empty_tables(start, end, VMEMMAP_START, VMEMMAP_END);
- #endif
  }
+ #endif /* CONFIG_MEMORY_HOTPLUG */
  
  static inline pud_t *fixmap_pud(unsigned long addr)
  {
diff --combined mm/page_alloc.c
@@@ -382,7 -382,7 +382,7 @@@ int page_group_by_mobility_disabled __r
  static DEFINE_STATIC_KEY_TRUE(deferred_pages);
  
  /*
-  * Calling kasan_free_pages() only after deferred memory initialization
+  * Calling kasan_poison_pages() only after deferred memory initialization
   * has completed. Poisoning pages during deferred memory init will greatly
   * lengthen the process and cause problem in large memory systems as the
   * deferred pages initialization is done with interrupt disabled.
   * on-demand allocation and then freed again before the deferred pages
   * initialization is done, but this is not likely to happen.
   */
- static inline void kasan_free_nondeferred_pages(struct page *page, int order,
-                                               bool init, fpi_t fpi_flags)
+ static inline bool should_skip_kasan_poison(struct page *page, fpi_t fpi_flags)
  {
-       if (static_branch_unlikely(&deferred_pages))
-               return;
-       if (!IS_ENABLED(CONFIG_KASAN_GENERIC) &&
-                       (fpi_flags & FPI_SKIP_KASAN_POISON))
-               return;
-       kasan_free_pages(page, order, init);
+       return static_branch_unlikely(&deferred_pages) ||
+              (!IS_ENABLED(CONFIG_KASAN_GENERIC) &&
+               (fpi_flags & FPI_SKIP_KASAN_POISON)) ||
+              PageSkipKASanPoison(page);
  }
  
  /* Returns true if the struct page for the pfn is uninitialised */
@@@ -453,13 -450,11 +450,11 @@@ defer_init(int nid, unsigned long pfn, 
        return false;
  }
  #else
- static inline void kasan_free_nondeferred_pages(struct page *page, int order,
-                                               bool init, fpi_t fpi_flags)
+ static inline bool should_skip_kasan_poison(struct page *page, fpi_t fpi_flags)
  {
-       if (!IS_ENABLED(CONFIG_KASAN_GENERIC) &&
-                       (fpi_flags & FPI_SKIP_KASAN_POISON))
-               return;
-       kasan_free_pages(page, order, init);
+       return (!IS_ENABLED(CONFIG_KASAN_GENERIC) &&
+               (fpi_flags & FPI_SKIP_KASAN_POISON)) ||
+              PageSkipKASanPoison(page);
  }
  
  static inline bool early_page_uninitialised(unsigned long pfn)
        return ret;
  }
  
- static void kernel_init_free_pages(struct page *page, int numpages)
+ static void kernel_init_free_pages(struct page *page, int numpages, bool zero_tags)
  {
        int i;
  
+       if (zero_tags) {
+               for (i = 0; i < numpages; i++)
+                       tag_clear_highpage(page + i);
+               return;
+       }
        /* s390's use of memset() could override KASAN redzones. */
        kasan_disable_current();
        for (i = 0; i < numpages; i++) {
@@@ -1245,7 -1246,7 +1246,7 @@@ static __always_inline bool free_pages_
                        unsigned int order, bool check_free, fpi_t fpi_flags)
  {
        int bad = 0;
-       bool init;
+       bool skip_kasan_poison = should_skip_kasan_poison(page, fpi_flags);
  
        VM_BUG_ON_PAGE(PageTail(page), page);
  
         * With hardware tag-based KASAN, memory tags must be set before the
         * page becomes unavailable via debug_pagealloc or arch_free_page.
         */
-       init = want_init_on_free();
-       if (init && !kasan_has_integrated_init())
-               kernel_init_free_pages(page, 1 << order);
-       kasan_free_nondeferred_pages(page, order, init, fpi_flags);
+       if (kasan_has_integrated_init()) {
+               if (!skip_kasan_poison)
+                       kasan_free_pages(page, order);
+       } else {
+               bool init = want_init_on_free();
+               if (init)
+                       kernel_init_free_pages(page, 1 << order, false);
+               if (!skip_kasan_poison)
+                       kasan_poison_pages(page, order, init);
+       }
  
        /*
         * arch_free_page() can make the page's contents inaccessible.  s390
@@@ -2324,8 -2332,6 +2332,6 @@@ static bool check_new_pages(struct pag
  inline void post_alloc_hook(struct page *page, unsigned int order,
                                gfp_t gfp_flags)
  {
-       bool init;
        set_page_private(page, 0);
        set_page_refcounted(page);
  
         * kasan_alloc_pages and kernel_init_free_pages must be
         * kept together to avoid discrepancies in behavior.
         */
-       init = !want_init_on_free() && want_init_on_alloc(gfp_flags);
-       kasan_alloc_pages(page, order, init);
-       if (init && !kasan_has_integrated_init())
-               kernel_init_free_pages(page, 1 << order);
+       if (kasan_has_integrated_init()) {
+               kasan_alloc_pages(page, order, gfp_flags);
+       } else {
+               bool init = !want_init_on_free() && want_init_on_alloc(gfp_flags);
+               kasan_unpoison_pages(page, order, init);
+               if (init)
+                       kernel_init_free_pages(page, 1 << order,
+                                              gfp_flags & __GFP_ZEROTAGS);
+       }
  
        set_page_owner(page, order, gfp_flags);
  }
@@@ -5053,13 -5065,9 +5065,13 @@@ unsigned long __alloc_pages_bulk(gfp_t 
         * Skip populated array elements to determine if any pages need
         * to be allocated before disabling IRQs.
         */
 -      while (page_array && page_array[nr_populated] && nr_populated < nr_pages)
 +      while (page_array && nr_populated < nr_pages && page_array[nr_populated])
                nr_populated++;
  
 +      /* Already populated array? */
 +      if (unlikely(page_array && nr_pages - nr_populated == 0))
 +              return nr_populated;
 +
        /* Use the single page allocator for one page. */
        if (nr_pages - nr_populated == 1)
                goto failed;
@@@ -9162,8 -9170,6 +9174,8 @@@ bool take_page_off_buddy(struct page *p
                        del_page_from_free_list(page_head, zone, page_order);
                        break_down_buddy_pages(zone, page_head, page, 0,
                                                page_order, migratetype);
 +                      if (!is_migrate_isolate(migratetype))
 +                              __mod_zone_freepage_state(zone, -1, migratetype);
                        ret = true;
                        break;
                }