]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/commitdiff
Merge branch 'akpm' (patches from Andrew)
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 29 Dec 2018 00:55:46 +0000 (16:55 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 29 Dec 2018 00:55:46 +0000 (16:55 -0800)
Merge misc updates from Andrew Morton:

 - large KASAN update to use arm's "software tag-based mode"

 - a few misc things

 - sh updates

 - ocfs2 updates

 - just about all of MM

* emailed patches from Andrew Morton <akpm@linux-foundation.org>: (167 commits)
  kernel/fork.c: mark 'stack_vm_area' with __maybe_unused
  memcg, oom: notify on oom killer invocation from the charge path
  mm, swap: fix swapoff with KSM pages
  include/linux/gfp.h: fix typo
  mm/hmm: fix memremap.h, move dev_page_fault_t callback to hmm
  hugetlbfs: Use i_mmap_rwsem to fix page fault/truncate race
  hugetlbfs: use i_mmap_rwsem for more pmd sharing synchronization
  memory_hotplug: add missing newlines to debugging output
  mm: remove __hugepage_set_anon_rmap()
  include/linux/vmstat.h: remove unused page state adjustment macro
  mm/page_alloc.c: allow error injection
  mm: migrate: drop unused argument of migrate_page_move_mapping()
  blkdev: avoid migration stalls for blkdev pages
  mm: migrate: provide buffer_migrate_page_norefs()
  mm: migrate: move migrate_page_lock_buffers()
  mm: migrate: lock buffers before migrate_page_move_mapping()
  mm: migration: factor out code to compute expected number of page references
  mm, page_alloc: enable pcpu_drain with zone capability
  kmemleak: add config to select auto scan
  mm/page_alloc.c: don't call kasan_free_pages() at deferred mem init
  ...

587 files changed:
Documentation/ABI/testing/sysfs-block-zram
Documentation/blockdev/zram.txt
Documentation/dev-tools/kasan.rst
Documentation/filesystems/proc.txt
Documentation/sysctl/vm.txt
arch/arm64/Kconfig
arch/arm64/Makefile
arch/arm64/include/asm/brk-imm.h
arch/arm64/include/asm/kasan.h
arch/arm64/include/asm/memory.h
arch/arm64/include/asm/pgtable-hwdef.h
arch/arm64/include/asm/uaccess.h
arch/arm64/kernel/traps.c
arch/arm64/mm/fault.c
arch/arm64/mm/kasan_init.c
arch/arm64/mm/mmu.c
arch/arm64/mm/proc.S
arch/csky/mm/init.c
arch/ia64/mm/init.c
arch/powerpc/mm/mem.c
arch/powerpc/platforms/pseries/cmm.c
arch/s390/mm/dump_pagetables.c
arch/s390/mm/init.c
arch/s390/mm/kasan_init.c
arch/sh/boards/board-apsh4a3a.c
arch/sh/boards/board-apsh4ad0a.c
arch/sh/boards/board-edosk7760.c
arch/sh/boards/board-espt.c
arch/sh/boards/board-magicpanelr2.c
arch/sh/boards/board-sh7757lcr.c
arch/sh/boards/board-sh7785lcr.c
arch/sh/boards/board-titan.c
arch/sh/boards/board-urquell.c
arch/sh/boards/mach-ap325rxa/Makefile
arch/sh/boards/mach-ap325rxa/sdram.S
arch/sh/boards/mach-cayman/Makefile
arch/sh/boards/mach-cayman/irq.c
arch/sh/boards/mach-cayman/panic.c
arch/sh/boards/mach-cayman/setup.c
arch/sh/boards/mach-dreamcast/Makefile
arch/sh/boards/mach-dreamcast/irq.c
arch/sh/boards/mach-dreamcast/rtc.c
arch/sh/boards/mach-dreamcast/setup.c
arch/sh/boards/mach-ecovec24/Makefile
arch/sh/boards/mach-ecovec24/sdram.S
arch/sh/boards/mach-ecovec24/setup.c
arch/sh/boards/mach-highlander/irq-r7780mp.c
arch/sh/boards/mach-highlander/irq-r7780rp.c
arch/sh/boards/mach-highlander/irq-r7785rp.c
arch/sh/boards/mach-highlander/pinmux-r7785rp.c
arch/sh/boards/mach-highlander/psw.c
arch/sh/boards/mach-highlander/setup.c
arch/sh/boards/mach-hp6xx/Makefile
arch/sh/boards/mach-hp6xx/hp6xx_apm.c
arch/sh/boards/mach-hp6xx/pm.c
arch/sh/boards/mach-hp6xx/pm_wakeup.S
arch/sh/boards/mach-hp6xx/setup.c
arch/sh/boards/mach-kfr2r09/Makefile
arch/sh/boards/mach-kfr2r09/lcd_wqvga.c
arch/sh/boards/mach-kfr2r09/sdram.S
arch/sh/boards/mach-kfr2r09/setup.c
arch/sh/boards/mach-landisk/Makefile
arch/sh/boards/mach-landisk/gio.c
arch/sh/boards/mach-landisk/irq.c
arch/sh/boards/mach-landisk/psw.c
arch/sh/boards/mach-landisk/setup.c
arch/sh/boards/mach-lboxre2/Makefile
arch/sh/boards/mach-lboxre2/irq.c
arch/sh/boards/mach-lboxre2/setup.c
arch/sh/boards/mach-microdev/Makefile
arch/sh/boards/mach-microdev/fdc37c93xapm.c
arch/sh/boards/mach-microdev/io.c
arch/sh/boards/mach-microdev/irq.c
arch/sh/boards/mach-microdev/setup.c
arch/sh/boards/mach-migor/Makefile
arch/sh/boards/mach-migor/lcd_qvga.c
arch/sh/boards/mach-migor/sdram.S
arch/sh/boards/mach-r2d/Makefile
arch/sh/boards/mach-r2d/setup.c
arch/sh/boards/mach-rsk/Makefile
arch/sh/boards/mach-rsk/devices-rsk7203.c
arch/sh/boards/mach-rsk/devices-rsk7264.c
arch/sh/boards/mach-rsk/devices-rsk7269.c
arch/sh/boards/mach-rsk/setup.c
arch/sh/boards/mach-sdk7780/Makefile
arch/sh/boards/mach-sdk7780/irq.c
arch/sh/boards/mach-sdk7780/setup.c
arch/sh/boards/mach-sdk7786/Makefile
arch/sh/boards/mach-sdk7786/fpga.c
arch/sh/boards/mach-sdk7786/gpio.c
arch/sh/boards/mach-sdk7786/irq.c
arch/sh/boards/mach-sdk7786/nmi.c
arch/sh/boards/mach-sdk7786/setup.c
arch/sh/boards/mach-sdk7786/sram.c
arch/sh/boards/mach-se/7206/Makefile
arch/sh/boards/mach-se/7343/Makefile
arch/sh/boards/mach-se/7343/irq.c
arch/sh/boards/mach-se/770x/Makefile
arch/sh/boards/mach-se/7721/Makefile
arch/sh/boards/mach-se/7721/irq.c
arch/sh/boards/mach-se/7721/setup.c
arch/sh/boards/mach-se/7722/Makefile
arch/sh/boards/mach-se/7722/irq.c
arch/sh/boards/mach-se/7722/setup.c
arch/sh/boards/mach-se/7724/Makefile
arch/sh/boards/mach-se/7724/irq.c
arch/sh/boards/mach-se/7724/sdram.S
arch/sh/boards/mach-se/7751/Makefile
arch/sh/boards/mach-se/7780/Makefile
arch/sh/boards/mach-se/7780/irq.c
arch/sh/boards/mach-se/7780/setup.c
arch/sh/boards/mach-sh03/Makefile
arch/sh/boards/mach-sh7763rdp/Makefile
arch/sh/boards/mach-sh7763rdp/irq.c
arch/sh/boards/mach-sh7763rdp/setup.c
arch/sh/boards/mach-x3proto/Makefile
arch/sh/boards/mach-x3proto/gpio.c
arch/sh/boards/mach-x3proto/ilsel.c
arch/sh/boards/mach-x3proto/setup.c
arch/sh/boards/of-generic.c
arch/sh/drivers/dma/Makefile
arch/sh/drivers/dma/dma-api.c
arch/sh/drivers/dma/dma-g2.c
arch/sh/drivers/dma/dma-pvr2.c
arch/sh/drivers/dma/dma-sh.c
arch/sh/drivers/dma/dma-sysfs.c
arch/sh/drivers/dma/dmabrg.c
arch/sh/drivers/heartbeat.c
arch/sh/drivers/pci/fixups-dreamcast.c
arch/sh/drivers/pci/fixups-landisk.c
arch/sh/drivers/pci/fixups-r7780rp.c
arch/sh/drivers/pci/fixups-rts7751r2d.c
arch/sh/drivers/pci/fixups-sdk7780.c
arch/sh/drivers/pci/fixups-sdk7786.c
arch/sh/drivers/pci/fixups-snapgear.c
arch/sh/drivers/pci/fixups-titan.c
arch/sh/drivers/pci/ops-dreamcast.c
arch/sh/drivers/pci/ops-sh4.c
arch/sh/drivers/pci/ops-sh5.c
arch/sh/drivers/pci/ops-sh7786.c
arch/sh/drivers/pci/pci-dreamcast.c
arch/sh/drivers/pci/pci-sh5.c
arch/sh/drivers/pci/pci-sh5.h
arch/sh/drivers/pci/pci-sh7751.c
arch/sh/drivers/pci/pci-sh7751.h
arch/sh/drivers/pci/pci-sh7780.c
arch/sh/drivers/pci/pci-sh7780.h
arch/sh/drivers/pci/pci.c
arch/sh/drivers/pci/pcie-sh7786.c
arch/sh/drivers/pci/pcie-sh7786.h
arch/sh/drivers/push-switch.c
arch/sh/drivers/superhyway/Makefile
arch/sh/drivers/superhyway/ops-sh4-202.c
arch/sh/include/asm/Kbuild
arch/sh/include/asm/addrspace.h
arch/sh/include/asm/asm-offsets.h
arch/sh/include/asm/bl_bit_64.h
arch/sh/include/asm/cache_insns_64.h
arch/sh/include/asm/checksum_32.h
arch/sh/include/asm/cmpxchg-xchg.h
arch/sh/include/asm/device.h
arch/sh/include/asm/dma-register.h
arch/sh/include/asm/dma.h
arch/sh/include/asm/dwarf.h
arch/sh/include/asm/fb.h
arch/sh/include/asm/fixmap.h
arch/sh/include/asm/flat.h
arch/sh/include/asm/freq.h
arch/sh/include/asm/gpio.h
arch/sh/include/asm/machvec.h
arch/sh/include/asm/mmu_context_64.h
arch/sh/include/asm/pgtable.h
arch/sh/include/asm/pgtable_64.h
arch/sh/include/asm/processor_64.h
arch/sh/include/asm/sfp-machine.h
arch/sh/include/asm/shmparam.h
arch/sh/include/asm/siu.h
arch/sh/include/asm/spinlock-cas.h
arch/sh/include/asm/spinlock-llsc.h
arch/sh/include/asm/spinlock.h
arch/sh/include/asm/string_32.h
arch/sh/include/asm/switch_to.h
arch/sh/include/asm/switch_to_64.h
arch/sh/include/asm/tlb_64.h
arch/sh/include/asm/traps_64.h
arch/sh/include/asm/uaccess_64.h
arch/sh/include/asm/vga.h
arch/sh/include/asm/watchdog.h
arch/sh/include/cpu-common/cpu/addrspace.h
arch/sh/include/cpu-common/cpu/mmu_context.h
arch/sh/include/cpu-common/cpu/pfc.h
arch/sh/include/cpu-common/cpu/timer.h
arch/sh/include/cpu-sh2/cpu/cache.h
arch/sh/include/cpu-sh2/cpu/freq.h
arch/sh/include/cpu-sh2/cpu/watchdog.h
arch/sh/include/cpu-sh2a/cpu/cache.h
arch/sh/include/cpu-sh2a/cpu/freq.h
arch/sh/include/cpu-sh2a/cpu/watchdog.h
arch/sh/include/cpu-sh3/cpu/cache.h
arch/sh/include/cpu-sh3/cpu/dma-register.h
arch/sh/include/cpu-sh3/cpu/freq.h
arch/sh/include/cpu-sh3/cpu/gpio.h
arch/sh/include/cpu-sh3/cpu/mmu_context.h
arch/sh/include/cpu-sh3/cpu/watchdog.h
arch/sh/include/cpu-sh4/cpu/addrspace.h
arch/sh/include/cpu-sh4/cpu/cache.h
arch/sh/include/cpu-sh4/cpu/dma-register.h
arch/sh/include/cpu-sh4/cpu/fpu.h
arch/sh/include/cpu-sh4/cpu/freq.h
arch/sh/include/cpu-sh4/cpu/mmu_context.h
arch/sh/include/cpu-sh4/cpu/sh7786.h
arch/sh/include/cpu-sh4/cpu/sq.h
arch/sh/include/cpu-sh4/cpu/watchdog.h
arch/sh/include/cpu-sh5/cpu/cache.h
arch/sh/include/cpu-sh5/cpu/irq.h
arch/sh/include/cpu-sh5/cpu/registers.h
arch/sh/include/mach-common/mach/hp6xx.h
arch/sh/include/mach-common/mach/lboxre2.h
arch/sh/include/mach-common/mach/magicpanelr2.h
arch/sh/include/mach-common/mach/mangle-port.h
arch/sh/include/mach-common/mach/microdev.h
arch/sh/include/mach-common/mach/sdk7780.h
arch/sh/include/mach-common/mach/secureedge5410.h
arch/sh/include/mach-common/mach/sh7763rdp.h
arch/sh/include/mach-dreamcast/mach/dma.h
arch/sh/include/mach-dreamcast/mach/pci.h
arch/sh/include/mach-dreamcast/mach/sysasic.h
arch/sh/include/mach-ecovec24/mach/partner-jet-setup.txt
arch/sh/include/mach-kfr2r09/mach/partner-jet-setup.txt
arch/sh/include/mach-se/mach/se7721.h
arch/sh/include/mach-se/mach/se7722.h
arch/sh/include/mach-se/mach/se7724.h
arch/sh/include/mach-se/mach/se7780.h
arch/sh/include/uapi/asm/Kbuild
arch/sh/include/uapi/asm/setup.h
arch/sh/include/uapi/asm/types.h
arch/sh/kernel/cpu/clock.c
arch/sh/kernel/cpu/init.c
arch/sh/kernel/cpu/irq/Makefile
arch/sh/kernel/cpu/irq/intc-sh5.c
arch/sh/kernel/cpu/irq/ipr.c
arch/sh/kernel/cpu/pfc.c
arch/sh/kernel/cpu/sh2/Makefile
arch/sh/kernel/cpu/sh2/clock-sh7619.c
arch/sh/kernel/cpu/sh2/entry.S
arch/sh/kernel/cpu/sh2/ex.S
arch/sh/kernel/cpu/sh2/probe.c
arch/sh/kernel/cpu/sh2/setup-sh7619.c
arch/sh/kernel/cpu/sh2/smp-j2.c
arch/sh/kernel/cpu/sh2a/clock-sh7201.c
arch/sh/kernel/cpu/sh2a/clock-sh7203.c
arch/sh/kernel/cpu/sh2a/clock-sh7206.c
arch/sh/kernel/cpu/sh2a/clock-sh7264.c
arch/sh/kernel/cpu/sh2a/clock-sh7269.c
arch/sh/kernel/cpu/sh2a/entry.S
arch/sh/kernel/cpu/sh2a/ex.S
arch/sh/kernel/cpu/sh2a/fpu.c
arch/sh/kernel/cpu/sh2a/opcode_helper.c
arch/sh/kernel/cpu/sh2a/pinmux-sh7203.c
arch/sh/kernel/cpu/sh2a/pinmux-sh7264.c
arch/sh/kernel/cpu/sh2a/pinmux-sh7269.c
arch/sh/kernel/cpu/sh2a/probe.c
arch/sh/kernel/cpu/sh2a/setup-mxg.c
arch/sh/kernel/cpu/sh2a/setup-sh7201.c
arch/sh/kernel/cpu/sh2a/setup-sh7203.c
arch/sh/kernel/cpu/sh2a/setup-sh7206.c
arch/sh/kernel/cpu/sh2a/setup-sh7264.c
arch/sh/kernel/cpu/sh2a/setup-sh7269.c
arch/sh/kernel/cpu/sh3/clock-sh3.c
arch/sh/kernel/cpu/sh3/clock-sh7705.c
arch/sh/kernel/cpu/sh3/clock-sh7706.c
arch/sh/kernel/cpu/sh3/clock-sh7709.c
arch/sh/kernel/cpu/sh3/clock-sh7710.c
arch/sh/kernel/cpu/sh3/clock-sh7712.c
arch/sh/kernel/cpu/sh3/entry.S
arch/sh/kernel/cpu/sh3/ex.S
arch/sh/kernel/cpu/sh3/pinmux-sh7720.c
arch/sh/kernel/cpu/sh3/probe.c
arch/sh/kernel/cpu/sh3/setup-sh3.c
arch/sh/kernel/cpu/sh3/setup-sh7705.c
arch/sh/kernel/cpu/sh3/setup-sh770x.c
arch/sh/kernel/cpu/sh3/setup-sh7710.c
arch/sh/kernel/cpu/sh3/setup-sh7720.c
arch/sh/kernel/cpu/sh3/swsusp.S
arch/sh/kernel/cpu/sh4/clock-sh4-202.c
arch/sh/kernel/cpu/sh4/clock-sh4.c
arch/sh/kernel/cpu/sh4/fpu.c
arch/sh/kernel/cpu/sh4/perf_event.c
arch/sh/kernel/cpu/sh4/probe.c
arch/sh/kernel/cpu/sh4/setup-sh4-202.c
arch/sh/kernel/cpu/sh4/setup-sh7750.c
arch/sh/kernel/cpu/sh4/setup-sh7760.c
arch/sh/kernel/cpu/sh4/sq.c
arch/sh/kernel/cpu/sh4a/clock-sh7343.c
arch/sh/kernel/cpu/sh4a/clock-sh7366.c
arch/sh/kernel/cpu/sh4a/clock-sh7722.c
arch/sh/kernel/cpu/sh4a/clock-sh7723.c
arch/sh/kernel/cpu/sh4a/clock-sh7724.c
arch/sh/kernel/cpu/sh4a/clock-sh7734.c
arch/sh/kernel/cpu/sh4a/clock-sh7757.c
arch/sh/kernel/cpu/sh4a/clock-sh7763.c
arch/sh/kernel/cpu/sh4a/clock-sh7770.c
arch/sh/kernel/cpu/sh4a/clock-sh7780.c
arch/sh/kernel/cpu/sh4a/clock-sh7785.c
arch/sh/kernel/cpu/sh4a/clock-sh7786.c
arch/sh/kernel/cpu/sh4a/clock-shx3.c
arch/sh/kernel/cpu/sh4a/intc-shx3.c
arch/sh/kernel/cpu/sh4a/perf_event.c
arch/sh/kernel/cpu/sh4a/pinmux-sh7723.c
arch/sh/kernel/cpu/sh4a/pinmux-sh7724.c
arch/sh/kernel/cpu/sh4a/pinmux-sh7734.c
arch/sh/kernel/cpu/sh4a/pinmux-sh7757.c
arch/sh/kernel/cpu/sh4a/pinmux-sh7785.c
arch/sh/kernel/cpu/sh4a/pinmux-sh7786.c
arch/sh/kernel/cpu/sh4a/pinmux-shx3.c
arch/sh/kernel/cpu/sh4a/setup-sh7343.c
arch/sh/kernel/cpu/sh4a/setup-sh7366.c
arch/sh/kernel/cpu/sh4a/setup-sh7722.c
arch/sh/kernel/cpu/sh4a/setup-sh7723.c
arch/sh/kernel/cpu/sh4a/setup-sh7724.c
arch/sh/kernel/cpu/sh4a/setup-sh7734.c
arch/sh/kernel/cpu/sh4a/setup-sh7757.c
arch/sh/kernel/cpu/sh4a/setup-sh7763.c
arch/sh/kernel/cpu/sh4a/setup-sh7770.c
arch/sh/kernel/cpu/sh4a/setup-sh7780.c
arch/sh/kernel/cpu/sh4a/setup-sh7785.c
arch/sh/kernel/cpu/sh4a/setup-sh7786.c
arch/sh/kernel/cpu/sh4a/setup-shx3.c
arch/sh/kernel/cpu/sh4a/smp-shx3.c
arch/sh/kernel/cpu/sh4a/ubc.c
arch/sh/kernel/cpu/sh5/clock-sh5.c
arch/sh/kernel/cpu/sh5/entry.S
arch/sh/kernel/cpu/sh5/fpu.c
arch/sh/kernel/cpu/sh5/probe.c
arch/sh/kernel/cpu/sh5/setup-sh5.c
arch/sh/kernel/cpu/sh5/switchto.S
arch/sh/kernel/cpu/sh5/unwind.c
arch/sh/kernel/cpu/shmobile/Makefile
arch/sh/kernel/cpu/shmobile/cpuidle.c
arch/sh/kernel/cpu/shmobile/pm.c
arch/sh/kernel/cpu/shmobile/sleep.S
arch/sh/kernel/debugtraps.S
arch/sh/kernel/disassemble.c
arch/sh/kernel/dma-coherent.c
arch/sh/kernel/dumpstack.c
arch/sh/kernel/dwarf.c
arch/sh/kernel/entry-common.S
arch/sh/kernel/head_32.S
arch/sh/kernel/head_64.S
arch/sh/kernel/hw_breakpoint.c
arch/sh/kernel/idle.c
arch/sh/kernel/io.c
arch/sh/kernel/io_trapped.c
arch/sh/kernel/iomap.c
arch/sh/kernel/ioport.c
arch/sh/kernel/irq_32.c
arch/sh/kernel/irq_64.c
arch/sh/kernel/kgdb.c
arch/sh/kernel/kprobes.c
arch/sh/kernel/machine_kexec.c
arch/sh/kernel/machvec.c
arch/sh/kernel/module.c
arch/sh/kernel/nmi_debug.c
arch/sh/kernel/perf_callchain.c
arch/sh/kernel/perf_event.c
arch/sh/kernel/process_32.c
arch/sh/kernel/process_64.c
arch/sh/kernel/ptrace_32.c
arch/sh/kernel/ptrace_64.c
arch/sh/kernel/relocate_kernel.S
arch/sh/kernel/return_address.c
arch/sh/kernel/sh_bios.c
arch/sh/kernel/sh_ksyms_64.c
arch/sh/kernel/signal_64.c
arch/sh/kernel/smp.c
arch/sh/kernel/stacktrace.c
arch/sh/kernel/swsusp.c
arch/sh/kernel/syscalls_32.S
arch/sh/kernel/syscalls_64.S
arch/sh/kernel/time.c
arch/sh/kernel/topology.c
arch/sh/kernel/traps_32.c
arch/sh/kernel/traps_64.c
arch/sh/kernel/unwinder.c
arch/sh/kernel/vsyscall/vsyscall.c
arch/sh/lib/ashiftrt.S
arch/sh/lib/ashlsi3.S
arch/sh/lib/ashrsi3.S
arch/sh/lib/checksum.S
arch/sh/lib/io.c
arch/sh/lib/libgcc.h
arch/sh/lib/lshrsi3.S
arch/sh/lib/mcount.S
arch/sh/lib/movmem.S
arch/sh/lib/udiv_qrnnd.S
arch/sh/lib/udivsi3.S
arch/sh/lib/udivsi3_i4i-Os.S
arch/sh/lib/udivsi3_i4i.S
arch/sh/mm/init.c
arch/um/kernel/mem.c
arch/x86/include/asm/processor.h
arch/x86/kernel/cpu/microcode/core.c
arch/x86/mm/dump_pagetables.c
arch/x86/mm/init.c
arch/x86/mm/init_32.c
arch/x86/mm/init_64.c
arch/x86/mm/kasan_init_64.c
arch/x86/mm/pgtable.c
arch/xtensa/mm/kasan_init.c
drivers/base/memory.c
drivers/block/zram/Kconfig
drivers/block/zram/zram_drv.c
drivers/block/zram/zram_drv.h
drivers/char/agp/backend.c
drivers/dax/pmem.c
drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c
drivers/gpu/drm/amd/amdkfd/kfd_crat.c
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_gem_userptr.c
drivers/gpu/drm/i915/selftests/i915_gem_gtt.c
drivers/gpu/drm/radeon/radeon_mn.c
drivers/hv/hv_balloon.c
drivers/infiniband/core/umem_odp.c
drivers/infiniband/hw/hfi1/mmu_rb.c
drivers/md/dm-bufio.c
drivers/md/dm-crypt.c
drivers/md/dm-integrity.c
drivers/md/dm-stats.c
drivers/media/platform/mtk-vpu/mtk_vpu.c
drivers/misc/mic/scif/scif_dma.c
drivers/misc/sgi-gru/grutlbpurge.c
drivers/misc/vmw_balloon.c
drivers/nvdimm/pmem.c
drivers/parisc/ccio-dma.c
drivers/parisc/sba_iommu.c
drivers/pci/p2pdma.c
drivers/staging/android/ion/ion_system_heap.c
drivers/xen/balloon.c
drivers/xen/gntdev.c
drivers/xen/xen-selfballoon.c
fs/aio.c
fs/block_dev.c
fs/ceph/super.h
fs/dax.c
fs/f2fs/data.c
fs/file_table.c
fs/fuse/inode.c
fs/hugetlbfs/inode.c
fs/iomap.c
fs/nfs/write.c
fs/nfsd/nfscache.c
fs/ntfs/malloc.h
fs/ocfs2/Makefile
fs/ocfs2/buffer_head_io.c
fs/ocfs2/cluster/heartbeat.c
fs/ocfs2/dlm/Makefile
fs/ocfs2/dlmfs/Makefile
fs/ocfs2/dlmfs/dlmfs.c
fs/ocfs2/journal.c
fs/ocfs2/localalloc.c
fs/proc/array.c
fs/proc/base.c
fs/proc/page.c
fs/proc/task_mmu.c
fs/ubifs/file.c
fs/userfaultfd.c
include/asm-generic/error-injection.h
include/asm-generic/pgtable.h
include/linux/backing-dev-defs.h
include/linux/compiler-clang.h
include/linux/compiler-gcc.h
include/linux/compiler_attributes.h
include/linux/fs.h
include/linux/gfp.h
include/linux/highmem.h
include/linux/hmm.h
include/linux/huge_mm.h
include/linux/kasan.h
include/linux/memblock.h
include/linux/memcontrol.h
include/linux/memory_hotplug.h
include/linux/memremap.h
include/linux/migrate.h
include/linux/mm.h
include/linux/mmu_notifier.h
include/linux/mmzone.h
include/linux/oom.h
include/linux/page-flags-layout.h
include/linux/page-flags.h
include/linux/page-isolation.h
include/linux/pageblock-flags.h
include/linux/pagemap.h
include/linux/slab.h
include/linux/slab_def.h
include/linux/swap.h
include/linux/vmstat.h
include/linux/xxhash.h
init/main.c
kernel/cgroup/cpuset.c
kernel/events/uprobes.c
kernel/fork.c
kernel/kexec_core.c
kernel/memremap.c
kernel/power/snapshot.c
kernel/resource.c
kernel/sysctl.c
lib/Kconfig.debug
lib/Kconfig.kasan
lib/debugobjects.c
lib/ioremap.c
lib/show_mem.c
mm/Kconfig
mm/cma.c
mm/compaction.c
mm/debug.c
mm/filemap.c
mm/highmem.c
mm/hmm.c
mm/huge_memory.c
mm/hugetlb.c
mm/internal.h
mm/kasan/Makefile
mm/kasan/common.c [new file with mode: 0644]
mm/kasan/generic.c [new file with mode: 0644]
mm/kasan/generic_report.c [new file with mode: 0644]
mm/kasan/init.c [new file with mode: 0644]
mm/kasan/kasan.c [deleted file]
mm/kasan/kasan.h
mm/kasan/kasan_init.c [deleted file]
mm/kasan/quarantine.c
mm/kasan/report.c
mm/kasan/tags.c [new file with mode: 0644]
mm/kasan/tags_report.c [new file with mode: 0644]
mm/khugepaged.c
mm/kmemleak.c
mm/ksm.c
mm/madvise.c
mm/memblock.c
mm/memcontrol.c
mm/memory-failure.c
mm/memory.c
mm/memory_hotplug.c
mm/migrate.c
mm/mm_init.c
mm/mmap.c
mm/mmu_notifier.c
mm/mprotect.c
mm/mremap.c
mm/oom_kill.c
mm/page-writeback.c
mm/page_alloc.c
mm/page_isolation.c
mm/page_owner.c
mm/readahead.c
mm/rmap.c
mm/shmem.c
mm/slab.c
mm/slab.h
mm/slab_common.c
mm/slub.c
mm/sparse.c
mm/swap.c
mm/swapfile.c
mm/userfaultfd.c
mm/util.c
mm/vmalloc.c
mm/vmscan.c
mm/vmstat.c
mm/workingset.c
mm/zswap.c
net/dccp/proto.c
net/decnet/dn_route.c
net/ipv4/tcp_metrics.c
net/netfilter/nf_conntrack_core.c
net/netfilter/xt_hashlimit.c
net/sctp/protocol.c
scripts/Makefile.kasan
scripts/bloat-o-meter
scripts/checkstack.pl
scripts/decode_stacktrace.sh
scripts/decodecode
scripts/spdxcheck-test.sh [new file with mode: 0644]
scripts/tags.sh
security/integrity/ima/ima_kexec.c
tools/testing/nvdimm/test/iomap.c
tools/vm/page-types.c
virt/kvm/kvm_main.c

index c1513c756af125ce5adb76ee8e4522e25572a099..9d2339a485c8ab17b2dd13979e139bb1309db8eb 100644 (file)
@@ -98,3 +98,35 @@ Description:
                The backing_dev file is read-write and set up backing
                device for zram to write incompressible pages.
                For using, user should enable CONFIG_ZRAM_WRITEBACK.
+
+What:          /sys/block/zram<id>/idle
+Date:          November 2018
+Contact:       Minchan Kim <minchan@kernel.org>
+Description:
+               idle file is write-only and mark zram slot as idle.
+               If system has mounted debugfs, user can see which slots
+               are idle via /sys/kernel/debug/zram/zram<id>/block_state
+
+What:          /sys/block/zram<id>/writeback
+Date:          November 2018
+Contact:       Minchan Kim <minchan@kernel.org>
+Description:
+               The writeback file is write-only and trigger idle and/or
+               huge page writeback to backing device.
+
+What:          /sys/block/zram<id>/bd_stat
+Date:          November 2018
+Contact:       Minchan Kim <minchan@kernel.org>
+Description:
+               The bd_stat file is read-only and represents backing device's
+               statistics (bd_count, bd_reads, bd_writes) in a format
+               similar to block layer statistics file format.
+
+What:          /sys/block/zram<id>/writeback_limit
+Date:          November 2018
+Contact:       Minchan Kim <minchan@kernel.org>
+Description:
+               The writeback_limit file is read-write and specifies the maximum
+               amount of writeback ZRAM can do. The limit could be changed
+               in run time and "0" means disable the limit.
+               No limit is the initial state.
index 3c1b5ab54bc07a487517c1441adc408b170cf5fa..436c5e98e1b6038511ac5bc1ac9ffd83e418d8ff 100644 (file)
@@ -164,11 +164,14 @@ reset             WO    trigger device reset
 mem_used_max      WO    reset the `mem_used_max' counter (see later)
 mem_limit         WO    specifies the maximum amount of memory ZRAM can use
                         to store the compressed data
+writeback_limit   WO    specifies the maximum amount of write IO zram can
+                       write out to backing device as 4KB unit
 max_comp_streams  RW    the number of possible concurrent compress operations
 comp_algorithm    RW    show and change the compression algorithm
 compact           WO    trigger memory compaction
 debug_stat        RO    this file is used for zram debugging purposes
 backing_dev      RW    set up backend storage for zram to write out
+idle             WO    mark allocated slot as idle
 
 
 User space is advised to use the following files to read the device statistics.
@@ -220,6 +223,17 @@ line of text and contains the following stats separated by whitespace:
  pages_compacted  the number of pages freed during compaction
  huge_pages      the number of incompressible pages
 
+File /sys/block/zram<id>/bd_stat
+
+The stat file represents device's backing device statistics. It consists of
+a single line of text and contains the following stats separated by whitespace:
+ bd_count      size of data written in backing device.
+               Unit: 4K bytes
+ bd_reads      the number of reads from backing device
+               Unit: 4K bytes
+ bd_writes     the number of writes to backing device
+               Unit: 4K bytes
+
 9) Deactivate:
        swapoff /dev/zram0
        umount /dev/zram1
@@ -237,11 +251,60 @@ line of text and contains the following stats separated by whitespace:
 
 = writeback
 
-With incompressible pages, there is no memory saving with zram.
-Instead, with CONFIG_ZRAM_WRITEBACK, zram can write incompressible page
+With CONFIG_ZRAM_WRITEBACK, zram can write idle/incompressible page
 to backing storage rather than keeping it in memory.
-User should set up backing device via /sys/block/zramX/backing_dev
-before disksize setting.
+To use the feature, admin should set up backing device via
+
+       "echo /dev/sda5 > /sys/block/zramX/backing_dev"
+
+before disksize setting. It supports only partition at this moment.
+If admin want to use incompressible page writeback, they could do via
+
+       "echo huge > /sys/block/zramX/write"
+
+To use idle page writeback, first, user need to declare zram pages
+as idle.
+
+       "echo all > /sys/block/zramX/idle"
+
+From now on, any pages on zram are idle pages. The idle mark
+will be removed until someone request access of the block.
+IOW, unless there is access request, those pages are still idle pages.
+
+Admin can request writeback of those idle pages at right timing via
+
+       "echo idle > /sys/block/zramX/writeback"
+
+With the command, zram writeback idle pages from memory to the storage.
+
+If there are lots of write IO with flash device, potentially, it has
+flash wearout problem so that admin needs to design write limitation
+to guarantee storage health for entire product life.
+To overcome the concern, zram supports "writeback_limit".
+The "writeback_limit"'s default value is 0 so that it doesn't limit
+any writeback. If admin want to measure writeback count in a certain
+period, he could know it via /sys/block/zram0/bd_stat's 3rd column.
+
+If admin want to limit writeback as per-day 400M, he could do it
+like below.
+
+    MB_SHIFT=20
+    4K_SHIFT=12
+    echo $((400<<MB_SHIFT>>4K_SHIFT)) > \
+           /sys/block/zram0/writeback_limit.
+
+If admin want to allow further write again, he could do it like below
+
+    echo 0 > /sys/block/zram0/writeback_limit
+
+If admin want to see remaining writeback budget since he set,
+
+    cat /sys/block/zram0/writeback_limit
+
+The writeback_limit count will reset whenever you reset zram(e.g.,
+system reboot, echo 1 > /sys/block/zramX/reset) so keeping how many of
+writeback happened until you reset the zram to allocate extra writeback
+budget in next setting is user's job.
 
 = memory tracking
 
@@ -251,16 +314,17 @@ pages of the process with*pagemap.
 If you enable the feature, you could see block state via
 /sys/kernel/debug/zram/zram0/block_state". The output is as follows,
 
-         300    75.033841 .wh
-         301    63.806904 s..
-         302    63.806919 ..h
+         300    75.033841 .wh.
+         301    63.806904 s...
+         302    63.806919 ..hi
 
 First column is zram's block index.
 Second column is access time since the system was booted
 Third column is state of the block.
 (s: same page
 w: written page to backing store
-h: huge page)
+h: huge page
+i: idle page)
 
 First line of above example says 300th block is accessed at 75.033841sec
 and the block's state is huge so it is written back to the backing
index aabc8738b3d8688bbc41951d79698b9e89f144fb..b72d07d70239c421e683c9df06411f728e114a9e 100644 (file)
@@ -4,15 +4,25 @@ The Kernel Address Sanitizer (KASAN)
 Overview
 --------
 
-KernelAddressSANitizer (KASAN) is a dynamic memory error detector. It provides
-a fast and comprehensive solution for finding use-after-free and out-of-bounds
-bugs.
+KernelAddressSANitizer (KASAN) is a dynamic memory error detector designed to
+find out-of-bound and use-after-free bugs. KASAN has two modes: generic KASAN
+(similar to userspace ASan) and software tag-based KASAN (similar to userspace
+HWASan).
 
-KASAN uses compile-time instrumentation for checking every memory access,
-therefore you will need a GCC version 4.9.2 or later. GCC 5.0 or later is
-required for detection of out-of-bounds accesses to stack or global variables.
+KASAN uses compile-time instrumentation to insert validity checks before every
+memory access, and therefore requires a compiler version that supports that.
 
-Currently KASAN is supported only for the x86_64 and arm64 architectures.
+Generic KASAN is supported in both GCC and Clang. With GCC it requires version
+4.9.2 or later for basic support and version 5.0 or later for detection of
+out-of-bounds accesses for stack and global variables and for inline
+instrumentation mode (see the Usage section). With Clang it requires version
+7.0.0 or later and it doesn't support detection of out-of-bounds accesses for
+global variables yet.
+
+Tag-based KASAN is only supported in Clang and requires version 7.0.0 or later.
+
+Currently generic KASAN is supported for the x86_64, arm64, xtensa and s390
+architectures, and tag-based KASAN is supported only for arm64.
 
 Usage
 -----
@@ -21,12 +31,14 @@ To enable KASAN configure kernel with::
 
          CONFIG_KASAN = y
 
-and choose between CONFIG_KASAN_OUTLINE and CONFIG_KASAN_INLINE. Outline and
-inline are compiler instrumentation types. The former produces smaller binary
-the latter is 1.1 - 2 times faster. Inline instrumentation requires a GCC
-version 5.0 or later.
+and choose between CONFIG_KASAN_GENERIC (to enable generic KASAN) and
+CONFIG_KASAN_SW_TAGS (to enable software tag-based KASAN).
+
+You also need to choose between CONFIG_KASAN_OUTLINE and CONFIG_KASAN_INLINE.
+Outline and inline are compiler instrumentation types. The former produces
+smaller binary while the latter is 1.1 - 2 times faster.
 
-KASAN works with both SLUB and SLAB memory allocators.
+Both KASAN modes work with both SLUB and SLAB memory allocators.
 For better bug detection and nicer reporting, enable CONFIG_STACKTRACE.
 
 To disable instrumentation for specific files or directories, add a line
@@ -43,85 +55,85 @@ similar to the following to the respective kernel Makefile:
 Error reports
 ~~~~~~~~~~~~~
 
-A typical out of bounds access report looks like this::
+A typical out-of-bounds access generic KASAN report looks like this::
 
     ==================================================================
-    BUG: AddressSanitizer: out of bounds access in kmalloc_oob_right+0x65/0x75 [test_kasan] at addr ffff8800693bc5d3
-    Write of size 1 by task modprobe/1689
-    =============================================================================
-    BUG kmalloc-128 (Not tainted): kasan error
-    -----------------------------------------------------------------------------
-
-    Disabling lock debugging due to kernel taint
-    INFO: Allocated in kmalloc_oob_right+0x3d/0x75 [test_kasan] age=0 cpu=0 pid=1689
-     __slab_alloc+0x4b4/0x4f0
-     kmem_cache_alloc_trace+0x10b/0x190
-     kmalloc_oob_right+0x3d/0x75 [test_kasan]
-     init_module+0x9/0x47 [test_kasan]
-     do_one_initcall+0x99/0x200
-     load_module+0x2cb3/0x3b20
-     SyS_finit_module+0x76/0x80
-     system_call_fastpath+0x12/0x17
-    INFO: Slab 0xffffea0001a4ef00 objects=17 used=7 fp=0xffff8800693bd728 flags=0x100000000004080
-    INFO: Object 0xffff8800693bc558 @offset=1368 fp=0xffff8800693bc720
-
-    Bytes b4 ffff8800693bc548: 00 00 00 00 00 00 00 00 5a 5a 5a 5a 5a 5a 5a 5a  ........ZZZZZZZZ
-    Object ffff8800693bc558: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
-    Object ffff8800693bc568: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
-    Object ffff8800693bc578: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
-    Object ffff8800693bc588: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
-    Object ffff8800693bc598: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
-    Object ffff8800693bc5a8: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
-    Object ffff8800693bc5b8: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
-    Object ffff8800693bc5c8: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b a5  kkkkkkkkkkkkkkk.
-    Redzone ffff8800693bc5d8: cc cc cc cc cc cc cc cc                          ........
-    Padding ffff8800693bc718: 5a 5a 5a 5a 5a 5a 5a 5a                          ZZZZZZZZ
-    CPU: 0 PID: 1689 Comm: modprobe Tainted: G    B          3.18.0-rc1-mm1+ #98
-    Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.7.5-0-ge51488c-20140602_164612-nilsson.home.kraxel.org 04/01/2014
-     ffff8800693bc000 0000000000000000 ffff8800693bc558 ffff88006923bb78
-     ffffffff81cc68ae 00000000000000f3 ffff88006d407600 ffff88006923bba8
-     ffffffff811fd848 ffff88006d407600 ffffea0001a4ef00 ffff8800693bc558
+    BUG: KASAN: slab-out-of-bounds in kmalloc_oob_right+0xa8/0xbc [test_kasan]
+    Write of size 1 at addr ffff8801f44ec37b by task insmod/2760
+
+    CPU: 1 PID: 2760 Comm: insmod Not tainted 4.19.0-rc3+ #698
+    Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-1 04/01/2014
     Call Trace:
-     [<ffffffff81cc68ae>] dump_stack+0x46/0x58
-     [<ffffffff811fd848>] print_trailer+0xf8/0x160
-     [<ffffffffa00026a7>] ? kmem_cache_oob+0xc3/0xc3 [test_kasan]
-     [<ffffffff811ff0f5>] object_err+0x35/0x40
-     [<ffffffffa0002065>] ? kmalloc_oob_right+0x65/0x75 [test_kasan]
-     [<ffffffff8120b9fa>] kasan_report_error+0x38a/0x3f0
-     [<ffffffff8120a79f>] ? kasan_poison_shadow+0x2f/0x40
-     [<ffffffff8120b344>] ? kasan_unpoison_shadow+0x14/0x40
-     [<ffffffff8120a79f>] ? kasan_poison_shadow+0x2f/0x40
-     [<ffffffffa00026a7>] ? kmem_cache_oob+0xc3/0xc3 [test_kasan]
-     [<ffffffff8120a995>] __asan_store1+0x75/0xb0
-     [<ffffffffa0002601>] ? kmem_cache_oob+0x1d/0xc3 [test_kasan]
-     [<ffffffffa0002065>] ? kmalloc_oob_right+0x65/0x75 [test_kasan]
-     [<ffffffffa0002065>] kmalloc_oob_right+0x65/0x75 [test_kasan]
-     [<ffffffffa00026b0>] init_module+0x9/0x47 [test_kasan]
-     [<ffffffff810002d9>] do_one_initcall+0x99/0x200
-     [<ffffffff811e4e5c>] ? __vunmap+0xec/0x160
-     [<ffffffff81114f63>] load_module+0x2cb3/0x3b20
-     [<ffffffff8110fd70>] ? m_show+0x240/0x240
-     [<ffffffff81115f06>] SyS_finit_module+0x76/0x80
-     [<ffffffff81cd3129>] system_call_fastpath+0x12/0x17
+     dump_stack+0x94/0xd8
+     print_address_description+0x73/0x280
+     kasan_report+0x144/0x187
+     __asan_report_store1_noabort+0x17/0x20
+     kmalloc_oob_right+0xa8/0xbc [test_kasan]
+     kmalloc_tests_init+0x16/0x700 [test_kasan]
+     do_one_initcall+0xa5/0x3ae
+     do_init_module+0x1b6/0x547
+     load_module+0x75df/0x8070
+     __do_sys_init_module+0x1c6/0x200
+     __x64_sys_init_module+0x6e/0xb0
+     do_syscall_64+0x9f/0x2c0
+     entry_SYSCALL_64_after_hwframe+0x44/0xa9
+    RIP: 0033:0x7f96443109da
+    RSP: 002b:00007ffcf0b51b08 EFLAGS: 00000202 ORIG_RAX: 00000000000000af
+    RAX: ffffffffffffffda RBX: 000055dc3ee521a0 RCX: 00007f96443109da
+    RDX: 00007f96445cff88 RSI: 0000000000057a50 RDI: 00007f9644992000
+    RBP: 000055dc3ee510b0 R08: 0000000000000003 R09: 0000000000000000
+    R10: 00007f964430cd0a R11: 0000000000000202 R12: 00007f96445cff88
+    R13: 000055dc3ee51090 R14: 0000000000000000 R15: 0000000000000000
+
+    Allocated by task 2760:
+     save_stack+0x43/0xd0
+     kasan_kmalloc+0xa7/0xd0
+     kmem_cache_alloc_trace+0xe1/0x1b0
+     kmalloc_oob_right+0x56/0xbc [test_kasan]
+     kmalloc_tests_init+0x16/0x700 [test_kasan]
+     do_one_initcall+0xa5/0x3ae
+     do_init_module+0x1b6/0x547
+     load_module+0x75df/0x8070
+     __do_sys_init_module+0x1c6/0x200
+     __x64_sys_init_module+0x6e/0xb0
+     do_syscall_64+0x9f/0x2c0
+     entry_SYSCALL_64_after_hwframe+0x44/0xa9
+
+    Freed by task 815:
+     save_stack+0x43/0xd0
+     __kasan_slab_free+0x135/0x190
+     kasan_slab_free+0xe/0x10
+     kfree+0x93/0x1a0
+     umh_complete+0x6a/0xa0
+     call_usermodehelper_exec_async+0x4c3/0x640
+     ret_from_fork+0x35/0x40
+
+    The buggy address belongs to the object at ffff8801f44ec300
+     which belongs to the cache kmalloc-128 of size 128
+    The buggy address is located 123 bytes inside of
+     128-byte region [ffff8801f44ec300, ffff8801f44ec380)
+    The buggy address belongs to the page:
+    page:ffffea0007d13b00 count:1 mapcount:0 mapping:ffff8801f7001640 index:0x0
+    flags: 0x200000000000100(slab)
+    raw: 0200000000000100 ffffea0007d11dc0 0000001a0000001a ffff8801f7001640
+    raw: 0000000000000000 0000000080150015 00000001ffffffff 0000000000000000
+    page dumped because: kasan: bad access detected
+
     Memory state around the buggy address:
-     ffff8800693bc300: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
-     ffff8800693bc380: fc fc 00 00 00 00 00 00 00 00 00 00 00 00 00 fc
-     ffff8800693bc400: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
-     ffff8800693bc480: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
-     ffff8800693bc500: fc fc fc fc fc fc fc fc fc fc fc 00 00 00 00 00
-    >ffff8800693bc580: 00 00 00 00 00 00 00 00 00 00 03 fc fc fc fc fc
-                                                 ^
-     ffff8800693bc600: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
-     ffff8800693bc680: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
-     ffff8800693bc700: fc fc fc fc fb fb fb fb fb fb fb fb fb fb fb fb
-     ffff8800693bc780: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
-     ffff8800693bc800: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
+     ffff8801f44ec200: fc fc fc fc fc fc fc fc fb fb fb fb fb fb fb fb
+     ffff8801f44ec280: fb fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc
+    >ffff8801f44ec300: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 03
+                                                                    ^
+     ffff8801f44ec380: fc fc fc fc fc fc fc fc fb fb fb fb fb fb fb fb
+     ffff8801f44ec400: fb fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc
     ==================================================================
 
-The header of the report discribe what kind of bug happened and what kind of
-access caused it. It's followed by the description of the accessed slub object
-(see 'SLUB Debug output' section in Documentation/vm/slub.rst for details) and
-the description of the accessed memory page.
+The header of the report provides a short summary of what kind of bug happened
+and what kind of access caused it. It's followed by a stack trace of the bad
+access, a stack trace of where the accessed memory was allocated (in case bad
+access happens on a slab object), and a stack trace of where the object was
+freed (in case of a use-after-free bug report). Next comes a description of
+the accessed slab object and information about the accessed memory page.
 
 In the last section the report shows memory state around the accessed address.
 Reading this part requires some understanding of how KASAN works.
@@ -138,18 +150,24 @@ inaccessible memory like redzones or freed memory (see mm/kasan/kasan.h).
 In the report above the arrows point to the shadow byte 03, which means that
 the accessed address is partially accessible.
 
+For tag-based KASAN this last report section shows the memory tags around the
+accessed address (see Implementation details section).
+
 
 Implementation details
 ----------------------
 
+Generic KASAN
+~~~~~~~~~~~~~
+
 From a high level, our approach to memory error detection is similar to that
 of kmemcheck: use shadow memory to record whether each byte of memory is safe
-to access, and use compile-time instrumentation to check shadow memory on each
-memory access.
+to access, and use compile-time instrumentation to insert checks of shadow
+memory on each memory access.
 
-AddressSanitizer dedicates 1/8 of kernel memory to its shadow memory
-(e.g. 16TB to cover 128TB on x86_64) and uses direct mapping with a scale and
-offset to translate a memory address to its corresponding shadow address.
+Generic KASAN dedicates 1/8th of kernel memory to its shadow memory (e.g. 16TB
+to cover 128TB on x86_64) and uses direct mapping with a scale and offset to
+translate a memory address to its corresponding shadow address.
 
 Here is the function which translates an address to its corresponding shadow
 address::
@@ -162,12 +180,38 @@ address::
 
 where ``KASAN_SHADOW_SCALE_SHIFT = 3``.
 
-Compile-time instrumentation used for checking memory accesses. Compiler inserts
-function calls (__asan_load*(addr), __asan_store*(addr)) before each memory
-access of size 1, 2, 4, 8 or 16. These functions check whether memory access is
-valid or not by checking corresponding shadow memory.
+Compile-time instrumentation is used to insert memory access checks. Compiler
+inserts function calls (__asan_load*(addr), __asan_store*(addr)) before each
+memory access of size 1, 2, 4, 8 or 16. These functions check whether memory
+access is valid or not by checking corresponding shadow memory.
 
 GCC 5.0 has possibility to perform inline instrumentation. Instead of making
 function calls GCC directly inserts the code to check the shadow memory.
 This option significantly enlarges kernel but it gives x1.1-x2 performance
 boost over outline instrumented kernel.
+
+Software tag-based KASAN
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+Tag-based KASAN uses the Top Byte Ignore (TBI) feature of modern arm64 CPUs to
+store a pointer tag in the top byte of kernel pointers. Like generic KASAN it
+uses shadow memory to store memory tags associated with each 16-byte memory
+cell (therefore it dedicates 1/16th of the kernel memory for shadow memory).
+
+On each memory allocation tag-based KASAN generates a random tag, tags the
+allocated memory with this tag, and embeds this tag into the returned pointer.
+Software tag-based KASAN uses compile-time instrumentation to insert checks
+before each memory access. These checks make sure that tag of the memory that
+is being accessed is equal to tag of the pointer that is used to access this
+memory. In case of a tag mismatch tag-based KASAN prints a bug report.
+
+Software tag-based KASAN also has two instrumentation modes (outline, that
+emits callbacks to check memory accesses; and inline, that performs the shadow
+memory checks inline). With outline instrumentation mode, a bug report is
+simply printed from the function that performs the access check. With inline
+instrumentation a brk instruction is emitted by the compiler, and a dedicated
+brk handler is used to print bug reports.
+
+A potential expansion of this mode is a hardware tag-based mode, which would
+use hardware memory tagging support instead of compiler instrumentation and
+manual shadow memory manipulation.
index 12a5e6e693b6e4f516ffb85d78677aff53ab81b0..b24fd9bccc990f71c6aab823851108a7c8773345 100644 (file)
@@ -182,6 +182,7 @@ read the file /proc/PID/status:
   VmSwap:        0 kB
   HugetlbPages:          0 kB
   CoreDumping:    0
+  THP_enabled:   1
   Threads:        1
   SigQ:   0/28578
   SigPnd: 0000000000000000
@@ -256,6 +257,8 @@ Table 1-2: Contents of the status files (as of 4.8)
  HugetlbPages                size of hugetlb memory portions
  CoreDumping                 process's memory is currently being dumped
                              (killing the process may lead to a corrupted core)
+ THP_enabled                process is allowed to use THP (returns 0 when
+                            PR_SET_THP_DISABLE is set on the process
  Threads                     number of threads
  SigQ                        number of signals queued/max. number for queue
  SigPnd                      bitmap of pending signals for the thread
@@ -425,6 +428,7 @@ SwapPss:               0 kB
 KernelPageSize:        4 kB
 MMUPageSize:           4 kB
 Locked:                0 kB
+THPeligible:           0
 VmFlags: rd ex mr mw me dw
 
 the first of these lines shows the same information as is displayed for the
@@ -462,6 +466,8 @@ replaced by copy-on-write) part of the underlying shmem object out on swap.
 "SwapPss" shows proportional swap share of this mapping. Unlike "Swap", this
 does not take into account swapped out page of underlying shmem objects.
 "Locked" indicates whether the mapping is locked in memory or not.
+"THPeligible" indicates whether the mapping is eligible for THP pages - 1 if
+true, 0 otherwise.
 
 "VmFlags" field deserves a separate description. This member represents the kernel
 flags associated with the particular virtual memory area in two letter encoded
@@ -496,7 +502,9 @@ manner. The codes are the following:
 
 Note that there is no guarantee that every flag and associated mnemonic will
 be present in all further kernel releases. Things get changed, the flags may
-be vanished or the reverse -- new added.
+be vanished or the reverse -- new added. Interpretation of their meaning
+might change in future as well. So each consumer of these flags has to
+follow each specific kernel version for the exact semantic.
 
 This file is only present if the CONFIG_MMU kernel configuration option is
 enabled.
index 7d73882e2c273c57d1277c701b71a1774b22763c..187ce4f599a267eed30f655b81580a89b45ce33c 100644 (file)
@@ -63,6 +63,7 @@ Currently, these files are in /proc/sys/vm:
 - swappiness
 - user_reserve_kbytes
 - vfs_cache_pressure
+- watermark_boost_factor
 - watermark_scale_factor
 - zone_reclaim_mode
 
@@ -856,6 +857,26 @@ ten times more freeable objects than there are.
 
 =============================================================
 
+watermark_boost_factor:
+
+This factor controls the level of reclaim when memory is being fragmented.
+It defines the percentage of the high watermark of a zone that will be
+reclaimed if pages of different mobility are being mixed within pageblocks.
+The intent is that compaction has less work to do in the future and to
+increase the success rate of future high-order allocations such as SLUB
+allocations, THP and hugetlbfs pages.
+
+To make it sensible with respect to the watermark_scale_factor parameter,
+the unit is in fractions of 10,000. The default value of 15,000 means
+that up to 150% of the high watermark will be reclaimed in the event of
+a pageblock being mixed due to fragmentation. The level of reclaim is
+determined by the number of fragmentation events that occurred in the
+recent past. If this value is smaller than a pageblock then a pageblocks
+worth of pages will be reclaimed (e.g.  2MB on 64-bit x86). A boost factor
+of 0 will disable the feature.
+
+=============================================================
+
 watermark_scale_factor:
 
 This factor controls the aggressiveness of kswapd. It defines the
index ff9291872372ad9456670ba17bca4b9580733c30..86b18c1bd33c84665dc776e8e4868021c16c5847 100644 (file)
@@ -110,6 +110,7 @@ config ARM64
        select HAVE_ARCH_JUMP_LABEL
        select HAVE_ARCH_JUMP_LABEL_RELATIVE
        select HAVE_ARCH_KASAN if !(ARM64_16K_PAGES && ARM64_VA_BITS_48)
+       select HAVE_ARCH_KASAN_SW_TAGS if HAVE_ARCH_KASAN
        select HAVE_ARCH_KGDB
        select HAVE_ARCH_MMAP_RND_BITS
        select HAVE_ARCH_MMAP_RND_COMPAT_BITS if COMPAT
index 398bdb81a9004345c0947e7bcdb82da4042e877c..b025304bde46206a68c7537a8613830f3a07f144 100644 (file)
@@ -101,10 +101,19 @@ else
 TEXT_OFFSET := 0x00080000
 endif
 
+ifeq ($(CONFIG_KASAN_SW_TAGS), y)
+KASAN_SHADOW_SCALE_SHIFT := 4
+else
+KASAN_SHADOW_SCALE_SHIFT := 3
+endif
+
+KBUILD_CFLAGS += -DKASAN_SHADOW_SCALE_SHIFT=$(KASAN_SHADOW_SCALE_SHIFT)
+KBUILD_CPPFLAGS += -DKASAN_SHADOW_SCALE_SHIFT=$(KASAN_SHADOW_SCALE_SHIFT)
+KBUILD_AFLAGS += -DKASAN_SHADOW_SCALE_SHIFT=$(KASAN_SHADOW_SCALE_SHIFT)
+
 # KASAN_SHADOW_OFFSET = VA_START + (1 << (VA_BITS - KASAN_SHADOW_SCALE_SHIFT))
 #                               - (1 << (64 - KASAN_SHADOW_SCALE_SHIFT))
 # in 32-bit arithmetic
-KASAN_SHADOW_SCALE_SHIFT := 3
 KASAN_SHADOW_OFFSET := $(shell printf "0x%08x00000000\n" $$(( \
        (0xffffffff & (-1 << ($(CONFIG_ARM64_VA_BITS) - 32))) \
        + (1 << ($(CONFIG_ARM64_VA_BITS) - 32 - $(KASAN_SHADOW_SCALE_SHIFT))) \
index ed693c5bcec06a69ad396b0096f5b55e4f9cac54..2945fe6cd863c2712451d13f544b961de13a6ea1 100644 (file)
  * 0x400: for dynamic BRK instruction
  * 0x401: for compile time BRK instruction
  * 0x800: kernel-mode BUG() and WARN() traps
+ * 0x9xx: tag-based KASAN trap (allowed values 0x900 - 0x9ff)
  */
 #define FAULT_BRK_IMM                  0x100
 #define KGDB_DYN_DBG_BRK_IMM           0x400
 #define KGDB_COMPILED_DBG_BRK_IMM      0x401
 #define BUG_BRK_IMM                    0x800
+#define KASAN_BRK_IMM                  0x900
 
 #endif
index 8758bb008436d4e3fb6a5b119c55fa07d0186bbb..b52aacd2c5261ada9d417f2a6de2dbb96658ff1c 100644 (file)
@@ -4,12 +4,16 @@
 
 #ifndef __ASSEMBLY__
 
-#ifdef CONFIG_KASAN
-
 #include <linux/linkage.h>
 #include <asm/memory.h>
 #include <asm/pgtable-types.h>
 
+#define arch_kasan_set_tag(addr, tag)  __tag_set(addr, tag)
+#define arch_kasan_reset_tag(addr)     __tag_reset(addr)
+#define arch_kasan_get_tag(addr)       __tag_get(addr)
+
+#ifdef CONFIG_KASAN
+
 /*
  * KASAN_SHADOW_START: beginning of the kernel virtual addresses.
  * KASAN_SHADOW_END: KASAN_SHADOW_START + 1/N of kernel virtual addresses,
index 0385752bd079b61cc1f40a80c934cf2f30ed83f2..2bb8721da7ef0ff9aaecb65066e1c0db2ebbcdea 100644 (file)
 #endif
 
 /*
- * KASAN requires 1/8th of the kernel virtual address space for the shadow
- * region. KASAN can bloat the stack significantly, so double the (minimum)
- * stack size when KASAN is in use, and then double it again if KASAN_EXTRA is
- * on.
+ * Generic and tag-based KASAN require 1/8th and 1/16th of the kernel virtual
+ * address space for the shadow region respectively. They can bloat the stack
+ * significantly, so double the (minimum) stack size when they are in use.
  */
 #ifdef CONFIG_KASAN
-#define KASAN_SHADOW_SCALE_SHIFT 3
 #define KASAN_SHADOW_SIZE      (UL(1) << (VA_BITS - KASAN_SHADOW_SCALE_SHIFT))
 #ifdef CONFIG_KASAN_EXTRA
 #define KASAN_THREAD_SHIFT     2
@@ -220,6 +218,26 @@ extern u64                 vabits_user;
  */
 #define PHYS_PFN_OFFSET        (PHYS_OFFSET >> PAGE_SHIFT)
 
+/*
+ * When dealing with data aborts, watchpoints, or instruction traps we may end
+ * up with a tagged userland pointer. Clear the tag to get a sane pointer to
+ * pass on to access_ok(), for instance.
+ */
+#define untagged_addr(addr)    \
+       ((__typeof__(addr))sign_extend64((u64)(addr), 55))
+
+#ifdef CONFIG_KASAN_SW_TAGS
+#define __tag_shifted(tag)     ((u64)(tag) << 56)
+#define __tag_set(addr, tag)   (__typeof__(addr))( \
+               ((u64)(addr) & ~__tag_shifted(0xff)) | __tag_shifted(tag))
+#define __tag_reset(addr)      untagged_addr(addr)
+#define __tag_get(addr)                (__u8)((u64)(addr) >> 56)
+#else
+#define __tag_set(addr, tag)   (addr)
+#define __tag_reset(addr)      (addr)
+#define __tag_get(addr)                0
+#endif
+
 /*
  * Physical vs virtual RAM address space conversion.  These are
  * private definitions which should NOT be used outside memory.h
@@ -303,7 +321,13 @@ static inline void *phys_to_virt(phys_addr_t x)
 #define __virt_to_pgoff(kaddr) (((u64)(kaddr) & ~PAGE_OFFSET) / PAGE_SIZE * sizeof(struct page))
 #define __page_to_voff(kaddr)  (((u64)(kaddr) & ~VMEMMAP_START) * PAGE_SIZE / sizeof(struct page))
 
-#define page_to_virt(page)     ((void *)((__page_to_voff(page)) | PAGE_OFFSET))
+#define page_to_virt(page)     ({                                      \
+       unsigned long __addr =                                          \
+               ((__page_to_voff(page)) | PAGE_OFFSET);                 \
+       __addr = __tag_set(__addr, page_kasan_tag(page));               \
+       ((void *)__addr);                                               \
+})
+
 #define virt_to_page(vaddr)    ((struct page *)((__virt_to_pgoff(vaddr)) | VMEMMAP_START))
 
 #define _virt_addr_valid(kaddr)        pfn_valid((((u64)(kaddr) & ~PAGE_OFFSET) \
@@ -311,9 +335,10 @@ static inline void *phys_to_virt(phys_addr_t x)
 #endif
 #endif
 
-#define _virt_addr_is_linear(kaddr)    (((u64)(kaddr)) >= PAGE_OFFSET)
-#define virt_addr_valid(kaddr)         (_virt_addr_is_linear(kaddr) && \
-                                        _virt_addr_valid(kaddr))
+#define _virt_addr_is_linear(kaddr)    \
+       (__tag_reset((u64)(kaddr)) >= PAGE_OFFSET)
+#define virt_addr_valid(kaddr)         \
+       (_virt_addr_is_linear(kaddr) && _virt_addr_valid(kaddr))
 
 #include <asm-generic/memory_model.h>
 
index 22bb3ae514f55845bf658416432f56bc8a411355..e9b0a7d751848e447e7023b286ffc39cffb53999 100644 (file)
 #define TCR_A1                 (UL(1) << 22)
 #define TCR_ASID16             (UL(1) << 36)
 #define TCR_TBI0               (UL(1) << 37)
+#define TCR_TBI1               (UL(1) << 38)
 #define TCR_HA                 (UL(1) << 39)
 #define TCR_HD                 (UL(1) << 40)
 #define TCR_NFD1               (UL(1) << 54)
index fad33f5fde47e41610ac9adbda9ad2a0175294d5..ed252435fd92484cde9d0c04a36ba27b35605948 100644 (file)
@@ -95,13 +95,6 @@ static inline unsigned long __range_ok(const void __user *addr, unsigned long si
        return ret;
 }
 
-/*
- * When dealing with data aborts, watchpoints, or instruction traps we may end
- * up with a tagged userland pointer. Clear the tag to get a sane pointer to
- * pass on to access_ok(), for instance.
- */
-#define untagged_addr(addr)            sign_extend64(addr, 55)
-
 #define access_ok(type, addr, size)    __range_ok(addr, size)
 #define user_addr_max                  get_fs
 
index 5f4d9acb32f50ea3fb13c35c3cc5cd5b5514a548..cdc71cf70aad4027f9638ebae8454e719ef3900a 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/sizes.h>
 #include <linux/syscalls.h>
 #include <linux/mm_types.h>
+#include <linux/kasan.h>
 
 #include <asm/atomic.h>
 #include <asm/bug.h>
@@ -969,6 +970,58 @@ static struct break_hook bug_break_hook = {
        .fn = bug_handler,
 };
 
+#ifdef CONFIG_KASAN_SW_TAGS
+
+#define KASAN_ESR_RECOVER      0x20
+#define KASAN_ESR_WRITE        0x10
+#define KASAN_ESR_SIZE_MASK    0x0f
+#define KASAN_ESR_SIZE(esr)    (1 << ((esr) & KASAN_ESR_SIZE_MASK))
+
+static int kasan_handler(struct pt_regs *regs, unsigned int esr)
+{
+       bool recover = esr & KASAN_ESR_RECOVER;
+       bool write = esr & KASAN_ESR_WRITE;
+       size_t size = KASAN_ESR_SIZE(esr);
+       u64 addr = regs->regs[0];
+       u64 pc = regs->pc;
+
+       if (user_mode(regs))
+               return DBG_HOOK_ERROR;
+
+       kasan_report(addr, size, write, pc);
+
+       /*
+        * The instrumentation allows to control whether we can proceed after
+        * a crash was detected. This is done by passing the -recover flag to
+        * the compiler. Disabling recovery allows to generate more compact
+        * code.
+        *
+        * Unfortunately disabling recovery doesn't work for the kernel right
+        * now. KASAN reporting is disabled in some contexts (for example when
+        * the allocator accesses slab object metadata; this is controlled by
+        * current->kasan_depth). All these accesses are detected by the tool,
+        * even though the reports for them are not printed.
+        *
+        * This is something that might be fixed at some point in the future.
+        */
+       if (!recover)
+               die("Oops - KASAN", regs, 0);
+
+       /* If thread survives, skip over the brk instruction and continue: */
+       arm64_skip_faulting_instruction(regs, AARCH64_INSN_SIZE);
+       return DBG_HOOK_HANDLED;
+}
+
+#define KASAN_ESR_VAL (0xf2000000 | KASAN_BRK_IMM)
+#define KASAN_ESR_MASK 0xffffff00
+
+static struct break_hook kasan_break_hook = {
+       .esr_val = KASAN_ESR_VAL,
+       .esr_mask = KASAN_ESR_MASK,
+       .fn = kasan_handler,
+};
+#endif
+
 /*
  * Initial handler for AArch64 BRK exceptions
  * This handler only used until debug_traps_init().
@@ -976,6 +1029,10 @@ static struct break_hook bug_break_hook = {
 int __init early_brk64(unsigned long addr, unsigned int esr,
                struct pt_regs *regs)
 {
+#ifdef CONFIG_KASAN_SW_TAGS
+       if ((esr & KASAN_ESR_MASK) == KASAN_ESR_VAL)
+               return kasan_handler(regs, esr) != DBG_HOOK_HANDLED;
+#endif
        return bug_handler(regs, esr) != DBG_HOOK_HANDLED;
 }
 
@@ -983,4 +1040,7 @@ int __init early_brk64(unsigned long addr, unsigned int esr,
 void __init trap_init(void)
 {
        register_break_hook(&bug_break_hook);
+#ifdef CONFIG_KASAN_SW_TAGS
+       register_break_hook(&kasan_break_hook);
+#endif
 }
index 5fe6d2e40e9b4be960ce12f73e69e00c3d7bfeef..efb7b2cbead529439b987f77494ff9c3cc18b874 100644 (file)
@@ -40,6 +40,7 @@
 #include <asm/daifflags.h>
 #include <asm/debug-monitors.h>
 #include <asm/esr.h>
+#include <asm/kasan.h>
 #include <asm/sysreg.h>
 #include <asm/system_misc.h>
 #include <asm/pgtable.h>
@@ -132,6 +133,18 @@ static void mem_abort_decode(unsigned int esr)
                data_abort_decode(esr);
 }
 
+static inline bool is_ttbr0_addr(unsigned long addr)
+{
+       /* entry assembly clears tags for TTBR0 addrs */
+       return addr < TASK_SIZE;
+}
+
+static inline bool is_ttbr1_addr(unsigned long addr)
+{
+       /* TTBR1 addresses may have a tag if KASAN_SW_TAGS is in use */
+       return arch_kasan_reset_tag(addr) >= VA_START;
+}
+
 /*
  * Dump out the page tables associated with 'addr' in the currently active mm.
  */
@@ -141,7 +154,7 @@ void show_pte(unsigned long addr)
        pgd_t *pgdp;
        pgd_t pgd;
 
-       if (addr < TASK_SIZE) {
+       if (is_ttbr0_addr(addr)) {
                /* TTBR0 */
                mm = current->active_mm;
                if (mm == &init_mm) {
@@ -149,7 +162,7 @@ void show_pte(unsigned long addr)
                                 addr);
                        return;
                }
-       } else if (addr >= VA_START) {
+       } else if (is_ttbr1_addr(addr)) {
                /* TTBR1 */
                mm = &init_mm;
        } else {
@@ -254,7 +267,7 @@ static inline bool is_el1_permission_fault(unsigned long addr, unsigned int esr,
        if (fsc_type == ESR_ELx_FSC_PERM)
                return true;
 
-       if (addr < TASK_SIZE && system_uses_ttbr0_pan())
+       if (is_ttbr0_addr(addr) && system_uses_ttbr0_pan())
                return fsc_type == ESR_ELx_FSC_FAULT &&
                        (regs->pstate & PSR_PAN_BIT);
 
@@ -319,7 +332,7 @@ static void set_thread_esr(unsigned long address, unsigned int esr)
         * type", so we ignore this wrinkle and just return the translation
         * fault.)
         */
-       if (current->thread.fault_address >= TASK_SIZE) {
+       if (!is_ttbr0_addr(current->thread.fault_address)) {
                switch (ESR_ELx_EC(esr)) {
                case ESR_ELx_EC_DABT_LOW:
                        /*
@@ -455,7 +468,7 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr,
                mm_flags |= FAULT_FLAG_WRITE;
        }
 
-       if (addr < TASK_SIZE && is_el1_permission_fault(addr, esr, regs)) {
+       if (is_ttbr0_addr(addr) && is_el1_permission_fault(addr, esr, regs)) {
                /* regs->orig_addr_limit may be 0 if we entered from EL0 */
                if (regs->orig_addr_limit == KERNEL_DS)
                        die_kernel_fault("access to user memory with fs=KERNEL_DS",
@@ -603,7 +616,7 @@ static int __kprobes do_translation_fault(unsigned long addr,
                                          unsigned int esr,
                                          struct pt_regs *regs)
 {
-       if (addr < TASK_SIZE)
+       if (is_ttbr0_addr(addr))
                return do_page_fault(addr, esr, regs);
 
        do_bad_area(addr, esr, regs);
@@ -758,7 +771,7 @@ asmlinkage void __exception do_el0_ia_bp_hardening(unsigned long addr,
         * re-enabled IRQs. If the address is a kernel address, apply
         * BP hardening prior to enabling IRQs and pre-emption.
         */
-       if (addr > TASK_SIZE)
+       if (!is_ttbr0_addr(addr))
                arm64_apply_bp_hardening();
 
        local_daif_restore(DAIF_PROCCTX);
@@ -771,7 +784,7 @@ asmlinkage void __exception do_sp_pc_abort(unsigned long addr,
                                           struct pt_regs *regs)
 {
        if (user_mode(regs)) {
-               if (instruction_pointer(regs) > TASK_SIZE)
+               if (!is_ttbr0_addr(instruction_pointer(regs)))
                        arm64_apply_bp_hardening();
                local_daif_restore(DAIF_PROCCTX);
        }
@@ -825,7 +838,7 @@ asmlinkage int __exception do_debug_exception(unsigned long addr,
        if (interrupts_enabled(regs))
                trace_hardirqs_off();
 
-       if (user_mode(regs) && instruction_pointer(regs) > TASK_SIZE)
+       if (user_mode(regs) && !is_ttbr0_addr(instruction_pointer(regs)))
                arm64_apply_bp_hardening();
 
        if (!inf->fn(addr, esr, regs)) {
index 63527e585aaceb6163f34898a0f4d389a3d61a03..4b55b15707a33e5a5c7c202977845f86e847bda5 100644 (file)
@@ -39,7 +39,15 @@ static phys_addr_t __init kasan_alloc_zeroed_page(int node)
 {
        void *p = memblock_alloc_try_nid(PAGE_SIZE, PAGE_SIZE,
                                              __pa(MAX_DMA_ADDRESS),
-                                             MEMBLOCK_ALLOC_ACCESSIBLE, node);
+                                             MEMBLOCK_ALLOC_KASAN, node);
+       return __pa(p);
+}
+
+static phys_addr_t __init kasan_alloc_raw_page(int node)
+{
+       void *p = memblock_alloc_try_nid_raw(PAGE_SIZE, PAGE_SIZE,
+                                               __pa(MAX_DMA_ADDRESS),
+                                               MEMBLOCK_ALLOC_KASAN, node);
        return __pa(p);
 }
 
@@ -47,8 +55,9 @@ static pte_t *__init kasan_pte_offset(pmd_t *pmdp, unsigned long addr, int node,
                                      bool early)
 {
        if (pmd_none(READ_ONCE(*pmdp))) {
-               phys_addr_t pte_phys = early ? __pa_symbol(kasan_zero_pte)
-                                            : kasan_alloc_zeroed_page(node);
+               phys_addr_t pte_phys = early ?
+                               __pa_symbol(kasan_early_shadow_pte)
+                                       : kasan_alloc_zeroed_page(node);
                __pmd_populate(pmdp, pte_phys, PMD_TYPE_TABLE);
        }
 
@@ -60,8 +69,9 @@ static pmd_t *__init kasan_pmd_offset(pud_t *pudp, unsigned long addr, int node,
                                      bool early)
 {
        if (pud_none(READ_ONCE(*pudp))) {
-               phys_addr_t pmd_phys = early ? __pa_symbol(kasan_zero_pmd)
-                                            : kasan_alloc_zeroed_page(node);
+               phys_addr_t pmd_phys = early ?
+                               __pa_symbol(kasan_early_shadow_pmd)
+                                       : kasan_alloc_zeroed_page(node);
                __pud_populate(pudp, pmd_phys, PMD_TYPE_TABLE);
        }
 
@@ -72,8 +82,9 @@ static pud_t *__init kasan_pud_offset(pgd_t *pgdp, unsigned long addr, int node,
                                      bool early)
 {
        if (pgd_none(READ_ONCE(*pgdp))) {
-               phys_addr_t pud_phys = early ? __pa_symbol(kasan_zero_pud)
-                                            : kasan_alloc_zeroed_page(node);
+               phys_addr_t pud_phys = early ?
+                               __pa_symbol(kasan_early_shadow_pud)
+                                       : kasan_alloc_zeroed_page(node);
                __pgd_populate(pgdp, pud_phys, PMD_TYPE_TABLE);
        }
 
@@ -87,8 +98,11 @@ static void __init kasan_pte_populate(pmd_t *pmdp, unsigned long addr,
        pte_t *ptep = kasan_pte_offset(pmdp, addr, node, early);
 
        do {
-               phys_addr_t page_phys = early ? __pa_symbol(kasan_zero_page)
-                                             : kasan_alloc_zeroed_page(node);
+               phys_addr_t page_phys = early ?
+                               __pa_symbol(kasan_early_shadow_page)
+                                       : kasan_alloc_raw_page(node);
+               if (!early)
+                       memset(__va(page_phys), KASAN_SHADOW_INIT, PAGE_SIZE);
                next = addr + PAGE_SIZE;
                set_pte(ptep, pfn_pte(__phys_to_pfn(page_phys), PAGE_KERNEL));
        } while (ptep++, addr = next, addr != end && pte_none(READ_ONCE(*ptep)));
@@ -205,14 +219,14 @@ void __init kasan_init(void)
        kasan_map_populate(kimg_shadow_start, kimg_shadow_end,
                           early_pfn_to_nid(virt_to_pfn(lm_alias(_text))));
 
-       kasan_populate_zero_shadow((void *)KASAN_SHADOW_START,
-                                  (void *)mod_shadow_start);
-       kasan_populate_zero_shadow((void *)kimg_shadow_end,
-                                  kasan_mem_to_shadow((void *)PAGE_OFFSET));
+       kasan_populate_early_shadow((void *)KASAN_SHADOW_START,
+                                   (void *)mod_shadow_start);
+       kasan_populate_early_shadow((void *)kimg_shadow_end,
+                                   kasan_mem_to_shadow((void *)PAGE_OFFSET));
 
        if (kimg_shadow_start > mod_shadow_end)
-               kasan_populate_zero_shadow((void *)mod_shadow_end,
-                                          (void *)kimg_shadow_start);
+               kasan_populate_early_shadow((void *)mod_shadow_end,
+                                           (void *)kimg_shadow_start);
 
        for_each_memblock(memory, reg) {
                void *start = (void *)__phys_to_virt(reg->base);
@@ -227,16 +241,19 @@ void __init kasan_init(void)
        }
 
        /*
-        * KAsan may reuse the contents of kasan_zero_pte directly, so we
-        * should make sure that it maps the zero page read-only.
+        * KAsan may reuse the contents of kasan_early_shadow_pte directly,
+        * so we should make sure that it maps the zero page read-only.
         */
        for (i = 0; i < PTRS_PER_PTE; i++)
-               set_pte(&kasan_zero_pte[i],
-                       pfn_pte(sym_to_pfn(kasan_zero_page), PAGE_KERNEL_RO));
+               set_pte(&kasan_early_shadow_pte[i],
+                       pfn_pte(sym_to_pfn(kasan_early_shadow_page),
+                               PAGE_KERNEL_RO));
 
-       memset(kasan_zero_page, 0, PAGE_SIZE);
+       memset(kasan_early_shadow_page, KASAN_SHADOW_INIT, PAGE_SIZE);
        cpu_replace_ttbr1(lm_alias(swapper_pg_dir));
 
+       kasan_init_tags();
+
        /* At this point kasan is fully initialized. Enable error messages */
        init_task.kasan_depth = 0;
        pr_info("KernelAddressSanitizer initialized\n");
index da513a1facf4fc4f1c45ecaab82321e5a1d1787f..b6f5aa52ac67d422c6544fbf43541a497e8684b9 100644 (file)
@@ -1003,10 +1003,8 @@ int pmd_free_pte_page(pmd_t *pmdp, unsigned long addr)
 
        pmd = READ_ONCE(*pmdp);
 
-       if (!pmd_present(pmd))
-               return 1;
        if (!pmd_table(pmd)) {
-               VM_WARN_ON(!pmd_table(pmd));
+               VM_WARN_ON(1);
                return 1;
        }
 
@@ -1026,10 +1024,8 @@ int pud_free_pmd_page(pud_t *pudp, unsigned long addr)
 
        pud = READ_ONCE(*pudp);
 
-       if (!pud_present(pud))
-               return 1;
        if (!pud_table(pud)) {
-               VM_WARN_ON(!pud_table(pud));
+               VM_WARN_ON(1);
                return 1;
        }
 
@@ -1047,6 +1043,11 @@ int pud_free_pmd_page(pud_t *pudp, unsigned long addr)
        return 1;
 }
 
+int p4d_free_pud_page(p4d_t *p4d, unsigned long addr)
+{
+       return 0;       /* Don't attempt a block mapping */
+}
+
 #ifdef CONFIG_MEMORY_HOTPLUG
 int arch_add_memory(int nid, u64 start, u64 size, struct vmem_altmap *altmap,
                    bool want_memblock)
index e05b3ce1db6b4e7083aad4d36c92a530bd545c17..73886a5f1f3048cc22149834c0fd91e94a5a48d7 100644 (file)
 /* PTWs cacheable, inner/outer WBWA */
 #define TCR_CACHE_FLAGS        TCR_IRGN_WBWA | TCR_ORGN_WBWA
 
+#ifdef CONFIG_KASAN_SW_TAGS
+#define TCR_KASAN_FLAGS TCR_TBI1
+#else
+#define TCR_KASAN_FLAGS 0
+#endif
+
 #define MAIR(attr, mt) ((attr) << ((mt) * 8))
 
 /*
@@ -449,7 +455,7 @@ ENTRY(__cpu_setup)
         */
        ldr     x10, =TCR_TxSZ(VA_BITS) | TCR_CACHE_FLAGS | TCR_SMP_FLAGS | \
                        TCR_TG_FLAGS | TCR_KASLR_FLAGS | TCR_ASID16 | \
-                       TCR_TBI0 | TCR_A1
+                       TCR_TBI0 | TCR_A1 | TCR_KASAN_FLAGS
 
 #ifdef CONFIG_ARM64_USER_VA_BITS_52
        ldr_l           x9, vabits_user
index dc07c078f9b8e92ee704bf1ef3664fb1ce9fae6c..66e59705348802374a939717612dd1698ac4afe0 100644 (file)
@@ -71,7 +71,7 @@ void free_initrd_mem(unsigned long start, unsigned long end)
                ClearPageReserved(virt_to_page(start));
                init_page_count(virt_to_page(start));
                free_page(start);
-               totalram_pages++;
+               totalram_pages_inc();
        }
 }
 #endif
@@ -88,7 +88,7 @@ void free_initmem(void)
                ClearPageReserved(virt_to_page(addr));
                init_page_count(virt_to_page(addr));
                free_page(addr);
-               totalram_pages++;
+               totalram_pages_inc();
                addr += PAGE_SIZE;
        }
 
index 0cf43bb13d6e561d4c22e46dd5a1bf4a07b08522..055382622f07c8d7706f7e244b341586ecec6d25 100644 (file)
@@ -658,7 +658,7 @@ int arch_add_memory(int nid, u64 start, u64 size, struct vmem_altmap *altmap,
 }
 
 #ifdef CONFIG_MEMORY_HOTREMOVE
-int arch_remove_memory(u64 start, u64 size, struct vmem_altmap *altmap)
+int arch_remove_memory(int nid, u64 start, u64 size, struct vmem_altmap *altmap)
 {
        unsigned long start_pfn = start >> PAGE_SHIFT;
        unsigned long nr_pages = size >> PAGE_SHIFT;
index 20394e52fe272836e7e21e3e495cb50206c02c97..33cc6f676fa6224b76fe0f37399a30b2d852b449 100644 (file)
@@ -139,7 +139,8 @@ int __meminit arch_add_memory(int nid, u64 start, u64 size, struct vmem_altmap *
 }
 
 #ifdef CONFIG_MEMORY_HOTREMOVE
-int __meminit arch_remove_memory(u64 start, u64 size, struct vmem_altmap *altmap)
+int __meminit arch_remove_memory(int nid, u64 start, u64 size,
+                                       struct vmem_altmap *altmap)
 {
        unsigned long start_pfn = start >> PAGE_SHIFT;
        unsigned long nr_pages = size >> PAGE_SHIFT;
index 25427a48feae3a2dcdee2182cd3bb6c5765066d9..e8d63a6a90023aee345b9235b4fc3afa2894d3b7 100644 (file)
@@ -208,7 +208,7 @@ static long cmm_alloc_pages(long nr)
 
                pa->page[pa->index++] = addr;
                loaned_pages++;
-               totalram_pages--;
+               totalram_pages_dec();
                spin_unlock(&cmm_lock);
                nr--;
        }
@@ -247,7 +247,7 @@ static long cmm_free_pages(long nr)
                free_page(addr);
                loaned_pages--;
                nr--;
-               totalram_pages++;
+               totalram_pages_inc();
        }
        spin_unlock(&cmm_lock);
        cmm_dbg("End request with %ld pages unfulfilled\n", nr);
@@ -291,7 +291,7 @@ static void cmm_get_mpp(void)
        int rc;
        struct hvcall_mpp_data mpp_data;
        signed long active_pages_target, page_loan_request, target;
-       signed long total_pages = totalram_pages + loaned_pages;
+       signed long total_pages = totalram_pages() + loaned_pages;
        signed long min_mem_pages = (min_mem_mb * 1024 * 1024) / PAGE_SIZE;
 
        rc = h_get_mpp(&mpp_data);
@@ -322,7 +322,7 @@ static void cmm_get_mpp(void)
 
        cmm_dbg("delta = %ld, loaned = %lu, target = %lu, oom = %lu, totalram = %lu\n",
                page_loan_request, loaned_pages, loaned_pages_target,
-               oom_freed_pages, totalram_pages);
+               oom_freed_pages, totalram_pages());
 }
 
 static struct notifier_block cmm_oom_nb = {
@@ -581,7 +581,7 @@ static int cmm_mem_going_offline(void *arg)
                        free_page(pa_curr->page[idx]);
                        freed++;
                        loaned_pages--;
-                       totalram_pages++;
+                       totalram_pages_inc();
                        pa_curr->page[idx] = pa_last->page[--pa_last->index];
                        if (pa_last->index == 0) {
                                if (pa_curr == pa_last)
index 363f6470d742e5ee3a198aab507362207cc5f16b..3b93ba0b5d8d6e03b3289f861c4f244681e2826f 100644 (file)
@@ -111,11 +111,12 @@ static void note_page(struct seq_file *m, struct pg_state *st,
 }
 
 #ifdef CONFIG_KASAN
-static void note_kasan_zero_page(struct seq_file *m, struct pg_state *st)
+static void note_kasan_early_shadow_page(struct seq_file *m,
+                                               struct pg_state *st)
 {
        unsigned int prot;
 
-       prot = pte_val(*kasan_zero_pte) &
+       prot = pte_val(*kasan_early_shadow_pte) &
                (_PAGE_PROTECT | _PAGE_INVALID | _PAGE_NOEXEC);
        note_page(m, st, prot, 4);
 }
@@ -154,8 +155,8 @@ static void walk_pmd_level(struct seq_file *m, struct pg_state *st,
        int i;
 
 #ifdef CONFIG_KASAN
-       if ((pud_val(*pud) & PAGE_MASK) == __pa(kasan_zero_pmd)) {
-               note_kasan_zero_page(m, st);
+       if ((pud_val(*pud) & PAGE_MASK) == __pa(kasan_early_shadow_pmd)) {
+               note_kasan_early_shadow_page(m, st);
                return;
        }
 #endif
@@ -185,8 +186,8 @@ static void walk_pud_level(struct seq_file *m, struct pg_state *st,
        int i;
 
 #ifdef CONFIG_KASAN
-       if ((p4d_val(*p4d) & PAGE_MASK) == __pa(kasan_zero_pud)) {
-               note_kasan_zero_page(m, st);
+       if ((p4d_val(*p4d) & PAGE_MASK) == __pa(kasan_early_shadow_pud)) {
+               note_kasan_early_shadow_page(m, st);
                return;
        }
 #endif
@@ -215,8 +216,8 @@ static void walk_p4d_level(struct seq_file *m, struct pg_state *st,
        int i;
 
 #ifdef CONFIG_KASAN
-       if ((pgd_val(*pgd) & PAGE_MASK) == __pa(kasan_zero_p4d)) {
-               note_kasan_zero_page(m, st);
+       if ((pgd_val(*pgd) & PAGE_MASK) == __pa(kasan_early_shadow_p4d)) {
+               note_kasan_early_shadow_page(m, st);
                return;
        }
 #endif
index 76d0708438e9b8d9c4dcabd5b280caceafb2bfb0..3e82f66d5c613e82e051235786f49c5d2e79b31f 100644 (file)
@@ -59,7 +59,7 @@ static void __init setup_zero_pages(void)
        order = 7;
 
        /* Limit number of empty zero pages for small memory sizes */
-       while (order > 2 && (totalram_pages >> 10) < (1UL << order))
+       while (order > 2 && (totalram_pages() >> 10) < (1UL << order))
                order--;
 
        empty_zero_page = __get_free_pages(GFP_KERNEL | __GFP_ZERO, order);
@@ -242,7 +242,7 @@ int arch_add_memory(int nid, u64 start, u64 size, struct vmem_altmap *altmap,
 }
 
 #ifdef CONFIG_MEMORY_HOTREMOVE
-int arch_remove_memory(u64 start, u64 size, struct vmem_altmap *altmap)
+int arch_remove_memory(int nid, u64 start, u64 size, struct vmem_altmap *altmap)
 {
        /*
         * There is no hardware or firmware interface which could trigger a
index acb9645b762b0c3a85ceb288123e0860f1b666d0..bac5c27d11fc5368997018d3d8cceff8ae960b59 100644 (file)
@@ -107,7 +107,8 @@ static void __init kasan_early_vmemmap_populate(unsigned long address,
                        if (mode == POPULATE_ZERO_SHADOW &&
                            IS_ALIGNED(address, PGDIR_SIZE) &&
                            end - address >= PGDIR_SIZE) {
-                               pgd_populate(&init_mm, pg_dir, kasan_zero_p4d);
+                               pgd_populate(&init_mm, pg_dir,
+                                               kasan_early_shadow_p4d);
                                address = (address + PGDIR_SIZE) & PGDIR_MASK;
                                continue;
                        }
@@ -120,7 +121,8 @@ static void __init kasan_early_vmemmap_populate(unsigned long address,
                        if (mode == POPULATE_ZERO_SHADOW &&
                            IS_ALIGNED(address, P4D_SIZE) &&
                            end - address >= P4D_SIZE) {
-                               p4d_populate(&init_mm, p4_dir, kasan_zero_pud);
+                               p4d_populate(&init_mm, p4_dir,
+                                               kasan_early_shadow_pud);
                                address = (address + P4D_SIZE) & P4D_MASK;
                                continue;
                        }
@@ -133,7 +135,8 @@ static void __init kasan_early_vmemmap_populate(unsigned long address,
                        if (mode == POPULATE_ZERO_SHADOW &&
                            IS_ALIGNED(address, PUD_SIZE) &&
                            end - address >= PUD_SIZE) {
-                               pud_populate(&init_mm, pu_dir, kasan_zero_pmd);
+                               pud_populate(&init_mm, pu_dir,
+                                               kasan_early_shadow_pmd);
                                address = (address + PUD_SIZE) & PUD_MASK;
                                continue;
                        }
@@ -146,7 +149,8 @@ static void __init kasan_early_vmemmap_populate(unsigned long address,
                        if (mode == POPULATE_ZERO_SHADOW &&
                            IS_ALIGNED(address, PMD_SIZE) &&
                            end - address >= PMD_SIZE) {
-                               pmd_populate(&init_mm, pm_dir, kasan_zero_pte);
+                               pmd_populate(&init_mm, pm_dir,
+                                               kasan_early_shadow_pte);
                                address = (address + PMD_SIZE) & PMD_MASK;
                                continue;
                        }
@@ -188,7 +192,7 @@ static void __init kasan_early_vmemmap_populate(unsigned long address,
                                pte_val(*pt_dir) = __pa(page) | pgt_prot;
                                break;
                        case POPULATE_ZERO_SHADOW:
-                               page = kasan_zero_page;
+                               page = kasan_early_shadow_page;
                                pte_val(*pt_dir) = __pa(page) | pgt_prot_zero;
                                break;
                        }
@@ -256,14 +260,14 @@ void __init kasan_early_init(void)
        unsigned long vmax;
        unsigned long pgt_prot = pgprot_val(PAGE_KERNEL_RO);
        pte_t pte_z;
-       pmd_t pmd_z = __pmd(__pa(kasan_zero_pte) | _SEGMENT_ENTRY);
-       pud_t pud_z = __pud(__pa(kasan_zero_pmd) | _REGION3_ENTRY);
-       p4d_t p4d_z = __p4d(__pa(kasan_zero_pud) | _REGION2_ENTRY);
+       pmd_t pmd_z = __pmd(__pa(kasan_early_shadow_pte) | _SEGMENT_ENTRY);
+       pud_t pud_z = __pud(__pa(kasan_early_shadow_pmd) | _REGION3_ENTRY);
+       p4d_t p4d_z = __p4d(__pa(kasan_early_shadow_pud) | _REGION2_ENTRY);
 
        kasan_early_detect_facilities();
        if (!has_nx)
                pgt_prot &= ~_PAGE_NOEXEC;
-       pte_z = __pte(__pa(kasan_zero_page) | pgt_prot);
+       pte_z = __pte(__pa(kasan_early_shadow_page) | pgt_prot);
 
        memsize = get_mem_detect_end();
        if (!memsize)
@@ -292,10 +296,13 @@ void __init kasan_early_init(void)
        }
 
        /* init kasan zero shadow */
-       crst_table_init((unsigned long *)kasan_zero_p4d, p4d_val(p4d_z));
-       crst_table_init((unsigned long *)kasan_zero_pud, pud_val(pud_z));
-       crst_table_init((unsigned long *)kasan_zero_pmd, pmd_val(pmd_z));
-       memset64((u64 *)kasan_zero_pte, pte_val(pte_z), PTRS_PER_PTE);
+       crst_table_init((unsigned long *)kasan_early_shadow_p4d,
+                               p4d_val(p4d_z));
+       crst_table_init((unsigned long *)kasan_early_shadow_pud,
+                               pud_val(pud_z));
+       crst_table_init((unsigned long *)kasan_early_shadow_pmd,
+                               pmd_val(pmd_z));
+       memset64((u64 *)kasan_early_shadow_pte, pte_val(pte_z), PTRS_PER_PTE);
 
        shadow_alloc_size = memsize >> KASAN_SHADOW_SCALE_SHIFT;
        pgalloc_low = round_up((unsigned long)_end, _SEGMENT_SIZE);
index 0a39c241628a8a797fc5e633cde90851a9953ae6..346eda7a2ef6af0563ffbbc9d8c7a16c3e62cce5 100644 (file)
@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * ALPHAPROJECT AP-SH4A-3A Support.
  *
  * Copyright (C) 2010 ALPHAPROJECT Co.,Ltd.
  * Copyright (C) 2008  Yoshihiro Shimoda
  * Copyright (C) 2009  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/platform_device.h>
index 92eac3a9918713a255cc742cde86a6a228bfc336..4efa9c571f64fc7370e4bd51f3ab5b83aa50d57f 100644 (file)
@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * ALPHAPROJECT AP-SH4AD-0A Support.
  *
  * Copyright (C) 2010 ALPHAPROJECT Co.,Ltd.
  * Copyright (C) 2010  Matt Fleming
  * Copyright (C) 2010  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/platform_device.h>
index bab5b95139048a10d1e845b521ca74a4b84952a3..0fbe91cba67a2bb2583bff30ab1fb438aa2376b7 100644 (file)
@@ -1,22 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Renesas Europe EDOSK7760 Board Support
  *
  * Copyright (C) 2008 SPES Societa' Progettazione Elettronica e Software Ltd.
  * Author: Luca Santini <luca.santini@spesonline.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 #include <linux/init.h>
 #include <linux/types.h>
index 4d6be53058d63953e484a6c2a744b7950e88eb85..f478fee3b48afcdcb5e782cc0c75584bc0be4a69 100644 (file)
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Data Technology Inc. ESPT-GIGA board support
  *
  * Copyright (C) 2008, 2009 Renesas Solutions Corp.
  * Copyright (C) 2008, 2009 Nobuhiro Iwamatsu <iwamatsu.nobuhiro@renesas.com>
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/platform_device.h>
index 20500858b56cc6f03a5cf0a4c47eddee2540da17..56bd386ff3b043d49b665c797244289f8950e4d3 100644 (file)
@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * linux/arch/sh/boards/magicpanel/setup.c
  *
  *  Copyright (C) 2007  Markus Brunner, Mark Jonas
  *
  *  Magic Panel Release 2 board setup
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/irq.h>
index 1bde08dc067dca20b40e7367ed22040cfee0c824..c32b4c6229d3f849e6f6fa971e1a41ad7e6916e1 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Renesas R0P7757LC0012RL Support.
  *
  * Copyright (C) 2009 - 2010  Renesas Solutions Corp.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 
 #include <linux/init.h>
index 3cba60ff7aab0941ab557707ed39647734e9bc36..d964c4d6b1390bd5e1329b8d47b227ca4de52168 100644 (file)
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Renesas Technology Corp. R0P7785LC0011RL Support.
  *
  * Copyright (C) 2008  Yoshihiro Shimoda
  * Copyright (C) 2009  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/platform_device.h>
index 94c36c7bc0b3bc1701768f938e8d92e6d3add5b9..074a848d8b564d1c2085ee2002aab68db26c06b2 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/boards/titan/setup.c - Setup for Titan
  *
  *  Copyright (C) 2006  Jamie Lenehan
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/irq.h>
index b52abcc5259a41ea5c3ab15a426dcf75be3b36ed..799af57c0b81532a3cf4a8e9eb63ed2580ce9305 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Renesas Technology Corp. SH7786 Urquell Support.
  *
@@ -6,10 +7,6 @@
  *
  * Based on board-sh7785lcr.c
  * Copyright (C) 2008  Yoshihiro Shimoda
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/platform_device.h>
index 4cf1774d26132e87b7d61e8eafc70bd3e94d5d27..dba5d0c202615a1372c0adb60466e2033dc70f97 100644 (file)
@@ -1,2 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
 obj-y   := setup.o sdram.o
 
index db24fbed4fca539a85e9e79fb98758c84182f4e9..541c82cc30b1127229d864ddb55b88934f8fc336 100644 (file)
@@ -1,11 +1,8 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
  * AP325RXA sdram self/auto-refresh setup code
  *
  *  Copyright (C) 2009 Magnus Damm
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 
 #include <linux/sys.h>
index 00fa3eaecb1be7a5e8bcad1ea3bb850095a0149c..775a4be57434b6a40c2e194fe0a3fe4883dd8330 100644 (file)
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
 #
 # Makefile for the Hitachi Cayman specific parts of the kernel
 #
index 724e8b7271f4a465a3008d06de4f65452bf3eb48..9108789fafef7c7e1e72ec4cd8645a32e8891600 100644 (file)
@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/mach-cayman/irq.c - SH-5 Cayman Interrupt Support
  *
  * This file handles the board specific parts of the Cayman interrupt system
  *
  * Copyright (C) 2002 Stuart Menefy
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/io.h>
 #include <linux/irq.h>
index d1e67306d07c068654b046fd58bbc5f46847f4c3..cfc46314e7d98c7da15d3507d3e3313f85591156 100644 (file)
@@ -1,9 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2003  Richard Curnow, SuperH UK Limited
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 
 #include <linux/kernel.h>
index 9c292c27e0d7114768a7bf8379df7be3fc157257..4cec14700adc652af3b4eaf1ec7671c35f9dcafe 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/mach-cayman/setup.c
  *
@@ -5,10 +6,6 @@
  *
  * Copyright (C) 2002  David J. Mckay & Benedict Gaster
  * Copyright (C) 2003 - 2007  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/io.h>
index 62b024bc2a3ef59a8e1654387a7de853c394c506..37b2452206aa218ac1a4a975b769bccdb62944cd 100644 (file)
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
 #
 # Makefile for the Sega Dreamcast specific parts of the kernel
 #
index 2789647abebef2308a28f3260b6016410c078cab..a929f764ae04030c2d2aa69ee2abadafe284f129 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/boards/dreamcast/irq.c
  *
@@ -6,7 +7,6 @@
  * Copyright (c) 2001, 2002 M. R. Brown <mrbrown@0xd6.org>
  *
  * This file is part of the LinuxDC project (www.linuxdc.org)
- * Released under the terms of the GNU GPL v2.0
  */
 #include <linux/irq.h>
 #include <linux/io.h>
index 0eb12c45fa597174d48bace5151b4b9fe5bfa9ce..7873cd27e4e008d7efcb064cf294f30f2e539494 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/boards/dreamcast/rtc.c
  *
@@ -5,9 +6,6 @@
  *
  * Copyright (c) 2001, 2002 M. R. Brown <mrbrown@0xd6.org>
  * Copyright (c) 2002 Paul Mundt <lethal@chaoticdreams.org>
- *
- * Released under the terms of the GNU GPL v2.0.
- *
  */
 
 #include <linux/time.h>
index 672c2ad8f8d57866e04c946c3727fd9746ba6af4..2d966c1c2cc1880c141b1d45fc2f74ff46581be5 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/boards/dreamcast/setup.c
  *
@@ -8,8 +9,6 @@
  *
  * This file is part of the LinuxDC project (www.linuxdc.org)
  *
- * Released under the terms of the GNU GPL v2.0.
- *
  * This file originally bore the message (with enclosed-$):
  *     Id: setup_dc.c,v 1.5 2001/05/24 05:09:16 mrbrown Exp
  *     SEGA Dreamcast support
index e69bc82208fc7fdfec6dc3ebeabdf830c06158cf..d78d4904ddee326dc35cc373945f4fae2f44c9ad 100644 (file)
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
 #
 # Makefile for the R0P7724LC0011/21RL (EcoVec)
 #
@@ -6,4 +7,4 @@
 # for more details.
 #
 
-obj-y   := setup.o sdram.o
\ No newline at end of file
+obj-y   := setup.o sdram.o
index 3963c6f23d52bb5fa8a7e7e60b9d18bb5677d498..d2f269169abb94428494f88db9d8b57423a33e2e 100644 (file)
@@ -1,11 +1,8 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
  * Ecovec24 sdram self/auto-refresh setup code
  *
  *  Copyright (C) 2009 Magnus Damm
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 
 #include <linux/sys.h>
index 058b168bdf26a664d922486569225dd50de73b3e..22b4106b808481280637b7be29d0d8efbec40bc6 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2009 Renesas Solutions Corp.
  *
  * Kuninori Morimoto <morimoto.kuninori@renesas.com>
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <asm/clock.h>
 #include <asm/heartbeat.h>
index 9893fd3a13587f8e79e4eb9ae6489e79390e83ed..f46637377b6a18120dd13abb0f90626d5f90db95 100644 (file)
@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Renesas Solutions Highlander R7780MP Support.
  *
  * Copyright (C) 2002  Atom Create Engineering Co., Ltd.
  * Copyright (C) 2006  Paul Mundt
  * Copyright (C) 2007  Magnus Damm
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/irq.h>
index 0805b2151452caaaa46a776228d61a3127b15976..c61177e8724ba7aa90291b1a9b778039799bcff8 100644 (file)
@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Renesas Solutions Highlander R7780RP-1 Support.
  *
  * Copyright (C) 2002  Atom Create Engineering Co., Ltd.
  * Copyright (C) 2006  Paul Mundt
  * Copyright (C) 2008  Magnus Damm
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/irq.h>
index 558b248627768d9fbd9bb68fa026853184c14edc..0ebebbed0d63fbe05ac75eddf4e9b61611552571 100644 (file)
@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Renesas Solutions Highlander R7785RP Support.
  *
  * Copyright (C) 2002  Atom Create Engineering Co., Ltd.
  * Copyright (C) 2006 - 2008  Paul Mundt
  * Copyright (C) 2007  Magnus Damm
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/irq.h>
index c77a2bea8f2a962032edab49c0983c68b7bafbaf..703179faf652b242c1a658556ae4b09895ed882b 100644 (file)
@@ -1,9 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2008 Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/gpio.h>
index 40e2b585d4887b7bc48361395c0b9881ecf64970..d445c54f74e4403b14ac6a686ae0a0d3da7d60f0 100644 (file)
@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/boards/renesas/r7780rp/psw.c
  *
  * push switch support for RDBRP-1/RDBREVRP-1 debug boards.
  *
  * Copyright (C) 2006  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/io.h>
 #include <linux/module.h>
index 4a52590fe3d8248961e781c9887a9a2deedb45d5..533393d779c2b97f987c7df2444847278e14b549 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/boards/renesas/r7780rp/setup.c
  *
@@ -8,10 +9,6 @@
  *
  * This contains support for the R7780RP-1, R7780MP, and R7785RP
  * Highlander modules.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/io.h>
index b3124278247c0d44707f8891f8d2e24d7543a58a..4b0fe29e5612eb0fc2567ee477cb19c866c9941e 100644 (file)
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
 #
 # Makefile for the HP6xx specific parts of the kernel
 #
index 865d8d6e823f89036402139b896f4465c12e85f9..e5c4c7d34139eab9e09d49672a12efb9e3170e34 100644 (file)
@@ -1,11 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * bios-less APM driver for hp680
  *
  * Copyright 2005 (c) Andriy Skulysh <askulysh@gmail.com>
  * Copyright 2008 (c) Kristoffer Ericson <kristoffer.ericson@gmail.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License.
  */
 #include <linux/module.h>
 #include <linux/kernel.h>
index 8b50cf763c065010666d9598bed8c1a3f59043f0..fe505ec168d02195bf7b2dd92b2fedda9ffb943f 100644 (file)
@@ -1,10 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * hp6x0 Power Management Routines
  *
  * Copyright (c) 2006 Andriy Skulysh <askulsyh@gmail.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License.
  */
 #include <linux/init.h>
 #include <linux/suspend.h>
index 4f18d44e05413f265e3de3d5629d6a8e97f50093..0fd43301f083d0fded7901f4fbb0591e2e48e6b4 100644 (file)
@@ -1,10 +1,6 @@
-/*
- * Copyright (c) 2006 Andriy Skulysh <askulsyh@gmail.com>
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
+/* SPDX-License-Identifier: GPL-2.0
  *
+ * Copyright (c) 2006 Andriy Skulysh <askulsyh@gmail.com>
  */
 
 #include <linux/linkage.h>
index 05797b33f68ef5e4b6d6c0cd50ff3fd1c67c0f08..2ceead68d7bf82c8632435920ffd568deedb60bc 100644 (file)
@@ -1,12 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * linux/arch/sh/boards/hp6xx/setup.c
  *
  * Copyright (C) 2002 Andriy Skulysh
  * Copyright (C) 2007 Kristoffer Ericson <Kristoffer_e1@hotmail.com>
  *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
  * Setup code for HP620/HP660/HP680/HP690 (internal peripherials only)
  */
 #include <linux/types.h>
index 60dd63f4a4272893f069ef70064d2b63a1a4f6f2..4a4a35ad7ba07c583b97decea3f83e30c42766d2 100644 (file)
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
 obj-y  := setup.o sdram.o
 ifneq ($(CONFIG_FB_SH_MOBILE_LCDC),)
 obj-y  +=  lcd_wqvga.o
index 355a78a3b3132d82b95eef93732b31c41e415580..f6bbac106d1328a612676a53ca2c9be7c4bcd6c9 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * KFR2R09 LCD panel support
  *
@@ -5,10 +6,6 @@
  *
  * Register settings based on the out-of-tree t33fb.c driver
  * Copyright (C) 2008 Lineo Solutions, Inc.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file COPYING in the main directory of this archive for
- * more details.
  */
 
 #include <linux/delay.h>
index 0c9f55bec2feea4326483fd52858962cd64e5388..f1b8985cb9223cfb7d2871f933756ad70bb54ec7 100644 (file)
@@ -1,11 +1,8 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
  * KFR2R09 sdram self/auto-refresh setup code
  *
  *  Copyright (C) 2009 Magnus Damm
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 
 #include <linux/sys.h>
index e59c577ed871591a62e5b25789469549a2641b2d..203d249a0a2b46763a833df25c2682740c4b67a6 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/memblock.h>
 #include <linux/mfd/tmio.h>
 #include <linux/mmc/host.h>
-#include <linux/mtd/onenand.h>
 #include <linux/mtd/physmap.h>
 #include <linux/platform_data/lv5207lp.h>
 #include <linux/platform_device.h>
@@ -478,7 +477,7 @@ extern char kfr2r09_sdram_leave_end;
 
 static int __init kfr2r09_devices_setup(void)
 {
-       static struct clk *camera_clk;
+       struct clk *camera_clk;
 
        /* register board specific self-refresh code */
        sh_mobile_register_self_refresh(SUSP_SH_STANDBY | SUSP_SH_SF |
index a696b4277fa977025c44d20d411490cfd7b189a0..6cba041fffe0f355d5ca3925817cb1caddbce862 100644 (file)
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
 #
 # Makefile for I-O DATA DEVICE, INC. "LANDISK Series"
 #
index 32c317f5d9910bbfd368d96274daebb070113ade..1c0da99dfc6059d882e6491738d452d8ed8f0017 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/boards/landisk/gio.c - driver for landisk
  *
@@ -6,11 +7,6 @@
  *
  *   Copylight (C) 2006 kogiidena
  *   Copylight (C) 2002 Atom Create Engineering Co., Ltd. *
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
  */
 #include <linux/module.h>
 #include <linux/init.h>
index c00ace38db3f6e0913e35ac218a7731dcc522870..29b8b1f8524668e6204768d8c17ec683a7522dd5 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/boards/mach-landisk/irq.c
  *
@@ -8,10 +9,6 @@
  *
  * Copyright (C) 2001  Ian da Silva, Jeremy Siegel
  * Based largely on io_se.c.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 
 #include <linux/init.h>
index 5192b1f43ada5ce884bc4a8abc3f1e0f53e7cc1d..e171d9af48f3dfbe16a63e4d83740145d384e9b9 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/boards/landisk/psw.c
  *
@@ -5,10 +6,6 @@
  *
  * Copyright (C) 2006-2007  Paul Mundt
  * Copyright (C) 2007  kogiidena
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/io.h>
 #include <linux/init.h>
index f1147caebacf020e6933b1069b962f1bc2a0cfca..16b4d8b0bb8503d962eeb9bbb79a4d4c5724a6dd 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/boards/landisk/setup.c
  *
@@ -7,10 +8,6 @@
  * Copyright (C) 2002 Paul Mundt
  * Copylight (C) 2002 Atom Create Engineering Co., Ltd.
  * Copyright (C) 2005-2007 kogiidena
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/platform_device.h>
index e9ed140c06f690529a2e3005e47df910075bbabf..0fbd0822911a497feff9c00c935d2ca63fba5757 100644 (file)
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
 #
 # Makefile for the L-BOX RE2 specific parts of the kernel
 # Copyright (c) 2007 Nobuhiro Iwamatsu
index 8aa171ab833e4c05734fbef453afe2fb78f9ab75..a250e3b9019de1168b39a6d5f8e0ef27c92c88b9 100644 (file)
@@ -1,14 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * linux/arch/sh/boards/lboxre2/irq.c
  *
  * Copyright (C) 2007 Nobuhiro Iwamatsu
  *
  * NTT COMWARE L-BOX RE2 Support.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
  */
 #include <linux/init.h>
 #include <linux/interrupt.h>
index 6660622aa457103f1fb2b3306e1be37f5653b7a0..20d01b430f2a811ce1f7ea7c9c94fbbfefa98f9b 100644 (file)
@@ -1,14 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * linux/arch/sh/boards/lbox/setup.c
  *
  * Copyright (C) 2007 Nobuhiro Iwamatsu
  *
  * NTT COMWARE L-BOX RE2 Support
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
  */
 
 #include <linux/init.h>
index 4e3588e8806bb80efc6a9e4a1ae76c1b60358cd0..05c5698dcad0250940b3e357a336932e69aa7e25 100644 (file)
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
 #
 # Makefile for the SuperH MicroDev specific parts of the kernel
 #
index 458a7cf5fb46472a31756907812b0090b7773c87..2a04f72dd1457788cafa5f0e9c9e964a2f412dde 100644 (file)
@@ -1,5 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
- *
  * Setup for the SMSC FDC37C93xAPM
  *
  * Copyright (C) 2003 Sean McGoogan (Sean.McGoogan@superh.com)
@@ -7,9 +7,6 @@
  * Copyright (C) 2004, 2005 Paul Mundt
  *
  * SuperH SH4-202 MicroDev board support.
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
  */
 #include <linux/init.h>
 #include <linux/ioport.h>
index acdafb0c6404a153cc482e46c0a17287f15ea26e..a76c12721e63dccb44b2a775cc3dd329601912b9 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * linux/arch/sh/boards/superh/microdev/io.c
  *
@@ -6,9 +7,6 @@
  * Copyright (C) 2004 Paul Mundt
  *
  * SuperH SH4-202 MicroDev board support.
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
  */
 
 #include <linux/init.h>
index 9a8aff3396197ca097d0a3d34c61c71da31401b4..dc27492c83d7657ae53d8fbf72d6759dcfa8fac2 100644 (file)
@@ -1,12 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/boards/superh/microdev/irq.c
  *
  * Copyright (C) 2003 Sean McGoogan (Sean.McGoogan@superh.com)
  *
  * SuperH SH4-202 MicroDev board support.
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
  */
 
 #include <linux/init.h>
index 6c66ee4d842bd467fd50b00aaabc9a4510bf306b..706b48f797bed63b4ca30b1b362402186757ee29 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/boards/superh/microdev/setup.c
  *
@@ -6,9 +7,6 @@
  * Copyright (C) 2004, 2005 Paul Mundt
  *
  * SuperH SH4-202 MicroDev board support.
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
  */
 #include <linux/init.h>
 #include <linux/platform_device.h>
index 4601a89e5ac736102805062999eb0aa57310940f..c223d759fcb1ee03d4e439158075fc7a3f58e748 100644 (file)
@@ -1,2 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
 obj-y   := setup.o sdram.o
 obj-$(CONFIG_SH_MIGOR_QVGA)    +=  lcd_qvga.o
index 8bccd345b69c24a577fb860ae1a6290d81c97e8e..4ebf130510bc6eb3826c139230855523d302e165 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Support for SuperH MigoR Quarter VGA LCD Panel
  *
@@ -5,10 +6,6 @@
  *
  * Based on lcd_powertip.c from Kenati Technologies Pvt Ltd.
  * Copyright (c) 2007 Ujjwal Pande <ujjwal@kenati.com>,
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
  */
 
 #include <linux/delay.h>
index 614aa3a1398c020e819943e378873ea0f7e56289..3a6bee1270aaf76cdda684cb4689ca5e080222ac 100644 (file)
@@ -1,11 +1,8 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
  * Migo-R sdram self/auto-refresh setup code
  *
  *  Copyright (C) 2009 Magnus Damm
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 
 #include <linux/sys.h>
index 0d4c75a72be0950bd2ac9daef868609a17b7e43f..7e7ac5e0566211385ff25fdeeb1444885c25b640 100644 (file)
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
 #
 # Makefile for the RTS7751R2D specific parts of the kernel
 #
index 4b98a5251f833f5e2eda2013e656a95a5fb3c81a..3bc52f651d961165df9acb415beccf6d97e7a744 100644 (file)
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Renesas Technology Sales RTS7751R2D Support.
  *
  * Copyright (C) 2002 - 2006 Atom Create Engineering Co., Ltd.
  * Copyright (C) 2004 - 2007 Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/platform_device.h>
index 6a4e1b538a6201417a6c481de1a6dcb817535054..43cca39a9fe6123bc16b284ea8dda536e305dd9d 100644 (file)
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
 obj-y                          := setup.o
 obj-$(CONFIG_SH_RSK7203)       += devices-rsk7203.o
 obj-$(CONFIG_SH_RSK7264)       += devices-rsk7264.o
index a8089f79d0580d5d0725e07c9193e1fa7c8d996c..e6b05d4588b7b974b2800ab27f861c127b7327c2 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Renesas Technology Europe RSK+ 7203 Support.
  *
  * Copyright (C) 2008 - 2010  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/types.h>
index 7251e37a842ff0b593916a7a1fba38a959673bf1..eaf700a20b833e33166c3e0e4c424bfbc2563271 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * RSK+SH7264 Support.
  *
  * Copyright (C) 2012 Renesas Electronics Europe
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/types.h>
index 4a544591d6f0ef3ae66834168fd9133cb38ec61a..4b1e386b51dd641c842ea1b85bbb6804b1d5ab85 100644 (file)
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * RSK+SH7269 Support
  *
  * Copyright (C) 2012  Renesas Electronics Europe Ltd
  * Copyright (C) 2012  Phil Edworthy
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/types.h>
index 6bc134bd7ec265555bdd6442775c285c38f2d5ab..9370c4fdc41e13ad81e337f9205fcde50d362bdd 100644 (file)
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Renesas Technology Europe RSK+ Support.
  *
  * Copyright (C) 2008 Paul Mundt
  * Copyright (C) 2008 Peter Griffin <pgriffin@mpc-data.co.uk>
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/types.h>
index 3d8f0befc35dd9cb2c004d75fcf80cc17b86c61d..37e857f9a55a2666114d921df6d54a052a553e9d 100644 (file)
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
 #
 # Makefile for the SDK7780 specific parts of the kernel
 #
index e5f7564f2511f0aa623cf6b17a3037e925e2f703..fa392f3dce266ba327ceac98fa694675049c7938 100644 (file)
@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * linux/arch/sh/boards/renesas/sdk7780/irq.c
  *
  * Renesas Technology Europe SDK7780 Support.
  *
  * Copyright (C) 2008  Nicholas Beck <nbeck@mpc-data.co.uk>
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/irq.h>
index 2241659c32990c2336b95ce9bb4865ae1c502c32..482761b780e406fcb938a9ee253b49bec0859f63 100644 (file)
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/boards/renesas/sdk7780/setup.c
  *
  * Renesas Solutions SH7780 SDK Support
  * Copyright (C) 2008 Nicholas Beck <nbeck@mpc-data.co.uk>
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/types.h>
index 45d32e3590b9715dc6d3ec08ce41f64123203a35..731a87c694b3bc81554d041b0080da984de732cc 100644 (file)
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
 obj-y  := fpga.o irq.o nmi.o setup.o
 
 obj-$(CONFIG_GPIOLIB)          += gpio.o
index 3e4ec66a04171cc36af9bb44bc0e4e79a606619b..6d2a3d381c2a4f94d97d30b2496110afb25be1a6 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * SDK7786 FPGA Support.
  *
  * Copyright (C) 2010  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/io.h>
index 47997010b77a2069f4b56db35f659ed85d13933f..c4587d1013e6118e07c7755394cf68f1d41801ad 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * SDK7786 FPGA USRGPIR Support.
  *
  * Copyright (C) 2010  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/interrupt.h>
index 46943a0da5b7b7faaef8edeffd9c0ce6d00becbe..340c306ea95239a2704db16008da4c59ff05981b 100644 (file)
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * SDK7786 FPGA IRQ Controller Support.
  *
  * Copyright (C) 2010  Matt Fleming
  * Copyright (C) 2010  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/irq.h>
 #include <mach/fpga.h>
index edcfa1f568bae6efcf477ac8b1cce1e35f68d66f..c2e09d798537c4468d7099b1a7635fecb860cccb 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * SDK7786 FPGA NMI Support.
  *
  * Copyright (C) 2010  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
index c29268bfd34a246d3be0c0c7cfc15b711ee529ca..65721c3a482c2f6bb66ebabeb36c28c2b3a26c40 100644 (file)
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Renesas Technology Europe SDK7786 Support.
  *
  * Copyright (C) 2010  Matt Fleming
  * Copyright (C) 2010  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/platform_device.h>
index c81c3abbe01cef4c421712d066010812ec59352d..d76cdb7ede39175624e8f3d7cad5c5aeeb5d7239 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * SDK7786 FPGA SRAM Support.
  *
  * Copyright (C) 2010  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
index 5c9eaa0535b935c5f90bde958b0ca79724e1dcc2..b40b30853ce37628322e7bee69b38445179375d2 100644 (file)
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
 #
 # Makefile for the 7206 SolutionEngine specific parts of the kernel
 #
index 4c3666a93790603f831ee4cb2b9dd5570bb42828..e058661091a26f263c63b82029bdc44d4c4af255 100644 (file)
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
 #
 # Makefile for the 7343 SolutionEngine specific parts of the kernel
 #
index 6129aef6db766366dd5628aa760f1a70d6ce2707..39a3175e72b268f0e6869e7bc3d60de6268494b5 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Hitachi UL SolutionEngine 7343 FPGA IRQ Support.
  *
@@ -6,10 +7,6 @@
  *
  * Based on linux/arch/sh/boards/se/7343/irq.c
  * Copyright (C) 2007  Nobuhiro Iwamatsu
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #define DRV_NAME "SE7343-FPGA"
 #define pr_fmt(fmt) DRV_NAME ": " fmt
index 43ea14feef51094d032c5b7eec98b35deff925f8..900d93cfb6a5318d59d9c6813651790d6a41c683 100644 (file)
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
 #
 # Makefile for the 770x SolutionEngine specific parts of the kernel
 #
index 7f09030980b37d5ed26f2fb7a5effca1f2da685b..09436f10ddf198d677e305bd118f9f89bd79d3b5 100644 (file)
@@ -1 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0
 obj-y   := setup.o irq.o
index d85022ea3f12f752825413ad138c255e2d11bc7e..e6ef2a2655c37c5a02dc2fb2f4793b324d574b37 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * linux/arch/sh/boards/se/7721/irq.c
  *
  * Copyright (C) 2008  Renesas Solutions Corp.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/irq.h>
index a0b3dba34ebfb74740a57fa37bdc93a858c9ca52..3af724dc4ba44aa9adbc92936bb9e9dd8cd2b5f7 100644 (file)
@@ -1,14 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * linux/arch/sh/boards/se/7721/setup.c
  *
  * Copyright (C) 2008 Renesas Solutions Corp.
  *
  * Hitachi UL SolutionEngine 7721 Support.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
  */
 #include <linux/init.h>
 #include <linux/platform_device.h>
index 8694373389e5c24e11967f0c4954609656d7097e..a5e89c0c6bb2d45539e4507b0d4a46c73634eb32 100644 (file)
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
 #
 # Makefile for the HITACHI UL SolutionEngine 7722 specific parts of the kernel
 #
index 24c74a88290c6559ef59108e4a478805c6bfd1b2..f6e3009edd4e2370dcab708b30b9697e40ca794d 100644 (file)
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Hitachi UL SolutionEngine 7722 FPGA IRQ Support.
  *
  * Copyright (C) 2007  Nobuhiro Iwamatsu
  * Copyright (C) 2012  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #define DRV_NAME "SE7722-FPGA"
 #define pr_fmt(fmt) DRV_NAME ": " fmt
index e04e2bc4698481374b2e6c16f9580d70021e9382..2cd4a2e84b930cd665e8e703c19410734d2031ec 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * linux/arch/sh/boards/se/7722/setup.c
  *
@@ -5,11 +6,6 @@
  * Copyright (C) 2012 Paul Mundt
  *
  * Hitachi UL SolutionEngine 7722 Support.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
  */
 #include <linux/init.h>
 #include <linux/platform_device.h>
index a08b36830f0eb4f8a50a27759a7643f31905fa17..6c6112b24617d0468c320caf3bebf1db7537ed5b 100644 (file)
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
 #
 # Makefile for the HITACHI UL SolutionEngine 7724 specific parts of the kernel
 #
index 64e681e66c5797c68b5d3f59929b5c17960a825a..14ce3024738f3b2d7173756bfa88c164c7e19c9b 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * linux/arch/sh/boards/se/7724/irq.c
  *
@@ -9,10 +10,6 @@
  * Copyright (C) 2007  Nobuhiro Iwamatsu
  *
  * Hitachi UL SolutionEngine 7724 Support.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/irq.h>
index 6fa4734d09c796ee6e3d3be60349df639f0210e7..61c1fe78d71a05740f14e49735c03052192b7477 100644 (file)
@@ -1,11 +1,8 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
  * MS7724SE sdram self/auto-refresh setup code
  *
  *  Copyright (C) 2009 Magnus Damm
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 
 #include <linux/sys.h>
index a338fd9d503944f84b4e84b5a3a3e7cccc4a5fcb..2406d3e353524b8f9bf8f06a0180129fba1f189a 100644 (file)
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
 #
 # Makefile for the 7751 SolutionEngine specific parts of the kernel
 #
index 6b88adae3ecc137dd5d0932424f942317d79f15e..1f6669ab1bc0dbe3d88d698358e0fb303e45ed1f 100644 (file)
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
 #
 # Makefile for the HITACHI UL SolutionEngine 7780 specific parts of the kernel
 #
index d5c9edc172a3d22e32370b120f9c5d67fd61d8d4..d427dfd711f171cbf2982f2fc1d6b06f215626d3 100644 (file)
@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * linux/arch/sh/boards/se/7780/irq.c
  *
  * Copyright (C) 2006,2007  Nobuhiro Iwamatsu
  *
  * Hitachi UL SolutionEngine 7780 Support.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/irq.h>
index ae5a1d84fdf8e0af6ff01ec897af817fc2ffdbf5..309f2681381b0856e6763376c93019c2a1d942f7 100644 (file)
@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * linux/arch/sh/boards/se/7780/setup.c
  *
  * Copyright (C) 2006,2007  Nobuhiro Iwamatsu
  *
  * Hitachi UL SolutionEngine 7780 Support.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/platform_device.h>
index 47007a3a2fc8add20654fe975ca9bbb42777f364..f89c25c6a39c8aa2f6f923c5fe9c45d4a1e4d9f8 100644 (file)
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
 #
 # Makefile for the Interface (CTP/PCI-SH03) specific parts of the kernel
 #
index f6c0b55516d23cb1c3737827f0e75da6f89dc6a2..d6341310444a5112a073f040a49e4a84952bf588 100644 (file)
@@ -1 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0
 obj-y    := setup.o irq.o
index add698c8f2b44ebf4a056d6054c7c521915373be..efd382b7dad4035731a5dfdd41c15cc34c359df5 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * linux/arch/sh/boards/renesas/sh7763rdp/irq.c
  *
@@ -5,10 +6,6 @@
  *
  * Copyright (C) 2008 Renesas Solutions Corp.
  * Copyright (C) 2008  Nobuhiro Iwamatsu <iwamatsu.nobuhiro@renesas.com>
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 
 #include <linux/init.h>
index 6e62686b81b145b1a11707969fe80988918dfd55..97e715e4e9b33c4072b334504f002050ad990f14 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * linux/arch/sh/boards/renesas/sh7763rdp/setup.c
  *
@@ -5,10 +6,6 @@
  *
  * Copyright (C) 2008 Renesas Solutions Corp.
  * Copyright (C) 2008 Nobuhiro Iwamatsu <iwamatsu.nobuhiro@renesas.com>
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/platform_device.h>
index 0cbe3d02dea30c6ddd476b153edee195401e82c4..6caefa1145980d93728993e68b2e822f99a083f0 100644 (file)
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
 obj-y += setup.o ilsel.o
 
 obj-$(CONFIG_GPIOLIB)          += gpio.o
index cea88b0effa218b907585cf3c9dcca58f1c571ce..efc992f641a6254191f4ec3cdcd2b298fa535430 100644 (file)
@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/boards/mach-x3proto/gpio.c
  *
  * Renesas SH-X3 Prototype Baseboard GPIO Support.
  *
  * Copyright (C) 2010 - 2012  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
index 95e34613951550d6a66c5d47164505bc093c3420..f0d5eb41521a49683f1429b9932aa4e421f680d4 100644 (file)
@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/boards/mach-x3proto/ilsel.c
  *
  * Helper routines for SH-X3 proto board ILSEL.
  *
  * Copyright (C) 2007 - 2010  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
index d682e2b6a856c42854e8b43bed314f9fb918f8e8..95b85f2e13dda75bec588bb2727d59b44a5521cc 100644 (file)
@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/boards/mach-x3proto/setup.c
  *
  * Renesas SH-X3 Prototype Board Support.
  *
  * Copyright (C) 2007 - 2010  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/platform_device.h>
index 6e9786548ac652f107600a2e4755ed78d341d898..958f46da3a7912cfd94a7b517e8e88b88fec3a5a 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * SH generic board support, using device tree
  *
  * Copyright (C) 2015-2016 Smart Energy Instruments, Inc.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 
 #include <linux/of.h>
index d88c9484762c941b54ce5166c544f0b7e767819b..d2fdd56208f6e3dadaeedc7c16b88d4a70d0f3e5 100644 (file)
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
 #
 # Makefile for the SuperH DMA specific kernel interface routines under Linux.
 #
index b05be597b19f4970fd5bff701c0bf741a2ceedb0..ab9170494dcc29e0a8b64ed991cd8010d3c3e694 100644 (file)
@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/drivers/dma/dma-api.c
  *
  * SuperH-specific DMA management API
  *
  * Copyright (C) 2003, 2004, 2005  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/module.h>
@@ -417,4 +414,4 @@ subsys_initcall(dma_api_init);
 
 MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>");
 MODULE_DESCRIPTION("DMA API for SuperH");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
index e1ab6eb3c04bbabd114e310562c27d25a2ccc0d4..52a8ae5e30d2fbe1cc0368af046b9c9dd276f6a4 100644 (file)
@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/drivers/dma/dma-g2.c
  *
  * G2 bus DMA support
  *
  * Copyright (C) 2003 - 2006  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
@@ -197,4 +194,4 @@ module_exit(g2_dma_exit);
 
 MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>");
 MODULE_DESCRIPTION("G2 bus DMA driver");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
index 706a3434af7a6f581b41d968286bc482c628b050..b5dbd1f75768b6f3ccc148a3a046ea714dfebc5a 100644 (file)
@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/drivers/dma/dma-pvr2.c
  *
  * NEC PowerVR 2 (Dreamcast) DMA support
  *
  * Copyright (C) 2003, 2004  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
@@ -105,4 +102,4 @@ module_exit(pvr2_dma_exit);
 
 MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>");
 MODULE_DESCRIPTION("NEC PowerVR 2 DMA driver");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
index afde2a7d3eb35859270fe4a3bbdf20d742b8b35a..96c626c2cd0a496487eb3c6f660497cd0a5d3281 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/drivers/dma/dma-sh.c
  *
@@ -6,10 +7,6 @@
  * Copyright (C) 2000 Takashi YOSHII
  * Copyright (C) 2003, 2004 Paul Mundt
  * Copyright (C) 2005 Andriy Skulysh
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/interrupt.h>
@@ -414,4 +411,4 @@ module_exit(sh_dmac_exit);
 
 MODULE_AUTHOR("Takashi YOSHII, Paul Mundt, Andriy Skulysh");
 MODULE_DESCRIPTION("SuperH On-Chip DMAC Support");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
index 4b15feda54b04a24061830868a1d4fc1fdf2bff1..8ef318150f84db9a3d1df309f8462bfd5edf5bc4 100644 (file)
@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/drivers/dma/dma-sysfs.c
  *
  * sysfs interface for SH DMA API
  *
  * Copyright (C) 2004 - 2006  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/kernel.h>
 #include <linux/init.h>
index e5a57a109d6ce03cf2cabf628a595425fdf2ed8f..5b2c1fd254d7295b75e983d23cfb19c875e8c33f 100644 (file)
@@ -1,9 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * SH7760 DMABRG IRQ handling
  *
  * (c) 2007 MSC Vertriebsges.m.b.H, Manuel Lauss <mlau@msc-ge.com>
- *  licensed under the GPLv2.
- *
  */
 
 #include <linux/interrupt.h>
index e8af2ff29bc3b06ca974a5e7a5139a4b2ba52a29..cf2fcccca8126dce0586fc363e04c509e18b633c 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Generic heartbeat driver for regular LED banks
  *
  * traditionally used for strobing the load average. This use case is
  * handled by this driver, rather than giving each LED bit position its
  * own struct device.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/platform_device.h>
index 48aaefd8f5d6ccc5a3a2a67f0b484743d896a632..dfdbd05b6eb1e156565ac9ab9430058f9f5db945 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/drivers/pci/fixups-dreamcast.c
  *
@@ -9,10 +10,6 @@
  * This file originally bore the message (with enclosed-$):
  *     Id: pci.c,v 1.3 2003/05/04 19:29:46 lethal Exp
  *     Dreamcast PCI: Supports SEGA Broadband Adaptor only.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 
 #include <linux/sched.h>
index db5b40a98e62aa53a013f050e62098fd6b97643a..53fa2fc87eec280f4df4ac97b163a4dd568c00d6 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/drivers/pci/fixups-landisk.c
  *
@@ -5,9 +6,6 @@
  *
  * Copyright (C) 2006 kogiidena
  * Copyright (C) 2010 Nobuhiro Iwamatsu
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
  */
 #include <linux/kernel.h>
 #include <linux/types.h>
index 2c9b58f848dd3457fd4913f56269445409d96fac..3c9139c5955e6d2cb14c3a8fa7ae3110d7224d0d 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/drivers/pci/fixups-r7780rp.c
  *
@@ -5,10 +6,6 @@
  *
  * Copyright (C) 2003  Lineo uSolutions, Inc.
  * Copyright (C) 2004 - 2006  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/pci.h>
 #include <linux/io.h>
index 358ac104f08c4ee572f08d9d9b701f04125def57..3f0a6fe1610b61cc865705ee8bf8dc781291132d 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/drivers/pci/fixups-rts7751r2d.c
  *
@@ -6,10 +7,6 @@
  * Copyright (C) 2003  Lineo uSolutions, Inc.
  * Copyright (C) 2004  Paul Mundt
  * Copyright (C) 2007  Nobuhiro Iwamatsu
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/pci.h>
 #include <mach/lboxre2.h>
index 24e96dfbdb229c3992bee3c200229283af24e87c..c306040485bd23399eaaed4a4fd277240f80349f 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/drivers/pci/fixups-sdk7780.c
  *
@@ -6,10 +7,6 @@
  * Copyright (C) 2003  Lineo uSolutions, Inc.
  * Copyright (C) 2004 - 2006  Paul Mundt
  * Copyright (C) 2006  Nobuhiro Iwamatsu
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/pci.h>
 #include <linux/io.h>
index 36eb6fc3c18abd883f1257b52cd9edf65e6f3ff3..8cbfa5310a4b227b1c0a776b0b8621f003cf0d7f 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * SDK7786 FPGA PCIe mux handling
  *
  * Copyright (C) 2010  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #define pr_fmt(fmt) "PCI: " fmt
 
index a931e5928f58ca544b4715dae6da08a4f0017d81..317225c094137f0146d616370c39caf8b738aac6 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/drivers/pci/ops-snapgear.c
  *
@@ -7,9 +8,6 @@
  *
  * Highly leveraged from pci-bigsur.c, written by Dustin McIntire.
  *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
  * PCI initialization for the SnapGear boards
  */
 #include <linux/kernel.h>
index a9d563e479d5c12b418957f4202dbbcf3fa61023..b5bb65caa16d6f6a6faf4e139909b0a9e944cf5f 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/drivers/pci/ops-titan.c
  *
@@ -6,9 +7,6 @@
  * Modified from ops-snapgear.c written by  David McCullough
  * Highly leveraged from pci-bigsur.c, written by Dustin McIntire.
  *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
  * PCI initialization for the Titan boards
  */
 #include <linux/kernel.h>
index 16e0a1baad88b099f30faee9f416fcc87bbdd77c..517a8a9702f6625eadf034a3425a74d30977adb1 100644 (file)
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * PCI operations for the Sega Dreamcast
  *
  * Copyright (C) 2001, 2002  M. R. Brown
  * Copyright (C) 2002, 2003  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 
 #include <linux/sched.h>
index b6234203e0ac19404ed2943d5e0c808953907dc6..a205be3bfc4a67839b80c0992d4daf32fb6647a1 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Generic SH-4 / SH-4A PCIC operations (SH7751, SH7780).
  *
  * Copyright (C) 2002 - 2009  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License v2. See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/pci.h>
 #include <linux/io.h>
index 45361946460fedd7fa2873a32a828542655aadb8..9fbaf72949ab72be82c5f84fff714afa80a39ba7 100644 (file)
@@ -1,12 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Support functions for the SH5 PCI hardware.
  *
  * Copyright (C) 2001 David J. Mckay (david.mckay@st.com)
  * Copyright (C) 2003, 2004 Paul Mundt
  * Copyright (C) 2004 Richard Curnow
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
  */
 #include <linux/kernel.h>
 #include <linux/rwsem.h>
index 128421009e3f2fbbf56ec01d2a13728d675eb0a1..a10f9f4ebd7fe999d5c7d316b9a6036e95d9cd06 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Generic SH7786 PCI-Express operations.
  *
  *  Copyright (C) 2009 - 2010  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License v2. See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/kernel.h>
 #include <linux/init.h>
index 633694193af8f7c08011ac971c28d3f58424dd2a..4cff2a8107bf065480ad0a5a93284412e7e48e51 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * PCI support for the Sega Dreamcast
  *
@@ -7,10 +8,6 @@
  * This file originally bore the message (with enclosed-$):
  *     Id: pci.c,v 1.3 2003/05/04 19:29:46 lethal Exp
  *     Dreamcast PCI: Supports SEGA Broadband Adaptor only.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 
 #include <linux/sched.h>
index 8229114c6a58cfa82c821d67570b0a93626a523d..49303fab187bf66fa1671f480bb32acd9eb2d38f 100644 (file)
@@ -1,11 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2001 David J. Mckay (david.mckay@st.com)
  * Copyright (C) 2003, 2004 Paul Mundt
  * Copyright (C) 2004 Richard Curnow
  *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
  * Support functions for the SH5 PCI hardware.
  */
 
index 3f01decb43076d53e89710342400efd31b0853ae..91348af0ef6c6d187611919de83987b4a273eaf3 100644 (file)
@@ -1,8 +1,6 @@
-/*
- * Copyright (C) 2001 David J. Mckay (david.mckay@st.com)
+/* SPDX-License-Identifier: GPL-2.0
  *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
+ * Copyright (C) 2001 David J. Mckay (david.mckay@st.com)
  *
  * Definitions for the SH5 PCI hardware.
  */
index 86adb1e235cdd6bf105e4e35c501045873ea2b67..1b9e5caac389838b995b1d17deb55b6314f3de13 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Low-Level PCI Support for the SH7751
  *
@@ -5,10 +6,6 @@
  *  Copyright (C) 2001  Dustin McIntire
  *
  *  With cleanup by Paul van Gool <pvangool@mimotech.com>, 2003.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/pci.h>
index 5ede38c330d35e8f8f3d33bb32b8464a9d3b6e04..d1951e50effc8b43f19af0a4291b6d49dddfe692 100644 (file)
@@ -1,12 +1,9 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
  *     Low-Level PCI Support for SH7751 targets
  *
  *  Dustin McIntire (dustin@sensoria.com) (c) 2001
  *  Paul Mundt (lethal@linux-sh.org) (c) 2003
- *
- *  May be copied or modified under the terms of the GNU General Public
- *  License.  See linux/COPYING for more information.
- *
  */
 
 #ifndef _PCI_SH7751_H_
index 5a6dab6e27d96deb24353f1e4630594825dc545f..3fd0f392a0ee05d5466c5dafc4a1f0d19a5fd012 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Low-Level PCI Support for the SH7780
  *
  *  Copyright (C) 2005 - 2010  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/types.h>
 #include <linux/kernel.h>
index 1742e2c9db7a0ed3c90d38478bd32553b31485d8..e2ac770f8e35026eca620f96268a5654e8e09522 100644 (file)
@@ -1,12 +1,9 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
  *     Low-Level PCI Support for SH7780 targets
  *
  *  Dustin McIntire (dustin@sensoria.com) (c) 2001
  *  Paul Mundt (lethal@linux-sh.org) (c) 2003
- *
- *  May be copied or modified under the terms of the GNU General Public
- *  License.  See linux/COPYING for more information.
- *
  */
 
 #ifndef _PCI_SH7780_H_
index 8256626bc53cc0125db0f3032ee1dcc0326442b3..c7784e1569644d768ad0c90934602f8e3b47824d 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * New-style PCI core.
  *
@@ -6,10 +7,6 @@
  *
  * Modelled after arch/mips/pci/pci.c:
  *  Copyright (C) 2003, 04 Ralf Baechle (ralf@linux-mips.org)
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/kernel.h>
 #include <linux/mm.h>
index 3d81a8b809427907754053549caa7aff654c6dcd..a58b77cea2957f981214aa97f28f11c36d138b96 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Low-Level PCI Express Support for the SH7786
  *
  *  Copyright (C) 2009 - 2011  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #define pr_fmt(fmt) "PCI: " fmt
 
index 4a6ff55f759b5152df4fcad623d8ce565d8dec10..ffe383681a0bd224191e7de8566fa0a467a640f6 100644 (file)
@@ -1,12 +1,9 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
  * SH7786 PCI-Express controller definitions.
  *
  * Copyright (C) 2008, 2009 Renesas Technology Corp.
  * All rights reserved.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #ifndef __PCI_SH7786_H
 #define __PCI_SH7786_H
index 762bc561991058c82cc2e19c90d87c1fa49fb70c..2813140fd92bb2dcdcc1136739818565081d41d5 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Generic push-switch framework
  *
  * Copyright (C) 2006  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/slab.h>
index 5b8e0c7ca3a57b087232644c9174a2c9bab5ef59..aa6e3267c055d92a49b2cd57eef92fc0600cc8c0 100644 (file)
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
 #
 # Makefile for the SuperHyway specific kernel interface routines under Linux.
 #
index 6da62e9475c45a498becee4c8041d3a0b248b19f..490142274e3b0a8f5cc5f345b16e1f728486160c 100644 (file)
@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/drivers/superhyway/ops-sh4-202.c
  *
  * SuperHyway bus support for SH4-202
  *
  * Copyright (C) 2005  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU
- * General Public License.  See the file "COPYING" in the main
- * directory of this archive for more details.
  */
 #include <linux/kernel.h>
 #include <linux/init.h>
index b15caf34813a71dbbb336eb3e3c5727734631cb7..a6ef3fee5f85714f69e6692e563491960372ab75 100644 (file)
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
 generated-y += syscall_table.h
 generic-y += compat.h
 generic-y += current.h
index 3d1ae2bfaa6fd7056701e8ddc41538d94a4a1a71..34bfbcddcce027790721f41372a5099a281fd476 100644 (file)
@@ -1,7 +1,4 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
+/* SPDX-License-Identifier: GPL-2.0
  *
  * Copyright (C) 1999 by Kaz Kojima
  *
index d370ee36a182ba510c28459f856b17f321bd57fc..9f8535716392cc62c3ab5fa9983f0b1fb4f3eea5 100644 (file)
@@ -1 +1,2 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 #include <generated/asm-offsets.h>
index 6cc8711af435b6a4854fcb07b5074b8a3503b9fe..aac9780fe8645410e242159d9e758e9eb2999b39 100644 (file)
@@ -1,11 +1,8 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
  * Copyright (C) 2000, 2001  Paolo Alberelli
  * Copyright (C) 2003  Paul Mundt
  * Copyright (C) 2004  Richard Curnow
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #ifndef __ASM_SH_BL_BIT_64_H
 #define __ASM_SH_BL_BIT_64_H
index 70b6357eaf1a470c0bee324220419ecc78c742e1..ed682b987b0d9d9d909994443197789ca224e0a0 100644 (file)
@@ -1,11 +1,8 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
  * Copyright (C) 2000, 2001  Paolo Alberelli
  * Copyright (C) 2003  Paul Mundt
  * Copyright (C) 2004  Richard Curnow
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #ifndef __ASM_SH_CACHE_INSNS_64_H
 #define __ASM_SH_CACHE_INSNS_64_H
index 9c84386d35cba988f95bc6d2c80b558cbc99ad9a..b58f3d95dc1913deacf48314535faac0ae4e37a9 100644 (file)
@@ -1,11 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 #ifndef __ASM_SH_CHECKSUM_H
 #define __ASM_SH_CHECKSUM_H
 
 /*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
  * Copyright (C) 1999 by Kaz Kojima & Niibe Yutaka
  */
 
index 593a9704782bdc7108696011ab0d65850d5393d3..c373f21efe4d9057507053e759958a290002c0dd 100644 (file)
@@ -1,12 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 #ifndef __ASM_SH_CMPXCHG_XCHG_H
 #define __ASM_SH_CMPXCHG_XCHG_H
 
 /*
  * Copyright (C) 2016 Red Hat, Inc.
  * Author: Michael S. Tsirkin <mst@redhat.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2.  See the
- * file "COPYING" in the main directory of this archive for more details.
  */
 #include <linux/bits.h>
 #include <linux/compiler.h>
index 071bcb4d4bfd12576f78e2c99e57d8df05bf4410..6f3e686a1c6f3e3ebf9a8ca6d84852f5013e620d 100644 (file)
@@ -1,7 +1,6 @@
-/*
- * Arch specific extensions to struct device
+/* SPDX-License-Identifier: GPL-2.0
  *
- * This file is released under the GPLv2
+ * Arch specific extensions to struct device
  */
 #ifndef __ASM_SH_DEVICE_H
 #define __ASM_SH_DEVICE_H
index c757b47e6b6481ff6ad49254b2f0b209f4e3d7af..724dab912b7108e645c9fb31f99b2997de1fd2a9 100644 (file)
@@ -1,14 +1,11 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
  * Common header for the legacy SH DMA driver and the new dmaengine driver
  *
  * extracted from arch/sh/include/asm/dma-sh.h:
  *
  * Copyright (C) 2000  Takashi YOSHII
  * Copyright (C) 2003  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #ifndef DMA_REGISTER_H
 #define DMA_REGISTER_H
index fb6e4f7b00a2c48fed82aa09b5cf72c837959b36..4d5a21a891c078822098e0966c67bfba92c4cfa3 100644 (file)
@@ -1,11 +1,8 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
  * include/asm-sh/dma.h
  *
  * Copyright (C) 2003, 2004  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #ifndef __ASM_SH_DMA_H
 #define __ASM_SH_DMA_H
index d62abd1d0c05b31b9da9d4e07dfff264d35abb82..57195447412212c3ce7a4724a98c3ae4f09477e3 100644 (file)
@@ -1,10 +1,6 @@
-/*
- * Copyright (C) 2009 Matt Fleming <matt@console-pimps.org>
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
+/* SPDX-License-Identifier: GPL-2.0
  *
+ * Copyright (C) 2009 Matt Fleming <matt@console-pimps.org>
  */
 #ifndef __ASM_SH_DWARF_H
 #define __ASM_SH_DWARF_H
index d92e99cd8c8aba17b2e80a33beb1ed466af3cea7..9a0bca2686fd3d34a7a89aa6be34cc587256b48f 100644 (file)
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 #ifndef _ASM_FB_H_
 #define _ASM_FB_H_
 
index 4daf91c3b725905e3b59f68151e0e3f71ba542ed..e30348c58073811376d7a63fa8ba65e6910de6f0 100644 (file)
@@ -1,9 +1,6 @@
-/*
- * fixmap.h: compile-time virtual memory allocation
+/* SPDX-License-Identifier: GPL-2.0
  *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
+ * fixmap.h: compile-time virtual memory allocation
  *
  * Copyright (C) 1998 Ingo Molnar
  *
index 275fcae2353920098bb95393873671e2d578c39a..843d458b8329fb944f18d740b53d36bdae527abd 100644 (file)
@@ -1,13 +1,10 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
  * include/asm-sh/flat.h
  *
  * uClinux flat-format executables
  *
  * Copyright (C) 2003  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive for
- * more details.
  */
 #ifndef __ASM_SH_FLAT_H
 #define __ASM_SH_FLAT_H
index 4ece90b09b9c4d94640ac155fdceccf7177f87dd..18133bf837386ba3cbe917a95aa2f7eee9a25eae 100644 (file)
@@ -1,12 +1,8 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0+
+ *
  * include/asm-sh/freq.h
  *
  * Copyright (C) 2002, 2003 Paul Mundt
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
  */
 #ifndef __ASM_SH_FREQ_H
 #define __ASM_SH_FREQ_H
index 7dfe15e2e990b5fd11ffab3945ddd5eed46923b3..351918894e867fd1f303cefa8037ba32383939ed 100644 (file)
@@ -1,13 +1,10 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
  *  include/asm-sh/gpio.h
  *
  * Generic GPIO API and pinmux table support for SuperH.
  *
  * Copyright (c) 2008 Magnus Damm
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #ifndef __ASM_SH_GPIO_H
 #define __ASM_SH_GPIO_H
index d3324e4f372ec9d544f7c35a19d70f1fb679fee1..f7d05546becaf8101870d2d8c4abb3f12855630a 100644 (file)
@@ -1,10 +1,8 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
  * include/asm-sh/machvec.h
  *
  * Copyright 2000 Stuart Menefy (stuart.menefy@st.com)
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
  */
 
 #ifndef _ASM_SH_MACHVEC_H
index de121025d87f28f367b374545496782e7a142e51..bacafe0b887d45e799b99b473526a1849fe85f7a 100644 (file)
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 #ifndef __ASM_SH_MMU_CONTEXT_64_H
 #define __ASM_SH_MMU_CONTEXT_64_H
 
@@ -6,10 +7,6 @@
  *
  * Copyright (C) 2000, 2001  Paolo Alberelli
  * Copyright (C) 2003 - 2007  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <cpu/registers.h>
 #include <asm/cacheflush.h>
index f6abfe2bca93b8254278f635420b1fbc410b4a99..3587103afe59e6e8d283576ff31d917814942841 100644 (file)
@@ -1,13 +1,10 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
  * This file contains the functions and defines necessary to modify and
  * use the SuperH page table tree.
  *
  * Copyright (C) 1999 Niibe Yutaka
  * Copyright (C) 2002 - 2007 Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file "COPYING" in the main directory of this
- * archive for more details.
  */
 #ifndef __ASM_SH_PGTABLE_H
 #define __ASM_SH_PGTABLE_H
index 07424968df6210154f188c212b2e97f12f259e6c..1778bc5971e753b3d7b0f848da3bceebae5d9601 100644 (file)
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 #ifndef __ASM_SH_PGTABLE_64_H
 #define __ASM_SH_PGTABLE_64_H
 
  * Copyright (C) 2000, 2001  Paolo Alberelli
  * Copyright (C) 2003, 2004  Paul Mundt
  * Copyright (C) 2003, 2004  Richard Curnow
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/threads.h>
 #include <asm/processor.h>
index f3d7075648d049239f58e1e5f76cb23d13dc89df..53efc9f51ef1512a05dd17d7df2d3ae23ca79028 100644 (file)
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 #ifndef __ASM_SH_PROCESSOR_64_H
 #define __ASM_SH_PROCESSOR_64_H
 
@@ -7,10 +8,6 @@
  * Copyright (C) 2000, 2001  Paolo Alberelli
  * Copyright (C) 2003  Paul Mundt
  * Copyright (C) 2004  Richard Curnow
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #ifndef __ASSEMBLY__
 
index d3c548443f2a6e7774e7f1f2fd6789e2d129d9c0..cbc7cf8c97ce613fec2c0f3e887cf95c5f1788d1 100644 (file)
@@ -1,4 +1,6 @@
-/* Machine-dependent software floating-point definitions.
+/* SPDX-License-Identifier: GPL-2.0+
+ *
+ * Machine-dependent software floating-point definitions.
    SuperH kernel version.
    Copyright (C) 1997,1998,1999 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
@@ -6,21 +8,7 @@
                  Jakub Jelinek (jj@ultra.linux.cz),
                  David S. Miller (davem@redhat.com) and
                  Peter Maydell (pmaydell@chiark.greenend.org.uk).
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Library General Public License as
-   published by the Free Software Foundation; either version 2 of the
-   License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Library General Public License for more details.
-
-   You should have received a copy of the GNU Library General Public
-   License along with the GNU C Library; see the file COPYING.LIB.  If
-   not, write to the Free Software Foundation, Inc.,
-   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+*/
 
 #ifndef _SFP_MACHINE_H
 #define _SFP_MACHINE_H
index ba1758d90106267f23ea1c05362e59f1805ff40d..6c580a644a78c6e020c1983c442813d283b7b58c 100644 (file)
@@ -1,12 +1,9 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
  * include/asm-sh/shmparam.h
  *
  * Copyright (C) 1999 Niibe Yutaka
  * Copyright (C) 2006 Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #ifndef __ASM_SH_SHMPARAM_H
 #define __ASM_SH_SHMPARAM_H
index 580b7ac228b72029073fc7736e7982ad064d6830..35e4839d381e882626042f8c92a9ec4b0803dc5b 100644 (file)
@@ -1,11 +1,8 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
  * platform header for the SIU ASoC driver
  *
  * Copyright (C) 2009-2010 Guennadi Liakhovetski <g.liakhovetski@gmx.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
  */
 
 #ifndef ASM_SIU_H
index 270ee4d3e25b8acc9fd2231d2b93d061d18a9fc7..3d49985ebf41c920f988362a9993ec8a1a028ff9 100644 (file)
@@ -1,11 +1,8 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
  * include/asm-sh/spinlock-cas.h
  *
  * Copyright (C) 2015 SEI
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #ifndef __ASM_SH_SPINLOCK_CAS_H
 #define __ASM_SH_SPINLOCK_CAS_H
index 715595de286a8348f05ac5470db369d130febcdd..786ee0fde3b010f3bae867220ec9c68d84e895e8 100644 (file)
@@ -1,12 +1,9 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
  * include/asm-sh/spinlock-llsc.h
  *
  * Copyright (C) 2002, 2003 Paul Mundt
  * Copyright (C) 2006, 2007 Akio Idehara
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #ifndef __ASM_SH_SPINLOCK_LLSC_H
 #define __ASM_SH_SPINLOCK_LLSC_H
index c2c61ea6a8e23244ae3ac586cc658b099b8e15ec..fa6801f63551cebe6de9a25805b9bb69d3dafa9e 100644 (file)
@@ -1,12 +1,9 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
  * include/asm-sh/spinlock.h
  *
  * Copyright (C) 2002, 2003 Paul Mundt
  * Copyright (C) 2006, 2007 Akio Idehara
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #ifndef __ASM_SH_SPINLOCK_H
 #define __ASM_SH_SPINLOCK_H
index 55f8db6bc1d75b1604e7493ab19c6b73ae601c7f..3558b1d7123e9c7ba53df3147a0b604a67e4dd7b 100644 (file)
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 #ifndef __ASM_SH_STRING_H
 #define __ASM_SH_STRING_H
 
index bcd722fc8347bd7389c8baf5d749cffb70213e8b..9eec80ab5aa27c648d6cec4d631a6483c413a68d 100644 (file)
@@ -1,11 +1,8 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
  * Copyright (C) 2000, 2001  Paolo Alberelli
  * Copyright (C) 2003  Paul Mundt
  * Copyright (C) 2004  Richard Curnow
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #ifndef __ASM_SH_SWITCH_TO_H
 #define __ASM_SH_SWITCH_TO_H
index ba3129d6bc21087c6f732fcb276f988c35edadde..2dbf2311669f5cf48b7a79099c76b84579aa474f 100644 (file)
@@ -1,11 +1,8 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
  * Copyright (C) 2000, 2001  Paolo Alberelli
  * Copyright (C) 2003  Paul Mundt
  * Copyright (C) 2004  Richard Curnow
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #ifndef __ASM_SH_SWITCH_TO_64_H
 #define __ASM_SH_SWITCH_TO_64_H
index ef0ae2a28f232638565519656f4f00bf3eb8cdd4..59fa0a23dad7ffdc49343565926e78681457aaa6 100644 (file)
@@ -1,11 +1,8 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
  * include/asm-sh/tlb_64.h
  *
  * Copyright (C) 2003  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #ifndef __ASM_SH_TLB_64_H
 #define __ASM_SH_TLB_64_H
index ef5eff9194498fa96288ba168357cde40181ebe6..f28db6dfbe455a6e6ef4f99c32070d51e5672fc6 100644 (file)
@@ -1,11 +1,8 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
  * Copyright (C) 2000, 2001  Paolo Alberelli
  * Copyright (C) 2003  Paul Mundt
  * Copyright (C) 2004  Richard Curnow
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #ifndef __ASM_SH_TRAPS_64_H
 #define __ASM_SH_TRAPS_64_H
index ca5073dd459674d1ad835406fc46baa1957d01ac..0c19d02dc566db2019f5253d70c49e7bc3516301 100644 (file)
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 #ifndef __ASM_SH_UACCESS_64_H
 #define __ASM_SH_UACCESS_64_H
 
  *     MIPS implementation version 1.15 by
  *              Copyright (C) 1996, 1997, 1998 by Ralf Baechle
  *     and i386 version.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 
 #define __get_user_size(x,ptr,size,retval)                     \
index 06a5de8ace1a6266575610c14cc9837e6d170d21..089fbdc6c0b1d0a5da9c952cc69019eeb760f077 100644 (file)
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 #ifndef __ASM_SH_VGA_H
 #define __ASM_SH_VGA_H
 
index 85a7aca7fb8f37dd42c13f8b658a14edfd9f89ca..cecd0fc507f9386a48fb40d12cde4618fea5e471 100644 (file)
@@ -1,14 +1,10 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0+
+ *
  * include/asm-sh/watchdog.h
  *
  * Copyright (C) 2002, 2003 Paul Mundt
  * Copyright (C) 2009 Siemens AG
  * Copyright (C) 2009 Valentin Sitdikov
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
  */
 #ifndef __ASM_SH_WATCHDOG_H
 #define __ASM_SH_WATCHDOG_H
index 2b9ab93efa4ef38bd14877d40c08a4ba782f7fc3..d8bf5d7d2fdf0a27888bb94e489725e40a24ada9 100644 (file)
@@ -1,11 +1,8 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
  * Definitions for the address spaces of the SH-2 CPUs.
  *
  * Copyright (C) 2003  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #ifndef __ASM_CPU_SH2_ADDRSPACE_H
 #define __ASM_CPU_SH2_ADDRSPACE_H
index beeb299e01ec4fd1af8b2231697cef3544d19045..cef3a30dbf97c812c0b9a9ae6afef7fdf6955617 100644 (file)
@@ -1,11 +1,8 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
  * include/asm-sh/cpu-sh2/mmu_context.h
  *
  * Copyright (C) 2003  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #ifndef __ASM_CPU_SH2_MMU_CONTEXT_H
 #define __ASM_CPU_SH2_MMU_CONTEXT_H
index e538813286a87463244a88ec0815196e4b96d029..879d2c9da537fa32239c1434175f393da9b115c4 100644 (file)
@@ -1,16 +1,8 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
  * SH Pin Function Control Initialization
  *
  * Copyright (C) 2012  Renesas Solutions Corp.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 #ifndef __ARCH_SH_CPU_PFC_H__
index a39c241e81955283ca95c1255b7780d610c796f0..af51438755e003aacb3d9309cb4d6db46ef13eef 100644 (file)
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 #ifndef __ASM_CPU_SH2_TIMER_H
 #define __ASM_CPU_SH2_TIMER_H
 
index aa1b2b9088a77b061758f48f4a434185e760d6ca..070aa9f50d3f0922f1aa4b7bd8daa86fa87843a3 100644 (file)
@@ -1,11 +1,8 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
  * include/asm-sh/cpu-sh2/cache.h
  *
  * Copyright (C) 2003 Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #ifndef __ASM_CPU_SH2_CACHE_H
 #define __ASM_CPU_SH2_CACHE_H
index 31de475da70bb210fc1511b0fe92bcc2f536cd57..fb2e5d2831bc765abc41578e46ea87050b191b4b 100644 (file)
@@ -1,11 +1,8 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
  * include/asm-sh/cpu-sh2/freq.h
  *
  * Copyright (C) 2006  Yoshinori Sato
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #ifndef __ASM_CPU_SH2_FREQ_H
 #define __ASM_CPU_SH2_FREQ_H
index 1eab8aa63a6d611fad7afb2e9bc0a584ac4c7875..141fe296d75168759878d830f9066743a8b039b3 100644 (file)
@@ -1,11 +1,8 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
  * include/asm-sh/cpu-sh2/watchdog.h
  *
  * Copyright (C) 2002, 2003 Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #ifndef __ASM_CPU_SH2_WATCHDOG_H
 #define __ASM_CPU_SH2_WATCHDOG_H
index b27ce92cb600bc17c47dacda12d0e3dc9f8d06a1..06efb233eb35f457dc434023f4e2e1be57551f90 100644 (file)
@@ -1,11 +1,8 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
  * include/asm-sh/cpu-sh2a/cache.h
  *
  * Copyright (C) 2004 Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #ifndef __ASM_CPU_SH2A_CACHE_H
 #define __ASM_CPU_SH2A_CACHE_H
index 830fd43b6cdc684fc26ed5bde1ed8d8fef2b6e78..fb0813f47043ea59fd7d96a44f44c720f8d23f42 100644 (file)
@@ -1,11 +1,8 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
  * include/asm-sh/cpu-sh2a/freq.h
  *
  * Copyright (C) 2006  Yoshinori Sato
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #ifndef __ASM_CPU_SH2A_FREQ_H
 #define __ASM_CPU_SH2A_FREQ_H
index e7e8259e468cb643b057378ffccd0786ddb878c8..8f932b733c67480de8727a8eab7f64865904f212 100644 (file)
@@ -1 +1,2 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 #include <cpu-sh2/cpu/watchdog.h>
index 29700fd88c75d30be16340966c3013f1c880f076..f571248269430c349714806f1830c226753c2ac2 100644 (file)
@@ -1,11 +1,8 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
  * include/asm-sh/cpu-sh3/cache.h
  *
  * Copyright (C) 1999 Niibe Yutaka
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #ifndef __ASM_CPU_SH3_CACHE_H
 #define __ASM_CPU_SH3_CACHE_H
index 2349e488c9a6b50b00b69af34c503d7e08315419..c0f921fb4edcd1864f5e945638796dbc28eff98d 100644 (file)
@@ -1,11 +1,8 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
  * SH3 CPU-specific DMA definitions, used by both DMA drivers
  *
  * Copyright (C) 2010 Guennadi Liakhovetski <g.liakhovetski@gmx.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
  */
 #ifndef CPU_DMA_REGISTER_H
 #define CPU_DMA_REGISTER_H
index 53c62302b2e35898806c8f0bcd56827a630a5fd4..7290f02b7173302d53b2148dd1852622055c5236 100644 (file)
@@ -1,11 +1,8 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
  * include/asm-sh/cpu-sh3/freq.h
  *
  * Copyright (C) 2002, 2003 Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #ifndef __ASM_CPU_SH3_FREQ_H
 #define __ASM_CPU_SH3_FREQ_H
index 9a22b882f3dc27392beaf0983ca32befccb3443d..aeb0588ace980c63380b5b1eeecfe67b57bf2148 100644 (file)
@@ -1,13 +1,10 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
  *  include/asm-sh/cpu-sh3/gpio.h
  *
  *  Copyright (C) 2007  Markus Brunner, Mark Jonas
  *
  *  Addresses for the Pin Function Controller
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #ifndef _CPU_SH3_GPIO_H
 #define _CPU_SH3_GPIO_H
index 0c7c735ea82ad4fdeb186ccb72b373493f82c3e2..ead9a6f721135d87c5bdadea80265d45014c4ae1 100644 (file)
@@ -1,11 +1,8 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
  * include/asm-sh/cpu-sh3/mmu_context.h
  *
  * Copyright (C) 1999 Niibe Yutaka
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #ifndef __ASM_CPU_SH3_MMU_CONTEXT_H
 #define __ASM_CPU_SH3_MMU_CONTEXT_H
index 4ee0347298d8c34ac58707336a1581ee99ee49a2..9d7e9d986809476abd4f96639b3fcdf1b8d388b3 100644 (file)
@@ -1,11 +1,8 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
  * include/asm-sh/cpu-sh3/watchdog.h
  *
  * Copyright (C) 2002, 2003 Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #ifndef __ASM_CPU_SH3_WATCHDOG_H
 #define __ASM_CPU_SH3_WATCHDOG_H
index d51da25da72c401267a05e01ed70bb86d0b03d82..f006c9489f5adb11ecd58d4398cacd7cc5ec9083 100644 (file)
@@ -1,7 +1,4 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
+/* SPDX-License-Identifier: GPL-2.0
  *
  * Copyright (C) 1999 by Kaz Kojima
  *
index 92c4cd119b662f99dc4ed9d0f5d1b54dea3001a9..72b4d13da127cd194fd37d761827af5d0085d7ff 100644 (file)
@@ -1,11 +1,8 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
  * include/asm-sh/cpu-sh4/cache.h
  *
  * Copyright (C) 1999 Niibe Yutaka
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #ifndef __ASM_CPU_SH4_CACHE_H
 #define __ASM_CPU_SH4_CACHE_H
index 9cd81e54056ac477f1a8091dafd5b736605f7578..53f7ab990d887421976e8896dea81a0778993aa9 100644 (file)
@@ -1,11 +1,8 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
  * SH4 CPU-specific DMA definitions, used by both DMA drivers
  *
  * Copyright (C) 2010 Guennadi Liakhovetski <g.liakhovetski@gmx.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
  */
 #ifndef CPU_DMA_REGISTER_H
 #define CPU_DMA_REGISTER_H
index febef73425287a7bafac347640548dd584a97b4d..29f451bfef19b45db322296b21595ed7f4055aa1 100644 (file)
@@ -1,12 +1,10 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
  * linux/arch/sh/kernel/cpu/sh4/sh4_fpu.h
  *
  * Copyright (C) 2006 STMicroelectronics Limited
  * Author: Carl Shaw <carl.shaw@st.com>
  *
- * May be copied or modified under the terms of the GNU General Public
- * License Version 2.  See linux/COPYING for more information.
- *
  * Definitions for SH4 FPU operations
  */
 
index 1631fc238e6f006439cb2a64b05fbca27e016caa..662f0f30e106e81c10ed1560c32653c46f5abfa6 100644 (file)
@@ -1,11 +1,8 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
  * include/asm-sh/cpu-sh4/freq.h
  *
  * Copyright (C) 2002, 2003 Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #ifndef __ASM_CPU_SH4_FREQ_H
 #define __ASM_CPU_SH4_FREQ_H
index e46ec708105af0b74e219b2cd3a00392a0cc92b6..421b56d5c5956223dbfe5db4902f893d69391a28 100644 (file)
@@ -1,11 +1,8 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
  * include/asm-sh/cpu-sh4/mmu_context.h
  *
  * Copyright (C) 1999 Niibe Yutaka
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #ifndef __ASM_CPU_SH4_MMU_CONTEXT_H
 #define __ASM_CPU_SH4_MMU_CONTEXT_H
index 96b8cb1f754a9556b428c1de4c6481f653bde334..8f9bfbf3cdb1097fe3f41390372723c3453f211b 100644 (file)
@@ -1,14 +1,11 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
  * SH7786 Pinmux
  *
  * Copyright (C) 2008, 2009  Renesas Solutions Corp.
  * Kuninori Morimoto <morimoto.kuninori@renesas.com>
  *
  *  Based on sh7785.h
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 
 #ifndef __CPU_SH7786_H__
index 74716ba2dc3cd3fb1cb3135c25689401e6dcf3ca..81966e41fc213be6a92b086290ba79edf63de0bc 100644 (file)
@@ -1,12 +1,9 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
  * include/asm-sh/cpu-sh4/sq.h
  *
  * Copyright (C) 2001, 2002, 2003  Paul Mundt
  * Copyright (C) 2001, 2002  M. R. Brown
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #ifndef __ASM_CPU_SH4_SQ_H
 #define __ASM_CPU_SH4_SQ_H
index 7f62b9380938203ad6d25a221db7c44424b1c46f..fa7bcb398b8cca22a702a94dbeb90d7202e5e9bb 100644 (file)
@@ -1,13 +1,10 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
  * include/asm-sh/cpu-sh4/watchdog.h
  *
  * Copyright (C) 2002, 2003 Paul Mundt
  * Copyright (C) 2009 Siemens AG
  * Copyright (C) 2009 Sitdikov Valentin
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #ifndef __ASM_CPU_SH4_WATCHDOG_H
 #define __ASM_CPU_SH4_WATCHDOG_H
index ed050ab526f2ef2c308a301a284ed36833f16474..ef49538f386f71de730501a808750750203b5605 100644 (file)
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 #ifndef __ASM_SH_CPU_SH5_CACHE_H
 #define __ASM_SH_CPU_SH5_CACHE_H
 
@@ -6,10 +7,6 @@
  *
  * Copyright (C) 2000, 2001  Paolo Alberelli
  * Copyright (C) 2003, 2004  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 
 #define L1_CACHE_SHIFT         5
index 0ccf257a72d1fa216468a5e871fd48afff35a308..4aa6ac54b9d60aaf0388f5a2a0da8bb6411a427d 100644 (file)
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 #ifndef __ASM_SH_CPU_SH5_IRQ_H
 #define __ASM_SH_CPU_SH5_IRQ_H
 
@@ -5,10 +6,6 @@
  * include/asm-sh/cpu-sh5/irq.h
  *
  * Copyright (C) 2000, 2001  Paolo Alberelli
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 
 
index 6664ea6f1566f748bf87dbbf36b24e08e64fe4f9..372c1e1978b3369837c50f0ec4c48a8ac0ea526e 100644 (file)
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 #ifndef __ASM_SH_CPU_SH5_REGISTERS_H
 #define __ASM_SH_CPU_SH5_REGISTERS_H
 
@@ -6,10 +7,6 @@
  *
  * Copyright (C) 2000, 2001  Paolo Alberelli
  * Copyright (C) 2004  Richard Curnow
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 
 #ifdef __ASSEMBLY__
index 6aaaf8596e6a823c0c17b74bb55849e46e97818d..71241f0d02a19c309bcb5edea05047c0742e1dbf 100644 (file)
@@ -1,14 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright (C) 2003, 2004, 2005  Andriy Skulysh
+ */
 #ifndef __ASM_SH_HP6XX_H
 #define __ASM_SH_HP6XX_H
 
-/*
- * Copyright (C) 2003, 2004, 2005  Andriy Skulysh
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- */
 #include <linux/sh_intc.h>
 
 #define HP680_BTN_IRQ          evt2irq(0x600)  /* IRQ0_IRQ */
index 3a4dcc5c74eea28187046d39af6ce3c946706b81..5b6bb8e3cf284742148518fd214938c2dfeca017 100644 (file)
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 #ifndef __ASM_SH_LBOXRE2_H
 #define __ASM_SH_LBOXRE2_H
 
@@ -5,11 +6,6 @@
  * Copyright (C) 2007 Nobuhiro Iwamatsu
  *
  * NTT COMWARE L-BOX RE2 support
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
  */
 #include <linux/sh_intc.h>
 
index eb0cf205176fb56d0e600b0af5561da1f29dcaee..c2d218cea74b65ac63b9c8d6f4e31f7eae365574 100644 (file)
@@ -1,13 +1,10 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
  *  include/asm-sh/magicpanelr2.h
  *
  *  Copyright (C) 2007  Markus Brunner, Mark Jonas
  *
  *  I/O addresses and bitmasks for Magic Panel Release 2 board
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 
 #ifndef __ASM_SH_MAGICPANELR2_H
index 4ca1769a0f12938e7de7589f8a3eec80b08a889b..dd5a761a52ee63a1e43e869e8ef85177a7a3a09f 100644 (file)
@@ -1,9 +1,6 @@
-/*
- * SH version cribbed from the MIPS copy:
+/* SPDX-License-Identifier: GPL-2.0
  *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
+ * SH version cribbed from the MIPS copy:
  *
  * Copyright (C) 2003, 2004 Ralf Baechle
  */
index dcb05fa8c164d9c9044df5ce85665953328f7e21..0e2f9ab119762052784a32189ea36fbda26bf35a 100644 (file)
@@ -1,12 +1,10 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
  * linux/include/asm-sh/microdev.h
  *
  * Copyright (C) 2003 Sean McGoogan (Sean.McGoogan@superh.com)
  *
  * Definitions for the SuperH SH4-202 MicroDev board.
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
  */
 #ifndef __ASM_SH_MICRODEV_H
 #define __ASM_SH_MICRODEV_H
index ce64e02e9b50f462dc4e3706bf7076462d39c194..a27dbe4184b35b2d42c5bc447c02829bf573e1fb 100644 (file)
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 #ifndef __ASM_SH_RENESAS_SDK7780_H
 #define __ASM_SH_RENESAS_SDK7780_H
 
@@ -6,10 +7,6 @@
  *
  * Renesas Solutions SH7780 SDK Support
  * Copyright (C) 2008 Nicholas Beck <nbeck@mpc-data.co.uk>
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/sh_intc.h>
 #include <asm/addrspace.h>
index 3653b9a4bacc323027fb3b8d98e45d9e8eea6dfe..dfc68aa910033dfb14af19f5a64463b1ac3691fc 100644 (file)
@@ -1,11 +1,9 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
  * include/asm-sh/snapgear.h
  *
  * Modified version of io_se.h for the snapgear-specific functions.
  *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
  * IO functions for a SnapGear
  */
 
index 8750cc8529770ac544e454bd46f458018db188be..301f85a1c044d285a0cbabbaaab0bbaef8bb5f5a 100644 (file)
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 #ifndef __ASM_SH_SH7763RDP_H
 #define __ASM_SH_SH7763RDP_H
 
@@ -6,11 +7,6 @@
  *
  * Copyright (C) 2008 Renesas Solutions
  * Copyright (C) 2008 Nobuhiro Iwamatsu <iwamatsu.nobuhiro@renesas.com>
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
  */
 #include <asm/addrspace.h>
 
index 1dbfdf701c9de0e16fc1b318f87e5bb414954c02..a773a763843aaa3378e5768e6d3bef36135dd4ad 100644 (file)
@@ -1,11 +1,8 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
  * include/asm-sh/dreamcast/dma.h
  *
  * Copyright (C) 2003 Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #ifndef __ASM_SH_DREAMCAST_DMA_H
 #define __ASM_SH_DREAMCAST_DMA_H
index 0314d975e62690f32c9ec50f9f2c7a15ee00849c..c037c1ec63a92816e218bc04ded91e3cfa3e63a8 100644 (file)
@@ -1,12 +1,9 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
  * include/asm-sh/dreamcast/pci.h
  *
  * Copyright (C) 2001, 2002  M. R. Brown
  * Copyright (C) 2002, 2003  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #ifndef __ASM_SH_DREAMCAST_PCI_H
 #define __ASM_SH_DREAMCAST_PCI_H
index 59effd1ed3e138de548efb2ce38a56a60b691ffb..ed69ce7f20301241831117de187dbd40d37641f1 100644 (file)
@@ -1,4 +1,6 @@
-/* include/asm-sh/dreamcast/sysasic.h
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * include/asm-sh/dreamcast/sysasic.h
  *
  * Definitions for the Dreamcast System ASIC and related peripherals.
  *
@@ -6,9 +8,6 @@
  * Copyright (C) 2003 Paul Mundt <lethal@linux-sh.org>
  *
  * This file is part of the LinuxDC project (www.linuxdc.org)
- *
- * Released under the terms of the GNU GPL v2.0.
- *
  */
 #ifndef __ASM_SH_DREAMCAST_SYSASIC_H
 #define __ASM_SH_DREAMCAST_SYSASIC_H
index cc737b807334c51d33362569fec7ab8dbd411f43..2d685cc2d54ced2099ac33da4c6f5dd25427b152 100644 (file)
@@ -1,3 +1,4 @@
+LIST "SPDX-License-Identifier: GPL-2.0"
 LIST "partner-jet-setup.txt"
 LIST "(C) Copyright 2009 Renesas Solutions Corp"
 LIST "Kuninori Morimoto <morimoto.kuninori@renesas.com>"
index 3a65503714eee8e9db44d659c22dd5c2d36d226e..a67b1926be222eefc36c95c0540ef2d9b101c79f 100644 (file)
@@ -1,3 +1,4 @@
+LIST "SPDX-License-Identifier: GPL-2.0"
 LIST "partner-jet-setup.txt - 20090729 Magnus Damm"
 LIST "set up enough of the kfr2r09 hardware to boot the kernel"
 
index eabd0538de44137dc445e70fb4025a8ebbe6629b..82226d40faf52838273a64c2f6ecccbd07084ad9 100644 (file)
@@ -1,12 +1,8 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
  * Copyright (C) 2008 Renesas Solutions Corp.
  *
  * Hitachi UL SolutionEngine 7721 Support.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
  */
 
 #ifndef __ASM_SH_SE7721_H
index 637e7ac753f84c8187d7ef1800d673cd3050f071..efb761f9f6e0e807a8c20fd5a1601cdc0c474fa7 100644 (file)
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 #ifndef __ASM_SH_SE7722_H
 #define __ASM_SH_SE7722_H
 
@@ -7,11 +8,6 @@
  * Copyright (C) 2007  Nobuhiro Iwamatsu
  *
  * Hitachi UL SolutionEngine 7722 Support.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
  */
 #include <linux/sh_intc.h>
 #include <asm/addrspace.h>
index be842dd1ca0281f15213b9c841720a1b8108215f..1fe28820dfa95373c42b46ac29e9dfc277c0be44 100644 (file)
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 #ifndef __ASM_SH_SE7724_H
 #define __ASM_SH_SE7724_H
 
  *
  * Based on se7722.h
  * Copyright (C) 2007  Nobuhiro Iwamatsu
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
  */
 #include <linux/sh_intc.h>
 #include <asm/addrspace.h>
index bde357cf81bd19514c20ffc4144974dc88852b12..24f0ac82f8b33052dbcbd90ded1bdfaf0d4441dc 100644 (file)
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 #ifndef __ASM_SH_SE7780_H
 #define __ASM_SH_SE7780_H
 
@@ -7,10 +8,6 @@
  * Copyright (C) 2006,2007  Nobuhiro Iwamatsu
  *
  * Hitachi UL SolutionEngine 7780 Support.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/sh_intc.h>
 #include <asm/addrspace.h>
index a55e317c1ef2e8ca89a9f3d456e463edd4aa0a47..dcb93543f55d9372f7b24452e49805b24b73d50f 100644 (file)
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
 # UAPI Header export list
 include include/uapi/asm-generic/Kbuild.asm
 
index 552df83f1a49627ddd1d49e1ba982c743a5bfefe..1170dd2fb99892a29bef0ac602a4d0d597a51cf9 100644 (file)
@@ -1 +1,2 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 #include <asm-generic/setup.h>
index b9e79bc580dd6cf47ae1c6a939eb8c67e6f5f7e5..f83795fdc0da2f35816f23e689ba690c9ecdce3c 100644 (file)
@@ -1 +1,2 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 #include <asm-generic/types.h>
index fca9b1e78a63bcffa3969a11422b8c3c84264b0f..6fb34410d630a5b0bf473bfe6a64e5b43cd71ce2 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/kernel/cpu/clock.c - SuperH clock framework
  *
@@ -9,10 +10,6 @@
  *     Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
  *
  *  Modified for omap shared clock framework by Tony Lindgren <tony@atomide.com>
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/kernel.h>
 #include <linux/init.h>
index c4f01c5c87362e2f0bf3dc2ce1ec0867ce56c9a9..ce7291e12a30c0492bf695719c70ea5bc473f7a3 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/kernel/cpu/init.c
  *
@@ -5,10 +6,6 @@
  *
  * Copyright (C) 2002 - 2009  Paul Mundt
  * Copyright (C) 2003  Richard Curnow
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
index 3f8e79402d7d79a38cc2a29bf10cb0bb23f1853b..8b91cb96411b7332bc9893ed55569565ce015ab7 100644 (file)
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
 #
 # Makefile for the Linux/SuperH CPU-specific IRQ handlers.
 #
index 9e056a3a0c73f98ad26917f810c2538c9fb30492..744f903b4df359b8efe63671897a2f769e5b91d8 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/kernel/cpu/irq/intc-sh5.c
  *
@@ -9,10 +10,6 @@
  * Per-interrupt selective. IRLM=0 (Fixed priority) is not
  * supported being useless without a cascaded interrupt
  * controller.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/interrupt.h>
index 5de6dff5c21b5b5ddcc9b4b713c85ce2d2e35e41..d41bce71f211fd0adb5ade1c60546bbac2bc795d 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Interrupt handling for IPR-based IRQ.
  *
  *     On-chip supporting modules for SH7709/SH7709A/SH7729.
  *     Hitachi SolutionEngine external I/O:
  *             MS7709SE01, MS7709ASE01, and MS7750SE01
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/interrupt.h>
index d766564ef7c2da5ac743197116666fa27e3eb9f4..062056ede88de4a7fb336601c5e802f4a1982b4c 100644 (file)
@@ -1,16 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * SH Pin Function Control Initialization
  *
  * Copyright (C) 2012  Renesas Solutions Corp.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 #include <linux/init.h>
index 904c4283d923f0682c1c54892febd49c1dc700c9..214c3a5b184ace7cf3836c23881178f55d5842d3 100644 (file)
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
 #
 # Makefile for the Linux/SuperH SH-2 backends.
 #
index e80252ae5bca7437b43957dce13d3f8dba5b5ed0..d66d194c7731b961e6f18f490405b30ffc0f371e 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/kernel/cpu/sh2/clock-sh7619.c
  *
@@ -7,10 +8,6 @@
  *
  * Based on clock-sh4.c
  *  Copyright (C) 2005  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
index 1ee0a6e774c6231cbefc8cc88322fd52f72bc488..0a1c2bf216bc03dbe04ad315ae8923557df58ac4 100644 (file)
@@ -1,14 +1,11 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
  * arch/sh/kernel/cpu/sh2/entry.S
  *
  * The SH-2 exception entry
  *
  * Copyright (C) 2005-2008 Yoshinori Sato
  * Copyright (C) 2005  AXE,Inc.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 
 #include <linux/linkage.h>
index 85b0bf81fc1d80c304ac01178f80cc68b8082d50..dd0cc887a3ca2c2f686a805a4d25d67f6bae4703 100644 (file)
@@ -1,13 +1,10 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
  * arch/sh/kernel/cpu/sh2/ex.S
  *
  * The SH-2 exception vector table
  *
  * Copyright (C) 2005 Yoshinori Sato
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 
 #include <linux/linkage.h>
index a5bd03642678906a21e1d5fc8f853b4264bfd2e8..d342ea08843f6a6262ce0b6838451ce97b6ce520 100644 (file)
@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/kernel/cpu/sh2/probe.c
  *
  * CPU Subtype Probing for SH-2.
  *
  * Copyright (C) 2002 Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/of_fdt.h>
index d08db08dec38127563175f24b2ee8bd384165446..f5b6841ef7e1cd3783918e216b3c4b7471024157 100644 (file)
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * SH7619 Setup
  *
  *  Copyright (C) 2006  Yoshinori Sato
  *  Copyright (C) 2009  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/platform_device.h>
 #include <linux/init.h>
index 6ccd7e4dc00867e2c953af932da3f0d28fd99d8a..ae44dc24c4557b972488bd334b77cfc3e42c0bf6 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * SMP support for J2 processor
  *
  * Copyright (C) 2015-2016 Smart Energy Instruments, Inc.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 
 #include <linux/smp.h>
index 532a36c72322706eeb9f19fca91d1284c07541bc..5a5daaafb27a493452193bc9e5f29c4246143a7c 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/kernel/cpu/sh2a/clock-sh7201.c
  *
@@ -7,10 +8,6 @@
  *
  * Based on clock-sh4.c
  *  Copyright (C) 2005  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
index 529f719b6e33541e078e97d49b7637cef3219678..c62053945664415df964b90a0968ad105c933dcd 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/kernel/cpu/sh2a/clock-sh7203.c
  *
  *
  * Based on clock-sh4.c
  *  Copyright (C) 2005  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
index 1777898346784fe76f1551d6f14e29650ac609b8..d286d7b918d5e384455f3ba2c0367d484a55c019 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/kernel/cpu/sh2a/clock-sh7206.c
  *
@@ -7,10 +8,6 @@
  *
  * Based on clock-sh4.c
  *  Copyright (C) 2005  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
index 7e06e39b095864d1d76b3e743153bea5bf789829..d9acc1ed79817c125ef1dceae8c36dbef9c3709a 100644 (file)
@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/kernel/cpu/sh2a/clock-sh7264.c
  *
  * SH7264 clock framework support
  *
  * Copyright (C) 2012  Phil Edworthy
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
index 663a97bed554ec5ccb6e1d1d7f205dc2e9dbba9a..c17ab0d7653888a519d01b61b55c50a82f7f6185 100644 (file)
@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/kernel/cpu/sh2a/clock-sh7269.c
  *
  * SH7269 clock framework support
  *
  * Copyright (C) 2012  Phil Edworthy
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
index da77a8ef4696e2dacb7e4bbf9bb4ccac8139c7a1..9f11fc8b505251a79bb5cc238faf328609e45ff3 100644 (file)
@@ -1,14 +1,11 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
  * arch/sh/kernel/cpu/sh2a/entry.S
  *
  * The SH-2A exception entry
  *
  * Copyright (C) 2008 Yoshinori Sato
  * Based on arch/sh/kernel/cpu/sh2/entry.S
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 
 #include <linux/linkage.h>
index 4568066700cfe4eb0e14e582d7dff6bf1b194e25..ed91996287c7d9e5c0c0030cc803dc67653e37f9 100644 (file)
@@ -1,13 +1,10 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
  * arch/sh/kernel/cpu/sh2a/ex.S
  *
  * The SH-2A exception vector table
  *
  * Copyright (C) 2008 Yoshinori Sato
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 
 #include <linux/linkage.h>
index 352f894bece10aee706f2a75ae93fc9ae2641300..74b48db86dd71350909ce40afcaee187e89ee22f 100644 (file)
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Save/restore floating point context for signal handlers.
  *
  * Copyright (C) 1999, 2000  Kaz Kojima & Niibe Yutaka
  *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
  * FIXME! These routines can be optimized in big endian case.
  */
 #include <linux/sched/signal.h>
index 72aa61c81e485389107755bdbf5fd8707d6f4cff..c509081d90b9affe1da01b0004a6a3daf9c7e0f9 100644 (file)
@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/kernel/cpu/sh2a/opcode_helper.c
  *
  * Helper for the SH-2A 32-bit opcodes.
  *
  *  Copyright (C) 2007  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/kernel.h>
 
index eef17dcc3a419a8cbca32526114ff274468980ae..a6777e6fc8cdc20b5a397b98a0df9dc444b656c1 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * SH7203 Pinmux
  *
  *  Copyright (C) 2008  Magnus Damm
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 
 #include <linux/bug.h>
index 569decbd6d9350d07a76c2b28175f180ce5ece0e..7a103e16cf01b061dcd67f83fe0f458397e01ade 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * SH7264 Pinmux
  *
  *  Copyright (C) 2012  Renesas Electronics Europe Ltd
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 
 #include <linux/bug.h>
index 4c17fb6970b1574e38f566e5e7baea5fc37b9b06..4da432ef1b40a9772cd6c2de2aee177aea102012 100644 (file)
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * SH7269 Pinmux
  *
  * Copyright (C) 2012  Renesas Electronics Europe Ltd
  * Copyright (C) 2012  Phil Edworthy
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 
 #include <linux/bug.h>
index 3f87971082f117b7d5fb1e5bbef048c67603d6e0..c66a3bc882bf9a6694b59bde143136d2590d8e25 100644 (file)
@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/kernel/cpu/sh2a/probe.c
  *
  * CPU Subtype Probing for SH-2A.
  *
  * Copyright (C) 2004 - 2007  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <asm/processor.h>
index 060fdd369f098ce41ab631a05c6f817797e84826..52350ad0b0a26a23e7158485bc6b63f0f6d93da6 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Renesas MX-G (R8A03022BG) Setup
  *
  *  Copyright (C) 2008, 2009  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/platform_device.h>
 #include <linux/init.h>
index c1301f68d3cd08e0277dbe3bae90209bb7722b3d..b51ed761ae087977e4bb4d3721636d830f67542f 100644 (file)
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  *  SH7201 setup
  *
  *  Copyright (C) 2008  Peter Griffin pgriffin@mpc-data.co.uk
  *  Copyright (C) 2009  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/platform_device.h>
 #include <linux/init.h>
index 32ec732e28e5e9760868440f59851361acd4ad6c..89b3e49fc2503673e5d5cf81ca82c4c6a1a9dcd2 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * SH7203 and SH7263 Setup
  *
  *  Copyright (C) 2007 - 2009  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/platform_device.h>
 #include <linux/init.h>
index 8d8d354851ce375f8a09bf6b81994b90b0cc6d24..36ff3a3139dabe1e98be6d60e32b0e56a1623d14 100644 (file)
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * SH7206 Setup
  *
  *  Copyright (C) 2006  Yoshinori Sato
  *  Copyright (C) 2009  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/platform_device.h>
 #include <linux/init.h>
index ab71eab690fd4f3e8ac9f9c5262d6b7bb8ef6ca9..d199618d877c070b2a4176d32027ea96a12f330a 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * SH7264 Setup
  *
  * Copyright (C) 2012  Renesas Electronics Europe Ltd
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/platform_device.h>
 #include <linux/init.h>
index c7e81b20967ca73fec526096f794470ee1fa6c49..9095c960b4558d90c9037c1a5849412d531c9519 100644 (file)
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * SH7269 Setup
  *
  * Copyright (C) 2012  Renesas Electronics Europe Ltd
  * Copyright (C) 2012  Phil Edworthy
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/platform_device.h>
 #include <linux/init.h>
index 90faa44ca94d191db1c1e2f8813956685cc6a53d..d7765728cadf5a5f494a1fddabc0e1ec229ab3c1 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/kernel/cpu/sh3/clock-sh3.c
  *
  *  Copyright (C) 2000  Philipp Rumpf <prumpf@tux.org>
  *  Copyright (C) 2002, 2003, 2004  Paul Mundt
  *  Copyright (C) 2002  M. R. Brown  <mrbrown@linux-sh.org>
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
index a8da4a9986b3aee646d619d8c5dce551deee05b9..4947114af0901bdc588282958814e21b8abfbebe 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/kernel/cpu/sh3/clock-sh7705.c
  *
  *  Copyright (C) 2000  Philipp Rumpf <prumpf@tux.org>
  *  Copyright (C) 2002, 2003, 2004  Paul Mundt
  *  Copyright (C) 2002  M. R. Brown  <mrbrown@linux-sh.org>
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
index a4088e5b2203209e02d5dda307a2eef0b7aa1839..17855022c118f50936b024e49073cd3aa64ebe14 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/kernel/cpu/sh3/clock-sh7706.c
  *
@@ -7,10 +8,6 @@
  *
  * Based on arch/sh/kernel/cpu/sh3/clock-sh7709.c
  *  Copyright (C) 2005  Andriy Skulysh
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
index 54a6d4bcc0db770a8640a72bbc093ca4847ec0ce..54701bbf7caae7dc15fd82b76e8927ca9c7b2991 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/kernel/cpu/sh3/clock-sh7709.c
  *
@@ -7,10 +8,6 @@
  *
  * Based on arch/sh/kernel/cpu/sh3/clock-sh7705.c
  *  Copyright (C) 2005  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
index ce601b2e39769aebae2a9e6f4963368fe9aad116..e60d0bc19cbe96d2a5df902e0274b8acdb3d09bb 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/kernel/cpu/sh3/clock-sh7710.c
  *
  *  Copyright (C) 2000  Philipp Rumpf <prumpf@tux.org>
  *  Copyright (C) 2002, 2003, 2004  Paul Mundt
  *  Copyright (C) 2002  M. R. Brown  <mrbrown@linux-sh.org>
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
index 21438a9a1ae1c5654d96500c78a3daa4cbe54f47..5af553f38d3a594d309cf2478df3a15fec14579e 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/kernel/cpu/sh3/clock-sh7712.c
  *
@@ -7,10 +8,6 @@
  *
  * Based on arch/sh/kernel/cpu/sh3/clock-sh3.c
  *  Copyright (C) 2005  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
index 262db6ec067ba0716b3511834ffd7f41eab2fde6..25eb8090541604cadc83bb8db671ee13219c5778 100644 (file)
@@ -1,12 +1,9 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
  * arch/sh/kernel/cpu/sh3/entry.S
  *
  *  Copyright (C) 1999, 2000, 2002  Niibe Yutaka
  *  Copyright (C) 2003 - 2012  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/sys.h>
 #include <linux/errno.h>
index 99b4d020179a5a0c17b52e9927cbda49d225ed38..ee2113f4215cb3ed3a9c8bbb506da0fc554e3ad2 100644 (file)
@@ -1,14 +1,11 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
  *  arch/sh/kernel/cpu/sh3/ex.S
  *
  *  The SH-3 and SH-4 exception vector table.
-
+ *
  *  Copyright (C) 1999, 2000, 2002  Niibe Yutaka
  *  Copyright (C) 2003 - 2008  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/linkage.h>
 
index 26e90a66ebb71de8e6874b23f069d10c1a690f47..34015e608ee93180cc432c6c3dca736023565d11 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * SH7720 Pinmux
  *
  *  Copyright (C) 2008  Magnus Damm
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 
 #include <linux/bug.h>
index 426e1e1dcedc7c08213cad2b971366516fff6771..5e7ad591ab16510ee30c7b35ba9a2d8559557048 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/kernel/cpu/sh3/probe.c
  *
@@ -5,10 +6,6 @@
  *
  * Copyright (C) 1999, 2000  Niibe Yutaka
  * Copyright (C) 2002  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 
 #include <linux/init.h>
index 53be70b9811615b70d5a56974965bc2e9d0398cc..8058c01cf09dfd187d8b29ed48eb241cd6739836 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Shared SH3 Setup code
  *
  *  Copyright (C) 2008  Magnus Damm
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 
 #include <linux/init.h>
index f6e392e0d27eb67ee3c118d382df528029d82dc9..e19d1ce7b6ad1f09730f0a676b55c9c8c6e76ba6 100644 (file)
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * SH7705 Setup
  *
  *  Copyright (C) 2006 - 2009  Paul Mundt
  *  Copyright (C) 2007  Nobuhiro Iwamatsu
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/platform_device.h>
 #include <linux/init.h>
index 59a88611df55ac8f8b8b03dc347cf00081b4f756..5c5144bee6bcc7ced870ccd785042b7c534eb224 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * SH3 Setup code for SH7706, SH7707, SH7708, SH7709
  *
@@ -7,10 +8,6 @@
  * Based on setup-sh7709.c
  *
  *  Copyright (C) 2006  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/io.h>
index ea52410b430d2e1597e539144a2e89dc6459f807..4776e2495738fde54720a9cbd5508672f727f7fa 100644 (file)
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * SH3 Setup code for SH7710, SH7712
  *
  *  Copyright (C) 2006 - 2009  Paul Mundt
  *  Copyright (C) 2007  Nobuhiro Iwamatsu
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/platform_device.h>
 #include <linux/init.h>
index bf34b4e2e9efeed062b07e4b1197b08f3ac3ae6a..1d4c34e7b7db98ced3eafe368c3ff87dc1689ede 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Setup code for SH7720, SH7721.
  *
@@ -8,10 +9,6 @@
  *
  *  Copyright (C) 2006  Paul Mundt
  *  Copyright (C) 2006  Jamie Lenehan
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/platform_device.h>
 #include <linux/init.h>
index 01145426a2b8620e3e0e18063d09c96841819c23..dc111c4ccf219982821b307ea4e4b7cc24282b25 100644 (file)
@@ -1,11 +1,8 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
  * arch/sh/kernel/cpu/sh3/swsusp.S
  *
  * Copyright (C) 2009 Magnus Damm
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/sys.h>
 #include <linux/errno.h>
index 4b5bab5f875f653966f0ba55007ff072c7a0ae24..c1cdef763cb256f92e4d09cc0ac1ce40fb612ac0 100644 (file)
@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/kernel/cpu/sh4/clock-sh4-202.c
  *
  * Additional SH4-202 support for the clock framework
  *
  *  Copyright (C) 2005  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
index 99e5ec8b483df24fc854700fc77386e0c3694912..ee3c5537a9d81a0488bc4944d0c25287f997b07e 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/kernel/cpu/sh4/clock-sh4.c
  *
  *  Copyright (C) 2000  Philipp Rumpf <prumpf@tux.org>
  *  Copyright (C) 2002, 2003, 2004  Paul Mundt
  *  Copyright (C) 2002  M. R. Brown  <mrbrown@linux-sh.org>
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
index 95fd2dcb83da3bb22d3a0e2ccb42b20858fafd2c..1ff56e5ba990ff90056780733651e146bc872899 100644 (file)
@@ -1,10 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Save/restore floating point context for signal handlers.
  *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
  * Copyright (C) 1999, 2000  Kaz Kojima & Niibe Yutaka
  * Copyright (C) 2006  ST Microelectronics Ltd. (denorm support)
  *
index fa4f724b295a1c6814902f4088c81f9fd6201ae3..db5847bb7330691bbdcf2f5f720d0e6628bcc6a1 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Performance events support for SH7750-style performance counters
  *
  *  Copyright (C) 2009  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/kernel.h>
 #include <linux/init.h>
index a521bcf506956cd6022846a37680061d212a0548..ef4dd6295263dd097ac13365bddd95bc71d64f07 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/kernel/cpu/sh4/probe.c
  *
@@ -5,10 +6,6 @@
  *
  * Copyright (C) 2001 - 2007  Paul Mundt
  * Copyright (C) 2003  Richard Curnow
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/io.h>
index 2623f820d510bde38a09bc1c7614cb64834885f9..a40ef35d101a9cb232ef69990aa1a1a329371e3b 100644 (file)
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * SH4-202 Setup
  *
  *  Copyright (C) 2006  Paul Mundt
  *  Copyright (C) 2009  Magnus Damm
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/platform_device.h>
 #include <linux/init.h>
index 57d30689204d03b96cb56b6dcfb9fc1c1db37881..b37bda66a532e8ddff486941114793db29bb62fa 100644 (file)
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * SH7091/SH7750/SH7750S/SH7750R/SH7751/SH7751R Setup
  *
  *  Copyright (C) 2006  Paul Mundt
  *  Copyright (C) 2006  Jamie Lenehan
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/platform_device.h>
 #include <linux/init.h>
index e51fe1734e1368e8baacf4459652a2dc4425be99..86845da859979da93e64c6e3da51b43f91fd7390 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * SH7760 Setup
  *
  *  Copyright (C) 2006  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/platform_device.h>
 #include <linux/init.h>
index 4ca78ed71ad2c8ff33707fb8a472d55b553de36e..934ff84844fa0bb8819d89fb7a13cf6ee00aa9a3 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/kernel/cpu/sh4/sq.c
  *
@@ -5,10 +6,6 @@
  *
  * Copyright (C) 2001 - 2006  Paul Mundt
  * Copyright (C) 2001, 2002  M. R. Brown
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/cpu.h>
index a907ee2388bfce508b98d5b6d2c7a714606177de..32cb5d1fd3b32f95fdab9e835e53f846b124f847 100644 (file)
@@ -1,22 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/kernel/cpu/sh4a/clock-sh7343.c
  *
  * SH7343 clock framework support
  *
  * Copyright (C) 2009 Magnus Damm
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
index ac9854179dee88f0642234063b911eb3d7b47e67..aa3444b41e72a2afe89815fa9fda8a1bf4806a97 100644 (file)
@@ -1,22 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/kernel/cpu/sh4a/clock-sh7366.c
  *
  * SH7366 clock framework support
  *
  * Copyright (C) 2009 Magnus Damm
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
index d85091ec4b01ad8b5b1fe6ad7cc4cdb9c5480b1a..38b057703eaadaaeead0f76fbdaddf8cecca8206 100644 (file)
@@ -1,22 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/kernel/cpu/sh4a/clock-sh7722.c
  *
  * SH7722 clock framework support
  *
  * Copyright (C) 2009 Magnus Damm
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
index af01664f7b4c6fee101ab05704bc394cf9591059..9dc3a987d7cf8789df780bd304b84e7056cb0d1e 100644 (file)
@@ -1,22 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/kernel/cpu/sh4a/clock-sh7723.c
  *
  * SH7723 clock framework support
  *
  * Copyright (C) 2009 Magnus Damm
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
index 3194336a35990db2083bda4f3947d068542868a6..2a1f0d847a2efb09b6fd18b56f2c9fb5117dd96e 100644 (file)
@@ -1,22 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/kernel/cpu/sh4a/clock-sh7724.c
  *
  * SH7724 clock framework support
  *
  * Copyright (C) 2009 Magnus Damm
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
index 354dcac5e4cd9938a20f8b4c1ceea8d74c592b49..c81ee60eddb8e776a29be54dc0dc4799bb123a90 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/kernel/cpu/sh4a/clock-sh7734.c
  *
@@ -5,10 +6,6 @@
  *
  * Copyright (C) 2011, 2012 Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
  * Copyright (C) 2011, 2012 Renesas Solutions Corp.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 
 #include <linux/init.h>
index b10af2ae9f350908e78b25b522f714249578307c..9acb72210fed48e0f28e7abaabcf51e981960151 100644 (file)
@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/kernel/cpu/sh4/clock-sh7757.c
  *
  * SH7757 support for the clock framework
  *
  *  Copyright (C) 2009-2010  Renesas Solutions Corp.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
index 7707e35aea46230b6f5c3a8e86528cbc36d8c4ce..aaff4b96812c6a5df07248b21c9e9256c3dd3a76 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/kernel/cpu/sh4a/clock-sh7763.c
  *
@@ -5,10 +6,6 @@
  *
  *  Copyright (C) 2005  Paul Mundt
  *  Copyright (C) 2007  Yoshihiro Shimoda
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
index 5d36f334bb0a74d51ddd00f36ed3cc82e95a2fbb..f356dfcd17b751945658a8e4216b07ec23e0dc62 100644 (file)
@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/kernel/cpu/sh4a/clock-sh7770.c
  *
  * SH7770 support for the clock framework
  *
  *  Copyright (C) 2005  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
index 793dae42a2f8490c536ecfd214255e920fa95adc..fc0a3efb53d5e0f924abafbd95362410fa826c4c 100644 (file)
@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/kernel/cpu/sh4a/clock-sh7780.c
  *
  * SH7780 support for the clock framework
  *
  *  Copyright (C) 2005  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
index 1aafd5496752f7f1132835b6a54b07a291e1a122..fca351378bbce69c0a545f43eafbfc4e50c4f589 100644 (file)
@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/kernel/cpu/sh4a/clock-sh7785.c
  *
  * SH7785 support for the clock framework
  *
  *  Copyright (C) 2007 - 2010  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
index ac3dcfe5d303d1341c37aa81441d40a96a81ac09..f23862df3e8fb91461ee5def0678fdf4d82f3cb0 100644 (file)
@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/kernel/cpu/sh4a/clock-sh7786.c
  *
  * SH7786 support for the clock framework
  *
  *  Copyright (C) 2010  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
index b1bdbc3cbc219af8df4a0d33d3e8a15616667532..6c7b6ab6cab5a69f05440f6168efd8d46dda634b 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/kernel/cpu/sh4/clock-shx3.c
  *
@@ -6,10 +7,6 @@
  *  Copyright (C) 2006-2007  Renesas Technology Corp.
  *  Copyright (C) 2006-2007  Renesas Solutions Corp.
  *  Copyright (C) 2006-2010  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
index 78c971486b4e9520b2b9ad10b1c26c04ef5c3361..eea87d25efbb3fd9c09066a34aeac45b49ce7968 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Shared support for SH-X3 interrupt controllers.
  *
  *  Copyright (C) 2009 - 2010  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/irq.h>
 #include <linux/io.h>
index 84a2c396ceee06ed54bef271ff7eae4f29e84c6b..3beb8fed3d289dc5ffe73d68853938fd5418094a 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Performance events support for SH-4A performance counters
  *
  *  Copyright (C) 2009, 2010  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/kernel.h>
 #include <linux/init.h>
index 99c637d5bf7a0163dc2b9e16ba9358ad9028a5e1..b67abc0637a4872b57d329df19919cd9395f6306 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * SH7723 Pinmux
  *
  *  Copyright (C) 2008  Magnus Damm
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 
 #include <linux/bug.h>
index 63be4749e34160c9b6164772248e5b43418932fd..b43c3259060bbecc3e33aef58fbcb08d07ae4f3b 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * SH7724 Pinmux
  *
@@ -7,10 +8,6 @@
  *
  * Based on SH7723 Pinmux
  *  Copyright (C) 2008  Magnus Damm
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 
 #include <linux/bug.h>
index ea2db632a764fb4b6a1a39a72d7b2560b3a75bbc..46256b19619a79ab66d1590ecdc1b681596e07d1 100644 (file)
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * SH7734 processor support - PFC hardware block
  *
  * Copyright (C) 2012  Renesas Solutions Corp.
  * Copyright (C) 2012  Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/bug.h>
 #include <linux/init.h>
index 567745d44221451daf6b5b71fc9de132f28da1cf..c92f304cb4bad17ebcdd9bb5b56a56f9e74ab062 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * SH7757 (B0 step) Pinmux
  *
@@ -7,10 +8,6 @@
  *
  * Based on SH7723 Pinmux
  *  Copyright (C) 2008  Magnus Damm
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 
 #include <linux/bug.h>
index e336ab8b5125a42d54dc0df91d0dea2ae5b5663e..f329de6e758a4fb9c053b6245d3712022d9ef53f 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * SH7785 Pinmux
  *
  *  Copyright (C) 2008  Magnus Damm
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 
 #include <linux/bug.h>
index 9a459556a2f78ad987eb270794653201c1e1aa6f..47e8639f3e71b123a0c256619ad9f3aa30a8a5a3 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * SH7786 Pinmux
  *
@@ -7,10 +8,6 @@
  *  Based on SH7785 pinmux
  *
  *  Copyright (C) 2008  Magnus Damm
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 
 #include <linux/bug.h>
index 444bf25c60fa215a4be3981663583116ed3a5b0a..6c02f6256467544c5bec06bfa191fa40efb64d57 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * SH-X3 prototype CPU pinmux
  *
  * Copyright (C) 2010  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/bug.h>
 #include <linux/init.h>
index 5788073a7c306185a10578f7a1428ed7cd33b604..a15e25690b5f96a3a78e3dead849228e5eafac77 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * SH7343 Setup
  *
  *  Copyright (C) 2006  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/platform_device.h>
 #include <linux/init.h>
index 646918713d9afc3e35a2a0df6edfee2c95830253..7bd2776441ba0981701dbb2b97122fa9ed32ff93 100644 (file)
@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * SH7366 Setup
  *
  *  Copyright (C) 2008 Renesas Solutions
  *
  * Based on linux/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/platform_device.h>
 #include <linux/init.h>
index 6b3a26e61abbddcacb01b13370d6c2e077ca40b3..1ce65f88f060e7350041dba893388a3d8eef05e2 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * SH7722 Setup
  *
  *  Copyright (C) 2006 - 2008  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/mm.h>
index 1c1b3c46983104f5e8bb65a98f0953a1437c636d..edb6499506625a74e2b52b7efc233653d08047d6 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * SH7723 Setup
  *
  *  Copyright (C) 2008  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/platform_device.h>
 #include <linux/init.h>
index c20258b18775727f76637dc6de36bea44ddfebae..3e9825031d3d76801a73f26b7675740743f2561d 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * SH7724 Setup
  *
@@ -7,10 +8,6 @@
  *
  * Based on SH7723 Setup
  * Copyright (C) 2008  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/platform_device.h>
 #include <linux/init.h>
index 8c0c9da6b5b32899cb48597867a0b6c2bbe865da..06a91569697a7c697a2a6f4d92b6bf749690efb9 100644 (file)
@@ -1,14 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/kernel/cpu/sh4a/setup-sh7734.c
-
+ *
  * SH7734 Setup
  *
  * Copyright (C) 2011,2012 Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
  * Copyright (C) 2011,2012 Renesas Solutions Corp.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 
 #include <linux/platform_device.h>
index a46a19b49e083566cd83f852818916d2326eed8b..2501ce656511b061bbe843831e31a7d77a955641 100644 (file)
@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * SH7757 Setup
  *
  * Copyright (C) 2009, 2011  Renesas Solutions Corp.
  *
  *  based on setup-sh7785.c : Copyright (C) 2007  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/platform_device.h>
 #include <linux/init.h>
index 40e6cda914d3af4d4098fd769e2e15f24294802f..419c5efe4a17fee24308ff77df5707bedeff6fe3 100644 (file)
@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * SH7763 Setup
  *
  *  Copyright (C) 2006  Paul Mundt
  *  Copyright (C) 2007  Yoshihiro Shimoda
  *  Copyright (C) 2008, 2009  Nobuhiro Iwamatsu
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/platform_device.h>
 #include <linux/init.h>
index 82e3bdf2e1b6bc12f985c0d6ac5ed3a0b798d066..5fb4cf9b58c691110ad41bff5dcc55f53e6e00e1 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * SH7770 Setup
  *
  *  Copyright (C) 2006 - 2008  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/platform_device.h>
 #include <linux/init.h>
index d90ff67a46331f0e72f2c2d93632b2f6677b5962..ab7d6b715865b54c07052660dfb960b4455bf832 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * SH7780 Setup
  *
  *  Copyright (C) 2006  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/platform_device.h>
 #include <linux/init.h>
index b0d6f82f2d71bba804b7712b6b6696b2509d25cc..a438da47285d6ceea28a5ff3c6609e2c93eb3e98 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * SH7785 Setup
  *
  *  Copyright (C) 2007  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/platform_device.h>
 #include <linux/init.h>
index 17aac38a6e904a1b91ffebaa3f35ef88104c4a8f..d894165a0ef6fb8ed16a94bd437501381e4b5ae9 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * SH7786 Setup
  *
@@ -8,10 +9,6 @@
  * Based on SH7785 Setup
  *
  *  Copyright (C) 2007  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/platform_device.h>
 #include <linux/init.h>
index ee14d92d840fb58ce1e507842fee835910853b8d..14aa4552bc45b5f75753f8aa2445f7795cd92467 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * SH-X3 Prototype Setup
  *
  *  Copyright (C) 2007 - 2010  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/platform_device.h>
 #include <linux/init.h>
index 0d3637c494bfe174854a3783702d60c81902cbdb..f8a2bec0f260b373b7e3e6cd3529a34635aa1b11 100644 (file)
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * SH-X3 SMP
  *
  *  Copyright (C) 2007 - 2010  Paul Mundt
  *  Copyright (C) 2007  Magnus Damm
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
index efb2745bcb36df2ffd68077d6054b727b5af97c9..25eacd9c47d1b8a92d69cedf51d4425d8d8bf6b9 100644 (file)
@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/kernel/cpu/sh4a/ubc.c
  *
  * On-chip UBC support for SH-4A CPUs.
  *
  * Copyright (C) 2009 - 2010  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/err.h>
index c48b93d4c0815b1129d27931f40191b9930b6e59..43763c26a752bbb4e43c6482acc8eba2fa9fdd88 100644 (file)
@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/kernel/cpu/sh5/clock-sh5.c
  *
  * SH-5 support for the clock framework
  *
  *  Copyright (C) 2008  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
index 0c8d0377d40bdf005a1d90e9929b9fe26011b0a9..de68ffdfffbf535260132ed383b8f6b1d115f45c 100644 (file)
@@ -1,13 +1,10 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
  * arch/sh/kernel/cpu/sh5/entry.S
  *
  * Copyright (C) 2000, 2001  Paolo Alberelli
  * Copyright (C) 2004 - 2008  Paul Mundt
  * Copyright (C) 2003, 2004  Richard Curnow
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/errno.h>
 #include <linux/init.h>
index 9f8713aa7184f3b4da3ad9ea46f8a1d629362eaf..9218d9ed787e87d1095029b39ce0ee5dbe33d9e1 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/kernel/cpu/sh5/fpu.c
  *
@@ -7,10 +8,6 @@
  *
  * Started from SH4 version:
  *   Copyright (C) 1999, 2000  Kaz Kojima & Niibe Yutaka
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/sched.h>
 #include <linux/signal.h>
index eca427c2f2f3de6c9d7b7665ea69d831377993a8..947250188065450e36a49b5b634726ce181716d0 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/kernel/cpu/sh5/probe.c
  *
@@ -5,10 +6,6 @@
  *
  * Copyright (C) 2000, 2001  Paolo Alberelli
  * Copyright (C) 2003 - 2007  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/io.h>
index 084a9cc99175bfa0ad8861b4d163fa0f99f9825a..41c1673afc0b4301a6e4b56b4530c01411fe614d 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * SH5-101/SH5-103 CPU Setup
  *
  *  Copyright (C) 2009  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/platform_device.h>
 #include <linux/init.h>
index 45c351b0f1bab2d883a4fa421926d46bd1bc3019..d1beff755632aa8823af5d008dc6e772043114e6 100644 (file)
@@ -1,13 +1,10 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
  * arch/sh/kernel/cpu/sh5/switchto.S
  *
  * sh64 context switch
  *
  * Copyright (C) 2004  Richard Curnow
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
 */
 
        .section .text..SHmedia32,"ax"
index 3a4fed406fc615b27d48088c2f35396b788dd779..3cb0cd9cea29cb08528c82ded48cc42876163877 100644 (file)
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/kernel/cpu/sh5/unwind.c
  *
  * Copyright (C) 2004  Paul Mundt
  * Copyright (C) 2004  Richard Curnow
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/kallsyms.h>
 #include <linux/kernel.h>
index e8a5111e848abd1ac463a62492736dbe7861bf30..7581d5f03ce155b2d56cc51ad7781f0318f7d972 100644 (file)
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
 #
 # Makefile for the Linux/SuperH SH-Mobile backends.
 #
index c32e66079f7c31f932995c47337adcf48da0deea..dbd2cdec2ddb65c7cb305643f81195d947ededfa 100644 (file)
@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/kernel/cpu/shmobile/cpuidle.c
  *
  * Cpuidle support code for SuperH Mobile
  *
  *  Copyright (C) 2009 Magnus Damm
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
index fba2be5d72e934cc773ae8c370e44ff027c18bd2..ca9945f51e51d42dd00af7ffdd67b2dc63fe0f6a 100644 (file)
@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/kernel/cpu/shmobile/pm.c
  *
  * Power management support code for SuperH Mobile
  *
  *  Copyright (C) 2009 Magnus Damm
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
index e6aac65f5750495c61ae17949b65f17a29cfac10..f928c03151296cdf58b3b89e0c63aaadfc913179 100644 (file)
@@ -1,13 +1,10 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
  * arch/sh/kernel/cpu/sh4a/sleep-sh_mobile.S
  *
  * Sleep mode and Standby modes support for SuperH Mobile
  *
  *  Copyright (C) 2009 Magnus Damm
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 
 #include <linux/sys.h>
index 7a1b46fec0f46c08c540f5c6e8f99e17275669f5..ad07527e2a990aec9af2a301254f955587f7fa40 100644 (file)
@@ -1,13 +1,10 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
  * arch/sh/kernel/debugtraps.S
  *
  * Debug trap jump tables for SuperH
  *
  *  Copyright (C) 2006 - 2008  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/sys.h>
 #include <linux/linkage.h>
index 015fee58014b14cd0e8f1b88342a8184efb0fe35..defebf1a9c8af223ad6ea4ed9af2f315acbc2202 100644 (file)
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Disassemble SuperH instructions.
  *
  * Copyright (C) 1999 kaz Kojima
  * Copyright (C) 2008 Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/kernel.h>
 #include <linux/string.h>
index a0021eef956bf335b9d09e5a47f2494fc413d997..b17514619b7e1f7de0d2df82efeaf0ac3b8144e8 100644 (file)
@@ -1,9 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2004 - 2007  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/mm.h>
 #include <linux/init.h>
index b564b1eae4aee6d508a0c8696b80b4aa529d8af6..93c6c0e691ee0038e7d93a2f4896ea1cf9573f92 100644 (file)
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  *  Copyright (C) 1991, 1992  Linus Torvalds
  *  Copyright (C) 2000, 2001, 2002 Andi Kleen, SuSE Labs
  *  Copyright (C) 2009  Matt Fleming
  *  Copyright (C) 2002 - 2012  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/kallsyms.h>
 #include <linux/ftrace.h>
index bb511e2d9d68131c65e68b400ef662527069a751..9e1d26c8a0c4f168dcc463d4865d1ca670f504ce 100644 (file)
@@ -1,10 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2009 Matt Fleming <matt@console-pimps.org>
  *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
  * This is an implementation of a DWARF unwinder. Its main purpose is
  * for generating stacktrace information. Based on the DWARF 3
  * specification from http://www.dwarfstd.org.
index 28cc61216b649773045d2eb16bdd997602ac9087..d31f66e82ce516366767ef531f6ef945acbab613 100644 (file)
@@ -1,11 +1,7 @@
-/* 
+/* SPDX-License-Identifier: GPL-2.0
+ *
  *  Copyright (C) 1999, 2000, 2002  Niibe Yutaka
  *  Copyright (C) 2003 - 2008  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
  */
 
 ! NOTE:
index 4e352c3f79e6b79f1338e5a90d7f4cfa39d304c4..4adbd4ade319460674ca1d7a56053c825b883ea3 100644 (file)
@@ -1,14 +1,11 @@
-/* $Id: head.S,v 1.7 2003/09/01 17:58:19 lethal Exp $
+/* SPDX-License-Identifier: GPL-2.0
+ * $Id: head.S,v 1.7 2003/09/01 17:58:19 lethal Exp $
  *
  *  arch/sh/kernel/head.S
  *
  *  Copyright (C) 1999, 2000  Niibe Yutaka & Kaz Kojima
  *  Copyright (C) 2010  Matt Fleming
  *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
  * Head.S contains the SH exception handlers and startup code.
  */
 #include <linux/init.h>
index cca491397a2836c2ec1653c70aaec7f522b7368d..67685e1f00e1d935bf9d27b328fb3d16833f5f73 100644 (file)
@@ -1,12 +1,9 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
  * arch/sh/kernel/head_64.S
  *
  * Copyright (C) 2000, 2001  Paolo Alberelli
  * Copyright (C) 2003, 2004  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 
 #include <linux/init.h>
index d9ff3b42da7cb11a3e6d62ec39dcfc2c35ce40d2..bc96b16288c1aec920d4e1fc41417f5236ddfa3a 100644 (file)
@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/kernel/hw_breakpoint.c
  *
  * Unified kernel/user-space hardware breakpoint facility for the on-chip UBC.
  *
  * Copyright (C) 2009 - 2010  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/perf_event.h>
index be616ee0cf8799a6c7deeb058a7a92da6a8f213c..c20fc5487e051f47a71cdb337b3f6e8794315d99 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * The idle loop for all SuperH platforms.
  *
  *  Copyright (C) 2002 - 2009  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/module.h>
 #include <linux/init.h>
index 5c51b794ba2a8a7591546f79a18271d73e33e771..da22f3b32d305e6f87948023035df68b424aebc3 100644 (file)
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/kernel/io.c - Machine independent I/O functions.
  *
  * Copyright (C) 2000 - 2009  Stuart Menefy
  * Copyright (C) 2005  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/module.h>
 #include <linux/pci.h>
index 4d4e7a2a774b0b283c38e79b03a7b861ae1faea8..bacad6da4fe4f04c44584ee414a2d75ba336381e 100644 (file)
@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Trapped io support
  *
  * Copyright (C) 2008 Magnus Damm
  *
  * Intercept io operations by trapping.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/kernel.h>
 #include <linux/mm.h>
index 2e8e8b9b9cefefd7281a4cb470718d5a799602ae..ef9e2c97cbb76d8451a6ba53c9ef7265649881f9 100644 (file)
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/kernel/iomap.c
  *
  * Copyright (C) 2000  Niibe Yutaka
  * Copyright (C) 2005 - 2007 Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/module.h>
 #include <linux/io.h>
index cca14ba84a379fea07bb74ddaabb02bb062cd649..34f8cdbbcf0beeffe85f3265f20ade9bd28ea21f 100644 (file)
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/kernel/ioport.c
  *
  * Copyright (C) 2000  Niibe Yutaka
  * Copyright (C) 2005 - 2007 Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/module.h>
 #include <linux/io.h>
index e5a755be9129a1c9d497be4851ac0948fbd8a210..e09cdc4ada68c8cb2593568396d1af8eac1be9bf 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * SHcompact irqflags support
  *
  * Copyright (C) 2006 - 2009 Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/irqflags.h>
 #include <linux/module.h>
index 8fc05b997b6db4cf4fc917a53cf88e2e180ef8d8..7a1f50435e33c48c0f2a922ad2cbb28e8aca5289 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * SHmedia irqflags support
  *
  * Copyright (C) 2006 - 2009 Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/irqflags.h>
 #include <linux/module.h>
index 4f04c6638a4d285f7524a69eac448690b96b6938..d24bd2d2ffad2dcc5566893c349b6d0b9fd0547d 100644 (file)
@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * SuperH KGDB support
  *
  * Copyright (C) 2008 - 2012  Paul Mundt
  *
  * Single stepping taken from the old stub by Henry Bell and Jeremy Siegel.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/kgdb.h>
 #include <linux/kdebug.h>
index 241e903dd3ee224a7f05b2318854389afeb13a94..1f8c0d30567fe203035509174d9dfd9f5abae7eb 100644 (file)
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Kernel probes (kprobes) for SuperH
  *
  * Copyright (C) 2007 Chris Smith <chris.smith@st.com>
  * Copyright (C) 2006 Lineo Solutions, Inc.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/kprobes.h>
 #include <linux/extable.h>
index 9fea49f6e667c9b4093bfaa6c59f725375b9760d..b9f9f1a5afdc1a2d71f61dce066f39e4cf11fc87 100644 (file)
@@ -1,12 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * machine_kexec.c - handle transition of Linux booting another kernel
  * Copyright (C) 2002-2003 Eric Biederman  <ebiederm@xmission.com>
  *
  * GameCube/ppc32 port Copyright (C) 2004 Albert Herranz
  * LANDISK/sh4 supported by kogiidena
- *
- * This source code is licensed under the GNU General Public License,
- * Version 2.  See the file COPYING for more details.
  */
 #include <linux/mm.h>
 #include <linux/kexec.h>
index ec05f491c3471ea1e5e57a0ef9b93409f996c008..beadbbdb44867759cd4a835fb61f56a26efba8b2 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/kernel/machvec.c
  *
@@ -5,10 +6,6 @@
  *
  *  Copyright (C) 1999  Niibe Yutaka
  *  Copyright (C) 2002 - 2007 Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/init.h>
 #include <linux/string.h>
index 1b525dedd29a50afe6e4f149bc3ef89a71d7b57c..bbc78d1d618ea131b2c43a2aa52293249d1f9f0a 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*  Kernel module help for SH.
 
     SHcompact version by Kaz Kojima and Paul Mundt.
@@ -9,20 +10,6 @@
 
        Based on the sh version, and on code from the sh64-specific parts of
        modutils, originally written by Richard Curnow and Ben Gaster.
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
 #include <linux/moduleloader.h>
 #include <linux/elf.h>
index 730d928f0d12428af6a888af4aab7b156eb52ce5..11777867c6f5fc69d19120784eacf40d352476d7 100644 (file)
@@ -1,9 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2007 Atmel Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
  */
 #include <linux/delay.h>
 #include <linux/kdebug.h>
index fa2c0cd23eaa88059e0470ed953fe6daedbbcb3e..6281f2fdf9cac9065aac4fe5150023b8da23406d 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Performance event callchain support - SuperH architecture code
  *
  * Copyright (C) 2009  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/kernel.h>
 #include <linux/sched.h>
index ba3269a8304b1ecd843ea41a75b0a92a6efa36a1..445e3ece4c23e6715de677c690661d9023a82c6a 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Performance event support framework for SuperH hardware counters.
  *
  *
  * ppc:
  *  Copyright 2008-2009 Paul Mackerras, IBM Corporation.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/kernel.h>
 #include <linux/init.h>
index 27fddb56b3e1a1806cb0de99527edd4df4436f3e..a094633874c373efb7eb8e1108af99015e7888b5 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/kernel/process.c
  *
@@ -8,10 +9,6 @@
  *  SuperH version:  Copyright (C) 1999, 2000  Niibe Yutaka & Kaz Kojima
  *                  Copyright (C) 2006 Lineo Solutions Inc. support SH4A UBC
  *                  Copyright (C) 2002 - 2008  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/module.h>
 #include <linux/mm.h>
index ee2abe96f9f3a56a532d95619bd46b57186b138b..c2844a2e18cde92f5c3fca9e7fb6df61ec72d4b4 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/kernel/process_64.c
  *
  *
  *   In turn started from i386 version:
  *     Copyright (C) 1995  Linus Torvalds
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/mm.h>
 #include <linux/fs.h>
index 5fc3ff606210c8271b997dd368c6093a6495ae6f..d5052c30a0e9abbab07458799b8dcc21a09ba81e 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * SuperH process tracing
  *
@@ -5,10 +6,6 @@
  * Copyright (C) 2002 - 2009  Paul Mundt
  *
  * Audit support by Yuichi Nakamura <ynakam@hitachisoft.jp>
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/kernel.h>
 #include <linux/sched.h>
index 1e0656d9e7afa645780b2eb044479927c5e9a967..3390349ff9769e88d23459812361512a77afb47b 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/kernel/ptrace_64.c
  *
  *   Original x86 implementation:
  *     By Ross Biro 1/23/92
  *     edited by Linus Torvalds
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/kernel.h>
 #include <linux/rwsem.h>
index fcc9934fb97b8fd24932ee034f88a1c1042fd1f4..d9bf2b727b429ed26a78ff98d411a34629ff9f01 100644 (file)
@@ -1,13 +1,11 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
  * relocate_kernel.S - put the kernel image in place to boot
  * 2005.9.17 kogiidena@eggplant.ddo.jp
  *
  * LANDISK/sh4 is supported. Maybe, SH archtecture works well.
  *
  * 2009-03-18 Magnus Damm - Added Kexec Jump support
- *
- * This source code is licensed under the GNU General Public License,
- * Version 2.  See the file COPYING for more details.
  */
 #include <linux/linkage.h>
 #include <asm/addrspace.h>
index 5124aeb28c3f333d9b7ff7755d8f01e738a044d1..8838094c9ff9444fadf5ceef6f6210772f8cb279 100644 (file)
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/kernel/return_address.c
  *
  * Copyright (C) 2009  Matt Fleming
  * Copyright (C) 2009  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/kernel.h>
 #include <linux/module.h>
index fe584e51696412e9eb9719251739f42ab679c4d3..250dbdf3fa7497623230474d0813768d5125de96 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  *  C interface for trapping into the standard LinuxSH BIOS.
  *
@@ -5,10 +6,6 @@
  *  Copyright (C) 1999, 2000  Niibe Yutaka
  *  Copyright (C) 2002  M. R. Brown
  *  Copyright (C) 2004 - 2010  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/module.h>
 #include <linux/console.h>
index 6ee3740e009ef287dbb04935fc2bffeba19c3301..9de17065afb4952f2433d27f1a96d7f6bf8136f4 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/kernel/sh_ksyms_64.c
  *
  * Copyright (C) 2000, 2001  Paolo Alberelli
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/rwsem.h>
 #include <linux/module.h>
index 7b77f18124349c5fabc7be8ca335e0693dfd2995..76661dee3c65610b6589e3247959e537ea02ad5c 100644 (file)
@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/kernel/signal_64.c
  *
  * Copyright (C) 2000, 2001  Paolo Alberelli
  * Copyright (C) 2003 - 2008  Paul Mundt
  * Copyright (C) 2004  Richard Curnow
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/rwsem.h>
 #include <linux/sched.h>
index c483422ea4d07517f31e03dfd2b0a34d6234a71e..372acdc9033eb35da2b5a610cc6221f53208e573 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/kernel/smp.c
  *
@@ -5,10 +6,6 @@
  *
  * Copyright (C) 2002 - 2010 Paul Mundt
  * Copyright (C) 2006 - 2007 Akio Idehara
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/err.h>
 #include <linux/cache.h>
index 7a73d2763e1ba3ffef136c83198ee75e5fe4256e..f3cb2cccb2624de9a509082047b7c6f10f1997ee 100644 (file)
@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/kernel/stacktrace.c
  *
  * Stack trace management functions
  *
  *  Copyright (C) 2006 - 2008  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/sched.h>
 #include <linux/sched/debug.h>
index 12b64a0f2f013a288aa24ddc1edba99dcf77228e..0b772d6d714fed25af7b491d972987a638b1dce5 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * swsusp.c - SuperH hibernation support
  *
  * Copyright (C) 2009 Magnus Damm
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 
 #include <linux/mm.h>
index 54978e01bf944f762b48215cb321a238f828cc68..96e9c54a07f5209af186fbfddeb89a6457c9208d 100644 (file)
@@ -1,15 +1,11 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
  * arch/sh/kernel/syscalls.S
  *
  * System call table for SuperH
  *
  *  Copyright (C) 1999, 2000, 2002  Niibe Yutaka
  *  Copyright (C) 2003  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
  */
 #include <linux/sys.h>
 #include <linux/linkage.h>
index d6a27f7a4c54b1c33d00c912fa5f7ebc02b80ced..1bcb86f0b728f0ae4f1cf606f18fd1e11fcb608a 100644 (file)
@@ -1,13 +1,10 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
  * arch/sh/kernel/syscalls_64.S
  *
  * Copyright (C) 2000, 2001  Paolo Alberelli
  * Copyright (C) 2004 - 2007  Paul Mundt
  * Copyright (C) 2003, 2004 Richard Curnow
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 
 #include <linux/sys.h>
index 8a1c6c8ab4ec9698b7f079c418e33f1775bc2791..e16b2cd269a331f911a02a35de7170e67922a382 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  *  arch/sh/kernel/time.c
  *
@@ -5,10 +6,6 @@
  *  Copyright (C) 2000  Philipp Rumpf <prumpf@tux.org>
  *  Copyright (C) 2002 - 2009  Paul Mundt
  *  Copyright (C) 2002  M. R. Brown  <mrbrown@linux-sh.org>
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/kernel.h>
 #include <linux/init.h>
index c82912a61d74f26a3d3b1b3e47913c899329ecf6..7a989eed3b18b32635ebca4f4460373f95532f49 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/kernel/topology.c
  *
  *  Copyright (C) 2007  Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/cpu.h>
 #include <linux/cpumask.h>
index 60709ad17fc77595c87de6e3275800bf70f8da04..f2a18b5fafd824bb64abdef412f77b7615fe47fa 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * 'traps.c' handles hardware traps and faults after we have saved some
  * state in 'entry.S'.
@@ -6,10 +7,6 @@
  *                  Copyright (C) 2000 Philipp Rumpf
  *                  Copyright (C) 2000 David Howells
  *                  Copyright (C) 2002 - 2010 Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/kernel.h>
 #include <linux/ptrace.h>
index 014fb08cf133a44d26fe0e78c6310055763d4418..c52bda4d2574aab18d91329c27c6015720363765 100644 (file)
@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/kernel/traps_64.c
  *
  * Copyright (C) 2000, 2001  Paolo Alberelli
  * Copyright (C) 2003, 2004  Paul Mundt
  * Copyright (C) 2003, 2004  Richard Curnow
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/sched.h>
 #include <linux/sched/debug.h>
index 521b5432471fcd24d896fc5edaaecc386fa180be..7a54b72dd923770a774d92eed3663d85d7c9cb80 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2009  Matt Fleming
  *
index cc0cc5b4ff1880ba4a0babf83717300bc6973304..98494480f048ded29aa1a848f6dac79ec14179d7 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/kernel/vsyscall/vsyscall.c
  *
@@ -5,10 +6,6 @@
  *
  * vDSO randomization
  * Copyright(C) 2005-2006, Red Hat, Inc., Ingo Molnar
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/mm.h>
 #include <linux/kernel.h>
index 45ce86558f461419d019e84002b885bfdf8e349a..0f7145e3c51ee2df0c02a8750f367842415bd18c 100644 (file)
@@ -1,30 +1,9 @@
-/* Copyright (C) 1994, 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
+/* SPDX-License-Identifier: GPL-2.0+ WITH GCC-exception-2.0
+
+   Copyright (C) 1994, 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
    2004, 2005, 2006
    Free Software Foundation, Inc.
-
-This file is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 2, or (at your option) any
-later version.
-
-In addition to the permissions in the GNU General Public License, the
-Free Software Foundation gives you unlimited permission to link the
-compiled version of this file into combinations with other programs,
-and to distribute those combinations without any restriction coming
-from the use of this file.  (The General Public License restrictions
-do apply in other respects; for example, they cover modification of
-the file, and distribution when not linked into a combine
-executable.)
-
-This file is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; see the file COPYING.  If not, write to
-the Free Software Foundation, 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA.  */
+*/
 
 !! libgcc routines for the Renesas / SuperH SH CPUs.
 !! Contributed by Steve Chamberlain.
index 70a6434945ab8acf084c166c4c21cb457334617b..4df4401cdf31d5a16dff719568cd6d1834ebabba 100644 (file)
@@ -1,30 +1,9 @@
-/* Copyright (C) 1994, 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
+/* SPDX-License-Identifier: GPL-2.0+ WITH GCC-exception-2.0
+
+   Copyright (C) 1994, 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
    2004, 2005, 2006
    Free Software Foundation, Inc.
-
-This file is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 2, or (at your option) any
-later version.
-
-In addition to the permissions in the GNU General Public License, the
-Free Software Foundation gives you unlimited permission to link the
-compiled version of this file into combinations with other programs,
-and to distribute those combinations without any restriction coming
-from the use of this file.  (The General Public License restrictions
-do apply in other respects; for example, they cover modification of
-the file, and distribution when not linked into a combine
-executable.)
-
-This file is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; see the file COPYING.  If not, write to
-the Free Software Foundation, 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA.  */
+*/
 
 !! libgcc routines for the Renesas / SuperH SH CPUs.
 !! Contributed by Steve Chamberlain.
index 602599d80209114bfc2de066f2f0e74459fc5648..bf3c4e03e6ffc9d4f523635457468210f8d7bfaa 100644 (file)
@@ -1,30 +1,9 @@
-/* Copyright (C) 1994, 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
+/* SPDX-License-Identifier: GPL-2.0+ WITH GCC-exception-2.0
+
+   Copyright (C) 1994, 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
    2004, 2005, 2006
    Free Software Foundation, Inc.
-
-This file is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 2, or (at your option) any
-later version.
-
-In addition to the permissions in the GNU General Public License, the
-Free Software Foundation gives you unlimited permission to link the
-compiled version of this file into combinations with other programs,
-and to distribute those combinations without any restriction coming
-from the use of this file.  (The General Public License restrictions
-do apply in other respects; for example, they cover modification of
-the file, and distribution when not linked into a combine
-executable.)
-
-This file is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; see the file COPYING.  If not, write to
-the Free Software Foundation, 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA.  */
+*/
 
 !! libgcc routines for the Renesas / SuperH SH CPUs.
 !! Contributed by Steve Chamberlain.
index 356c8ec928930fc3d4c00487767c94ee321d67b5..97b5c2d9fec49ce684fc08cb33f110fdf0462f10 100644 (file)
@@ -1,4 +1,6 @@
-/* $Id: checksum.S,v 1.10 2001/07/06 13:11:32 gniibe Exp $
+/* SPDX-License-Identifier: GPL-2.0+
+ *
+ * $Id: checksum.S,v 1.10 2001/07/06 13:11:32 gniibe Exp $
  *
  * INET                An implementation of the TCP/IP protocol suite for the LINUX
  *             operating system.  INET is implemented using the  BSD Socket
  *                   converted to pure assembler
  *
  * SuperH version:  Copyright (C) 1999  Niibe Yutaka
- *
- *             This program is free software; you can redistribute it and/or
- *             modify it under the terms of the GNU General Public License
- *             as published by the Free Software Foundation; either version
- *             2 of the License, or (at your option) any later version.
  */
 
 #include <asm/errno.h>
index 88dfe6e396bc44a67e557534e8bcb86b94b43e63..ebcf7c0a7335adf158e5d1ed679adf12fb069787 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * arch/sh/lib/io.c - SH32 optimized I/O routines
  *
@@ -6,10 +7,6 @@
  *
  * Provide real functions which expand to whatever the header file defined.
  * Also definitions of machine independent IO functions.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <linux/module.h>
 #include <linux/io.h>
index 05909d58e2fe1c278e3f30a3d196e1c214724194..58ada9e8f1c2bd5bba23c19c0367cec08991fdba 100644 (file)
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
 #ifndef __ASM_LIBGCC_H
 #define __ASM_LIBGCC_H
 
index f2a6959f526d30bcda3c7ed0b0eab2d7975aa2b1..b79b8170061f3350b2aca22570b1e6b25f0ef60f 100644 (file)
@@ -1,30 +1,9 @@
-/* Copyright (C) 1994, 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
+/* SPDX-License-Identifier: GPL-2.0+ WITH GCC-exception-2.0
+
+   Copyright (C) 1994, 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
    2004, 2005, 2006
    Free Software Foundation, Inc.
-
-This file is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 2, or (at your option) any
-later version.
-
-In addition to the permissions in the GNU General Public License, the
-Free Software Foundation gives you unlimited permission to link the
-compiled version of this file into combinations with other programs,
-and to distribute those combinations without any restriction coming
-from the use of this file.  (The General Public License restrictions
-do apply in other respects; for example, they cover modification of
-the file, and distribution when not linked into a combine
-executable.)
-
-This file is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; see the file COPYING.  If not, write to
-the Free Software Foundation, 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA.  */
+*/
 
 !! libgcc routines for the Renesas / SuperH SH CPUs.
 !! Contributed by Steve Chamberlain.
index 7a8572f9d58bcdadc1fa5fb31fad65166907f515..c6ca90cc960618726bd620aa2948bfaad014dc57 100644 (file)
@@ -1,12 +1,9 @@
-/*
+/* SPDX-License-Identifier: GPL-2.0
+ *
  * arch/sh/lib/mcount.S
  *
  *  Copyright (C) 2008, 2009  Paul Mundt
  *  Copyright (C) 2008, 2009  Matt Fleming
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #include <asm/ftrace.h>
 #include <asm/thread_info.h>
index 62075f6bc67ca4ad74ea91bc9a5b43c451fad653..8ac54d6b38a1b9f505370bc9f2c4b19e3cc73628 100644 (file)
@@ -1,30 +1,9 @@
-/* Copyright (C) 1994, 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
+/* SPDX-License-Identifier: GPL-2.0+ WITH GCC-exception-2.0
+
+   Copyright (C) 1994, 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
    2004, 2005, 2006
    Free Software Foundation, Inc.
-
-This file is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 2, or (at your option) any
-later version.
-
-In addition to the permissions in the GNU General Public License, the
-Free Software Foundation gives you unlimited permission to link the
-compiled version of this file into combinations with other programs,
-and to distribute those combinations without any restriction coming
-from the use of this file.  (The General Public License restrictions
-do apply in other respects; for example, they cover modification of
-the file, and distribution when not linked into a combine
-executable.)
-
-This file is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; see the file COPYING.  If not, write to
-the Free Software Foundation, 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA.  */
+*/
 
 !! libgcc routines for the Renesas / SuperH SH CPUs.
 !! Contributed by Steve Chamberlain.
index 32b9a36de943ff824263b3cc41d52c650a6f1de0..28938daccd6b444c476c30f60b56adb995fef09c 100644 (file)
@@ -1,30 +1,9 @@
-/* Copyright (C) 1994, 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
+/* SPDX-License-Identifier: GPL-2.0+ WITH GCC-exception-2.0
+
+   Copyright (C) 1994, 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
    2004, 2005, 2006
    Free Software Foundation, Inc.
-
-This file is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 2, or (at your option) any
-later version.
-
-In addition to the permissions in the GNU General Public License, the
-Free Software Foundation gives you unlimited permission to link the
-compiled version of this file into combinations with other programs,
-and to distribute those combinations without any restriction coming
-from the use of this file.  (The General Public License restrictions
-do apply in other respects; for example, they cover modification of
-the file, and distribution when not linked into a combine
-executable.)
-
-This file is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; see the file COPYING.  If not, write to
-the Free Software Foundation, 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA.  */
+*/
 
 !! libgcc routines for the Renesas / SuperH SH CPUs.
 !! Contributed by Steve Chamberlain.
index 72157ab5c314619942743574a80aa81f63e1130e..09ed1f9deb2ea79e49d7bdae84bfcda2265ffa23 100644 (file)
@@ -1,30 +1,9 @@
-/* Copyright (C) 1994, 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
+/* SPDX-License-Identifier: GPL-2.0+ WITH GCC-exception-2.0
+
+   Copyright (C) 1994, 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
    2004, 2005
    Free Software Foundation, Inc.
-
-This file is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 2, or (at your option) any
-later version.
-
-In addition to the permissions in the GNU General Public License, the
-Free Software Foundation gives you unlimited permission to link the
-compiled version of this file into combinations with other programs,
-and to distribute those combinations without any restriction coming
-from the use of this file.  (The General Public License restrictions
-do apply in other respects; for example, they cover modification of
-the file, and distribution when not linked into a combine
-executable.)
-
-This file is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; see the file COPYING.  If not, write to
-the Free Software Foundation, 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA.  */
+*/
 
 !! libgcc routines for the Renesas / SuperH SH CPUs.
 !! Contributed by Steve Chamberlain.
index 4835553e1ea90f68198133bfde564b703f7e284b..fa4e4dff3da1420f94181d78bd3c47519d3a7dbe 100644 (file)
@@ -1,28 +1,7 @@
-/* Copyright (C) 2006 Free Software Foundation, Inc.
-
-This file is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 2, or (at your option) any
-later version.
-
-In addition to the permissions in the GNU General Public License, the
-Free Software Foundation gives you unlimited permission to link the
-compiled version of this file into combinations with other programs,
-and to distribute those combinations without any restriction coming
-from the use of this file.  (The General Public License restrictions
-do apply in other respects; for example, they cover modification of
-the file, and distribution when not linked into a combine
-executable.)
-
-This file is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; see the file COPYING.  If not, write to
-the Free Software Foundation, 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA.  */
+/* SPDX-License-Identifier: GPL-2.0+ WITH GCC-exception-2.0
+ *
+ * Copyright (C) 2006 Free Software Foundation, Inc.
+ */
 
 /* Moderately Space-optimized libgcc routines for the Renesas SH /
    STMicroelectronics ST40 CPUs.
index f1a79d9c5015f382565d4f796694c6c7e6883a7d..6944eb6b4a75ca0158cfb3e8942d5dc51b9509ec 100644 (file)
@@ -1,30 +1,9 @@
-/* Copyright (C) 1994, 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
+/* SPDX-License-Identifier: GPL-2.0+ WITH GCC-exception-2.0
+
+   Copyright (C) 1994, 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
    2004, 2005, 2006
    Free Software Foundation, Inc.
-
-This file is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 2, or (at your option) any
-later version.
-
-In addition to the permissions in the GNU General Public License, the
-Free Software Foundation gives you unlimited permission to link the
-compiled version of this file into combinations with other programs,
-and to distribute those combinations without any restriction coming
-from the use of this file.  (The General Public License restrictions
-do apply in other respects; for example, they cover modification of
-the file, and distribution when not linked into a combine
-executable.)
-
-This file is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; see the file COPYING.  If not, write to
-the Free Software Foundation, 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA.  */
+*/
 
 !! libgcc routines for the Renesas / SuperH SH CPUs.
 !! Contributed by Steve Chamberlain.
index c8c13c777162c42ce5c189b1ff0c8c71806796e0..a8e5c0e00fcaef3d85a0ce595db38fbe36c46532 100644 (file)
@@ -443,7 +443,7 @@ EXPORT_SYMBOL_GPL(memory_add_physaddr_to_nid);
 #endif
 
 #ifdef CONFIG_MEMORY_HOTREMOVE
-int arch_remove_memory(u64 start, u64 size, struct vmem_altmap *altmap)
+int arch_remove_memory(int nid, u64 start, u64 size, struct vmem_altmap *altmap)
 {
        unsigned long start_pfn = PFN_DOWN(start);
        unsigned long nr_pages = size >> PAGE_SHIFT;
index 1067469ba2ea54acf89c7ccbe3e4dbd21e2f952e..8d21a83dd28933721fa479711b112be745d27b7a 100644 (file)
@@ -51,8 +51,8 @@ void __init mem_init(void)
 
        /* this will put all low memory onto the freelists */
        memblock_free_all();
-       max_low_pfn = totalram_pages;
-       max_pfn = totalram_pages;
+       max_low_pfn = totalram_pages();
+       max_pfn = max_low_pfn;
        mem_init_print_info(NULL);
        kmalloc_ok = 1;
 }
index 071b2a6fff85c9a85c3cc5f4f349fb836224254f..33051436c86459131a23005b67ecfdaa952cc123 100644 (file)
@@ -967,7 +967,7 @@ static inline uint32_t hypervisor_cpuid_base(const char *sig, uint32_t leaves)
 }
 
 extern unsigned long arch_align_stack(unsigned long sp);
-extern void free_init_pages(char *what, unsigned long begin, unsigned long end);
+void free_init_pages(const char *what, unsigned long begin, unsigned long end);
 extern void free_kernel_image_pages(void *begin, void *end);
 
 void default_idle(void);
index 2637ff09d6a0da6b7e25cd3942ecb05650fd51e5..97f9ada9cedaf4e7cde47e819f7b4a0d6ac39d77 100644 (file)
@@ -434,9 +434,10 @@ static ssize_t microcode_write(struct file *file, const char __user *buf,
                               size_t len, loff_t *ppos)
 {
        ssize_t ret = -EINVAL;
+       unsigned long nr_pages = totalram_pages();
 
-       if ((len >> PAGE_SHIFT) > totalram_pages) {
-               pr_err("too much data (max %ld pages)\n", totalram_pages);
+       if ((len >> PAGE_SHIFT) > nr_pages) {
+               pr_err("too much data (max %ld pages)\n", nr_pages);
                return ret;
        }
 
index abcb8d00b01486f431fc9fa591f6e6260c8e1153..e3cdc85ce5b6e06644c654c30fafebe3912e390d 100644 (file)
@@ -377,7 +377,7 @@ static void walk_pte_level(struct seq_file *m, struct pg_state *st, pmd_t addr,
 
 /*
  * This is an optimization for KASAN=y case. Since all kasan page tables
- * eventually point to the kasan_zero_page we could call note_page()
+ * eventually point to the kasan_early_shadow_page we could call note_page()
  * right away without walking through lower level page tables. This saves
  * us dozens of seconds (minutes for 5-level config) while checking for
  * W+X mapping or reading kernel_page_tables debugfs file.
@@ -385,10 +385,11 @@ static void walk_pte_level(struct seq_file *m, struct pg_state *st, pmd_t addr,
 static inline bool kasan_page_table(struct seq_file *m, struct pg_state *st,
                                void *pt)
 {
-       if (__pa(pt) == __pa(kasan_zero_pmd) ||
-           (pgtable_l5_enabled() && __pa(pt) == __pa(kasan_zero_p4d)) ||
-           __pa(pt) == __pa(kasan_zero_pud)) {
-               pgprotval_t prot = pte_flags(kasan_zero_pte[0]);
+       if (__pa(pt) == __pa(kasan_early_shadow_pmd) ||
+           (pgtable_l5_enabled() &&
+                       __pa(pt) == __pa(kasan_early_shadow_p4d)) ||
+           __pa(pt) == __pa(kasan_early_shadow_pud)) {
+               pgprotval_t prot = pte_flags(kasan_early_shadow_pte[0]);
                note_page(m, st, __pgprot(prot), 0, 5);
                return true;
        }
index 427a955a2cf2c49fdc1fd5c84494f064a5704caf..f905a2371080beee339dac3f5dad13d0ab1e7ef8 100644 (file)
@@ -742,7 +742,7 @@ int devmem_is_allowed(unsigned long pagenr)
        return 1;
 }
 
-void free_init_pages(char *what, unsigned long begin, unsigned long end)
+void free_init_pages(const char *what, unsigned long begin, unsigned long end)
 {
        unsigned long begin_aligned, end_aligned;
 
index 49ecf5ecf6d329f82e11e2bf12a71fe739de3545..85c94f9a87f8c6247ddb0f645f69fee610cd1fe5 100644 (file)
@@ -860,7 +860,7 @@ int arch_add_memory(int nid, u64 start, u64 size, struct vmem_altmap *altmap,
 }
 
 #ifdef CONFIG_MEMORY_HOTREMOVE
-int arch_remove_memory(u64 start, u64 size, struct vmem_altmap *altmap)
+int arch_remove_memory(int nid, u64 start, u64 size, struct vmem_altmap *altmap)
 {
        unsigned long start_pfn = start >> PAGE_SHIFT;
        unsigned long nr_pages = size >> PAGE_SHIFT;
index 484c1b92f078feb1605681c5c5a5df73e42e41cb..bccff68e32670ddd70762020b68551053c7c3a58 100644 (file)
@@ -1141,7 +1141,8 @@ kernel_physical_mapping_remove(unsigned long start, unsigned long end)
        remove_pagetable(start, end, true, NULL);
 }
 
-int __ref arch_remove_memory(u64 start, u64 size, struct vmem_altmap *altmap)
+int __ref arch_remove_memory(int nid, u64 start, u64 size,
+                               struct vmem_altmap *altmap)
 {
        unsigned long start_pfn = start >> PAGE_SHIFT;
        unsigned long nr_pages = size >> PAGE_SHIFT;
index 04a9cf6b034fe4ec8b0d451416a759e6c21ee051..462fde83b515e60c8b83aea1fa57827eccd09f22 100644 (file)
@@ -211,7 +211,8 @@ static void __init kasan_early_p4d_populate(pgd_t *pgd,
        unsigned long next;
 
        if (pgd_none(*pgd)) {
-               pgd_entry = __pgd(_KERNPG_TABLE | __pa_nodebug(kasan_zero_p4d));
+               pgd_entry = __pgd(_KERNPG_TABLE |
+                                       __pa_nodebug(kasan_early_shadow_p4d));
                set_pgd(pgd, pgd_entry);
        }
 
@@ -222,7 +223,8 @@ static void __init kasan_early_p4d_populate(pgd_t *pgd,
                if (!p4d_none(*p4d))
                        continue;
 
-               p4d_entry = __p4d(_KERNPG_TABLE | __pa_nodebug(kasan_zero_pud));
+               p4d_entry = __p4d(_KERNPG_TABLE |
+                                       __pa_nodebug(kasan_early_shadow_pud));
                set_p4d(p4d, p4d_entry);
        } while (p4d++, addr = next, addr != end && p4d_none(*p4d));
 }
@@ -261,10 +263,11 @@ static struct notifier_block kasan_die_notifier = {
 void __init kasan_early_init(void)
 {
        int i;
-       pteval_t pte_val = __pa_nodebug(kasan_zero_page) | __PAGE_KERNEL | _PAGE_ENC;
-       pmdval_t pmd_val = __pa_nodebug(kasan_zero_pte) | _KERNPG_TABLE;
-       pudval_t pud_val = __pa_nodebug(kasan_zero_pmd) | _KERNPG_TABLE;
-       p4dval_t p4d_val = __pa_nodebug(kasan_zero_pud) | _KERNPG_TABLE;
+       pteval_t pte_val = __pa_nodebug(kasan_early_shadow_page) |
+                               __PAGE_KERNEL | _PAGE_ENC;
+       pmdval_t pmd_val = __pa_nodebug(kasan_early_shadow_pte) | _KERNPG_TABLE;
+       pudval_t pud_val = __pa_nodebug(kasan_early_shadow_pmd) | _KERNPG_TABLE;
+       p4dval_t p4d_val = __pa_nodebug(kasan_early_shadow_pud) | _KERNPG_TABLE;
 
        /* Mask out unsupported __PAGE_KERNEL bits: */
        pte_val &= __default_kernel_pte_mask;
@@ -273,16 +276,16 @@ void __init kasan_early_init(void)
        p4d_val &= __default_kernel_pte_mask;
 
        for (i = 0; i < PTRS_PER_PTE; i++)
-               kasan_zero_pte[i] = __pte(pte_val);
+               kasan_early_shadow_pte[i] = __pte(pte_val);
 
        for (i = 0; i < PTRS_PER_PMD; i++)
-               kasan_zero_pmd[i] = __pmd(pmd_val);
+               kasan_early_shadow_pmd[i] = __pmd(pmd_val);
 
        for (i = 0; i < PTRS_PER_PUD; i++)
-               kasan_zero_pud[i] = __pud(pud_val);
+               kasan_early_shadow_pud[i] = __pud(pud_val);
 
        for (i = 0; pgtable_l5_enabled() && i < PTRS_PER_P4D; i++)
-               kasan_zero_p4d[i] = __p4d(p4d_val);
+               kasan_early_shadow_p4d[i] = __p4d(p4d_val);
 
        kasan_map_early_shadow(early_top_pgt);
        kasan_map_early_shadow(init_top_pgt);
@@ -326,7 +329,7 @@ void __init kasan_init(void)
 
        clear_pgds(KASAN_SHADOW_START & PGDIR_MASK, KASAN_SHADOW_END);
 
-       kasan_populate_zero_shadow((void *)(KASAN_SHADOW_START & PGDIR_MASK),
+       kasan_populate_early_shadow((void *)(KASAN_SHADOW_START & PGDIR_MASK),
                        kasan_mem_to_shadow((void *)PAGE_OFFSET));
 
        for (i = 0; i < E820_MAX_ENTRIES; i++) {
@@ -338,41 +341,41 @@ void __init kasan_init(void)
 
        shadow_cpu_entry_begin = (void *)CPU_ENTRY_AREA_BASE;
        shadow_cpu_entry_begin = kasan_mem_to_shadow(shadow_cpu_entry_begin);
-       shadow_cpu_entry_begin = (void *)round_down((unsigned long)shadow_cpu_entry_begin,
-                                               PAGE_SIZE);
+       shadow_cpu_entry_begin = (void *)round_down(
+                       (unsigned long)shadow_cpu_entry_begin, PAGE_SIZE);
 
        shadow_cpu_entry_end = (void *)(CPU_ENTRY_AREA_BASE +
                                        CPU_ENTRY_AREA_MAP_SIZE);
        shadow_cpu_entry_end = kasan_mem_to_shadow(shadow_cpu_entry_end);
-       shadow_cpu_entry_end = (void *)round_up((unsigned long)shadow_cpu_entry_end,
-                                       PAGE_SIZE);
+       shadow_cpu_entry_end = (void *)round_up(
+                       (unsigned long)shadow_cpu_entry_end, PAGE_SIZE);
 
-       kasan_populate_zero_shadow(
+       kasan_populate_early_shadow(
                kasan_mem_to_shadow((void *)PAGE_OFFSET + MAXMEM),
                shadow_cpu_entry_begin);
 
        kasan_populate_shadow((unsigned long)shadow_cpu_entry_begin,
                              (unsigned long)shadow_cpu_entry_end, 0);
 
-       kasan_populate_zero_shadow(shadow_cpu_entry_end,
-                               kasan_mem_to_shadow((void *)__START_KERNEL_map));
+       kasan_populate_early_shadow(shadow_cpu_entry_end,
+                       kasan_mem_to_shadow((void *)__START_KERNEL_map));
 
        kasan_populate_shadow((unsigned long)kasan_mem_to_shadow(_stext),
                              (unsigned long)kasan_mem_to_shadow(_end),
                              early_pfn_to_nid(__pa(_stext)));
 
-       kasan_populate_zero_shadow(kasan_mem_to_shadow((void *)MODULES_END),
-                               (void *)KASAN_SHADOW_END);
+       kasan_populate_early_shadow(kasan_mem_to_shadow((void *)MODULES_END),
+                                       (void *)KASAN_SHADOW_END);
 
        load_cr3(init_top_pgt);
        __flush_tlb_all();
 
        /*
-        * kasan_zero_page has been used as early shadow memory, thus it may
-        * contain some garbage. Now we can clear and write protect it, since
-        * after the TLB flush no one should write to it.
+        * kasan_early_shadow_page has been used as early shadow memory, thus
+        * it may contain some garbage. Now we can clear and write protect it,
+        * since after the TLB flush no one should write to it.
         */
-       memset(kasan_zero_page, 0, PAGE_SIZE);
+       memset(kasan_early_shadow_page, 0, PAGE_SIZE);
        for (i = 0; i < PTRS_PER_PTE; i++) {
                pte_t pte;
                pgprot_t prot;
@@ -380,8 +383,8 @@ void __init kasan_init(void)
                prot = __pgprot(__PAGE_KERNEL_RO | _PAGE_ENC);
                pgprot_val(prot) &= __default_kernel_pte_mask;
 
-               pte = __pte(__pa(kasan_zero_page) | pgprot_val(prot));
-               set_pte(&kasan_zero_pte[i], pte);
+               pte = __pte(__pa(kasan_early_shadow_page) | pgprot_val(prot));
+               set_pte(&kasan_early_shadow_pte[i], pte);
        }
        /* Flush TLBs again to be sure that write protection applied. */
        __flush_tlb_all();
index 59274e2c1ac44c0fb2fb4c004e3e64484b305335..b0284eab14dc6c04f1b287f5089e61b2b3ca4143 100644 (file)
@@ -794,6 +794,14 @@ int pmd_clear_huge(pmd_t *pmd)
        return 0;
 }
 
+/*
+ * Until we support 512GB pages, skip them in the vmap area.
+ */
+int p4d_free_pud_page(p4d_t *p4d, unsigned long addr)
+{
+       return 0;
+}
+
 #ifdef CONFIG_X86_64
 /**
  * pud_free_pmd_page - Clear pud entry and free pmd page.
@@ -811,9 +819,6 @@ int pud_free_pmd_page(pud_t *pud, unsigned long addr)
        pte_t *pte;
        int i;
 
-       if (pud_none(*pud))
-               return 1;
-
        pmd = (pmd_t *)pud_page_vaddr(*pud);
        pmd_sv = (pmd_t *)__get_free_page(GFP_KERNEL);
        if (!pmd_sv)
@@ -855,9 +860,6 @@ int pmd_free_pte_page(pmd_t *pmd, unsigned long addr)
 {
        pte_t *pte;
 
-       if (pmd_none(*pmd))
-               return 1;
-
        pte = (pte_t *)pmd_page_vaddr(*pmd);
        pmd_clear(pmd);
 
index 6b95ca43aec0f78cd1827824d84b4b3ee5507357..1734cda6bc4ae5f51f3b44ebfe63fb21fe0c2ecb 100644 (file)
@@ -24,12 +24,13 @@ void __init kasan_early_init(void)
        int i;
 
        for (i = 0; i < PTRS_PER_PTE; ++i)
-               set_pte(kasan_zero_pte + i,
-                       mk_pte(virt_to_page(kasan_zero_page), PAGE_KERNEL));
+               set_pte(kasan_early_shadow_pte + i,
+                       mk_pte(virt_to_page(kasan_early_shadow_page),
+                               PAGE_KERNEL));
 
        for (vaddr = 0; vaddr < KASAN_SHADOW_SIZE; vaddr += PMD_SIZE, ++pmd) {
                BUG_ON(!pmd_none(*pmd));
-               set_pmd(pmd, __pmd((unsigned long)kasan_zero_pte));
+               set_pmd(pmd, __pmd((unsigned long)kasan_early_shadow_pte));
        }
        early_trap_init();
 }
@@ -80,13 +81,16 @@ void __init kasan_init(void)
        populate(kasan_mem_to_shadow((void *)VMALLOC_START),
                 kasan_mem_to_shadow((void *)XCHAL_KSEG_BYPASS_VADDR));
 
-       /* Write protect kasan_zero_page and zero-initialize it again. */
+       /*
+        * Write protect kasan_early_shadow_page and zero-initialize it again.
+        */
        for (i = 0; i < PTRS_PER_PTE; ++i)
-               set_pte(kasan_zero_pte + i,
-                       mk_pte(virt_to_page(kasan_zero_page), PAGE_KERNEL_RO));
+               set_pte(kasan_early_shadow_pte + i,
+                       mk_pte(virt_to_page(kasan_early_shadow_page),
+                               PAGE_KERNEL_RO));
 
        local_flush_tlb_all();
-       memset(kasan_zero_page, 0, PAGE_SIZE);
+       memset(kasan_early_shadow_page, 0, PAGE_SIZE);
 
        /* At this point kasan is fully initialized. Enable error messages. */
        current->kasan_depth = 0;
index 0e598568264217f13fd515817800ae2bca12ee7c..fb75a6fd4bd9b309ff16a1ec49cf2f2ec228d515 100644 (file)
@@ -207,15 +207,15 @@ static bool pages_correctly_probed(unsigned long start_pfn)
                        return false;
 
                if (!present_section_nr(section_nr)) {
-                       pr_warn("section %ld pfn[%lx, %lx) not present",
+                       pr_warn("section %ld pfn[%lx, %lx) not present\n",
                                section_nr, pfn, pfn + PAGES_PER_SECTION);
                        return false;
                } else if (!valid_section_nr(section_nr)) {
-                       pr_warn("section %ld pfn[%lx, %lx) no valid memmap",
+                       pr_warn("section %ld pfn[%lx, %lx) no valid memmap\n",
                                section_nr, pfn, pfn + PAGES_PER_SECTION);
                        return false;
                } else if (online_section_nr(section_nr)) {
-                       pr_warn("section %ld pfn[%lx, %lx) is already online",
+                       pr_warn("section %ld pfn[%lx, %lx) is already online\n",
                                section_nr, pfn, pfn + PAGES_PER_SECTION);
                        return false;
                }
@@ -688,7 +688,7 @@ static int add_memory_block(int base_section_nr)
        int i, ret, section_count = 0, section_nr;
 
        for (i = base_section_nr;
-            (i < base_section_nr + sections_per_block) && i < NR_MEM_SECTIONS;
+            i < base_section_nr + sections_per_block;
             i++) {
                if (!present_section_nr(i))
                        continue;
index fcd055457364d6e4efeec59402dc3be77c306ac7..1ffc6477064319f0ebbe27681a79bc62578bd75b 100644 (file)
@@ -15,7 +15,7 @@ config ZRAM
          See Documentation/blockdev/zram.txt for more information.
 
 config ZRAM_WRITEBACK
-       bool "Write back incompressible page to backing device"
+       bool "Write back incompressible or idle page to backing device"
        depends on ZRAM
        help
         With incompressible page, there is no memory saving to keep it
@@ -23,6 +23,9 @@ config ZRAM_WRITEBACK
         For this feature, admin should set up backing device via
         /sys/block/zramX/backing_dev.
 
+        With /sys/block/zramX/{idle,writeback}, application could ask
+        idle page's writeback to the backing device to save in memory.
+
         See Documentation/blockdev/zram.txt for more information.
 
 config ZRAM_MEMORY_TRACKING
index 4879595200e1cf951849c75b7fca0be2ff1f6e15..33c5cc879f246e09b413de0d53687cf9f433a87f 100644 (file)
@@ -52,15 +52,23 @@ static unsigned int num_devices = 1;
 static size_t huge_class_size;
 
 static void zram_free_page(struct zram *zram, size_t index);
+static int zram_bvec_read(struct zram *zram, struct bio_vec *bvec,
+                               u32 index, int offset, struct bio *bio);
+
+
+static int zram_slot_trylock(struct zram *zram, u32 index)
+{
+       return bit_spin_trylock(ZRAM_LOCK, &zram->table[index].flags);
+}
 
 static void zram_slot_lock(struct zram *zram, u32 index)
 {
-       bit_spin_lock(ZRAM_LOCK, &zram->table[index].value);
+       bit_spin_lock(ZRAM_LOCK, &zram->table[index].flags);
 }
 
 static void zram_slot_unlock(struct zram *zram, u32 index)
 {
-       bit_spin_unlock(ZRAM_LOCK, &zram->table[index].value);
+       bit_spin_unlock(ZRAM_LOCK, &zram->table[index].flags);
 }
 
 static inline bool init_done(struct zram *zram)
@@ -68,13 +76,6 @@ static inline bool init_done(struct zram *zram)
        return zram->disksize;
 }
 
-static inline bool zram_allocated(struct zram *zram, u32 index)
-{
-
-       return (zram->table[index].value >> (ZRAM_FLAG_SHIFT + 1)) ||
-                                       zram->table[index].handle;
-}
-
 static inline struct zram *dev_to_zram(struct device *dev)
 {
        return (struct zram *)dev_to_disk(dev)->private_data;
@@ -94,19 +95,19 @@ static void zram_set_handle(struct zram *zram, u32 index, unsigned long handle)
 static bool zram_test_flag(struct zram *zram, u32 index,
                        enum zram_pageflags flag)
 {
-       return zram->table[index].value & BIT(flag);
+       return zram->table[index].flags & BIT(flag);
 }
 
 static void zram_set_flag(struct zram *zram, u32 index,
                        enum zram_pageflags flag)
 {
-       zram->table[index].value |= BIT(flag);
+       zram->table[index].flags |= BIT(flag);
 }
 
 static void zram_clear_flag(struct zram *zram, u32 index,
                        enum zram_pageflags flag)
 {
-       zram->table[index].value &= ~BIT(flag);
+       zram->table[index].flags &= ~BIT(flag);
 }
 
 static inline void zram_set_element(struct zram *zram, u32 index,
@@ -122,15 +123,22 @@ static unsigned long zram_get_element(struct zram *zram, u32 index)
 
 static size_t zram_get_obj_size(struct zram *zram, u32 index)
 {
-       return zram->table[index].value & (BIT(ZRAM_FLAG_SHIFT) - 1);
+       return zram->table[index].flags & (BIT(ZRAM_FLAG_SHIFT) - 1);
 }
 
 static void zram_set_obj_size(struct zram *zram,
                                        u32 index, size_t size)
 {
-       unsigned long flags = zram->table[index].value >> ZRAM_FLAG_SHIFT;
+       unsigned long flags = zram->table[index].flags >> ZRAM_FLAG_SHIFT;
 
-       zram->table[index].value = (flags << ZRAM_FLAG_SHIFT) | size;
+       zram->table[index].flags = (flags << ZRAM_FLAG_SHIFT) | size;
+}
+
+static inline bool zram_allocated(struct zram *zram, u32 index)
+{
+       return zram_get_obj_size(zram, index) ||
+                       zram_test_flag(zram, index, ZRAM_SAME) ||
+                       zram_test_flag(zram, index, ZRAM_WB);
 }
 
 #if PAGE_SIZE != 4096
@@ -276,17 +284,90 @@ static ssize_t mem_used_max_store(struct device *dev,
        return len;
 }
 
+static ssize_t idle_store(struct device *dev,
+               struct device_attribute *attr, const char *buf, size_t len)
+{
+       struct zram *zram = dev_to_zram(dev);
+       unsigned long nr_pages = zram->disksize >> PAGE_SHIFT;
+       int index;
+       char mode_buf[8];
+       ssize_t sz;
+
+       sz = strscpy(mode_buf, buf, sizeof(mode_buf));
+       if (sz <= 0)
+               return -EINVAL;
+
+       /* ignore trailing new line */
+       if (mode_buf[sz - 1] == '\n')
+               mode_buf[sz - 1] = 0x00;
+
+       if (strcmp(mode_buf, "all"))
+               return -EINVAL;
+
+       down_read(&zram->init_lock);
+       if (!init_done(zram)) {
+               up_read(&zram->init_lock);
+               return -EINVAL;
+       }
+
+       for (index = 0; index < nr_pages; index++) {
+               /*
+                * Do not mark ZRAM_UNDER_WB slot as ZRAM_IDLE to close race.
+                * See the comment in writeback_store.
+                */
+               zram_slot_lock(zram, index);
+               if (!zram_allocated(zram, index) ||
+                               zram_test_flag(zram, index, ZRAM_UNDER_WB))
+                       goto next;
+               zram_set_flag(zram, index, ZRAM_IDLE);
+next:
+               zram_slot_unlock(zram, index);
+       }
+
+       up_read(&zram->init_lock);
+
+       return len;
+}
+
 #ifdef CONFIG_ZRAM_WRITEBACK
-static bool zram_wb_enabled(struct zram *zram)
+static ssize_t writeback_limit_store(struct device *dev,
+               struct device_attribute *attr, const char *buf, size_t len)
+{
+       struct zram *zram = dev_to_zram(dev);
+       u64 val;
+       ssize_t ret = -EINVAL;
+
+       if (kstrtoull(buf, 10, &val))
+               return ret;
+
+       down_read(&zram->init_lock);
+       atomic64_set(&zram->stats.bd_wb_limit, val);
+       if (val == 0)
+               zram->stop_writeback = false;
+       up_read(&zram->init_lock);
+       ret = len;
+
+       return ret;
+}
+
+static ssize_t writeback_limit_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
 {
-       return zram->backing_dev;
+       u64 val;
+       struct zram *zram = dev_to_zram(dev);
+
+       down_read(&zram->init_lock);
+       val = atomic64_read(&zram->stats.bd_wb_limit);
+       up_read(&zram->init_lock);
+
+       return scnprintf(buf, PAGE_SIZE, "%llu\n", val);
 }
 
 static void reset_bdev(struct zram *zram)
 {
        struct block_device *bdev;
 
-       if (!zram_wb_enabled(zram))
+       if (!zram->backing_dev)
                return;
 
        bdev = zram->bdev;
@@ -313,7 +394,7 @@ static ssize_t backing_dev_show(struct device *dev,
        ssize_t ret;
 
        down_read(&zram->init_lock);
-       if (!zram_wb_enabled(zram)) {
+       if (!zram->backing_dev) {
                memcpy(buf, "none\n", 5);
                up_read(&zram->init_lock);
                return 5;
@@ -382,8 +463,10 @@ static ssize_t backing_dev_store(struct device *dev,
 
        bdev = bdgrab(I_BDEV(inode));
        err = blkdev_get(bdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL, zram);
-       if (err < 0)
+       if (err < 0) {
+               bdev = NULL;
                goto out;
+       }
 
        nr_pages = i_size_read(inode) >> PAGE_SHIFT;
        bitmap_sz = BITS_TO_LONGS(nr_pages) * sizeof(long);
@@ -399,7 +482,6 @@ static ssize_t backing_dev_store(struct device *dev,
                goto out;
 
        reset_bdev(zram);
-       spin_lock_init(&zram->bitmap_lock);
 
        zram->old_block_size = old_block_size;
        zram->bdev = bdev;
@@ -441,32 +523,29 @@ out:
        return err;
 }
 
-static unsigned long get_entry_bdev(struct zram *zram)
+static unsigned long alloc_block_bdev(struct zram *zram)
 {
-       unsigned long entry;
-
-       spin_lock(&zram->bitmap_lock);
+       unsigned long blk_idx = 1;
+retry:
        /* skip 0 bit to confuse zram.handle = 0 */
-       entry = find_next_zero_bit(zram->bitmap, zram->nr_pages, 1);
-       if (entry == zram->nr_pages) {
-               spin_unlock(&zram->bitmap_lock);
+       blk_idx = find_next_zero_bit(zram->bitmap, zram->nr_pages, blk_idx);
+       if (blk_idx == zram->nr_pages)
                return 0;
-       }
 
-       set_bit(entry, zram->bitmap);
-       spin_unlock(&zram->bitmap_lock);
+       if (test_and_set_bit(blk_idx, zram->bitmap))
+               goto retry;
 
-       return entry;
+       atomic64_inc(&zram->stats.bd_count);
+       return blk_idx;
 }
 
-static void put_entry_bdev(struct zram *zram, unsigned long entry)
+static void free_block_bdev(struct zram *zram, unsigned long blk_idx)
 {
        int was_set;
 
-       spin_lock(&zram->bitmap_lock);
-       was_set = test_and_clear_bit(entry, zram->bitmap);
-       spin_unlock(&zram->bitmap_lock);
+       was_set = test_and_clear_bit(blk_idx, zram->bitmap);
        WARN_ON_ONCE(!was_set);
+       atomic64_dec(&zram->stats.bd_count);
 }
 
 static void zram_page_end_io(struct bio *bio)
@@ -509,6 +588,169 @@ static int read_from_bdev_async(struct zram *zram, struct bio_vec *bvec,
        return 1;
 }
 
+#define HUGE_WRITEBACK 0x1
+#define IDLE_WRITEBACK 0x2
+
+static ssize_t writeback_store(struct device *dev,
+               struct device_attribute *attr, const char *buf, size_t len)
+{
+       struct zram *zram = dev_to_zram(dev);
+       unsigned long nr_pages = zram->disksize >> PAGE_SHIFT;
+       unsigned long index;
+       struct bio bio;
+       struct bio_vec bio_vec;
+       struct page *page;
+       ssize_t ret, sz;
+       char mode_buf[8];
+       unsigned long mode = -1UL;
+       unsigned long blk_idx = 0;
+
+       sz = strscpy(mode_buf, buf, sizeof(mode_buf));
+       if (sz <= 0)
+               return -EINVAL;
+
+       /* ignore trailing newline */
+       if (mode_buf[sz - 1] == '\n')
+               mode_buf[sz - 1] = 0x00;
+
+       if (!strcmp(mode_buf, "idle"))
+               mode = IDLE_WRITEBACK;
+       else if (!strcmp(mode_buf, "huge"))
+               mode = HUGE_WRITEBACK;
+
+       if (mode == -1UL)
+               return -EINVAL;
+
+       down_read(&zram->init_lock);
+       if (!init_done(zram)) {
+               ret = -EINVAL;
+               goto release_init_lock;
+       }
+
+       if (!zram->backing_dev) {
+               ret = -ENODEV;
+               goto release_init_lock;
+       }
+
+       page = alloc_page(GFP_KERNEL);
+       if (!page) {
+               ret = -ENOMEM;
+               goto release_init_lock;
+       }
+
+       for (index = 0; index < nr_pages; index++) {
+               struct bio_vec bvec;
+
+               bvec.bv_page = page;
+               bvec.bv_len = PAGE_SIZE;
+               bvec.bv_offset = 0;
+
+               if (zram->stop_writeback) {
+                       ret = -EIO;
+                       break;
+               }
+
+               if (!blk_idx) {
+                       blk_idx = alloc_block_bdev(zram);
+                       if (!blk_idx) {
+                               ret = -ENOSPC;
+                               break;
+                       }
+               }
+
+               zram_slot_lock(zram, index);
+               if (!zram_allocated(zram, index))
+                       goto next;
+
+               if (zram_test_flag(zram, index, ZRAM_WB) ||
+                               zram_test_flag(zram, index, ZRAM_SAME) ||
+                               zram_test_flag(zram, index, ZRAM_UNDER_WB))
+                       goto next;
+
+               if ((mode & IDLE_WRITEBACK &&
+                         !zram_test_flag(zram, index, ZRAM_IDLE)) &&
+                   (mode & HUGE_WRITEBACK &&
+                         !zram_test_flag(zram, index, ZRAM_HUGE)))
+                       goto next;
+               /*
+                * Clearing ZRAM_UNDER_WB is duty of caller.
+                * IOW, zram_free_page never clear it.
+                */
+               zram_set_flag(zram, index, ZRAM_UNDER_WB);
+               /* Need for hugepage writeback racing */
+               zram_set_flag(zram, index, ZRAM_IDLE);
+               zram_slot_unlock(zram, index);
+               if (zram_bvec_read(zram, &bvec, index, 0, NULL)) {
+                       zram_slot_lock(zram, index);
+                       zram_clear_flag(zram, index, ZRAM_UNDER_WB);
+                       zram_clear_flag(zram, index, ZRAM_IDLE);
+                       zram_slot_unlock(zram, index);
+                       continue;
+               }
+
+               bio_init(&bio, &bio_vec, 1);
+               bio_set_dev(&bio, zram->bdev);
+               bio.bi_iter.bi_sector = blk_idx * (PAGE_SIZE >> 9);
+               bio.bi_opf = REQ_OP_WRITE | REQ_SYNC;
+
+               bio_add_page(&bio, bvec.bv_page, bvec.bv_len,
+                               bvec.bv_offset);
+               /*
+                * XXX: A single page IO would be inefficient for write
+                * but it would be not bad as starter.
+                */
+               ret = submit_bio_wait(&bio);
+               if (ret) {
+                       zram_slot_lock(zram, index);
+                       zram_clear_flag(zram, index, ZRAM_UNDER_WB);
+                       zram_clear_flag(zram, index, ZRAM_IDLE);
+                       zram_slot_unlock(zram, index);
+                       continue;
+               }
+
+               atomic64_inc(&zram->stats.bd_writes);
+               /*
+                * We released zram_slot_lock so need to check if the slot was
+                * changed. If there is freeing for the slot, we can catch it
+                * easily by zram_allocated.
+                * A subtle case is the slot is freed/reallocated/marked as
+                * ZRAM_IDLE again. To close the race, idle_store doesn't
+                * mark ZRAM_IDLE once it found the slot was ZRAM_UNDER_WB.
+                * Thus, we could close the race by checking ZRAM_IDLE bit.
+                */
+               zram_slot_lock(zram, index);
+               if (!zram_allocated(zram, index) ||
+                         !zram_test_flag(zram, index, ZRAM_IDLE)) {
+                       zram_clear_flag(zram, index, ZRAM_UNDER_WB);
+                       zram_clear_flag(zram, index, ZRAM_IDLE);
+                       goto next;
+               }
+
+               zram_free_page(zram, index);
+               zram_clear_flag(zram, index, ZRAM_UNDER_WB);
+               zram_set_flag(zram, index, ZRAM_WB);
+               zram_set_element(zram, index, blk_idx);
+               blk_idx = 0;
+               atomic64_inc(&zram->stats.pages_stored);
+               if (atomic64_add_unless(&zram->stats.bd_wb_limit,
+                                       -1 << (PAGE_SHIFT - 12), 0)) {
+                       if (atomic64_read(&zram->stats.bd_wb_limit) == 0)
+                               zram->stop_writeback = true;
+               }
+next:
+               zram_slot_unlock(zram, index);
+       }
+
+       if (blk_idx)
+               free_block_bdev(zram, blk_idx);
+       ret = len;
+       __free_page(page);
+release_init_lock:
+       up_read(&zram->init_lock);
+
+       return ret;
+}
+
 struct zram_work {
        struct work_struct work;
        struct zram *zram;
@@ -561,79 +803,21 @@ static int read_from_bdev_sync(struct zram *zram, struct bio_vec *bvec,
 static int read_from_bdev(struct zram *zram, struct bio_vec *bvec,
                        unsigned long entry, struct bio *parent, bool sync)
 {
+       atomic64_inc(&zram->stats.bd_reads);
        if (sync)
                return read_from_bdev_sync(zram, bvec, entry, parent);
        else
                return read_from_bdev_async(zram, bvec, entry, parent);
 }
-
-static int write_to_bdev(struct zram *zram, struct bio_vec *bvec,
-                                       u32 index, struct bio *parent,
-                                       unsigned long *pentry)
-{
-       struct bio *bio;
-       unsigned long entry;
-
-       bio = bio_alloc(GFP_ATOMIC, 1);
-       if (!bio)
-               return -ENOMEM;
-
-       entry = get_entry_bdev(zram);
-       if (!entry) {
-               bio_put(bio);
-               return -ENOSPC;
-       }
-
-       bio->bi_iter.bi_sector = entry * (PAGE_SIZE >> 9);
-       bio_set_dev(bio, zram->bdev);
-       if (!bio_add_page(bio, bvec->bv_page, bvec->bv_len,
-                                       bvec->bv_offset)) {
-               bio_put(bio);
-               put_entry_bdev(zram, entry);
-               return -EIO;
-       }
-
-       if (!parent) {
-               bio->bi_opf = REQ_OP_WRITE | REQ_SYNC;
-               bio->bi_end_io = zram_page_end_io;
-       } else {
-               bio->bi_opf = parent->bi_opf;
-               bio_chain(bio, parent);
-       }
-
-       submit_bio(bio);
-       *pentry = entry;
-
-       return 0;
-}
-
-static void zram_wb_clear(struct zram *zram, u32 index)
-{
-       unsigned long entry;
-
-       zram_clear_flag(zram, index, ZRAM_WB);
-       entry = zram_get_element(zram, index);
-       zram_set_element(zram, index, 0);
-       put_entry_bdev(zram, entry);
-}
-
 #else
-static bool zram_wb_enabled(struct zram *zram) { return false; }
 static inline void reset_bdev(struct zram *zram) {};
-static int write_to_bdev(struct zram *zram, struct bio_vec *bvec,
-                                       u32 index, struct bio *parent,
-                                       unsigned long *pentry)
-
-{
-       return -EIO;
-}
-
 static int read_from_bdev(struct zram *zram, struct bio_vec *bvec,
                        unsigned long entry, struct bio *parent, bool sync)
 {
        return -EIO;
 }
-static void zram_wb_clear(struct zram *zram, u32 index) {}
+
+static void free_block_bdev(struct zram *zram, unsigned long blk_idx) {};
 #endif
 
 #ifdef CONFIG_ZRAM_MEMORY_TRACKING
@@ -652,14 +836,10 @@ static void zram_debugfs_destroy(void)
 
 static void zram_accessed(struct zram *zram, u32 index)
 {
+       zram_clear_flag(zram, index, ZRAM_IDLE);
        zram->table[index].ac_time = ktime_get_boottime();
 }
 
-static void zram_reset_access(struct zram *zram, u32 index)
-{
-       zram->table[index].ac_time = 0;
-}
-
 static ssize_t read_block_state(struct file *file, char __user *buf,
                                size_t count, loff_t *ppos)
 {
@@ -689,12 +869,13 @@ static ssize_t read_block_state(struct file *file, char __user *buf,
 
                ts = ktime_to_timespec64(zram->table[index].ac_time);
                copied = snprintf(kbuf + written, count,
-                       "%12zd %12lld.%06lu %c%c%c\n",
+                       "%12zd %12lld.%06lu %c%c%c%c\n",
                        index, (s64)ts.tv_sec,
                        ts.tv_nsec / NSEC_PER_USEC,
                        zram_test_flag(zram, index, ZRAM_SAME) ? 's' : '.',
                        zram_test_flag(zram, index, ZRAM_WB) ? 'w' : '.',
-                       zram_test_flag(zram, index, ZRAM_HUGE) ? 'h' : '.');
+                       zram_test_flag(zram, index, ZRAM_HUGE) ? 'h' : '.',
+                       zram_test_flag(zram, index, ZRAM_IDLE) ? 'i' : '.');
 
                if (count < copied) {
                        zram_slot_unlock(zram, index);
@@ -739,8 +920,10 @@ static void zram_debugfs_unregister(struct zram *zram)
 #else
 static void zram_debugfs_create(void) {};
 static void zram_debugfs_destroy(void) {};
-static void zram_accessed(struct zram *zram, u32 index) {};
-static void zram_reset_access(struct zram *zram, u32 index) {};
+static void zram_accessed(struct zram *zram, u32 index)
+{
+       zram_clear_flag(zram, index, ZRAM_IDLE);
+};
 static void zram_debugfs_register(struct zram *zram) {};
 static void zram_debugfs_unregister(struct zram *zram) {};
 #endif
@@ -877,6 +1060,26 @@ static ssize_t mm_stat_show(struct device *dev,
        return ret;
 }
 
+#ifdef CONFIG_ZRAM_WRITEBACK
+#define FOUR_K(x) ((x) * (1 << (PAGE_SHIFT - 12)))
+static ssize_t bd_stat_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       struct zram *zram = dev_to_zram(dev);
+       ssize_t ret;
+
+       down_read(&zram->init_lock);
+       ret = scnprintf(buf, PAGE_SIZE,
+               "%8llu %8llu %8llu\n",
+                       FOUR_K((u64)atomic64_read(&zram->stats.bd_count)),
+                       FOUR_K((u64)atomic64_read(&zram->stats.bd_reads)),
+                       FOUR_K((u64)atomic64_read(&zram->stats.bd_writes)));
+       up_read(&zram->init_lock);
+
+       return ret;
+}
+#endif
+
 static ssize_t debug_stat_show(struct device *dev,
                struct device_attribute *attr, char *buf)
 {
@@ -886,9 +1089,10 @@ static ssize_t debug_stat_show(struct device *dev,
 
        down_read(&zram->init_lock);
        ret = scnprintf(buf, PAGE_SIZE,
-                       "version: %d\n%8llu\n",
+                       "version: %d\n%8llu %8llu\n",
                        version,
-                       (u64)atomic64_read(&zram->stats.writestall));
+                       (u64)atomic64_read(&zram->stats.writestall),
+                       (u64)atomic64_read(&zram->stats.miss_free));
        up_read(&zram->init_lock);
 
        return ret;
@@ -896,6 +1100,9 @@ static ssize_t debug_stat_show(struct device *dev,
 
 static DEVICE_ATTR_RO(io_stat);
 static DEVICE_ATTR_RO(mm_stat);
+#ifdef CONFIG_ZRAM_WRITEBACK
+static DEVICE_ATTR_RO(bd_stat);
+#endif
 static DEVICE_ATTR_RO(debug_stat);
 
 static void zram_meta_free(struct zram *zram, u64 disksize)
@@ -940,17 +1147,21 @@ static void zram_free_page(struct zram *zram, size_t index)
 {
        unsigned long handle;
 
-       zram_reset_access(zram, index);
+#ifdef CONFIG_ZRAM_MEMORY_TRACKING
+       zram->table[index].ac_time = 0;
+#endif
+       if (zram_test_flag(zram, index, ZRAM_IDLE))
+               zram_clear_flag(zram, index, ZRAM_IDLE);
 
        if (zram_test_flag(zram, index, ZRAM_HUGE)) {
                zram_clear_flag(zram, index, ZRAM_HUGE);
                atomic64_dec(&zram->stats.huge_pages);
        }
 
-       if (zram_wb_enabled(zram) && zram_test_flag(zram, index, ZRAM_WB)) {
-               zram_wb_clear(zram, index);
-               atomic64_dec(&zram->stats.pages_stored);
-               return;
+       if (zram_test_flag(zram, index, ZRAM_WB)) {
+               zram_clear_flag(zram, index, ZRAM_WB);
+               free_block_bdev(zram, zram_get_element(zram, index));
+               goto out;
        }
 
        /*
@@ -959,10 +1170,8 @@ static void zram_free_page(struct zram *zram, size_t index)
         */
        if (zram_test_flag(zram, index, ZRAM_SAME)) {
                zram_clear_flag(zram, index, ZRAM_SAME);
-               zram_set_element(zram, index, 0);
                atomic64_dec(&zram->stats.same_pages);
-               atomic64_dec(&zram->stats.pages_stored);
-               return;
+               goto out;
        }
 
        handle = zram_get_handle(zram, index);
@@ -973,10 +1182,12 @@ static void zram_free_page(struct zram *zram, size_t index)
 
        atomic64_sub(zram_get_obj_size(zram, index),
                        &zram->stats.compr_data_size);
+out:
        atomic64_dec(&zram->stats.pages_stored);
-
        zram_set_handle(zram, index, 0);
        zram_set_obj_size(zram, index, 0);
+       WARN_ON_ONCE(zram->table[index].flags &
+               ~(1UL << ZRAM_LOCK | 1UL << ZRAM_UNDER_WB));
 }
 
 static int __zram_bvec_read(struct zram *zram, struct page *page, u32 index,
@@ -987,24 +1198,20 @@ static int __zram_bvec_read(struct zram *zram, struct page *page, u32 index,
        unsigned int size;
        void *src, *dst;
 
-       if (zram_wb_enabled(zram)) {
-               zram_slot_lock(zram, index);
-               if (zram_test_flag(zram, index, ZRAM_WB)) {
-                       struct bio_vec bvec;
-
-                       zram_slot_unlock(zram, index);
+       zram_slot_lock(zram, index);
+       if (zram_test_flag(zram, index, ZRAM_WB)) {
+               struct bio_vec bvec;
 
-                       bvec.bv_page = page;
-                       bvec.bv_len = PAGE_SIZE;
-                       bvec.bv_offset = 0;
-                       return read_from_bdev(zram, &bvec,
-                                       zram_get_element(zram, index),
-                                       bio, partial_io);
-               }
                zram_slot_unlock(zram, index);
+
+               bvec.bv_page = page;
+               bvec.bv_len = PAGE_SIZE;
+               bvec.bv_offset = 0;
+               return read_from_bdev(zram, &bvec,
+                               zram_get_element(zram, index),
+                               bio, partial_io);
        }
 
-       zram_slot_lock(zram, index);
        handle = zram_get_handle(zram, index);
        if (!handle || zram_test_flag(zram, index, ZRAM_SAME)) {
                unsigned long value;
@@ -1089,7 +1296,6 @@ static int __zram_bvec_write(struct zram *zram, struct bio_vec *bvec,
        struct page *page = bvec->bv_page;
        unsigned long element = 0;
        enum zram_pageflags flags = 0;
-       bool allow_wb = true;
 
        mem = kmap_atomic(page);
        if (page_same_filled(mem, &element)) {
@@ -1114,21 +1320,8 @@ compress_again:
                return ret;
        }
 
-       if (unlikely(comp_len >= huge_class_size)) {
+       if (comp_len >= huge_class_size)
                comp_len = PAGE_SIZE;
-               if (zram_wb_enabled(zram) && allow_wb) {
-                       zcomp_stream_put(zram->comp);
-                       ret = write_to_bdev(zram, bvec, index, bio, &element);
-                       if (!ret) {
-                               flags = ZRAM_WB;
-                               ret = 1;
-                               goto out;
-                       }
-                       allow_wb = false;
-                       goto compress_again;
-               }
-       }
-
        /*
         * handle allocation has 2 paths:
         * a) fast path is executed with preemption disabled (for
@@ -1400,10 +1593,14 @@ static void zram_slot_free_notify(struct block_device *bdev,
 
        zram = bdev->bd_disk->private_data;
 
-       zram_slot_lock(zram, index);
+       atomic64_inc(&zram->stats.notify_free);
+       if (!zram_slot_trylock(zram, index)) {
+               atomic64_inc(&zram->stats.miss_free);
+               return;
+       }
+
        zram_free_page(zram, index);
        zram_slot_unlock(zram, index);
-       atomic64_inc(&zram->stats.notify_free);
 }
 
 static int zram_rw_page(struct block_device *bdev, sector_t sector,
@@ -1608,10 +1805,13 @@ static DEVICE_ATTR_RO(initstate);
 static DEVICE_ATTR_WO(reset);
 static DEVICE_ATTR_WO(mem_limit);
 static DEVICE_ATTR_WO(mem_used_max);
+static DEVICE_ATTR_WO(idle);
 static DEVICE_ATTR_RW(max_comp_streams);
 static DEVICE_ATTR_RW(comp_algorithm);
 #ifdef CONFIG_ZRAM_WRITEBACK
 static DEVICE_ATTR_RW(backing_dev);
+static DEVICE_ATTR_WO(writeback);
+static DEVICE_ATTR_RW(writeback_limit);
 #endif
 
 static struct attribute *zram_disk_attrs[] = {
@@ -1621,13 +1821,19 @@ static struct attribute *zram_disk_attrs[] = {
        &dev_attr_compact.attr,
        &dev_attr_mem_limit.attr,
        &dev_attr_mem_used_max.attr,
+       &dev_attr_idle.attr,
        &dev_attr_max_comp_streams.attr,
        &dev_attr_comp_algorithm.attr,
 #ifdef CONFIG_ZRAM_WRITEBACK
        &dev_attr_backing_dev.attr,
+       &dev_attr_writeback.attr,
+       &dev_attr_writeback_limit.attr,
 #endif
        &dev_attr_io_stat.attr,
        &dev_attr_mm_stat.attr,
+#ifdef CONFIG_ZRAM_WRITEBACK
+       &dev_attr_bd_stat.attr,
+#endif
        &dev_attr_debug_stat.attr,
        NULL,
 };
index 72c8584b6dfff46847a73dbc066ceeff3ecbcec1..4bd3afd15e833e2e8a75292e9f8ffcc34e162b63 100644 (file)
@@ -30,7 +30,7 @@
 
 
 /*
- * The lower ZRAM_FLAG_SHIFT bits of table.value is for
+ * The lower ZRAM_FLAG_SHIFT bits of table.flags is for
  * object size (excluding header), the higher bits is for
  * zram_pageflags.
  *
  */
 #define ZRAM_FLAG_SHIFT 24
 
-/* Flags for zram pages (table[page_no].value) */
+/* Flags for zram pages (table[page_no].flags) */
 enum zram_pageflags {
        /* zram slot is locked */
        ZRAM_LOCK = ZRAM_FLAG_SHIFT,
        ZRAM_SAME,      /* Page consists the same element */
        ZRAM_WB,        /* page is stored on backing_device */
+       ZRAM_UNDER_WB,  /* page is under writeback */
        ZRAM_HUGE,      /* Incompressible page */
+       ZRAM_IDLE,      /* not accessed page since last idle marking */
 
        __NR_ZRAM_PAGEFLAGS,
 };
@@ -60,7 +62,7 @@ struct zram_table_entry {
                unsigned long handle;
                unsigned long element;
        };
-       unsigned long value;
+       unsigned long flags;
 #ifdef CONFIG_ZRAM_MEMORY_TRACKING
        ktime_t ac_time;
 #endif
@@ -79,6 +81,13 @@ struct zram_stats {
        atomic64_t pages_stored;        /* no. of pages currently stored */
        atomic_long_t max_used_pages;   /* no. of maximum pages stored */
        atomic64_t writestall;          /* no. of write slow paths */
+       atomic64_t miss_free;           /* no. of missed free */
+#ifdef CONFIG_ZRAM_WRITEBACK
+       atomic64_t bd_count;            /* no. of pages in backing device */
+       atomic64_t bd_reads;            /* no. of reads from backing device */
+       atomic64_t bd_writes;           /* no. of writes from backing device */
+       atomic64_t bd_wb_limit;         /* writeback limit of backing device */
+#endif
 };
 
 struct zram {
@@ -104,13 +113,13 @@ struct zram {
         * zram is claimed so open request will be failed
         */
        bool claim; /* Protected by bdev->bd_mutex */
-#ifdef CONFIG_ZRAM_WRITEBACK
        struct file *backing_dev;
+       bool stop_writeback;
+#ifdef CONFIG_ZRAM_WRITEBACK
        struct block_device *bdev;
        unsigned int old_block_size;
        unsigned long *bitmap;
        unsigned long nr_pages;
-       spinlock_t bitmap_lock;
 #endif
 #ifdef CONFIG_ZRAM_MEMORY_TRACKING
        struct dentry *debugfs_dir;
index 38ffb281df97c71eee3dc8980a98e19df3ca24d3..004a3ce8ba72d5df0b7dd8c72f98074d111c26a8 100644 (file)
@@ -115,9 +115,9 @@ static int agp_find_max(void)
        long memory, index, result;
 
 #if PAGE_SHIFT < 20
-       memory = totalram_pages >> (20 - PAGE_SHIFT);
+       memory = totalram_pages() >> (20 - PAGE_SHIFT);
 #else
-       memory = totalram_pages << (PAGE_SHIFT - 20);
+       memory = totalram_pages() << (PAGE_SHIFT - 20);
 #endif
        index = 1;
 
index 99e2aace8078c87fde81019ccd3380fcccc666ec..2c1f459c0c63aab5a2ad1e7089c06ff7556f19c9 100644 (file)
@@ -48,9 +48,8 @@ static void dax_pmem_percpu_exit(void *data)
        percpu_ref_exit(ref);
 }
 
-static void dax_pmem_percpu_kill(void *data)
+static void dax_pmem_percpu_kill(struct percpu_ref *ref)
 {
-       struct percpu_ref *ref = data;
        struct dax_pmem *dax_pmem = to_dax_pmem(ref);
 
        dev_dbg(dax_pmem->dev, "trace\n");
@@ -112,17 +111,10 @@ static int dax_pmem_probe(struct device *dev)
        }
 
        dax_pmem->pgmap.ref = &dax_pmem->ref;
+       dax_pmem->pgmap.kill = dax_pmem_percpu_kill;
        addr = devm_memremap_pages(dev, &dax_pmem->pgmap);
-       if (IS_ERR(addr)) {
-               devm_remove_action(dev, dax_pmem_percpu_exit, &dax_pmem->ref);
-               percpu_ref_exit(&dax_pmem->ref);
+       if (IS_ERR(addr))
                return PTR_ERR(addr);
-       }
-
-       rc = devm_add_action_or_reset(dev, dax_pmem_percpu_kill,
-                                                       &dax_pmem->ref);
-       if (rc)
-               return rc;
 
        /* adjust the dax_region resource to the start of data */
        memcpy(&res, &dax_pmem->pgmap.res, sizeof(res));
index e55508b394962d8d77e6fe285cee1a9544214714..3e6823fdd93942cce3ace2c21b456f1e4e1d8d84 100644 (file)
@@ -238,44 +238,40 @@ static void amdgpu_mn_invalidate_node(struct amdgpu_mn_node *node,
  * amdgpu_mn_invalidate_range_start_gfx - callback to notify about mm change
  *
  * @mn: our notifier
- * @mm: the mm this callback is about
- * @start: start of updated range
- * @end: end of updated range
+ * @range: mmu notifier context
  *
  * Block for operations on BOs to finish and mark pages as accessed and
  * potentially dirty.
  */
 static int amdgpu_mn_invalidate_range_start_gfx(struct mmu_notifier *mn,
-                                                struct mm_struct *mm,
-                                                unsigned long start,
-                                                unsigned long end,
-                                                bool blockable)
+                       const struct mmu_notifier_range *range)
 {
        struct amdgpu_mn *amn = container_of(mn, struct amdgpu_mn, mn);
        struct interval_tree_node *it;
+       unsigned long end;
 
        /* notification is exclusive, but interval is inclusive */
-       end -= 1;
+       end = range->end - 1;
 
        /* TODO we should be able to split locking for interval tree and
         * amdgpu_mn_invalidate_node
         */
-       if (amdgpu_mn_read_lock(amn, blockable))
+       if (amdgpu_mn_read_lock(amn, range->blockable))
                return -EAGAIN;
 
-       it = interval_tree_iter_first(&amn->objects, start, end);
+       it = interval_tree_iter_first(&amn->objects, range->start, end);
        while (it) {
                struct amdgpu_mn_node *node;
 
-               if (!blockable) {
+               if (!range->blockable) {
                        amdgpu_mn_read_unlock(amn);
                        return -EAGAIN;
                }
 
                node = container_of(it, struct amdgpu_mn_node, it);
-               it = interval_tree_iter_next(it, start, end);
+               it = interval_tree_iter_next(it, range->start, end);
 
-               amdgpu_mn_invalidate_node(node, start, end);
+               amdgpu_mn_invalidate_node(node, range->start, end);
        }
 
        return 0;
@@ -294,39 +290,38 @@ static int amdgpu_mn_invalidate_range_start_gfx(struct mmu_notifier *mn,
  * are restorted in amdgpu_mn_invalidate_range_end_hsa.
  */
 static int amdgpu_mn_invalidate_range_start_hsa(struct mmu_notifier *mn,
-                                                struct mm_struct *mm,
-                                                unsigned long start,
-                                                unsigned long end,
-                                                bool blockable)
+                       const struct mmu_notifier_range *range)
 {
        struct amdgpu_mn *amn = container_of(mn, struct amdgpu_mn, mn);
        struct interval_tree_node *it;
+       unsigned long end;
 
        /* notification is exclusive, but interval is inclusive */
-       end -= 1;
+       end = range->end - 1;
 
-       if (amdgpu_mn_read_lock(amn, blockable))
+       if (amdgpu_mn_read_lock(amn, range->blockable))
                return -EAGAIN;
 
-       it = interval_tree_iter_first(&amn->objects, start, end);
+       it = interval_tree_iter_first(&amn->objects, range->start, end);
        while (it) {
                struct amdgpu_mn_node *node;
                struct amdgpu_bo *bo;
 
-               if (!blockable) {
+               if (!range->blockable) {
                        amdgpu_mn_read_unlock(amn);
                        return -EAGAIN;
                }
 
                node = container_of(it, struct amdgpu_mn_node, it);
-               it = interval_tree_iter_next(it, start, end);
+               it = interval_tree_iter_next(it, range->start, end);
 
                list_for_each_entry(bo, &node->bos, mn_list) {
                        struct kgd_mem *mem = bo->kfd_bo;
 
                        if (amdgpu_ttm_tt_affect_userptr(bo->tbo.ttm,
-                                                        start, end))
-                               amdgpu_amdkfd_evict_userptr(mem, mm);
+                                                        range->start,
+                                                        end))
+                               amdgpu_amdkfd_evict_userptr(mem, range->mm);
                }
        }
 
@@ -344,9 +339,7 @@ static int amdgpu_mn_invalidate_range_start_hsa(struct mmu_notifier *mn,
  * Release the lock again to allow new command submissions.
  */
 static void amdgpu_mn_invalidate_range_end(struct mmu_notifier *mn,
-                                          struct mm_struct *mm,
-                                          unsigned long start,
-                                          unsigned long end)
+                       const struct mmu_notifier_range *range)
 {
        struct amdgpu_mn *amn = container_of(mn, struct amdgpu_mn, mn);
 
index c02adbbeef2a645f2bfbe98da652b9694b9afec3..b7bc7d7d048f679cb11d58184578859868bd9bd4 100644 (file)
@@ -853,7 +853,7 @@ static int kfd_fill_mem_info_for_cpu(int numa_node_id, int *avail_size,
         */
        pgdat = NODE_DATA(numa_node_id);
        for (zone_type = 0; zone_type < MAX_NR_ZONES; zone_type++)
-               mem_in_bytes += pgdat->node_zones[zone_type].managed_pages;
+               mem_in_bytes += zone_managed_pages(&pgdat->node_zones[zone_type]);
        mem_in_bytes <<= PAGE_SHIFT;
 
        sub_type_hdr->length_low = lower_32_bits(mem_in_bytes);
index d36a9755ad910f29870e252bb7d6a18a800101d3..a9de07bb72c896e8f3714799fd3a9264010bb79e 100644 (file)
@@ -2559,7 +2559,7 @@ static int i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj)
         * If there's no chance of allocating enough pages for the whole
         * object, bail early.
         */
-       if (page_count > totalram_pages)
+       if (page_count > totalram_pages())
                return -ENOMEM;
 
        st = kmalloc(sizeof(*st), GFP_KERNEL);
index 2c9b284036d10217a013e146eba8704123006d65..3df77020aada8539330a8d3b86f1f23fbadd20f9 100644 (file)
@@ -113,27 +113,25 @@ static void del_object(struct i915_mmu_object *mo)
 }
 
 static int i915_gem_userptr_mn_invalidate_range_start(struct mmu_notifier *_mn,
-                                                      struct mm_struct *mm,
-                                                      unsigned long start,
-                                                      unsigned long end,
-                                                      bool blockable)
+                       const struct mmu_notifier_range *range)
 {
        struct i915_mmu_notifier *mn =
                container_of(_mn, struct i915_mmu_notifier, mn);
        struct i915_mmu_object *mo;
        struct interval_tree_node *it;
        LIST_HEAD(cancelled);
+       unsigned long end;
 
        if (RB_EMPTY_ROOT(&mn->objects.rb_root))
                return 0;
 
        /* interval ranges are inclusive, but invalidate range is exclusive */
-       end--;
+       end = range->end - 1;
 
        spin_lock(&mn->lock);
-       it = interval_tree_iter_first(&mn->objects, start, end);
+       it = interval_tree_iter_first(&mn->objects, range->start, end);
        while (it) {
-               if (!blockable) {
+               if (!range->blockable) {
                        spin_unlock(&mn->lock);
                        return -EAGAIN;
                }
@@ -151,7 +149,7 @@ static int i915_gem_userptr_mn_invalidate_range_start(struct mmu_notifier *_mn,
                        queue_work(mn->wq, &mo->work);
 
                list_add(&mo->link, &cancelled);
-               it = interval_tree_iter_next(it, start, end);
+               it = interval_tree_iter_next(it, range->start, end);
        }
        list_for_each_entry(mo, &cancelled, link)
                del_object(mo);
index 69fe86b30fbb79aaea1c8d8ece1edffe03c9d684..a9ed0ecc94e2d77fa23a721fb9ace38655851597 100644 (file)
@@ -170,7 +170,7 @@ static int igt_ppgtt_alloc(void *arg)
         * This should ensure that we do not run into the oomkiller during
         * the test and take down the machine wilfully.
         */
-       limit = totalram_pages << PAGE_SHIFT;
+       limit = totalram_pages() << PAGE_SHIFT;
        limit = min(ppgtt->vm.total, limit);
 
        /* Check we can allocate the entire range */
@@ -1244,7 +1244,7 @@ static int exercise_mock(struct drm_i915_private *i915,
                                     u64 hole_start, u64 hole_end,
                                     unsigned long end_time))
 {
-       const u64 limit = totalram_pages << PAGE_SHIFT;
+       const u64 limit = totalram_pages() << PAGE_SHIFT;
        struct i915_gem_context *ctx;
        struct i915_hw_ppgtt *ppgtt;
        IGT_TIMEOUT(end_time);
index f8b35df44c60eba57e7b2ec76c068190dd941c79..b3019505065ab2d2591aad3fb077b9a6183a5a10 100644 (file)
@@ -119,40 +119,38 @@ static void radeon_mn_release(struct mmu_notifier *mn,
  * unmap them by move them into system domain again.
  */
 static int radeon_mn_invalidate_range_start(struct mmu_notifier *mn,
-                                            struct mm_struct *mm,
-                                            unsigned long start,
-                                            unsigned long end,
-                                            bool blockable)
+                               const struct mmu_notifier_range *range)
 {
        struct radeon_mn *rmn = container_of(mn, struct radeon_mn, mn);
        struct ttm_operation_ctx ctx = { false, false };
        struct interval_tree_node *it;
+       unsigned long end;
        int ret = 0;
 
        /* notification is exclusive, but interval is inclusive */
-       end -= 1;
+       end = range->end - 1;
 
        /* TODO we should be able to split locking for interval tree and
         * the tear down.
         */
-       if (blockable)
+       if (range->blockable)
                mutex_lock(&rmn->lock);
        else if (!mutex_trylock(&rmn->lock))
                return -EAGAIN;
 
-       it = interval_tree_iter_first(&rmn->objects, start, end);
+       it = interval_tree_iter_first(&rmn->objects, range->start, end);
        while (it) {
                struct radeon_mn_node *node;
                struct radeon_bo *bo;
                long r;
 
-               if (!blockable) {
+               if (!range->blockable) {
                        ret = -EAGAIN;
                        goto out_unlock;
                }
 
                node = container_of(it, struct radeon_mn_node, it);
-               it = interval_tree_iter_next(it, start, end);
+               it = interval_tree_iter_next(it, range->start, end);
 
                list_for_each_entry(bo, &node->bos, mn_list) {
 
index 41631512ae97e3ab20a4d52e2b3614a03eb832a6..5301fef16c31b740fab409ced2f3e7ef6c5bbe23 100644 (file)
@@ -1090,6 +1090,7 @@ static void process_info(struct hv_dynmem_device *dm, struct dm_info_msg *msg)
 static unsigned long compute_balloon_floor(void)
 {
        unsigned long min_pages;
+       unsigned long nr_pages = totalram_pages();
 #define MB2PAGES(mb) ((mb) << (20 - PAGE_SHIFT))
        /* Simple continuous piecewiese linear function:
         *  max MiB -> min MiB  gradient
@@ -1102,16 +1103,16 @@ static unsigned long compute_balloon_floor(void)
         *    8192       744    (1/16)
         *   32768      1512    (1/32)
         */
-       if (totalram_pages < MB2PAGES(128))
-               min_pages = MB2PAGES(8) + (totalram_pages >> 1);
-       else if (totalram_pages < MB2PAGES(512))
-               min_pages = MB2PAGES(40) + (totalram_pages >> 2);
-       else if (totalram_pages < MB2PAGES(2048))
-               min_pages = MB2PAGES(104) + (totalram_pages >> 3);
-       else if (totalram_pages < MB2PAGES(8192))
-               min_pages = MB2PAGES(232) + (totalram_pages >> 4);
+       if (nr_pages < MB2PAGES(128))
+               min_pages = MB2PAGES(8) + (nr_pages >> 1);
+       else if (nr_pages < MB2PAGES(512))
+               min_pages = MB2PAGES(40) + (nr_pages >> 2);
+       else if (nr_pages < MB2PAGES(2048))
+               min_pages = MB2PAGES(104) + (nr_pages >> 3);
+       else if (nr_pages < MB2PAGES(8192))
+               min_pages = MB2PAGES(232) + (nr_pages >> 4);
        else
-               min_pages = MB2PAGES(488) + (totalram_pages >> 5);
+               min_pages = MB2PAGES(488) + (nr_pages >> 5);
 #undef MB2PAGES
        return min_pages;
 }
index 9608681224e668d92ebe1c4b1b2004e61a930160..a4ec43093cb3a73bd87197aa9d72557cdbe93029 100644 (file)
@@ -146,15 +146,12 @@ static int invalidate_range_start_trampoline(struct ib_umem_odp *item,
 }
 
 static int ib_umem_notifier_invalidate_range_start(struct mmu_notifier *mn,
-                                                   struct mm_struct *mm,
-                                                   unsigned long start,
-                                                   unsigned long end,
-                                                   bool blockable)
+                               const struct mmu_notifier_range *range)
 {
        struct ib_ucontext_per_mm *per_mm =
                container_of(mn, struct ib_ucontext_per_mm, mn);
 
-       if (blockable)
+       if (range->blockable)
                down_read(&per_mm->umem_rwsem);
        else if (!down_read_trylock(&per_mm->umem_rwsem))
                return -EAGAIN;
@@ -169,9 +166,10 @@ static int ib_umem_notifier_invalidate_range_start(struct mmu_notifier *mn,
                return 0;
        }
 
-       return rbt_ib_umem_for_each_in_range(&per_mm->umem_tree, start, end,
+       return rbt_ib_umem_for_each_in_range(&per_mm->umem_tree, range->start,
+                                            range->end,
                                             invalidate_range_start_trampoline,
-                                            blockable, NULL);
+                                            range->blockable, NULL);
 }
 
 static int invalidate_range_end_trampoline(struct ib_umem_odp *item, u64 start,
@@ -182,9 +180,7 @@ static int invalidate_range_end_trampoline(struct ib_umem_odp *item, u64 start,
 }
 
 static void ib_umem_notifier_invalidate_range_end(struct mmu_notifier *mn,
-                                                 struct mm_struct *mm,
-                                                 unsigned long start,
-                                                 unsigned long end)
+                               const struct mmu_notifier_range *range)
 {
        struct ib_ucontext_per_mm *per_mm =
                container_of(mn, struct ib_ucontext_per_mm, mn);
@@ -192,8 +188,8 @@ static void ib_umem_notifier_invalidate_range_end(struct mmu_notifier *mn,
        if (unlikely(!per_mm->active))
                return;
 
-       rbt_ib_umem_for_each_in_range(&per_mm->umem_tree, start,
-                                     end,
+       rbt_ib_umem_for_each_in_range(&per_mm->umem_tree, range->start,
+                                     range->end,
                                      invalidate_range_end_trampoline, true, NULL);
        up_read(&per_mm->umem_rwsem);
 }
index 475b769e120ca3bb7ba6db662c5815cd1575a905..14d2a90964c3c38b1b3b43f3dbde887acc53daa6 100644 (file)
@@ -68,8 +68,7 @@ struct mmu_rb_handler {
 static unsigned long mmu_node_start(struct mmu_rb_node *);
 static unsigned long mmu_node_last(struct mmu_rb_node *);
 static int mmu_notifier_range_start(struct mmu_notifier *,
-                                    struct mm_struct *,
-                                    unsigned long, unsigned long, bool);
+               const struct mmu_notifier_range *);
 static struct mmu_rb_node *__mmu_rb_search(struct mmu_rb_handler *,
                                           unsigned long, unsigned long);
 static void do_remove(struct mmu_rb_handler *handler,
@@ -284,10 +283,7 @@ void hfi1_mmu_rb_remove(struct mmu_rb_handler *handler,
 }
 
 static int mmu_notifier_range_start(struct mmu_notifier *mn,
-                                    struct mm_struct *mm,
-                                    unsigned long start,
-                                    unsigned long end,
-                                    bool blockable)
+               const struct mmu_notifier_range *range)
 {
        struct mmu_rb_handler *handler =
                container_of(mn, struct mmu_rb_handler, mn);
@@ -297,10 +293,11 @@ static int mmu_notifier_range_start(struct mmu_notifier *mn,
        bool added = false;
 
        spin_lock_irqsave(&handler->lock, flags);
-       for (node = __mmu_int_rb_iter_first(root, start, end - 1);
+       for (node = __mmu_int_rb_iter_first(root, range->start, range->end-1);
             node; node = ptr) {
                /* Guard against node removal. */
-               ptr = __mmu_int_rb_iter_next(node, start, end - 1);
+               ptr = __mmu_int_rb_iter_next(node, range->start,
+                                            range->end - 1);
                trace_hfi1_mmu_mem_invalidate(node->addr, node->len);
                if (handler->ops->invalidate(handler->ops_arg, node)) {
                        __mmu_int_rb_remove(node, root);
index 0e9fcceaefd2c1e2517a625df7bd16eaace9cadf..1ecef76225a187174b0f9c48d1835eea769b8c7d 100644 (file)
@@ -1887,7 +1887,7 @@ static int __init dm_bufio_init(void)
        dm_bufio_allocated_vmalloc = 0;
        dm_bufio_current_allocated = 0;
 
-       mem = (__u64)mult_frac(totalram_pages - totalhigh_pages,
+       mem = (__u64)mult_frac(totalram_pages() - totalhigh_pages(),
                               DM_BUFIO_MEMORY_PERCENT, 100) << PAGE_SHIFT;
 
        if (mem > ULONG_MAX)
index 1ea73ace9b9e44831266aa2b92cde477f64afb3e..0ff22159a0ca96d6b9c831bdd8a1e8ba724b90a9 100644 (file)
@@ -2167,7 +2167,7 @@ static int crypt_wipe_key(struct crypt_config *cc)
 
 static void crypt_calculate_pages_per_client(void)
 {
-       unsigned long pages = (totalram_pages - totalhigh_pages) * DM_CRYPT_MEMORY_PERCENT / 100;
+       unsigned long pages = (totalram_pages() - totalhigh_pages()) * DM_CRYPT_MEMORY_PERCENT / 100;
 
        if (!dm_crypt_clients_n)
                return;
index 2b27abfa428d759e6020bc9f2fe26123cb478272..457200ca62878ee87b0cd5127540597454e7bbd9 100644 (file)
@@ -2843,7 +2843,7 @@ static int create_journal(struct dm_integrity_c *ic, char **error)
        journal_pages = roundup((__u64)ic->journal_sections * ic->journal_section_sectors,
                                PAGE_SIZE >> SECTOR_SHIFT) >> (PAGE_SHIFT - SECTOR_SHIFT);
        journal_desc_size = journal_pages * sizeof(struct page_list);
-       if (journal_pages >= totalram_pages - totalhigh_pages || journal_desc_size > ULONG_MAX) {
+       if (journal_pages >= totalram_pages() - totalhigh_pages() || journal_desc_size > ULONG_MAX) {
                *error = "Journal doesn't fit into memory";
                r = -ENOMEM;
                goto bad;
index 21de30b4e2a16051490ce5a2548c3711a3f0284e..45b92a3d9d8e17a493c11df5cbd85b0caacacf36 100644 (file)
@@ -85,7 +85,7 @@ static bool __check_shared_memory(size_t alloc_size)
        a = shared_memory_amount + alloc_size;
        if (a < shared_memory_amount)
                return false;
-       if (a >> PAGE_SHIFT > totalram_pages / DM_STATS_MEMORY_FACTOR)
+       if (a >> PAGE_SHIFT > totalram_pages() / DM_STATS_MEMORY_FACTOR)
                return false;
 #ifdef CONFIG_MMU
        if (a > (VMALLOC_END - VMALLOC_START) / DM_STATS_VMALLOC_FACTOR)
index 616f78b24a795ae1f555921b1220f159df692db3..b6602490a247c55429bea653785cca1c397cfec5 100644 (file)
@@ -855,7 +855,7 @@ static int mtk_vpu_probe(struct platform_device *pdev)
        /* Set PTCM to 96K and DTCM to 32K */
        vpu_cfg_writel(vpu, 0x2, VPU_TCM_CFG);
 
-       vpu->enable_4GB = !!(totalram_pages > (SZ_2G >> PAGE_SHIFT));
+       vpu->enable_4GB = !!(totalram_pages() > (SZ_2G >> PAGE_SHIFT));
        dev_info(dev, "4GB mode %u\n", vpu->enable_4GB);
 
        if (vpu->enable_4GB) {
index 18b8ed57c4ac7cd7079b4ee1b9bc643d61045c19..e0d97044d0e95b4465efd7e9d6bef89b48c303da 100644 (file)
@@ -201,23 +201,18 @@ static void scif_mmu_notifier_release(struct mmu_notifier *mn,
 }
 
 static int scif_mmu_notifier_invalidate_range_start(struct mmu_notifier *mn,
-                                                    struct mm_struct *mm,
-                                                    unsigned long start,
-                                                    unsigned long end,
-                                                    bool blockable)
+                                       const struct mmu_notifier_range *range)
 {
        struct scif_mmu_notif   *mmn;
 
        mmn = container_of(mn, struct scif_mmu_notif, ep_mmu_notifier);
-       scif_rma_destroy_tcw(mmn, start, end - start);
+       scif_rma_destroy_tcw(mmn, range->start, range->end - range->start);
 
        return 0;
 }
 
 static void scif_mmu_notifier_invalidate_range_end(struct mmu_notifier *mn,
-                                                  struct mm_struct *mm,
-                                                  unsigned long start,
-                                                  unsigned long end)
+                       const struct mmu_notifier_range *range)
 {
        /*
         * Nothing to do here, everything needed was done in
index 03b49d52092ef6b4c795a63a93b55871046d129b..ca2032afe035ba51a30d98c6e2736f0482e80b4f 100644 (file)
@@ -220,9 +220,7 @@ void gru_flush_all_tlb(struct gru_state *gru)
  * MMUOPS notifier callout functions
  */
 static int gru_invalidate_range_start(struct mmu_notifier *mn,
-                                      struct mm_struct *mm,
-                                      unsigned long start, unsigned long end,
-                                      bool blockable)
+                       const struct mmu_notifier_range *range)
 {
        struct gru_mm_struct *gms = container_of(mn, struct gru_mm_struct,
                                                 ms_notifier);
@@ -230,15 +228,14 @@ static int gru_invalidate_range_start(struct mmu_notifier *mn,
        STAT(mmu_invalidate_range);
        atomic_inc(&gms->ms_range_active);
        gru_dbg(grudev, "gms %p, start 0x%lx, end 0x%lx, act %d\n", gms,
-               start, end, atomic_read(&gms->ms_range_active));
-       gru_flush_tlb_range(gms, start, end - start);
+               range->start, range->end, atomic_read(&gms->ms_range_active));
+       gru_flush_tlb_range(gms, range->start, range->end - range->start);
 
        return 0;
 }
 
 static void gru_invalidate_range_end(struct mmu_notifier *mn,
-                                    struct mm_struct *mm, unsigned long start,
-                                    unsigned long end)
+                       const struct mmu_notifier_range *range)
 {
        struct gru_mm_struct *gms = container_of(mn, struct gru_mm_struct,
                                                 ms_notifier);
@@ -247,7 +244,8 @@ static void gru_invalidate_range_end(struct mmu_notifier *mn,
        (void)atomic_dec_and_test(&gms->ms_range_active);
 
        wake_up_all(&gms->ms_wait_queue);
-       gru_dbg(grudev, "gms %p, start 0x%lx, end 0x%lx\n", gms, start, end);
+       gru_dbg(grudev, "gms %p, start 0x%lx, end 0x%lx\n",
+               gms, range->start, range->end);
 }
 
 static void gru_release(struct mmu_notifier *mn, struct mm_struct *mm)
index 9b0b3fa4f8367c421abb1e58e3bf7b5e82b16aeb..e6126a4b95d3c92960d59775310bb11646eb1474 100644 (file)
@@ -570,7 +570,7 @@ static int vmballoon_send_get_target(struct vmballoon *b)
        unsigned long status;
        unsigned long limit;
 
-       limit = totalram_pages;
+       limit = totalram_pages();
 
        /* Ensure limit fits in 32-bits */
        if (limit != (u32)limit)
index f7019294740cf6ef2923c0b43e4048ee3a882546..bc2f700feef8abdad873197237f34f765055c22f 100644 (file)
@@ -309,8 +309,11 @@ static void pmem_release_queue(void *q)
        blk_cleanup_queue(q);
 }
 
-static void pmem_freeze_queue(void *q)
+static void pmem_freeze_queue(struct percpu_ref *ref)
 {
+       struct request_queue *q;
+
+       q = container_of(ref, typeof(*q), q_usage_counter);
        blk_freeze_queue_start(q);
 }
 
@@ -402,6 +405,7 @@ static int pmem_attach_disk(struct device *dev,
 
        pmem->pfn_flags = PFN_DEV;
        pmem->pgmap.ref = &q->q_usage_counter;
+       pmem->pgmap.kill = pmem_freeze_queue;
        if (is_nd_pfn(dev)) {
                if (setup_pagemap_fsdax(dev, &pmem->pgmap))
                        return -ENOMEM;
@@ -427,13 +431,6 @@ static int pmem_attach_disk(struct device *dev,
                memcpy(&bb_res, &nsio->res, sizeof(bb_res));
        }
 
-       /*
-        * At release time the queue must be frozen before
-        * devm_memremap_pages is unwound
-        */
-       if (devm_add_action_or_reset(dev, pmem_freeze_queue, q))
-               return -ENOMEM;
-
        if (IS_ERR(addr))
                return PTR_ERR(addr);
        pmem->virt_addr = addr;
index 714aac72df0ec88841a3ad9062a85a41963b19a2..8d2fc84119c6f854a2fbf6834f8eb2db16c334d0 100644 (file)
@@ -1243,7 +1243,7 @@ ccio_ioc_init(struct ioc *ioc)
        ** Hot-Plug/Removal of PCI cards. (aka PCI OLARD).
        */
 
-       iova_space_size = (u32) (totalram_pages / count_parisc_driver(&ccio_driver));
+       iova_space_size = (u32) (totalram_pages() / count_parisc_driver(&ccio_driver));
 
        /* limit IOVA space size to 1MB-1GB */
 
@@ -1282,7 +1282,7 @@ ccio_ioc_init(struct ioc *ioc)
 
        DBG_INIT("%s() hpa 0x%p mem %luMB IOV %dMB (%d bits)\n",
                        __func__, ioc->ioc_regs,
-                       (unsigned long) totalram_pages >> (20 - PAGE_SHIFT),
+                       (unsigned long) totalram_pages() >> (20 - PAGE_SHIFT),
                        iova_space_size>>20,
                        iov_order + PAGE_SHIFT);
 
index 452d306ce5cb8dffb848200d9ae9cb314580f034..42172eb322359343fd9e85a39a753d88d356b4cf 100644 (file)
@@ -1406,7 +1406,7 @@ sba_ioc_init(struct parisc_device *sba, struct ioc *ioc, int ioc_num)
        ** for DMA hints - ergo only 30 bits max.
        */
 
-       iova_space_size = (u32) (totalram_pages/global_ioc_cnt);
+       iova_space_size = (u32) (totalram_pages()/global_ioc_cnt);
 
        /* limit IOVA space size to 1MB-1GB */
        if (iova_space_size < (1 << (20 - PAGE_SHIFT))) {
@@ -1431,7 +1431,7 @@ sba_ioc_init(struct parisc_device *sba, struct ioc *ioc, int ioc_num)
        DBG_INIT("%s() hpa 0x%lx mem %ldMB IOV %dMB (%d bits)\n",
                        __func__,
                        ioc->ioc_hpa,
-                       (unsigned long) totalram_pages >> (20 - PAGE_SHIFT),
+                       (unsigned long) totalram_pages() >> (20 - PAGE_SHIFT),
                        iova_space_size>>20,
                        iov_order + PAGE_SHIFT);
 
index ae3c5b25dcc7d0fb80cae736e8090c137edf3420..a2eb25271c9697a9bd60c220be4d5273114cf98d 100644 (file)
@@ -82,10 +82,8 @@ static void pci_p2pdma_percpu_release(struct percpu_ref *ref)
        complete_all(&p2p->devmap_ref_done);
 }
 
-static void pci_p2pdma_percpu_kill(void *data)
+static void pci_p2pdma_percpu_kill(struct percpu_ref *ref)
 {
-       struct percpu_ref *ref = data;
-
        /*
         * pci_p2pdma_add_resource() may be called multiple times
         * by a driver and may register the percpu_kill devm action multiple
@@ -198,6 +196,7 @@ int pci_p2pdma_add_resource(struct pci_dev *pdev, int bar, size_t size,
        pgmap->type = MEMORY_DEVICE_PCI_P2PDMA;
        pgmap->pci_p2pdma_bus_offset = pci_bus_address(pdev, bar) -
                pci_resource_start(pdev, bar);
+       pgmap->kill = pci_p2pdma_percpu_kill;
 
        addr = devm_memremap_pages(&pdev->dev, pgmap);
        if (IS_ERR(addr)) {
@@ -211,11 +210,6 @@ int pci_p2pdma_add_resource(struct pci_dev *pdev, int bar, size_t size,
        if (error)
                goto pgmap_free;
 
-       error = devm_add_action_or_reset(&pdev->dev, pci_p2pdma_percpu_kill,
-                                         &pdev->p2pdma->devmap_ref);
-       if (error)
-               goto pgmap_free;
-
        pci_info(pdev, "added peer-to-peer DMA memory %pR\n",
                 &pgmap->res);
 
index 548bb02c0ca6b049aa0f9949368931b4460b7994..6cb0eebdff894327abd69732fa2da8f6b56ab765 100644 (file)
@@ -110,7 +110,7 @@ static int ion_system_heap_allocate(struct ion_heap *heap,
        unsigned long size_remaining = PAGE_ALIGN(size);
        unsigned int max_order = orders[0];
 
-       if (size / PAGE_SIZE > totalram_pages / 2)
+       if (size / PAGE_SIZE > totalram_pages() / 2)
                return -ENOMEM;
 
        INIT_LIST_HEAD(&pages);
index 221b7333d067bc95c262a3eee4913ea70dfde1bd..ceb5048de9a7eb8f2e861380964ebf3c15f8a23a 100644 (file)
@@ -352,7 +352,7 @@ static enum bp_state reserve_additional_memory(void)
        mutex_unlock(&balloon_mutex);
        /* add_memory_resource() requires the device_hotplug lock */
        lock_device_hotplug();
-       rc = add_memory_resource(nid, resource, memhp_auto_online);
+       rc = add_memory_resource(nid, resource);
        unlock_device_hotplug();
        mutex_lock(&balloon_mutex);
 
index b0b02a5011672b6670e136728b2c2a8a8f2ee68e..5efc5eee954488d492aff1ff640883bd531b0e01 100644 (file)
@@ -520,26 +520,26 @@ static int unmap_if_in_range(struct gntdev_grant_map *map,
 }
 
 static int mn_invl_range_start(struct mmu_notifier *mn,
-                               struct mm_struct *mm,
-                               unsigned long start, unsigned long end,
-                               bool blockable)
+                              const struct mmu_notifier_range *range)
 {
        struct gntdev_priv *priv = container_of(mn, struct gntdev_priv, mn);
        struct gntdev_grant_map *map;
        int ret = 0;
 
-       if (blockable)
+       if (range->blockable)
                mutex_lock(&priv->lock);
        else if (!mutex_trylock(&priv->lock))
                return -EAGAIN;
 
        list_for_each_entry(map, &priv->maps, next) {
-               ret = unmap_if_in_range(map, start, end, blockable);
+               ret = unmap_if_in_range(map, range->start, range->end,
+                                       range->blockable);
                if (ret)
                        goto out_unlock;
        }
        list_for_each_entry(map, &priv->freeable_maps, next) {
-               ret = unmap_if_in_range(map, start, end, blockable);
+               ret = unmap_if_in_range(map, range->start, range->end,
+                                       range->blockable);
                if (ret)
                        goto out_unlock;
        }
index 5165aa82bf7d47322f9abc1ad7e7fb161663b6e4..246f6122c9ee0f3fec46a1bdbc354e5ab10cbeb3 100644 (file)
@@ -189,7 +189,7 @@ static void selfballoon_process(struct work_struct *work)
        bool reset_timer = false;
 
        if (xen_selfballooning_enabled) {
-               cur_pages = totalram_pages;
+               cur_pages = totalram_pages();
                tgt_pages = cur_pages; /* default is no change */
                goal_pages = vm_memory_committed() +
                                totalreserve_pages +
@@ -227,7 +227,7 @@ static void selfballoon_process(struct work_struct *work)
                if (tgt_pages < floor_pages)
                        tgt_pages = floor_pages;
                balloon_set_new_target(tgt_pages +
-                       balloon_stats.current_pages - totalram_pages);
+                       balloon_stats.current_pages - totalram_pages());
                reset_timer = true;
        }
 #ifdef CONFIG_FRONTSWAP
@@ -569,7 +569,7 @@ int xen_selfballoon_init(bool use_selfballooning, bool use_frontswap_selfshrink)
         * much more reliably and response faster in some cases.
         */
        if (!selfballoon_reserved_mb) {
-               reserve_pages = totalram_pages / 10;
+               reserve_pages = totalram_pages() / 10;
                selfballoon_reserved_mb = PAGES2MB(reserve_pages);
        }
        schedule_delayed_work(&selfballoon_worker, selfballoon_interval * HZ);
index 43c508f99e3516fe413f53093f5b84a7db48b570..b906ff70c90f809ba1d7a4e6f38019c0df4da4e8 100644 (file)
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -415,7 +415,7 @@ static int aio_migratepage(struct address_space *mapping, struct page *new,
        BUG_ON(PageWriteback(old));
        get_page(new);
 
-       rc = migrate_page_move_mapping(mapping, new, old, NULL, mode, 1);
+       rc = migrate_page_move_mapping(mapping, new, old, mode, 1);
        if (rc != MIGRATEPAGE_SUCCESS) {
                put_page(new);
                goto out_unlock;
index e1886cc7048fbcea35fff0591b3679aa059d8a07..450be88cffef3a7e0b9d68973159ac1c2a2b00fc 100644 (file)
@@ -1992,6 +1992,7 @@ static const struct address_space_operations def_blk_aops = {
        .writepages     = blkdev_writepages,
        .releasepage    = blkdev_releasepage,
        .direct_IO      = blkdev_direct_IO,
+       .migratepage    = buffer_migrate_page_norefs,
        .is_dirty_writeback = buffer_check_dirty_writeback,
 };
 
index 79a265ba92006b309796c525a5a2db3e9522f076..dfb64a5211b61e19f0fd03e26093fa261d6591bf 100644 (file)
@@ -810,7 +810,7 @@ static inline int default_congestion_kb(void)
         * This allows larger machines to have larger/more transfers.
         * Limit the default to 256M
         */
-       congestion_kb = (16*int_sqrt(totalram_pages)) << (PAGE_SHIFT-10);
+       congestion_kb = (16*int_sqrt(totalram_pages())) << (PAGE_SHIFT-10);
        if (congestion_kb > 256*1024)
                congestion_kb = 256*1024;
 
index 48132eca3761de2b4cdf7c6c75ab8efda8cf7a26..262e14f299337803aa3656adca515722cb89796b 100644 (file)
--- a/fs/dax.c
+++ b/fs/dax.c
@@ -779,7 +779,8 @@ static void dax_entry_mkclean(struct address_space *mapping, pgoff_t index,
 
        i_mmap_lock_read(mapping);
        vma_interval_tree_foreach(vma, &mapping->i_mmap, index, index) {
-               unsigned long address, start, end;
+               struct mmu_notifier_range range;
+               unsigned long address;
 
                cond_resched();
 
@@ -793,7 +794,8 @@ static void dax_entry_mkclean(struct address_space *mapping, pgoff_t index,
                 * call mmu_notifier_invalidate_range_start() on our behalf
                 * before taking any lock.
                 */
-               if (follow_pte_pmd(vma->vm_mm, address, &start, &end, &ptep, &pmdp, &ptl))
+               if (follow_pte_pmd(vma->vm_mm, address, &range,
+                                  &ptep, &pmdp, &ptl))
                        continue;
 
                /*
@@ -835,7 +837,7 @@ unlock_pte:
                        pte_unmap_unlock(ptep, ptl);
                }
 
-               mmu_notifier_invalidate_range_end(vma->vm_mm, start, end);
+               mmu_notifier_invalidate_range_end(&range);
        }
        i_mmap_unlock_read(mapping);
 }
index b293cb3e27a228bd4549b71aed643116fb1c80bc..008b74eff00dafd4d501d615c5c36a6c5ee3eac8 100644 (file)
@@ -2738,7 +2738,7 @@ int f2fs_migrate_page(struct address_space *mapping,
         */
        extra_count = (atomic_written ? 1 : 0) - page_has_private(page);
        rc = migrate_page_move_mapping(mapping, newpage,
-                               page, NULL, mode, extra_count);
+                               page, mode, extra_count);
        if (rc != MIGRATEPAGE_SUCCESS) {
                if (atomic_written)
                        mutex_unlock(&fi->inmem_lock);
index e49af4caf15d92e3a33bbd02e4e551d778d8180e..5679e7fcb6b0a47d972b34a58478aeaa1456acf0 100644 (file)
@@ -380,10 +380,11 @@ void __init files_init(void)
 void __init files_maxfiles_init(void)
 {
        unsigned long n;
-       unsigned long memreserve = (totalram_pages - nr_free_pages()) * 3/2;
+       unsigned long nr_pages = totalram_pages();
+       unsigned long memreserve = (nr_pages - nr_free_pages()) * 3/2;
 
-       memreserve = min(memreserve, totalram_pages - 1);
-       n = ((totalram_pages - memreserve) * (PAGE_SIZE / 1024)) / 10;
+       memreserve = min(memreserve, nr_pages - 1);
+       n = ((nr_pages - memreserve) * (PAGE_SIZE / 1024)) / 10;
 
        files_stat.max_files = max_t(unsigned long, n, NR_FILE);
 }
index 568abed20eb20a097f43c108db7f274947ad604a..76baaa6be3934eef20c1c2a327a4f3b10c9bffed 100644 (file)
@@ -824,7 +824,7 @@ static const struct super_operations fuse_super_operations = {
 static void sanitize_global_limit(unsigned *limit)
 {
        if (*limit == 0)
-               *limit = ((totalram_pages << PAGE_SHIFT) >> 13) /
+               *limit = ((totalram_pages() << PAGE_SHIFT) >> 13) /
                         sizeof(struct fuse_req);
 
        if (*limit >= 1 << 16)
index 32920a10100e23fc60f53cf36c882278ae972cee..a2fcea5f8225c1ec0228623b1f332ee02bba9c1c 100644 (file)
@@ -383,17 +383,16 @@ hugetlb_vmdelete_list(struct rb_root_cached *root, pgoff_t start, pgoff_t end)
  * truncation is indicated by end of range being LLONG_MAX
  *     In this case, we first scan the range and release found pages.
  *     After releasing pages, hugetlb_unreserve_pages cleans up region/reserv
- *     maps and global counts.  Page faults can not race with truncation
- *     in this routine.  hugetlb_no_page() prevents page faults in the
- *     truncated range.  It checks i_size before allocation, and again after
- *     with the page table lock for the page held.  The same lock must be
- *     acquired to unmap a page.
+ *     maps and global counts.
  * hole punch is indicated if end is not LLONG_MAX
  *     In the hole punch case we scan the range and release found pages.
  *     Only when releasing a page is the associated region/reserv map
  *     deleted.  The region/reserv map for ranges without associated
- *     pages are not modified.  Page faults can race with hole punch.
- *     This is indicated if we find a mapped page.
+ *     pages are not modified.
+ *
+ * Callers of this routine must hold the i_mmap_rwsem in write mode to prevent
+ * races with page faults.
+ *
  * Note: If the passed end of range value is beyond the end of file, but
  * not LLONG_MAX this routine still performs a hole punch operation.
  */
@@ -423,32 +422,14 @@ static void remove_inode_hugepages(struct inode *inode, loff_t lstart,
 
                for (i = 0; i < pagevec_count(&pvec); ++i) {
                        struct page *page = pvec.pages[i];
-                       u32 hash;
 
                        index = page->index;
-                       hash = hugetlb_fault_mutex_hash(h, current->mm,
-                                                       &pseudo_vma,
-                                                       mapping, index, 0);
-                       mutex_lock(&hugetlb_fault_mutex_table[hash]);
-
                        /*
-                        * If page is mapped, it was faulted in after being
-                        * unmapped in caller.  Unmap (again) now after taking
-                        * the fault mutex.  The mutex will prevent faults
-                        * until we finish removing the page.
-                        *
-                        * This race can only happen in the hole punch case.
-                        * Getting here in a truncate operation is a bug.
+                        * A mapped page is impossible as callers should unmap
+                        * all references before calling.  And, i_mmap_rwsem
+                        * prevents the creation of additional mappings.
                         */
-                       if (unlikely(page_mapped(page))) {
-                               BUG_ON(truncate_op);
-
-                               i_mmap_lock_write(mapping);
-                               hugetlb_vmdelete_list(&mapping->i_mmap,
-                                       index * pages_per_huge_page(h),
-                                       (index + 1) * pages_per_huge_page(h));
-                               i_mmap_unlock_write(mapping);
-                       }
+                       VM_BUG_ON(page_mapped(page));
 
                        lock_page(page);
                        /*
@@ -470,7 +451,6 @@ static void remove_inode_hugepages(struct inode *inode, loff_t lstart,
                        }
 
                        unlock_page(page);
-                       mutex_unlock(&hugetlb_fault_mutex_table[hash]);
                }
                huge_pagevec_release(&pvec);
                cond_resched();
@@ -482,9 +462,20 @@ static void remove_inode_hugepages(struct inode *inode, loff_t lstart,
 
 static void hugetlbfs_evict_inode(struct inode *inode)
 {
+       struct address_space *mapping = inode->i_mapping;
        struct resv_map *resv_map;
 
+       /*
+        * The vfs layer guarantees that there are no other users of this
+        * inode.  Therefore, it would be safe to call remove_inode_hugepages
+        * without holding i_mmap_rwsem.  We acquire and hold here to be
+        * consistent with other callers.  Since there will be no contention
+        * on the semaphore, overhead is negligible.
+        */
+       i_mmap_lock_write(mapping);
        remove_inode_hugepages(inode, 0, LLONG_MAX);
+       i_mmap_unlock_write(mapping);
+
        resv_map = (struct resv_map *)inode->i_mapping->private_data;
        /* root inode doesn't have the resv_map, so we should check it */
        if (resv_map)
@@ -505,8 +496,8 @@ static int hugetlb_vmtruncate(struct inode *inode, loff_t offset)
        i_mmap_lock_write(mapping);
        if (!RB_EMPTY_ROOT(&mapping->i_mmap.rb_root))
                hugetlb_vmdelete_list(&mapping->i_mmap, pgoff, 0);
-       i_mmap_unlock_write(mapping);
        remove_inode_hugepages(inode, offset, LLONG_MAX);
+       i_mmap_unlock_write(mapping);
        return 0;
 }
 
@@ -540,8 +531,8 @@ static long hugetlbfs_punch_hole(struct inode *inode, loff_t offset, loff_t len)
                        hugetlb_vmdelete_list(&mapping->i_mmap,
                                                hole_start >> PAGE_SHIFT,
                                                hole_end  >> PAGE_SHIFT);
-               i_mmap_unlock_write(mapping);
                remove_inode_hugepages(inode, hole_start, hole_end);
+               i_mmap_unlock_write(mapping);
                inode_unlock(inode);
        }
 
@@ -624,7 +615,11 @@ static long hugetlbfs_fallocate(struct file *file, int mode, loff_t offset,
                /* addr is the offset within the file (zero based) */
                addr = index * hpage_size;
 
-               /* mutex taken here, fault path and hole punch */
+               /*
+                * fault mutex taken here, protects against fault path
+                * and hole punch.  inode_lock previously taken protects
+                * against truncation.
+                */
                hash = hugetlb_fault_mutex_hash(h, mm, &pseudo_vma, mapping,
                                                index, addr);
                mutex_lock(&hugetlb_fault_mutex_table[hash]);
index e87c288cd5ef6d3abe5aee1002f83fd2369986d6..3a0cd557b4cf8edfa0d068acd77f3ad9c88320e4 100644 (file)
@@ -563,7 +563,7 @@ iomap_migrate_page(struct address_space *mapping, struct page *newpage,
 {
        int ret;
 
-       ret = migrate_page_move_mapping(mapping, newpage, page, NULL, mode, 0);
+       ret = migrate_page_move_mapping(mapping, newpage, page, mode, 0);
        if (ret != MIGRATEPAGE_SUCCESS)
                return ret;
 
index 586726a590d88149fa0fe769de37fa7aa14033a2..4f15665f0ad1c8fdd72367b8e952aa6cb6d376c6 100644 (file)
@@ -2121,7 +2121,7 @@ int __init nfs_init_writepagecache(void)
         * This allows larger machines to have larger/more transfers.
         * Limit the default to 256M
         */
-       nfs_congestion_kb = (16*int_sqrt(totalram_pages)) << (PAGE_SHIFT-10);
+       nfs_congestion_kb = (16*int_sqrt(totalram_pages())) << (PAGE_SHIFT-10);
        if (nfs_congestion_kb > 256*1024)
                nfs_congestion_kb = 256*1024;
 
index e2fe0e9ce0df08973e400db9754c842005ace49a..da52b594362a4d58299f8dbba503bde35e75fe20 100644 (file)
@@ -99,7 +99,7 @@ static unsigned int
 nfsd_cache_size_limit(void)
 {
        unsigned int limit;
-       unsigned long low_pages = totalram_pages - totalhigh_pages;
+       unsigned long low_pages = totalram_pages() - totalhigh_pages();
 
        limit = (16 * int_sqrt(low_pages)) << (PAGE_SHIFT-10);
        return min_t(unsigned int, limit, 256*1024);
index ab172e5f51d91f874f4dfa19f03fb1600c37d01c..5becc8acc8f4d0d3e306e823e2a7269c6b3977f5 100644 (file)
@@ -47,7 +47,7 @@ static inline void *__ntfs_malloc(unsigned long size, gfp_t gfp_mask)
                return kmalloc(PAGE_SIZE, gfp_mask & ~__GFP_HIGHMEM);
                /* return (void *)__get_free_page(gfp_mask); */
        }
-       if (likely((size >> PAGE_SHIFT) < totalram_pages))
+       if (likely((size >> PAGE_SHIFT) < totalram_pages()))
                return __vmalloc(size, gfp_mask, PAGE_KERNEL);
        return NULL;
 }
index 99ee093182cbe1e867e7a3b817cdb4b127734daf..cc9b32b9db7cf6da37fa8db7807490c00304b2cf 100644 (file)
@@ -1,5 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0
-ccflags-y := -Ifs/ocfs2
+ccflags-y := -I$(src)
 
 obj-$(CONFIG_OCFS2_FS) +=      \
        ocfs2.o                 \
index 4ebbd57cbf8460da741860a4e657ab5fa60f6d7b..f9b84f7a3e4bb244f70b5a91de6fb62a7dd97224 100644 (file)
@@ -161,7 +161,6 @@ int ocfs2_read_blocks_sync(struct ocfs2_super *osb, u64 block,
 #endif
                }
 
-               clear_buffer_uptodate(bh);
                get_bh(bh); /* for end_buffer_read_sync() */
                bh->b_end_io = end_buffer_read_sync;
                submit_bh(REQ_OP_READ, 0, bh);
@@ -341,7 +340,6 @@ int ocfs2_read_blocks(struct ocfs2_caching_info *ci, u64 block, int nr,
                                continue;
                        }
 
-                       clear_buffer_uptodate(bh);
                        get_bh(bh); /* for end_buffer_read_sync() */
                        if (validate)
                                set_buffer_needs_validate(bh);
index 9b2ed62dd6385dd6625091d6336cc1018f08e733..f3c20b279eb2e6bc00b4fda0911d1a54ecbc641c 100644 (file)
@@ -582,9 +582,10 @@ bail:
 }
 
 static int o2hb_read_slots(struct o2hb_region *reg,
+                          unsigned int begin_slot,
                           unsigned int max_slots)
 {
-       unsigned int current_slot=0;
+       unsigned int current_slot = begin_slot;
        int status;
        struct o2hb_bio_wait_ctxt wc;
        struct bio *bio;
@@ -1093,9 +1094,14 @@ static int o2hb_highest_node(unsigned long *nodes, int numbits)
        return find_last_bit(nodes, numbits);
 }
 
+static int o2hb_lowest_node(unsigned long *nodes, int numbits)
+{
+       return find_first_bit(nodes, numbits);
+}
+
 static int o2hb_do_disk_heartbeat(struct o2hb_region *reg)
 {
-       int i, ret, highest_node;
+       int i, ret, highest_node, lowest_node;
        int membership_change = 0, own_slot_ok = 0;
        unsigned long configured_nodes[BITS_TO_LONGS(O2NM_MAX_NODES)];
        unsigned long live_node_bitmap[BITS_TO_LONGS(O2NM_MAX_NODES)];
@@ -1120,7 +1126,8 @@ static int o2hb_do_disk_heartbeat(struct o2hb_region *reg)
        }
 
        highest_node = o2hb_highest_node(configured_nodes, O2NM_MAX_NODES);
-       if (highest_node >= O2NM_MAX_NODES) {
+       lowest_node = o2hb_lowest_node(configured_nodes, O2NM_MAX_NODES);
+       if (highest_node >= O2NM_MAX_NODES || lowest_node >= O2NM_MAX_NODES) {
                mlog(ML_NOTICE, "o2hb: No configured nodes found!\n");
                ret = -EINVAL;
                goto bail;
@@ -1130,7 +1137,7 @@ static int o2hb_do_disk_heartbeat(struct o2hb_region *reg)
         * yet. Of course, if the node definitions have holes in them
         * then we're reading an empty slot anyway... Consider this
         * best-effort. */
-       ret = o2hb_read_slots(reg, highest_node + 1);
+       ret = o2hb_read_slots(reg, lowest_node, highest_node + 1);
        if (ret < 0) {
                mlog_errno(ret);
                goto bail;
@@ -1801,7 +1808,7 @@ static int o2hb_populate_slot_data(struct o2hb_region *reg)
        struct o2hb_disk_slot *slot;
        struct o2hb_disk_heartbeat_block *hb_block;
 
-       ret = o2hb_read_slots(reg, reg->hr_blocks);
+       ret = o2hb_read_slots(reg, 0, reg->hr_blocks);
        if (ret)
                goto out;
 
index bd1aab1f49a437ccf4e44b77ed7391c3c4d219d8..ef2854422a6e16f203ad3ba198b8b5316b20237f 100644 (file)
@@ -1,4 +1,4 @@
-ccflags-y := -Ifs/ocfs2
+ccflags-y := -I$(src)/..
 
 obj-$(CONFIG_OCFS2_FS_O2CB) += ocfs2_dlm.o
 
index eed3db8c5b49295a1f0fc1904b25a27acdf93274..33431a0296a32b4d98c09a224ccebe0001fba656 100644 (file)
@@ -1,4 +1,4 @@
-ccflags-y := -Ifs/ocfs2
+ccflags-y := -I$(src)/..
 
 obj-$(CONFIG_OCFS2_FS) += ocfs2_dlmfs.o
 
index 602c71f32740941e57d34a1aa21a3af48a4b60d4..b8fa1487cd85a40a901f8480075c2d58165548ed 100644 (file)
@@ -179,7 +179,7 @@ bail:
 static int dlmfs_file_release(struct inode *inode,
                              struct file *file)
 {
-       int level, status;
+       int level;
        struct dlmfs_inode_private *ip = DLMFS_I(inode);
        struct dlmfs_filp_private *fp = file->private_data;
 
@@ -188,7 +188,6 @@ static int dlmfs_file_release(struct inode *inode,
 
        mlog(0, "close called on inode %lu\n", inode->i_ino);
 
-       status = 0;
        if (fp) {
                level = fp->fp_lock_level;
                if (level != DLM_LOCK_IV)
index b63c97f4318e063889fe1ca203d19092c1abbedf..46fd3ef2cf212e4ae45ad0bf6f248b89612b9d6d 100644 (file)
@@ -1017,7 +1017,8 @@ void ocfs2_journal_shutdown(struct ocfs2_super *osb)
                        mlog_errno(status);
        }
 
-       if (status == 0) {
+       /* Shutdown the kernel journal system */
+       if (!jbd2_journal_destroy(journal->j_journal) && !status) {
                /*
                 * Do not toggle if flush was unsuccessful otherwise
                 * will leave dirty metadata in a "clean" journal
@@ -1026,9 +1027,6 @@ void ocfs2_journal_shutdown(struct ocfs2_super *osb)
                if (status < 0)
                        mlog_errno(status);
        }
-
-       /* Shutdown the kernel journal system */
-       jbd2_journal_destroy(journal->j_journal);
        journal->j_journal = NULL;
 
        OCFS2_I(inode)->ip_open_count--;
index 7642b6712c39e1812d0f7b23016bfe21142dcb85..58973e4d24715747cc90918025a3140b85471fae 100644 (file)
@@ -345,13 +345,18 @@ int ocfs2_load_local_alloc(struct ocfs2_super *osb)
        if (num_used
            || alloc->id1.bitmap1.i_used
            || alloc->id1.bitmap1.i_total
-           || la->la_bm_off)
-               mlog(ML_ERROR, "Local alloc hasn't been recovered!\n"
+           || la->la_bm_off) {
+               mlog(ML_ERROR, "inconsistent detected, clean journal with"
+                    " unrecovered local alloc, please run fsck.ocfs2!\n"
                     "found = %u, set = %u, taken = %u, off = %u\n",
                     num_used, le32_to_cpu(alloc->id1.bitmap1.i_used),
                     le32_to_cpu(alloc->id1.bitmap1.i_total),
                     OCFS2_LOCAL_ALLOC(alloc)->la_bm_off);
 
+               status = -EINVAL;
+               goto bail;
+       }
+
        osb->local_alloc_bh = alloc_bh;
        osb->local_alloc_state = OCFS2_LA_ENABLED;
 
@@ -835,7 +840,7 @@ static int ocfs2_local_alloc_find_clear_bits(struct ocfs2_super *osb,
                                     u32 *numbits,
                                     struct ocfs2_alloc_reservation *resv)
 {
-       int numfound = 0, bitoff, left, startoff, lastzero;
+       int numfound = 0, bitoff, left, startoff;
        int local_resv = 0;
        struct ocfs2_alloc_reservation r;
        void *bitmap = NULL;
@@ -873,7 +878,6 @@ static int ocfs2_local_alloc_find_clear_bits(struct ocfs2_super *osb,
        bitmap = OCFS2_LOCAL_ALLOC(alloc)->la_bitmap;
 
        numfound = bitoff = startoff = 0;
-       lastzero = -1;
        left = le32_to_cpu(alloc->id1.bitmap1.i_total);
        while ((bitoff = ocfs2_find_next_zero_bit(bitmap, left, startoff)) != -1) {
                if (bitoff == left) {
index 0ceb3b6b37e7310ed12d8d7f4215efe3b4c8a0a8..9d428d5a0ac88c4a2ca65f3d74eba922ee72f3a8 100644 (file)
@@ -392,6 +392,15 @@ static inline void task_core_dumping(struct seq_file *m, struct mm_struct *mm)
        seq_putc(m, '\n');
 }
 
+static inline void task_thp_status(struct seq_file *m, struct mm_struct *mm)
+{
+       bool thp_enabled = IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE);
+
+       if (thp_enabled)
+               thp_enabled = !test_bit(MMF_DISABLE_THP, &mm->flags);
+       seq_printf(m, "THP_enabled:\t%d\n", thp_enabled);
+}
+
 int proc_pid_status(struct seq_file *m, struct pid_namespace *ns,
                        struct pid *pid, struct task_struct *task)
 {
@@ -406,6 +415,7 @@ int proc_pid_status(struct seq_file *m, struct pid_namespace *ns,
        if (mm) {
                task_mem(m, mm);
                task_core_dumping(m, mm);
+               task_thp_status(m, mm);
                mmput(mm);
        }
        task_sig(m, task);
index ce34654794472d0a7b8c2574340c18cc7d594f7a..d7fd1ca807d2c32ca28c78bd852d50b66e001822 100644 (file)
@@ -530,7 +530,7 @@ static const struct file_operations proc_lstats_operations = {
 static int proc_oom_score(struct seq_file *m, struct pid_namespace *ns,
                          struct pid *pid, struct task_struct *task)
 {
-       unsigned long totalpages = totalram_pages + total_swap_pages;
+       unsigned long totalpages = totalram_pages() + total_swap_pages;
        unsigned long points = 0;
 
        points = oom_badness(task, NULL, NULL, totalpages) *
index 6c517b11acf829b5a1e2729f9d4748cb9cd56025..40b05e0d427464aef7670d299b059aa50b322e94 100644 (file)
@@ -46,7 +46,7 @@ static ssize_t kpagecount_read(struct file *file, char __user *buf,
                        ppage = pfn_to_page(pfn);
                else
                        ppage = NULL;
-               if (!ppage || PageSlab(ppage))
+               if (!ppage || PageSlab(ppage) || page_has_type(ppage))
                        pcount = 0;
                else
                        pcount = page_mapcount(ppage);
index 47c3764c469b01c24db489d38020e9bf0f021456..f0ec9edab2f31858c5928b5b425d21192ec60466 100644 (file)
@@ -790,6 +790,8 @@ static int show_smap(struct seq_file *m, void *v)
 
        __show_smap(m, &mss);
 
+       seq_printf(m, "THPeligible:    %d\n", transparent_hugepage_enabled(vma));
+
        if (arch_pkeys_enabled())
                seq_printf(m, "ProtectionKey:  %8u\n", vma_pkey(vma));
        show_smap_vma_flags(m, vma);
@@ -1096,6 +1098,7 @@ static ssize_t clear_refs_write(struct file *file, const char __user *buf,
                return -ESRCH;
        mm = get_task_mm(task);
        if (mm) {
+               struct mmu_notifier_range range;
                struct clear_refs_private cp = {
                        .type = type,
                };
@@ -1139,11 +1142,13 @@ static ssize_t clear_refs_write(struct file *file, const char __user *buf,
                                downgrade_write(&mm->mmap_sem);
                                break;
                        }
-                       mmu_notifier_invalidate_range_start(mm, 0, -1);
+
+                       mmu_notifier_range_init(&range, mm, 0, -1UL);
+                       mmu_notifier_invalidate_range_start(&range);
                }
                walk_page_range(0, mm->highest_vm_end, &clear_refs_walk);
                if (type == CLEAR_REFS_SOFT_DIRTY)
-                       mmu_notifier_invalidate_range_end(mm, 0, -1);
+                       mmu_notifier_invalidate_range_end(&range);
                tlb_finish_mmu(&tlb, 0, -1);
                up_read(&mm->mmap_sem);
 out_mm:
index 1b78f2e09218bd3fcf44f2772c47af54347a1bc1..5d2ffb1a45fcfcc37cd857a613484aee99da13aa 100644 (file)
@@ -1481,7 +1481,7 @@ static int ubifs_migrate_page(struct address_space *mapping,
 {
        int rc;
 
-       rc = migrate_page_move_mapping(mapping, newpage, page, NULL, mode, 0);
+       rc = migrate_page_move_mapping(mapping, newpage, page, mode, 0);
        if (rc != MIGRATEPAGE_SUCCESS)
                return rc;
 
index 59dc280470305175dd765a65c226ba61cac15599..89800fc7dc9d562cd3557988adc766fa41c51209 100644 (file)
@@ -53,7 +53,7 @@ struct userfaultfd_ctx {
        /* a refile sequence protected by fault_pending_wqh lock */
        struct seqcount refile_seq;
        /* pseudo fd refcounting */
-       atomic_t refcount;
+       refcount_t refcount;
        /* userfaultfd syscall flags */
        unsigned int flags;
        /* features requested from the userspace */
@@ -140,8 +140,7 @@ out:
  */
 static void userfaultfd_ctx_get(struct userfaultfd_ctx *ctx)
 {
-       if (!atomic_inc_not_zero(&ctx->refcount))
-               BUG();
+       refcount_inc(&ctx->refcount);
 }
 
 /**
@@ -154,7 +153,7 @@ static void userfaultfd_ctx_get(struct userfaultfd_ctx *ctx)
  */
 static void userfaultfd_ctx_put(struct userfaultfd_ctx *ctx)
 {
-       if (atomic_dec_and_test(&ctx->refcount)) {
+       if (refcount_dec_and_test(&ctx->refcount)) {
                VM_BUG_ON(spin_is_locked(&ctx->fault_pending_wqh.lock));
                VM_BUG_ON(waitqueue_active(&ctx->fault_pending_wqh));
                VM_BUG_ON(spin_is_locked(&ctx->fault_wqh.lock));
@@ -686,7 +685,7 @@ int dup_userfaultfd(struct vm_area_struct *vma, struct list_head *fcs)
                        return -ENOMEM;
                }
 
-               atomic_set(&ctx->refcount, 1);
+               refcount_set(&ctx->refcount, 1);
                ctx->flags = octx->flags;
                ctx->state = UFFD_STATE_RUNNING;
                ctx->features = octx->features;
@@ -736,10 +735,18 @@ void mremap_userfaultfd_prep(struct vm_area_struct *vma,
        struct userfaultfd_ctx *ctx;
 
        ctx = vma->vm_userfaultfd_ctx.ctx;
-       if (ctx && (ctx->features & UFFD_FEATURE_EVENT_REMAP)) {
+
+       if (!ctx)
+               return;
+
+       if (ctx->features & UFFD_FEATURE_EVENT_REMAP) {
                vm_ctx->ctx = ctx;
                userfaultfd_ctx_get(ctx);
                WRITE_ONCE(ctx->mmap_changing, true);
+       } else {
+               /* Drop uffd context if remap feature not enabled */
+               vma->vm_userfaultfd_ctx = NULL_VM_UFFD_CTX;
+               vma->vm_flags &= ~(VM_UFFD_WP | VM_UFFD_MISSING);
        }
 }
 
@@ -1927,7 +1934,7 @@ SYSCALL_DEFINE1(userfaultfd, int, flags)
        if (!ctx)
                return -ENOMEM;
 
-       atomic_set(&ctx->refcount, 1);
+       refcount_set(&ctx->refcount, 1);
        ctx->flags = flags;
        ctx->features = 0;
        ctx->state = UFFD_STATE_WAIT_API;
index 296c65442f001810923fd3c3dc028cb2ac558fb1..95a159a4137fb645f3fbe0ed5e4278d55ad58fd2 100644 (file)
@@ -8,6 +8,7 @@ enum {
        EI_ETYPE_NULL,          /* Return NULL if failure */
        EI_ETYPE_ERRNO,         /* Return -ERRNO if failure */
        EI_ETYPE_ERRNO_NULL,    /* Return -ERRNO or NULL if failure */
+       EI_ETYPE_TRUE,          /* Return true if failure */
 };
 
 struct error_injection_entry {
index a9cac82e9a7aec978df220a104af627a477dca8a..05e61e6c843f3d82f935c4bdefbc721f659a4ea7 100644 (file)
@@ -1057,6 +1057,7 @@ int pud_set_huge(pud_t *pud, phys_addr_t addr, pgprot_t prot);
 int pmd_set_huge(pmd_t *pmd, phys_addr_t addr, pgprot_t prot);
 int pud_clear_huge(pud_t *pud);
 int pmd_clear_huge(pmd_t *pmd);
+int p4d_free_pud_page(p4d_t *p4d, unsigned long addr);
 int pud_free_pmd_page(pud_t *pud, unsigned long addr);
 int pmd_free_pte_page(pmd_t *pmd, unsigned long addr);
 #else  /* !CONFIG_HAVE_ARCH_HUGE_VMAP */
@@ -1084,6 +1085,10 @@ static inline int pmd_clear_huge(pmd_t *pmd)
 {
        return 0;
 }
+static inline int p4d_free_pud_page(p4d_t *p4d, unsigned long addr)
+{
+       return 0;
+}
 static inline int pud_free_pmd_page(pud_t *pud, unsigned long addr)
 {
        return 0;
index 9a6bc0951cfaf1559607ea2a6a6df6f1abb106f0..c31157135598150332d3aa193764c39e18f247b2 100644 (file)
@@ -258,6 +258,14 @@ static inline void wb_get(struct bdi_writeback *wb)
  */
 static inline void wb_put(struct bdi_writeback *wb)
 {
+       if (WARN_ON_ONCE(!wb->bdi)) {
+               /*
+                * A driver bug might cause a file to be removed before bdi was
+                * initialized.
+                */
+               return;
+       }
+
        if (wb != &wb->bdi->wb)
                percpu_ref_put(&wb->refcnt);
 }
index 3e7dafb3ea8099285d4185df113f2c89a0426e06..39f668d5066b0a8f4228b4d1504ae97760313944 100644 (file)
 /* all clang versions usable with the kernel support KASAN ABI version 5 */
 #define KASAN_ABI_VERSION 5
 
+#if __has_feature(address_sanitizer) || __has_feature(hwaddress_sanitizer)
 /* emulate gcc's __SANITIZE_ADDRESS__ flag */
-#if __has_feature(address_sanitizer)
 #define __SANITIZE_ADDRESS__
+#define __no_sanitize_address \
+               __attribute__((no_sanitize("address", "hwaddress")))
+#else
+#define __no_sanitize_address
 #endif
 
 /*
index 2010493e1040846c999804e2e157233c27ccef60..5776da43da9766a842e6170479deb2037418fcec 100644 (file)
 #define KASAN_ABI_VERSION 3
 #endif
 
+#if __has_attribute(__no_sanitize_address__)
+#define __no_sanitize_address __attribute__((no_sanitize_address))
+#else
+#define __no_sanitize_address
+#endif
+
 #if GCC_VERSION >= 50100
 #define COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW 1
 #endif
index fe07b680dd4a3d2c2c8d8f925051faa005a57020..19f32b0c29af3ded16736b43b33604f910bac3dc 100644 (file)
  */
 #define __noreturn                      __attribute__((__noreturn__))
 
-/*
- * Optional: only supported since gcc >= 4.8
- * Optional: not supported by icc
- *
- *   gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-no_005fsanitize_005faddress-function-attribute
- * clang: https://clang.llvm.org/docs/AttributeReference.html#no-sanitize-address-no-address-safety-analysis
- */
-#if __has_attribute(__no_sanitize_address__)
-# define __no_sanitize_address          __attribute__((__no_sanitize_address__))
-#else
-# define __no_sanitize_address
-#endif
-
 /*
  *   gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Type-Attributes.html#index-packed-type-attribute
  * clang: https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html#index-packed-variable-attribute
index 6d52ce6af4ff3ca63bf80b976e4bc36d580c3992..811c77743dad2870282e6c3c85e8f238f8643767 100644 (file)
@@ -3269,8 +3269,12 @@ extern int generic_check_addressable(unsigned, u64);
 extern int buffer_migrate_page(struct address_space *,
                                struct page *, struct page *,
                                enum migrate_mode);
+extern int buffer_migrate_page_norefs(struct address_space *,
+                               struct page *, struct page *,
+                               enum migrate_mode);
 #else
 #define buffer_migrate_page NULL
+#define buffer_migrate_page_norefs NULL
 #endif
 
 extern int setattr_prepare(struct dentry *, struct iattr *);
index 0705164f928c949720d9a0927f1564119146c3fa..5f5e25fd61491173894ea5255e28f5e154b348f7 100644 (file)
@@ -81,7 +81,7 @@ struct vm_area_struct;
  *
  * %__GFP_HARDWALL enforces the cpuset memory allocation policy.
  *
- * %__GFP_THISNODE forces the allocation to be satisified from the requested
+ * %__GFP_THISNODE forces the allocation to be satisfied from the requested
  * node with no fallbacks or placement policy enforcements.
  *
  * %__GFP_ACCOUNT causes the allocation to be accounted to kmemcg.
index 0690679832d45fda5c4c945dc5e96f980eae5ca1..ea5cdbd8c2c326cd6f8702bfc2e6aa2e9fbca2c0 100644 (file)
@@ -36,7 +36,31 @@ static inline void invalidate_kernel_vmap_range(void *vaddr, int size)
 
 /* declarations for linux/mm/highmem.c */
 unsigned int nr_free_highpages(void);
-extern unsigned long totalhigh_pages;
+extern atomic_long_t _totalhigh_pages;
+static inline unsigned long totalhigh_pages(void)
+{
+       return (unsigned long)atomic_long_read(&_totalhigh_pages);
+}
+
+static inline void totalhigh_pages_inc(void)
+{
+       atomic_long_inc(&_totalhigh_pages);
+}
+
+static inline void totalhigh_pages_dec(void)
+{
+       atomic_long_dec(&_totalhigh_pages);
+}
+
+static inline void totalhigh_pages_add(long count)
+{
+       atomic_long_add(count, &_totalhigh_pages);
+}
+
+static inline void totalhigh_pages_set(long val)
+{
+       atomic_long_set(&_totalhigh_pages, val);
+}
 
 void kmap_flush_unused(void);
 
@@ -51,7 +75,7 @@ static inline struct page *kmap_to_page(void *addr)
        return virt_to_page(addr);
 }
 
-#define totalhigh_pages 0UL
+static inline unsigned long totalhigh_pages(void) { return 0UL; }
 
 #ifndef ARCH_HAS_KMAP
 static inline void *kmap(struct page *page)
index c6fb869a81c0e1ca3b6086bb709ba493532bad8a..66f9ebbb1df3ffb91120bcaae4987ced0781e98e 100644 (file)
@@ -69,6 +69,7 @@
 #define LINUX_HMM_H
 
 #include <linux/kconfig.h>
+#include <asm/pgtable.h>
 
 #if IS_ENABLED(CONFIG_HMM)
 
@@ -486,6 +487,7 @@ struct hmm_devmem_ops {
  * @device: device to bind resource to
  * @ops: memory operations callback
  * @ref: per CPU refcount
+ * @page_fault: callback when CPU fault on an unaddressable device page
  *
  * This an helper structure for device drivers that do not wish to implement
  * the gory details related to hotplugging new memoy and allocating struct
@@ -493,7 +495,28 @@ struct hmm_devmem_ops {
  *
  * Device drivers can directly use ZONE_DEVICE memory on their own if they
  * wish to do so.
+ *
+ * The page_fault() callback must migrate page back, from device memory to
+ * system memory, so that the CPU can access it. This might fail for various
+ * reasons (device issues,  device have been unplugged, ...). When such error
+ * conditions happen, the page_fault() callback must return VM_FAULT_SIGBUS and
+ * set the CPU page table entry to "poisoned".
+ *
+ * Note that because memory cgroup charges are transferred to the device memory,
+ * this should never fail due to memory restrictions. However, allocation
+ * of a regular system page might still fail because we are out of memory. If
+ * that happens, the page_fault() callback must return VM_FAULT_OOM.
+ *
+ * The page_fault() callback can also try to migrate back multiple pages in one
+ * chunk, as an optimization. It must, however, prioritize the faulting address
+ * over all the others.
  */
+typedef int (*dev_page_fault_t)(struct vm_area_struct *vma,
+                               unsigned long addr,
+                               const struct page *page,
+                               unsigned int flags,
+                               pmd_t *pmdp);
+
 struct hmm_devmem {
        struct completion               completion;
        unsigned long                   pfn_first;
@@ -503,6 +526,7 @@ struct hmm_devmem {
        struct dev_pagemap              pagemap;
        const struct hmm_devmem_ops     *ops;
        struct percpu_ref               ref;
+       dev_page_fault_t                page_fault;
 };
 
 /*
@@ -512,8 +536,7 @@ struct hmm_devmem {
  * enough and allocate struct page for it.
  *
  * The device driver can wrap the hmm_devmem struct inside a private device
- * driver struct. The device driver must call hmm_devmem_remove() before the
- * device goes away and before freeing the hmm_devmem struct memory.
+ * driver struct.
  */
 struct hmm_devmem *hmm_devmem_add(const struct hmm_devmem_ops *ops,
                                  struct device *device,
@@ -521,7 +544,6 @@ struct hmm_devmem *hmm_devmem_add(const struct hmm_devmem_ops *ops,
 struct hmm_devmem *hmm_devmem_add_resource(const struct hmm_devmem_ops *ops,
                                           struct device *device,
                                           struct resource *res);
-void hmm_devmem_remove(struct hmm_devmem *devmem);
 
 /*
  * hmm_devmem_page_set_drvdata - set per-page driver data field
index 4663ee96cf5981198de6b6c841faf5331ff67b07..381e872bfde04c86aa68ba6c15f18bcc09e4b0b5 100644 (file)
@@ -93,7 +93,11 @@ extern bool is_vma_temporary_stack(struct vm_area_struct *vma);
 
 extern unsigned long transparent_hugepage_flags;
 
-static inline bool transparent_hugepage_enabled(struct vm_area_struct *vma)
+/*
+ * to be used on vmas which are known to support THP.
+ * Use transparent_hugepage_enabled otherwise
+ */
+static inline bool __transparent_hugepage_enabled(struct vm_area_struct *vma)
 {
        if (vma->vm_flags & VM_NOHUGEPAGE)
                return false;
@@ -117,6 +121,8 @@ static inline bool transparent_hugepage_enabled(struct vm_area_struct *vma)
        return false;
 }
 
+bool transparent_hugepage_enabled(struct vm_area_struct *vma);
+
 #define transparent_hugepage_use_zero_page()                           \
        (transparent_hugepage_flags &                                   \
         (1<<TRANSPARENT_HUGEPAGE_USE_ZERO_PAGE_FLAG))
@@ -257,6 +263,11 @@ static inline bool thp_migration_supported(void)
 
 #define hpage_nr_pages(x) 1
 
+static inline bool __transparent_hugepage_enabled(struct vm_area_struct *vma)
+{
+       return false;
+}
+
 static inline bool transparent_hugepage_enabled(struct vm_area_struct *vma)
 {
        return false;
index 46aae129917c69d2f314365281eb281c062cb609..b40ea104dd369819159ea1265ca6e20584ea4ef1 100644 (file)
@@ -14,13 +14,13 @@ struct task_struct;
 #include <asm/kasan.h>
 #include <asm/pgtable.h>
 
-extern unsigned char kasan_zero_page[PAGE_SIZE];
-extern pte_t kasan_zero_pte[PTRS_PER_PTE];
-extern pmd_t kasan_zero_pmd[PTRS_PER_PMD];
-extern pud_t kasan_zero_pud[PTRS_PER_PUD];
-extern p4d_t kasan_zero_p4d[MAX_PTRS_PER_P4D];
+extern unsigned char kasan_early_shadow_page[PAGE_SIZE];
+extern pte_t kasan_early_shadow_pte[PTRS_PER_PTE];
+extern pmd_t kasan_early_shadow_pmd[PTRS_PER_PMD];
+extern pud_t kasan_early_shadow_pud[PTRS_PER_PUD];
+extern p4d_t kasan_early_shadow_p4d[MAX_PTRS_PER_P4D];
 
-int kasan_populate_zero_shadow(const void *shadow_start,
+int kasan_populate_early_shadow(const void *shadow_start,
                                const void *shadow_end);
 
 static inline void *kasan_mem_to_shadow(const void *addr)
@@ -45,22 +45,24 @@ void kasan_free_pages(struct page *page, unsigned int order);
 
 void kasan_cache_create(struct kmem_cache *cache, unsigned int *size,
                        slab_flags_t *flags);
-void kasan_cache_shrink(struct kmem_cache *cache);
-void kasan_cache_shutdown(struct kmem_cache *cache);
 
 void kasan_poison_slab(struct page *page);
 void kasan_unpoison_object_data(struct kmem_cache *cache, void *object);
 void kasan_poison_object_data(struct kmem_cache *cache, void *object);
-void kasan_init_slab_obj(struct kmem_cache *cache, const void *object);
+void * __must_check kasan_init_slab_obj(struct kmem_cache *cache,
+                                       const void *object);
 
-void kasan_kmalloc_large(const void *ptr, size_t size, gfp_t flags);
+void * __must_check kasan_kmalloc_large(const void *ptr, size_t size,
+                                               gfp_t flags);
 void kasan_kfree_large(void *ptr, unsigned long ip);
 void kasan_poison_kfree(void *ptr, unsigned long ip);
-void kasan_kmalloc(struct kmem_cache *s, const void *object, size_t size,
-                 gfp_t flags);
-void kasan_krealloc(const void *object, size_t new_size, gfp_t flags);
+void * __must_check kasan_kmalloc(struct kmem_cache *s, const void *object,
+                                       size_t size, gfp_t flags);
+void * __must_check kasan_krealloc(const void *object, size_t new_size,
+                                       gfp_t flags);
 
-void kasan_slab_alloc(struct kmem_cache *s, void *object, gfp_t flags);
+void * __must_check kasan_slab_alloc(struct kmem_cache *s, void *object,
+                                       gfp_t flags);
 bool kasan_slab_free(struct kmem_cache *s, void *object, unsigned long ip);
 
 struct kasan_cache {
@@ -97,27 +99,40 @@ static inline void kasan_free_pages(struct page *page, unsigned int order) {}
 static inline void kasan_cache_create(struct kmem_cache *cache,
                                      unsigned int *size,
                                      slab_flags_t *flags) {}
-static inline void kasan_cache_shrink(struct kmem_cache *cache) {}
-static inline void kasan_cache_shutdown(struct kmem_cache *cache) {}
 
 static inline void kasan_poison_slab(struct page *page) {}
 static inline void kasan_unpoison_object_data(struct kmem_cache *cache,
                                        void *object) {}
 static inline void kasan_poison_object_data(struct kmem_cache *cache,
                                        void *object) {}
-static inline void kasan_init_slab_obj(struct kmem_cache *cache,
-                               const void *object) {}
+static inline void *kasan_init_slab_obj(struct kmem_cache *cache,
+                               const void *object)
+{
+       return (void *)object;
+}
 
-static inline void kasan_kmalloc_large(void *ptr, size_t size, gfp_t flags) {}
+static inline void *kasan_kmalloc_large(void *ptr, size_t size, gfp_t flags)
+{
+       return ptr;
+}
 static inline void kasan_kfree_large(void *ptr, unsigned long ip) {}
 static inline void kasan_poison_kfree(void *ptr, unsigned long ip) {}
-static inline void kasan_kmalloc(struct kmem_cache *s, const void *object,
-                               size_t size, gfp_t flags) {}
-static inline void kasan_krealloc(const void *object, size_t new_size,
-                                gfp_t flags) {}
+static inline void *kasan_kmalloc(struct kmem_cache *s, const void *object,
+                               size_t size, gfp_t flags)
+{
+       return (void *)object;
+}
+static inline void *kasan_krealloc(const void *object, size_t new_size,
+                                gfp_t flags)
+{
+       return (void *)object;
+}
 
-static inline void kasan_slab_alloc(struct kmem_cache *s, void *object,
-                                  gfp_t flags) {}
+static inline void *kasan_slab_alloc(struct kmem_cache *s, void *object,
+                                  gfp_t flags)
+{
+       return object;
+}
 static inline bool kasan_slab_free(struct kmem_cache *s, void *object,
                                   unsigned long ip)
 {
@@ -140,4 +155,40 @@ static inline size_t kasan_metadata_size(struct kmem_cache *cache) { return 0; }
 
 #endif /* CONFIG_KASAN */
 
+#ifdef CONFIG_KASAN_GENERIC
+
+#define KASAN_SHADOW_INIT 0
+
+void kasan_cache_shrink(struct kmem_cache *cache);
+void kasan_cache_shutdown(struct kmem_cache *cache);
+
+#else /* CONFIG_KASAN_GENERIC */
+
+static inline void kasan_cache_shrink(struct kmem_cache *cache) {}
+static inline void kasan_cache_shutdown(struct kmem_cache *cache) {}
+
+#endif /* CONFIG_KASAN_GENERIC */
+
+#ifdef CONFIG_KASAN_SW_TAGS
+
+#define KASAN_SHADOW_INIT 0xFF
+
+void kasan_init_tags(void);
+
+void *kasan_reset_tag(const void *addr);
+
+void kasan_report(unsigned long addr, size_t size,
+               bool is_write, unsigned long ip);
+
+#else /* CONFIG_KASAN_SW_TAGS */
+
+static inline void kasan_init_tags(void) { }
+
+static inline void *kasan_reset_tag(const void *addr)
+{
+       return (void *)addr;
+}
+
+#endif /* CONFIG_KASAN_SW_TAGS */
+
 #endif /* LINUX_KASAN_H */
index aee299a6aa76d328f4d0bcf3494a5ad93b496ee9..64c41cf455906ab750d042f93410fa0c4c5aded6 100644 (file)
@@ -154,7 +154,6 @@ void __next_mem_range_rev(u64 *idx, int nid, enum memblock_flags flags,
 void __next_reserved_mem_region(u64 *idx, phys_addr_t *out_start,
                                phys_addr_t *out_end);
 
-void __memblock_free_early(phys_addr_t base, phys_addr_t size);
 void __memblock_free_late(phys_addr_t base, phys_addr_t size);
 
 /**
@@ -320,6 +319,7 @@ static inline int memblock_get_region_node(const struct memblock_region *r)
 /* Flags for memblock allocation APIs */
 #define MEMBLOCK_ALLOC_ANYWHERE        (~(phys_addr_t)0)
 #define MEMBLOCK_ALLOC_ACCESSIBLE      0
+#define MEMBLOCK_ALLOC_KASAN           1
 
 /* We are using top down, so it is safe to use 0 here */
 #define MEMBLOCK_LOW_LIMIT 0
@@ -414,13 +414,13 @@ static inline void * __init memblock_alloc_node_nopanic(phys_addr_t size,
 static inline void __init memblock_free_early(phys_addr_t base,
                                              phys_addr_t size)
 {
-       __memblock_free_early(base, size);
+       memblock_free(base, size);
 }
 
 static inline void __init memblock_free_early_nid(phys_addr_t base,
                                                  phys_addr_t size, int nid)
 {
-       __memblock_free_early(base, size);
+       memblock_free(base, size);
 }
 
 static inline void __init memblock_free_late(phys_addr_t base, phys_addr_t size)
index 7ab2120155a43d05c9cdfae28cb3d498798595d7..83ae11cbd12c6d0dea58af06f7b71560eec57278 100644 (file)
@@ -526,9 +526,11 @@ void mem_cgroup_handle_over_high(void);
 
 unsigned long mem_cgroup_get_max(struct mem_cgroup *memcg);
 
-void mem_cgroup_print_oom_info(struct mem_cgroup *memcg,
+void mem_cgroup_print_oom_context(struct mem_cgroup *memcg,
                                struct task_struct *p);
 
+void mem_cgroup_print_oom_meminfo(struct mem_cgroup *memcg);
+
 static inline void mem_cgroup_enter_user_fault(void)
 {
        WARN_ON(current->in_user_fault);
@@ -970,7 +972,12 @@ static inline unsigned long mem_cgroup_get_max(struct mem_cgroup *memcg)
 }
 
 static inline void
-mem_cgroup_print_oom_info(struct mem_cgroup *memcg, struct task_struct *p)
+mem_cgroup_print_oom_context(struct mem_cgroup *memcg, struct task_struct *p)
+{
+}
+
+static inline void
+mem_cgroup_print_oom_meminfo(struct mem_cgroup *memcg)
 {
 }
 
index ffd9cd10fcf35fb20b8728e6294eff42d90c135e..07da5c6c5ba0fc1de1eac7fb1ccd9ff34e5a0a10 100644 (file)
@@ -107,8 +107,8 @@ static inline bool movable_node_is_enabled(void)
 }
 
 #ifdef CONFIG_MEMORY_HOTREMOVE
-extern int arch_remove_memory(u64 start, u64 size,
-               struct vmem_altmap *altmap);
+extern int arch_remove_memory(int nid, u64 start, u64 size,
+                               struct vmem_altmap *altmap);
 extern int __remove_pages(struct zone *zone, unsigned long start_pfn,
        unsigned long nr_pages, struct vmem_altmap *altmap);
 #endif /* CONFIG_MEMORY_HOTREMOVE */
@@ -326,15 +326,14 @@ extern int walk_memory_range(unsigned long start_pfn, unsigned long end_pfn,
                void *arg, int (*func)(struct memory_block *, void *));
 extern int __add_memory(int nid, u64 start, u64 size);
 extern int add_memory(int nid, u64 start, u64 size);
-extern int add_memory_resource(int nid, struct resource *resource, bool online);
+extern int add_memory_resource(int nid, struct resource *resource);
 extern int arch_add_memory(int nid, u64 start, u64 size,
                struct vmem_altmap *altmap, bool want_memblock);
 extern void move_pfn_range_to_zone(struct zone *zone, unsigned long start_pfn,
                unsigned long nr_pages, struct vmem_altmap *altmap);
-extern int offline_pages(unsigned long start_pfn, unsigned long nr_pages);
 extern bool is_memblock_offlined(struct memory_block *mem);
-extern int sparse_add_one_section(struct pglist_data *pgdat,
-               unsigned long start_pfn, struct vmem_altmap *altmap);
+extern int sparse_add_one_section(int nid, unsigned long start_pfn,
+                                 struct vmem_altmap *altmap);
 extern void sparse_remove_one_section(struct zone *zone, struct mem_section *ms,
                unsigned long map_offset, struct vmem_altmap *altmap);
 extern struct page *sparse_decode_mem_map(unsigned long coded_mem_map,
index 0ac69ddf5fc461bb907fb28ff11f6a417a5354c3..f0628660d54100ffd890b7878c863bc698569a41 100644 (file)
@@ -4,8 +4,6 @@
 #include <linux/ioport.h>
 #include <linux/percpu-refcount.h>
 
-#include <asm/pgtable.h>
-
 struct resource;
 struct device;
 
@@ -66,62 +64,34 @@ enum memory_type {
 };
 
 /*
- * For MEMORY_DEVICE_PRIVATE we use ZONE_DEVICE and extend it with two
- * callbacks:
- *   page_fault()
- *   page_free()
- *
  * Additional notes about MEMORY_DEVICE_PRIVATE may be found in
  * include/linux/hmm.h and Documentation/vm/hmm.rst. There is also a brief
  * explanation in include/linux/memory_hotplug.h.
  *
- * The page_fault() callback must migrate page back, from device memory to
- * system memory, so that the CPU can access it. This might fail for various
- * reasons (device issues,  device have been unplugged, ...). When such error
- * conditions happen, the page_fault() callback must return VM_FAULT_SIGBUS and
- * set the CPU page table entry to "poisoned".
- *
- * Note that because memory cgroup charges are transferred to the device memory,
- * this should never fail due to memory restrictions. However, allocation
- * of a regular system page might still fail because we are out of memory. If
- * that happens, the page_fault() callback must return VM_FAULT_OOM.
- *
- * The page_fault() callback can also try to migrate back multiple pages in one
- * chunk, as an optimization. It must, however, prioritize the faulting address
- * over all the others.
- *
- *
  * The page_free() callback is called once the page refcount reaches 1
  * (ZONE_DEVICE pages never reach 0 refcount unless there is a refcount bug.
  * This allows the device driver to implement its own memory management.)
- *
- * For MEMORY_DEVICE_PUBLIC only the page_free() callback matter.
  */
-typedef int (*dev_page_fault_t)(struct vm_area_struct *vma,
-                               unsigned long addr,
-                               const struct page *page,
-                               unsigned int flags,
-                               pmd_t *pmdp);
 typedef void (*dev_page_free_t)(struct page *page, void *data);
 
 /**
  * struct dev_pagemap - metadata for ZONE_DEVICE mappings
- * @page_fault: callback when CPU fault on an unaddressable device page
  * @page_free: free page callback when page refcount reaches 1
  * @altmap: pre-allocated/reserved memory for vmemmap allocations
  * @res: physical address range covered by @ref
  * @ref: reference count that pins the devm_memremap_pages() mapping
+ * @kill: callback to transition @ref to the dead state
  * @dev: host device of the mapping for debug
  * @data: private data pointer for page_free()
  * @type: memory type: see MEMORY_* in memory_hotplug.h
  */
 struct dev_pagemap {
-       dev_page_fault_t page_fault;
        dev_page_free_t page_free;
        struct vmem_altmap altmap;
        bool altmap_valid;
        struct resource res;
        struct percpu_ref *ref;
+       void (*kill)(struct percpu_ref *ref);
        struct device *dev;
        void *data;
        enum memory_type type;
index f2b4abbca55e75f82c55dd6b8f7771d54738a23b..e13d9bf2f9a5ac29ad685ce4ebf18e59d62b854e 100644 (file)
@@ -29,7 +29,7 @@ enum migrate_reason {
 };
 
 /* In mm/debug.c; also keep sync with include/trace/events/migrate.h */
-extern char *migrate_reason_names[MR_TYPES];
+extern const char *migrate_reason_names[MR_TYPES];
 
 static inline struct page *new_page_nodemask(struct page *page,
                                int preferred_nid, nodemask_t *nodemask)
@@ -77,8 +77,7 @@ extern void migrate_page_copy(struct page *newpage, struct page *page);
 extern int migrate_huge_page_move_mapping(struct address_space *mapping,
                                  struct page *newpage, struct page *page);
 extern int migrate_page_move_mapping(struct address_space *mapping,
-               struct page *newpage, struct page *page,
-               struct buffer_head *head, enum migrate_mode mode,
+               struct page *newpage, struct page *page, enum migrate_mode mode,
                int extra_count);
 #else
 
index 5411de93a363e8a14bb980a30c8e5af67f25907e..ea1f12d15365bd8517f2b57f7bf3ab35a289bae6 100644 (file)
@@ -48,7 +48,32 @@ static inline void set_max_mapnr(unsigned long limit)
 static inline void set_max_mapnr(unsigned long limit) { }
 #endif
 
-extern unsigned long totalram_pages;
+extern atomic_long_t _totalram_pages;
+static inline unsigned long totalram_pages(void)
+{
+       return (unsigned long)atomic_long_read(&_totalram_pages);
+}
+
+static inline void totalram_pages_inc(void)
+{
+       atomic_long_inc(&_totalram_pages);
+}
+
+static inline void totalram_pages_dec(void)
+{
+       atomic_long_dec(&_totalram_pages);
+}
+
+static inline void totalram_pages_add(long count)
+{
+       atomic_long_add(count, &_totalram_pages);
+}
+
+static inline void totalram_pages_set(long val)
+{
+       atomic_long_set(&_totalram_pages, val);
+}
+
 extern void * high_memory;
 extern int page_cluster;
 
@@ -804,6 +829,7 @@ vm_fault_t finish_mkwrite_fault(struct vm_fault *vmf);
 #define NODES_PGOFF            (SECTIONS_PGOFF - NODES_WIDTH)
 #define ZONES_PGOFF            (NODES_PGOFF - ZONES_WIDTH)
 #define LAST_CPUPID_PGOFF      (ZONES_PGOFF - LAST_CPUPID_WIDTH)
+#define KASAN_TAG_PGOFF                (LAST_CPUPID_PGOFF - KASAN_TAG_WIDTH)
 
 /*
  * Define the bit shifts to access each section.  For non-existent
@@ -814,6 +840,7 @@ vm_fault_t finish_mkwrite_fault(struct vm_fault *vmf);
 #define NODES_PGSHIFT          (NODES_PGOFF * (NODES_WIDTH != 0))
 #define ZONES_PGSHIFT          (ZONES_PGOFF * (ZONES_WIDTH != 0))
 #define LAST_CPUPID_PGSHIFT    (LAST_CPUPID_PGOFF * (LAST_CPUPID_WIDTH != 0))
+#define KASAN_TAG_PGSHIFT      (KASAN_TAG_PGOFF * (KASAN_TAG_WIDTH != 0))
 
 /* NODE:ZONE or SECTION:ZONE is used to ID a zone for the buddy allocator */
 #ifdef NODE_NOT_IN_PAGE_FLAGS
@@ -836,6 +863,7 @@ vm_fault_t finish_mkwrite_fault(struct vm_fault *vmf);
 #define NODES_MASK             ((1UL << NODES_WIDTH) - 1)
 #define SECTIONS_MASK          ((1UL << SECTIONS_WIDTH) - 1)
 #define LAST_CPUPID_MASK       ((1UL << LAST_CPUPID_SHIFT) - 1)
+#define KASAN_TAG_MASK         ((1UL << KASAN_TAG_WIDTH) - 1)
 #define ZONEID_MASK            ((1UL << ZONEID_SHIFT) - 1)
 
 static inline enum zone_type page_zonenum(const struct page *page)
@@ -1101,6 +1129,32 @@ static inline bool cpupid_match_pid(struct task_struct *task, int cpupid)
 }
 #endif /* CONFIG_NUMA_BALANCING */
 
+#ifdef CONFIG_KASAN_SW_TAGS
+static inline u8 page_kasan_tag(const struct page *page)
+{
+       return (page->flags >> KASAN_TAG_PGSHIFT) & KASAN_TAG_MASK;
+}
+
+static inline void page_kasan_tag_set(struct page *page, u8 tag)
+{
+       page->flags &= ~(KASAN_TAG_MASK << KASAN_TAG_PGSHIFT);
+       page->flags |= (tag & KASAN_TAG_MASK) << KASAN_TAG_PGSHIFT;
+}
+
+static inline void page_kasan_tag_reset(struct page *page)
+{
+       page_kasan_tag_set(page, 0xff);
+}
+#else
+static inline u8 page_kasan_tag(const struct page *page)
+{
+       return 0xff;
+}
+
+static inline void page_kasan_tag_set(struct page *page, u8 tag) { }
+static inline void page_kasan_tag_reset(struct page *page) { }
+#endif
+
 static inline struct zone *page_zone(const struct page *page)
 {
        return &NODE_DATA(page_to_nid(page))->node_zones[page_zonenum(page)];
@@ -1397,6 +1451,8 @@ struct mm_walk {
        void *private;
 };
 
+struct mmu_notifier_range;
+
 int walk_page_range(unsigned long addr, unsigned long end,
                struct mm_walk *walk);
 int walk_page_vma(struct vm_area_struct *vma, struct mm_walk *walk);
@@ -1405,8 +1461,8 @@ void free_pgd_range(struct mmu_gather *tlb, unsigned long addr,
 int copy_page_range(struct mm_struct *dst, struct mm_struct *src,
                        struct vm_area_struct *vma);
 int follow_pte_pmd(struct mm_struct *mm, unsigned long address,
-                            unsigned long *start, unsigned long *end,
-                            pte_t **ptepp, pmd_t **pmdpp, spinlock_t **ptlp);
+                  struct mmu_notifier_range *range,
+                  pte_t **ptepp, pmd_t **pmdpp, spinlock_t **ptlp);
 int follow_pfn(struct vm_area_struct *vma, unsigned long address,
        unsigned long *pfn);
 int follow_phys(struct vm_area_struct *vma, unsigned long address,
@@ -1900,13 +1956,6 @@ static inline bool ptlock_init(struct page *page)
        return true;
 }
 
-/* Reset page->mapping so free_pages_check won't complain. */
-static inline void pte_lock_deinit(struct page *page)
-{
-       page->mapping = NULL;
-       ptlock_free(page);
-}
-
 #else  /* !USE_SPLIT_PTE_PTLOCKS */
 /*
  * We use mm->page_table_lock to guard all pagetable pages of the mm.
@@ -1917,7 +1966,7 @@ static inline spinlock_t *pte_lockptr(struct mm_struct *mm, pmd_t *pmd)
 }
 static inline void ptlock_cache_init(void) {}
 static inline bool ptlock_init(struct page *page) { return true; }
-static inline void pte_lock_deinit(struct page *page) {}
+static inline void ptlock_free(struct page *page) {}
 #endif /* USE_SPLIT_PTE_PTLOCKS */
 
 static inline void pgtable_init(void)
@@ -1937,7 +1986,7 @@ static inline bool pgtable_page_ctor(struct page *page)
 
 static inline void pgtable_page_dtor(struct page *page)
 {
-       pte_lock_deinit(page);
+       ptlock_free(page);
        __ClearPageTable(page);
        dec_zone_page_state(page, NR_PAGETABLE);
 }
@@ -2054,7 +2103,7 @@ extern void free_initmem(void);
  * Return pages freed into the buddy system.
  */
 extern unsigned long free_reserved_area(void *start, void *end,
-                                       int poison, char *s);
+                                       int poison, const char *s);
 
 #ifdef CONFIG_HIGHMEM
 /*
@@ -2202,6 +2251,7 @@ extern void zone_pcp_reset(struct zone *zone);
 
 /* page_alloc.c */
 extern int min_free_kbytes;
+extern int watermark_boost_factor;
 extern int watermark_scale_factor;
 
 /* nommu.c */
index 9893a6432adf9064c585b500f47754ce7909daed..4050ec1c3b45efcd7ede562256f5df50819cd792 100644 (file)
@@ -25,6 +25,13 @@ struct mmu_notifier_mm {
        spinlock_t lock;
 };
 
+struct mmu_notifier_range {
+       struct mm_struct *mm;
+       unsigned long start;
+       unsigned long end;
+       bool blockable;
+};
+
 struct mmu_notifier_ops {
        /*
         * Called either by mmu_notifier_unregister or when the mm is
@@ -146,12 +153,9 @@ struct mmu_notifier_ops {
         *
         */
        int (*invalidate_range_start)(struct mmu_notifier *mn,
-                                      struct mm_struct *mm,
-                                      unsigned long start, unsigned long end,
-                                      bool blockable);
+                                     const struct mmu_notifier_range *range);
        void (*invalidate_range_end)(struct mmu_notifier *mn,
-                                    struct mm_struct *mm,
-                                    unsigned long start, unsigned long end);
+                                    const struct mmu_notifier_range *range);
 
        /*
         * invalidate_range() is either called between
@@ -216,11 +220,8 @@ extern int __mmu_notifier_test_young(struct mm_struct *mm,
                                     unsigned long address);
 extern void __mmu_notifier_change_pte(struct mm_struct *mm,
                                      unsigned long address, pte_t pte);
-extern int __mmu_notifier_invalidate_range_start(struct mm_struct *mm,
-                                 unsigned long start, unsigned long end,
-                                 bool blockable);
-extern void __mmu_notifier_invalidate_range_end(struct mm_struct *mm,
-                                 unsigned long start, unsigned long end,
+extern int __mmu_notifier_invalidate_range_start(struct mmu_notifier_range *r);
+extern void __mmu_notifier_invalidate_range_end(struct mmu_notifier_range *r,
                                  bool only_end);
 extern void __mmu_notifier_invalidate_range(struct mm_struct *mm,
                                  unsigned long start, unsigned long end);
@@ -264,33 +265,37 @@ static inline void mmu_notifier_change_pte(struct mm_struct *mm,
                __mmu_notifier_change_pte(mm, address, pte);
 }
 
-static inline void mmu_notifier_invalidate_range_start(struct mm_struct *mm,
-                                 unsigned long start, unsigned long end)
+static inline void
+mmu_notifier_invalidate_range_start(struct mmu_notifier_range *range)
 {
-       if (mm_has_notifiers(mm))
-               __mmu_notifier_invalidate_range_start(mm, start, end, true);
+       if (mm_has_notifiers(range->mm)) {
+               range->blockable = true;
+               __mmu_notifier_invalidate_range_start(range);
+       }
 }
 
-static inline int mmu_notifier_invalidate_range_start_nonblock(struct mm_struct *mm,
-                                 unsigned long start, unsigned long end)
+static inline int
+mmu_notifier_invalidate_range_start_nonblock(struct mmu_notifier_range *range)
 {
-       if (mm_has_notifiers(mm))
-               return __mmu_notifier_invalidate_range_start(mm, start, end, false);
+       if (mm_has_notifiers(range->mm)) {
+               range->blockable = false;
+               return __mmu_notifier_invalidate_range_start(range);
+       }
        return 0;
 }
 
-static inline void mmu_notifier_invalidate_range_end(struct mm_struct *mm,
-                                 unsigned long start, unsigned long end)
+static inline void
+mmu_notifier_invalidate_range_end(struct mmu_notifier_range *range)
 {
-       if (mm_has_notifiers(mm))
-               __mmu_notifier_invalidate_range_end(mm, start, end, false);
+       if (mm_has_notifiers(range->mm))
+               __mmu_notifier_invalidate_range_end(range, false);
 }
 
-static inline void mmu_notifier_invalidate_range_only_end(struct mm_struct *mm,
-                                 unsigned long start, unsigned long end)
+static inline void
+mmu_notifier_invalidate_range_only_end(struct mmu_notifier_range *range)
 {
-       if (mm_has_notifiers(mm))
-               __mmu_notifier_invalidate_range_end(mm, start, end, true);
+       if (mm_has_notifiers(range->mm))
+               __mmu_notifier_invalidate_range_end(range, true);
 }
 
 static inline void mmu_notifier_invalidate_range(struct mm_struct *mm,
@@ -311,6 +316,17 @@ static inline void mmu_notifier_mm_destroy(struct mm_struct *mm)
                __mmu_notifier_mm_destroy(mm);
 }
 
+
+static inline void mmu_notifier_range_init(struct mmu_notifier_range *range,
+                                          struct mm_struct *mm,
+                                          unsigned long start,
+                                          unsigned long end)
+{
+       range->mm = mm;
+       range->start = start;
+       range->end = end;
+}
+
 #define ptep_clear_flush_young_notify(__vma, __address, __ptep)                \
 ({                                                                     \
        int __young;                                                    \
@@ -420,10 +436,26 @@ static inline void mmu_notifier_mm_destroy(struct mm_struct *mm)
 
 extern void mmu_notifier_call_srcu(struct rcu_head *rcu,
                                   void (*func)(struct rcu_head *rcu));
-extern void mmu_notifier_synchronize(void);
 
 #else /* CONFIG_MMU_NOTIFIER */
 
+struct mmu_notifier_range {
+       unsigned long start;
+       unsigned long end;
+};
+
+static inline void _mmu_notifier_range_init(struct mmu_notifier_range *range,
+                                           unsigned long start,
+                                           unsigned long end)
+{
+       range->start = start;
+       range->end = end;
+}
+
+#define mmu_notifier_range_init(range, mm, start, end) \
+       _mmu_notifier_range_init(range, start, end)
+
+
 static inline int mm_has_notifiers(struct mm_struct *mm)
 {
        return 0;
@@ -451,24 +483,24 @@ static inline void mmu_notifier_change_pte(struct mm_struct *mm,
 {
 }
 
-static inline void mmu_notifier_invalidate_range_start(struct mm_struct *mm,
-                                 unsigned long start, unsigned long end)
+static inline void
+mmu_notifier_invalidate_range_start(struct mmu_notifier_range *range)
 {
 }
 
-static inline int mmu_notifier_invalidate_range_start_nonblock(struct mm_struct *mm,
-                                 unsigned long start, unsigned long end)
+static inline int
+mmu_notifier_invalidate_range_start_nonblock(struct mmu_notifier_range *range)
 {
        return 0;
 }
 
-static inline void mmu_notifier_invalidate_range_end(struct mm_struct *mm,
-                                 unsigned long start, unsigned long end)
+static inline
+void mmu_notifier_invalidate_range_end(struct mmu_notifier_range *range)
 {
 }
 
-static inline void mmu_notifier_invalidate_range_only_end(struct mm_struct *mm,
-                                 unsigned long start, unsigned long end)
+static inline void
+mmu_notifier_invalidate_range_only_end(struct mmu_notifier_range *range)
 {
 }
 
index 077d797d1f608149d80d3a320545ca6b0074b10a..cc4a507d7ca45bb3e88cce09dad4d3ed8d4e40f7 100644 (file)
@@ -65,7 +65,7 @@ enum migratetype {
 };
 
 /* In mm/page_alloc.c; keep in sync also with show_migration_types() there */
-extern char * const migratetype_names[MIGRATE_TYPES];
+extern const char * const migratetype_names[MIGRATE_TYPES];
 
 #ifdef CONFIG_CMA
 #  define is_migrate_cma(migratetype) unlikely((migratetype) == MIGRATE_CMA)
@@ -269,9 +269,10 @@ enum zone_watermarks {
        NR_WMARK
 };
 
-#define min_wmark_pages(z) (z->watermark[WMARK_MIN])
-#define low_wmark_pages(z) (z->watermark[WMARK_LOW])
-#define high_wmark_pages(z) (z->watermark[WMARK_HIGH])
+#define min_wmark_pages(z) (z->_watermark[WMARK_MIN] + z->watermark_boost)
+#define low_wmark_pages(z) (z->_watermark[WMARK_LOW] + z->watermark_boost)
+#define high_wmark_pages(z) (z->_watermark[WMARK_HIGH] + z->watermark_boost)
+#define wmark_pages(z, i) (z->_watermark[i] + z->watermark_boost)
 
 struct per_cpu_pages {
        int count;              /* number of pages in the list */
@@ -362,7 +363,8 @@ struct zone {
        /* Read-mostly fields */
 
        /* zone watermarks, access with *_wmark_pages(zone) macros */
-       unsigned long watermark[NR_WMARK];
+       unsigned long _watermark[NR_WMARK];
+       unsigned long watermark_boost;
 
        unsigned long nr_reserved_highatomic;
 
@@ -428,14 +430,8 @@ struct zone {
         * Write access to present_pages at runtime should be protected by
         * mem_hotplug_begin/end(). Any reader who can't tolerant drift of
         * present_pages should get_online_mems() to get a stable value.
-        *
-        * Read access to managed_pages should be safe because it's unsigned
-        * long. Write access to zone->managed_pages and totalram_pages are
-        * protected by managed_page_count_lock at runtime. Idealy only
-        * adjust_managed_page_count() should be used instead of directly
-        * touching zone->managed_pages and totalram_pages.
         */
-       unsigned long           managed_pages;
+       atomic_long_t           managed_pages;
        unsigned long           spanned_pages;
        unsigned long           present_pages;
 
@@ -524,6 +520,11 @@ enum pgdat_flags {
        PGDAT_RECLAIM_LOCKED,           /* prevents concurrent reclaim */
 };
 
+static inline unsigned long zone_managed_pages(struct zone *zone)
+{
+       return (unsigned long)atomic_long_read(&zone->managed_pages);
+}
+
 static inline unsigned long zone_end_pfn(const struct zone *zone)
 {
        return zone->zone_start_pfn + zone->spanned_pages;
@@ -635,9 +636,8 @@ typedef struct pglist_data {
 #endif
 #if defined(CONFIG_MEMORY_HOTPLUG) || defined(CONFIG_DEFERRED_STRUCT_PAGE_INIT)
        /*
-        * Must be held any time you expect node_start_pfn, node_present_pages
-        * or node_spanned_pages stay constant.  Holding this will also
-        * guarantee that any pfn_valid() stays that way.
+        * Must be held any time you expect node_start_pfn,
+        * node_present_pages, node_spanned_pages or nr_zones to stay constant.
         *
         * pgdat_resize_lock() and pgdat_resize_unlock() are provided to
         * manipulate node_size_lock without checking for CONFIG_MEMORY_HOTPLUG
@@ -691,8 +691,6 @@ typedef struct pglist_data {
         * is the first PFN that needs to be initialised.
         */
        unsigned long first_deferred_pfn;
-       /* Number of non-deferred pages */
-       unsigned long static_init_pgcnt;
 #endif /* CONFIG_DEFERRED_STRUCT_PAGE_INIT */
 
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
@@ -820,7 +818,7 @@ static inline bool is_dev_zone(const struct zone *zone)
  */
 static inline bool managed_zone(struct zone *zone)
 {
-       return zone->managed_pages;
+       return zone_managed_pages(zone);
 }
 
 /* Returns true if a zone has memory */
@@ -890,6 +888,8 @@ static inline int is_highmem(struct zone *zone)
 struct ctl_table;
 int min_free_kbytes_sysctl_handler(struct ctl_table *, int,
                                        void __user *, size_t *, loff_t *);
+int watermark_boost_factor_sysctl_handler(struct ctl_table *, int,
+                                       void __user *, size_t *, loff_t *);
 int watermark_scale_factor_sysctl_handler(struct ctl_table *, int,
                                        void __user *, size_t *, loff_t *);
 extern int sysctl_lowmem_reserve_ratio[MAX_NR_ZONES];
index 69864a547663ecda818ac17c171ed085dbe33c26..d07992009265ab6a865ba70d0f20db21e478d5df 100644 (file)
@@ -15,6 +15,13 @@ struct notifier_block;
 struct mem_cgroup;
 struct task_struct;
 
+enum oom_constraint {
+       CONSTRAINT_NONE,
+       CONSTRAINT_CPUSET,
+       CONSTRAINT_MEMORY_POLICY,
+       CONSTRAINT_MEMCG,
+};
+
 /*
  * Details of the page allocation that triggered the oom killer that are used to
  * determine what should be killed.
@@ -42,6 +49,9 @@ struct oom_control {
        unsigned long totalpages;
        struct task_struct *chosen;
        unsigned long chosen_points;
+
+       /* Used to print the constraint info. */
+       enum oom_constraint constraint;
 };
 
 extern struct mutex oom_lock;
index 7ec86bf31ce48602b2fdbbdadca43a9436c5d62a..1dda31825ec4ae78c8852f15288a80c4a651bcf3 100644 (file)
 #define LAST_CPUPID_WIDTH 0
 #endif
 
+#ifdef CONFIG_KASAN_SW_TAGS
+#define KASAN_TAG_WIDTH 8
+#if SECTIONS_WIDTH+NODES_WIDTH+ZONES_WIDTH+LAST_CPUPID_WIDTH+KASAN_TAG_WIDTH \
+       > BITS_PER_LONG - NR_PAGEFLAGS
+#error "KASAN: not enough bits in page flags for tag"
+#endif
+#else
+#define KASAN_TAG_WIDTH 0
+#endif
+
 /*
  * We are going to use the flags for the page to node mapping if its in
  * there.  This includes the case where there is no node, so it is implicit.
index 50ce1bddaf56c20176ef51b772170efa0fdfda40..39b4494e29f1fa8805cb3f51125576a82de7b816 100644 (file)
@@ -669,6 +669,7 @@ PAGEFLAG_FALSE(DoubleMap)
 
 #define PAGE_TYPE_BASE 0xf0000000
 /* Reserve             0x0000007f to catch underflows of page_mapcount */
+#define PAGE_MAPCOUNT_RESERVE  -128
 #define PG_buddy       0x00000080
 #define PG_balloon     0x00000100
 #define PG_kmemcg      0x00000200
@@ -677,6 +678,11 @@ PAGEFLAG_FALSE(DoubleMap)
 #define PageType(page, flag)                                           \
        ((page->page_type & (PAGE_TYPE_BASE | flag)) == PAGE_TYPE_BASE)
 
+static inline int page_has_type(struct page *page)
+{
+       return (int)page->page_type < PAGE_MAPCOUNT_RESERVE;
+}
+
 #define PAGE_TYPE_OPS(uname, lname)                                    \
 static __always_inline int Page##uname(struct page *page)              \
 {                                                                      \
index 4ae347cbc36d16fcaed260ee9f39ad63259c7ed7..4eb26d2780460a6a821f110ce903ad2a1a54ccce 100644 (file)
@@ -30,8 +30,11 @@ static inline bool is_migrate_isolate(int migratetype)
 }
 #endif
 
+#define SKIP_HWPOISON  0x1
+#define REPORT_FAILURE 0x2
+
 bool has_unmovable_pages(struct zone *zone, struct page *page, int count,
-                        int migratetype, bool skip_hwpoisoned_pages);
+                        int migratetype, int flags);
 void set_pageblock_migratetype(struct page *page, int migratetype);
 int move_freepages_block(struct zone *zone, struct page *page,
                                int migratetype, int *num_movable);
@@ -44,10 +47,14 @@ int move_freepages_block(struct zone *zone, struct page *page,
  * For isolating all pages in the range finally, the caller have to
  * free all pages in the range. test_page_isolated() can be used for
  * test it.
+ *
+ * The following flags are allowed (they can be combined in a bit mask)
+ * SKIP_HWPOISON - ignore hwpoison pages
+ * REPORT_FAILURE - report details about the failure to isolate the range
  */
 int
 start_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn,
-                        unsigned migratetype, bool skip_hwpoisoned_pages);
+                        unsigned migratetype, int flags);
 
 /*
  * Changes MIGRATE_ISOLATE to MIGRATE_MOVABLE.
index 9132c5cb41f10eadb92674e67184fb53baf28bd7..06a66327333de383ebb79ee04a13cd8faf99b962 100644 (file)
 
 #include <linux/types.h>
 
+#define PB_migratetype_bits 3
 /* Bit indices that affect a whole block of pages */
 enum pageblock_bits {
        PB_migrate,
-       PB_migrate_end = PB_migrate + 3 - 1,
+       PB_migrate_end = PB_migrate + PB_migratetype_bits - 1,
                        /* 3 bits required for migrate types */
        PB_migrate_skip,/* If set the block is skipped by compaction */
 
index 226f96f0dee0611e44622aaf6e401c588423e2de..e2d7039af6a38b65f13a5a4fd2dfd8bd1b86f489 100644 (file)
@@ -537,6 +537,8 @@ static inline int wait_on_page_locked_killable(struct page *page)
        return wait_on_page_bit_killable(compound_head(page), PG_locked);
 }
 
+extern void put_and_wait_on_page_locked(struct page *page);
+
 /* 
  * Wait for a page to complete writeback
  */
index 918f374e7156f4739b30c178e5c8beaf5137c4d0..6d9bd6fc0c571775b4b7d49cba613f7d6940dd97 100644 (file)
@@ -314,22 +314,22 @@ kmalloc_caches[NR_KMALLOC_TYPES][KMALLOC_SHIFT_HIGH + 1];
 
 static __always_inline enum kmalloc_cache_type kmalloc_type(gfp_t flags)
 {
-       int is_dma = 0;
-       int type_dma = 0;
-       int is_reclaimable;
-
 #ifdef CONFIG_ZONE_DMA
-       is_dma = !!(flags & __GFP_DMA);
-       type_dma = is_dma * KMALLOC_DMA;
-#endif
-
-       is_reclaimable = !!(flags & __GFP_RECLAIMABLE);
+       /*
+        * The most common case is KMALLOC_NORMAL, so test for it
+        * with a single branch for both flags.
+        */
+       if (likely((flags & (__GFP_DMA | __GFP_RECLAIMABLE)) == 0))
+               return KMALLOC_NORMAL;
 
        /*
-        * If an allocation is both __GFP_DMA and __GFP_RECLAIMABLE, return
-        * KMALLOC_DMA and effectively ignore __GFP_RECLAIMABLE
+        * At least one of the flags has to be set. If both are, __GFP_DMA
+        * is more important.
         */
-       return type_dma + (is_reclaimable & !is_dma) * KMALLOC_RECLAIM;
+       return flags & __GFP_DMA ? KMALLOC_DMA : KMALLOC_RECLAIM;
+#else
+       return flags & __GFP_RECLAIMABLE ? KMALLOC_RECLAIM : KMALLOC_NORMAL;
+#endif
 }
 
 /*
@@ -444,7 +444,7 @@ static __always_inline void *kmem_cache_alloc_trace(struct kmem_cache *s,
 {
        void *ret = kmem_cache_alloc(s, flags);
 
-       kasan_kmalloc(s, ret, size, flags);
+       ret = kasan_kmalloc(s, ret, size, flags);
        return ret;
 }
 
@@ -455,7 +455,7 @@ kmem_cache_alloc_node_trace(struct kmem_cache *s,
 {
        void *ret = kmem_cache_alloc_node(s, gfpflags, node);
 
-       kasan_kmalloc(s, ret, size, gfpflags);
+       ret = kasan_kmalloc(s, ret, size, gfpflags);
        return ret;
 }
 #endif /* CONFIG_TRACING */
index 3485c58cfd1ca7dd3514226894b0534a710d5051..9a5eafb7145bb1733fa8ffeaf26ff15445ee013c 100644 (file)
@@ -104,4 +104,17 @@ static inline void *nearest_obj(struct kmem_cache *cache, struct page *page,
                return object;
 }
 
+/*
+ * We want to avoid an expensive divide : (offset / cache->size)
+ *   Using the fact that size is a constant for a particular cache,
+ *   we can replace (offset / cache->size) by
+ *   reciprocal_divide(offset, cache->reciprocal_buffer_size)
+ */
+static inline unsigned int obj_to_index(const struct kmem_cache *cache,
+                                       const struct page *page, void *obj)
+{
+       u32 offset = (obj - page->s_mem);
+       return reciprocal_divide(offset, cache->reciprocal_buffer_size);
+}
+
 #endif /* _LINUX_SLAB_DEF_H */
index a8f6d5d89524d3163a0c8f1dc835259f8d1dea51..622025ac1461e1d58b8961a1c72df66ecf60efb6 100644 (file)
@@ -235,7 +235,6 @@ struct swap_info_struct {
        unsigned long   flags;          /* SWP_USED etc: see above */
        signed short    prio;           /* swap priority of this type */
        struct plist_node list;         /* entry in swap_active_head */
-       struct plist_node avail_lists[MAX_NUMNODES];/* entry in swap_avail_heads */
        signed char     type;           /* strange name for an index */
        unsigned int    max;            /* extent of the swap_map */
        unsigned char *swap_map;        /* vmalloc'ed array of usage counts */
@@ -276,6 +275,16 @@ struct swap_info_struct {
                                         */
        struct work_struct discard_work; /* discard worker */
        struct swap_cluster_list discard_clusters; /* discard clusters list */
+       struct plist_node avail_lists[0]; /*
+                                          * entries in swap_avail_heads, one
+                                          * entry per node.
+                                          * Must be last as the number of the
+                                          * array is nr_node_ids, which is not
+                                          * a fixed value so have to allocate
+                                          * dynamically.
+                                          * And it has to be an array so that
+                                          * plist_for_each_* can work.
+                                          */
 };
 
 #ifdef CONFIG_64BIT
@@ -310,7 +319,6 @@ void workingset_update_node(struct xa_node *node);
 } while (0)
 
 /* linux/mm/page_alloc.c */
-extern unsigned long totalram_pages;
 extern unsigned long totalreserve_pages;
 extern unsigned long nr_free_buffer_pages(void);
 extern unsigned long nr_free_pagecache_pages(void);
@@ -360,14 +368,8 @@ extern unsigned long vm_total_pages;
 extern int node_reclaim_mode;
 extern int sysctl_min_unmapped_ratio;
 extern int sysctl_min_slab_ratio;
-extern int node_reclaim(struct pglist_data *, gfp_t, unsigned int);
 #else
 #define node_reclaim_mode 0
-static inline int node_reclaim(struct pglist_data *pgdat, gfp_t mask,
-                               unsigned int order)
-{
-       return 0;
-}
 #endif
 
 extern int page_evictable(struct page *page);
index f25cef84b41db718a0d977c471b9afbc6773378e..2db8d60981fe51c08b841ab50f46f2c7e640c080 100644 (file)
@@ -239,11 +239,6 @@ extern unsigned long node_page_state(struct pglist_data *pgdat,
 #define node_page_state(node, item) global_node_page_state(item)
 #endif /* CONFIG_NUMA */
 
-#define add_zone_page_state(__z, __i, __d) mod_zone_page_state(__z, __i, __d)
-#define sub_zone_page_state(__z, __i, __d) mod_zone_page_state(__z, __i, -(__d))
-#define add_node_page_state(__p, __i, __d) mod_node_page_state(__p, __i, __d)
-#define sub_node_page_state(__p, __i, __d) mod_node_page_state(__p, __i, -(__d))
-
 #ifdef CONFIG_SMP
 void __mod_zone_page_state(struct zone *, enum zone_stat_item item, long);
 void __inc_zone_page_state(struct page *, enum zone_stat_item);
index 9e1f42cb57e9e98fb4300c3361b5e8d7eb593a4b..52b073fea17fe4f72b872c8002687fe6adbc5a0d 100644 (file)
@@ -107,6 +107,29 @@ uint32_t xxh32(const void *input, size_t length, uint32_t seed);
  */
 uint64_t xxh64(const void *input, size_t length, uint64_t seed);
 
+/**
+ * xxhash() - calculate wordsize hash of the input with a given seed
+ * @input:  The data to hash.
+ * @length: The length of the data to hash.
+ * @seed:   The seed can be used to alter the result predictably.
+ *
+ * If the hash does not need to be comparable between machines with
+ * different word sizes, this function will call whichever of xxh32()
+ * or xxh64() is faster.
+ *
+ * Return:  wordsize hash of the data.
+ */
+
+static inline unsigned long xxhash(const void *input, size_t length,
+                                  uint64_t seed)
+{
+#if BITS_PER_LONG == 64
+       return xxh64(input, length, seed);
+#else
+       return xxh32(input, length, seed);
+#endif
+}
+
 /*-****************************
  * Streaming Hash Functions
  *****************************/
index 0f8cc626e63459a237a489dac5f5438b2160c633..86d894852bef8b4e25cddde0967d4f08a86ab269 100644 (file)
@@ -521,6 +521,7 @@ static void __init mm_init(void)
        mem_init();
        kmem_cache_init();
        pgtable_init();
+       debug_objects_mem_init();
        vmalloc_init();
        ioremap_huge_init();
        /* Should be run before the first non-init thread is created */
@@ -697,7 +698,6 @@ asmlinkage __visible void __init start_kernel(void)
 #endif
        page_ext_init();
        kmemleak_init();
-       debug_objects_mem_init();
        setup_per_cpu_pageset();
        numa_policy_init();
        acpi_early_init();
index 266f10cb7222b558aca0a777206d7bc747912750..9510a5b32eaf6be16dd2817028235410f673d7dc 100644 (file)
@@ -2666,9 +2666,9 @@ void cpuset_print_current_mems_allowed(void)
        rcu_read_lock();
 
        cgrp = task_cs(current)->css.cgroup;
-       pr_info("%s cpuset=", current->comm);
+       pr_cont(",cpuset=");
        pr_cont_cgroup_name(cgrp);
-       pr_cont(" mems_allowed=%*pbl\n",
+       pr_cont(",mems_allowed=%*pbl",
                nodemask_pr_args(&current->mems_allowed));
 
        rcu_read_unlock();
index abbd8da9ac21613d6520e1a8533d3fe0b28dccb0..8aef47ee7bfad62f6147412caa9af28314bd7758 100644 (file)
@@ -171,11 +171,11 @@ static int __replace_page(struct vm_area_struct *vma, unsigned long addr,
                .address = addr,
        };
        int err;
-       /* For mmu_notifiers */
-       const unsigned long mmun_start = addr;
-       const unsigned long mmun_end   = addr + PAGE_SIZE;
+       struct mmu_notifier_range range;
        struct mem_cgroup *memcg;
 
+       mmu_notifier_range_init(&range, mm, addr, addr + PAGE_SIZE);
+
        VM_BUG_ON_PAGE(PageTransHuge(old_page), old_page);
 
        err = mem_cgroup_try_charge(new_page, vma->vm_mm, GFP_KERNEL, &memcg,
@@ -186,7 +186,7 @@ static int __replace_page(struct vm_area_struct *vma, unsigned long addr,
        /* For try_to_free_swap() and munlock_vma_page() below */
        lock_page(old_page);
 
-       mmu_notifier_invalidate_range_start(mm, mmun_start, mmun_end);
+       mmu_notifier_invalidate_range_start(&range);
        err = -EAGAIN;
        if (!page_vma_mapped_walk(&pvmw)) {
                mem_cgroup_cancel_charge(new_page, memcg, false);
@@ -220,7 +220,7 @@ static int __replace_page(struct vm_area_struct *vma, unsigned long addr,
 
        err = 0;
  unlock:
-       mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end);
+       mmu_notifier_invalidate_range_end(&range);
        unlock_page(old_page);
        return err;
 }
index e2a5156bc9c3301eeb83b21d0fc4f1f9541b3d7b..d439c48ecf181c5914cbf467a1754ac355c830f9 100644 (file)
@@ -744,15 +744,16 @@ void __init __weak arch_task_cache_init(void) { }
 static void set_max_threads(unsigned int max_threads_suggested)
 {
        u64 threads;
+       unsigned long nr_pages = totalram_pages();
 
        /*
         * The number of threads shall be limited such that the thread
         * structures may only consume a small part of the available memory.
         */
-       if (fls64(totalram_pages) + fls64(PAGE_SIZE) > 64)
+       if (fls64(nr_pages) + fls64(PAGE_SIZE) > 64)
                threads = MAX_THREADS;
        else
-               threads = div64_u64((u64) totalram_pages * (u64) PAGE_SIZE,
+               threads = div64_u64((u64) nr_pages * (u64) PAGE_SIZE,
                                    (u64) THREAD_SIZE * 8UL);
 
        if (threads > max_threads_suggested)
@@ -840,7 +841,7 @@ static struct task_struct *dup_task_struct(struct task_struct *orig, int node)
 {
        struct task_struct *tsk;
        unsigned long *stack;
-       struct vm_struct *stack_vm_area;
+       struct vm_struct *stack_vm_area __maybe_unused;
        int err;
 
        if (node == NUMA_NO_NODE)
index 86ef06d3dbe3a067ee00fe31c924b11be7340d31..d7140447be75b809c5f5979d7be280c2f46de1c2 100644 (file)
@@ -152,6 +152,7 @@ int sanity_check_segment_list(struct kimage *image)
        int i;
        unsigned long nr_segments = image->nr_segments;
        unsigned long total_pages = 0;
+       unsigned long nr_pages = totalram_pages();
 
        /*
         * Verify we have good destination addresses.  The caller is
@@ -217,13 +218,13 @@ int sanity_check_segment_list(struct kimage *image)
         * wasted allocating pages, which can cause a soft lockup.
         */
        for (i = 0; i < nr_segments; i++) {
-               if (PAGE_COUNT(image->segment[i].memsz) > totalram_pages / 2)
+               if (PAGE_COUNT(image->segment[i].memsz) > nr_pages / 2)
                        return -EINVAL;
 
                total_pages += PAGE_COUNT(image->segment[i].memsz);
        }
 
-       if (total_pages > totalram_pages / 2)
+       if (total_pages > nr_pages / 2)
                return -EINVAL;
 
        /*
index 9eced2cc9f94d7f58d692b2e3dc84ee594d52171..a856cb5ff192aa5584f98c5138d8cabece672f3b 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/types.h>
 #include <linux/wait_bit.h>
 #include <linux/xarray.h>
+#include <linux/hmm.h>
 
 static DEFINE_XARRAY(pgmap_array);
 #define SECTION_MASK ~((1UL << PA_SECTION_SHIFT) - 1)
@@ -24,6 +25,9 @@ vm_fault_t device_private_entry_fault(struct vm_area_struct *vma,
                       pmd_t *pmdp)
 {
        struct page *page = device_private_entry_to_page(entry);
+       struct hmm_devmem *devmem;
+
+       devmem = container_of(page->pgmap, typeof(*devmem), pagemap);
 
        /*
         * The page_fault() callback must migrate page back to system memory
@@ -39,7 +43,7 @@ vm_fault_t device_private_entry_fault(struct vm_area_struct *vma,
         * There is a more in-depth description of what that callback can and
         * cannot do, in include/linux/memremap.h
         */
-       return page->pgmap->page_fault(vma, addr, page, flags, pmdp);
+       return devmem->page_fault(vma, addr, page, flags, pmdp);
 }
 EXPORT_SYMBOL(device_private_entry_fault);
 #endif /* CONFIG_DEVICE_PRIVATE */
@@ -87,24 +91,29 @@ static void devm_memremap_pages_release(void *data)
        struct resource *res = &pgmap->res;
        resource_size_t align_start, align_size;
        unsigned long pfn;
+       int nid;
 
+       pgmap->kill(pgmap->ref);
        for_each_device_pfn(pfn, pgmap)
                put_page(pfn_to_page(pfn));
 
-       if (percpu_ref_tryget_live(pgmap->ref)) {
-               dev_WARN(dev, "%s: page mapping is still live!\n", __func__);
-               percpu_ref_put(pgmap->ref);
-       }
-
        /* pages are dead and unused, undo the arch mapping */
        align_start = res->start & ~(SECTION_SIZE - 1);
        align_size = ALIGN(res->start + resource_size(res), SECTION_SIZE)
                - align_start;
 
+       nid = page_to_nid(pfn_to_page(align_start >> PAGE_SHIFT));
+
        mem_hotplug_begin();
-       arch_remove_memory(align_start, align_size, pgmap->altmap_valid ?
-                       &pgmap->altmap : NULL);
-       kasan_remove_zero_shadow(__va(align_start), align_size);
+       if (pgmap->type == MEMORY_DEVICE_PRIVATE) {
+               pfn = align_start >> PAGE_SHIFT;
+               __remove_pages(page_zone(pfn_to_page(pfn)), pfn,
+                               align_size >> PAGE_SHIFT, NULL);
+       } else {
+               arch_remove_memory(nid, align_start, align_size,
+                               pgmap->altmap_valid ? &pgmap->altmap : NULL);
+               kasan_remove_zero_shadow(__va(align_start), align_size);
+       }
        mem_hotplug_done();
 
        untrack_pfn(NULL, PHYS_PFN(align_start), align_size);
@@ -116,7 +125,7 @@ static void devm_memremap_pages_release(void *data)
 /**
  * devm_memremap_pages - remap and provide memmap backing for the given resource
  * @dev: hosting device for @res
- * @pgmap: pointer to a struct dev_pgmap
+ * @pgmap: pointer to a struct dev_pagemap
  *
  * Notes:
  * 1/ At a minimum the res, ref and type members of @pgmap must be initialized
@@ -125,11 +134,8 @@ static void devm_memremap_pages_release(void *data)
  * 2/ The altmap field may optionally be initialized, in which case altmap_valid
  *    must be set to true
  *
- * 3/ pgmap.ref must be 'live' on entry and 'dead' before devm_memunmap_pages()
- *    time (or devm release event). The expected order of events is that ref has
- *    been through percpu_ref_kill() before devm_memremap_pages_release(). The
- *    wait for the completion of all references being dropped and
- *    percpu_ref_exit() must occur after devm_memremap_pages_release().
+ * 3/ pgmap->ref must be 'live' on entry and will be killed at
+ *    devm_memremap_pages_release() time, or if this routine fails.
  *
  * 4/ res is expected to be a host memory range that could feasibly be
  *    treated as a "System RAM" range, i.e. not a device mmio range, but
@@ -145,6 +151,9 @@ void *devm_memremap_pages(struct device *dev, struct dev_pagemap *pgmap)
        pgprot_t pgprot = PAGE_KERNEL;
        int error, nid, is_ram;
 
+       if (!pgmap->ref || !pgmap->kill)
+               return ERR_PTR(-EINVAL);
+
        align_start = res->start & ~(SECTION_SIZE - 1);
        align_size = ALIGN(res->start + resource_size(res), SECTION_SIZE)
                - align_start;
@@ -167,18 +176,13 @@ void *devm_memremap_pages(struct device *dev, struct dev_pagemap *pgmap)
        is_ram = region_intersects(align_start, align_size,
                IORESOURCE_SYSTEM_RAM, IORES_DESC_NONE);
 
-       if (is_ram == REGION_MIXED) {
-               WARN_ONCE(1, "%s attempted on mixed region %pr\n",
-                               __func__, res);
-               return ERR_PTR(-ENXIO);
+       if (is_ram != REGION_DISJOINT) {
+               WARN_ONCE(1, "%s attempted on %s region %pr\n", __func__,
+                               is_ram == REGION_MIXED ? "mixed" : "ram", res);
+               error = -ENXIO;
+               goto err_array;
        }
 
-       if (is_ram == REGION_INTERSECTS)
-               return __va(res->start);
-
-       if (!pgmap->ref)
-               return ERR_PTR(-EINVAL);
-
        pgmap->dev = dev;
 
        error = xa_err(xa_store_range(&pgmap_array, PHYS_PFN(res->start),
@@ -196,17 +200,40 @@ void *devm_memremap_pages(struct device *dev, struct dev_pagemap *pgmap)
                goto err_pfn_remap;
 
        mem_hotplug_begin();
-       error = kasan_add_zero_shadow(__va(align_start), align_size);
-       if (error) {
-               mem_hotplug_done();
-               goto err_kasan;
+
+       /*
+        * For device private memory we call add_pages() as we only need to
+        * allocate and initialize struct page for the device memory. More-
+        * over the device memory is un-accessible thus we do not want to
+        * create a linear mapping for the memory like arch_add_memory()
+        * would do.
+        *
+        * For all other device memory types, which are accessible by
+        * the CPU, we do want the linear mapping and thus use
+        * arch_add_memory().
+        */
+       if (pgmap->type == MEMORY_DEVICE_PRIVATE) {
+               error = add_pages(nid, align_start >> PAGE_SHIFT,
+                               align_size >> PAGE_SHIFT, NULL, false);
+       } else {
+               error = kasan_add_zero_shadow(__va(align_start), align_size);
+               if (error) {
+                       mem_hotplug_done();
+                       goto err_kasan;
+               }
+
+               error = arch_add_memory(nid, align_start, align_size, altmap,
+                               false);
+       }
+
+       if (!error) {
+               struct zone *zone;
+
+               zone = &NODE_DATA(nid)->node_zones[ZONE_DEVICE];
+               move_pfn_range_to_zone(zone, align_start >> PAGE_SHIFT,
+                               align_size >> PAGE_SHIFT, altmap);
        }
 
-       error = arch_add_memory(nid, align_start, align_size, altmap, false);
-       if (!error)
-               move_pfn_range_to_zone(&NODE_DATA(nid)->node_zones[ZONE_DEVICE],
-                                       align_start >> PAGE_SHIFT,
-                                       align_size >> PAGE_SHIFT, altmap);
        mem_hotplug_done();
        if (error)
                goto err_add_memory;
@@ -220,7 +247,10 @@ void *devm_memremap_pages(struct device *dev, struct dev_pagemap *pgmap)
                                align_size >> PAGE_SHIFT, pgmap);
        percpu_ref_get_many(pgmap->ref, pfn_end(pgmap) - pfn_first(pgmap));
 
-       devm_add_action(dev, devm_memremap_pages_release, pgmap);
+       error = devm_add_action_or_reset(dev, devm_memremap_pages_release,
+                       pgmap);
+       if (error)
+               return ERR_PTR(error);
 
        return __va(res->start);
 
@@ -231,9 +261,10 @@ void *devm_memremap_pages(struct device *dev, struct dev_pagemap *pgmap)
  err_pfn_remap:
        pgmap_array_delete(res);
  err_array:
+       pgmap->kill(pgmap->ref);
        return ERR_PTR(error);
 }
-EXPORT_SYMBOL(devm_memremap_pages);
+EXPORT_SYMBOL_GPL(devm_memremap_pages);
 
 unsigned long vmem_altmap_offset(struct vmem_altmap *altmap)
 {
index b0308a2c6000d3bf34b897a5a2d248049cb4c492..640b2034edd660da46372b38d8eca7b37bd482fc 100644 (file)
@@ -105,7 +105,7 @@ unsigned long image_size;
 
 void __init hibernate_image_size_init(void)
 {
-       image_size = ((totalram_pages * 2) / 5) * PAGE_SIZE;
+       image_size = ((totalram_pages() * 2) / 5) * PAGE_SIZE;
 }
 
 /*
index b0fbf685c77a52ba45dc4c3e2044782080a74953..915c02e8e5dd28ff36e7555be769b6e5fa77e309 100644 (file)
@@ -1256,6 +1256,21 @@ int release_mem_region_adjustable(struct resource *parent,
                        continue;
                }
 
+               /*
+                * All memory regions added from memory-hotplug path have the
+                * flag IORESOURCE_SYSTEM_RAM. If the resource does not have
+                * this flag, we know that we are dealing with a resource coming
+                * from HMM/devm. HMM/devm use another mechanism to add/release
+                * a resource. This goes via devm_request_mem_region and
+                * devm_release_mem_region.
+                * HMM/devm take care to release their resources when they want,
+                * so if we are dealing with them, let us just back off here.
+                */
+               if (!(res->flags & IORESOURCE_SYSRAM)) {
+                       ret = 0;
+                       break;
+               }
+
                if (!(res->flags & IORESOURCE_MEM))
                        break;
 
index 5fc724e4e454c3304ecaebe7c868eb622f784eb8..1825f712e73bb74809e921503622dd5511b94923 100644 (file)
@@ -1462,6 +1462,14 @@ static struct ctl_table vm_table[] = {
                .proc_handler   = min_free_kbytes_sysctl_handler,
                .extra1         = &zero,
        },
+       {
+               .procname       = "watermark_boost_factor",
+               .data           = &watermark_boost_factor,
+               .maxlen         = sizeof(watermark_boost_factor),
+               .mode           = 0644,
+               .proc_handler   = watermark_boost_factor_sysctl_handler,
+               .extra1         = &zero,
+       },
        {
                .procname       = "watermark_scale_factor",
                .data           = &watermark_scale_factor,
index b3c91b9e32f84e0f5ccb0bf303ba72e9f265dbb6..2b5a4256e88bc37b3a1b61278b2ed406493d2d5f 100644 (file)
@@ -593,6 +593,21 @@ config DEBUG_KMEMLEAK_DEFAULT_OFF
          Say Y here to disable kmemleak by default. It can then be enabled
          on the command line via kmemleak=on.
 
+config DEBUG_KMEMLEAK_AUTO_SCAN
+       bool "Enable kmemleak auto scan thread on boot up"
+       default y
+       depends on DEBUG_KMEMLEAK
+       help
+         Depending on the cpu, kmemleak scan may be cpu intensive and can
+         stall user tasks at times. This option enables/disables automatic
+         kmemleak scan at boot up.
+
+         Say N here to disable kmemleak auto scan thread to stop automatic
+         scanning. Disabling this option disables automatic reporting of
+         memory leaks.
+
+         If unsure, say Y.
+
 config DEBUG_STACK_USAGE
        bool "Stack utilization instrumentation"
        depends on DEBUG_KERNEL && !IA64
index d0bad1bd9a2b1ef148058dff17eb6375f019fb2a..d8c474b6691e92c6a2d26519c5f59cb4b4d04afc 100644 (file)
@@ -1,36 +1,92 @@
+# This config refers to the generic KASAN mode.
 config HAVE_ARCH_KASAN
        bool
 
-if HAVE_ARCH_KASAN
+config HAVE_ARCH_KASAN_SW_TAGS
+       bool
+
+config CC_HAS_KASAN_GENERIC
+       def_bool $(cc-option, -fsanitize=kernel-address)
+
+config CC_HAS_KASAN_SW_TAGS
+       def_bool $(cc-option, -fsanitize=kernel-hwaddress)
 
 config KASAN
-       bool "KASan: runtime memory debugger"
+       bool "KASAN: runtime memory debugger"
+       depends on (HAVE_ARCH_KASAN && CC_HAS_KASAN_GENERIC) || \
+                  (HAVE_ARCH_KASAN_SW_TAGS && CC_HAS_KASAN_SW_TAGS)
+       depends on (SLUB && SYSFS) || (SLAB && !DEBUG_SLAB)
+       help
+         Enables KASAN (KernelAddressSANitizer) - runtime memory debugger,
+         designed to find out-of-bounds accesses and use-after-free bugs.
+         See Documentation/dev-tools/kasan.rst for details.
+
+choice
+       prompt "KASAN mode"
+       depends on KASAN
+       default KASAN_GENERIC
+       help
+         KASAN has two modes: generic KASAN (similar to userspace ASan,
+         x86_64/arm64/xtensa, enabled with CONFIG_KASAN_GENERIC) and
+         software tag-based KASAN (a version based on software memory
+         tagging, arm64 only, similar to userspace HWASan, enabled with
+         CONFIG_KASAN_SW_TAGS).
+         Both generic and tag-based KASAN are strictly debugging features.
+
+config KASAN_GENERIC
+       bool "Generic mode"
+       depends on HAVE_ARCH_KASAN && CC_HAS_KASAN_GENERIC
        depends on (SLUB && SYSFS) || (SLAB && !DEBUG_SLAB)
        select SLUB_DEBUG if SLUB
        select CONSTRUCTORS
        select STACKDEPOT
        help
-         Enables kernel address sanitizer - runtime memory debugger,
-         designed to find out-of-bounds accesses and use-after-free bugs.
-         This is strictly a debugging feature and it requires a gcc version
-         of 4.9.2 or later. Detection of out of bounds accesses to stack or
-         global variables requires gcc 5.0 or later.
-         This feature consumes about 1/8 of available memory and brings about
-         ~x3 performance slowdown.
+         Enables generic KASAN mode.
+         Supported in both GCC and Clang. With GCC it requires version 4.9.2
+         or later for basic support and version 5.0 or later for detection of
+         out-of-bounds accesses for stack and global variables and for inline
+         instrumentation mode (CONFIG_KASAN_INLINE). With Clang it requires
+         version 3.7.0 or later and it doesn't support detection of
+         out-of-bounds accesses for global variables yet.
+         This mode consumes about 1/8th of available memory at kernel start
+         and introduces an overhead of ~x1.5 for the rest of the allocations.
+         The performance slowdown is ~x3.
          For better error detection enable CONFIG_STACKTRACE.
-         Currently CONFIG_KASAN doesn't work with CONFIG_DEBUG_SLAB
+         Currently CONFIG_KASAN_GENERIC doesn't work with CONFIG_DEBUG_SLAB
          (the resulting kernel does not boot).
 
+config KASAN_SW_TAGS
+       bool "Software tag-based mode"
+       depends on HAVE_ARCH_KASAN_SW_TAGS && CC_HAS_KASAN_SW_TAGS
+       depends on (SLUB && SYSFS) || (SLAB && !DEBUG_SLAB)
+       select SLUB_DEBUG if SLUB
+       select CONSTRUCTORS
+       select STACKDEPOT
+       help
+         Enables software tag-based KASAN mode.
+         This mode requires Top Byte Ignore support by the CPU and therefore
+         is only supported for arm64.
+         This mode requires Clang version 7.0.0 or later.
+         This mode consumes about 1/16th of available memory at kernel start
+         and introduces an overhead of ~20% for the rest of the allocations.
+         This mode may potentially introduce problems relating to pointer
+         casting and comparison, as it embeds tags into the top byte of each
+         pointer.
+         For better error detection enable CONFIG_STACKTRACE.
+         Currently CONFIG_KASAN_SW_TAGS doesn't work with CONFIG_DEBUG_SLAB
+         (the resulting kernel does not boot).
+
+endchoice
+
 config KASAN_EXTRA
-       bool "KAsan: extra checks"
-       depends on KASAN && DEBUG_KERNEL && !COMPILE_TEST
+       bool "KASAN: extra checks"
+       depends on KASAN_GENERIC && DEBUG_KERNEL && !COMPILE_TEST
        help
-         This enables further checks in the kernel address sanitizer, for now
-         it only includes the address-use-after-scope check that can lead
-         to excessive kernel stack usage, frame size warnings and longer
+         This enables further checks in generic KASAN, for now it only
+         includes the address-use-after-scope check that can lead to
+         excessive kernel stack usage, frame size warnings and longer
          compile time.
-         https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 has more
-
+         See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81715
 
 choice
        prompt "Instrumentation type"
@@ -53,7 +109,7 @@ config KASAN_INLINE
          memory accesses. This is faster than outline (in some workloads
          it gives about x2 boost over outline instrumentation), but
          make kernel's .text size much bigger.
-         This requires a gcc version of 5.0 or later.
+         For CONFIG_KASAN_GENERIC this requires GCC 5.0 or later.
 
 endchoice
 
@@ -67,11 +123,9 @@ config KASAN_S390_4_LEVEL_PAGING
          4-level paging instead.
 
 config TEST_KASAN
-       tristate "Module for testing kasan for bug detection"
+       tristate "Module for testing KASAN for bug detection"
        depends on m && KASAN
        help
          This is a test module doing various nasty things like
          out of bounds accesses, use after free. It is useful for testing
-         kernel debugging features like kernel address sanitizer.
-
-endif
+         kernel debugging features like KASAN.
index 14afeeb7d6ef5b91929702af25f96ef4eeb711ec..55437fd5128bede3c172b8f6ac9bc7041d5733a2 100644 (file)
@@ -1131,11 +1131,10 @@ static int __init debug_objects_replace_static_objects(void)
        }
 
        /*
-        * When debug_objects_mem_init() is called we know that only
-        * one CPU is up, so disabling interrupts is enough
-        * protection. This avoids the lockdep hell of lock ordering.
+        * debug_objects_mem_init() is now called early that only one CPU is up
+        * and interrupts have been disabled, so it is safe to replace the
+        * active object references.
         */
-       local_irq_disable();
 
        /* Remove the statically allocated objects from the pool */
        hlist_for_each_entry_safe(obj, tmp, &obj_pool, node)
@@ -1156,7 +1155,6 @@ static int __init debug_objects_replace_static_objects(void)
                        cnt++;
                }
        }
-       local_irq_enable();
 
        pr_debug("%d of %d active objects replaced\n",
                 cnt, obj_pool_used);
index 517f5853ffed1726a462543f902450ddb7f9a9b4..063213685563c30c2575161f4fbc92dc1bb53d64 100644 (file)
@@ -76,83 +76,123 @@ static int ioremap_pte_range(pmd_t *pmd, unsigned long addr,
        return 0;
 }
 
+static int ioremap_try_huge_pmd(pmd_t *pmd, unsigned long addr,
+                               unsigned long end, phys_addr_t phys_addr,
+                               pgprot_t prot)
+{
+       if (!ioremap_pmd_enabled())
+               return 0;
+
+       if ((end - addr) != PMD_SIZE)
+               return 0;
+
+       if (!IS_ALIGNED(phys_addr, PMD_SIZE))
+               return 0;
+
+       if (pmd_present(*pmd) && !pmd_free_pte_page(pmd, addr))
+               return 0;
+
+       return pmd_set_huge(pmd, phys_addr, prot);
+}
+
 static inline int ioremap_pmd_range(pud_t *pud, unsigned long addr,
                unsigned long end, phys_addr_t phys_addr, pgprot_t prot)
 {
        pmd_t *pmd;
        unsigned long next;
 
-       phys_addr -= addr;
        pmd = pmd_alloc(&init_mm, pud, addr);
        if (!pmd)
                return -ENOMEM;
        do {
                next = pmd_addr_end(addr, end);
 
-               if (ioremap_pmd_enabled() &&
-                   ((next - addr) == PMD_SIZE) &&
-                   IS_ALIGNED(phys_addr + addr, PMD_SIZE) &&
-                   pmd_free_pte_page(pmd, addr)) {
-                       if (pmd_set_huge(pmd, phys_addr + addr, prot))
-                               continue;
-               }
+               if (ioremap_try_huge_pmd(pmd, addr, next, phys_addr, prot))
+                       continue;
 
-               if (ioremap_pte_range(pmd, addr, next, phys_addr + addr, prot))
+               if (ioremap_pte_range(pmd, addr, next, phys_addr, prot))
                        return -ENOMEM;
-       } while (pmd++, addr = next, addr != end);
+       } while (pmd++, phys_addr += (next - addr), addr = next, addr != end);
        return 0;
 }
 
+static int ioremap_try_huge_pud(pud_t *pud, unsigned long addr,
+                               unsigned long end, phys_addr_t phys_addr,
+                               pgprot_t prot)
+{
+       if (!ioremap_pud_enabled())
+               return 0;
+
+       if ((end - addr) != PUD_SIZE)
+               return 0;
+
+       if (!IS_ALIGNED(phys_addr, PUD_SIZE))
+               return 0;
+
+       if (pud_present(*pud) && !pud_free_pmd_page(pud, addr))
+               return 0;
+
+       return pud_set_huge(pud, phys_addr, prot);
+}
+
 static inline int ioremap_pud_range(p4d_t *p4d, unsigned long addr,
                unsigned long end, phys_addr_t phys_addr, pgprot_t prot)
 {
        pud_t *pud;
        unsigned long next;
 
-       phys_addr -= addr;
        pud = pud_alloc(&init_mm, p4d, addr);
        if (!pud)
                return -ENOMEM;
        do {
                next = pud_addr_end(addr, end);
 
-               if (ioremap_pud_enabled() &&
-                   ((next - addr) == PUD_SIZE) &&
-                   IS_ALIGNED(phys_addr + addr, PUD_SIZE) &&
-                   pud_free_pmd_page(pud, addr)) {
-                       if (pud_set_huge(pud, phys_addr + addr, prot))
-                               continue;
-               }
+               if (ioremap_try_huge_pud(pud, addr, next, phys_addr, prot))
+                       continue;
 
-               if (ioremap_pmd_range(pud, addr, next, phys_addr + addr, prot))
+               if (ioremap_pmd_range(pud, addr, next, phys_addr, prot))
                        return -ENOMEM;
-       } while (pud++, addr = next, addr != end);
+       } while (pud++, phys_addr += (next - addr), addr = next, addr != end);
        return 0;
 }
 
+static int ioremap_try_huge_p4d(p4d_t *p4d, unsigned long addr,
+                               unsigned long end, phys_addr_t phys_addr,
+                               pgprot_t prot)
+{
+       if (!ioremap_p4d_enabled())
+               return 0;
+
+       if ((end - addr) != P4D_SIZE)
+               return 0;
+
+       if (!IS_ALIGNED(phys_addr, P4D_SIZE))
+               return 0;
+
+       if (p4d_present(*p4d) && !p4d_free_pud_page(p4d, addr))
+               return 0;
+
+       return p4d_set_huge(p4d, phys_addr, prot);
+}
+
 static inline int ioremap_p4d_range(pgd_t *pgd, unsigned long addr,
                unsigned long end, phys_addr_t phys_addr, pgprot_t prot)
 {
        p4d_t *p4d;
        unsigned long next;
 
-       phys_addr -= addr;
        p4d = p4d_alloc(&init_mm, pgd, addr);
        if (!p4d)
                return -ENOMEM;
        do {
                next = p4d_addr_end(addr, end);
 
-               if (ioremap_p4d_enabled() &&
-                   ((next - addr) == P4D_SIZE) &&
-                   IS_ALIGNED(phys_addr + addr, P4D_SIZE)) {
-                       if (p4d_set_huge(p4d, phys_addr + addr, prot))
-                               continue;
-               }
+               if (ioremap_try_huge_p4d(p4d, addr, next, phys_addr, prot))
+                       continue;
 
-               if (ioremap_pud_range(p4d, addr, next, phys_addr + addr, prot))
+               if (ioremap_pud_range(p4d, addr, next, phys_addr, prot))
                        return -ENOMEM;
-       } while (p4d++, addr = next, addr != end);
+       } while (p4d++, phys_addr += (next - addr), addr = next, addr != end);
        return 0;
 }
 
@@ -168,14 +208,13 @@ int ioremap_page_range(unsigned long addr,
        BUG_ON(addr >= end);
 
        start = addr;
-       phys_addr -= addr;
        pgd = pgd_offset_k(addr);
        do {
                next = pgd_addr_end(addr, end);
-               err = ioremap_p4d_range(pgd, addr, next, phys_addr+addr, prot);
+               err = ioremap_p4d_range(pgd, addr, next, phys_addr, prot);
                if (err)
                        break;
-       } while (pgd++, addr = next, addr != end);
+       } while (pgd++, phys_addr += (next - addr), addr = next, addr != end);
 
        flush_cache_vmap(start, end);
 
index 0beaa1d899aae5b962410b4ca1b708181fb6cb32..6a042f53e7bbc6c84a7ccb61bbc4c85a7032e558 100644 (file)
@@ -18,22 +18,19 @@ void show_mem(unsigned int filter, nodemask_t *nodemask)
        show_free_areas(filter, nodemask);
 
        for_each_online_pgdat(pgdat) {
-               unsigned long flags;
                int zoneid;
 
-               pgdat_resize_lock(pgdat, &flags);
                for (zoneid = 0; zoneid < MAX_NR_ZONES; zoneid++) {
                        struct zone *zone = &pgdat->node_zones[zoneid];
                        if (!populated_zone(zone))
                                continue;
 
                        total += zone->present_pages;
-                       reserved += zone->present_pages - zone->managed_pages;
+                       reserved += zone->present_pages - zone_managed_pages(zone);
 
                        if (is_highmem_idx(zoneid))
                                highmem += zone->present_pages;
                }
-               pgdat_resize_unlock(pgdat, &flags);
        }
 
        printk("%lu pages RAM\n", total);
index d85e39da47aed166d58f7bba669d60afb12bad59..25c71eb8a7dbd9170f29cdbca9d273d02afb1cf3 100644 (file)
@@ -291,6 +291,7 @@ config MMU_NOTIFIER
 config KSM
        bool "Enable KSM for page merging"
        depends on MMU
+       select XXHASH
        help
          Enable Kernel Samepage Merging: KSM periodically scans those areas
          of an application's address space that an app has advised may be
index 4cb76121a3ab065de3157547e4f1b828d16f07ec..c7b39dd3b4f65f07e6b3ed5582601b52c9d8393b 100644 (file)
--- a/mm/cma.c
+++ b/mm/cma.c
@@ -407,6 +407,7 @@ struct page *cma_alloc(struct cma *cma, size_t count, unsigned int align,
        unsigned long pfn = -1;
        unsigned long start = 0;
        unsigned long bitmap_maxno, bitmap_no, bitmap_count;
+       size_t i;
        struct page *page = NULL;
        int ret = -ENOMEM;
 
@@ -466,6 +467,16 @@ struct page *cma_alloc(struct cma *cma, size_t count, unsigned int align,
 
        trace_cma_alloc(pfn, page, count, align);
 
+       /*
+        * CMA can allocate multiple page blocks, which results in different
+        * blocks being marked with different tags. Reset the tags to ignore
+        * those page blocks.
+        */
+       if (page) {
+               for (i = 0; i < count; i++)
+                       page_kasan_tag_reset(page + i);
+       }
+
        if (ret && !no_warn) {
                pr_err("%s: alloc failed, req-size: %zu pages, ret: %d\n",
                        __func__, count, ret);
index 7c607479de4a8b9c871f5b5dafbbc10784a7c6d4..ef29490b0f462349ec90b8672448f80627ef3af6 100644 (file)
@@ -1431,7 +1431,7 @@ static enum compact_result __compaction_suitable(struct zone *zone, int order,
        if (is_via_compact_memory(order))
                return COMPACT_CONTINUE;
 
-       watermark = zone->watermark[alloc_flags & ALLOC_WMARK_MASK];
+       watermark = wmark_pages(zone, alloc_flags & ALLOC_WMARK_MASK);
        /*
         * If watermarks for high-order allocation are already met, there
         * should be no need for compaction at all.
index cdacba12e09aeebdcd4c2e5c904a59d8e940aaeb..0abb987dad9b3d697f252469d2111dc61f530913 100644 (file)
@@ -17,7 +17,7 @@
 
 #include "internal.h"
 
-char *migrate_reason_names[MR_TYPES] = {
+const char *migrate_reason_names[MR_TYPES] = {
        "compaction",
        "memory_failure",
        "memory_hotplug",
@@ -44,6 +44,7 @@ const struct trace_print_flags vmaflag_names[] = {
 
 void __dump_page(struct page *page, const char *reason)
 {
+       struct address_space *mapping = page_mapping(page);
        bool page_poisoned = PagePoisoned(page);
        int mapcount;
 
@@ -53,7 +54,7 @@ void __dump_page(struct page *page, const char *reason)
         * dump_page() when detected.
         */
        if (page_poisoned) {
-               pr_emerg("page:%px is uninitialized and poisoned", page);
+               pr_warn("page:%px is uninitialized and poisoned", page);
                goto hex_only;
        }
 
@@ -64,27 +65,39 @@ void __dump_page(struct page *page, const char *reason)
         */
        mapcount = PageSlab(page) ? 0 : page_mapcount(page);
 
-       pr_emerg("page:%px count:%d mapcount:%d mapping:%px index:%#lx",
+       pr_warn("page:%px count:%d mapcount:%d mapping:%px index:%#lx",
                  page, page_ref_count(page), mapcount,
                  page->mapping, page_to_pgoff(page));
        if (PageCompound(page))
                pr_cont(" compound_mapcount: %d", compound_mapcount(page));
        pr_cont("\n");
+       if (PageAnon(page))
+               pr_warn("anon ");
+       else if (PageKsm(page))
+               pr_warn("ksm ");
+       else if (mapping) {
+               pr_warn("%ps ", mapping->a_ops);
+               if (mapping->host->i_dentry.first) {
+                       struct dentry *dentry;
+                       dentry = container_of(mapping->host->i_dentry.first, struct dentry, d_u.d_alias);
+                       pr_warn("name:\"%pd\" ", dentry);
+               }
+       }
        BUILD_BUG_ON(ARRAY_SIZE(pageflag_names) != __NR_PAGEFLAGS + 1);
 
-       pr_emerg("flags: %#lx(%pGp)\n", page->flags, &page->flags);
+       pr_warn("flags: %#lx(%pGp)\n", page->flags, &page->flags);
 
 hex_only:
-       print_hex_dump(KERN_ALERT, "raw: ", DUMP_PREFIX_NONE, 32,
+       print_hex_dump(KERN_WARNING, "raw: ", DUMP_PREFIX_NONE, 32,
                        sizeof(unsigned long), page,
                        sizeof(struct page), false);
 
        if (reason)
-               pr_alert("page dumped because: %s\n", reason);
+               pr_warn("page dumped because: %s\n", reason);
 
 #ifdef CONFIG_MEMCG
        if (!page_poisoned && page->mem_cgroup)
-               pr_alert("page->mem_cgroup:%px\n", page->mem_cgroup);
+               pr_warn("page->mem_cgroup:%px\n", page->mem_cgroup);
 #endif
 }
 
index 81adec8ee02cc3bdb765625e28c3d765f203e512..29655fb47a2c4b2cf61e1c61e5b06d6f51e537a8 100644 (file)
@@ -981,7 +981,14 @@ static int wake_page_function(wait_queue_entry_t *wait, unsigned mode, int sync,
        if (wait_page->bit_nr != key->bit_nr)
                return 0;
 
-       /* Stop walking if it's locked */
+       /*
+        * Stop walking if it's locked.
+        * Is this safe if put_and_wait_on_page_locked() is in use?
+        * Yes: the waker must hold a reference to this page, and if PG_locked
+        * has now already been set by another task, that task must also hold
+        * a reference to the *same usage* of this page; so there is no need
+        * to walk on to wake even the put_and_wait_on_page_locked() callers.
+        */
        if (test_bit(key->bit_nr, &key->page->flags))
                return -1;
 
@@ -1049,25 +1056,44 @@ static void wake_up_page(struct page *page, int bit)
        wake_up_page_bit(page, bit);
 }
 
+/*
+ * A choice of three behaviors for wait_on_page_bit_common():
+ */
+enum behavior {
+       EXCLUSIVE,      /* Hold ref to page and take the bit when woken, like
+                        * __lock_page() waiting on then setting PG_locked.
+                        */
+       SHARED,         /* Hold ref to page and check the bit when woken, like
+                        * wait_on_page_writeback() waiting on PG_writeback.
+                        */
+       DROP,           /* Drop ref to page before wait, no check when woken,
+                        * like put_and_wait_on_page_locked() on PG_locked.
+                        */
+};
+
 static inline int wait_on_page_bit_common(wait_queue_head_t *q,
-               struct page *page, int bit_nr, int state, bool lock)
+       struct page *page, int bit_nr, int state, enum behavior behavior)
 {
        struct wait_page_queue wait_page;
        wait_queue_entry_t *wait = &wait_page.wait;
+       bool bit_is_set;
        bool thrashing = false;
+       bool delayacct = false;
        unsigned long pflags;
        int ret = 0;
 
        if (bit_nr == PG_locked &&
            !PageUptodate(page) && PageWorkingset(page)) {
-               if (!PageSwapBacked(page))
+               if (!PageSwapBacked(page)) {
                        delayacct_thrashing_start();
+                       delayacct = true;
+               }
                psi_memstall_enter(&pflags);
                thrashing = true;
        }
 
        init_wait(wait);
-       wait->flags = lock ? WQ_FLAG_EXCLUSIVE : 0;
+       wait->flags = behavior == EXCLUSIVE ? WQ_FLAG_EXCLUSIVE : 0;
        wait->func = wake_page_function;
        wait_page.page = page;
        wait_page.bit_nr = bit_nr;
@@ -1084,14 +1110,17 @@ static inline int wait_on_page_bit_common(wait_queue_head_t *q,
 
                spin_unlock_irq(&q->lock);
 
-               if (likely(test_bit(bit_nr, &page->flags))) {
+               bit_is_set = test_bit(bit_nr, &page->flags);
+               if (behavior == DROP)
+                       put_page(page);
+
+               if (likely(bit_is_set))
                        io_schedule();
-               }
 
-               if (lock) {
+               if (behavior == EXCLUSIVE) {
                        if (!test_and_set_bit_lock(bit_nr, &page->flags))
                                break;
-               } else {
+               } else if (behavior == SHARED) {
                        if (!test_bit(bit_nr, &page->flags))
                                break;
                }
@@ -1100,12 +1129,23 @@ static inline int wait_on_page_bit_common(wait_queue_head_t *q,
                        ret = -EINTR;
                        break;
                }
+
+               if (behavior == DROP) {
+                       /*
+                        * We can no longer safely access page->flags:
+                        * even if CONFIG_MEMORY_HOTREMOVE is not enabled,
+                        * there is a risk of waiting forever on a page reused
+                        * for something that keeps it locked indefinitely.
+                        * But best check for -EINTR above before breaking.
+                        */
+                       break;
+               }
        }
 
        finish_wait(q, wait);
 
        if (thrashing) {
-               if (!PageSwapBacked(page))
+               if (delayacct)
                        delayacct_thrashing_end();
                psi_memstall_leave(&pflags);
        }
@@ -1124,17 +1164,36 @@ static inline int wait_on_page_bit_common(wait_queue_head_t *q,
 void wait_on_page_bit(struct page *page, int bit_nr)
 {
        wait_queue_head_t *q = page_waitqueue(page);
-       wait_on_page_bit_common(q, page, bit_nr, TASK_UNINTERRUPTIBLE, false);
+       wait_on_page_bit_common(q, page, bit_nr, TASK_UNINTERRUPTIBLE, SHARED);
 }
 EXPORT_SYMBOL(wait_on_page_bit);
 
 int wait_on_page_bit_killable(struct page *page, int bit_nr)
 {
        wait_queue_head_t *q = page_waitqueue(page);
-       return wait_on_page_bit_common(q, page, bit_nr, TASK_KILLABLE, false);
+       return wait_on_page_bit_common(q, page, bit_nr, TASK_KILLABLE, SHARED);
 }
 EXPORT_SYMBOL(wait_on_page_bit_killable);
 
+/**
+ * put_and_wait_on_page_locked - Drop a reference and wait for it to be unlocked
+ * @page: The page to wait for.
+ *
+ * The caller should hold a reference on @page.  They expect the page to
+ * become unlocked relatively soon, but do not wish to hold up migration
+ * (for example) by holding the reference while waiting for the page to
+ * come unlocked.  After this function returns, the caller should not
+ * dereference @page.
+ */
+void put_and_wait_on_page_locked(struct page *page)
+{
+       wait_queue_head_t *q;
+
+       page = compound_head(page);
+       q = page_waitqueue(page);
+       wait_on_page_bit_common(q, page, PG_locked, TASK_UNINTERRUPTIBLE, DROP);
+}
+
 /**
  * add_page_wait_queue - Add an arbitrary waiter to a page's wait queue
  * @page: Page defining the wait queue of interest
@@ -1264,7 +1323,8 @@ void __lock_page(struct page *__page)
 {
        struct page *page = compound_head(__page);
        wait_queue_head_t *q = page_waitqueue(page);
-       wait_on_page_bit_common(q, page, PG_locked, TASK_UNINTERRUPTIBLE, true);
+       wait_on_page_bit_common(q, page, PG_locked, TASK_UNINTERRUPTIBLE,
+                               EXCLUSIVE);
 }
 EXPORT_SYMBOL(__lock_page);
 
@@ -1272,7 +1332,8 @@ int __lock_page_killable(struct page *__page)
 {
        struct page *page = compound_head(__page);
        wait_queue_head_t *q = page_waitqueue(page);
-       return wait_on_page_bit_common(q, page, PG_locked, TASK_KILLABLE, true);
+       return wait_on_page_bit_common(q, page, PG_locked, TASK_KILLABLE,
+                                       EXCLUSIVE);
 }
 EXPORT_SYMBOL_GPL(__lock_page_killable);
 
@@ -1540,7 +1601,7 @@ repeat:
                VM_BUG_ON_PAGE(page->index != offset, page);
        }
 
-       if (page && (fgp_flags & FGP_ACCESSED))
+       if (fgp_flags & FGP_ACCESSED)
                mark_page_accessed(page);
 
 no_page:
@@ -2553,6 +2614,13 @@ void filemap_map_pages(struct vm_fault *vmf,
                        goto next;
 
                head = compound_head(page);
+
+               /*
+                * Check for a locked page first, as a speculative
+                * reference may adversely influence page migration.
+                */
+               if (PageLocked(head))
+                       goto next;
                if (!page_cache_get_speculative(head))
                        goto next;
 
index 59db3223a5d62a9ea26f506ed3fd9fe6d54d2cf2..107b10f9878ef73bb936721728d28b39612884bd 100644 (file)
@@ -105,9 +105,8 @@ static inline wait_queue_head_t *get_pkmap_wait_queue_head(unsigned int color)
 }
 #endif
 
-unsigned long totalhigh_pages __read_mostly;
-EXPORT_SYMBOL(totalhigh_pages);
-
+atomic_long_t _totalhigh_pages __read_mostly;
+EXPORT_SYMBOL(_totalhigh_pages);
 
 EXPORT_PER_CPU_SYMBOL(__kmap_atomic_idx);
 
index 90c34f3d1243aa5ec18970ec7aac095d8f657d32..a04e4b81061012b003c260d8e3cabc388947090c 100644 (file)
--- a/mm/hmm.c
+++ b/mm/hmm.c
@@ -189,35 +189,30 @@ static void hmm_release(struct mmu_notifier *mn, struct mm_struct *mm)
 }
 
 static int hmm_invalidate_range_start(struct mmu_notifier *mn,
-                                     struct mm_struct *mm,
-                                     unsigned long start,
-                                     unsigned long end,
-                                     bool blockable)
+                       const struct mmu_notifier_range *range)
 {
        struct hmm_update update;
-       struct hmm *hmm = mm->hmm;
+       struct hmm *hmm = range->mm->hmm;
 
        VM_BUG_ON(!hmm);
 
-       update.start = start;
-       update.end = end;
+       update.start = range->start;
+       update.end = range->end;
        update.event = HMM_UPDATE_INVALIDATE;
-       update.blockable = blockable;
+       update.blockable = range->blockable;
        return hmm_invalidate_range(hmm, true, &update);
 }
 
 static void hmm_invalidate_range_end(struct mmu_notifier *mn,
-                                    struct mm_struct *mm,
-                                    unsigned long start,
-                                    unsigned long end)
+                       const struct mmu_notifier_range *range)
 {
        struct hmm_update update;
-       struct hmm *hmm = mm->hmm;
+       struct hmm *hmm = range->mm->hmm;
 
        VM_BUG_ON(!hmm);
 
-       update.start = start;
-       update.end = end;
+       update.start = range->start;
+       update.end = range->end;
        update.event = HMM_UPDATE_INVALIDATE;
        update.blockable = true;
        hmm_invalidate_range(hmm, false, &update);
@@ -986,19 +981,13 @@ static void hmm_devmem_ref_exit(void *data)
        struct hmm_devmem *devmem;
 
        devmem = container_of(ref, struct hmm_devmem, ref);
+       wait_for_completion(&devmem->completion);
        percpu_ref_exit(ref);
-       devm_remove_action(devmem->device, &hmm_devmem_ref_exit, data);
 }
 
-static void hmm_devmem_ref_kill(void *data)
+static void hmm_devmem_ref_kill(struct percpu_ref *ref)
 {
-       struct percpu_ref *ref = data;
-       struct hmm_devmem *devmem;
-
-       devmem = container_of(ref, struct hmm_devmem, ref);
        percpu_ref_kill(ref);
-       wait_for_completion(&devmem->completion);
-       devm_remove_action(devmem->device, &hmm_devmem_ref_kill, data);
 }
 
 static int hmm_devmem_fault(struct vm_area_struct *vma,
@@ -1021,172 +1010,6 @@ static void hmm_devmem_free(struct page *page, void *data)
        devmem->ops->free(devmem, page);
 }
 
-static DEFINE_MUTEX(hmm_devmem_lock);
-static RADIX_TREE(hmm_devmem_radix, GFP_KERNEL);
-
-static void hmm_devmem_radix_release(struct resource *resource)
-{
-       resource_size_t key;
-
-       mutex_lock(&hmm_devmem_lock);
-       for (key = resource->start;
-            key <= resource->end;
-            key += PA_SECTION_SIZE)
-               radix_tree_delete(&hmm_devmem_radix, key >> PA_SECTION_SHIFT);
-       mutex_unlock(&hmm_devmem_lock);
-}
-
-static void hmm_devmem_release(struct device *dev, void *data)
-{
-       struct hmm_devmem *devmem = data;
-       struct resource *resource = devmem->resource;
-       unsigned long start_pfn, npages;
-       struct zone *zone;
-       struct page *page;
-
-       if (percpu_ref_tryget_live(&devmem->ref)) {
-               dev_WARN(dev, "%s: page mapping is still live!\n", __func__);
-               percpu_ref_put(&devmem->ref);
-       }
-
-       /* pages are dead and unused, undo the arch mapping */
-       start_pfn = (resource->start & ~(PA_SECTION_SIZE - 1)) >> PAGE_SHIFT;
-       npages = ALIGN(resource_size(resource), PA_SECTION_SIZE) >> PAGE_SHIFT;
-
-       page = pfn_to_page(start_pfn);
-       zone = page_zone(page);
-
-       mem_hotplug_begin();
-       if (resource->desc == IORES_DESC_DEVICE_PRIVATE_MEMORY)
-               __remove_pages(zone, start_pfn, npages, NULL);
-       else
-               arch_remove_memory(start_pfn << PAGE_SHIFT,
-                                  npages << PAGE_SHIFT, NULL);
-       mem_hotplug_done();
-
-       hmm_devmem_radix_release(resource);
-}
-
-static int hmm_devmem_pages_create(struct hmm_devmem *devmem)
-{
-       resource_size_t key, align_start, align_size, align_end;
-       struct device *device = devmem->device;
-       int ret, nid, is_ram;
-
-       align_start = devmem->resource->start & ~(PA_SECTION_SIZE - 1);
-       align_size = ALIGN(devmem->resource->start +
-                          resource_size(devmem->resource),
-                          PA_SECTION_SIZE) - align_start;
-
-       is_ram = region_intersects(align_start, align_size,
-                                  IORESOURCE_SYSTEM_RAM,
-                                  IORES_DESC_NONE);
-       if (is_ram == REGION_MIXED) {
-               WARN_ONCE(1, "%s attempted on mixed region %pr\n",
-                               __func__, devmem->resource);
-               return -ENXIO;
-       }
-       if (is_ram == REGION_INTERSECTS)
-               return -ENXIO;
-
-       if (devmem->resource->desc == IORES_DESC_DEVICE_PUBLIC_MEMORY)
-               devmem->pagemap.type = MEMORY_DEVICE_PUBLIC;
-       else
-               devmem->pagemap.type = MEMORY_DEVICE_PRIVATE;
-
-       devmem->pagemap.res = *devmem->resource;
-       devmem->pagemap.page_fault = hmm_devmem_fault;
-       devmem->pagemap.page_free = hmm_devmem_free;
-       devmem->pagemap.dev = devmem->device;
-       devmem->pagemap.ref = &devmem->ref;
-       devmem->pagemap.data = devmem;
-
-       mutex_lock(&hmm_devmem_lock);
-       align_end = align_start + align_size - 1;
-       for (key = align_start; key <= align_end; key += PA_SECTION_SIZE) {
-               struct hmm_devmem *dup;
-
-               dup = radix_tree_lookup(&hmm_devmem_radix,
-                                       key >> PA_SECTION_SHIFT);
-               if (dup) {
-                       dev_err(device, "%s: collides with mapping for %s\n",
-                               __func__, dev_name(dup->device));
-                       mutex_unlock(&hmm_devmem_lock);
-                       ret = -EBUSY;
-                       goto error;
-               }
-               ret = radix_tree_insert(&hmm_devmem_radix,
-                                       key >> PA_SECTION_SHIFT,
-                                       devmem);
-               if (ret) {
-                       dev_err(device, "%s: failed: %d\n", __func__, ret);
-                       mutex_unlock(&hmm_devmem_lock);
-                       goto error_radix;
-               }
-       }
-       mutex_unlock(&hmm_devmem_lock);
-
-       nid = dev_to_node(device);
-       if (nid < 0)
-               nid = numa_mem_id();
-
-       mem_hotplug_begin();
-       /*
-        * For device private memory we call add_pages() as we only need to
-        * allocate and initialize struct page for the device memory. More-
-        * over the device memory is un-accessible thus we do not want to
-        * create a linear mapping for the memory like arch_add_memory()
-        * would do.
-        *
-        * For device public memory, which is accesible by the CPU, we do
-        * want the linear mapping and thus use arch_add_memory().
-        */
-       if (devmem->pagemap.type == MEMORY_DEVICE_PUBLIC)
-               ret = arch_add_memory(nid, align_start, align_size, NULL,
-                               false);
-       else
-               ret = add_pages(nid, align_start >> PAGE_SHIFT,
-                               align_size >> PAGE_SHIFT, NULL, false);
-       if (ret) {
-               mem_hotplug_done();
-               goto error_add_memory;
-       }
-       move_pfn_range_to_zone(&NODE_DATA(nid)->node_zones[ZONE_DEVICE],
-                               align_start >> PAGE_SHIFT,
-                               align_size >> PAGE_SHIFT, NULL);
-       mem_hotplug_done();
-
-       /*
-        * Initialization of the pages has been deferred until now in order
-        * to allow us to do the work while not holding the hotplug lock.
-        */
-       memmap_init_zone_device(&NODE_DATA(nid)->node_zones[ZONE_DEVICE],
-                               align_start >> PAGE_SHIFT,
-                               align_size >> PAGE_SHIFT, &devmem->pagemap);
-
-       return 0;
-
-error_add_memory:
-       untrack_pfn(NULL, PHYS_PFN(align_start), align_size);
-error_radix:
-       hmm_devmem_radix_release(devmem->resource);
-error:
-       return ret;
-}
-
-static int hmm_devmem_match(struct device *dev, void *data, void *match_data)
-{
-       struct hmm_devmem *devmem = data;
-
-       return devmem->resource == match_data;
-}
-
-static void hmm_devmem_pages_remove(struct hmm_devmem *devmem)
-{
-       devres_release(devmem->device, &hmm_devmem_release,
-                      &hmm_devmem_match, devmem->resource);
-}
-
 /*
  * hmm_devmem_add() - hotplug ZONE_DEVICE memory for device memory
  *
@@ -1210,12 +1033,12 @@ struct hmm_devmem *hmm_devmem_add(const struct hmm_devmem_ops *ops,
 {
        struct hmm_devmem *devmem;
        resource_size_t addr;
+       void *result;
        int ret;
 
        dev_pagemap_get_ops();
 
-       devmem = devres_alloc_node(&hmm_devmem_release, sizeof(*devmem),
-                                  GFP_KERNEL, dev_to_node(device));
+       devmem = devm_kzalloc(device, sizeof(*devmem), GFP_KERNEL);
        if (!devmem)
                return ERR_PTR(-ENOMEM);
 
@@ -1229,11 +1052,11 @@ struct hmm_devmem *hmm_devmem_add(const struct hmm_devmem_ops *ops,
        ret = percpu_ref_init(&devmem->ref, &hmm_devmem_ref_release,
                              0, GFP_KERNEL);
        if (ret)
-               goto error_percpu_ref;
+               return ERR_PTR(ret);
 
-       ret = devm_add_action(device, hmm_devmem_ref_exit, &devmem->ref);
+       ret = devm_add_action_or_reset(device, hmm_devmem_ref_exit, &devmem->ref);
        if (ret)
-               goto error_devm_add_action;
+               return ERR_PTR(ret);
 
        size = ALIGN(size, PA_SECTION_SIZE);
        addr = min((unsigned long)iomem_resource.end,
@@ -1253,54 +1076,40 @@ struct hmm_devmem *hmm_devmem_add(const struct hmm_devmem_ops *ops,
 
                devmem->resource = devm_request_mem_region(device, addr, size,
                                                           dev_name(device));
-               if (!devmem->resource) {
-                       ret = -ENOMEM;
-                       goto error_no_resource;
-               }
+               if (!devmem->resource)
+                       return ERR_PTR(-ENOMEM);
                break;
        }
-       if (!devmem->resource) {
-               ret = -ERANGE;
-               goto error_no_resource;
-       }
+       if (!devmem->resource)
+               return ERR_PTR(-ERANGE);
 
        devmem->resource->desc = IORES_DESC_DEVICE_PRIVATE_MEMORY;
        devmem->pfn_first = devmem->resource->start >> PAGE_SHIFT;
        devmem->pfn_last = devmem->pfn_first +
                           (resource_size(devmem->resource) >> PAGE_SHIFT);
+       devmem->page_fault = hmm_devmem_fault;
 
-       ret = hmm_devmem_pages_create(devmem);
-       if (ret)
-               goto error_pages;
-
-       devres_add(device, devmem);
-
-       ret = devm_add_action(device, hmm_devmem_ref_kill, &devmem->ref);
-       if (ret) {
-               hmm_devmem_remove(devmem);
-               return ERR_PTR(ret);
-       }
+       devmem->pagemap.type = MEMORY_DEVICE_PRIVATE;
+       devmem->pagemap.res = *devmem->resource;
+       devmem->pagemap.page_free = hmm_devmem_free;
+       devmem->pagemap.altmap_valid = false;
+       devmem->pagemap.ref = &devmem->ref;
+       devmem->pagemap.data = devmem;
+       devmem->pagemap.kill = hmm_devmem_ref_kill;
 
+       result = devm_memremap_pages(devmem->device, &devmem->pagemap);
+       if (IS_ERR(result))
+               return result;
        return devmem;
-
-error_pages:
-       devm_release_mem_region(device, devmem->resource->start,
-                               resource_size(devmem->resource));
-error_no_resource:
-error_devm_add_action:
-       hmm_devmem_ref_kill(&devmem->ref);
-       hmm_devmem_ref_exit(&devmem->ref);
-error_percpu_ref:
-       devres_free(devmem);
-       return ERR_PTR(ret);
 }
-EXPORT_SYMBOL(hmm_devmem_add);
+EXPORT_SYMBOL_GPL(hmm_devmem_add);
 
 struct hmm_devmem *hmm_devmem_add_resource(const struct hmm_devmem_ops *ops,
                                           struct device *device,
                                           struct resource *res)
 {
        struct hmm_devmem *devmem;
+       void *result;
        int ret;
 
        if (res->desc != IORES_DESC_DEVICE_PUBLIC_MEMORY)
@@ -1308,8 +1117,7 @@ struct hmm_devmem *hmm_devmem_add_resource(const struct hmm_devmem_ops *ops,
 
        dev_pagemap_get_ops();
 
-       devmem = devres_alloc_node(&hmm_devmem_release, sizeof(*devmem),
-                                  GFP_KERNEL, dev_to_node(device));
+       devmem = devm_kzalloc(device, sizeof(*devmem), GFP_KERNEL);
        if (!devmem)
                return ERR_PTR(-ENOMEM);
 
@@ -1323,71 +1131,32 @@ struct hmm_devmem *hmm_devmem_add_resource(const struct hmm_devmem_ops *ops,
        ret = percpu_ref_init(&devmem->ref, &hmm_devmem_ref_release,
                              0, GFP_KERNEL);
        if (ret)
-               goto error_percpu_ref;
+               return ERR_PTR(ret);
 
-       ret = devm_add_action(device, hmm_devmem_ref_exit, &devmem->ref);
+       ret = devm_add_action_or_reset(device, hmm_devmem_ref_exit,
+                       &devmem->ref);
        if (ret)
-               goto error_devm_add_action;
-
+               return ERR_PTR(ret);
 
        devmem->pfn_first = devmem->resource->start >> PAGE_SHIFT;
        devmem->pfn_last = devmem->pfn_first +
                           (resource_size(devmem->resource) >> PAGE_SHIFT);
+       devmem->page_fault = hmm_devmem_fault;
 
-       ret = hmm_devmem_pages_create(devmem);
-       if (ret)
-               goto error_devm_add_action;
-
-       devres_add(device, devmem);
-
-       ret = devm_add_action(device, hmm_devmem_ref_kill, &devmem->ref);
-       if (ret) {
-               hmm_devmem_remove(devmem);
-               return ERR_PTR(ret);
-       }
+       devmem->pagemap.type = MEMORY_DEVICE_PUBLIC;
+       devmem->pagemap.res = *devmem->resource;
+       devmem->pagemap.page_free = hmm_devmem_free;
+       devmem->pagemap.altmap_valid = false;
+       devmem->pagemap.ref = &devmem->ref;
+       devmem->pagemap.data = devmem;
+       devmem->pagemap.kill = hmm_devmem_ref_kill;
 
+       result = devm_memremap_pages(devmem->device, &devmem->pagemap);
+       if (IS_ERR(result))
+               return result;
        return devmem;
-
-error_devm_add_action:
-       hmm_devmem_ref_kill(&devmem->ref);
-       hmm_devmem_ref_exit(&devmem->ref);
-error_percpu_ref:
-       devres_free(devmem);
-       return ERR_PTR(ret);
-}
-EXPORT_SYMBOL(hmm_devmem_add_resource);
-
-/*
- * hmm_devmem_remove() - remove device memory (kill and free ZONE_DEVICE)
- *
- * @devmem: hmm_devmem struct use to track and manage the ZONE_DEVICE memory
- *
- * This will hot-unplug memory that was hotplugged by hmm_devmem_add on behalf
- * of the device driver. It will free struct page and remove the resource that
- * reserved the physical address range for this device memory.
- */
-void hmm_devmem_remove(struct hmm_devmem *devmem)
-{
-       resource_size_t start, size;
-       struct device *device;
-       bool cdm = false;
-
-       if (!devmem)
-               return;
-
-       device = devmem->device;
-       start = devmem->resource->start;
-       size = resource_size(devmem->resource);
-
-       cdm = devmem->resource->desc == IORES_DESC_DEVICE_PUBLIC_MEMORY;
-       hmm_devmem_ref_kill(&devmem->ref);
-       hmm_devmem_ref_exit(&devmem->ref);
-       hmm_devmem_pages_remove(devmem);
-
-       if (!cdm)
-               devm_release_mem_region(device, start, size);
 }
-EXPORT_SYMBOL(hmm_devmem_remove);
+EXPORT_SYMBOL_GPL(hmm_devmem_add_resource);
 
 /*
  * A device driver that wants to handle multiple devices memory through a
index e84a10b0d310d0be5acebedcd2d422fe5e928f86..cbd977b1d60d4006d854c92f3e79141bdb7f4493 100644 (file)
@@ -62,6 +62,16 @@ static struct shrinker deferred_split_shrinker;
 static atomic_t huge_zero_refcount;
 struct page *huge_zero_page __read_mostly;
 
+bool transparent_hugepage_enabled(struct vm_area_struct *vma)
+{
+       if (vma_is_anonymous(vma))
+               return __transparent_hugepage_enabled(vma);
+       if (vma_is_shmem(vma) && shmem_huge_enabled(vma))
+               return __transparent_hugepage_enabled(vma);
+
+       return false;
+}
+
 static struct page *get_huge_zero_page(void)
 {
        struct page *zero_page;
@@ -420,7 +430,7 @@ static int __init hugepage_init(void)
         * where the extra memory used could hurt more than TLB overhead
         * is likely to save.  The admin can still enable it through /sys.
         */
-       if (totalram_pages < (512 << (20 - PAGE_SHIFT))) {
+       if (totalram_pages() < (512 << (20 - PAGE_SHIFT))) {
                transparent_hugepage_flags = 0;
                return 0;
        }
@@ -1134,8 +1144,7 @@ static vm_fault_t do_huge_pmd_wp_page_fallback(struct vm_fault *vmf,
        int i;
        vm_fault_t ret = 0;
        struct page **pages;
-       unsigned long mmun_start;       /* For mmu_notifiers */
-       unsigned long mmun_end;         /* For mmu_notifiers */
+       struct mmu_notifier_range range;
 
        pages = kmalloc_array(HPAGE_PMD_NR, sizeof(struct page *),
                              GFP_KERNEL);
@@ -1173,9 +1182,9 @@ static vm_fault_t do_huge_pmd_wp_page_fallback(struct vm_fault *vmf,
                cond_resched();
        }
 
-       mmun_start = haddr;
-       mmun_end   = haddr + HPAGE_PMD_SIZE;
-       mmu_notifier_invalidate_range_start(vma->vm_mm, mmun_start, mmun_end);
+       mmu_notifier_range_init(&range, vma->vm_mm, haddr,
+                               haddr + HPAGE_PMD_SIZE);
+       mmu_notifier_invalidate_range_start(&range);
 
        vmf->ptl = pmd_lock(vma->vm_mm, vmf->pmd);
        if (unlikely(!pmd_same(*vmf->pmd, orig_pmd)))
@@ -1220,8 +1229,7 @@ static vm_fault_t do_huge_pmd_wp_page_fallback(struct vm_fault *vmf,
         * No need to double call mmu_notifier->invalidate_range() callback as
         * the above pmdp_huge_clear_flush_notify() did already call it.
         */
-       mmu_notifier_invalidate_range_only_end(vma->vm_mm, mmun_start,
-                                               mmun_end);
+       mmu_notifier_invalidate_range_only_end(&range);
 
        ret |= VM_FAULT_WRITE;
        put_page(page);
@@ -1231,7 +1239,7 @@ out:
 
 out_free_pages:
        spin_unlock(vmf->ptl);
-       mmu_notifier_invalidate_range_end(vma->vm_mm, mmun_start, mmun_end);
+       mmu_notifier_invalidate_range_end(&range);
        for (i = 0; i < HPAGE_PMD_NR; i++) {
                memcg = (void *)page_private(pages[i]);
                set_page_private(pages[i], 0);
@@ -1248,8 +1256,7 @@ vm_fault_t do_huge_pmd_wp_page(struct vm_fault *vmf, pmd_t orig_pmd)
        struct page *page = NULL, *new_page;
        struct mem_cgroup *memcg;
        unsigned long haddr = vmf->address & HPAGE_PMD_MASK;
-       unsigned long mmun_start;       /* For mmu_notifiers */
-       unsigned long mmun_end;         /* For mmu_notifiers */
+       struct mmu_notifier_range range;
        gfp_t huge_gfp;                 /* for allocation and charge */
        vm_fault_t ret = 0;
 
@@ -1293,7 +1300,7 @@ vm_fault_t do_huge_pmd_wp_page(struct vm_fault *vmf, pmd_t orig_pmd)
        get_page(page);
        spin_unlock(vmf->ptl);
 alloc:
-       if (transparent_hugepage_enabled(vma) &&
+       if (__transparent_hugepage_enabled(vma) &&
            !transparent_hugepage_debug_cow()) {
                huge_gfp = alloc_hugepage_direct_gfpmask(vma);
                new_page = alloc_hugepage_vma(huge_gfp, vma, haddr, HPAGE_PMD_ORDER);
@@ -1338,9 +1345,9 @@ alloc:
                                    vma, HPAGE_PMD_NR);
        __SetPageUptodate(new_page);
 
-       mmun_start = haddr;
-       mmun_end   = haddr + HPAGE_PMD_SIZE;
-       mmu_notifier_invalidate_range_start(vma->vm_mm, mmun_start, mmun_end);
+       mmu_notifier_range_init(&range, vma->vm_mm, haddr,
+                               haddr + HPAGE_PMD_SIZE);
+       mmu_notifier_invalidate_range_start(&range);
 
        spin_lock(vmf->ptl);
        if (page)
@@ -1375,8 +1382,7 @@ out_mn:
         * No need to double call mmu_notifier->invalidate_range() callback as
         * the above pmdp_huge_clear_flush_notify() did already call it.
         */
-       mmu_notifier_invalidate_range_only_end(vma->vm_mm, mmun_start,
-                                              mmun_end);
+       mmu_notifier_invalidate_range_only_end(&range);
 out:
        return ret;
 out_unlock:
@@ -1490,8 +1496,7 @@ vm_fault_t do_huge_pmd_numa_page(struct vm_fault *vmf, pmd_t pmd)
                if (!get_page_unless_zero(page))
                        goto out_unlock;
                spin_unlock(vmf->ptl);
-               wait_on_page_locked(page);
-               put_page(page);
+               put_and_wait_on_page_locked(page);
                goto out;
        }
 
@@ -1527,8 +1532,7 @@ vm_fault_t do_huge_pmd_numa_page(struct vm_fault *vmf, pmd_t pmd)
                if (!get_page_unless_zero(page))
                        goto out_unlock;
                spin_unlock(vmf->ptl);
-               wait_on_page_locked(page);
-               put_page(page);
+               put_and_wait_on_page_locked(page);
                goto out;
        }
 
@@ -2017,14 +2021,15 @@ void __split_huge_pud(struct vm_area_struct *vma, pud_t *pud,
                unsigned long address)
 {
        spinlock_t *ptl;
-       struct mm_struct *mm = vma->vm_mm;
-       unsigned long haddr = address & HPAGE_PUD_MASK;
+       struct mmu_notifier_range range;
 
-       mmu_notifier_invalidate_range_start(mm, haddr, haddr + HPAGE_PUD_SIZE);
-       ptl = pud_lock(mm, pud);
+       mmu_notifier_range_init(&range, vma->vm_mm, address & HPAGE_PUD_MASK,
+                               (address & HPAGE_PUD_MASK) + HPAGE_PUD_SIZE);
+       mmu_notifier_invalidate_range_start(&range);
+       ptl = pud_lock(vma->vm_mm, pud);
        if (unlikely(!pud_trans_huge(*pud) && !pud_devmap(*pud)))
                goto out;
-       __split_huge_pud_locked(vma, pud, haddr);
+       __split_huge_pud_locked(vma, pud, range.start);
 
 out:
        spin_unlock(ptl);
@@ -2032,8 +2037,7 @@ out:
         * No need to double call mmu_notifier->invalidate_range() callback as
         * the above pudp_huge_clear_flush_notify() did already call it.
         */
-       mmu_notifier_invalidate_range_only_end(mm, haddr, haddr +
-                                              HPAGE_PUD_SIZE);
+       mmu_notifier_invalidate_range_only_end(&range);
 }
 #endif /* CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD */
 
@@ -2235,11 +2239,12 @@ void __split_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd,
                unsigned long address, bool freeze, struct page *page)
 {
        spinlock_t *ptl;
-       struct mm_struct *mm = vma->vm_mm;
-       unsigned long haddr = address & HPAGE_PMD_MASK;
+       struct mmu_notifier_range range;
 
-       mmu_notifier_invalidate_range_start(mm, haddr, haddr + HPAGE_PMD_SIZE);
-       ptl = pmd_lock(mm, pmd);
+       mmu_notifier_range_init(&range, vma->vm_mm, address & HPAGE_PMD_MASK,
+                               (address & HPAGE_PMD_MASK) + HPAGE_PMD_SIZE);
+       mmu_notifier_invalidate_range_start(&range);
+       ptl = pmd_lock(vma->vm_mm, pmd);
 
        /*
         * If caller asks to setup a migration entries, we need a page to check
@@ -2255,7 +2260,7 @@ void __split_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd,
                        clear_page_mlock(page);
        } else if (!(pmd_devmap(*pmd) || is_pmd_migration_entry(*pmd)))
                goto out;
-       __split_huge_pmd_locked(vma, pmd, haddr, freeze);
+       __split_huge_pmd_locked(vma, pmd, range.start, freeze);
 out:
        spin_unlock(ptl);
        /*
@@ -2271,8 +2276,7 @@ out:
         *     any further changes to individual pte will notify. So no need
         *     to call mmu_notifier->invalidate_range()
         */
-       mmu_notifier_invalidate_range_only_end(mm, haddr, haddr +
-                                              HPAGE_PMD_SIZE);
+       mmu_notifier_invalidate_range_only_end(&range);
 }
 
 void split_huge_pmd_address(struct vm_area_struct *vma, unsigned long address,
index a80832487981b456a6d9c287134abc329f4c48e3..e37efd5d831830123ca117a0efec6eead901eaa7 100644 (file)
@@ -3238,24 +3238,35 @@ int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src,
        struct page *ptepage;
        unsigned long addr;
        int cow;
+       struct address_space *mapping = vma->vm_file->f_mapping;
        struct hstate *h = hstate_vma(vma);
        unsigned long sz = huge_page_size(h);
-       unsigned long mmun_start;       /* For mmu_notifiers */
-       unsigned long mmun_end;         /* For mmu_notifiers */
+       struct mmu_notifier_range range;
        int ret = 0;
 
        cow = (vma->vm_flags & (VM_SHARED | VM_MAYWRITE)) == VM_MAYWRITE;
 
-       mmun_start = vma->vm_start;
-       mmun_end = vma->vm_end;
-       if (cow)
-               mmu_notifier_invalidate_range_start(src, mmun_start, mmun_end);
+       if (cow) {
+               mmu_notifier_range_init(&range, src, vma->vm_start,
+                                       vma->vm_end);
+               mmu_notifier_invalidate_range_start(&range);
+       } else {
+               /*
+                * For shared mappings i_mmap_rwsem must be held to call
+                * huge_pte_alloc, otherwise the returned ptep could go
+                * away if part of a shared pmd and another thread calls
+                * huge_pmd_unshare.
+                */
+               i_mmap_lock_read(mapping);
+       }
 
        for (addr = vma->vm_start; addr < vma->vm_end; addr += sz) {
                spinlock_t *src_ptl, *dst_ptl;
+
                src_pte = huge_pte_offset(src, addr, sz);
                if (!src_pte)
                        continue;
+
                dst_pte = huge_pte_alloc(dst, addr, sz);
                if (!dst_pte) {
                        ret = -ENOMEM;
@@ -3325,7 +3336,9 @@ int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src,
        }
 
        if (cow)
-               mmu_notifier_invalidate_range_end(src, mmun_start, mmun_end);
+               mmu_notifier_invalidate_range_end(&range);
+       else
+               i_mmap_unlock_read(mapping);
 
        return ret;
 }
@@ -3342,8 +3355,7 @@ void __unmap_hugepage_range(struct mmu_gather *tlb, struct vm_area_struct *vma,
        struct page *page;
        struct hstate *h = hstate_vma(vma);
        unsigned long sz = huge_page_size(h);
-       unsigned long mmun_start = start;       /* For mmu_notifiers */
-       unsigned long mmun_end   = end;         /* For mmu_notifiers */
+       struct mmu_notifier_range range;
 
        WARN_ON(!is_vm_hugetlb_page(vma));
        BUG_ON(start & ~huge_page_mask(h));
@@ -3359,8 +3371,9 @@ void __unmap_hugepage_range(struct mmu_gather *tlb, struct vm_area_struct *vma,
        /*
         * If sharing possible, alert mmu notifiers of worst case.
         */
-       adjust_range_if_pmd_sharing_possible(vma, &mmun_start, &mmun_end);
-       mmu_notifier_invalidate_range_start(mm, mmun_start, mmun_end);
+       mmu_notifier_range_init(&range, mm, start, end);
+       adjust_range_if_pmd_sharing_possible(vma, &range.start, &range.end);
+       mmu_notifier_invalidate_range_start(&range);
        address = start;
        for (; address < end; address += sz) {
                ptep = huge_pte_offset(mm, address, sz);
@@ -3428,7 +3441,7 @@ void __unmap_hugepage_range(struct mmu_gather *tlb, struct vm_area_struct *vma,
                if (ref_page)
                        break;
        }
-       mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end);
+       mmu_notifier_invalidate_range_end(&range);
        tlb_end_vma(tlb, vma);
 }
 
@@ -3546,9 +3559,8 @@ static vm_fault_t hugetlb_cow(struct mm_struct *mm, struct vm_area_struct *vma,
        struct page *old_page, *new_page;
        int outside_reserve = 0;
        vm_fault_t ret = 0;
-       unsigned long mmun_start;       /* For mmu_notifiers */
-       unsigned long mmun_end;         /* For mmu_notifiers */
        unsigned long haddr = address & huge_page_mask(h);
+       struct mmu_notifier_range range;
 
        pte = huge_ptep_get(ptep);
        old_page = pte_page(pte);
@@ -3627,9 +3639,8 @@ retry_avoidcopy:
        __SetPageUptodate(new_page);
        set_page_huge_active(new_page);
 
-       mmun_start = haddr;
-       mmun_end = mmun_start + huge_page_size(h);
-       mmu_notifier_invalidate_range_start(mm, mmun_start, mmun_end);
+       mmu_notifier_range_init(&range, mm, haddr, haddr + huge_page_size(h));
+       mmu_notifier_invalidate_range_start(&range);
 
        /*
         * Retake the page table lock to check for racing updates
@@ -3642,7 +3653,7 @@ retry_avoidcopy:
 
                /* Break COW */
                huge_ptep_clear_flush(vma, haddr, ptep);
-               mmu_notifier_invalidate_range(mm, mmun_start, mmun_end);
+               mmu_notifier_invalidate_range(mm, range.start, range.end);
                set_huge_pte_at(mm, haddr, ptep,
                                make_huge_pte(vma, new_page, 1));
                page_remove_rmap(old_page, true);
@@ -3651,7 +3662,7 @@ retry_avoidcopy:
                new_page = old_page;
        }
        spin_unlock(ptl);
-       mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end);
+       mmu_notifier_invalidate_range_end(&range);
 out_release_all:
        restore_reserve_on_error(h, vma, haddr, new_page);
        put_page(new_page);
@@ -3744,16 +3755,16 @@ static vm_fault_t hugetlb_no_page(struct mm_struct *mm,
        }
 
        /*
-        * Use page lock to guard against racing truncation
-        * before we get page_table_lock.
+        * We can not race with truncation due to holding i_mmap_rwsem.
+        * Check once here for faults beyond end of file.
         */
+       size = i_size_read(mapping->host) >> huge_page_shift(h);
+       if (idx >= size)
+               goto out;
+
 retry:
        page = find_lock_page(mapping, idx);
        if (!page) {
-               size = i_size_read(mapping->host) >> huge_page_shift(h);
-               if (idx >= size)
-                       goto out;
-
                /*
                 * Check for page in userfault range
                 */
@@ -3773,14 +3784,18 @@ retry:
                        };
 
                        /*
-                        * hugetlb_fault_mutex must be dropped before
-                        * handling userfault.  Reacquire after handling
-                        * fault to make calling code simpler.
+                        * hugetlb_fault_mutex and i_mmap_rwsem must be
+                        * dropped before handling userfault.  Reacquire
+                        * after handling fault to make calling code simpler.
                         */
                        hash = hugetlb_fault_mutex_hash(h, mm, vma, mapping,
                                                        idx, haddr);
                        mutex_unlock(&hugetlb_fault_mutex_table[hash]);
+                       i_mmap_unlock_read(mapping);
+
                        ret = handle_userfault(&vmf, VM_UFFD_MISSING);
+
+                       i_mmap_lock_read(mapping);
                        mutex_lock(&hugetlb_fault_mutex_table[hash]);
                        goto out;
                }
@@ -3839,9 +3854,6 @@ retry:
        }
 
        ptl = huge_pte_lock(h, mm, ptep);
-       size = i_size_read(mapping->host) >> huge_page_shift(h);
-       if (idx >= size)
-               goto backout;
 
        ret = 0;
        if (!huge_pte_none(huge_ptep_get(ptep)))
@@ -3928,6 +3940,11 @@ vm_fault_t hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma,
 
        ptep = huge_pte_offset(mm, haddr, huge_page_size(h));
        if (ptep) {
+               /*
+                * Since we hold no locks, ptep could be stale.  That is
+                * OK as we are only making decisions based on content and
+                * not actually modifying content here.
+                */
                entry = huge_ptep_get(ptep);
                if (unlikely(is_hugetlb_entry_migration(entry))) {
                        migration_entry_wait_huge(vma, mm, ptep);
@@ -3935,20 +3952,33 @@ vm_fault_t hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma,
                } else if (unlikely(is_hugetlb_entry_hwpoisoned(entry)))
                        return VM_FAULT_HWPOISON_LARGE |
                                VM_FAULT_SET_HINDEX(hstate_index(h));
-       } else {
-               ptep = huge_pte_alloc(mm, haddr, huge_page_size(h));
-               if (!ptep)
-                       return VM_FAULT_OOM;
        }
 
+       /*
+        * Acquire i_mmap_rwsem before calling huge_pte_alloc and hold
+        * until finished with ptep.  This serves two purposes:
+        * 1) It prevents huge_pmd_unshare from being called elsewhere
+        *    and making the ptep no longer valid.
+        * 2) It synchronizes us with file truncation.
+        *
+        * ptep could have already be assigned via huge_pte_offset.  That
+        * is OK, as huge_pte_alloc will return the same value unless
+        * something changed.
+        */
        mapping = vma->vm_file->f_mapping;
-       idx = vma_hugecache_offset(h, vma, haddr);
+       i_mmap_lock_read(mapping);
+       ptep = huge_pte_alloc(mm, haddr, huge_page_size(h));
+       if (!ptep) {
+               i_mmap_unlock_read(mapping);
+               return VM_FAULT_OOM;
+       }
 
        /*
         * Serialize hugepage allocation and instantiation, so that we don't
         * get spurious allocation failures if two CPUs race to instantiate
         * the same page in the page cache.
         */
+       idx = vma_hugecache_offset(h, vma, haddr);
        hash = hugetlb_fault_mutex_hash(h, mm, vma, mapping, idx, haddr);
        mutex_lock(&hugetlb_fault_mutex_table[hash]);
 
@@ -4036,6 +4066,7 @@ out_ptl:
        }
 out_mutex:
        mutex_unlock(&hugetlb_fault_mutex_table[hash]);
+       i_mmap_unlock_read(mapping);
        /*
         * Generally it's safe to hold refcount during waiting page lock. But
         * here we just wait to defer the next page fault to avoid busy loop and
@@ -4340,21 +4371,21 @@ unsigned long hugetlb_change_protection(struct vm_area_struct *vma,
        pte_t pte;
        struct hstate *h = hstate_vma(vma);
        unsigned long pages = 0;
-       unsigned long f_start = start;
-       unsigned long f_end = end;
        bool shared_pmd = false;
+       struct mmu_notifier_range range;
 
        /*
         * In the case of shared PMDs, the area to flush could be beyond
-        * start/end.  Set f_start/f_end to cover the maximum possible
+        * start/end.  Set range.start/range.end to cover the maximum possible
         * range if PMD sharing is possible.
         */
-       adjust_range_if_pmd_sharing_possible(vma, &f_start, &f_end);
+       mmu_notifier_range_init(&range, mm, start, end);
+       adjust_range_if_pmd_sharing_possible(vma, &range.start, &range.end);
 
        BUG_ON(address >= end);
-       flush_cache_range(vma, f_start, f_end);
+       flush_cache_range(vma, range.start, range.end);
 
-       mmu_notifier_invalidate_range_start(mm, f_start, f_end);
+       mmu_notifier_invalidate_range_start(&range);
        i_mmap_lock_write(vma->vm_file->f_mapping);
        for (; address < end; address += huge_page_size(h)) {
                spinlock_t *ptl;
@@ -4405,7 +4436,7 @@ unsigned long hugetlb_change_protection(struct vm_area_struct *vma,
         * did unshare a page of pmds, flush the range corresponding to the pud.
         */
        if (shared_pmd)
-               flush_hugetlb_tlb_range(vma, f_start, f_end);
+               flush_hugetlb_tlb_range(vma, range.start, range.end);
        else
                flush_hugetlb_tlb_range(vma, start, end);
        /*
@@ -4415,7 +4446,7 @@ unsigned long hugetlb_change_protection(struct vm_area_struct *vma,
         * See Documentation/vm/mmu_notifier.rst
         */
        i_mmap_unlock_write(vma->vm_file->f_mapping);
-       mmu_notifier_invalidate_range_end(mm, f_start, f_end);
+       mmu_notifier_invalidate_range_end(&range);
 
        return pages << h->order;
 }
@@ -4640,10 +4671,12 @@ void adjust_range_if_pmd_sharing_possible(struct vm_area_struct *vma,
  * Search for a shareable pmd page for hugetlb. In any case calls pmd_alloc()
  * and returns the corresponding pte. While this is not necessary for the
  * !shared pmd case because we can allocate the pmd later as well, it makes the
- * code much cleaner. pmd allocation is essential for the shared case because
- * pud has to be populated inside the same i_mmap_rwsem section - otherwise
- * racing tasks could either miss the sharing (see huge_pte_offset) or select a
- * bad pmd for sharing.
+ * code much cleaner.
+ *
+ * This routine must be called with i_mmap_rwsem held in at least read mode.
+ * For hugetlbfs, this prevents removal of any page table entries associated
+ * with the address space.  This is important as we are setting up sharing
+ * based on existing page table entries (mappings).
  */
 pte_t *huge_pmd_share(struct mm_struct *mm, unsigned long addr, pud_t *pud)
 {
@@ -4660,7 +4693,6 @@ pte_t *huge_pmd_share(struct mm_struct *mm, unsigned long addr, pud_t *pud)
        if (!vma_shareable(vma, addr))
                return (pte_t *)pmd_alloc(mm, pud, addr);
 
-       i_mmap_lock_write(mapping);
        vma_interval_tree_foreach(svma, &mapping->i_mmap, idx, idx) {
                if (svma == vma)
                        continue;
@@ -4690,7 +4722,6 @@ pte_t *huge_pmd_share(struct mm_struct *mm, unsigned long addr, pud_t *pud)
        spin_unlock(ptl);
 out:
        pte = (pte_t *)pmd_alloc(mm, pud, addr);
-       i_mmap_unlock_write(mapping);
        return pte;
 }
 
@@ -4701,7 +4732,7 @@ out:
  * indicated by page_count > 1, unmap is achieved by clearing pud and
  * decrementing the ref count. If count == 1, the pte page is not shared.
  *
- * called with page table lock held.
+ * Called with page table lock held and i_mmap_rwsem held in write mode.
  *
  * returns: 1 successfully unmapped a shared pte page
  *         0 the underlying pte page is not shared, or it is the last user
index 291eb2b6d1d8c5504d4a51090b03d836c4990660..f4a7bb02decfea1a5509c0a96cc8aa653ebc816c 100644 (file)
@@ -444,6 +444,16 @@ static inline void mminit_validate_memmodel_limits(unsigned long *start_pfn,
 #define NODE_RECLAIM_SOME      0
 #define NODE_RECLAIM_SUCCESS   1
 
+#ifdef CONFIG_NUMA
+extern int node_reclaim(struct pglist_data *, gfp_t, unsigned int);
+#else
+static inline int node_reclaim(struct pglist_data *pgdat, gfp_t mask,
+                               unsigned int order)
+{
+       return NODE_RECLAIM_NOSCAN;
+}
+#endif
+
 extern int hwpoison_filter(struct page *p);
 
 extern u32 hwpoison_filter_dev_major;
@@ -480,10 +490,16 @@ unsigned long reclaim_clean_pages_from_list(struct zone *zone,
 #define ALLOC_OOM              ALLOC_NO_WATERMARKS
 #endif
 
-#define ALLOC_HARDER           0x10 /* try to alloc harder */
-#define ALLOC_HIGH             0x20 /* __GFP_HIGH set */
-#define ALLOC_CPUSET           0x40 /* check for correct cpuset */
-#define ALLOC_CMA              0x80 /* allow allocations from CMA areas */
+#define ALLOC_HARDER            0x10 /* try to alloc harder */
+#define ALLOC_HIGH              0x20 /* __GFP_HIGH set */
+#define ALLOC_CPUSET            0x40 /* check for correct cpuset */
+#define ALLOC_CMA               0x80 /* allow allocations from CMA areas */
+#ifdef CONFIG_ZONE_DMA32
+#define ALLOC_NOFRAGMENT       0x100 /* avoid mixing pageblock types */
+#else
+#define ALLOC_NOFRAGMENT         0x0
+#endif
+#define ALLOC_KSWAPD           0x200 /* allow waking of kswapd */
 
 enum ttu_flags;
 struct tlbflush_unmap_batch;
index 3289db38bc87b600703843369d84b28a55920a55..0a14fcff70ed70b385bddd0d842176966d88547b 100644 (file)
@@ -1,11 +1,18 @@
 # SPDX-License-Identifier: GPL-2.0
 KASAN_SANITIZE := n
-UBSAN_SANITIZE_kasan.o := n
+UBSAN_SANITIZE_common.o := n
+UBSAN_SANITIZE_generic.o := n
+UBSAN_SANITIZE_tags.o := n
 KCOV_INSTRUMENT := n
 
-CFLAGS_REMOVE_kasan.o = -pg
+CFLAGS_REMOVE_generic.o = -pg
 # Function splitter causes unnecessary splits in __asan_load1/__asan_store1
 # see: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63533
-CFLAGS_kasan.o := $(call cc-option, -fno-conserve-stack -fno-stack-protector)
 
-obj-y := kasan.o report.o kasan_init.o quarantine.o
+CFLAGS_common.o := $(call cc-option, -fno-conserve-stack -fno-stack-protector)
+CFLAGS_generic.o := $(call cc-option, -fno-conserve-stack -fno-stack-protector)
+CFLAGS_tags.o := $(call cc-option, -fno-conserve-stack -fno-stack-protector)
+
+obj-$(CONFIG_KASAN) := common.o init.o report.o
+obj-$(CONFIG_KASAN_GENERIC) += generic.o generic_report.o quarantine.o
+obj-$(CONFIG_KASAN_SW_TAGS) += tags.o tags_report.o
diff --git a/mm/kasan/common.c b/mm/kasan/common.c
new file mode 100644 (file)
index 0000000..03d5d13
--- /dev/null
@@ -0,0 +1,697 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * This file contains common generic and tag-based KASAN code.
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * Author: Andrey Ryabinin <ryabinin.a.a@gmail.com>
+ *
+ * Some code borrowed from https://github.com/xairy/kasan-prototype by
+ *        Andrey Konovalov <andreyknvl@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/export.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/kasan.h>
+#include <linux/kernel.h>
+#include <linux/kmemleak.h>
+#include <linux/linkage.h>
+#include <linux/memblock.h>
+#include <linux/memory.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/printk.h>
+#include <linux/sched.h>
+#include <linux/sched/task_stack.h>
+#include <linux/slab.h>
+#include <linux/stacktrace.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/vmalloc.h>
+#include <linux/bug.h>
+
+#include "kasan.h"
+#include "../slab.h"
+
+static inline int in_irqentry_text(unsigned long ptr)
+{
+       return (ptr >= (unsigned long)&__irqentry_text_start &&
+               ptr < (unsigned long)&__irqentry_text_end) ||
+               (ptr >= (unsigned long)&__softirqentry_text_start &&
+                ptr < (unsigned long)&__softirqentry_text_end);
+}
+
+static inline void filter_irq_stacks(struct stack_trace *trace)
+{
+       int i;
+
+       if (!trace->nr_entries)
+               return;
+       for (i = 0; i < trace->nr_entries; i++)
+               if (in_irqentry_text(trace->entries[i])) {
+                       /* Include the irqentry function into the stack. */
+                       trace->nr_entries = i + 1;
+                       break;
+               }
+}
+
+static inline depot_stack_handle_t save_stack(gfp_t flags)
+{
+       unsigned long entries[KASAN_STACK_DEPTH];
+       struct stack_trace trace = {
+               .nr_entries = 0,
+               .entries = entries,
+               .max_entries = KASAN_STACK_DEPTH,
+               .skip = 0
+       };
+
+       save_stack_trace(&trace);
+       filter_irq_stacks(&trace);
+       if (trace.nr_entries != 0 &&
+           trace.entries[trace.nr_entries-1] == ULONG_MAX)
+               trace.nr_entries--;
+
+       return depot_save_stack(&trace, flags);
+}
+
+static inline void set_track(struct kasan_track *track, gfp_t flags)
+{
+       track->pid = current->pid;
+       track->stack = save_stack(flags);
+}
+
+void kasan_enable_current(void)
+{
+       current->kasan_depth++;
+}
+
+void kasan_disable_current(void)
+{
+       current->kasan_depth--;
+}
+
+void kasan_check_read(const volatile void *p, unsigned int size)
+{
+       check_memory_region((unsigned long)p, size, false, _RET_IP_);
+}
+EXPORT_SYMBOL(kasan_check_read);
+
+void kasan_check_write(const volatile void *p, unsigned int size)
+{
+       check_memory_region((unsigned long)p, size, true, _RET_IP_);
+}
+EXPORT_SYMBOL(kasan_check_write);
+
+#undef memset
+void *memset(void *addr, int c, size_t len)
+{
+       check_memory_region((unsigned long)addr, len, true, _RET_IP_);
+
+       return __memset(addr, c, len);
+}
+
+#undef memmove
+void *memmove(void *dest, const void *src, size_t len)
+{
+       check_memory_region((unsigned long)src, len, false, _RET_IP_);
+       check_memory_region((unsigned long)dest, len, true, _RET_IP_);
+
+       return __memmove(dest, src, len);
+}
+
+#undef memcpy
+void *memcpy(void *dest, const void *src, size_t len)
+{
+       check_memory_region((unsigned long)src, len, false, _RET_IP_);
+       check_memory_region((unsigned long)dest, len, true, _RET_IP_);
+
+       return __memcpy(dest, src, len);
+}
+
+/*
+ * Poisons the shadow memory for 'size' bytes starting from 'addr'.
+ * Memory addresses should be aligned to KASAN_SHADOW_SCALE_SIZE.
+ */
+void kasan_poison_shadow(const void *address, size_t size, u8 value)
+{
+       void *shadow_start, *shadow_end;
+
+       /*
+        * Perform shadow offset calculation based on untagged address, as
+        * some of the callers (e.g. kasan_poison_object_data) pass tagged
+        * addresses to this function.
+        */
+       address = reset_tag(address);
+
+       shadow_start = kasan_mem_to_shadow(address);
+       shadow_end = kasan_mem_to_shadow(address + size);
+
+       __memset(shadow_start, value, shadow_end - shadow_start);
+}
+
+void kasan_unpoison_shadow(const void *address, size_t size)
+{
+       u8 tag = get_tag(address);
+
+       /*
+        * Perform shadow offset calculation based on untagged address, as
+        * some of the callers (e.g. kasan_unpoison_object_data) pass tagged
+        * addresses to this function.
+        */
+       address = reset_tag(address);
+
+       kasan_poison_shadow(address, size, tag);
+
+       if (size & KASAN_SHADOW_MASK) {
+               u8 *shadow = (u8 *)kasan_mem_to_shadow(address + size);
+
+               if (IS_ENABLED(CONFIG_KASAN_SW_TAGS))
+                       *shadow = tag;
+               else
+                       *shadow = size & KASAN_SHADOW_MASK;
+       }
+}
+
+static void __kasan_unpoison_stack(struct task_struct *task, const void *sp)
+{
+       void *base = task_stack_page(task);
+       size_t size = sp - base;
+
+       kasan_unpoison_shadow(base, size);
+}
+
+/* Unpoison the entire stack for a task. */
+void kasan_unpoison_task_stack(struct task_struct *task)
+{
+       __kasan_unpoison_stack(task, task_stack_page(task) + THREAD_SIZE);
+}
+
+/* Unpoison the stack for the current task beyond a watermark sp value. */
+asmlinkage void kasan_unpoison_task_stack_below(const void *watermark)
+{
+       /*
+        * Calculate the task stack base address.  Avoid using 'current'
+        * because this function is called by early resume code which hasn't
+        * yet set up the percpu register (%gs).
+        */
+       void *base = (void *)((unsigned long)watermark & ~(THREAD_SIZE - 1));
+
+       kasan_unpoison_shadow(base, watermark - base);
+}
+
+/*
+ * Clear all poison for the region between the current SP and a provided
+ * watermark value, as is sometimes required prior to hand-crafted asm function
+ * returns in the middle of functions.
+ */
+void kasan_unpoison_stack_above_sp_to(const void *watermark)
+{
+       const void *sp = __builtin_frame_address(0);
+       size_t size = watermark - sp;
+
+       if (WARN_ON(sp > watermark))
+               return;
+       kasan_unpoison_shadow(sp, size);
+}
+
+void kasan_alloc_pages(struct page *page, unsigned int order)
+{
+       u8 tag;
+       unsigned long i;
+
+       if (unlikely(PageHighMem(page)))
+               return;
+
+       tag = random_tag();
+       for (i = 0; i < (1 << order); i++)
+               page_kasan_tag_set(page + i, tag);
+       kasan_unpoison_shadow(page_address(page), PAGE_SIZE << order);
+}
+
+void kasan_free_pages(struct page *page, unsigned int order)
+{
+       if (likely(!PageHighMem(page)))
+               kasan_poison_shadow(page_address(page),
+                               PAGE_SIZE << order,
+                               KASAN_FREE_PAGE);
+}
+
+/*
+ * Adaptive redzone policy taken from the userspace AddressSanitizer runtime.
+ * For larger allocations larger redzones are used.
+ */
+static inline unsigned int optimal_redzone(unsigned int object_size)
+{
+       if (IS_ENABLED(CONFIG_KASAN_SW_TAGS))
+               return 0;
+
+       return
+               object_size <= 64        - 16   ? 16 :
+               object_size <= 128       - 32   ? 32 :
+               object_size <= 512       - 64   ? 64 :
+               object_size <= 4096      - 128  ? 128 :
+               object_size <= (1 << 14) - 256  ? 256 :
+               object_size <= (1 << 15) - 512  ? 512 :
+               object_size <= (1 << 16) - 1024 ? 1024 : 2048;
+}
+
+void kasan_cache_create(struct kmem_cache *cache, unsigned int *size,
+                       slab_flags_t *flags)
+{
+       unsigned int orig_size = *size;
+       unsigned int redzone_size;
+       int redzone_adjust;
+
+       /* Add alloc meta. */
+       cache->kasan_info.alloc_meta_offset = *size;
+       *size += sizeof(struct kasan_alloc_meta);
+
+       /* Add free meta. */
+       if (IS_ENABLED(CONFIG_KASAN_GENERIC) &&
+           (cache->flags & SLAB_TYPESAFE_BY_RCU || cache->ctor ||
+            cache->object_size < sizeof(struct kasan_free_meta))) {
+               cache->kasan_info.free_meta_offset = *size;
+               *size += sizeof(struct kasan_free_meta);
+       }
+
+       redzone_size = optimal_redzone(cache->object_size);
+       redzone_adjust = redzone_size - (*size - cache->object_size);
+       if (redzone_adjust > 0)
+               *size += redzone_adjust;
+
+       *size = min_t(unsigned int, KMALLOC_MAX_SIZE,
+                       max(*size, cache->object_size + redzone_size));
+
+       /*
+        * If the metadata doesn't fit, don't enable KASAN at all.
+        */
+       if (*size <= cache->kasan_info.alloc_meta_offset ||
+                       *size <= cache->kasan_info.free_meta_offset) {
+               cache->kasan_info.alloc_meta_offset = 0;
+               cache->kasan_info.free_meta_offset = 0;
+               *size = orig_size;
+               return;
+       }
+
+       cache->align = round_up(cache->align, KASAN_SHADOW_SCALE_SIZE);
+
+       *flags |= SLAB_KASAN;
+}
+
+size_t kasan_metadata_size(struct kmem_cache *cache)
+{
+       return (cache->kasan_info.alloc_meta_offset ?
+               sizeof(struct kasan_alloc_meta) : 0) +
+               (cache->kasan_info.free_meta_offset ?
+               sizeof(struct kasan_free_meta) : 0);
+}
+
+struct kasan_alloc_meta *get_alloc_info(struct kmem_cache *cache,
+                                       const void *object)
+{
+       BUILD_BUG_ON(sizeof(struct kasan_alloc_meta) > 32);
+       return (void *)object + cache->kasan_info.alloc_meta_offset;
+}
+
+struct kasan_free_meta *get_free_info(struct kmem_cache *cache,
+                                     const void *object)
+{
+       BUILD_BUG_ON(sizeof(struct kasan_free_meta) > 32);
+       return (void *)object + cache->kasan_info.free_meta_offset;
+}
+
+void kasan_poison_slab(struct page *page)
+{
+       unsigned long i;
+
+       for (i = 0; i < (1 << compound_order(page)); i++)
+               page_kasan_tag_reset(page + i);
+       kasan_poison_shadow(page_address(page),
+                       PAGE_SIZE << compound_order(page),
+                       KASAN_KMALLOC_REDZONE);
+}
+
+void kasan_unpoison_object_data(struct kmem_cache *cache, void *object)
+{
+       kasan_unpoison_shadow(object, cache->object_size);
+}
+
+void kasan_poison_object_data(struct kmem_cache *cache, void *object)
+{
+       kasan_poison_shadow(object,
+                       round_up(cache->object_size, KASAN_SHADOW_SCALE_SIZE),
+                       KASAN_KMALLOC_REDZONE);
+}
+
+/*
+ * Since it's desirable to only call object contructors once during slab
+ * allocation, we preassign tags to all such objects. Also preassign tags for
+ * SLAB_TYPESAFE_BY_RCU slabs to avoid use-after-free reports.
+ * For SLAB allocator we can't preassign tags randomly since the freelist is
+ * stored as an array of indexes instead of a linked list. Assign tags based
+ * on objects indexes, so that objects that are next to each other get
+ * different tags.
+ * After a tag is assigned, the object always gets allocated with the same tag.
+ * The reason is that we can't change tags for objects with constructors on
+ * reallocation (even for non-SLAB_TYPESAFE_BY_RCU), because the constructor
+ * code can save the pointer to the object somewhere (e.g. in the object
+ * itself). Then if we retag it, the old saved pointer will become invalid.
+ */
+static u8 assign_tag(struct kmem_cache *cache, const void *object, bool new)
+{
+       if (!cache->ctor && !(cache->flags & SLAB_TYPESAFE_BY_RCU))
+               return new ? KASAN_TAG_KERNEL : random_tag();
+
+#ifdef CONFIG_SLAB
+       return (u8)obj_to_index(cache, virt_to_page(object), (void *)object);
+#else
+       return new ? random_tag() : get_tag(object);
+#endif
+}
+
+void * __must_check kasan_init_slab_obj(struct kmem_cache *cache,
+                                               const void *object)
+{
+       struct kasan_alloc_meta *alloc_info;
+
+       if (!(cache->flags & SLAB_KASAN))
+               return (void *)object;
+
+       alloc_info = get_alloc_info(cache, object);
+       __memset(alloc_info, 0, sizeof(*alloc_info));
+
+       if (IS_ENABLED(CONFIG_KASAN_SW_TAGS))
+               object = set_tag(object, assign_tag(cache, object, true));
+
+       return (void *)object;
+}
+
+void * __must_check kasan_slab_alloc(struct kmem_cache *cache, void *object,
+                                       gfp_t flags)
+{
+       return kasan_kmalloc(cache, object, cache->object_size, flags);
+}
+
+static inline bool shadow_invalid(u8 tag, s8 shadow_byte)
+{
+       if (IS_ENABLED(CONFIG_KASAN_GENERIC))
+               return shadow_byte < 0 ||
+                       shadow_byte >= KASAN_SHADOW_SCALE_SIZE;
+       else
+               return tag != (u8)shadow_byte;
+}
+
+static bool __kasan_slab_free(struct kmem_cache *cache, void *object,
+                             unsigned long ip, bool quarantine)
+{
+       s8 shadow_byte;
+       u8 tag;
+       void *tagged_object;
+       unsigned long rounded_up_size;
+
+       tag = get_tag(object);
+       tagged_object = object;
+       object = reset_tag(object);
+
+       if (unlikely(nearest_obj(cache, virt_to_head_page(object), object) !=
+           object)) {
+               kasan_report_invalid_free(tagged_object, ip);
+               return true;
+       }
+
+       /* RCU slabs could be legally used after free within the RCU period */
+       if (unlikely(cache->flags & SLAB_TYPESAFE_BY_RCU))
+               return false;
+
+       shadow_byte = READ_ONCE(*(s8 *)kasan_mem_to_shadow(object));
+       if (shadow_invalid(tag, shadow_byte)) {
+               kasan_report_invalid_free(tagged_object, ip);
+               return true;
+       }
+
+       rounded_up_size = round_up(cache->object_size, KASAN_SHADOW_SCALE_SIZE);
+       kasan_poison_shadow(object, rounded_up_size, KASAN_KMALLOC_FREE);
+
+       if ((IS_ENABLED(CONFIG_KASAN_GENERIC) && !quarantine) ||
+                       unlikely(!(cache->flags & SLAB_KASAN)))
+               return false;
+
+       set_track(&get_alloc_info(cache, object)->free_track, GFP_NOWAIT);
+       quarantine_put(get_free_info(cache, object), cache);
+
+       return IS_ENABLED(CONFIG_KASAN_GENERIC);
+}
+
+bool kasan_slab_free(struct kmem_cache *cache, void *object, unsigned long ip)
+{
+       return __kasan_slab_free(cache, object, ip, true);
+}
+
+void * __must_check kasan_kmalloc(struct kmem_cache *cache, const void *object,
+                                       size_t size, gfp_t flags)
+{
+       unsigned long redzone_start;
+       unsigned long redzone_end;
+       u8 tag;
+
+       if (gfpflags_allow_blocking(flags))
+               quarantine_reduce();
+
+       if (unlikely(object == NULL))
+               return NULL;
+
+       redzone_start = round_up((unsigned long)(object + size),
+                               KASAN_SHADOW_SCALE_SIZE);
+       redzone_end = round_up((unsigned long)object + cache->object_size,
+                               KASAN_SHADOW_SCALE_SIZE);
+
+       if (IS_ENABLED(CONFIG_KASAN_SW_TAGS))
+               tag = assign_tag(cache, object, false);
+
+       /* Tag is ignored in set_tag without CONFIG_KASAN_SW_TAGS */
+       kasan_unpoison_shadow(set_tag(object, tag), size);
+       kasan_poison_shadow((void *)redzone_start, redzone_end - redzone_start,
+               KASAN_KMALLOC_REDZONE);
+
+       if (cache->flags & SLAB_KASAN)
+               set_track(&get_alloc_info(cache, object)->alloc_track, flags);
+
+       return set_tag(object, tag);
+}
+EXPORT_SYMBOL(kasan_kmalloc);
+
+void * __must_check kasan_kmalloc_large(const void *ptr, size_t size,
+                                               gfp_t flags)
+{
+       struct page *page;
+       unsigned long redzone_start;
+       unsigned long redzone_end;
+
+       if (gfpflags_allow_blocking(flags))
+               quarantine_reduce();
+
+       if (unlikely(ptr == NULL))
+               return NULL;
+
+       page = virt_to_page(ptr);
+       redzone_start = round_up((unsigned long)(ptr + size),
+                               KASAN_SHADOW_SCALE_SIZE);
+       redzone_end = (unsigned long)ptr + (PAGE_SIZE << compound_order(page));
+
+       kasan_unpoison_shadow(ptr, size);
+       kasan_poison_shadow((void *)redzone_start, redzone_end - redzone_start,
+               KASAN_PAGE_REDZONE);
+
+       return (void *)ptr;
+}
+
+void * __must_check kasan_krealloc(const void *object, size_t size, gfp_t flags)
+{
+       struct page *page;
+
+       if (unlikely(object == ZERO_SIZE_PTR))
+               return (void *)object;
+
+       page = virt_to_head_page(object);
+
+       if (unlikely(!PageSlab(page)))
+               return kasan_kmalloc_large(object, size, flags);
+       else
+               return kasan_kmalloc(page->slab_cache, object, size, flags);
+}
+
+void kasan_poison_kfree(void *ptr, unsigned long ip)
+{
+       struct page *page;
+
+       page = virt_to_head_page(ptr);
+
+       if (unlikely(!PageSlab(page))) {
+               if (ptr != page_address(page)) {
+                       kasan_report_invalid_free(ptr, ip);
+                       return;
+               }
+               kasan_poison_shadow(ptr, PAGE_SIZE << compound_order(page),
+                               KASAN_FREE_PAGE);
+       } else {
+               __kasan_slab_free(page->slab_cache, ptr, ip, false);
+       }
+}
+
+void kasan_kfree_large(void *ptr, unsigned long ip)
+{
+       if (ptr != page_address(virt_to_head_page(ptr)))
+               kasan_report_invalid_free(ptr, ip);
+       /* The object will be poisoned by page_alloc. */
+}
+
+int kasan_module_alloc(void *addr, size_t size)
+{
+       void *ret;
+       size_t scaled_size;
+       size_t shadow_size;
+       unsigned long shadow_start;
+
+       shadow_start = (unsigned long)kasan_mem_to_shadow(addr);
+       scaled_size = (size + KASAN_SHADOW_MASK) >> KASAN_SHADOW_SCALE_SHIFT;
+       shadow_size = round_up(scaled_size, PAGE_SIZE);
+
+       if (WARN_ON(!PAGE_ALIGNED(shadow_start)))
+               return -EINVAL;
+
+       ret = __vmalloc_node_range(shadow_size, 1, shadow_start,
+                       shadow_start + shadow_size,
+                       GFP_KERNEL,
+                       PAGE_KERNEL, VM_NO_GUARD, NUMA_NO_NODE,
+                       __builtin_return_address(0));
+
+       if (ret) {
+               __memset(ret, KASAN_SHADOW_INIT, shadow_size);
+               find_vm_area(addr)->flags |= VM_KASAN;
+               kmemleak_ignore(ret);
+               return 0;
+       }
+
+       return -ENOMEM;
+}
+
+void kasan_free_shadow(const struct vm_struct *vm)
+{
+       if (vm->flags & VM_KASAN)
+               vfree(kasan_mem_to_shadow(vm->addr));
+}
+
+#ifdef CONFIG_MEMORY_HOTPLUG
+static bool shadow_mapped(unsigned long addr)
+{
+       pgd_t *pgd = pgd_offset_k(addr);
+       p4d_t *p4d;
+       pud_t *pud;
+       pmd_t *pmd;
+       pte_t *pte;
+
+       if (pgd_none(*pgd))
+               return false;
+       p4d = p4d_offset(pgd, addr);
+       if (p4d_none(*p4d))
+               return false;
+       pud = pud_offset(p4d, addr);
+       if (pud_none(*pud))
+               return false;
+
+       /*
+        * We can't use pud_large() or pud_huge(), the first one is
+        * arch-specific, the last one depends on HUGETLB_PAGE.  So let's abuse
+        * pud_bad(), if pud is bad then it's bad because it's huge.
+        */
+       if (pud_bad(*pud))
+               return true;
+       pmd = pmd_offset(pud, addr);
+       if (pmd_none(*pmd))
+               return false;
+
+       if (pmd_bad(*pmd))
+               return true;
+       pte = pte_offset_kernel(pmd, addr);
+       return !pte_none(*pte);
+}
+
+static int __meminit kasan_mem_notifier(struct notifier_block *nb,
+                       unsigned long action, void *data)
+{
+       struct memory_notify *mem_data = data;
+       unsigned long nr_shadow_pages, start_kaddr, shadow_start;
+       unsigned long shadow_end, shadow_size;
+
+       nr_shadow_pages = mem_data->nr_pages >> KASAN_SHADOW_SCALE_SHIFT;
+       start_kaddr = (unsigned long)pfn_to_kaddr(mem_data->start_pfn);
+       shadow_start = (unsigned long)kasan_mem_to_shadow((void *)start_kaddr);
+       shadow_size = nr_shadow_pages << PAGE_SHIFT;
+       shadow_end = shadow_start + shadow_size;
+
+       if (WARN_ON(mem_data->nr_pages % KASAN_SHADOW_SCALE_SIZE) ||
+               WARN_ON(start_kaddr % (KASAN_SHADOW_SCALE_SIZE << PAGE_SHIFT)))
+               return NOTIFY_BAD;
+
+       switch (action) {
+       case MEM_GOING_ONLINE: {
+               void *ret;
+
+               /*
+                * If shadow is mapped already than it must have been mapped
+                * during the boot. This could happen if we onlining previously
+                * offlined memory.
+                */
+               if (shadow_mapped(shadow_start))
+                       return NOTIFY_OK;
+
+               ret = __vmalloc_node_range(shadow_size, PAGE_SIZE, shadow_start,
+                                       shadow_end, GFP_KERNEL,
+                                       PAGE_KERNEL, VM_NO_GUARD,
+                                       pfn_to_nid(mem_data->start_pfn),
+                                       __builtin_return_address(0));
+               if (!ret)
+                       return NOTIFY_BAD;
+
+               kmemleak_ignore(ret);
+               return NOTIFY_OK;
+       }
+       case MEM_CANCEL_ONLINE:
+       case MEM_OFFLINE: {
+               struct vm_struct *vm;
+
+               /*
+                * shadow_start was either mapped during boot by kasan_init()
+                * or during memory online by __vmalloc_node_range().
+                * In the latter case we can use vfree() to free shadow.
+                * Non-NULL result of the find_vm_area() will tell us if
+                * that was the second case.
+                *
+                * Currently it's not possible to free shadow mapped
+                * during boot by kasan_init(). It's because the code
+                * to do that hasn't been written yet. So we'll just
+                * leak the memory.
+                */
+               vm = find_vm_area((void *)shadow_start);
+               if (vm)
+                       vfree((void *)shadow_start);
+       }
+       }
+
+       return NOTIFY_OK;
+}
+
+static int __init kasan_memhotplug_init(void)
+{
+       hotplug_memory_notifier(kasan_mem_notifier, 0);
+
+       return 0;
+}
+
+core_initcall(kasan_memhotplug_init);
+#endif
diff --git a/mm/kasan/generic.c b/mm/kasan/generic.c
new file mode 100644 (file)
index 0000000..ccb6207
--- /dev/null
@@ -0,0 +1,344 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * This file contains core generic KASAN code.
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * Author: Andrey Ryabinin <ryabinin.a.a@gmail.com>
+ *
+ * Some code borrowed from https://github.com/xairy/kasan-prototype by
+ *        Andrey Konovalov <andreyknvl@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#define DISABLE_BRANCH_PROFILING
+
+#include <linux/export.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/kasan.h>
+#include <linux/kernel.h>
+#include <linux/kmemleak.h>
+#include <linux/linkage.h>
+#include <linux/memblock.h>
+#include <linux/memory.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/printk.h>
+#include <linux/sched.h>
+#include <linux/sched/task_stack.h>
+#include <linux/slab.h>
+#include <linux/stacktrace.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/vmalloc.h>
+#include <linux/bug.h>
+
+#include "kasan.h"
+#include "../slab.h"
+
+/*
+ * All functions below always inlined so compiler could
+ * perform better optimizations in each of __asan_loadX/__assn_storeX
+ * depending on memory access size X.
+ */
+
+static __always_inline bool memory_is_poisoned_1(unsigned long addr)
+{
+       s8 shadow_value = *(s8 *)kasan_mem_to_shadow((void *)addr);
+
+       if (unlikely(shadow_value)) {
+               s8 last_accessible_byte = addr & KASAN_SHADOW_MASK;
+               return unlikely(last_accessible_byte >= shadow_value);
+       }
+
+       return false;
+}
+
+static __always_inline bool memory_is_poisoned_2_4_8(unsigned long addr,
+                                               unsigned long size)
+{
+       u8 *shadow_addr = (u8 *)kasan_mem_to_shadow((void *)addr);
+
+       /*
+        * Access crosses 8(shadow size)-byte boundary. Such access maps
+        * into 2 shadow bytes, so we need to check them both.
+        */
+       if (unlikely(((addr + size - 1) & KASAN_SHADOW_MASK) < size - 1))
+               return *shadow_addr || memory_is_poisoned_1(addr + size - 1);
+
+       return memory_is_poisoned_1(addr + size - 1);
+}
+
+static __always_inline bool memory_is_poisoned_16(unsigned long addr)
+{
+       u16 *shadow_addr = (u16 *)kasan_mem_to_shadow((void *)addr);
+
+       /* Unaligned 16-bytes access maps into 3 shadow bytes. */
+       if (unlikely(!IS_ALIGNED(addr, KASAN_SHADOW_SCALE_SIZE)))
+               return *shadow_addr || memory_is_poisoned_1(addr + 15);
+
+       return *shadow_addr;
+}
+
+static __always_inline unsigned long bytes_is_nonzero(const u8 *start,
+                                       size_t size)
+{
+       while (size) {
+               if (unlikely(*start))
+                       return (unsigned long)start;
+               start++;
+               size--;
+       }
+
+       return 0;
+}
+
+static __always_inline unsigned long memory_is_nonzero(const void *start,
+                                               const void *end)
+{
+       unsigned int words;
+       unsigned long ret;
+       unsigned int prefix = (unsigned long)start % 8;
+
+       if (end - start <= 16)
+               return bytes_is_nonzero(start, end - start);
+
+       if (prefix) {
+               prefix = 8 - prefix;
+               ret = bytes_is_nonzero(start, prefix);
+               if (unlikely(ret))
+                       return ret;
+               start += prefix;
+       }
+
+       words = (end - start) / 8;
+       while (words) {
+               if (unlikely(*(u64 *)start))
+                       return bytes_is_nonzero(start, 8);
+               start += 8;
+               words--;
+       }
+
+       return bytes_is_nonzero(start, (end - start) % 8);
+}
+
+static __always_inline bool memory_is_poisoned_n(unsigned long addr,
+                                               size_t size)
+{
+       unsigned long ret;
+
+       ret = memory_is_nonzero(kasan_mem_to_shadow((void *)addr),
+                       kasan_mem_to_shadow((void *)addr + size - 1) + 1);
+
+       if (unlikely(ret)) {
+               unsigned long last_byte = addr + size - 1;
+               s8 *last_shadow = (s8 *)kasan_mem_to_shadow((void *)last_byte);
+
+               if (unlikely(ret != (unsigned long)last_shadow ||
+                       ((long)(last_byte & KASAN_SHADOW_MASK) >= *last_shadow)))
+                       return true;
+       }
+       return false;
+}
+
+static __always_inline bool memory_is_poisoned(unsigned long addr, size_t size)
+{
+       if (__builtin_constant_p(size)) {
+               switch (size) {
+               case 1:
+                       return memory_is_poisoned_1(addr);
+               case 2:
+               case 4:
+               case 8:
+                       return memory_is_poisoned_2_4_8(addr, size);
+               case 16:
+                       return memory_is_poisoned_16(addr);
+               default:
+                       BUILD_BUG();
+               }
+       }
+
+       return memory_is_poisoned_n(addr, size);
+}
+
+static __always_inline void check_memory_region_inline(unsigned long addr,
+                                               size_t size, bool write,
+                                               unsigned long ret_ip)
+{
+       if (unlikely(size == 0))
+               return;
+
+       if (unlikely((void *)addr <
+               kasan_shadow_to_mem((void *)KASAN_SHADOW_START))) {
+               kasan_report(addr, size, write, ret_ip);
+               return;
+       }
+
+       if (likely(!memory_is_poisoned(addr, size)))
+               return;
+
+       kasan_report(addr, size, write, ret_ip);
+}
+
+void check_memory_region(unsigned long addr, size_t size, bool write,
+                               unsigned long ret_ip)
+{
+       check_memory_region_inline(addr, size, write, ret_ip);
+}
+
+void kasan_cache_shrink(struct kmem_cache *cache)
+{
+       quarantine_remove_cache(cache);
+}
+
+void kasan_cache_shutdown(struct kmem_cache *cache)
+{
+       if (!__kmem_cache_empty(cache))
+               quarantine_remove_cache(cache);
+}
+
+static void register_global(struct kasan_global *global)
+{
+       size_t aligned_size = round_up(global->size, KASAN_SHADOW_SCALE_SIZE);
+
+       kasan_unpoison_shadow(global->beg, global->size);
+
+       kasan_poison_shadow(global->beg + aligned_size,
+               global->size_with_redzone - aligned_size,
+               KASAN_GLOBAL_REDZONE);
+}
+
+void __asan_register_globals(struct kasan_global *globals, size_t size)
+{
+       int i;
+
+       for (i = 0; i < size; i++)
+               register_global(&globals[i]);
+}
+EXPORT_SYMBOL(__asan_register_globals);
+
+void __asan_unregister_globals(struct kasan_global *globals, size_t size)
+{
+}
+EXPORT_SYMBOL(__asan_unregister_globals);
+
+#define DEFINE_ASAN_LOAD_STORE(size)                                   \
+       void __asan_load##size(unsigned long addr)                      \
+       {                                                               \
+               check_memory_region_inline(addr, size, false, _RET_IP_);\
+       }                                                               \
+       EXPORT_SYMBOL(__asan_load##size);                               \
+       __alias(__asan_load##size)                                      \
+       void __asan_load##size##_noabort(unsigned long);                \
+       EXPORT_SYMBOL(__asan_load##size##_noabort);                     \
+       void __asan_store##size(unsigned long addr)                     \
+       {                                                               \
+               check_memory_region_inline(addr, size, true, _RET_IP_); \
+       }                                                               \
+       EXPORT_SYMBOL(__asan_store##size);                              \
+       __alias(__asan_store##size)                                     \
+       void __asan_store##size##_noabort(unsigned long);               \
+       EXPORT_SYMBOL(__asan_store##size##_noabort)
+
+DEFINE_ASAN_LOAD_STORE(1);
+DEFINE_ASAN_LOAD_STORE(2);
+DEFINE_ASAN_LOAD_STORE(4);
+DEFINE_ASAN_LOAD_STORE(8);
+DEFINE_ASAN_LOAD_STORE(16);
+
+void __asan_loadN(unsigned long addr, size_t size)
+{
+       check_memory_region(addr, size, false, _RET_IP_);
+}
+EXPORT_SYMBOL(__asan_loadN);
+
+__alias(__asan_loadN)
+void __asan_loadN_noabort(unsigned long, size_t);
+EXPORT_SYMBOL(__asan_loadN_noabort);
+
+void __asan_storeN(unsigned long addr, size_t size)
+{
+       check_memory_region(addr, size, true, _RET_IP_);
+}
+EXPORT_SYMBOL(__asan_storeN);
+
+__alias(__asan_storeN)
+void __asan_storeN_noabort(unsigned long, size_t);
+EXPORT_SYMBOL(__asan_storeN_noabort);
+
+/* to shut up compiler complaints */
+void __asan_handle_no_return(void) {}
+EXPORT_SYMBOL(__asan_handle_no_return);
+
+/* Emitted by compiler to poison large objects when they go out of scope. */
+void __asan_poison_stack_memory(const void *addr, size_t size)
+{
+       /*
+        * Addr is KASAN_SHADOW_SCALE_SIZE-aligned and the object is surrounded
+        * by redzones, so we simply round up size to simplify logic.
+        */
+       kasan_poison_shadow(addr, round_up(size, KASAN_SHADOW_SCALE_SIZE),
+                           KASAN_USE_AFTER_SCOPE);
+}
+EXPORT_SYMBOL(__asan_poison_stack_memory);
+
+/* Emitted by compiler to unpoison large objects when they go into scope. */
+void __asan_unpoison_stack_memory(const void *addr, size_t size)
+{
+       kasan_unpoison_shadow(addr, size);
+}
+EXPORT_SYMBOL(__asan_unpoison_stack_memory);
+
+/* Emitted by compiler to poison alloca()ed objects. */
+void __asan_alloca_poison(unsigned long addr, size_t size)
+{
+       size_t rounded_up_size = round_up(size, KASAN_SHADOW_SCALE_SIZE);
+       size_t padding_size = round_up(size, KASAN_ALLOCA_REDZONE_SIZE) -
+                       rounded_up_size;
+       size_t rounded_down_size = round_down(size, KASAN_SHADOW_SCALE_SIZE);
+
+       const void *left_redzone = (const void *)(addr -
+                       KASAN_ALLOCA_REDZONE_SIZE);
+       const void *right_redzone = (const void *)(addr + rounded_up_size);
+
+       WARN_ON(!IS_ALIGNED(addr, KASAN_ALLOCA_REDZONE_SIZE));
+
+       kasan_unpoison_shadow((const void *)(addr + rounded_down_size),
+                             size - rounded_down_size);
+       kasan_poison_shadow(left_redzone, KASAN_ALLOCA_REDZONE_SIZE,
+                       KASAN_ALLOCA_LEFT);
+       kasan_poison_shadow(right_redzone,
+                       padding_size + KASAN_ALLOCA_REDZONE_SIZE,
+                       KASAN_ALLOCA_RIGHT);
+}
+EXPORT_SYMBOL(__asan_alloca_poison);
+
+/* Emitted by compiler to unpoison alloca()ed areas when the stack unwinds. */
+void __asan_allocas_unpoison(const void *stack_top, const void *stack_bottom)
+{
+       if (unlikely(!stack_top || stack_top > stack_bottom))
+               return;
+
+       kasan_unpoison_shadow(stack_top, stack_bottom - stack_top);
+}
+EXPORT_SYMBOL(__asan_allocas_unpoison);
+
+/* Emitted by the compiler to [un]poison local variables. */
+#define DEFINE_ASAN_SET_SHADOW(byte) \
+       void __asan_set_shadow_##byte(const void *addr, size_t size)    \
+       {                                                               \
+               __memset((void *)addr, 0x##byte, size);                 \
+       }                                                               \
+       EXPORT_SYMBOL(__asan_set_shadow_##byte)
+
+DEFINE_ASAN_SET_SHADOW(00);
+DEFINE_ASAN_SET_SHADOW(f1);
+DEFINE_ASAN_SET_SHADOW(f2);
+DEFINE_ASAN_SET_SHADOW(f3);
+DEFINE_ASAN_SET_SHADOW(f5);
+DEFINE_ASAN_SET_SHADOW(f8);
diff --git a/mm/kasan/generic_report.c b/mm/kasan/generic_report.c
new file mode 100644 (file)
index 0000000..5e12035
--- /dev/null
@@ -0,0 +1,153 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * This file contains generic KASAN specific error reporting code.
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * Author: Andrey Ryabinin <ryabinin.a.a@gmail.com>
+ *
+ * Some code borrowed from https://github.com/xairy/kasan-prototype by
+ *        Andrey Konovalov <andreyknvl@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/bitops.h>
+#include <linux/ftrace.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/printk.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/stackdepot.h>
+#include <linux/stacktrace.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/kasan.h>
+#include <linux/module.h>
+
+#include <asm/sections.h>
+
+#include "kasan.h"
+#include "../slab.h"
+
+void *find_first_bad_addr(void *addr, size_t size)
+{
+       void *p = addr;
+
+       while (p < addr + size && !(*(u8 *)kasan_mem_to_shadow(p)))
+               p += KASAN_SHADOW_SCALE_SIZE;
+       return p;
+}
+
+static const char *get_shadow_bug_type(struct kasan_access_info *info)
+{
+       const char *bug_type = "unknown-crash";
+       u8 *shadow_addr;
+
+       shadow_addr = (u8 *)kasan_mem_to_shadow(info->first_bad_addr);
+
+       /*
+        * If shadow byte value is in [0, KASAN_SHADOW_SCALE_SIZE) we can look
+        * at the next shadow byte to determine the type of the bad access.
+        */
+       if (*shadow_addr > 0 && *shadow_addr <= KASAN_SHADOW_SCALE_SIZE - 1)
+               shadow_addr++;
+
+       switch (*shadow_addr) {
+       case 0 ... KASAN_SHADOW_SCALE_SIZE - 1:
+               /*
+                * In theory it's still possible to see these shadow values
+                * due to a data race in the kernel code.
+                */
+               bug_type = "out-of-bounds";
+               break;
+       case KASAN_PAGE_REDZONE:
+       case KASAN_KMALLOC_REDZONE:
+               bug_type = "slab-out-of-bounds";
+               break;
+       case KASAN_GLOBAL_REDZONE:
+               bug_type = "global-out-of-bounds";
+               break;
+       case KASAN_STACK_LEFT:
+       case KASAN_STACK_MID:
+       case KASAN_STACK_RIGHT:
+       case KASAN_STACK_PARTIAL:
+               bug_type = "stack-out-of-bounds";
+               break;
+       case KASAN_FREE_PAGE:
+       case KASAN_KMALLOC_FREE:
+               bug_type = "use-after-free";
+               break;
+       case KASAN_USE_AFTER_SCOPE:
+               bug_type = "use-after-scope";
+               break;
+       case KASAN_ALLOCA_LEFT:
+       case KASAN_ALLOCA_RIGHT:
+               bug_type = "alloca-out-of-bounds";
+               break;
+       }
+
+       return bug_type;
+}
+
+static const char *get_wild_bug_type(struct kasan_access_info *info)
+{
+       const char *bug_type = "unknown-crash";
+
+       if ((unsigned long)info->access_addr < PAGE_SIZE)
+               bug_type = "null-ptr-deref";
+       else if ((unsigned long)info->access_addr < TASK_SIZE)
+               bug_type = "user-memory-access";
+       else
+               bug_type = "wild-memory-access";
+
+       return bug_type;
+}
+
+const char *get_bug_type(struct kasan_access_info *info)
+{
+       if (addr_has_shadow(info->access_addr))
+               return get_shadow_bug_type(info);
+       return get_wild_bug_type(info);
+}
+
+#define DEFINE_ASAN_REPORT_LOAD(size)                     \
+void __asan_report_load##size##_noabort(unsigned long addr) \
+{                                                         \
+       kasan_report(addr, size, false, _RET_IP_);        \
+}                                                         \
+EXPORT_SYMBOL(__asan_report_load##size##_noabort)
+
+#define DEFINE_ASAN_REPORT_STORE(size)                     \
+void __asan_report_store##size##_noabort(unsigned long addr) \
+{                                                          \
+       kasan_report(addr, size, true, _RET_IP_);          \
+}                                                          \
+EXPORT_SYMBOL(__asan_report_store##size##_noabort)
+
+DEFINE_ASAN_REPORT_LOAD(1);
+DEFINE_ASAN_REPORT_LOAD(2);
+DEFINE_ASAN_REPORT_LOAD(4);
+DEFINE_ASAN_REPORT_LOAD(8);
+DEFINE_ASAN_REPORT_LOAD(16);
+DEFINE_ASAN_REPORT_STORE(1);
+DEFINE_ASAN_REPORT_STORE(2);
+DEFINE_ASAN_REPORT_STORE(4);
+DEFINE_ASAN_REPORT_STORE(8);
+DEFINE_ASAN_REPORT_STORE(16);
+
+void __asan_report_load_n_noabort(unsigned long addr, size_t size)
+{
+       kasan_report(addr, size, false, _RET_IP_);
+}
+EXPORT_SYMBOL(__asan_report_load_n_noabort);
+
+void __asan_report_store_n_noabort(unsigned long addr, size_t size)
+{
+       kasan_report(addr, size, true, _RET_IP_);
+}
+EXPORT_SYMBOL(__asan_report_store_n_noabort);
diff --git a/mm/kasan/init.c b/mm/kasan/init.c
new file mode 100644 (file)
index 0000000..34afad5
--- /dev/null
@@ -0,0 +1,499 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * This file contains some kasan initialization code.
+ *
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Author: Andrey Ryabinin <ryabinin.a.a@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/memblock.h>
+#include <linux/init.h>
+#include <linux/kasan.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/pfn.h>
+#include <linux/slab.h>
+
+#include <asm/page.h>
+#include <asm/pgalloc.h>
+
+#include "kasan.h"
+
+/*
+ * This page serves two purposes:
+ *   - It used as early shadow memory. The entire shadow region populated
+ *     with this page, before we will be able to setup normal shadow memory.
+ *   - Latter it reused it as zero shadow to cover large ranges of memory
+ *     that allowed to access, but not handled by kasan (vmalloc/vmemmap ...).
+ */
+unsigned char kasan_early_shadow_page[PAGE_SIZE] __page_aligned_bss;
+
+#if CONFIG_PGTABLE_LEVELS > 4
+p4d_t kasan_early_shadow_p4d[MAX_PTRS_PER_P4D] __page_aligned_bss;
+static inline bool kasan_p4d_table(pgd_t pgd)
+{
+       return pgd_page(pgd) == virt_to_page(lm_alias(kasan_early_shadow_p4d));
+}
+#else
+static inline bool kasan_p4d_table(pgd_t pgd)
+{
+       return 0;
+}
+#endif
+#if CONFIG_PGTABLE_LEVELS > 3
+pud_t kasan_early_shadow_pud[PTRS_PER_PUD] __page_aligned_bss;
+static inline bool kasan_pud_table(p4d_t p4d)
+{
+       return p4d_page(p4d) == virt_to_page(lm_alias(kasan_early_shadow_pud));
+}
+#else
+static inline bool kasan_pud_table(p4d_t p4d)
+{
+       return 0;
+}
+#endif
+#if CONFIG_PGTABLE_LEVELS > 2
+pmd_t kasan_early_shadow_pmd[PTRS_PER_PMD] __page_aligned_bss;
+static inline bool kasan_pmd_table(pud_t pud)
+{
+       return pud_page(pud) == virt_to_page(lm_alias(kasan_early_shadow_pmd));
+}
+#else
+static inline bool kasan_pmd_table(pud_t pud)
+{
+       return 0;
+}
+#endif
+pte_t kasan_early_shadow_pte[PTRS_PER_PTE] __page_aligned_bss;
+
+static inline bool kasan_pte_table(pmd_t pmd)
+{
+       return pmd_page(pmd) == virt_to_page(lm_alias(kasan_early_shadow_pte));
+}
+
+static inline bool kasan_early_shadow_page_entry(pte_t pte)
+{
+       return pte_page(pte) == virt_to_page(lm_alias(kasan_early_shadow_page));
+}
+
+static __init void *early_alloc(size_t size, int node)
+{
+       return memblock_alloc_try_nid(size, size, __pa(MAX_DMA_ADDRESS),
+                                       MEMBLOCK_ALLOC_ACCESSIBLE, node);
+}
+
+static void __ref zero_pte_populate(pmd_t *pmd, unsigned long addr,
+                               unsigned long end)
+{
+       pte_t *pte = pte_offset_kernel(pmd, addr);
+       pte_t zero_pte;
+
+       zero_pte = pfn_pte(PFN_DOWN(__pa_symbol(kasan_early_shadow_page)),
+                               PAGE_KERNEL);
+       zero_pte = pte_wrprotect(zero_pte);
+
+       while (addr + PAGE_SIZE <= end) {
+               set_pte_at(&init_mm, addr, pte, zero_pte);
+               addr += PAGE_SIZE;
+               pte = pte_offset_kernel(pmd, addr);
+       }
+}
+
+static int __ref zero_pmd_populate(pud_t *pud, unsigned long addr,
+                               unsigned long end)
+{
+       pmd_t *pmd = pmd_offset(pud, addr);
+       unsigned long next;
+
+       do {
+               next = pmd_addr_end(addr, end);
+
+               if (IS_ALIGNED(addr, PMD_SIZE) && end - addr >= PMD_SIZE) {
+                       pmd_populate_kernel(&init_mm, pmd,
+                                       lm_alias(kasan_early_shadow_pte));
+                       continue;
+               }
+
+               if (pmd_none(*pmd)) {
+                       pte_t *p;
+
+                       if (slab_is_available())
+                               p = pte_alloc_one_kernel(&init_mm, addr);
+                       else
+                               p = early_alloc(PAGE_SIZE, NUMA_NO_NODE);
+                       if (!p)
+                               return -ENOMEM;
+
+                       pmd_populate_kernel(&init_mm, pmd, p);
+               }
+               zero_pte_populate(pmd, addr, next);
+       } while (pmd++, addr = next, addr != end);
+
+       return 0;
+}
+
+static int __ref zero_pud_populate(p4d_t *p4d, unsigned long addr,
+                               unsigned long end)
+{
+       pud_t *pud = pud_offset(p4d, addr);
+       unsigned long next;
+
+       do {
+               next = pud_addr_end(addr, end);
+               if (IS_ALIGNED(addr, PUD_SIZE) && end - addr >= PUD_SIZE) {
+                       pmd_t *pmd;
+
+                       pud_populate(&init_mm, pud,
+                                       lm_alias(kasan_early_shadow_pmd));
+                       pmd = pmd_offset(pud, addr);
+                       pmd_populate_kernel(&init_mm, pmd,
+                                       lm_alias(kasan_early_shadow_pte));
+                       continue;
+               }
+
+               if (pud_none(*pud)) {
+                       pmd_t *p;
+
+                       if (slab_is_available()) {
+                               p = pmd_alloc(&init_mm, pud, addr);
+                               if (!p)
+                                       return -ENOMEM;
+                       } else {
+                               pud_populate(&init_mm, pud,
+                                       early_alloc(PAGE_SIZE, NUMA_NO_NODE));
+                       }
+               }
+               zero_pmd_populate(pud, addr, next);
+       } while (pud++, addr = next, addr != end);
+
+       return 0;
+}
+
+static int __ref zero_p4d_populate(pgd_t *pgd, unsigned long addr,
+                               unsigned long end)
+{
+       p4d_t *p4d = p4d_offset(pgd, addr);
+       unsigned long next;
+
+       do {
+               next = p4d_addr_end(addr, end);
+               if (IS_ALIGNED(addr, P4D_SIZE) && end - addr >= P4D_SIZE) {
+                       pud_t *pud;
+                       pmd_t *pmd;
+
+                       p4d_populate(&init_mm, p4d,
+                                       lm_alias(kasan_early_shadow_pud));
+                       pud = pud_offset(p4d, addr);
+                       pud_populate(&init_mm, pud,
+                                       lm_alias(kasan_early_shadow_pmd));
+                       pmd = pmd_offset(pud, addr);
+                       pmd_populate_kernel(&init_mm, pmd,
+                                       lm_alias(kasan_early_shadow_pte));
+                       continue;
+               }
+
+               if (p4d_none(*p4d)) {
+                       pud_t *p;
+
+                       if (slab_is_available()) {
+                               p = pud_alloc(&init_mm, p4d, addr);
+                               if (!p)
+                                       return -ENOMEM;
+                       } else {
+                               p4d_populate(&init_mm, p4d,
+                                       early_alloc(PAGE_SIZE, NUMA_NO_NODE));
+                       }
+               }
+               zero_pud_populate(p4d, addr, next);
+       } while (p4d++, addr = next, addr != end);
+
+       return 0;
+}
+
+/**
+ * kasan_populate_early_shadow - populate shadow memory region with
+ *                               kasan_early_shadow_page
+ * @shadow_start - start of the memory range to populate
+ * @shadow_end   - end of the memory range to populate
+ */
+int __ref kasan_populate_early_shadow(const void *shadow_start,
+                                       const void *shadow_end)
+{
+       unsigned long addr = (unsigned long)shadow_start;
+       unsigned long end = (unsigned long)shadow_end;
+       pgd_t *pgd = pgd_offset_k(addr);
+       unsigned long next;
+
+       do {
+               next = pgd_addr_end(addr, end);
+
+               if (IS_ALIGNED(addr, PGDIR_SIZE) && end - addr >= PGDIR_SIZE) {
+                       p4d_t *p4d;
+                       pud_t *pud;
+                       pmd_t *pmd;
+
+                       /*
+                        * kasan_early_shadow_pud should be populated with pmds
+                        * at this moment.
+                        * [pud,pmd]_populate*() below needed only for
+                        * 3,2 - level page tables where we don't have
+                        * puds,pmds, so pgd_populate(), pud_populate()
+                        * is noops.
+                        *
+                        * The ifndef is required to avoid build breakage.
+                        *
+                        * With 5level-fixup.h, pgd_populate() is not nop and
+                        * we reference kasan_early_shadow_p4d. It's not defined
+                        * unless 5-level paging enabled.
+                        *
+                        * The ifndef can be dropped once all KASAN-enabled
+                        * architectures will switch to pgtable-nop4d.h.
+                        */
+#ifndef __ARCH_HAS_5LEVEL_HACK
+                       pgd_populate(&init_mm, pgd,
+                                       lm_alias(kasan_early_shadow_p4d));
+#endif
+                       p4d = p4d_offset(pgd, addr);
+                       p4d_populate(&init_mm, p4d,
+                                       lm_alias(kasan_early_shadow_pud));
+                       pud = pud_offset(p4d, addr);
+                       pud_populate(&init_mm, pud,
+                                       lm_alias(kasan_early_shadow_pmd));
+                       pmd = pmd_offset(pud, addr);
+                       pmd_populate_kernel(&init_mm, pmd,
+                                       lm_alias(kasan_early_shadow_pte));
+                       continue;
+               }
+
+               if (pgd_none(*pgd)) {
+                       p4d_t *p;
+
+                       if (slab_is_available()) {
+                               p = p4d_alloc(&init_mm, pgd, addr);
+                               if (!p)
+                                       return -ENOMEM;
+                       } else {
+                               pgd_populate(&init_mm, pgd,
+                                       early_alloc(PAGE_SIZE, NUMA_NO_NODE));
+                       }
+               }
+               zero_p4d_populate(pgd, addr, next);
+       } while (pgd++, addr = next, addr != end);
+
+       return 0;
+}
+
+static void kasan_free_pte(pte_t *pte_start, pmd_t *pmd)
+{
+       pte_t *pte;
+       int i;
+
+       for (i = 0; i < PTRS_PER_PTE; i++) {
+               pte = pte_start + i;
+               if (!pte_none(*pte))
+                       return;
+       }
+
+       pte_free_kernel(&init_mm, (pte_t *)page_to_virt(pmd_page(*pmd)));
+       pmd_clear(pmd);
+}
+
+static void kasan_free_pmd(pmd_t *pmd_start, pud_t *pud)
+{
+       pmd_t *pmd;
+       int i;
+
+       for (i = 0; i < PTRS_PER_PMD; i++) {
+               pmd = pmd_start + i;
+               if (!pmd_none(*pmd))
+                       return;
+       }
+
+       pmd_free(&init_mm, (pmd_t *)page_to_virt(pud_page(*pud)));
+       pud_clear(pud);
+}
+
+static void kasan_free_pud(pud_t *pud_start, p4d_t *p4d)
+{
+       pud_t *pud;
+       int i;
+
+       for (i = 0; i < PTRS_PER_PUD; i++) {
+               pud = pud_start + i;
+               if (!pud_none(*pud))
+                       return;
+       }
+
+       pud_free(&init_mm, (pud_t *)page_to_virt(p4d_page(*p4d)));
+       p4d_clear(p4d);
+}
+
+static void kasan_free_p4d(p4d_t *p4d_start, pgd_t *pgd)
+{
+       p4d_t *p4d;
+       int i;
+
+       for (i = 0; i < PTRS_PER_P4D; i++) {
+               p4d = p4d_start + i;
+               if (!p4d_none(*p4d))
+                       return;
+       }
+
+       p4d_free(&init_mm, (p4d_t *)page_to_virt(pgd_page(*pgd)));
+       pgd_clear(pgd);
+}
+
+static void kasan_remove_pte_table(pte_t *pte, unsigned long addr,
+                               unsigned long end)
+{
+       unsigned long next;
+
+       for (; addr < end; addr = next, pte++) {
+               next = (addr + PAGE_SIZE) & PAGE_MASK;
+               if (next > end)
+                       next = end;
+
+               if (!pte_present(*pte))
+                       continue;
+
+               if (WARN_ON(!kasan_early_shadow_page_entry(*pte)))
+                       continue;
+               pte_clear(&init_mm, addr, pte);
+       }
+}
+
+static void kasan_remove_pmd_table(pmd_t *pmd, unsigned long addr,
+                               unsigned long end)
+{
+       unsigned long next;
+
+       for (; addr < end; addr = next, pmd++) {
+               pte_t *pte;
+
+               next = pmd_addr_end(addr, end);
+
+               if (!pmd_present(*pmd))
+                       continue;
+
+               if (kasan_pte_table(*pmd)) {
+                       if (IS_ALIGNED(addr, PMD_SIZE) &&
+                           IS_ALIGNED(next, PMD_SIZE))
+                               pmd_clear(pmd);
+                       continue;
+               }
+               pte = pte_offset_kernel(pmd, addr);
+               kasan_remove_pte_table(pte, addr, next);
+               kasan_free_pte(pte_offset_kernel(pmd, 0), pmd);
+       }
+}
+
+static void kasan_remove_pud_table(pud_t *pud, unsigned long addr,
+                               unsigned long end)
+{
+       unsigned long next;
+
+       for (; addr < end; addr = next, pud++) {
+               pmd_t *pmd, *pmd_base;
+
+               next = pud_addr_end(addr, end);
+
+               if (!pud_present(*pud))
+                       continue;
+
+               if (kasan_pmd_table(*pud)) {
+                       if (IS_ALIGNED(addr, PUD_SIZE) &&
+                           IS_ALIGNED(next, PUD_SIZE))
+                               pud_clear(pud);
+                       continue;
+               }
+               pmd = pmd_offset(pud, addr);
+               pmd_base = pmd_offset(pud, 0);
+               kasan_remove_pmd_table(pmd, addr, next);
+               kasan_free_pmd(pmd_base, pud);
+       }
+}
+
+static void kasan_remove_p4d_table(p4d_t *p4d, unsigned long addr,
+                               unsigned long end)
+{
+       unsigned long next;
+
+       for (; addr < end; addr = next, p4d++) {
+               pud_t *pud;
+
+               next = p4d_addr_end(addr, end);
+
+               if (!p4d_present(*p4d))
+                       continue;
+
+               if (kasan_pud_table(*p4d)) {
+                       if (IS_ALIGNED(addr, P4D_SIZE) &&
+                           IS_ALIGNED(next, P4D_SIZE))
+                               p4d_clear(p4d);
+                       continue;
+               }
+               pud = pud_offset(p4d, addr);
+               kasan_remove_pud_table(pud, addr, next);
+               kasan_free_pud(pud_offset(p4d, 0), p4d);
+       }
+}
+
+void kasan_remove_zero_shadow(void *start, unsigned long size)
+{
+       unsigned long addr, end, next;
+       pgd_t *pgd;
+
+       addr = (unsigned long)kasan_mem_to_shadow(start);
+       end = addr + (size >> KASAN_SHADOW_SCALE_SHIFT);
+
+       if (WARN_ON((unsigned long)start %
+                       (KASAN_SHADOW_SCALE_SIZE * PAGE_SIZE)) ||
+           WARN_ON(size % (KASAN_SHADOW_SCALE_SIZE * PAGE_SIZE)))
+               return;
+
+       for (; addr < end; addr = next) {
+               p4d_t *p4d;
+
+               next = pgd_addr_end(addr, end);
+
+               pgd = pgd_offset_k(addr);
+               if (!pgd_present(*pgd))
+                       continue;
+
+               if (kasan_p4d_table(*pgd)) {
+                       if (IS_ALIGNED(addr, PGDIR_SIZE) &&
+                           IS_ALIGNED(next, PGDIR_SIZE))
+                               pgd_clear(pgd);
+                       continue;
+               }
+
+               p4d = p4d_offset(pgd, addr);
+               kasan_remove_p4d_table(p4d, addr, next);
+               kasan_free_p4d(p4d_offset(pgd, 0), pgd);
+       }
+}
+
+int kasan_add_zero_shadow(void *start, unsigned long size)
+{
+       int ret;
+       void *shadow_start, *shadow_end;
+
+       shadow_start = kasan_mem_to_shadow(start);
+       shadow_end = shadow_start + (size >> KASAN_SHADOW_SCALE_SHIFT);
+
+       if (WARN_ON((unsigned long)start %
+                       (KASAN_SHADOW_SCALE_SIZE * PAGE_SIZE)) ||
+           WARN_ON(size % (KASAN_SHADOW_SCALE_SIZE * PAGE_SIZE)))
+               return -EINVAL;
+
+       ret = kasan_populate_early_shadow(shadow_start, shadow_end);
+       if (ret)
+               kasan_remove_zero_shadow(shadow_start,
+                                       size >> KASAN_SHADOW_SCALE_SHIFT);
+       return ret;
+}
diff --git a/mm/kasan/kasan.c b/mm/kasan/kasan.c
deleted file mode 100644 (file)
index c3bd520..0000000
+++ /dev/null
@@ -1,903 +0,0 @@
-/*
- * This file contains shadow memory manipulation code.
- *
- * Copyright (c) 2014 Samsung Electronics Co., Ltd.
- * Author: Andrey Ryabinin <ryabinin.a.a@gmail.com>
- *
- * Some code borrowed from https://github.com/xairy/kasan-prototype by
- *        Andrey Konovalov <andreyknvl@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-#define DISABLE_BRANCH_PROFILING
-
-#include <linux/export.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/kasan.h>
-#include <linux/kernel.h>
-#include <linux/kmemleak.h>
-#include <linux/linkage.h>
-#include <linux/memblock.h>
-#include <linux/memory.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/printk.h>
-#include <linux/sched.h>
-#include <linux/sched/task_stack.h>
-#include <linux/slab.h>
-#include <linux/stacktrace.h>
-#include <linux/string.h>
-#include <linux/types.h>
-#include <linux/vmalloc.h>
-#include <linux/bug.h>
-
-#include "kasan.h"
-#include "../slab.h"
-
-void kasan_enable_current(void)
-{
-       current->kasan_depth++;
-}
-
-void kasan_disable_current(void)
-{
-       current->kasan_depth--;
-}
-
-/*
- * Poisons the shadow memory for 'size' bytes starting from 'addr'.
- * Memory addresses should be aligned to KASAN_SHADOW_SCALE_SIZE.
- */
-static void kasan_poison_shadow(const void *address, size_t size, u8 value)
-{
-       void *shadow_start, *shadow_end;
-
-       shadow_start = kasan_mem_to_shadow(address);
-       shadow_end = kasan_mem_to_shadow(address + size);
-
-       memset(shadow_start, value, shadow_end - shadow_start);
-}
-
-void kasan_unpoison_shadow(const void *address, size_t size)
-{
-       kasan_poison_shadow(address, size, 0);
-
-       if (size & KASAN_SHADOW_MASK) {
-               u8 *shadow = (u8 *)kasan_mem_to_shadow(address + size);
-               *shadow = size & KASAN_SHADOW_MASK;
-       }
-}
-
-static void __kasan_unpoison_stack(struct task_struct *task, const void *sp)
-{
-       void *base = task_stack_page(task);
-       size_t size = sp - base;
-
-       kasan_unpoison_shadow(base, size);
-}
-
-/* Unpoison the entire stack for a task. */
-void kasan_unpoison_task_stack(struct task_struct *task)
-{
-       __kasan_unpoison_stack(task, task_stack_page(task) + THREAD_SIZE);
-}
-
-/* Unpoison the stack for the current task beyond a watermark sp value. */
-asmlinkage void kasan_unpoison_task_stack_below(const void *watermark)
-{
-       /*
-        * Calculate the task stack base address.  Avoid using 'current'
-        * because this function is called by early resume code which hasn't
-        * yet set up the percpu register (%gs).
-        */
-       void *base = (void *)((unsigned long)watermark & ~(THREAD_SIZE - 1));
-
-       kasan_unpoison_shadow(base, watermark - base);
-}
-
-/*
- * Clear all poison for the region between the current SP and a provided
- * watermark value, as is sometimes required prior to hand-crafted asm function
- * returns in the middle of functions.
- */
-void kasan_unpoison_stack_above_sp_to(const void *watermark)
-{
-       const void *sp = __builtin_frame_address(0);
-       size_t size = watermark - sp;
-
-       if (WARN_ON(sp > watermark))
-               return;
-       kasan_unpoison_shadow(sp, size);
-}
-
-/*
- * All functions below always inlined so compiler could
- * perform better optimizations in each of __asan_loadX/__assn_storeX
- * depending on memory access size X.
- */
-
-static __always_inline bool memory_is_poisoned_1(unsigned long addr)
-{
-       s8 shadow_value = *(s8 *)kasan_mem_to_shadow((void *)addr);
-
-       if (unlikely(shadow_value)) {
-               s8 last_accessible_byte = addr & KASAN_SHADOW_MASK;
-               return unlikely(last_accessible_byte >= shadow_value);
-       }
-
-       return false;
-}
-
-static __always_inline bool memory_is_poisoned_2_4_8(unsigned long addr,
-                                               unsigned long size)
-{
-       u8 *shadow_addr = (u8 *)kasan_mem_to_shadow((void *)addr);
-
-       /*
-        * Access crosses 8(shadow size)-byte boundary. Such access maps
-        * into 2 shadow bytes, so we need to check them both.
-        */
-       if (unlikely(((addr + size - 1) & KASAN_SHADOW_MASK) < size - 1))
-               return *shadow_addr || memory_is_poisoned_1(addr + size - 1);
-
-       return memory_is_poisoned_1(addr + size - 1);
-}
-
-static __always_inline bool memory_is_poisoned_16(unsigned long addr)
-{
-       u16 *shadow_addr = (u16 *)kasan_mem_to_shadow((void *)addr);
-
-       /* Unaligned 16-bytes access maps into 3 shadow bytes. */
-       if (unlikely(!IS_ALIGNED(addr, KASAN_SHADOW_SCALE_SIZE)))
-               return *shadow_addr || memory_is_poisoned_1(addr + 15);
-
-       return *shadow_addr;
-}
-
-static __always_inline unsigned long bytes_is_nonzero(const u8 *start,
-                                       size_t size)
-{
-       while (size) {
-               if (unlikely(*start))
-                       return (unsigned long)start;
-               start++;
-               size--;
-       }
-
-       return 0;
-}
-
-static __always_inline unsigned long memory_is_nonzero(const void *start,
-                                               const void *end)
-{
-       unsigned int words;
-       unsigned long ret;
-       unsigned int prefix = (unsigned long)start % 8;
-
-       if (end - start <= 16)
-               return bytes_is_nonzero(start, end - start);
-
-       if (prefix) {
-               prefix = 8 - prefix;
-               ret = bytes_is_nonzero(start, prefix);
-               if (unlikely(ret))
-                       return ret;
-               start += prefix;
-       }
-
-       words = (end - start) / 8;
-       while (words) {
-               if (unlikely(*(u64 *)start))
-                       return bytes_is_nonzero(start, 8);
-               start += 8;
-               words--;
-       }
-
-       return bytes_is_nonzero(start, (end - start) % 8);
-}
-
-static __always_inline bool memory_is_poisoned_n(unsigned long addr,
-                                               size_t size)
-{
-       unsigned long ret;
-
-       ret = memory_is_nonzero(kasan_mem_to_shadow((void *)addr),
-                       kasan_mem_to_shadow((void *)addr + size - 1) + 1);
-
-       if (unlikely(ret)) {
-               unsigned long last_byte = addr + size - 1;
-               s8 *last_shadow = (s8 *)kasan_mem_to_shadow((void *)last_byte);
-
-               if (unlikely(ret != (unsigned long)last_shadow ||
-                       ((long)(last_byte & KASAN_SHADOW_MASK) >= *last_shadow)))
-                       return true;
-       }
-       return false;
-}
-
-static __always_inline bool memory_is_poisoned(unsigned long addr, size_t size)
-{
-       if (__builtin_constant_p(size)) {
-               switch (size) {
-               case 1:
-                       return memory_is_poisoned_1(addr);
-               case 2:
-               case 4:
-               case 8:
-                       return memory_is_poisoned_2_4_8(addr, size);
-               case 16:
-                       return memory_is_poisoned_16(addr);
-               default:
-                       BUILD_BUG();
-               }
-       }
-
-       return memory_is_poisoned_n(addr, size);
-}
-
-static __always_inline void check_memory_region_inline(unsigned long addr,
-                                               size_t size, bool write,
-                                               unsigned long ret_ip)
-{
-       if (unlikely(size == 0))
-               return;
-
-       if (unlikely((void *)addr <
-               kasan_shadow_to_mem((void *)KASAN_SHADOW_START))) {
-               kasan_report(addr, size, write, ret_ip);
-               return;
-       }
-
-       if (likely(!memory_is_poisoned(addr, size)))
-               return;
-
-       kasan_report(addr, size, write, ret_ip);
-}
-
-static void check_memory_region(unsigned long addr,
-                               size_t size, bool write,
-                               unsigned long ret_ip)
-{
-       check_memory_region_inline(addr, size, write, ret_ip);
-}
-
-void kasan_check_read(const volatile void *p, unsigned int size)
-{
-       check_memory_region((unsigned long)p, size, false, _RET_IP_);
-}
-EXPORT_SYMBOL(kasan_check_read);
-
-void kasan_check_write(const volatile void *p, unsigned int size)
-{
-       check_memory_region((unsigned long)p, size, true, _RET_IP_);
-}
-EXPORT_SYMBOL(kasan_check_write);
-
-#undef memset
-void *memset(void *addr, int c, size_t len)
-{
-       check_memory_region((unsigned long)addr, len, true, _RET_IP_);
-
-       return __memset(addr, c, len);
-}
-
-#undef memmove
-void *memmove(void *dest, const void *src, size_t len)
-{
-       check_memory_region((unsigned long)src, len, false, _RET_IP_);
-       check_memory_region((unsigned long)dest, len, true, _RET_IP_);
-
-       return __memmove(dest, src, len);
-}
-
-#undef memcpy
-void *memcpy(void *dest, const void *src, size_t len)
-{
-       check_memory_region((unsigned long)src, len, false, _RET_IP_);
-       check_memory_region((unsigned long)dest, len, true, _RET_IP_);
-
-       return __memcpy(dest, src, len);
-}
-
-void kasan_alloc_pages(struct page *page, unsigned int order)
-{
-       if (likely(!PageHighMem(page)))
-               kasan_unpoison_shadow(page_address(page), PAGE_SIZE << order);
-}
-
-void kasan_free_pages(struct page *page, unsigned int order)
-{
-       if (likely(!PageHighMem(page)))
-               kasan_poison_shadow(page_address(page),
-                               PAGE_SIZE << order,
-                               KASAN_FREE_PAGE);
-}
-
-/*
- * Adaptive redzone policy taken from the userspace AddressSanitizer runtime.
- * For larger allocations larger redzones are used.
- */
-static unsigned int optimal_redzone(unsigned int object_size)
-{
-       return
-               object_size <= 64        - 16   ? 16 :
-               object_size <= 128       - 32   ? 32 :
-               object_size <= 512       - 64   ? 64 :
-               object_size <= 4096      - 128  ? 128 :
-               object_size <= (1 << 14) - 256  ? 256 :
-               object_size <= (1 << 15) - 512  ? 512 :
-               object_size <= (1 << 16) - 1024 ? 1024 : 2048;
-}
-
-void kasan_cache_create(struct kmem_cache *cache, unsigned int *size,
-                       slab_flags_t *flags)
-{
-       unsigned int orig_size = *size;
-       int redzone_adjust;
-
-       /* Add alloc meta. */
-       cache->kasan_info.alloc_meta_offset = *size;
-       *size += sizeof(struct kasan_alloc_meta);
-
-       /* Add free meta. */
-       if (cache->flags & SLAB_TYPESAFE_BY_RCU || cache->ctor ||
-           cache->object_size < sizeof(struct kasan_free_meta)) {
-               cache->kasan_info.free_meta_offset = *size;
-               *size += sizeof(struct kasan_free_meta);
-       }
-       redzone_adjust = optimal_redzone(cache->object_size) -
-               (*size - cache->object_size);
-
-       if (redzone_adjust > 0)
-               *size += redzone_adjust;
-
-       *size = min_t(unsigned int, KMALLOC_MAX_SIZE,
-                       max(*size, cache->object_size +
-                                       optimal_redzone(cache->object_size)));
-
-       /*
-        * If the metadata doesn't fit, don't enable KASAN at all.
-        */
-       if (*size <= cache->kasan_info.alloc_meta_offset ||
-                       *size <= cache->kasan_info.free_meta_offset) {
-               cache->kasan_info.alloc_meta_offset = 0;
-               cache->kasan_info.free_meta_offset = 0;
-               *size = orig_size;
-               return;
-       }
-
-       *flags |= SLAB_KASAN;
-}
-
-void kasan_cache_shrink(struct kmem_cache *cache)
-{
-       quarantine_remove_cache(cache);
-}
-
-void kasan_cache_shutdown(struct kmem_cache *cache)
-{
-       if (!__kmem_cache_empty(cache))
-               quarantine_remove_cache(cache);
-}
-
-size_t kasan_metadata_size(struct kmem_cache *cache)
-{
-       return (cache->kasan_info.alloc_meta_offset ?
-               sizeof(struct kasan_alloc_meta) : 0) +
-               (cache->kasan_info.free_meta_offset ?
-               sizeof(struct kasan_free_meta) : 0);
-}
-
-void kasan_poison_slab(struct page *page)
-{
-       kasan_poison_shadow(page_address(page),
-                       PAGE_SIZE << compound_order(page),
-                       KASAN_KMALLOC_REDZONE);
-}
-
-void kasan_unpoison_object_data(struct kmem_cache *cache, void *object)
-{
-       kasan_unpoison_shadow(object, cache->object_size);
-}
-
-void kasan_poison_object_data(struct kmem_cache *cache, void *object)
-{
-       kasan_poison_shadow(object,
-                       round_up(cache->object_size, KASAN_SHADOW_SCALE_SIZE),
-                       KASAN_KMALLOC_REDZONE);
-}
-
-static inline int in_irqentry_text(unsigned long ptr)
-{
-       return (ptr >= (unsigned long)&__irqentry_text_start &&
-               ptr < (unsigned long)&__irqentry_text_end) ||
-               (ptr >= (unsigned long)&__softirqentry_text_start &&
-                ptr < (unsigned long)&__softirqentry_text_end);
-}
-
-static inline void filter_irq_stacks(struct stack_trace *trace)
-{
-       int i;
-
-       if (!trace->nr_entries)
-               return;
-       for (i = 0; i < trace->nr_entries; i++)
-               if (in_irqentry_text(trace->entries[i])) {
-                       /* Include the irqentry function into the stack. */
-                       trace->nr_entries = i + 1;
-                       break;
-               }
-}
-
-static inline depot_stack_handle_t save_stack(gfp_t flags)
-{
-       unsigned long entries[KASAN_STACK_DEPTH];
-       struct stack_trace trace = {
-               .nr_entries = 0,
-               .entries = entries,
-               .max_entries = KASAN_STACK_DEPTH,
-               .skip = 0
-       };
-
-       save_stack_trace(&trace);
-       filter_irq_stacks(&trace);
-       if (trace.nr_entries != 0 &&
-           trace.entries[trace.nr_entries-1] == ULONG_MAX)
-               trace.nr_entries--;
-
-       return depot_save_stack(&trace, flags);
-}
-
-static inline void set_track(struct kasan_track *track, gfp_t flags)
-{
-       track->pid = current->pid;
-       track->stack = save_stack(flags);
-}
-
-struct kasan_alloc_meta *get_alloc_info(struct kmem_cache *cache,
-                                       const void *object)
-{
-       BUILD_BUG_ON(sizeof(struct kasan_alloc_meta) > 32);
-       return (void *)object + cache->kasan_info.alloc_meta_offset;
-}
-
-struct kasan_free_meta *get_free_info(struct kmem_cache *cache,
-                                     const void *object)
-{
-       BUILD_BUG_ON(sizeof(struct kasan_free_meta) > 32);
-       return (void *)object + cache->kasan_info.free_meta_offset;
-}
-
-void kasan_init_slab_obj(struct kmem_cache *cache, const void *object)
-{
-       struct kasan_alloc_meta *alloc_info;
-
-       if (!(cache->flags & SLAB_KASAN))
-               return;
-
-       alloc_info = get_alloc_info(cache, object);
-       __memset(alloc_info, 0, sizeof(*alloc_info));
-}
-
-void kasan_slab_alloc(struct kmem_cache *cache, void *object, gfp_t flags)
-{
-       kasan_kmalloc(cache, object, cache->object_size, flags);
-}
-
-static bool __kasan_slab_free(struct kmem_cache *cache, void *object,
-                             unsigned long ip, bool quarantine)
-{
-       s8 shadow_byte;
-       unsigned long rounded_up_size;
-
-       if (unlikely(nearest_obj(cache, virt_to_head_page(object), object) !=
-           object)) {
-               kasan_report_invalid_free(object, ip);
-               return true;
-       }
-
-       /* RCU slabs could be legally used after free within the RCU period */
-       if (unlikely(cache->flags & SLAB_TYPESAFE_BY_RCU))
-               return false;
-
-       shadow_byte = READ_ONCE(*(s8 *)kasan_mem_to_shadow(object));
-       if (shadow_byte < 0 || shadow_byte >= KASAN_SHADOW_SCALE_SIZE) {
-               kasan_report_invalid_free(object, ip);
-               return true;
-       }
-
-       rounded_up_size = round_up(cache->object_size, KASAN_SHADOW_SCALE_SIZE);
-       kasan_poison_shadow(object, rounded_up_size, KASAN_KMALLOC_FREE);
-
-       if (!quarantine || unlikely(!(cache->flags & SLAB_KASAN)))
-               return false;
-
-       set_track(&get_alloc_info(cache, object)->free_track, GFP_NOWAIT);
-       quarantine_put(get_free_info(cache, object), cache);
-       return true;
-}
-
-bool kasan_slab_free(struct kmem_cache *cache, void *object, unsigned long ip)
-{
-       return __kasan_slab_free(cache, object, ip, true);
-}
-
-void kasan_kmalloc(struct kmem_cache *cache, const void *object, size_t size,
-                  gfp_t flags)
-{
-       unsigned long redzone_start;
-       unsigned long redzone_end;
-
-       if (gfpflags_allow_blocking(flags))
-               quarantine_reduce();
-
-       if (unlikely(object == NULL))
-               return;
-
-       redzone_start = round_up((unsigned long)(object + size),
-                               KASAN_SHADOW_SCALE_SIZE);
-       redzone_end = round_up((unsigned long)object + cache->object_size,
-                               KASAN_SHADOW_SCALE_SIZE);
-
-       kasan_unpoison_shadow(object, size);
-       kasan_poison_shadow((void *)redzone_start, redzone_end - redzone_start,
-               KASAN_KMALLOC_REDZONE);
-
-       if (cache->flags & SLAB_KASAN)
-               set_track(&get_alloc_info(cache, object)->alloc_track, flags);
-}
-EXPORT_SYMBOL(kasan_kmalloc);
-
-void kasan_kmalloc_large(const void *ptr, size_t size, gfp_t flags)
-{
-       struct page *page;
-       unsigned long redzone_start;
-       unsigned long redzone_end;
-
-       if (gfpflags_allow_blocking(flags))
-               quarantine_reduce();
-
-       if (unlikely(ptr == NULL))
-               return;
-
-       page = virt_to_page(ptr);
-       redzone_start = round_up((unsigned long)(ptr + size),
-                               KASAN_SHADOW_SCALE_SIZE);
-       redzone_end = (unsigned long)ptr + (PAGE_SIZE << compound_order(page));
-
-       kasan_unpoison_shadow(ptr, size);
-       kasan_poison_shadow((void *)redzone_start, redzone_end - redzone_start,
-               KASAN_PAGE_REDZONE);
-}
-
-void kasan_krealloc(const void *object, size_t size, gfp_t flags)
-{
-       struct page *page;
-
-       if (unlikely(object == ZERO_SIZE_PTR))
-               return;
-
-       page = virt_to_head_page(object);
-
-       if (unlikely(!PageSlab(page)))
-               kasan_kmalloc_large(object, size, flags);
-       else
-               kasan_kmalloc(page->slab_cache, object, size, flags);
-}
-
-void kasan_poison_kfree(void *ptr, unsigned long ip)
-{
-       struct page *page;
-
-       page = virt_to_head_page(ptr);
-
-       if (unlikely(!PageSlab(page))) {
-               if (ptr != page_address(page)) {
-                       kasan_report_invalid_free(ptr, ip);
-                       return;
-               }
-               kasan_poison_shadow(ptr, PAGE_SIZE << compound_order(page),
-                               KASAN_FREE_PAGE);
-       } else {
-               __kasan_slab_free(page->slab_cache, ptr, ip, false);
-       }
-}
-
-void kasan_kfree_large(void *ptr, unsigned long ip)
-{
-       if (ptr != page_address(virt_to_head_page(ptr)))
-               kasan_report_invalid_free(ptr, ip);
-       /* The object will be poisoned by page_alloc. */
-}
-
-int kasan_module_alloc(void *addr, size_t size)
-{
-       void *ret;
-       size_t scaled_size;
-       size_t shadow_size;
-       unsigned long shadow_start;
-
-       shadow_start = (unsigned long)kasan_mem_to_shadow(addr);
-       scaled_size = (size + KASAN_SHADOW_MASK) >> KASAN_SHADOW_SCALE_SHIFT;
-       shadow_size = round_up(scaled_size, PAGE_SIZE);
-
-       if (WARN_ON(!PAGE_ALIGNED(shadow_start)))
-               return -EINVAL;
-
-       ret = __vmalloc_node_range(shadow_size, 1, shadow_start,
-                       shadow_start + shadow_size,
-                       GFP_KERNEL | __GFP_ZERO,
-                       PAGE_KERNEL, VM_NO_GUARD, NUMA_NO_NODE,
-                       __builtin_return_address(0));
-
-       if (ret) {
-               find_vm_area(addr)->flags |= VM_KASAN;
-               kmemleak_ignore(ret);
-               return 0;
-       }
-
-       return -ENOMEM;
-}
-
-void kasan_free_shadow(const struct vm_struct *vm)
-{
-       if (vm->flags & VM_KASAN)
-               vfree(kasan_mem_to_shadow(vm->addr));
-}
-
-static void register_global(struct kasan_global *global)
-{
-       size_t aligned_size = round_up(global->size, KASAN_SHADOW_SCALE_SIZE);
-
-       kasan_unpoison_shadow(global->beg, global->size);
-
-       kasan_poison_shadow(global->beg + aligned_size,
-               global->size_with_redzone - aligned_size,
-               KASAN_GLOBAL_REDZONE);
-}
-
-void __asan_register_globals(struct kasan_global *globals, size_t size)
-{
-       int i;
-
-       for (i = 0; i < size; i++)
-               register_global(&globals[i]);
-}
-EXPORT_SYMBOL(__asan_register_globals);
-
-void __asan_unregister_globals(struct kasan_global *globals, size_t size)
-{
-}
-EXPORT_SYMBOL(__asan_unregister_globals);
-
-#define DEFINE_ASAN_LOAD_STORE(size)                                   \
-       void __asan_load##size(unsigned long addr)                      \
-       {                                                               \
-               check_memory_region_inline(addr, size, false, _RET_IP_);\
-       }                                                               \
-       EXPORT_SYMBOL(__asan_load##size);                               \
-       __alias(__asan_load##size)                                      \
-       void __asan_load##size##_noabort(unsigned long);                \
-       EXPORT_SYMBOL(__asan_load##size##_noabort);                     \
-       void __asan_store##size(unsigned long addr)                     \
-       {                                                               \
-               check_memory_region_inline(addr, size, true, _RET_IP_); \
-       }                                                               \
-       EXPORT_SYMBOL(__asan_store##size);                              \
-       __alias(__asan_store##size)                                     \
-       void __asan_store##size##_noabort(unsigned long);               \
-       EXPORT_SYMBOL(__asan_store##size##_noabort)
-
-DEFINE_ASAN_LOAD_STORE(1);
-DEFINE_ASAN_LOAD_STORE(2);
-DEFINE_ASAN_LOAD_STORE(4);
-DEFINE_ASAN_LOAD_STORE(8);
-DEFINE_ASAN_LOAD_STORE(16);
-
-void __asan_loadN(unsigned long addr, size_t size)
-{
-       check_memory_region(addr, size, false, _RET_IP_);
-}
-EXPORT_SYMBOL(__asan_loadN);
-
-__alias(__asan_loadN)
-void __asan_loadN_noabort(unsigned long, size_t);
-EXPORT_SYMBOL(__asan_loadN_noabort);
-
-void __asan_storeN(unsigned long addr, size_t size)
-{
-       check_memory_region(addr, size, true, _RET_IP_);
-}
-EXPORT_SYMBOL(__asan_storeN);
-
-__alias(__asan_storeN)
-void __asan_storeN_noabort(unsigned long, size_t);
-EXPORT_SYMBOL(__asan_storeN_noabort);
-
-/* to shut up compiler complaints */
-void __asan_handle_no_return(void) {}
-EXPORT_SYMBOL(__asan_handle_no_return);
-
-/* Emitted by compiler to poison large objects when they go out of scope. */
-void __asan_poison_stack_memory(const void *addr, size_t size)
-{
-       /*
-        * Addr is KASAN_SHADOW_SCALE_SIZE-aligned and the object is surrounded
-        * by redzones, so we simply round up size to simplify logic.
-        */
-       kasan_poison_shadow(addr, round_up(size, KASAN_SHADOW_SCALE_SIZE),
-                           KASAN_USE_AFTER_SCOPE);
-}
-EXPORT_SYMBOL(__asan_poison_stack_memory);
-
-/* Emitted by compiler to unpoison large objects when they go into scope. */
-void __asan_unpoison_stack_memory(const void *addr, size_t size)
-{
-       kasan_unpoison_shadow(addr, size);
-}
-EXPORT_SYMBOL(__asan_unpoison_stack_memory);
-
-/* Emitted by compiler to poison alloca()ed objects. */
-void __asan_alloca_poison(unsigned long addr, size_t size)
-{
-       size_t rounded_up_size = round_up(size, KASAN_SHADOW_SCALE_SIZE);
-       size_t padding_size = round_up(size, KASAN_ALLOCA_REDZONE_SIZE) -
-                       rounded_up_size;
-       size_t rounded_down_size = round_down(size, KASAN_SHADOW_SCALE_SIZE);
-
-       const void *left_redzone = (const void *)(addr -
-                       KASAN_ALLOCA_REDZONE_SIZE);
-       const void *right_redzone = (const void *)(addr + rounded_up_size);
-
-       WARN_ON(!IS_ALIGNED(addr, KASAN_ALLOCA_REDZONE_SIZE));
-
-       kasan_unpoison_shadow((const void *)(addr + rounded_down_size),
-                             size - rounded_down_size);
-       kasan_poison_shadow(left_redzone, KASAN_ALLOCA_REDZONE_SIZE,
-                       KASAN_ALLOCA_LEFT);
-       kasan_poison_shadow(right_redzone,
-                       padding_size + KASAN_ALLOCA_REDZONE_SIZE,
-                       KASAN_ALLOCA_RIGHT);
-}
-EXPORT_SYMBOL(__asan_alloca_poison);
-
-/* Emitted by compiler to unpoison alloca()ed areas when the stack unwinds. */
-void __asan_allocas_unpoison(const void *stack_top, const void *stack_bottom)
-{
-       if (unlikely(!stack_top || stack_top > stack_bottom))
-               return;
-
-       kasan_unpoison_shadow(stack_top, stack_bottom - stack_top);
-}
-EXPORT_SYMBOL(__asan_allocas_unpoison);
-
-/* Emitted by the compiler to [un]poison local variables. */
-#define DEFINE_ASAN_SET_SHADOW(byte) \
-       void __asan_set_shadow_##byte(const void *addr, size_t size)    \
-       {                                                               \
-               __memset((void *)addr, 0x##byte, size);                 \
-       }                                                               \
-       EXPORT_SYMBOL(__asan_set_shadow_##byte)
-
-DEFINE_ASAN_SET_SHADOW(00);
-DEFINE_ASAN_SET_SHADOW(f1);
-DEFINE_ASAN_SET_SHADOW(f2);
-DEFINE_ASAN_SET_SHADOW(f3);
-DEFINE_ASAN_SET_SHADOW(f5);
-DEFINE_ASAN_SET_SHADOW(f8);
-
-#ifdef CONFIG_MEMORY_HOTPLUG
-static bool shadow_mapped(unsigned long addr)
-{
-       pgd_t *pgd = pgd_offset_k(addr);
-       p4d_t *p4d;
-       pud_t *pud;
-       pmd_t *pmd;
-       pte_t *pte;
-
-       if (pgd_none(*pgd))
-               return false;
-       p4d = p4d_offset(pgd, addr);
-       if (p4d_none(*p4d))
-               return false;
-       pud = pud_offset(p4d, addr);
-       if (pud_none(*pud))
-               return false;
-
-       /*
-        * We can't use pud_large() or pud_huge(), the first one is
-        * arch-specific, the last one depends on HUGETLB_PAGE.  So let's abuse
-        * pud_bad(), if pud is bad then it's bad because it's huge.
-        */
-       if (pud_bad(*pud))
-               return true;
-       pmd = pmd_offset(pud, addr);
-       if (pmd_none(*pmd))
-               return false;
-
-       if (pmd_bad(*pmd))
-               return true;
-       pte = pte_offset_kernel(pmd, addr);
-       return !pte_none(*pte);
-}
-
-static int __meminit kasan_mem_notifier(struct notifier_block *nb,
-                       unsigned long action, void *data)
-{
-       struct memory_notify *mem_data = data;
-       unsigned long nr_shadow_pages, start_kaddr, shadow_start;
-       unsigned long shadow_end, shadow_size;
-
-       nr_shadow_pages = mem_data->nr_pages >> KASAN_SHADOW_SCALE_SHIFT;
-       start_kaddr = (unsigned long)pfn_to_kaddr(mem_data->start_pfn);
-       shadow_start = (unsigned long)kasan_mem_to_shadow((void *)start_kaddr);
-       shadow_size = nr_shadow_pages << PAGE_SHIFT;
-       shadow_end = shadow_start + shadow_size;
-
-       if (WARN_ON(mem_data->nr_pages % KASAN_SHADOW_SCALE_SIZE) ||
-               WARN_ON(start_kaddr % (KASAN_SHADOW_SCALE_SIZE << PAGE_SHIFT)))
-               return NOTIFY_BAD;
-
-       switch (action) {
-       case MEM_GOING_ONLINE: {
-               void *ret;
-
-               /*
-                * If shadow is mapped already than it must have been mapped
-                * during the boot. This could happen if we onlining previously
-                * offlined memory.
-                */
-               if (shadow_mapped(shadow_start))
-                       return NOTIFY_OK;
-
-               ret = __vmalloc_node_range(shadow_size, PAGE_SIZE, shadow_start,
-                                       shadow_end, GFP_KERNEL,
-                                       PAGE_KERNEL, VM_NO_GUARD,
-                                       pfn_to_nid(mem_data->start_pfn),
-                                       __builtin_return_address(0));
-               if (!ret)
-                       return NOTIFY_BAD;
-
-               kmemleak_ignore(ret);
-               return NOTIFY_OK;
-       }
-       case MEM_CANCEL_ONLINE:
-       case MEM_OFFLINE: {
-               struct vm_struct *vm;
-
-               /*
-                * shadow_start was either mapped during boot by kasan_init()
-                * or during memory online by __vmalloc_node_range().
-                * In the latter case we can use vfree() to free shadow.
-                * Non-NULL result of the find_vm_area() will tell us if
-                * that was the second case.
-                *
-                * Currently it's not possible to free shadow mapped
-                * during boot by kasan_init(). It's because the code
-                * to do that hasn't been written yet. So we'll just
-                * leak the memory.
-                */
-               vm = find_vm_area((void *)shadow_start);
-               if (vm)
-                       vfree((void *)shadow_start);
-       }
-       }
-
-       return NOTIFY_OK;
-}
-
-static int __init kasan_memhotplug_init(void)
-{
-       hotplug_memory_notifier(kasan_mem_notifier, 0);
-
-       return 0;
-}
-
-core_initcall(kasan_memhotplug_init);
-#endif
index c12dcfde2ebd406f685af9716d7738a6b2a118bd..ea51b2d898ec22abb4ac9831adc7a38801ae49db 100644 (file)
@@ -8,10 +8,22 @@
 #define KASAN_SHADOW_SCALE_SIZE (1UL << KASAN_SHADOW_SCALE_SHIFT)
 #define KASAN_SHADOW_MASK       (KASAN_SHADOW_SCALE_SIZE - 1)
 
+#define KASAN_TAG_KERNEL       0xFF /* native kernel pointers tag */
+#define KASAN_TAG_INVALID      0xFE /* inaccessible memory tag */
+#define KASAN_TAG_MAX          0xFD /* maximum value for random tags */
+
+#ifdef CONFIG_KASAN_GENERIC
 #define KASAN_FREE_PAGE         0xFF  /* page was freed */
 #define KASAN_PAGE_REDZONE      0xFE  /* redzone for kmalloc_large allocations */
 #define KASAN_KMALLOC_REDZONE   0xFC  /* redzone inside slub object */
 #define KASAN_KMALLOC_FREE      0xFB  /* object was freed (kmem_cache_free/kfree) */
+#else
+#define KASAN_FREE_PAGE         KASAN_TAG_INVALID
+#define KASAN_PAGE_REDZONE      KASAN_TAG_INVALID
+#define KASAN_KMALLOC_REDZONE   KASAN_TAG_INVALID
+#define KASAN_KMALLOC_FREE      KASAN_TAG_INVALID
+#endif
+
 #define KASAN_GLOBAL_REDZONE    0xFA  /* redzone for global variable */
 
 /*
@@ -105,11 +117,25 @@ static inline const void *kasan_shadow_to_mem(const void *shadow_addr)
                << KASAN_SHADOW_SCALE_SHIFT);
 }
 
+static inline bool addr_has_shadow(const void *addr)
+{
+       return (addr >= kasan_shadow_to_mem((void *)KASAN_SHADOW_START));
+}
+
+void kasan_poison_shadow(const void *address, size_t size, u8 value);
+
+void check_memory_region(unsigned long addr, size_t size, bool write,
+                               unsigned long ret_ip);
+
+void *find_first_bad_addr(void *addr, size_t size);
+const char *get_bug_type(struct kasan_access_info *info);
+
 void kasan_report(unsigned long addr, size_t size,
                bool is_write, unsigned long ip);
 void kasan_report_invalid_free(void *object, unsigned long ip);
 
-#if defined(CONFIG_SLAB) || defined(CONFIG_SLUB)
+#if defined(CONFIG_KASAN_GENERIC) && \
+       (defined(CONFIG_SLAB) || defined(CONFIG_SLUB))
 void quarantine_put(struct kasan_free_meta *info, struct kmem_cache *cache);
 void quarantine_reduce(void);
 void quarantine_remove_cache(struct kmem_cache *cache);
@@ -120,6 +146,37 @@ static inline void quarantine_reduce(void) { }
 static inline void quarantine_remove_cache(struct kmem_cache *cache) { }
 #endif
 
+#ifdef CONFIG_KASAN_SW_TAGS
+
+void print_tags(u8 addr_tag, const void *addr);
+
+u8 random_tag(void);
+
+#else
+
+static inline void print_tags(u8 addr_tag, const void *addr) { }
+
+static inline u8 random_tag(void)
+{
+       return 0;
+}
+
+#endif
+
+#ifndef arch_kasan_set_tag
+#define arch_kasan_set_tag(addr, tag)  ((void *)(addr))
+#endif
+#ifndef arch_kasan_reset_tag
+#define arch_kasan_reset_tag(addr)     ((void *)(addr))
+#endif
+#ifndef arch_kasan_get_tag
+#define arch_kasan_get_tag(addr)       0
+#endif
+
+#define set_tag(addr, tag)     ((void *)arch_kasan_set_tag((addr), (tag)))
+#define reset_tag(addr)                ((void *)arch_kasan_reset_tag(addr))
+#define get_tag(addr)          arch_kasan_get_tag(addr)
+
 /*
  * Exported functions for interfaces called from assembly or from generated
  * code. Declarations here to avoid warning about missing declarations.
diff --git a/mm/kasan/kasan_init.c b/mm/kasan/kasan_init.c
deleted file mode 100644 (file)
index c7550eb..0000000
+++ /dev/null
@@ -1,488 +0,0 @@
-/*
- * This file contains some kasan initialization code.
- *
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
- * Author: Andrey Ryabinin <ryabinin.a.a@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-
-#include <linux/memblock.h>
-#include <linux/init.h>
-#include <linux/kasan.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/pfn.h>
-#include <linux/slab.h>
-
-#include <asm/page.h>
-#include <asm/pgalloc.h>
-
-#include "kasan.h"
-
-/*
- * This page serves two purposes:
- *   - It used as early shadow memory. The entire shadow region populated
- *     with this page, before we will be able to setup normal shadow memory.
- *   - Latter it reused it as zero shadow to cover large ranges of memory
- *     that allowed to access, but not handled by kasan (vmalloc/vmemmap ...).
- */
-unsigned char kasan_zero_page[PAGE_SIZE] __page_aligned_bss;
-
-#if CONFIG_PGTABLE_LEVELS > 4
-p4d_t kasan_zero_p4d[MAX_PTRS_PER_P4D] __page_aligned_bss;
-static inline bool kasan_p4d_table(pgd_t pgd)
-{
-       return pgd_page(pgd) == virt_to_page(lm_alias(kasan_zero_p4d));
-}
-#else
-static inline bool kasan_p4d_table(pgd_t pgd)
-{
-       return 0;
-}
-#endif
-#if CONFIG_PGTABLE_LEVELS > 3
-pud_t kasan_zero_pud[PTRS_PER_PUD] __page_aligned_bss;
-static inline bool kasan_pud_table(p4d_t p4d)
-{
-       return p4d_page(p4d) == virt_to_page(lm_alias(kasan_zero_pud));
-}
-#else
-static inline bool kasan_pud_table(p4d_t p4d)
-{
-       return 0;
-}
-#endif
-#if CONFIG_PGTABLE_LEVELS > 2
-pmd_t kasan_zero_pmd[PTRS_PER_PMD] __page_aligned_bss;
-static inline bool kasan_pmd_table(pud_t pud)
-{
-       return pud_page(pud) == virt_to_page(lm_alias(kasan_zero_pmd));
-}
-#else
-static inline bool kasan_pmd_table(pud_t pud)
-{
-       return 0;
-}
-#endif
-pte_t kasan_zero_pte[PTRS_PER_PTE] __page_aligned_bss;
-
-static inline bool kasan_pte_table(pmd_t pmd)
-{
-       return pmd_page(pmd) == virt_to_page(lm_alias(kasan_zero_pte));
-}
-
-static inline bool kasan_zero_page_entry(pte_t pte)
-{
-       return pte_page(pte) == virt_to_page(lm_alias(kasan_zero_page));
-}
-
-static __init void *early_alloc(size_t size, int node)
-{
-       return memblock_alloc_try_nid(size, size, __pa(MAX_DMA_ADDRESS),
-                                       MEMBLOCK_ALLOC_ACCESSIBLE, node);
-}
-
-static void __ref zero_pte_populate(pmd_t *pmd, unsigned long addr,
-                               unsigned long end)
-{
-       pte_t *pte = pte_offset_kernel(pmd, addr);
-       pte_t zero_pte;
-
-       zero_pte = pfn_pte(PFN_DOWN(__pa_symbol(kasan_zero_page)), PAGE_KERNEL);
-       zero_pte = pte_wrprotect(zero_pte);
-
-       while (addr + PAGE_SIZE <= end) {
-               set_pte_at(&init_mm, addr, pte, zero_pte);
-               addr += PAGE_SIZE;
-               pte = pte_offset_kernel(pmd, addr);
-       }
-}
-
-static int __ref zero_pmd_populate(pud_t *pud, unsigned long addr,
-                               unsigned long end)
-{
-       pmd_t *pmd = pmd_offset(pud, addr);
-       unsigned long next;
-
-       do {
-               next = pmd_addr_end(addr, end);
-
-               if (IS_ALIGNED(addr, PMD_SIZE) && end - addr >= PMD_SIZE) {
-                       pmd_populate_kernel(&init_mm, pmd, lm_alias(kasan_zero_pte));
-                       continue;
-               }
-
-               if (pmd_none(*pmd)) {
-                       pte_t *p;
-
-                       if (slab_is_available())
-                               p = pte_alloc_one_kernel(&init_mm, addr);
-                       else
-                               p = early_alloc(PAGE_SIZE, NUMA_NO_NODE);
-                       if (!p)
-                               return -ENOMEM;
-
-                       pmd_populate_kernel(&init_mm, pmd, p);
-               }
-               zero_pte_populate(pmd, addr, next);
-       } while (pmd++, addr = next, addr != end);
-
-       return 0;
-}
-
-static int __ref zero_pud_populate(p4d_t *p4d, unsigned long addr,
-                               unsigned long end)
-{
-       pud_t *pud = pud_offset(p4d, addr);
-       unsigned long next;
-
-       do {
-               next = pud_addr_end(addr, end);
-               if (IS_ALIGNED(addr, PUD_SIZE) && end - addr >= PUD_SIZE) {
-                       pmd_t *pmd;
-
-                       pud_populate(&init_mm, pud, lm_alias(kasan_zero_pmd));
-                       pmd = pmd_offset(pud, addr);
-                       pmd_populate_kernel(&init_mm, pmd, lm_alias(kasan_zero_pte));
-                       continue;
-               }
-
-               if (pud_none(*pud)) {
-                       pmd_t *p;
-
-                       if (slab_is_available()) {
-                               p = pmd_alloc(&init_mm, pud, addr);
-                               if (!p)
-                                       return -ENOMEM;
-                       } else {
-                               pud_populate(&init_mm, pud,
-                                       early_alloc(PAGE_SIZE, NUMA_NO_NODE));
-                       }
-               }
-               zero_pmd_populate(pud, addr, next);
-       } while (pud++, addr = next, addr != end);
-
-       return 0;
-}
-
-static int __ref zero_p4d_populate(pgd_t *pgd, unsigned long addr,
-                               unsigned long end)
-{
-       p4d_t *p4d = p4d_offset(pgd, addr);
-       unsigned long next;
-
-       do {
-               next = p4d_addr_end(addr, end);
-               if (IS_ALIGNED(addr, P4D_SIZE) && end - addr >= P4D_SIZE) {
-                       pud_t *pud;
-                       pmd_t *pmd;
-
-                       p4d_populate(&init_mm, p4d, lm_alias(kasan_zero_pud));
-                       pud = pud_offset(p4d, addr);
-                       pud_populate(&init_mm, pud, lm_alias(kasan_zero_pmd));
-                       pmd = pmd_offset(pud, addr);
-                       pmd_populate_kernel(&init_mm, pmd,
-                                               lm_alias(kasan_zero_pte));
-                       continue;
-               }
-
-               if (p4d_none(*p4d)) {
-                       pud_t *p;
-
-                       if (slab_is_available()) {
-                               p = pud_alloc(&init_mm, p4d, addr);
-                               if (!p)
-                                       return -ENOMEM;
-                       } else {
-                               p4d_populate(&init_mm, p4d,
-                                       early_alloc(PAGE_SIZE, NUMA_NO_NODE));
-                       }
-               }
-               zero_pud_populate(p4d, addr, next);
-       } while (p4d++, addr = next, addr != end);
-
-       return 0;
-}
-
-/**
- * kasan_populate_zero_shadow - populate shadow memory region with
- *                               kasan_zero_page
- * @shadow_start - start of the memory range to populate
- * @shadow_end   - end of the memory range to populate
- */
-int __ref kasan_populate_zero_shadow(const void *shadow_start,
-                               const void *shadow_end)
-{
-       unsigned long addr = (unsigned long)shadow_start;
-       unsigned long end = (unsigned long)shadow_end;
-       pgd_t *pgd = pgd_offset_k(addr);
-       unsigned long next;
-
-       do {
-               next = pgd_addr_end(addr, end);
-
-               if (IS_ALIGNED(addr, PGDIR_SIZE) && end - addr >= PGDIR_SIZE) {
-                       p4d_t *p4d;
-                       pud_t *pud;
-                       pmd_t *pmd;
-
-                       /*
-                        * kasan_zero_pud should be populated with pmds
-                        * at this moment.
-                        * [pud,pmd]_populate*() below needed only for
-                        * 3,2 - level page tables where we don't have
-                        * puds,pmds, so pgd_populate(), pud_populate()
-                        * is noops.
-                        *
-                        * The ifndef is required to avoid build breakage.
-                        *
-                        * With 5level-fixup.h, pgd_populate() is not nop and
-                        * we reference kasan_zero_p4d. It's not defined
-                        * unless 5-level paging enabled.
-                        *
-                        * The ifndef can be dropped once all KASAN-enabled
-                        * architectures will switch to pgtable-nop4d.h.
-                        */
-#ifndef __ARCH_HAS_5LEVEL_HACK
-                       pgd_populate(&init_mm, pgd, lm_alias(kasan_zero_p4d));
-#endif
-                       p4d = p4d_offset(pgd, addr);
-                       p4d_populate(&init_mm, p4d, lm_alias(kasan_zero_pud));
-                       pud = pud_offset(p4d, addr);
-                       pud_populate(&init_mm, pud, lm_alias(kasan_zero_pmd));
-                       pmd = pmd_offset(pud, addr);
-                       pmd_populate_kernel(&init_mm, pmd, lm_alias(kasan_zero_pte));
-                       continue;
-               }
-
-               if (pgd_none(*pgd)) {
-                       p4d_t *p;
-
-                       if (slab_is_available()) {
-                               p = p4d_alloc(&init_mm, pgd, addr);
-                               if (!p)
-                                       return -ENOMEM;
-                       } else {
-                               pgd_populate(&init_mm, pgd,
-                                       early_alloc(PAGE_SIZE, NUMA_NO_NODE));
-                       }
-               }
-               zero_p4d_populate(pgd, addr, next);
-       } while (pgd++, addr = next, addr != end);
-
-       return 0;
-}
-
-static void kasan_free_pte(pte_t *pte_start, pmd_t *pmd)
-{
-       pte_t *pte;
-       int i;
-
-       for (i = 0; i < PTRS_PER_PTE; i++) {
-               pte = pte_start + i;
-               if (!pte_none(*pte))
-                       return;
-       }
-
-       pte_free_kernel(&init_mm, (pte_t *)page_to_virt(pmd_page(*pmd)));
-       pmd_clear(pmd);
-}
-
-static void kasan_free_pmd(pmd_t *pmd_start, pud_t *pud)
-{
-       pmd_t *pmd;
-       int i;
-
-       for (i = 0; i < PTRS_PER_PMD; i++) {
-               pmd = pmd_start + i;
-               if (!pmd_none(*pmd))
-                       return;
-       }
-
-       pmd_free(&init_mm, (pmd_t *)page_to_virt(pud_page(*pud)));
-       pud_clear(pud);
-}
-
-static void kasan_free_pud(pud_t *pud_start, p4d_t *p4d)
-{
-       pud_t *pud;
-       int i;
-
-       for (i = 0; i < PTRS_PER_PUD; i++) {
-               pud = pud_start + i;
-               if (!pud_none(*pud))
-                       return;
-       }
-
-       pud_free(&init_mm, (pud_t *)page_to_virt(p4d_page(*p4d)));
-       p4d_clear(p4d);
-}
-
-static void kasan_free_p4d(p4d_t *p4d_start, pgd_t *pgd)
-{
-       p4d_t *p4d;
-       int i;
-
-       for (i = 0; i < PTRS_PER_P4D; i++) {
-               p4d = p4d_start + i;
-               if (!p4d_none(*p4d))
-                       return;
-       }
-
-       p4d_free(&init_mm, (p4d_t *)page_to_virt(pgd_page(*pgd)));
-       pgd_clear(pgd);
-}
-
-static void kasan_remove_pte_table(pte_t *pte, unsigned long addr,
-                               unsigned long end)
-{
-       unsigned long next;
-
-       for (; addr < end; addr = next, pte++) {
-               next = (addr + PAGE_SIZE) & PAGE_MASK;
-               if (next > end)
-                       next = end;
-
-               if (!pte_present(*pte))
-                       continue;
-
-               if (WARN_ON(!kasan_zero_page_entry(*pte)))
-                       continue;
-               pte_clear(&init_mm, addr, pte);
-       }
-}
-
-static void kasan_remove_pmd_table(pmd_t *pmd, unsigned long addr,
-                               unsigned long end)
-{
-       unsigned long next;
-
-       for (; addr < end; addr = next, pmd++) {
-               pte_t *pte;
-
-               next = pmd_addr_end(addr, end);
-
-               if (!pmd_present(*pmd))
-                       continue;
-
-               if (kasan_pte_table(*pmd)) {
-                       if (IS_ALIGNED(addr, PMD_SIZE) &&
-                           IS_ALIGNED(next, PMD_SIZE))
-                               pmd_clear(pmd);
-                       continue;
-               }
-               pte = pte_offset_kernel(pmd, addr);
-               kasan_remove_pte_table(pte, addr, next);
-               kasan_free_pte(pte_offset_kernel(pmd, 0), pmd);
-       }
-}
-
-static void kasan_remove_pud_table(pud_t *pud, unsigned long addr,
-                               unsigned long end)
-{
-       unsigned long next;
-
-       for (; addr < end; addr = next, pud++) {
-               pmd_t *pmd, *pmd_base;
-
-               next = pud_addr_end(addr, end);
-
-               if (!pud_present(*pud))
-                       continue;
-
-               if (kasan_pmd_table(*pud)) {
-                       if (IS_ALIGNED(addr, PUD_SIZE) &&
-                           IS_ALIGNED(next, PUD_SIZE))
-                               pud_clear(pud);
-                       continue;
-               }
-               pmd = pmd_offset(pud, addr);
-               pmd_base = pmd_offset(pud, 0);
-               kasan_remove_pmd_table(pmd, addr, next);
-               kasan_free_pmd(pmd_base, pud);
-       }
-}
-
-static void kasan_remove_p4d_table(p4d_t *p4d, unsigned long addr,
-                               unsigned long end)
-{
-       unsigned long next;
-
-       for (; addr < end; addr = next, p4d++) {
-               pud_t *pud;
-
-               next = p4d_addr_end(addr, end);
-
-               if (!p4d_present(*p4d))
-                       continue;
-
-               if (kasan_pud_table(*p4d)) {
-                       if (IS_ALIGNED(addr, P4D_SIZE) &&
-                           IS_ALIGNED(next, P4D_SIZE))
-                               p4d_clear(p4d);
-                       continue;
-               }
-               pud = pud_offset(p4d, addr);
-               kasan_remove_pud_table(pud, addr, next);
-               kasan_free_pud(pud_offset(p4d, 0), p4d);
-       }
-}
-
-void kasan_remove_zero_shadow(void *start, unsigned long size)
-{
-       unsigned long addr, end, next;
-       pgd_t *pgd;
-
-       addr = (unsigned long)kasan_mem_to_shadow(start);
-       end = addr + (size >> KASAN_SHADOW_SCALE_SHIFT);
-
-       if (WARN_ON((unsigned long)start %
-                       (KASAN_SHADOW_SCALE_SIZE * PAGE_SIZE)) ||
-           WARN_ON(size % (KASAN_SHADOW_SCALE_SIZE * PAGE_SIZE)))
-               return;
-
-       for (; addr < end; addr = next) {
-               p4d_t *p4d;
-
-               next = pgd_addr_end(addr, end);
-
-               pgd = pgd_offset_k(addr);
-               if (!pgd_present(*pgd))
-                       continue;
-
-               if (kasan_p4d_table(*pgd)) {
-                       if (IS_ALIGNED(addr, PGDIR_SIZE) &&
-                           IS_ALIGNED(next, PGDIR_SIZE))
-                               pgd_clear(pgd);
-                       continue;
-               }
-
-               p4d = p4d_offset(pgd, addr);
-               kasan_remove_p4d_table(p4d, addr, next);
-               kasan_free_p4d(p4d_offset(pgd, 0), pgd);
-       }
-}
-
-int kasan_add_zero_shadow(void *start, unsigned long size)
-{
-       int ret;
-       void *shadow_start, *shadow_end;
-
-       shadow_start = kasan_mem_to_shadow(start);
-       shadow_end = shadow_start + (size >> KASAN_SHADOW_SCALE_SHIFT);
-
-       if (WARN_ON((unsigned long)start %
-                       (KASAN_SHADOW_SCALE_SIZE * PAGE_SIZE)) ||
-           WARN_ON(size % (KASAN_SHADOW_SCALE_SIZE * PAGE_SIZE)))
-               return -EINVAL;
-
-       ret = kasan_populate_zero_shadow(shadow_start, shadow_end);
-       if (ret)
-               kasan_remove_zero_shadow(shadow_start,
-                                       size >> KASAN_SHADOW_SCALE_SHIFT);
-       return ret;
-}
index b209dbaefde822315201ab409dce65ca52b371eb..978bc4a3eb51a8d2db006e52a97b52de400bc8b1 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * KASAN quarantine.
  *
@@ -236,7 +237,7 @@ void quarantine_reduce(void)
         * Update quarantine size in case of hotplug. Allocate a fraction of
         * the installed memory to quarantine minus per-cpu queue limits.
         */
-       total_size = (READ_ONCE(totalram_pages) << PAGE_SHIFT) /
+       total_size = (totalram_pages() << PAGE_SHIFT) /
                QUARANTINE_FRACTION;
        percpu_quarantines = QUARANTINE_PERCPU_SIZE * num_online_cpus();
        new_quarantine_size = (total_size < percpu_quarantines) ?
index 5c169aa688fde8b189b092dfc724b9a0d6c88cdd..ca9418fe9232a115d42af35af0a027598a375a13 100644 (file)
@@ -1,5 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
- * This file contains error reporting code.
+ * This file contains common generic and tag-based KASAN error reporting code.
  *
  * Copyright (c) 2014 Samsung Electronics Co., Ltd.
  * Author: Andrey Ryabinin <ryabinin.a.a@gmail.com>
 #define SHADOW_BYTES_PER_ROW (SHADOW_BLOCKS_PER_ROW * SHADOW_BYTES_PER_BLOCK)
 #define SHADOW_ROWS_AROUND_ADDR 2
 
-static const void *find_first_bad_addr(const void *addr, size_t size)
-{
-       u8 shadow_val = *(u8 *)kasan_mem_to_shadow(addr);
-       const void *first_bad_addr = addr;
-
-       while (!shadow_val && first_bad_addr < addr + size) {
-               first_bad_addr += KASAN_SHADOW_SCALE_SIZE;
-               shadow_val = *(u8 *)kasan_mem_to_shadow(first_bad_addr);
-       }
-       return first_bad_addr;
-}
+static unsigned long kasan_flags;
 
-static bool addr_has_shadow(struct kasan_access_info *info)
-{
-       return (info->access_addr >=
-               kasan_shadow_to_mem((void *)KASAN_SHADOW_START));
-}
+#define KASAN_BIT_REPORTED     0
+#define KASAN_BIT_MULTI_SHOT   1
 
-static const char *get_shadow_bug_type(struct kasan_access_info *info)
+bool kasan_save_enable_multi_shot(void)
 {
-       const char *bug_type = "unknown-crash";
-       u8 *shadow_addr;
-
-       info->first_bad_addr = find_first_bad_addr(info->access_addr,
-                                               info->access_size);
-
-       shadow_addr = (u8 *)kasan_mem_to_shadow(info->first_bad_addr);
-
-       /*
-        * If shadow byte value is in [0, KASAN_SHADOW_SCALE_SIZE) we can look
-        * at the next shadow byte to determine the type of the bad access.
-        */
-       if (*shadow_addr > 0 && *shadow_addr <= KASAN_SHADOW_SCALE_SIZE - 1)
-               shadow_addr++;
-
-       switch (*shadow_addr) {
-       case 0 ... KASAN_SHADOW_SCALE_SIZE - 1:
-               /*
-                * In theory it's still possible to see these shadow values
-                * due to a data race in the kernel code.
-                */
-               bug_type = "out-of-bounds";
-               break;
-       case KASAN_PAGE_REDZONE:
-       case KASAN_KMALLOC_REDZONE:
-               bug_type = "slab-out-of-bounds";
-               break;
-       case KASAN_GLOBAL_REDZONE:
-               bug_type = "global-out-of-bounds";
-               break;
-       case KASAN_STACK_LEFT:
-       case KASAN_STACK_MID:
-       case KASAN_STACK_RIGHT:
-       case KASAN_STACK_PARTIAL:
-               bug_type = "stack-out-of-bounds";
-               break;
-       case KASAN_FREE_PAGE:
-       case KASAN_KMALLOC_FREE:
-               bug_type = "use-after-free";
-               break;
-       case KASAN_USE_AFTER_SCOPE:
-               bug_type = "use-after-scope";
-               break;
-       case KASAN_ALLOCA_LEFT:
-       case KASAN_ALLOCA_RIGHT:
-               bug_type = "alloca-out-of-bounds";
-               break;
-       }
-
-       return bug_type;
+       return test_and_set_bit(KASAN_BIT_MULTI_SHOT, &kasan_flags);
 }
+EXPORT_SYMBOL_GPL(kasan_save_enable_multi_shot);
 
-static const char *get_wild_bug_type(struct kasan_access_info *info)
+void kasan_restore_multi_shot(bool enabled)
 {
-       const char *bug_type = "unknown-crash";
-
-       if ((unsigned long)info->access_addr < PAGE_SIZE)
-               bug_type = "null-ptr-deref";
-       else if ((unsigned long)info->access_addr < TASK_SIZE)
-               bug_type = "user-memory-access";
-       else
-               bug_type = "wild-memory-access";
-
-       return bug_type;
+       if (!enabled)
+               clear_bit(KASAN_BIT_MULTI_SHOT, &kasan_flags);
 }
+EXPORT_SYMBOL_GPL(kasan_restore_multi_shot);
 
-static const char *get_bug_type(struct kasan_access_info *info)
+static int __init kasan_set_multi_shot(char *str)
 {
-       if (addr_has_shadow(info))
-               return get_shadow_bug_type(info);
-       return get_wild_bug_type(info);
+       set_bit(KASAN_BIT_MULTI_SHOT, &kasan_flags);
+       return 1;
 }
+__setup("kasan_multi_shot", kasan_set_multi_shot);
 
 static void print_error_description(struct kasan_access_info *info)
 {
-       const char *bug_type = get_bug_type(info);
-
        pr_err("BUG: KASAN: %s in %pS\n",
-               bug_type, (void *)info->ip);
+               get_bug_type(info), (void *)info->ip);
        pr_err("%s of size %zu at addr %px by task %s/%d\n",
                info->is_write ? "Write" : "Read", info->access_size,
                info->access_addr, current->comm, task_pid_nr(current));
 }
 
-static inline bool kernel_or_module_addr(const void *addr)
-{
-       if (addr >= (void *)_stext && addr < (void *)_end)
-               return true;
-       if (is_module_address((unsigned long)addr))
-               return true;
-       return false;
-}
-
-static inline bool init_task_stack_addr(const void *addr)
-{
-       return addr >= (void *)&init_thread_union.stack &&
-               (addr <= (void *)&init_thread_union.stack +
-                       sizeof(init_thread_union.stack));
-}
-
 static DEFINE_SPINLOCK(report_lock);
 
-static void kasan_start_report(unsigned long *flags)
+static void start_report(unsigned long *flags)
 {
        /*
         * Make sure we don't end up in loop.
@@ -171,7 +86,7 @@ static void kasan_start_report(unsigned long *flags)
        pr_err("==================================================================\n");
 }
 
-static void kasan_end_report(unsigned long *flags)
+static void end_report(unsigned long *flags)
 {
        pr_err("==================================================================\n");
        add_taint(TAINT_BAD_PAGE, LOCKDEP_NOW_UNRELIABLE);
@@ -249,6 +164,22 @@ static void describe_object(struct kmem_cache *cache, void *object,
        describe_object_addr(cache, object, addr);
 }
 
+static inline bool kernel_or_module_addr(const void *addr)
+{
+       if (addr >= (void *)_stext && addr < (void *)_end)
+               return true;
+       if (is_module_address((unsigned long)addr))
+               return true;
+       return false;
+}
+
+static inline bool init_task_stack_addr(const void *addr)
+{
+       return addr >= (void *)&init_thread_union.stack &&
+               (addr <= (void *)&init_thread_union.stack +
+                       sizeof(init_thread_union.stack));
+}
+
 static void print_address_description(void *addr)
 {
        struct page *page = addr_to_page(addr);
@@ -326,126 +257,69 @@ static void print_shadow_for_address(const void *addr)
        }
 }
 
+static bool report_enabled(void)
+{
+       if (current->kasan_depth)
+               return false;
+       if (test_bit(KASAN_BIT_MULTI_SHOT, &kasan_flags))
+               return true;
+       return !test_and_set_bit(KASAN_BIT_REPORTED, &kasan_flags);
+}
+
 void kasan_report_invalid_free(void *object, unsigned long ip)
 {
        unsigned long flags;
 
-       kasan_start_report(&flags);
+       start_report(&flags);
        pr_err("BUG: KASAN: double-free or invalid-free in %pS\n", (void *)ip);
+       print_tags(get_tag(object), reset_tag(object));
+       object = reset_tag(object);
        pr_err("\n");
        print_address_description(object);
        pr_err("\n");
        print_shadow_for_address(object);
-       kasan_end_report(&flags);
-}
-
-static void kasan_report_error(struct kasan_access_info *info)
-{
-       unsigned long flags;
-
-       kasan_start_report(&flags);
-
-       print_error_description(info);
-       pr_err("\n");
-
-       if (!addr_has_shadow(info)) {
-               dump_stack();
-       } else {
-               print_address_description((void *)info->access_addr);
-               pr_err("\n");
-               print_shadow_for_address(info->first_bad_addr);
-       }
-
-       kasan_end_report(&flags);
-}
-
-static unsigned long kasan_flags;
-
-#define KASAN_BIT_REPORTED     0
-#define KASAN_BIT_MULTI_SHOT   1
-
-bool kasan_save_enable_multi_shot(void)
-{
-       return test_and_set_bit(KASAN_BIT_MULTI_SHOT, &kasan_flags);
-}
-EXPORT_SYMBOL_GPL(kasan_save_enable_multi_shot);
-
-void kasan_restore_multi_shot(bool enabled)
-{
-       if (!enabled)
-               clear_bit(KASAN_BIT_MULTI_SHOT, &kasan_flags);
-}
-EXPORT_SYMBOL_GPL(kasan_restore_multi_shot);
-
-static int __init kasan_set_multi_shot(char *str)
-{
-       set_bit(KASAN_BIT_MULTI_SHOT, &kasan_flags);
-       return 1;
-}
-__setup("kasan_multi_shot", kasan_set_multi_shot);
-
-static inline bool kasan_report_enabled(void)
-{
-       if (current->kasan_depth)
-               return false;
-       if (test_bit(KASAN_BIT_MULTI_SHOT, &kasan_flags))
-               return true;
-       return !test_and_set_bit(KASAN_BIT_REPORTED, &kasan_flags);
+       end_report(&flags);
 }
 
 void kasan_report(unsigned long addr, size_t size,
                bool is_write, unsigned long ip)
 {
        struct kasan_access_info info;
+       void *tagged_addr;
+       void *untagged_addr;
+       unsigned long flags;
 
-       if (likely(!kasan_report_enabled()))
+       if (likely(!report_enabled()))
                return;
 
        disable_trace_on_warning();
 
-       info.access_addr = (void *)addr;
-       info.first_bad_addr = (void *)addr;
+       tagged_addr = (void *)addr;
+       untagged_addr = reset_tag(tagged_addr);
+
+       info.access_addr = tagged_addr;
+       if (addr_has_shadow(untagged_addr))
+               info.first_bad_addr = find_first_bad_addr(tagged_addr, size);
+       else
+               info.first_bad_addr = untagged_addr;
        info.access_size = size;
        info.is_write = is_write;
        info.ip = ip;
 
-       kasan_report_error(&info);
-}
+       start_report(&flags);
 
+       print_error_description(&info);
+       if (addr_has_shadow(untagged_addr))
+               print_tags(get_tag(tagged_addr), info.first_bad_addr);
+       pr_err("\n");
 
-#define DEFINE_ASAN_REPORT_LOAD(size)                     \
-void __asan_report_load##size##_noabort(unsigned long addr) \
-{                                                         \
-       kasan_report(addr, size, false, _RET_IP_);        \
-}                                                         \
-EXPORT_SYMBOL(__asan_report_load##size##_noabort)
-
-#define DEFINE_ASAN_REPORT_STORE(size)                     \
-void __asan_report_store##size##_noabort(unsigned long addr) \
-{                                                          \
-       kasan_report(addr, size, true, _RET_IP_);          \
-}                                                          \
-EXPORT_SYMBOL(__asan_report_store##size##_noabort)
-
-DEFINE_ASAN_REPORT_LOAD(1);
-DEFINE_ASAN_REPORT_LOAD(2);
-DEFINE_ASAN_REPORT_LOAD(4);
-DEFINE_ASAN_REPORT_LOAD(8);
-DEFINE_ASAN_REPORT_LOAD(16);
-DEFINE_ASAN_REPORT_STORE(1);
-DEFINE_ASAN_REPORT_STORE(2);
-DEFINE_ASAN_REPORT_STORE(4);
-DEFINE_ASAN_REPORT_STORE(8);
-DEFINE_ASAN_REPORT_STORE(16);
-
-void __asan_report_load_n_noabort(unsigned long addr, size_t size)
-{
-       kasan_report(addr, size, false, _RET_IP_);
-}
-EXPORT_SYMBOL(__asan_report_load_n_noabort);
+       if (addr_has_shadow(untagged_addr)) {
+               print_address_description(untagged_addr);
+               pr_err("\n");
+               print_shadow_for_address(info.first_bad_addr);
+       } else {
+               dump_stack();
+       }
 
-void __asan_report_store_n_noabort(unsigned long addr, size_t size)
-{
-       kasan_report(addr, size, true, _RET_IP_);
+       end_report(&flags);
 }
-EXPORT_SYMBOL(__asan_report_store_n_noabort);
diff --git a/mm/kasan/tags.c b/mm/kasan/tags.c
new file mode 100644 (file)
index 0000000..0777649
--- /dev/null
@@ -0,0 +1,161 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * This file contains core tag-based KASAN code.
+ *
+ * Copyright (c) 2018 Google, Inc.
+ * Author: Andrey Konovalov <andreyknvl@google.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#define DISABLE_BRANCH_PROFILING
+
+#include <linux/export.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/kasan.h>
+#include <linux/kernel.h>
+#include <linux/kmemleak.h>
+#include <linux/linkage.h>
+#include <linux/memblock.h>
+#include <linux/memory.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/printk.h>
+#include <linux/random.h>
+#include <linux/sched.h>
+#include <linux/sched/task_stack.h>
+#include <linux/slab.h>
+#include <linux/stacktrace.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/vmalloc.h>
+#include <linux/bug.h>
+
+#include "kasan.h"
+#include "../slab.h"
+
+static DEFINE_PER_CPU(u32, prng_state);
+
+void kasan_init_tags(void)
+{
+       int cpu;
+
+       for_each_possible_cpu(cpu)
+               per_cpu(prng_state, cpu) = get_random_u32();
+}
+
+/*
+ * If a preemption happens between this_cpu_read and this_cpu_write, the only
+ * side effect is that we'll give a few allocated in different contexts objects
+ * the same tag. Since tag-based KASAN is meant to be used a probabilistic
+ * bug-detection debug feature, this doesn't have significant negative impact.
+ *
+ * Ideally the tags use strong randomness to prevent any attempts to predict
+ * them during explicit exploit attempts. But strong randomness is expensive,
+ * and we did an intentional trade-off to use a PRNG. This non-atomic RMW
+ * sequence has in fact positive effect, since interrupts that randomly skew
+ * PRNG at unpredictable points do only good.
+ */
+u8 random_tag(void)
+{
+       u32 state = this_cpu_read(prng_state);
+
+       state = 1664525 * state + 1013904223;
+       this_cpu_write(prng_state, state);
+
+       return (u8)(state % (KASAN_TAG_MAX + 1));
+}
+
+void *kasan_reset_tag(const void *addr)
+{
+       return reset_tag(addr);
+}
+
+void check_memory_region(unsigned long addr, size_t size, bool write,
+                               unsigned long ret_ip)
+{
+       u8 tag;
+       u8 *shadow_first, *shadow_last, *shadow;
+       void *untagged_addr;
+
+       if (unlikely(size == 0))
+               return;
+
+       tag = get_tag((const void *)addr);
+
+       /*
+        * Ignore accesses for pointers tagged with 0xff (native kernel
+        * pointer tag) to suppress false positives caused by kmap.
+        *
+        * Some kernel code was written to account for archs that don't keep
+        * high memory mapped all the time, but rather map and unmap particular
+        * pages when needed. Instead of storing a pointer to the kernel memory,
+        * this code saves the address of the page structure and offset within
+        * that page for later use. Those pages are then mapped and unmapped
+        * with kmap/kunmap when necessary and virt_to_page is used to get the
+        * virtual address of the page. For arm64 (that keeps the high memory
+        * mapped all the time), kmap is turned into a page_address call.
+
+        * The issue is that with use of the page_address + virt_to_page
+        * sequence the top byte value of the original pointer gets lost (gets
+        * set to KASAN_TAG_KERNEL (0xFF)).
+        */
+       if (tag == KASAN_TAG_KERNEL)
+               return;
+
+       untagged_addr = reset_tag((const void *)addr);
+       if (unlikely(untagged_addr <
+                       kasan_shadow_to_mem((void *)KASAN_SHADOW_START))) {
+               kasan_report(addr, size, write, ret_ip);
+               return;
+       }
+       shadow_first = kasan_mem_to_shadow(untagged_addr);
+       shadow_last = kasan_mem_to_shadow(untagged_addr + size - 1);
+       for (shadow = shadow_first; shadow <= shadow_last; shadow++) {
+               if (*shadow != tag) {
+                       kasan_report(addr, size, write, ret_ip);
+                       return;
+               }
+       }
+}
+
+#define DEFINE_HWASAN_LOAD_STORE(size)                                 \
+       void __hwasan_load##size##_noabort(unsigned long addr)          \
+       {                                                               \
+               check_memory_region(addr, size, false, _RET_IP_);       \
+       }                                                               \
+       EXPORT_SYMBOL(__hwasan_load##size##_noabort);                   \
+       void __hwasan_store##size##_noabort(unsigned long addr)         \
+       {                                                               \
+               check_memory_region(addr, size, true, _RET_IP_);        \
+       }                                                               \
+       EXPORT_SYMBOL(__hwasan_store##size##_noabort)
+
+DEFINE_HWASAN_LOAD_STORE(1);
+DEFINE_HWASAN_LOAD_STORE(2);
+DEFINE_HWASAN_LOAD_STORE(4);
+DEFINE_HWASAN_LOAD_STORE(8);
+DEFINE_HWASAN_LOAD_STORE(16);
+
+void __hwasan_loadN_noabort(unsigned long addr, unsigned long size)
+{
+       check_memory_region(addr, size, false, _RET_IP_);
+}
+EXPORT_SYMBOL(__hwasan_loadN_noabort);
+
+void __hwasan_storeN_noabort(unsigned long addr, unsigned long size)
+{
+       check_memory_region(addr, size, true, _RET_IP_);
+}
+EXPORT_SYMBOL(__hwasan_storeN_noabort);
+
+void __hwasan_tag_memory(unsigned long addr, u8 tag, unsigned long size)
+{
+       kasan_poison_shadow((void *)addr, size, tag);
+}
+EXPORT_SYMBOL(__hwasan_tag_memory);
diff --git a/mm/kasan/tags_report.c b/mm/kasan/tags_report.c
new file mode 100644 (file)
index 0000000..8eaf5f7
--- /dev/null
@@ -0,0 +1,58 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * This file contains tag-based KASAN specific error reporting code.
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * Author: Andrey Ryabinin <ryabinin.a.a@gmail.com>
+ *
+ * Some code borrowed from https://github.com/xairy/kasan-prototype by
+ *        Andrey Konovalov <andreyknvl@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/bitops.h>
+#include <linux/ftrace.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/printk.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/stackdepot.h>
+#include <linux/stacktrace.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/kasan.h>
+#include <linux/module.h>
+
+#include <asm/sections.h>
+
+#include "kasan.h"
+#include "../slab.h"
+
+const char *get_bug_type(struct kasan_access_info *info)
+{
+       return "invalid-access";
+}
+
+void *find_first_bad_addr(void *addr, size_t size)
+{
+       u8 tag = get_tag(addr);
+       void *p = reset_tag(addr);
+       void *end = p + size;
+
+       while (p < end && tag == *(u8 *)kasan_mem_to_shadow(p))
+               p += KASAN_SHADOW_SCALE_SIZE;
+       return p;
+}
+
+void print_tags(u8 addr_tag, const void *addr)
+{
+       u8 *shadow = (u8 *)kasan_mem_to_shadow(addr);
+
+       pr_err("Pointer tag: [%02x], memory tag: [%02x]\n", addr_tag, *shadow);
+}
index 43ce2f4d255128c4cbce5d9982034385877cac47..4f017339ddb29861c5bb04595592f56e5cbdcc06 100644 (file)
@@ -944,8 +944,7 @@ static void collapse_huge_page(struct mm_struct *mm,
        int isolated = 0, result = 0;
        struct mem_cgroup *memcg;
        struct vm_area_struct *vma;
-       unsigned long mmun_start;       /* For mmu_notifiers */
-       unsigned long mmun_end;         /* For mmu_notifiers */
+       struct mmu_notifier_range range;
        gfp_t gfp;
 
        VM_BUG_ON(address & ~HPAGE_PMD_MASK);
@@ -1017,9 +1016,8 @@ static void collapse_huge_page(struct mm_struct *mm,
        pte = pte_offset_map(pmd, address);
        pte_ptl = pte_lockptr(mm, pmd);
 
-       mmun_start = address;
-       mmun_end   = address + HPAGE_PMD_SIZE;
-       mmu_notifier_invalidate_range_start(mm, mmun_start, mmun_end);
+       mmu_notifier_range_init(&range, mm, address, address + HPAGE_PMD_SIZE);
+       mmu_notifier_invalidate_range_start(&range);
        pmd_ptl = pmd_lock(mm, pmd); /* probably unnecessary */
        /*
         * After this gup_fast can't run anymore. This also removes
@@ -1029,7 +1027,7 @@ static void collapse_huge_page(struct mm_struct *mm,
         */
        _pmd = pmdp_collapse_flush(vma, address, pmd);
        spin_unlock(pmd_ptl);
-       mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end);
+       mmu_notifier_invalidate_range_end(&range);
 
        spin_lock(pte_ptl);
        isolated = __collapse_huge_page_isolate(vma, address, pte);
index 877de4fa0720baea7252af98b1c03f718c33b118..f9d9dc250428142569672a5a5e7c56d8ff949e90 100644 (file)
@@ -1547,11 +1547,14 @@ static void kmemleak_scan(void)
                unsigned long pfn;
 
                for (pfn = start_pfn; pfn < end_pfn; pfn++) {
-                       struct page *page;
+                       struct page *page = pfn_to_online_page(pfn);
 
-                       if (!pfn_valid(pfn))
+                       if (!page)
+                               continue;
+
+                       /* only scan pages belonging to this node */
+                       if (page_to_nid(page) != i)
                                continue;
-                       page = pfn_to_page(pfn);
                        /* only scan if page is in use */
                        if (page_count(page) == 0)
                                continue;
@@ -1647,7 +1650,7 @@ static void kmemleak_scan(void)
  */
 static int kmemleak_scan_thread(void *arg)
 {
-       static int first_run = 1;
+       static int first_run = IS_ENABLED(CONFIG_DEBUG_KMEMLEAK_AUTO_SCAN);
 
        pr_info("Automatic memory scanning thread started\n");
        set_user_nice(current, 10);
@@ -2141,9 +2144,11 @@ static int __init kmemleak_late_init(void)
                return -ENOMEM;
        }
 
-       mutex_lock(&scan_mutex);
-       start_scan_thread();
-       mutex_unlock(&scan_mutex);
+       if (IS_ENABLED(CONFIG_DEBUG_KMEMLEAK_AUTO_SCAN)) {
+               mutex_lock(&scan_mutex);
+               start_scan_thread();
+               mutex_unlock(&scan_mutex);
+       }
 
        pr_info("Kernel memory leak detector initialized\n");
 
index 5b0894b45ee57257f34bde6072ae63a26c1714e6..6c48ad13b4c9b543aba0fc7a11b7973aeb71cc0f 100644 (file)
--- a/mm/ksm.c
+++ b/mm/ksm.c
@@ -25,7 +25,7 @@
 #include <linux/pagemap.h>
 #include <linux/rmap.h>
 #include <linux/spinlock.h>
-#include <linux/jhash.h>
+#include <linux/xxhash.h>
 #include <linux/delay.h>
 #include <linux/kthread.h>
 #include <linux/wait.h>
@@ -296,6 +296,7 @@ static unsigned long ksm_run = KSM_RUN_STOP;
 static void wait_while_offlining(void);
 
 static DECLARE_WAIT_QUEUE_HEAD(ksm_thread_wait);
+static DECLARE_WAIT_QUEUE_HEAD(ksm_iter_wait);
 static DEFINE_MUTEX(ksm_thread_mutex);
 static DEFINE_SPINLOCK(ksm_mmlist_lock);
 
@@ -1009,7 +1010,7 @@ static u32 calc_checksum(struct page *page)
 {
        u32 checksum;
        void *addr = kmap_atomic(page);
-       checksum = jhash2(addr, PAGE_SIZE / 4, 17);
+       checksum = xxhash(addr, PAGE_SIZE, 0);
        kunmap_atomic(addr);
        return checksum;
 }
@@ -1042,8 +1043,7 @@ static int write_protect_page(struct vm_area_struct *vma, struct page *page,
        };
        int swapped;
        int err = -EFAULT;
-       unsigned long mmun_start;       /* For mmu_notifiers */
-       unsigned long mmun_end;         /* For mmu_notifiers */
+       struct mmu_notifier_range range;
 
        pvmw.address = page_address_in_vma(page, vma);
        if (pvmw.address == -EFAULT)
@@ -1051,9 +1051,9 @@ static int write_protect_page(struct vm_area_struct *vma, struct page *page,
 
        BUG_ON(PageTransCompound(page));
 
-       mmun_start = pvmw.address;
-       mmun_end   = pvmw.address + PAGE_SIZE;
-       mmu_notifier_invalidate_range_start(mm, mmun_start, mmun_end);
+       mmu_notifier_range_init(&range, mm, pvmw.address,
+                               pvmw.address + PAGE_SIZE);
+       mmu_notifier_invalidate_range_start(&range);
 
        if (!page_vma_mapped_walk(&pvmw))
                goto out_mn;
@@ -1105,7 +1105,7 @@ static int write_protect_page(struct vm_area_struct *vma, struct page *page,
 out_unlock:
        page_vma_mapped_walk_done(&pvmw);
 out_mn:
-       mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end);
+       mmu_notifier_invalidate_range_end(&range);
 out:
        return err;
 }
@@ -1129,8 +1129,7 @@ static int replace_page(struct vm_area_struct *vma, struct page *page,
        spinlock_t *ptl;
        unsigned long addr;
        int err = -EFAULT;
-       unsigned long mmun_start;       /* For mmu_notifiers */
-       unsigned long mmun_end;         /* For mmu_notifiers */
+       struct mmu_notifier_range range;
 
        addr = page_address_in_vma(page, vma);
        if (addr == -EFAULT)
@@ -1140,9 +1139,8 @@ static int replace_page(struct vm_area_struct *vma, struct page *page,
        if (!pmd)
                goto out;
 
-       mmun_start = addr;
-       mmun_end   = addr + PAGE_SIZE;
-       mmu_notifier_invalidate_range_start(mm, mmun_start, mmun_end);
+       mmu_notifier_range_init(&range, mm, addr, addr + PAGE_SIZE);
+       mmu_notifier_invalidate_range_start(&range);
 
        ptep = pte_offset_map_lock(mm, pmd, addr, &ptl);
        if (!pte_same(*ptep, orig_pte)) {
@@ -1188,7 +1186,7 @@ static int replace_page(struct vm_area_struct *vma, struct page *page,
        pte_unmap_unlock(ptep, ptl);
        err = 0;
 out_mn:
-       mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end);
+       mmu_notifier_invalidate_range_end(&range);
 out:
        return err;
 }
@@ -2391,6 +2389,8 @@ static int ksmd_should_run(void)
 
 static int ksm_scan_thread(void *nothing)
 {
+       unsigned int sleep_ms;
+
        set_freezable();
        set_user_nice(current, 5);
 
@@ -2404,8 +2404,10 @@ static int ksm_scan_thread(void *nothing)
                try_to_freeze();
 
                if (ksmd_should_run()) {
-                       schedule_timeout_interruptible(
-                               msecs_to_jiffies(ksm_thread_sleep_millisecs));
+                       sleep_ms = READ_ONCE(ksm_thread_sleep_millisecs);
+                       wait_event_interruptible_timeout(ksm_iter_wait,
+                               sleep_ms != READ_ONCE(ksm_thread_sleep_millisecs),
+                               msecs_to_jiffies(sleep_ms));
                } else {
                        wait_event_freezable(ksm_thread_wait,
                                ksmd_should_run() || kthread_should_stop());
@@ -2824,6 +2826,7 @@ static ssize_t sleep_millisecs_store(struct kobject *kobj,
                return -EINVAL;
 
        ksm_thread_sleep_millisecs = msecs;
+       wake_up_interruptible(&ksm_iter_wait);
 
        return count;
 }
index 6cb1ca93e290743144567bb64ae3c87894aa1f5d..21a7881a2db41e994c977ae49bddcf6e2ee2ffd8 100644 (file)
@@ -458,29 +458,30 @@ static void madvise_free_page_range(struct mmu_gather *tlb,
 static int madvise_free_single_vma(struct vm_area_struct *vma,
                        unsigned long start_addr, unsigned long end_addr)
 {
-       unsigned long start, end;
        struct mm_struct *mm = vma->vm_mm;
+       struct mmu_notifier_range range;
        struct mmu_gather tlb;
 
        /* MADV_FREE works for only anon vma at the moment */
        if (!vma_is_anonymous(vma))
                return -EINVAL;
 
-       start = max(vma->vm_start, start_addr);
-       if (start >= vma->vm_end)
+       range.start = max(vma->vm_start, start_addr);
+       if (range.start >= vma->vm_end)
                return -EINVAL;
-       end = min(vma->vm_end, end_addr);
-       if (end <= vma->vm_start)
+       range.end = min(vma->vm_end, end_addr);
+       if (range.end <= vma->vm_start)
                return -EINVAL;
+       mmu_notifier_range_init(&range, mm, range.start, range.end);
 
        lru_add_drain();
-       tlb_gather_mmu(&tlb, mm, start, end);
+       tlb_gather_mmu(&tlb, mm, range.start, range.end);
        update_hiwater_rss(mm);
 
-       mmu_notifier_invalidate_range_start(mm, start, end);
-       madvise_free_page_range(&tlb, vma, start, end);
-       mmu_notifier_invalidate_range_end(mm, start, end);
-       tlb_finish_mmu(&tlb, start, end);
+       mmu_notifier_invalidate_range_start(&range);
+       madvise_free_page_range(&tlb, vma, range.start, range.end);
+       mmu_notifier_invalidate_range_end(&range);
+       tlb_finish_mmu(&tlb, range.start, range.end);
 
        return 0;
 }
index 81ae63ca78d0bb8cb20d615c28f41795d57b2827..022d4cbb3618bb3886cec62e69912b4e9a5e8067 100644 (file)
@@ -262,7 +262,8 @@ phys_addr_t __init_memblock memblock_find_in_range_node(phys_addr_t size,
        phys_addr_t kernel_end, ret;
 
        /* pump up @end */
-       if (end == MEMBLOCK_ALLOC_ACCESSIBLE)
+       if (end == MEMBLOCK_ALLOC_ACCESSIBLE ||
+           end == MEMBLOCK_ALLOC_KASAN)
                end = memblock.current_limit;
 
        /* avoid allocating the first page */
@@ -800,7 +801,14 @@ int __init_memblock memblock_remove(phys_addr_t base, phys_addr_t size)
        return memblock_remove_range(&memblock.memory, base, size);
 }
 
-
+/**
+ * memblock_free - free boot memory block
+ * @base: phys starting address of the  boot memory block
+ * @size: size of the boot memory block in bytes
+ *
+ * Free boot memory block previously allocated by memblock_alloc_xx() API.
+ * The freeing memory will not be released to the buddy allocator.
+ */
 int __init_memblock memblock_free(phys_addr_t base, phys_addr_t size)
 {
        phys_addr_t end = base + size - 1;
@@ -1412,13 +1420,15 @@ again:
 done:
        ptr = phys_to_virt(alloc);
 
-       /*
-        * The min_count is set to 0 so that bootmem allocated blocks
-        * are never reported as leaks. This is because many of these blocks
-        * are only referred via the physical address which is not
-        * looked up by kmemleak.
-        */
-       kmemleak_alloc(ptr, size, 0, 0);
+       /* Skip kmemleak for kasan_init() due to high volume. */
+       if (max_addr != MEMBLOCK_ALLOC_KASAN)
+               /*
+                * The min_count is set to 0 so that bootmem allocated
+                * blocks are never reported as leaks. This is because many
+                * of these blocks are only referred via the physical
+                * address which is not looked up by kmemleak.
+                */
+               kmemleak_alloc(ptr, size, 0, 0);
 
        return ptr;
 }
@@ -1536,24 +1546,6 @@ void * __init memblock_alloc_try_nid(
        return NULL;
 }
 
-/**
- * __memblock_free_early - free boot memory block
- * @base: phys starting address of the  boot memory block
- * @size: size of the boot memory block in bytes
- *
- * Free boot memory block previously allocated by memblock_alloc_xx() API.
- * The freeing memory will not be released to the buddy allocator.
- */
-void __init __memblock_free_early(phys_addr_t base, phys_addr_t size)
-{
-       phys_addr_t end = base + size - 1;
-
-       memblock_dbg("%s: [%pa-%pa] %pF\n",
-                    __func__, &base, &end, (void *)_RET_IP_);
-       kmemleak_free_part_phys(base, size);
-       memblock_remove_range(&memblock.reserved, base, size);
-}
-
 /**
  * __memblock_free_late - free bootmem block pages directly to buddy allocator
  * @base: phys starting address of the  boot memory block
@@ -1576,7 +1568,7 @@ void __init __memblock_free_late(phys_addr_t base, phys_addr_t size)
 
        for (; cursor < end; cursor++) {
                memblock_free_pages(pfn_to_page(cursor), cursor, 0);
-               totalram_pages++;
+               totalram_pages_inc();
        }
 }
 
@@ -1950,7 +1942,7 @@ void reset_node_managed_pages(pg_data_t *pgdat)
        struct zone *z;
 
        for (z = pgdat->node_zones; z < pgdat->node_zones + MAX_NR_ZONES; z++)
-               z->managed_pages = 0;
+               atomic_long_set(&z->managed_pages, 0);
 }
 
 void __init reset_all_zones_managed_pages(void)
@@ -1978,7 +1970,7 @@ unsigned long __init memblock_free_all(void)
        reset_all_zones_managed_pages();
 
        pages = free_low_memory_core_early();
-       totalram_pages += pages;
+       totalram_pages_add(pages);
 
        return pages;
 }
index 6e1469b80cb7d57d3cdf01ef9c917a21ece0b7fa..af7f18b32389e4ec0435128aa4b6d93fac6b80ca 100644 (file)
@@ -1293,32 +1293,39 @@ static const char *const memcg1_stat_names[] = {
 
 #define K(x) ((x) << (PAGE_SHIFT-10))
 /**
- * mem_cgroup_print_oom_info: Print OOM information relevant to memory controller.
+ * mem_cgroup_print_oom_context: Print OOM information relevant to
+ * memory controller.
  * @memcg: The memory cgroup that went over limit
  * @p: Task that is going to be killed
  *
  * NOTE: @memcg and @p's mem_cgroup can be different when hierarchy is
  * enabled
  */
-void mem_cgroup_print_oom_info(struct mem_cgroup *memcg, struct task_struct *p)
+void mem_cgroup_print_oom_context(struct mem_cgroup *memcg, struct task_struct *p)
 {
-       struct mem_cgroup *iter;
-       unsigned int i;
-
        rcu_read_lock();
 
+       if (memcg) {
+               pr_cont(",oom_memcg=");
+               pr_cont_cgroup_path(memcg->css.cgroup);
+       } else
+               pr_cont(",global_oom");
        if (p) {
-               pr_info("Task in ");
+               pr_cont(",task_memcg=");
                pr_cont_cgroup_path(task_cgroup(p, memory_cgrp_id));
-               pr_cont(" killed as a result of limit of ");
-       } else {
-               pr_info("Memory limit reached of cgroup ");
        }
-
-       pr_cont_cgroup_path(memcg->css.cgroup);
-       pr_cont("\n");
-
        rcu_read_unlock();
+}
+
+/**
+ * mem_cgroup_print_oom_meminfo: Print OOM memory information relevant to
+ * memory controller.
+ * @memcg: The memory cgroup that went over limit
+ */
+void mem_cgroup_print_oom_meminfo(struct mem_cgroup *memcg)
+{
+       struct mem_cgroup *iter;
+       unsigned int i;
 
        pr_info("memory: usage %llukB, limit %llukB, failcnt %lu\n",
                K((u64)page_counter_read(&memcg->memory)),
@@ -1666,6 +1673,9 @@ enum oom_status {
 
 static enum oom_status mem_cgroup_oom(struct mem_cgroup *memcg, gfp_t mask, int order)
 {
+       enum oom_status ret;
+       bool locked;
+
        if (order > PAGE_ALLOC_COSTLY_ORDER)
                return OOM_SKIPPED;
 
@@ -1700,10 +1710,23 @@ static enum oom_status mem_cgroup_oom(struct mem_cgroup *memcg, gfp_t mask, int
                return OOM_ASYNC;
        }
 
+       mem_cgroup_mark_under_oom(memcg);
+
+       locked = mem_cgroup_oom_trylock(memcg);
+
+       if (locked)
+               mem_cgroup_oom_notify(memcg);
+
+       mem_cgroup_unmark_under_oom(memcg);
        if (mem_cgroup_out_of_memory(memcg, mask, order))
-               return OOM_SUCCESS;
+               ret = OOM_SUCCESS;
+       else
+               ret = OOM_FAILED;
 
-       return OOM_FAILED;
+       if (locked)
+               mem_cgroup_oom_unlock(memcg);
+
+       return ret;
 }
 
 /**
index 7c72f2a95785e0d3d5df615ea33477b0bdcc5278..6379fff1a5ff260fbf4499fc0855572c0c04192c 100644 (file)
@@ -966,7 +966,7 @@ static bool hwpoison_user_mappings(struct page *p, unsigned long pfn,
        enum ttu_flags ttu = TTU_IGNORE_MLOCK | TTU_IGNORE_ACCESS;
        struct address_space *mapping;
        LIST_HEAD(tokill);
-       bool unmap_success;
+       bool unmap_success = true;
        int kill = 1, forcekill;
        struct page *hpage = *hpagep;
        bool mlocked = PageMlocked(hpage);
@@ -1028,7 +1028,19 @@ static bool hwpoison_user_mappings(struct page *p, unsigned long pfn,
        if (kill)
                collect_procs(hpage, &tokill, flags & MF_ACTION_REQUIRED);
 
-       unmap_success = try_to_unmap(hpage, ttu);
+       if (!PageHuge(hpage)) {
+               unmap_success = try_to_unmap(hpage, ttu);
+       } else if (mapping) {
+               /*
+                * For hugetlb pages, try_to_unmap could potentially call
+                * huge_pmd_unshare.  Because of this, take semaphore in
+                * write mode here and set TTU_RMAP_LOCKED to indicate we
+                * have taken the lock at this higer level.
+                */
+               i_mmap_lock_write(mapping);
+               unmap_success = try_to_unmap(hpage, ttu|TTU_RMAP_LOCKED);
+               i_mmap_unlock_write(mapping);
+       }
        if (!unmap_success)
                pr_err("Memory failure: %#lx: failed to unmap page (mapcount=%d)\n",
                       pfn, page_mapcount(hpage));
index 4ad2d293ddc2605d2ae44ce075de68beb93841e0..2dd2f9ab57f4656c7dd0e06411a6416b8964922d 100644 (file)
@@ -973,8 +973,7 @@ int copy_page_range(struct mm_struct *dst_mm, struct mm_struct *src_mm,
        unsigned long next;
        unsigned long addr = vma->vm_start;
        unsigned long end = vma->vm_end;
-       unsigned long mmun_start;       /* For mmu_notifiers */
-       unsigned long mmun_end;         /* For mmu_notifiers */
+       struct mmu_notifier_range range;
        bool is_cow;
        int ret;
 
@@ -1008,11 +1007,11 @@ int copy_page_range(struct mm_struct *dst_mm, struct mm_struct *src_mm,
         * is_cow_mapping() returns true.
         */
        is_cow = is_cow_mapping(vma->vm_flags);
-       mmun_start = addr;
-       mmun_end   = end;
-       if (is_cow)
-               mmu_notifier_invalidate_range_start(src_mm, mmun_start,
-                                                   mmun_end);
+
+       if (is_cow) {
+               mmu_notifier_range_init(&range, src_mm, addr, end);
+               mmu_notifier_invalidate_range_start(&range);
+       }
 
        ret = 0;
        dst_pgd = pgd_offset(dst_mm, addr);
@@ -1029,7 +1028,7 @@ int copy_page_range(struct mm_struct *dst_mm, struct mm_struct *src_mm,
        } while (dst_pgd++, src_pgd++, addr = next, addr != end);
 
        if (is_cow)
-               mmu_notifier_invalidate_range_end(src_mm, mmun_start, mmun_end);
+               mmu_notifier_invalidate_range_end(&range);
        return ret;
 }
 
@@ -1332,12 +1331,13 @@ void unmap_vmas(struct mmu_gather *tlb,
                struct vm_area_struct *vma, unsigned long start_addr,
                unsigned long end_addr)
 {
-       struct mm_struct *mm = vma->vm_mm;
+       struct mmu_notifier_range range;
 
-       mmu_notifier_invalidate_range_start(mm, start_addr, end_addr);
+       mmu_notifier_range_init(&range, vma->vm_mm, start_addr, end_addr);
+       mmu_notifier_invalidate_range_start(&range);
        for ( ; vma && vma->vm_start < end_addr; vma = vma->vm_next)
                unmap_single_vma(tlb, vma, start_addr, end_addr, NULL);
-       mmu_notifier_invalidate_range_end(mm, start_addr, end_addr);
+       mmu_notifier_invalidate_range_end(&range);
 }
 
 /**
@@ -1351,18 +1351,18 @@ void unmap_vmas(struct mmu_gather *tlb,
 void zap_page_range(struct vm_area_struct *vma, unsigned long start,
                unsigned long size)
 {
-       struct mm_struct *mm = vma->vm_mm;
+       struct mmu_notifier_range range;
        struct mmu_gather tlb;
-       unsigned long end = start + size;
 
        lru_add_drain();
-       tlb_gather_mmu(&tlb, mm, start, end);
-       update_hiwater_rss(mm);
-       mmu_notifier_invalidate_range_start(mm, start, end);
-       for ( ; vma && vma->vm_start < end; vma = vma->vm_next)
-               unmap_single_vma(&tlb, vma, start, end, NULL);
-       mmu_notifier_invalidate_range_end(mm, start, end);
-       tlb_finish_mmu(&tlb, start, end);
+       mmu_notifier_range_init(&range, vma->vm_mm, start, start + size);
+       tlb_gather_mmu(&tlb, vma->vm_mm, start, range.end);
+       update_hiwater_rss(vma->vm_mm);
+       mmu_notifier_invalidate_range_start(&range);
+       for ( ; vma && vma->vm_start < range.end; vma = vma->vm_next)
+               unmap_single_vma(&tlb, vma, start, range.end, NULL);
+       mmu_notifier_invalidate_range_end(&range);
+       tlb_finish_mmu(&tlb, start, range.end);
 }
 
 /**
@@ -1377,17 +1377,17 @@ void zap_page_range(struct vm_area_struct *vma, unsigned long start,
 static void zap_page_range_single(struct vm_area_struct *vma, unsigned long address,
                unsigned long size, struct zap_details *details)
 {
-       struct mm_struct *mm = vma->vm_mm;
+       struct mmu_notifier_range range;
        struct mmu_gather tlb;
-       unsigned long end = address + size;
 
        lru_add_drain();
-       tlb_gather_mmu(&tlb, mm, address, end);
-       update_hiwater_rss(mm);
-       mmu_notifier_invalidate_range_start(mm, address, end);
-       unmap_single_vma(&tlb, vma, address, end, details);
-       mmu_notifier_invalidate_range_end(mm, address, end);
-       tlb_finish_mmu(&tlb, address, end);
+       mmu_notifier_range_init(&range, vma->vm_mm, address, address + size);
+       tlb_gather_mmu(&tlb, vma->vm_mm, address, range.end);
+       update_hiwater_rss(vma->vm_mm);
+       mmu_notifier_invalidate_range_start(&range);
+       unmap_single_vma(&tlb, vma, address, range.end, details);
+       mmu_notifier_invalidate_range_end(&range);
+       tlb_finish_mmu(&tlb, address, range.end);
 }
 
 /**
@@ -2247,9 +2247,8 @@ static vm_fault_t wp_page_copy(struct vm_fault *vmf)
        struct page *new_page = NULL;
        pte_t entry;
        int page_copied = 0;
-       const unsigned long mmun_start = vmf->address & PAGE_MASK;
-       const unsigned long mmun_end = mmun_start + PAGE_SIZE;
        struct mem_cgroup *memcg;
+       struct mmu_notifier_range range;
 
        if (unlikely(anon_vma_prepare(vma)))
                goto oom;
@@ -2272,7 +2271,9 @@ static vm_fault_t wp_page_copy(struct vm_fault *vmf)
 
        __SetPageUptodate(new_page);
 
-       mmu_notifier_invalidate_range_start(mm, mmun_start, mmun_end);
+       mmu_notifier_range_init(&range, mm, vmf->address & PAGE_MASK,
+                               (vmf->address & PAGE_MASK) + PAGE_SIZE);
+       mmu_notifier_invalidate_range_start(&range);
 
        /*
         * Re-check the pte - we dropped the lock
@@ -2349,7 +2350,7 @@ static vm_fault_t wp_page_copy(struct vm_fault *vmf)
         * No need to double call mmu_notifier->invalidate_range() callback as
         * the above ptep_clear_flush_notify() did already call it.
         */
-       mmu_notifier_invalidate_range_only_end(mm, mmun_start, mmun_end);
+       mmu_notifier_invalidate_range_only_end(&range);
        if (old_page) {
                /*
                 * Don't let another task, with possibly unlocked vma,
@@ -3830,7 +3831,7 @@ static vm_fault_t __handle_mm_fault(struct vm_area_struct *vma,
        vmf.pud = pud_alloc(mm, p4d, address);
        if (!vmf.pud)
                return VM_FAULT_OOM;
-       if (pud_none(*vmf.pud) && transparent_hugepage_enabled(vma)) {
+       if (pud_none(*vmf.pud) && __transparent_hugepage_enabled(vma)) {
                ret = create_huge_pud(&vmf);
                if (!(ret & VM_FAULT_FALLBACK))
                        return ret;
@@ -3856,7 +3857,7 @@ static vm_fault_t __handle_mm_fault(struct vm_area_struct *vma,
        vmf.pmd = pmd_alloc(mm, vmf.pud, address);
        if (!vmf.pmd)
                return VM_FAULT_OOM;
-       if (pmd_none(*vmf.pmd) && transparent_hugepage_enabled(vma)) {
+       if (pmd_none(*vmf.pmd) && __transparent_hugepage_enabled(vma)) {
                ret = create_huge_pmd(&vmf);
                if (!(ret & VM_FAULT_FALLBACK))
                        return ret;
@@ -4030,7 +4031,7 @@ int __pmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long address)
 #endif /* __PAGETABLE_PMD_FOLDED */
 
 static int __follow_pte_pmd(struct mm_struct *mm, unsigned long address,
-                           unsigned long *start, unsigned long *end,
+                           struct mmu_notifier_range *range,
                            pte_t **ptepp, pmd_t **pmdpp, spinlock_t **ptlp)
 {
        pgd_t *pgd;
@@ -4058,10 +4059,10 @@ static int __follow_pte_pmd(struct mm_struct *mm, unsigned long address,
                if (!pmdpp)
                        goto out;
 
-               if (start && end) {
-                       *start = address & PMD_MASK;
-                       *end = *start + PMD_SIZE;
-                       mmu_notifier_invalidate_range_start(mm, *start, *end);
+               if (range) {
+                       mmu_notifier_range_init(range, mm, address & PMD_MASK,
+                                            (address & PMD_MASK) + PMD_SIZE);
+                       mmu_notifier_invalidate_range_start(range);
                }
                *ptlp = pmd_lock(mm, pmd);
                if (pmd_huge(*pmd)) {
@@ -4069,17 +4070,17 @@ static int __follow_pte_pmd(struct mm_struct *mm, unsigned long address,
                        return 0;
                }
                spin_unlock(*ptlp);
-               if (start && end)
-                       mmu_notifier_invalidate_range_end(mm, *start, *end);
+               if (range)
+                       mmu_notifier_invalidate_range_end(range);
        }
 
        if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd)))
                goto out;
 
-       if (start && end) {
-               *start = address & PAGE_MASK;
-               *end = *start + PAGE_SIZE;
-               mmu_notifier_invalidate_range_start(mm, *start, *end);
+       if (range) {
+               range->start = address & PAGE_MASK;
+               range->end = range->start + PAGE_SIZE;
+               mmu_notifier_invalidate_range_start(range);
        }
        ptep = pte_offset_map_lock(mm, pmd, address, ptlp);
        if (!pte_present(*ptep))
@@ -4088,8 +4089,8 @@ static int __follow_pte_pmd(struct mm_struct *mm, unsigned long address,
        return 0;
 unlock:
        pte_unmap_unlock(ptep, *ptlp);
-       if (start && end)
-               mmu_notifier_invalidate_range_end(mm, *start, *end);
+       if (range)
+               mmu_notifier_invalidate_range_end(range);
 out:
        return -EINVAL;
 }
@@ -4101,20 +4102,20 @@ static inline int follow_pte(struct mm_struct *mm, unsigned long address,
 
        /* (void) is needed to make gcc happy */
        (void) __cond_lock(*ptlp,
-                          !(res = __follow_pte_pmd(mm, address, NULL, NULL,
+                          !(res = __follow_pte_pmd(mm, address, NULL,
                                                    ptepp, NULL, ptlp)));
        return res;
 }
 
 int follow_pte_pmd(struct mm_struct *mm, unsigned long address,
-                            unsigned long *start, unsigned long *end,
-                            pte_t **ptepp, pmd_t **pmdpp, spinlock_t **ptlp)
+                  struct mmu_notifier_range *range,
+                  pte_t **ptepp, pmd_t **pmdpp, spinlock_t **ptlp)
 {
        int res;
 
        /* (void) is needed to make gcc happy */
        (void) __cond_lock(*ptlp,
-                          !(res = __follow_pte_pmd(mm, address, start, end,
+                          !(res = __follow_pte_pmd(mm, address, range,
                                                    ptepp, pmdpp, ptlp)));
        return res;
 }
index 2b2b3ccbbfb5768a3d6b530799ebf5c4c3129688..b9a667d36c554afc46c2d337a2712e6ca8664fb5 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/hugetlb.h>
 #include <linux/memblock.h>
 #include <linux/compaction.h>
+#include <linux/rmap.h>
 
 #include <asm/tlbflush.h>
 
@@ -253,7 +254,7 @@ static int __meminit __add_section(int nid, unsigned long phys_start_pfn,
        if (pfn_valid(phys_start_pfn))
                return -EEXIST;
 
-       ret = sparse_add_one_section(NODE_DATA(nid), phys_start_pfn, altmap);
+       ret = sparse_add_one_section(nid, phys_start_pfn, altmap);
        if (ret < 0)
                return ret;
 
@@ -743,14 +744,13 @@ void __ref move_pfn_range_to_zone(struct zone *zone, unsigned long start_pfn,
        int nid = pgdat->node_id;
        unsigned long flags;
 
-       if (zone_is_empty(zone))
-               init_currently_empty_zone(zone, start_pfn, nr_pages);
-
        clear_zone_contiguous(zone);
 
        /* TODO Huh pgdat is irqsave while zone is not. It used to be like that before */
        pgdat_resize_lock(pgdat, &flags);
        zone_span_writelock(zone);
+       if (zone_is_empty(zone))
+               init_currently_empty_zone(zone, start_pfn, nr_pages);
        resize_zone_range(zone, start_pfn, nr_pages);
        zone_span_writeunlock(zone);
        resize_pgdat_range(pgdat, start_pfn, nr_pages);
@@ -1078,7 +1078,7 @@ static int online_memory_block(struct memory_block *mem, void *arg)
  *
  * we are OK calling __meminit stuff here - we have CONFIG_MEMORY_HOTPLUG
  */
-int __ref add_memory_resource(int nid, struct resource *res, bool online)
+int __ref add_memory_resource(int nid, struct resource *res)
 {
        u64 start, size;
        bool new_node = false;
@@ -1133,7 +1133,7 @@ int __ref add_memory_resource(int nid, struct resource *res, bool online)
        mem_hotplug_done();
 
        /* online pages if requested */
-       if (online)
+       if (memhp_auto_online)
                walk_memory_range(PFN_DOWN(start), PFN_UP(start + size - 1),
                                  NULL, online_memory_block);
 
@@ -1157,7 +1157,7 @@ int __ref __add_memory(int nid, u64 start, u64 size)
        if (IS_ERR(res))
                return PTR_ERR(res);
 
-       ret = add_memory_resource(nid, res, memhp_auto_online);
+       ret = add_memory_resource(nid, res);
        if (ret < 0)
                release_memory_resource(res);
        return ret;
@@ -1226,7 +1226,7 @@ static bool is_pageblock_removable_nolock(struct page *page)
        if (!zone_spans_pfn(zone, pfn))
                return false;
 
-       return !has_unmovable_pages(zone, page, 0, MIGRATE_MOVABLE, true);
+       return !has_unmovable_pages(zone, page, 0, MIGRATE_MOVABLE, SKIP_HWPOISON);
 }
 
 /* Checks if this range of memory is likely to be hot-removable. */
@@ -1339,18 +1339,16 @@ static struct page *new_node_page(struct page *page, unsigned long private)
        return new_page_nodemask(page, nid, &nmask);
 }
 
-#define NR_OFFLINE_AT_ONCE_PAGES       (256)
 static int
 do_migrate_range(unsigned long start_pfn, unsigned long end_pfn)
 {
        unsigned long pfn;
        struct page *page;
-       int move_pages = NR_OFFLINE_AT_ONCE_PAGES;
        int not_managed = 0;
        int ret = 0;
        LIST_HEAD(source);
 
-       for (pfn = start_pfn; pfn < end_pfn && move_pages > 0; pfn++) {
+       for (pfn = start_pfn; pfn < end_pfn; pfn++) {
                if (!pfn_valid(pfn))
                        continue;
                page = pfn_to_page(pfn);
@@ -1362,13 +1360,27 @@ do_migrate_range(unsigned long start_pfn, unsigned long end_pfn)
                                ret = -EBUSY;
                                break;
                        }
-                       if (isolate_huge_page(page, &source))
-                               move_pages -= 1 << compound_order(head);
+                       isolate_huge_page(page, &source);
                        continue;
                } else if (PageTransHuge(page))
                        pfn = page_to_pfn(compound_head(page))
                                + hpage_nr_pages(page) - 1;
 
+               /*
+                * HWPoison pages have elevated reference counts so the migration would
+                * fail on them. It also doesn't make any sense to migrate them in the
+                * first place. Still try to unmap such a page in case it is still mapped
+                * (e.g. current hwpoison implementation doesn't unmap KSM pages but keep
+                * the unmap as the catch all safety net).
+                */
+               if (PageHWPoison(page)) {
+                       if (WARN_ON(PageLRU(page)))
+                               isolate_lru_page(page);
+                       if (page_mapped(page))
+                               try_to_unmap(page, TTU_IGNORE_MLOCK | TTU_IGNORE_ACCESS);
+                       continue;
+               }
+
                if (!get_page_unless_zero(page))
                        continue;
                /*
@@ -1382,16 +1394,13 @@ do_migrate_range(unsigned long start_pfn, unsigned long end_pfn)
                if (!ret) { /* Success */
                        put_page(page);
                        list_add_tail(&page->lru, &source);
-                       move_pages--;
                        if (!__PageMovable(page))
                                inc_node_page_state(page, NR_ISOLATED_ANON +
                                                    page_is_file_cache(page));
 
                } else {
-#ifdef CONFIG_DEBUG_VM
-                       pr_alert("failed to isolate pfn %lx\n", pfn);
+                       pr_warn("failed to isolate pfn %lx\n", pfn);
                        dump_page(page, "isolation failed");
-#endif
                        put_page(page);
                        /* Because we don't have big zone->lock. we should
                           check this again here. */
@@ -1411,8 +1420,14 @@ do_migrate_range(unsigned long start_pfn, unsigned long end_pfn)
                /* Allocate a new page from the nearest neighbor node */
                ret = migrate_pages(&source, new_node_page, NULL, 0,
                                        MIGRATE_SYNC, MR_MEMORY_HOTPLUG);
-               if (ret)
+               if (ret) {
+                       list_for_each_entry(page, &source, lru) {
+                               pr_warn("migrating pfn %lx failed ret:%d ",
+                                      page_to_pfn(page), ret);
+                               dump_page(page, "migration failure");
+                       }
                        putback_movable_pages(&source);
+               }
        }
 out:
        return ret;
@@ -1553,12 +1568,7 @@ static int __ref __offline_pages(unsigned long start_pfn,
        unsigned long valid_start, valid_end;
        struct zone *zone;
        struct memory_notify arg;
-
-       /* at least, alignment against pageblock is necessary */
-       if (!IS_ALIGNED(start_pfn, pageblock_nr_pages))
-               return -EINVAL;
-       if (!IS_ALIGNED(end_pfn, pageblock_nr_pages))
-               return -EINVAL;
+       char *reason;
 
        mem_hotplug_begin();
 
@@ -1567,7 +1577,9 @@ static int __ref __offline_pages(unsigned long start_pfn,
        if (!test_pages_in_a_zone(start_pfn, end_pfn, &valid_start,
                                  &valid_end)) {
                mem_hotplug_done();
-               return -EINVAL;
+               ret = -EINVAL;
+               reason = "multizone range";
+               goto failed_removal;
        }
 
        zone = page_zone(pfn_to_page(valid_start));
@@ -1576,10 +1588,12 @@ static int __ref __offline_pages(unsigned long start_pfn,
 
        /* set above range as isolated */
        ret = start_isolate_page_range(start_pfn, end_pfn,
-                                      MIGRATE_MOVABLE, true);
+                                      MIGRATE_MOVABLE,
+                                      SKIP_HWPOISON | REPORT_FAILURE);
        if (ret) {
                mem_hotplug_done();
-               return ret;
+               reason = "failure to isolate range";
+               goto failed_removal;
        }
 
        arg.start_pfn = start_pfn;
@@ -1588,37 +1602,47 @@ static int __ref __offline_pages(unsigned long start_pfn,
 
        ret = memory_notify(MEM_GOING_OFFLINE, &arg);
        ret = notifier_to_errno(ret);
-       if (ret)
-               goto failed_removal;
+       if (ret) {
+               reason = "notifier failure";
+               goto failed_removal_isolated;
+       }
 
-       pfn = start_pfn;
-repeat:
-       /* start memory hot removal */
-       ret = -EINTR;
-       if (signal_pending(current))
-               goto failed_removal;
+       do {
+               for (pfn = start_pfn; pfn;) {
+                       if (signal_pending(current)) {
+                               ret = -EINTR;
+                               reason = "signal backoff";
+                               goto failed_removal_isolated;
+                       }
 
-       cond_resched();
-       lru_add_drain_all();
-       drain_all_pages(zone);
+                       cond_resched();
+                       lru_add_drain_all();
+                       drain_all_pages(zone);
+
+                       pfn = scan_movable_pages(pfn, end_pfn);
+                       if (pfn) {
+                               /*
+                                * TODO: fatal migration failures should bail
+                                * out
+                                */
+                               do_migrate_range(pfn, end_pfn);
+                       }
+               }
 
-       pfn = scan_movable_pages(start_pfn, end_pfn);
-       if (pfn) { /* We have movable pages */
-               ret = do_migrate_range(pfn, end_pfn);
-               goto repeat;
-       }
+               /*
+                * Dissolve free hugepages in the memory block before doing
+                * offlining actually in order to make hugetlbfs's object
+                * counting consistent.
+                */
+               ret = dissolve_free_huge_pages(start_pfn, end_pfn);
+               if (ret) {
+                       reason = "failure to dissolve huge pages";
+                       goto failed_removal_isolated;
+               }
+               /* check again */
+               offlined_pages = check_pages_isolated(start_pfn, end_pfn);
+       } while (offlined_pages < 0);
 
-       /*
-        * dissolve free hugepages in the memory block before doing offlining
-        * actually in order to make hugetlbfs's object counting consistent.
-        */
-       ret = dissolve_free_huge_pages(start_pfn, end_pfn);
-       if (ret)
-               goto failed_removal;
-       /* check again */
-       offlined_pages = check_pages_isolated(start_pfn, end_pfn);
-       if (offlined_pages < 0)
-               goto repeat;
        pr_info("Offlined Pages %ld\n", offlined_pages);
        /* Ok, all of our target is isolated.
           We cannot do rollback at this point. */
@@ -1654,13 +1678,15 @@ repeat:
        mem_hotplug_done();
        return 0;
 
+failed_removal_isolated:
+       undo_isolate_page_range(start_pfn, end_pfn, MIGRATE_MOVABLE);
 failed_removal:
-       pr_debug("memory offlining [mem %#010llx-%#010llx] failed\n",
+       pr_debug("memory offlining [mem %#010llx-%#010llx] failed due to %s\n",
                 (unsigned long long) start_pfn << PAGE_SHIFT,
-                ((unsigned long long) end_pfn << PAGE_SHIFT) - 1);
+                ((unsigned long long) end_pfn << PAGE_SHIFT) - 1,
+                reason);
        memory_notify(MEM_CANCEL_OFFLINE, &arg);
        /* pushback to free area */
-       undo_isolate_page_range(start_pfn, end_pfn, MIGRATE_MOVABLE);
        mem_hotplug_done();
        return ret;
 }
@@ -1753,34 +1779,6 @@ static int check_cpu_on_node(pg_data_t *pgdat)
        return 0;
 }
 
-static void unmap_cpu_on_node(pg_data_t *pgdat)
-{
-#ifdef CONFIG_ACPI_NUMA
-       int cpu;
-
-       for_each_possible_cpu(cpu)
-               if (cpu_to_node(cpu) == pgdat->node_id)
-                       numa_clear_node(cpu);
-#endif
-}
-
-static int check_and_unmap_cpu_on_node(pg_data_t *pgdat)
-{
-       int ret;
-
-       ret = check_cpu_on_node(pgdat);
-       if (ret)
-               return ret;
-
-       /*
-        * the node will be offlined when we come here, so we can clear
-        * the cpu_to_node() now.
-        */
-
-       unmap_cpu_on_node(pgdat);
-       return 0;
-}
-
 /**
  * try_offline_node
  * @nid: the node ID
@@ -1813,7 +1811,7 @@ void try_offline_node(int nid)
                return;
        }
 
-       if (check_and_unmap_cpu_on_node(pgdat))
+       if (check_cpu_on_node(pgdat))
                return;
 
        /*
@@ -1858,7 +1856,7 @@ void __ref __remove_memory(int nid, u64 start, u64 size)
        memblock_free(start, size);
        memblock_remove(start, size);
 
-       arch_remove_memory(start, size, NULL);
+       arch_remove_memory(nid, start, size, NULL);
 
        try_offline_node(nid);
 
index f7e4bfdc13b780137d08fa522b070e7192056f24..5d1839a9148df0d98f4183dbe931b3abe7541f68 100644 (file)
@@ -327,16 +327,13 @@ void __migration_entry_wait(struct mm_struct *mm, pte_t *ptep,
 
        /*
         * Once page cache replacement of page migration started, page_count
-        * *must* be zero. And, we don't want to call wait_on_page_locked()
-        * against a page without get_page().
-        * So, we use get_page_unless_zero(), here. Even failed, page fault
-        * will occur again.
+        * is zero; but we must not call put_and_wait_on_page_locked() without
+        * a ref. Use get_page_unless_zero(), and just fault again if it fails.
         */
        if (!get_page_unless_zero(page))
                goto out;
        pte_unmap_unlock(ptep, ptl);
-       wait_on_page_locked(page);
-       put_page(page);
+       put_and_wait_on_page_locked(page);
        return;
 out:
        pte_unmap_unlock(ptep, ptl);
@@ -370,63 +367,28 @@ void pmd_migration_entry_wait(struct mm_struct *mm, pmd_t *pmd)
        if (!get_page_unless_zero(page))
                goto unlock;
        spin_unlock(ptl);
-       wait_on_page_locked(page);
-       put_page(page);
+       put_and_wait_on_page_locked(page);
        return;
 unlock:
        spin_unlock(ptl);
 }
 #endif
 
-#ifdef CONFIG_BLOCK
-/* Returns true if all buffers are successfully locked */
-static bool buffer_migrate_lock_buffers(struct buffer_head *head,
-                                                       enum migrate_mode mode)
+static int expected_page_refs(struct page *page)
 {
-       struct buffer_head *bh = head;
-
-       /* Simple case, sync compaction */
-       if (mode != MIGRATE_ASYNC) {
-               do {
-                       get_bh(bh);
-                       lock_buffer(bh);
-                       bh = bh->b_this_page;
-
-               } while (bh != head);
+       int expected_count = 1;
 
-               return true;
-       }
-
-       /* async case, we cannot block on lock_buffer so use trylock_buffer */
-       do {
-               get_bh(bh);
-               if (!trylock_buffer(bh)) {
-                       /*
-                        * We failed to lock the buffer and cannot stall in
-                        * async migration. Release the taken locks
-                        */
-                       struct buffer_head *failed_bh = bh;
-                       put_bh(failed_bh);
-                       bh = head;
-                       while (bh != failed_bh) {
-                               unlock_buffer(bh);
-                               put_bh(bh);
-                               bh = bh->b_this_page;
-                       }
-                       return false;
-               }
+       /*
+        * Device public or private pages have an extra refcount as they are
+        * ZONE_DEVICE pages.
+        */
+       expected_count += is_device_private_page(page);
+       expected_count += is_device_public_page(page);
+       if (page_mapping(page))
+               expected_count += hpage_nr_pages(page) + page_has_private(page);
 
-               bh = bh->b_this_page;
-       } while (bh != head);
-       return true;
-}
-#else
-static inline bool buffer_migrate_lock_buffers(struct buffer_head *head,
-                                                       enum migrate_mode mode)
-{
-       return true;
+       return expected_count;
 }
-#endif /* CONFIG_BLOCK */
 
 /*
  * Replace the page in the mapping.
@@ -437,21 +399,13 @@ static inline bool buffer_migrate_lock_buffers(struct buffer_head *head,
  * 3 for pages with a mapping and PagePrivate/PagePrivate2 set.
  */
 int migrate_page_move_mapping(struct address_space *mapping,
-               struct page *newpage, struct page *page,
-               struct buffer_head *head, enum migrate_mode mode,
+               struct page *newpage, struct page *page, enum migrate_mode mode,
                int extra_count)
 {
        XA_STATE(xas, &mapping->i_pages, page_index(page));
        struct zone *oldzone, *newzone;
        int dirty;
-       int expected_count = 1 + extra_count;
-
-       /*
-        * Device public or private pages have an extra refcount as they are
-        * ZONE_DEVICE pages.
-        */
-       expected_count += is_device_private_page(page);
-       expected_count += is_device_public_page(page);
+       int expected_count = expected_page_refs(page) + extra_count;
 
        if (!mapping) {
                /* Anonymous page without mapping */
@@ -471,8 +425,6 @@ int migrate_page_move_mapping(struct address_space *mapping,
        newzone = page_zone(newpage);
 
        xas_lock_irq(&xas);
-
-       expected_count += hpage_nr_pages(page) + page_has_private(page);
        if (page_count(page) != expected_count || xas_load(&xas) != page) {
                xas_unlock_irq(&xas);
                return -EAGAIN;
@@ -483,20 +435,6 @@ int migrate_page_move_mapping(struct address_space *mapping,
                return -EAGAIN;
        }
 
-       /*
-        * In the async migration case of moving a page with buffers, lock the
-        * buffers using trylock before the mapping is moved. If the mapping
-        * was moved, we later failed to lock the buffers and could not move
-        * the mapping back due to an elevated page count, we would have to
-        * block waiting on other references to be dropped.
-        */
-       if (mode == MIGRATE_ASYNC && head &&
-                       !buffer_migrate_lock_buffers(head, mode)) {
-               page_ref_unfreeze(page, expected_count);
-               xas_unlock_irq(&xas);
-               return -EAGAIN;
-       }
-
        /*
         * Now we know that no one else is looking at the page:
         * no turning back from here.
@@ -748,7 +686,7 @@ int migrate_page(struct address_space *mapping,
 
        BUG_ON(PageWriteback(page));    /* Writeback must be complete */
 
-       rc = migrate_page_move_mapping(mapping, newpage, page, NULL, mode, 0);
+       rc = migrate_page_move_mapping(mapping, newpage, page, mode, 0);
 
        if (rc != MIGRATEPAGE_SUCCESS)
                return rc;
@@ -762,34 +700,98 @@ int migrate_page(struct address_space *mapping,
 EXPORT_SYMBOL(migrate_page);
 
 #ifdef CONFIG_BLOCK
-/*
- * Migration function for pages with buffers. This function can only be used
- * if the underlying filesystem guarantees that no other references to "page"
- * exist.
- */
-int buffer_migrate_page(struct address_space *mapping,
-               struct page *newpage, struct page *page, enum migrate_mode mode)
+/* Returns true if all buffers are successfully locked */
+static bool buffer_migrate_lock_buffers(struct buffer_head *head,
+                                                       enum migrate_mode mode)
+{
+       struct buffer_head *bh = head;
+
+       /* Simple case, sync compaction */
+       if (mode != MIGRATE_ASYNC) {
+               do {
+                       get_bh(bh);
+                       lock_buffer(bh);
+                       bh = bh->b_this_page;
+
+               } while (bh != head);
+
+               return true;
+       }
+
+       /* async case, we cannot block on lock_buffer so use trylock_buffer */
+       do {
+               get_bh(bh);
+               if (!trylock_buffer(bh)) {
+                       /*
+                        * We failed to lock the buffer and cannot stall in
+                        * async migration. Release the taken locks
+                        */
+                       struct buffer_head *failed_bh = bh;
+                       put_bh(failed_bh);
+                       bh = head;
+                       while (bh != failed_bh) {
+                               unlock_buffer(bh);
+                               put_bh(bh);
+                               bh = bh->b_this_page;
+                       }
+                       return false;
+               }
+
+               bh = bh->b_this_page;
+       } while (bh != head);
+       return true;
+}
+
+static int __buffer_migrate_page(struct address_space *mapping,
+               struct page *newpage, struct page *page, enum migrate_mode mode,
+               bool check_refs)
 {
        struct buffer_head *bh, *head;
        int rc;
+       int expected_count;
 
        if (!page_has_buffers(page))
                return migrate_page(mapping, newpage, page, mode);
 
+       /* Check whether page does not have extra refs before we do more work */
+       expected_count = expected_page_refs(page);
+       if (page_count(page) != expected_count)
+               return -EAGAIN;
+
        head = page_buffers(page);
+       if (!buffer_migrate_lock_buffers(head, mode))
+               return -EAGAIN;
 
-       rc = migrate_page_move_mapping(mapping, newpage, page, head, mode, 0);
+       if (check_refs) {
+               bool busy;
+               bool invalidated = false;
 
-       if (rc != MIGRATEPAGE_SUCCESS)
-               return rc;
+recheck_buffers:
+               busy = false;
+               spin_lock(&mapping->private_lock);
+               bh = head;
+               do {
+                       if (atomic_read(&bh->b_count)) {
+                               busy = true;
+                               break;
+                       }
+                       bh = bh->b_this_page;
+               } while (bh != head);
+               spin_unlock(&mapping->private_lock);
+               if (busy) {
+                       if (invalidated) {
+                               rc = -EAGAIN;
+                               goto unlock_buffers;
+                       }
+                       invalidate_bh_lrus();
+                       invalidated = true;
+                       goto recheck_buffers;
+               }
+       }
 
-       /*
-        * In the async case, migrate_page_move_mapping locked the buffers
-        * with an IRQ-safe spinlock held. In the sync case, the buffers
-        * need to be locked now
-        */
-       if (mode != MIGRATE_ASYNC)
-               BUG_ON(!buffer_migrate_lock_buffers(head, mode));
+       rc = migrate_page_move_mapping(mapping, newpage, page, mode, 0);
+       if (rc != MIGRATEPAGE_SUCCESS)
+               goto unlock_buffers;
 
        ClearPagePrivate(page);
        set_page_private(newpage, page_private(page));
@@ -811,6 +813,8 @@ int buffer_migrate_page(struct address_space *mapping,
        else
                migrate_page_states(newpage, page);
 
+       rc = MIGRATEPAGE_SUCCESS;
+unlock_buffers:
        bh = head;
        do {
                unlock_buffer(bh);
@@ -819,9 +823,32 @@ int buffer_migrate_page(struct address_space *mapping,
 
        } while (bh != head);
 
-       return MIGRATEPAGE_SUCCESS;
+       return rc;
+}
+
+/*
+ * Migration function for pages with buffers. This function can only be used
+ * if the underlying filesystem guarantees that no other references to "page"
+ * exist. For example attached buffer heads are accessed only under page lock.
+ */
+int buffer_migrate_page(struct address_space *mapping,
+               struct page *newpage, struct page *page, enum migrate_mode mode)
+{
+       return __buffer_migrate_page(mapping, newpage, page, mode, false);
 }
 EXPORT_SYMBOL(buffer_migrate_page);
+
+/*
+ * Same as above except that this variant is more careful and checks that there
+ * are also no buffer head references. This function is the right one for
+ * mappings where buffer heads are directly looked up and referenced (such as
+ * block device mappings).
+ */
+int buffer_migrate_page_norefs(struct address_space *mapping,
+               struct page *newpage, struct page *page, enum migrate_mode mode)
+{
+       return __buffer_migrate_page(mapping, newpage, page, mode, true);
+}
 #endif
 
 /*
@@ -1297,8 +1324,19 @@ static int unmap_and_move_huge_page(new_page_t get_new_page,
                goto put_anon;
 
        if (page_mapped(hpage)) {
+               struct address_space *mapping = page_mapping(hpage);
+
+               /*
+                * try_to_unmap could potentially call huge_pmd_unshare.
+                * Because of this, take semaphore in write mode here and
+                * set TTU_RMAP_LOCKED to let lower levels know we have
+                * taken the lock.
+                */
+               i_mmap_lock_write(mapping);
                try_to_unmap(hpage,
-                       TTU_MIGRATION|TTU_IGNORE_MLOCK|TTU_IGNORE_ACCESS);
+                       TTU_MIGRATION|TTU_IGNORE_MLOCK|TTU_IGNORE_ACCESS|
+                       TTU_RMAP_LOCKED);
+               i_mmap_unlock_write(mapping);
                page_was_mapped = 1;
        }
 
@@ -2303,6 +2341,7 @@ next:
  */
 static void migrate_vma_collect(struct migrate_vma *migrate)
 {
+       struct mmu_notifier_range range;
        struct mm_walk mm_walk;
 
        mm_walk.pmd_entry = migrate_vma_collect_pmd;
@@ -2314,13 +2353,11 @@ static void migrate_vma_collect(struct migrate_vma *migrate)
        mm_walk.mm = migrate->vma->vm_mm;
        mm_walk.private = migrate;
 
-       mmu_notifier_invalidate_range_start(mm_walk.mm,
-                                           migrate->start,
-                                           migrate->end);
+       mmu_notifier_range_init(&range, mm_walk.mm, migrate->start,
+                               migrate->end);
+       mmu_notifier_invalidate_range_start(&range);
        walk_page_range(migrate->start, migrate->end, &mm_walk);
-       mmu_notifier_invalidate_range_end(mm_walk.mm,
-                                         migrate->start,
-                                         migrate->end);
+       mmu_notifier_invalidate_range_end(&range);
 
        migrate->end = migrate->start + (migrate->npages << PAGE_SHIFT);
 }
@@ -2701,9 +2738,8 @@ static void migrate_vma_pages(struct migrate_vma *migrate)
 {
        const unsigned long npages = migrate->npages;
        const unsigned long start = migrate->start;
-       struct vm_area_struct *vma = migrate->vma;
-       struct mm_struct *mm = vma->vm_mm;
-       unsigned long addr, i, mmu_start;
+       struct mmu_notifier_range range;
+       unsigned long addr, i;
        bool notified = false;
 
        for (i = 0, addr = start; i < npages; addr += PAGE_SIZE, i++) {
@@ -2722,11 +2758,12 @@ static void migrate_vma_pages(struct migrate_vma *migrate)
                                continue;
                        }
                        if (!notified) {
-                               mmu_start = addr;
                                notified = true;
-                               mmu_notifier_invalidate_range_start(mm,
-                                                               mmu_start,
-                                                               migrate->end);
+
+                               mmu_notifier_range_init(&range,
+                                                       migrate->vma->vm_mm,
+                                                       addr, migrate->end);
+                               mmu_notifier_invalidate_range_start(&range);
                        }
                        migrate_vma_insert_page(migrate, addr, newpage,
                                                &migrate->src[i],
@@ -2767,8 +2804,7 @@ static void migrate_vma_pages(struct migrate_vma *migrate)
         * did already call it.
         */
        if (notified)
-               mmu_notifier_invalidate_range_only_end(mm, mmu_start,
-                                                      migrate->end);
+               mmu_notifier_invalidate_range_only_end(&range);
 }
 
 /*
index 6838a530789b414bcda3a2fca71747d067760118..33917105a3a28ce4d791fb6d47144d3feef403f2 100644 (file)
@@ -146,7 +146,7 @@ static void __meminit mm_compute_batch(void)
        s32 batch = max_t(s32, nr*2, 32);
 
        /* batch size set to 0.4% of (total memory/#cpus), or max int32 */
-       memsized_batch = min_t(u64, (totalram_pages/nr)/256, 0x7fffffff);
+       memsized_batch = min_t(u64, (totalram_pages()/nr)/256, 0x7fffffff);
 
        vm_committed_as_batch = max_t(s32, memsized_batch, batch);
 }
index 7bb64381e77c09e2af0a3b693a93d5d48659ae7b..f901065c4c64cf63b455497fb993e7c4eacfc184 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -2973,16 +2973,6 @@ out:
        return ret;
 }
 
-static inline void verify_mm_writelocked(struct mm_struct *mm)
-{
-#ifdef CONFIG_DEBUG_VM
-       if (unlikely(down_read_trylock(&mm->mmap_sem))) {
-               WARN_ON(1);
-               up_read(&mm->mmap_sem);
-       }
-#endif
-}
-
 /*
  *  this is really a simplified "do_mmap".  it only handles
  *  anonymous maps.  eventually we may be able to do some
@@ -3009,12 +2999,6 @@ static int do_brk_flags(unsigned long addr, unsigned long len, unsigned long fla
        if (error)
                return error;
 
-       /*
-        * mm->mmap_sem is required to protect against another thread
-        * changing the mappings in case we sleep.
-        */
-       verify_mm_writelocked(mm);
-
        /*
         * Clear old maps.  this also does some error checking for us
         */
index 5119ff8467690f6696c63489e96062ece67c24fa..9c884abc785089d596b13a1edf7520ef0ee4123d 100644 (file)
@@ -35,13 +35,6 @@ void mmu_notifier_call_srcu(struct rcu_head *rcu,
 }
 EXPORT_SYMBOL_GPL(mmu_notifier_call_srcu);
 
-void mmu_notifier_synchronize(void)
-{
-       /* Wait for any running method to finish. */
-       srcu_barrier(&srcu);
-}
-EXPORT_SYMBOL_GPL(mmu_notifier_synchronize);
-
 /*
  * This function can't run concurrently against mmu_notifier_register
  * because mm->mm_users > 0 during mmu_notifier_register and exit_mmap
@@ -174,22 +167,20 @@ void __mmu_notifier_change_pte(struct mm_struct *mm, unsigned long address,
        srcu_read_unlock(&srcu, id);
 }
 
-int __mmu_notifier_invalidate_range_start(struct mm_struct *mm,
-                                 unsigned long start, unsigned long end,
-                                 bool blockable)
+int __mmu_notifier_invalidate_range_start(struct mmu_notifier_range *range)
 {
        struct mmu_notifier *mn;
        int ret = 0;
        int id;
 
        id = srcu_read_lock(&srcu);
-       hlist_for_each_entry_rcu(mn, &mm->mmu_notifier_mm->list, hlist) {
+       hlist_for_each_entry_rcu(mn, &range->mm->mmu_notifier_mm->list, hlist) {
                if (mn->ops->invalidate_range_start) {
-                       int _ret = mn->ops->invalidate_range_start(mn, mm, start, end, blockable);
+                       int _ret = mn->ops->invalidate_range_start(mn, range);
                        if (_ret) {
                                pr_info("%pS callback failed with %d in %sblockable context.\n",
-                                               mn->ops->invalidate_range_start, _ret,
-                                               !blockable ? "non-" : "");
+                                       mn->ops->invalidate_range_start, _ret,
+                                       !range->blockable ? "non-" : "");
                                ret = _ret;
                        }
                }
@@ -200,16 +191,14 @@ int __mmu_notifier_invalidate_range_start(struct mm_struct *mm,
 }
 EXPORT_SYMBOL_GPL(__mmu_notifier_invalidate_range_start);
 
-void __mmu_notifier_invalidate_range_end(struct mm_struct *mm,
-                                        unsigned long start,
-                                        unsigned long end,
+void __mmu_notifier_invalidate_range_end(struct mmu_notifier_range *range,
                                         bool only_end)
 {
        struct mmu_notifier *mn;
        int id;
 
        id = srcu_read_lock(&srcu);
-       hlist_for_each_entry_rcu(mn, &mm->mmu_notifier_mm->list, hlist) {
+       hlist_for_each_entry_rcu(mn, &range->mm->mmu_notifier_mm->list, hlist) {
                /*
                 * Call invalidate_range here too to avoid the need for the
                 * subsystem of having to register an invalidate_range_end
@@ -224,9 +213,11 @@ void __mmu_notifier_invalidate_range_end(struct mm_struct *mm,
                 * already happen under page table lock.
                 */
                if (!only_end && mn->ops->invalidate_range)
-                       mn->ops->invalidate_range(mn, mm, start, end);
+                       mn->ops->invalidate_range(mn, range->mm,
+                                                 range->start,
+                                                 range->end);
                if (mn->ops->invalidate_range_end)
-                       mn->ops->invalidate_range_end(mn, mm, start, end);
+                       mn->ops->invalidate_range_end(mn, range);
        }
        srcu_read_unlock(&srcu, id);
 }
index 6d331620b9e539747d703556be892a75eae65352..36cb358db1702d689a45b8514c987fe83b953242 100644 (file)
@@ -167,11 +167,12 @@ static inline unsigned long change_pmd_range(struct vm_area_struct *vma,
                pgprot_t newprot, int dirty_accountable, int prot_numa)
 {
        pmd_t *pmd;
-       struct mm_struct *mm = vma->vm_mm;
        unsigned long next;
        unsigned long pages = 0;
        unsigned long nr_huge_updates = 0;
-       unsigned long mni_start = 0;
+       struct mmu_notifier_range range;
+
+       range.start = 0;
 
        pmd = pmd_offset(pud, addr);
        do {
@@ -183,9 +184,9 @@ static inline unsigned long change_pmd_range(struct vm_area_struct *vma,
                        goto next;
 
                /* invoke the mmu notifier if the pmd is populated */
-               if (!mni_start) {
-                       mni_start = addr;
-                       mmu_notifier_invalidate_range_start(mm, mni_start, end);
+               if (!range.start) {
+                       mmu_notifier_range_init(&range, vma->vm_mm, addr, end);
+                       mmu_notifier_invalidate_range_start(&range);
                }
 
                if (is_swap_pmd(*pmd) || pmd_trans_huge(*pmd) || pmd_devmap(*pmd)) {
@@ -214,8 +215,8 @@ next:
                cond_resched();
        } while (pmd++, addr = next, addr != end);
 
-       if (mni_start)
-               mmu_notifier_invalidate_range_end(mm, mni_start, end);
+       if (range.start)
+               mmu_notifier_invalidate_range_end(&range);
 
        if (nr_huge_updates)
                count_vm_numa_events(NUMA_HUGE_PTE_UPDATES, nr_huge_updates);
index 7f9f9180e4013084a02fd27390321240af972e3c..def01d86e36fd370f9764a9cdb746f3925fbbf8e 100644 (file)
@@ -197,16 +197,14 @@ unsigned long move_page_tables(struct vm_area_struct *vma,
                bool need_rmap_locks)
 {
        unsigned long extent, next, old_end;
+       struct mmu_notifier_range range;
        pmd_t *old_pmd, *new_pmd;
-       unsigned long mmun_start;       /* For mmu_notifiers */
-       unsigned long mmun_end;         /* For mmu_notifiers */
 
        old_end = old_addr + len;
        flush_cache_range(vma, old_addr, old_end);
 
-       mmun_start = old_addr;
-       mmun_end   = old_end;
-       mmu_notifier_invalidate_range_start(vma->vm_mm, mmun_start, mmun_end);
+       mmu_notifier_range_init(&range, vma->vm_mm, old_addr, old_end);
+       mmu_notifier_invalidate_range_start(&range);
 
        for (; old_addr < old_end; old_addr += extent, new_addr += extent) {
                cond_resched();
@@ -247,7 +245,7 @@ unsigned long move_page_tables(struct vm_area_struct *vma,
                          new_pmd, new_addr, need_rmap_locks);
        }
 
-       mmu_notifier_invalidate_range_end(vma->vm_mm, mmun_start, mmun_end);
+       mmu_notifier_invalidate_range_end(&range);
 
        return len + old_addr - old_end;        /* how much done */
 }
index 6589f60d50186aca3812be1a9ae3d8ba7369b87b..f0e8cd9edb1a875819aca9f72c0c5225e90c590b 100644 (file)
@@ -245,11 +245,11 @@ unsigned long oom_badness(struct task_struct *p, struct mem_cgroup *memcg,
        return points > 0 ? points : 1;
 }
 
-enum oom_constraint {
-       CONSTRAINT_NONE,
-       CONSTRAINT_CPUSET,
-       CONSTRAINT_MEMORY_POLICY,
-       CONSTRAINT_MEMCG,
+static const char * const oom_constraint_text[] = {
+       [CONSTRAINT_NONE] = "CONSTRAINT_NONE",
+       [CONSTRAINT_CPUSET] = "CONSTRAINT_CPUSET",
+       [CONSTRAINT_MEMORY_POLICY] = "CONSTRAINT_MEMORY_POLICY",
+       [CONSTRAINT_MEMCG] = "CONSTRAINT_MEMCG",
 };
 
 /*
@@ -269,7 +269,7 @@ static enum oom_constraint constrained_alloc(struct oom_control *oc)
        }
 
        /* Default to all available memory */
-       oc->totalpages = totalram_pages + total_swap_pages;
+       oc->totalpages = totalram_pages() + total_swap_pages;
 
        if (!IS_ENABLED(CONFIG_NUMA))
                return CONSTRAINT_NONE;
@@ -428,19 +428,29 @@ static void dump_tasks(struct mem_cgroup *memcg, const nodemask_t *nodemask)
        rcu_read_unlock();
 }
 
+static void dump_oom_summary(struct oom_control *oc, struct task_struct *victim)
+{
+       /* one line summary of the oom killer context. */
+       pr_info("oom-kill:constraint=%s,nodemask=%*pbl",
+                       oom_constraint_text[oc->constraint],
+                       nodemask_pr_args(oc->nodemask));
+       cpuset_print_current_mems_allowed();
+       mem_cgroup_print_oom_context(oc->memcg, victim);
+       pr_cont(",task=%s,pid=%d,uid=%d\n", victim->comm, victim->pid,
+               from_kuid(&init_user_ns, task_uid(victim)));
+}
+
 static void dump_header(struct oom_control *oc, struct task_struct *p)
 {
-       pr_warn("%s invoked oom-killer: gfp_mask=%#x(%pGg), nodemask=%*pbl, order=%d, oom_score_adj=%hd\n",
-               current->comm, oc->gfp_mask, &oc->gfp_mask,
-               nodemask_pr_args(oc->nodemask), oc->order,
+       pr_warn("%s invoked oom-killer: gfp_mask=%#x(%pGg), order=%d, oom_score_adj=%hd\n",
+               current->comm, oc->gfp_mask, &oc->gfp_mask, oc->order,
                        current->signal->oom_score_adj);
        if (!IS_ENABLED(CONFIG_COMPACTION) && oc->order)
                pr_warn("COMPACTION is disabled!!!\n");
 
-       cpuset_print_current_mems_allowed();
        dump_stack();
        if (is_memcg_oom(oc))
-               mem_cgroup_print_oom_info(oc->memcg, p);
+               mem_cgroup_print_oom_meminfo(oc->memcg);
        else {
                show_mem(SHOW_MEM_FILTER_NODES, oc->nodemask);
                if (is_dump_unreclaim_slabs())
@@ -448,6 +458,8 @@ static void dump_header(struct oom_control *oc, struct task_struct *p)
        }
        if (sysctl_oom_dump_tasks)
                dump_tasks(oc->memcg, oc->nodemask);
+       if (p)
+               dump_oom_summary(oc, p);
 }
 
 /*
@@ -516,19 +528,20 @@ bool __oom_reap_task_mm(struct mm_struct *mm)
                 * count elevated without a good reason.
                 */
                if (vma_is_anonymous(vma) || !(vma->vm_flags & VM_SHARED)) {
-                       const unsigned long start = vma->vm_start;
-                       const unsigned long end = vma->vm_end;
+                       struct mmu_notifier_range range;
                        struct mmu_gather tlb;
 
-                       tlb_gather_mmu(&tlb, mm, start, end);
-                       if (mmu_notifier_invalidate_range_start_nonblock(mm, start, end)) {
-                               tlb_finish_mmu(&tlb, start, end);
+                       mmu_notifier_range_init(&range, mm, vma->vm_start,
+                                               vma->vm_end);
+                       tlb_gather_mmu(&tlb, mm, range.start, range.end);
+                       if (mmu_notifier_invalidate_range_start_nonblock(&range)) {
+                               tlb_finish_mmu(&tlb, range.start, range.end);
                                ret = false;
                                continue;
                        }
-                       unmap_page_range(&tlb, vma, start, end, NULL);
-                       mmu_notifier_invalidate_range_end(mm, start, end);
-                       tlb_finish_mmu(&tlb, start, end);
+                       unmap_page_range(&tlb, vma, range.start, range.end, NULL);
+                       mmu_notifier_invalidate_range_end(&range);
+                       tlb_finish_mmu(&tlb, range.start, range.end);
                }
        }
 
index 3f690bae6b780304ad31ea04e999a3f377c35991..7d1010453fb95a26c13e9004999d028659815987 100644 (file)
@@ -2154,6 +2154,7 @@ int write_cache_pages(struct address_space *mapping,
 {
        int ret = 0;
        int done = 0;
+       int error;
        struct pagevec pvec;
        int nr_pages;
        pgoff_t uninitialized_var(writeback_index);
@@ -2227,25 +2228,31 @@ continue_unlock:
                                goto continue_unlock;
 
                        trace_wbc_writepage(wbc, inode_to_bdi(mapping->host));
-                       ret = (*writepage)(page, wbc, data);
-                       if (unlikely(ret)) {
-                               if (ret == AOP_WRITEPAGE_ACTIVATE) {
+                       error = (*writepage)(page, wbc, data);
+                       if (unlikely(error)) {
+                               /*
+                                * Handle errors according to the type of
+                                * writeback. There's no need to continue for
+                                * background writeback. Just push done_index
+                                * past this page so media errors won't choke
+                                * writeout for the entire file. For integrity
+                                * writeback, we must process the entire dirty
+                                * set regardless of errors because the fs may
+                                * still have state to clear for each page. In
+                                * that case we continue processing and return
+                                * the first error.
+                                */
+                               if (error == AOP_WRITEPAGE_ACTIVATE) {
                                        unlock_page(page);
-                                       ret = 0;
-                               } else {
-                                       /*
-                                        * done_index is set past this page,
-                                        * so media errors will not choke
-                                        * background writeout for the entire
-                                        * file. This has consequences for
-                                        * range_cyclic semantics (ie. it may
-                                        * not be suitable for data integrity
-                                        * writeout).
-                                        */
+                                       error = 0;
+                               } else if (wbc->sync_mode != WB_SYNC_ALL) {
+                                       ret = error;
                                        done_index = page->index + 1;
                                        done = 1;
                                        break;
                                }
+                               if (!ret)
+                                       ret = error;
                        }
 
                        /*
index e95b5b7c9c3d637efe29d07d86c75975acbfc500..cde5dac6229a7811541ccedab88d408f609df743 100644 (file)
@@ -16,6 +16,7 @@
 
 #include <linux/stddef.h>
 #include <linux/mm.h>
+#include <linux/highmem.h>
 #include <linux/swap.h>
 #include <linux/interrupt.h>
 #include <linux/pagemap.h>
@@ -96,8 +97,12 @@ int _node_numa_mem_[MAX_NUMNODES];
 #endif
 
 /* work_structs for global per-cpu drains */
+struct pcpu_drain {
+       struct zone *zone;
+       struct work_struct work;
+};
 DEFINE_MUTEX(pcpu_drain_mutex);
-DEFINE_PER_CPU(struct work_struct, pcpu_drain);
+DEFINE_PER_CPU(struct pcpu_drain, pcpu_drain);
 
 #ifdef CONFIG_GCC_PLUGIN_LATENT_ENTROPY
 volatile unsigned long latent_entropy __latent_entropy;
@@ -121,10 +126,8 @@ nodemask_t node_states[NR_NODE_STATES] __read_mostly = {
 };
 EXPORT_SYMBOL(node_states);
 
-/* Protect totalram_pages and zone->managed_pages */
-static DEFINE_SPINLOCK(managed_page_count_lock);
-
-unsigned long totalram_pages __read_mostly;
+atomic_long_t _totalram_pages __read_mostly;
+EXPORT_SYMBOL(_totalram_pages);
 unsigned long totalreserve_pages __read_mostly;
 unsigned long totalcma_pages __read_mostly;
 
@@ -237,7 +240,7 @@ static char * const zone_names[MAX_NR_ZONES] = {
 #endif
 };
 
-char * const migratetype_names[MIGRATE_TYPES] = {
+const char * const migratetype_names[MIGRATE_TYPES] = {
        "Unmovable",
        "Movable",
        "Reclaimable",
@@ -263,20 +266,21 @@ compound_page_dtor * const compound_page_dtors[] = {
 
 int min_free_kbytes = 1024;
 int user_min_free_kbytes = -1;
+int watermark_boost_factor __read_mostly = 15000;
 int watermark_scale_factor = 10;
 
-static unsigned long nr_kernel_pages __meminitdata;
-static unsigned long nr_all_pages __meminitdata;
-static unsigned long dma_reserve __meminitdata;
+static unsigned long nr_kernel_pages __initdata;
+static unsigned long nr_all_pages __initdata;
+static unsigned long dma_reserve __initdata;
 
 #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
-static unsigned long arch_zone_lowest_possible_pfn[MAX_NR_ZONES] __meminitdata;
-static unsigned long arch_zone_highest_possible_pfn[MAX_NR_ZONES] __meminitdata;
+static unsigned long arch_zone_lowest_possible_pfn[MAX_NR_ZONES] __initdata;
+static unsigned long arch_zone_highest_possible_pfn[MAX_NR_ZONES] __initdata;
 static unsigned long required_kernelcore __initdata;
 static unsigned long required_kernelcore_percent __initdata;
 static unsigned long required_movablecore __initdata;
 static unsigned long required_movablecore_percent __initdata;
-static unsigned long zone_movable_pfn[MAX_NUMNODES] __meminitdata;
+static unsigned long zone_movable_pfn[MAX_NUMNODES] __initdata;
 static bool mirrored_kernelcore __meminitdata;
 
 /* movable_zone is the "real" zone pages in ZONE_MOVABLE are taken from */
@@ -294,6 +298,32 @@ EXPORT_SYMBOL(nr_online_nodes);
 int page_group_by_mobility_disabled __read_mostly;
 
 #ifdef CONFIG_DEFERRED_STRUCT_PAGE_INIT
+/*
+ * During boot we initialize deferred pages on-demand, as needed, but once
+ * page_alloc_init_late() has finished, the deferred pages are all initialized,
+ * and we can permanently disable that path.
+ */
+static DEFINE_STATIC_KEY_TRUE(deferred_pages);
+
+/*
+ * Calling kasan_free_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.
+ *
+ * Assuming that there will be no reference to those newly initialized
+ * pages before they are ever allocated, this should have no effect on
+ * KASAN memory tracking as the poison will be properly inserted at page
+ * allocation time. The only corner case is when pages are allocated by
+ * 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)
+{
+       if (!static_branch_unlikely(&deferred_pages))
+               kasan_free_pages(page, order);
+}
+
 /* Returns true if the struct page for the pfn is uninitialised */
 static inline bool __meminit early_page_uninitialised(unsigned long pfn)
 {
@@ -326,8 +356,13 @@ defer_init(int nid, unsigned long pfn, unsigned long end_pfn)
        /* Always populate low zones for address-constrained allocations */
        if (end_pfn < pgdat_end_pfn(NODE_DATA(nid)))
                return false;
+
+       /*
+        * We start only with one section of pages, more pages are added as
+        * needed until the rest of deferred pages are initialized.
+        */
        nr_initialised++;
-       if ((nr_initialised > NODE_DATA(nid)->static_init_pgcnt) &&
+       if ((nr_initialised > PAGES_PER_SECTION) &&
            (pfn & (PAGES_PER_SECTION - 1)) == 0) {
                NODE_DATA(nid)->first_deferred_pfn = pfn;
                return true;
@@ -335,6 +370,8 @@ defer_init(int nid, unsigned long pfn, unsigned long end_pfn)
        return false;
 }
 #else
+#define kasan_free_nondeferred_pages(p, o)     kasan_free_pages(p, o)
+
 static inline bool early_page_uninitialised(unsigned long pfn)
 {
        return false;
@@ -426,6 +463,7 @@ void set_pfnblock_flags_mask(struct page *page, unsigned long flags,
        unsigned long old_word, word;
 
        BUILD_BUG_ON(NR_PAGEBLOCK_BITS != 4);
+       BUILD_BUG_ON(MIGRATE_TYPES > (1 << PB_migratetype_bits));
 
        bitmap = get_pageblock_bitmap(page, pfn);
        bitidx = pfn_to_bitidx(page, pfn);
@@ -1037,7 +1075,7 @@ static __always_inline bool free_pages_prepare(struct page *page,
        arch_free_page(page, order);
        kernel_poison_pages(page, 1 << order, 0);
        kernel_map_pages(page, 1 << order, 0);
-       kasan_free_pages(page, order);
+       kasan_free_nondeferred_pages(page, order);
 
        return true;
 }
@@ -1183,6 +1221,7 @@ static void __meminit __init_single_page(struct page *page, unsigned long pfn,
        init_page_count(page);
        page_mapcount_reset(page);
        page_cpupid_reset_last(page);
+       page_kasan_tag_reset(page);
 
        INIT_LIST_HEAD(&page->lru);
 #ifdef WANT_PAGE_VIRTUAL
@@ -1279,7 +1318,7 @@ static void __init __free_pages_boot_core(struct page *page, unsigned int order)
        __ClearPageReserved(p);
        set_page_count(p, 0);
 
-       page_zone(page)->managed_pages += nr_pages;
+       atomic_long_add(nr_pages, &page_zone(page)->managed_pages);
        set_page_refcounted(page);
        __free_pages(page, order);
 }
@@ -1605,13 +1644,6 @@ static int __init deferred_init_memmap(void *data)
        return 0;
 }
 
-/*
- * During boot we initialize deferred pages on-demand, as needed, but once
- * page_alloc_init_late() has finished, the deferred pages are all initialized,
- * and we can permanently disable that path.
- */
-static DEFINE_STATIC_KEY_TRUE(deferred_pages);
-
 /*
  * If this zone has deferred pages, try to grow it by initializing enough
  * deferred pages to satisfy the allocation specified by order, rounded up to
@@ -1981,8 +2013,8 @@ struct page *__rmqueue_smallest(struct zone *zone, unsigned int order,
  */
 static int fallbacks[MIGRATE_TYPES][4] = {
        [MIGRATE_UNMOVABLE]   = { MIGRATE_RECLAIMABLE, MIGRATE_MOVABLE,   MIGRATE_TYPES },
-       [MIGRATE_RECLAIMABLE] = { MIGRATE_UNMOVABLE,   MIGRATE_MOVABLE,   MIGRATE_TYPES },
        [MIGRATE_MOVABLE]     = { MIGRATE_RECLAIMABLE, MIGRATE_UNMOVABLE, MIGRATE_TYPES },
+       [MIGRATE_RECLAIMABLE] = { MIGRATE_UNMOVABLE,   MIGRATE_MOVABLE,   MIGRATE_TYPES },
 #ifdef CONFIG_CMA
        [MIGRATE_CMA]         = { MIGRATE_TYPES }, /* Never used */
 #endif
@@ -2129,6 +2161,21 @@ static bool can_steal_fallback(unsigned int order, int start_mt)
        return false;
 }
 
+static inline void boost_watermark(struct zone *zone)
+{
+       unsigned long max_boost;
+
+       if (!watermark_boost_factor)
+               return;
+
+       max_boost = mult_frac(zone->_watermark[WMARK_HIGH],
+                       watermark_boost_factor, 10000);
+       max_boost = max(pageblock_nr_pages, max_boost);
+
+       zone->watermark_boost = min(zone->watermark_boost + pageblock_nr_pages,
+               max_boost);
+}
+
 /*
  * This function implements actual steal behaviour. If order is large enough,
  * we can steal whole pageblock. If not, we first move freepages in this
@@ -2138,7 +2185,7 @@ static bool can_steal_fallback(unsigned int order, int start_mt)
  * itself, so pages freed in the future will be put on the correct free list.
  */
 static void steal_suitable_fallback(struct zone *zone, struct page *page,
-                                       int start_type, bool whole_block)
+               unsigned int alloc_flags, int start_type, bool whole_block)
 {
        unsigned int current_order = page_order(page);
        struct free_area *area;
@@ -2160,6 +2207,15 @@ static void steal_suitable_fallback(struct zone *zone, struct page *page,
                goto single_page;
        }
 
+       /*
+        * Boost watermarks to increase reclaim pressure to reduce the
+        * likelihood of future fallbacks. Wake kswapd now as the node
+        * may be balanced overall and kswapd will not wake naturally.
+        */
+       boost_watermark(zone);
+       if (alloc_flags & ALLOC_KSWAPD)
+               wakeup_kswapd(zone, 0, 0, zone_idx(zone));
+
        /* We are not allowed to try stealing from the whole block */
        if (!whole_block)
                goto single_page;
@@ -2258,7 +2314,7 @@ static void reserve_highatomic_pageblock(struct page *page, struct zone *zone,
         * Limit the number reserved to 1 pageblock or roughly 1% of a zone.
         * Check is race-prone but harmless.
         */
-       max_managed = (zone->managed_pages / 100) + pageblock_nr_pages;
+       max_managed = (zone_managed_pages(zone) / 100) + pageblock_nr_pages;
        if (zone->nr_reserved_highatomic >= max_managed)
                return;
 
@@ -2375,20 +2431,30 @@ static bool unreserve_highatomic_pageblock(const struct alloc_context *ac,
  * condition simpler.
  */
 static __always_inline bool
-__rmqueue_fallback(struct zone *zone, int order, int start_migratetype)
+__rmqueue_fallback(struct zone *zone, int order, int start_migratetype,
+                                               unsigned int alloc_flags)
 {
        struct free_area *area;
        int current_order;
+       int min_order = order;
        struct page *page;
        int fallback_mt;
        bool can_steal;
 
+       /*
+        * Do not steal pages from freelists belonging to other pageblocks
+        * i.e. orders < pageblock_order. If there are no local zones free,
+        * the zonelists will be reiterated without ALLOC_NOFRAGMENT.
+        */
+       if (alloc_flags & ALLOC_NOFRAGMENT)
+               min_order = pageblock_order;
+
        /*
         * Find the largest available free page in the other list. This roughly
         * approximates finding the pageblock with the most free pages, which
         * would be too costly to do exactly.
         */
-       for (current_order = MAX_ORDER - 1; current_order >= order;
+       for (current_order = MAX_ORDER - 1; current_order >= min_order;
                                --current_order) {
                area = &(zone->free_area[current_order]);
                fallback_mt = find_suitable_fallback(area, current_order,
@@ -2433,7 +2499,8 @@ do_steal:
        page = list_first_entry(&area->free_list[fallback_mt],
                                                        struct page, lru);
 
-       steal_suitable_fallback(zone, page, start_migratetype, can_steal);
+       steal_suitable_fallback(zone, page, alloc_flags, start_migratetype,
+                                                               can_steal);
 
        trace_mm_page_alloc_extfrag(page, order, current_order,
                start_migratetype, fallback_mt);
@@ -2447,7 +2514,8 @@ do_steal:
  * Call me with the zone->lock already held.
  */
 static __always_inline struct page *
-__rmqueue(struct zone *zone, unsigned int order, int migratetype)
+__rmqueue(struct zone *zone, unsigned int order, int migratetype,
+                                               unsigned int alloc_flags)
 {
        struct page *page;
 
@@ -2457,7 +2525,8 @@ retry:
                if (migratetype == MIGRATE_MOVABLE)
                        page = __rmqueue_cma_fallback(zone, order);
 
-               if (!page && __rmqueue_fallback(zone, order, migratetype))
+               if (!page && __rmqueue_fallback(zone, order, migratetype,
+                                                               alloc_flags))
                        goto retry;
        }
 
@@ -2472,13 +2541,14 @@ retry:
  */
 static int rmqueue_bulk(struct zone *zone, unsigned int order,
                        unsigned long count, struct list_head *list,
-                       int migratetype)
+                       int migratetype, unsigned int alloc_flags)
 {
        int i, alloced = 0;
 
        spin_lock(&zone->lock);
        for (i = 0; i < count; ++i) {
-               struct page *page = __rmqueue(zone, order, migratetype);
+               struct page *page = __rmqueue(zone, order, migratetype,
+                                                               alloc_flags);
                if (unlikely(page == NULL))
                        break;
 
@@ -2592,6 +2662,10 @@ void drain_local_pages(struct zone *zone)
 
 static void drain_local_pages_wq(struct work_struct *work)
 {
+       struct pcpu_drain *drain;
+
+       drain = container_of(work, struct pcpu_drain, work);
+
        /*
         * drain_all_pages doesn't use proper cpu hotplug protection so
         * we can race with cpu offline when the WQ can move this from
@@ -2600,7 +2674,7 @@ static void drain_local_pages_wq(struct work_struct *work)
         * a different one.
         */
        preempt_disable();
-       drain_local_pages(NULL);
+       drain_local_pages(drain->zone);
        preempt_enable();
 }
 
@@ -2671,12 +2745,14 @@ void drain_all_pages(struct zone *zone)
        }
 
        for_each_cpu(cpu, &cpus_with_pcps) {
-               struct work_struct *work = per_cpu_ptr(&pcpu_drain, cpu);
-               INIT_WORK(work, drain_local_pages_wq);
-               queue_work_on(cpu, mm_percpu_wq, work);
+               struct pcpu_drain *drain = per_cpu_ptr(&pcpu_drain, cpu);
+
+               drain->zone = zone;
+               INIT_WORK(&drain->work, drain_local_pages_wq);
+               queue_work_on(cpu, mm_percpu_wq, &drain->work);
        }
        for_each_cpu(cpu, &cpus_with_pcps)
-               flush_work(per_cpu_ptr(&pcpu_drain, cpu));
+               flush_work(&per_cpu_ptr(&pcpu_drain, cpu)->work);
 
        mutex_unlock(&pcpu_drain_mutex);
 }
@@ -2934,6 +3010,7 @@ static inline void zone_statistics(struct zone *preferred_zone, struct zone *z)
 
 /* Remove page from the per-cpu list, caller must protect the list */
 static struct page *__rmqueue_pcplist(struct zone *zone, int migratetype,
+                       unsigned int alloc_flags,
                        struct per_cpu_pages *pcp,
                        struct list_head *list)
 {
@@ -2943,7 +3020,7 @@ static struct page *__rmqueue_pcplist(struct zone *zone, int migratetype,
                if (list_empty(list)) {
                        pcp->count += rmqueue_bulk(zone, 0,
                                        pcp->batch, list,
-                                       migratetype);
+                                       migratetype, alloc_flags);
                        if (unlikely(list_empty(list)))
                                return NULL;
                }
@@ -2959,7 +3036,8 @@ static struct page *__rmqueue_pcplist(struct zone *zone, int migratetype,
 /* Lock and remove page from the per-cpu list */
 static struct page *rmqueue_pcplist(struct zone *preferred_zone,
                        struct zone *zone, unsigned int order,
-                       gfp_t gfp_flags, int migratetype)
+                       gfp_t gfp_flags, int migratetype,
+                       unsigned int alloc_flags)
 {
        struct per_cpu_pages *pcp;
        struct list_head *list;
@@ -2969,7 +3047,7 @@ static struct page *rmqueue_pcplist(struct zone *preferred_zone,
        local_irq_save(flags);
        pcp = &this_cpu_ptr(zone->pageset)->pcp;
        list = &pcp->lists[migratetype];
-       page = __rmqueue_pcplist(zone,  migratetype, pcp, list);
+       page = __rmqueue_pcplist(zone,  migratetype, alloc_flags, pcp, list);
        if (page) {
                __count_zid_vm_events(PGALLOC, page_zonenum(page), 1 << order);
                zone_statistics(preferred_zone, zone);
@@ -2992,7 +3070,7 @@ struct page *rmqueue(struct zone *preferred_zone,
 
        if (likely(order == 0)) {
                page = rmqueue_pcplist(preferred_zone, zone, order,
-                               gfp_flags, migratetype);
+                               gfp_flags, migratetype, alloc_flags);
                goto out;
        }
 
@@ -3011,7 +3089,7 @@ struct page *rmqueue(struct zone *preferred_zone,
                                trace_mm_page_alloc_zone_locked(page, order, migratetype);
                }
                if (!page)
-                       page = __rmqueue(zone, order, migratetype);
+                       page = __rmqueue(zone, order, migratetype, alloc_flags);
        } while (page && check_new_pages(page, order));
        spin_unlock(&zone->lock);
        if (!page)
@@ -3053,7 +3131,7 @@ static int __init setup_fail_page_alloc(char *str)
 }
 __setup("fail_page_alloc=", setup_fail_page_alloc);
 
-static bool should_fail_alloc_page(gfp_t gfp_mask, unsigned int order)
+static bool __should_fail_alloc_page(gfp_t gfp_mask, unsigned int order)
 {
        if (order < fail_page_alloc.min_order)
                return false;
@@ -3103,13 +3181,19 @@ late_initcall(fail_page_alloc_debugfs);
 
 #else /* CONFIG_FAIL_PAGE_ALLOC */
 
-static inline bool should_fail_alloc_page(gfp_t gfp_mask, unsigned int order)
+static inline bool __should_fail_alloc_page(gfp_t gfp_mask, unsigned int order)
 {
        return false;
 }
 
 #endif /* CONFIG_FAIL_PAGE_ALLOC */
 
+static noinline bool should_fail_alloc_page(gfp_t gfp_mask, unsigned int order)
+{
+       return __should_fail_alloc_page(gfp_mask, order);
+}
+ALLOW_ERROR_INJECTION(should_fail_alloc_page, TRUE);
+
 /*
  * Return true if free base pages are above 'mark'. For high-order checks it
  * will return true of the order-0 watermark is reached and there is at least
@@ -3253,6 +3337,40 @@ static bool zone_allows_reclaim(struct zone *local_zone, struct zone *zone)
 }
 #endif /* CONFIG_NUMA */
 
+/*
+ * The restriction on ZONE_DMA32 as being a suitable zone to use to avoid
+ * fragmentation is subtle. If the preferred zone was HIGHMEM then
+ * premature use of a lower zone may cause lowmem pressure problems that
+ * are worse than fragmentation. If the next zone is ZONE_DMA then it is
+ * probably too small. It only makes sense to spread allocations to avoid
+ * fragmentation between the Normal and DMA32 zones.
+ */
+static inline unsigned int
+alloc_flags_nofragment(struct zone *zone, gfp_t gfp_mask)
+{
+       unsigned int alloc_flags = 0;
+
+       if (gfp_mask & __GFP_KSWAPD_RECLAIM)
+               alloc_flags |= ALLOC_KSWAPD;
+
+#ifdef CONFIG_ZONE_DMA32
+       if (zone_idx(zone) != ZONE_NORMAL)
+               goto out;
+
+       /*
+        * If ZONE_DMA32 exists, assume it is the one after ZONE_NORMAL and
+        * the pointer is within zone->zone_pgdat->node_zones[]. Also assume
+        * on UMA that if Normal is populated then so is DMA32.
+        */
+       BUILD_BUG_ON(ZONE_NORMAL - ZONE_DMA32 != 1);
+       if (nr_online_nodes > 1 && !populated_zone(--zone))
+               goto out;
+
+out:
+#endif /* CONFIG_ZONE_DMA32 */
+       return alloc_flags;
+}
+
 /*
  * get_page_from_freelist goes through the zonelist trying to allocate
  * a page.
@@ -3261,14 +3379,18 @@ static struct page *
 get_page_from_freelist(gfp_t gfp_mask, unsigned int order, int alloc_flags,
                                                const struct alloc_context *ac)
 {
-       struct zoneref *z = ac->preferred_zoneref;
+       struct zoneref *z;
        struct zone *zone;
        struct pglist_data *last_pgdat_dirty_limit = NULL;
+       bool no_fallback;
 
+retry:
        /*
         * Scan zonelist, looking for a zone with enough free.
         * See also __cpuset_node_allowed() comment in kernel/cpuset.c.
         */
+       no_fallback = alloc_flags & ALLOC_NOFRAGMENT;
+       z = ac->preferred_zoneref;
        for_next_zone_zonelist_nodemask(zone, z, ac->zonelist, ac->high_zoneidx,
                                                                ac->nodemask) {
                struct page *page;
@@ -3307,7 +3429,23 @@ get_page_from_freelist(gfp_t gfp_mask, unsigned int order, int alloc_flags,
                        }
                }
 
-               mark = zone->watermark[alloc_flags & ALLOC_WMARK_MASK];
+               if (no_fallback && nr_online_nodes > 1 &&
+                   zone != ac->preferred_zoneref->zone) {
+                       int local_nid;
+
+                       /*
+                        * If moving to a remote node, retry but allow
+                        * fragmenting fallbacks. Locality is more important
+                        * than fragmentation avoidance.
+                        */
+                       local_nid = zone_to_nid(ac->preferred_zoneref->zone);
+                       if (zone_to_nid(zone) != local_nid) {
+                               alloc_flags &= ~ALLOC_NOFRAGMENT;
+                               goto retry;
+                       }
+               }
+
+               mark = wmark_pages(zone, alloc_flags & ALLOC_WMARK_MASK);
                if (!zone_watermark_fast(zone, order, mark,
                                       ac_classzone_idx(ac), alloc_flags)) {
                        int ret;
@@ -3374,6 +3512,15 @@ try_this_zone:
                }
        }
 
+       /*
+        * It's possible on a UMA machine to get through all zones that are
+        * fragmented. If avoiding fragmentation, reset and try again.
+        */
+       if (no_fallback) {
+               alloc_flags &= ~ALLOC_NOFRAGMENT;
+               goto retry;
+       }
+
        return NULL;
 }
 
@@ -3413,13 +3560,13 @@ void warn_alloc(gfp_t gfp_mask, nodemask_t *nodemask, const char *fmt, ...)
        va_start(args, fmt);
        vaf.fmt = fmt;
        vaf.va = &args;
-       pr_warn("%s: %pV, mode:%#x(%pGg), nodemask=%*pbl\n",
+       pr_warn("%s: %pV, mode:%#x(%pGg), nodemask=%*pbl",
                        current->comm, &vaf, gfp_mask, &gfp_mask,
                        nodemask_pr_args(nodemask));
        va_end(args);
 
        cpuset_print_current_mems_allowed();
-
+       pr_cont("\n");
        dump_stack();
        warn_alloc_show_mem(gfp_mask, nodemask);
 }
@@ -3861,6 +4008,9 @@ gfp_to_alloc_flags(gfp_t gfp_mask)
        } else if (unlikely(rt_task(current)) && !in_interrupt())
                alloc_flags |= ALLOC_HARDER;
 
+       if (gfp_mask & __GFP_KSWAPD_RECLAIM)
+               alloc_flags |= ALLOC_KSWAPD;
+
 #ifdef CONFIG_CMA
        if (gfpflags_to_migratetype(gfp_mask) == MIGRATE_MOVABLE)
                alloc_flags |= ALLOC_CMA;
@@ -4092,7 +4242,7 @@ retry_cpuset:
        if (!ac->preferred_zoneref->zone)
                goto nopage;
 
-       if (gfp_mask & __GFP_KSWAPD_RECLAIM)
+       if (alloc_flags & ALLOC_KSWAPD)
                wake_all_kswapds(order, gfp_mask, ac);
 
        /*
@@ -4150,7 +4300,7 @@ retry_cpuset:
 
 retry:
        /* Ensure kswapd doesn't accidentally go to sleep as long as we loop */
-       if (gfp_mask & __GFP_KSWAPD_RECLAIM)
+       if (alloc_flags & ALLOC_KSWAPD)
                wake_all_kswapds(order, gfp_mask, ac);
 
        reserve_flags = __gfp_pfmemalloc_flags(gfp_mask);
@@ -4369,6 +4519,12 @@ __alloc_pages_nodemask(gfp_t gfp_mask, unsigned int order, int preferred_nid,
 
        finalise_ac(gfp_mask, &ac);
 
+       /*
+        * Forbid the first pass from falling back to types that fragment
+        * memory until all local zones are considered.
+        */
+       alloc_flags |= alloc_flags_nofragment(ac.preferred_zoneref->zone, gfp_mask);
+
        /* First allocation attempt */
        page = get_page_from_freelist(alloc_mask, order, alloc_flags, &ac);
        if (likely(page))
@@ -4427,16 +4583,19 @@ unsigned long get_zeroed_page(gfp_t gfp_mask)
 }
 EXPORT_SYMBOL(get_zeroed_page);
 
-void __free_pages(struct page *page, unsigned int order)
+static inline void free_the_page(struct page *page, unsigned int order)
 {
-       if (put_page_testzero(page)) {
-               if (order == 0)
-                       free_unref_page(page);
-               else
-                       __free_pages_ok(page, order);
-       }
+       if (order == 0)         /* Via pcp? */
+               free_unref_page(page);
+       else
+               __free_pages_ok(page, order);
 }
 
+void __free_pages(struct page *page, unsigned int order)
+{
+       if (put_page_testzero(page))
+               free_the_page(page, order);
+}
 EXPORT_SYMBOL(__free_pages);
 
 void free_pages(unsigned long addr, unsigned int order)
@@ -4485,14 +4644,8 @@ void __page_frag_cache_drain(struct page *page, unsigned int count)
 {
        VM_BUG_ON_PAGE(page_ref_count(page) == 0, page);
 
-       if (page_ref_sub_and_test(page, count)) {
-               unsigned int order = compound_order(page);
-
-               if (order == 0)
-                       free_unref_page(page);
-               else
-                       __free_pages_ok(page, order);
-       }
+       if (page_ref_sub_and_test(page, count))
+               free_the_page(page, compound_order(page));
 }
 EXPORT_SYMBOL(__page_frag_cache_drain);
 
@@ -4558,7 +4711,7 @@ void page_frag_free(void *addr)
        struct page *page = virt_to_head_page(addr);
 
        if (unlikely(put_page_testzero(page)))
-               __free_pages_ok(page, compound_order(page));
+               free_the_page(page, compound_order(page));
 }
 EXPORT_SYMBOL(page_frag_free);
 
@@ -4660,7 +4813,7 @@ static unsigned long nr_free_zone_pages(int offset)
        struct zonelist *zonelist = node_zonelist(numa_node_id(), GFP_KERNEL);
 
        for_each_zone_zonelist(zone, z, zonelist, offset) {
-               unsigned long size = zone->managed_pages;
+               unsigned long size = zone_managed_pages(zone);
                unsigned long high = high_wmark_pages(zone);
                if (size > high)
                        sum += size - high;
@@ -4712,7 +4865,7 @@ long si_mem_available(void)
                pages[lru] = global_node_page_state(NR_LRU_BASE + lru);
 
        for_each_zone(zone)
-               wmark_low += zone->watermark[WMARK_LOW];
+               wmark_low += low_wmark_pages(zone);
 
        /*
         * Estimate the amount of memory available for userspace allocations,
@@ -4746,11 +4899,11 @@ EXPORT_SYMBOL_GPL(si_mem_available);
 
 void si_meminfo(struct sysinfo *val)
 {
-       val->totalram = totalram_pages;
+       val->totalram = totalram_pages();
        val->sharedram = global_node_page_state(NR_SHMEM);
        val->freeram = global_zone_page_state(NR_FREE_PAGES);
        val->bufferram = nr_blockdev_pages();
-       val->totalhigh = totalhigh_pages;
+       val->totalhigh = totalhigh_pages();
        val->freehigh = nr_free_highpages();
        val->mem_unit = PAGE_SIZE;
 }
@@ -4767,7 +4920,7 @@ void si_meminfo_node(struct sysinfo *val, int nid)
        pg_data_t *pgdat = NODE_DATA(nid);
 
        for (zone_type = 0; zone_type < MAX_NR_ZONES; zone_type++)
-               managed_pages += pgdat->node_zones[zone_type].managed_pages;
+               managed_pages += zone_managed_pages(&pgdat->node_zones[zone_type]);
        val->totalram = managed_pages;
        val->sharedram = node_page_state(pgdat, NR_SHMEM);
        val->freeram = sum_zone_node_page_state(nid, NR_FREE_PAGES);
@@ -4776,7 +4929,7 @@ void si_meminfo_node(struct sysinfo *val, int nid)
                struct zone *zone = &pgdat->node_zones[zone_type];
 
                if (is_highmem(zone)) {
-                       managed_highpages += zone->managed_pages;
+                       managed_highpages += zone_managed_pages(zone);
                        free_highpages += zone_page_state(zone, NR_FREE_PAGES);
                }
        }
@@ -4983,7 +5136,7 @@ void show_free_areas(unsigned int filter, nodemask_t *nodemask)
                        K(zone_page_state(zone, NR_ZONE_UNEVICTABLE)),
                        K(zone_page_state(zone, NR_ZONE_WRITE_PENDING)),
                        K(zone->present_pages),
-                       K(zone->managed_pages),
+                       K(zone_managed_pages(zone)),
                        K(zone_page_state(zone, NR_MLOCK)),
                        zone_page_state(zone, NR_KERNEL_STACK_KB),
                        K(zone_page_state(zone, NR_PAGETABLE)),
@@ -5655,7 +5808,7 @@ static int zone_batchsize(struct zone *zone)
         * The per-cpu-pages pools are set to around 1000th of the
         * size of the zone.
         */
-       batch = zone->managed_pages / 1024;
+       batch = zone_managed_pages(zone) / 1024;
        /* But no more than a meg. */
        if (batch * PAGE_SIZE > 1024 * 1024)
                batch = (1024 * 1024) / PAGE_SIZE;
@@ -5736,7 +5889,6 @@ static void pageset_init(struct per_cpu_pageset *p)
        memset(p, 0, sizeof(*p));
 
        pcp = &p->pcp;
-       pcp->count = 0;
        for (migratetype = 0; migratetype < MIGRATE_PCPTYPES; migratetype++)
                INIT_LIST_HEAD(&pcp->lists[migratetype]);
 }
@@ -5766,7 +5918,7 @@ static void pageset_set_high_and_batch(struct zone *zone,
 {
        if (percpu_pagelist_fraction)
                pageset_set_high(pcp,
-                       (zone->managed_pages /
+                       (zone_managed_pages(zone) /
                                percpu_pagelist_fraction));
        else
                pageset_set_batch(pcp, zone_batchsize(zone));
@@ -5920,7 +6072,7 @@ void __init sparse_memory_present_with_active_regions(int nid)
  * with no available memory, a warning is printed and the start and end
  * PFNs will be 0.
  */
-void __meminit get_pfn_range_for_nid(unsigned int nid,
+void __init get_pfn_range_for_nid(unsigned int nid,
                        unsigned long *start_pfn, unsigned long *end_pfn)
 {
        unsigned long this_start_pfn, this_end_pfn;
@@ -5969,7 +6121,7 @@ static void __init find_usable_zone_for_movable(void)
  * highest usable zone for ZONE_MOVABLE. This preserves the assumption that
  * zones within a node are in order of monotonic increases memory addresses
  */
-static void __meminit adjust_zone_range_for_zone_movable(int nid,
+static void __init adjust_zone_range_for_zone_movable(int nid,
                                        unsigned long zone_type,
                                        unsigned long node_start_pfn,
                                        unsigned long node_end_pfn,
@@ -6000,7 +6152,7 @@ static void __meminit adjust_zone_range_for_zone_movable(int nid,
  * Return the number of pages a zone spans in a node, including holes
  * present_pages = zone_spanned_pages_in_node() - zone_absent_pages_in_node()
  */
-static unsigned long __meminit zone_spanned_pages_in_node(int nid,
+static unsigned long __init zone_spanned_pages_in_node(int nid,
                                        unsigned long zone_type,
                                        unsigned long node_start_pfn,
                                        unsigned long node_end_pfn,
@@ -6035,7 +6187,7 @@ static unsigned long __meminit zone_spanned_pages_in_node(int nid,
  * Return the number of holes in a range on a node. If nid is MAX_NUMNODES,
  * then all holes in the requested range will be accounted for.
  */
-unsigned long __meminit __absent_pages_in_range(int nid,
+unsigned long __init __absent_pages_in_range(int nid,
                                unsigned long range_start_pfn,
                                unsigned long range_end_pfn)
 {
@@ -6065,7 +6217,7 @@ unsigned long __init absent_pages_in_range(unsigned long start_pfn,
 }
 
 /* Return the number of page frames in holes in a zone on a node */
-static unsigned long __meminit zone_absent_pages_in_node(int nid,
+static unsigned long __init zone_absent_pages_in_node(int nid,
                                        unsigned long zone_type,
                                        unsigned long node_start_pfn,
                                        unsigned long node_end_pfn,
@@ -6117,7 +6269,7 @@ static unsigned long __meminit zone_absent_pages_in_node(int nid,
 }
 
 #else /* CONFIG_HAVE_MEMBLOCK_NODE_MAP */
-static inline unsigned long __meminit zone_spanned_pages_in_node(int nid,
+static inline unsigned long __init zone_spanned_pages_in_node(int nid,
                                        unsigned long zone_type,
                                        unsigned long node_start_pfn,
                                        unsigned long node_end_pfn,
@@ -6136,7 +6288,7 @@ static inline unsigned long __meminit zone_spanned_pages_in_node(int nid,
        return zones_size[zone_type];
 }
 
-static inline unsigned long __meminit zone_absent_pages_in_node(int nid,
+static inline unsigned long __init zone_absent_pages_in_node(int nid,
                                                unsigned long zone_type,
                                                unsigned long node_start_pfn,
                                                unsigned long node_end_pfn,
@@ -6150,7 +6302,7 @@ static inline unsigned long __meminit zone_absent_pages_in_node(int nid,
 
 #endif /* CONFIG_HAVE_MEMBLOCK_NODE_MAP */
 
-static void __meminit calculate_node_totalpages(struct pglist_data *pgdat,
+static void __init calculate_node_totalpages(struct pglist_data *pgdat,
                                                unsigned long node_start_pfn,
                                                unsigned long node_end_pfn,
                                                unsigned long *zones_size,
@@ -6323,7 +6475,7 @@ static void __meminit pgdat_init_internals(struct pglist_data *pgdat)
 static void __meminit zone_init_internals(struct zone *zone, enum zone_type idx, int nid,
                                                        unsigned long remaining_pages)
 {
-       zone->managed_pages = remaining_pages;
+       atomic_long_set(&zone->managed_pages, remaining_pages);
        zone_set_nid(zone, nid);
        zone->name = zone_names[idx];
        zone->zone_pgdat = NODE_DATA(nid);
@@ -6476,12 +6628,6 @@ static void __ref alloc_node_mem_map(struct pglist_data *pgdat) { }
 #ifdef CONFIG_DEFERRED_STRUCT_PAGE_INIT
 static inline void pgdat_set_deferred_range(pg_data_t *pgdat)
 {
-       /*
-        * We start only with one section of pages, more pages are added as
-        * needed until the rest of deferred pages are initialized.
-        */
-       pgdat->static_init_pgcnt = min_t(unsigned long, PAGES_PER_SECTION,
-                                               pgdat->node_spanned_pages);
        pgdat->first_deferred_pfn = ULONG_MAX;
 }
 #else
@@ -7075,18 +7221,16 @@ early_param("movablecore", cmdline_parse_movablecore);
 
 void adjust_managed_page_count(struct page *page, long count)
 {
-       spin_lock(&managed_page_count_lock);
-       page_zone(page)->managed_pages += count;
-       totalram_pages += count;
+       atomic_long_add(count, &page_zone(page)->managed_pages);
+       totalram_pages_add(count);
 #ifdef CONFIG_HIGHMEM
        if (PageHighMem(page))
-               totalhigh_pages += count;
+               totalhigh_pages_add(count);
 #endif
-       spin_unlock(&managed_page_count_lock);
 }
 EXPORT_SYMBOL(adjust_managed_page_count);
 
-unsigned long free_reserved_area(void *start, void *end, int poison, char *s)
+unsigned long free_reserved_area(void *start, void *end, int poison, const char *s)
 {
        void *pos;
        unsigned long pages = 0;
@@ -7123,9 +7267,9 @@ EXPORT_SYMBOL(free_reserved_area);
 void free_highmem_page(struct page *page)
 {
        __free_reserved_page(page);
-       totalram_pages++;
-       page_zone(page)->managed_pages++;
-       totalhigh_pages++;
+       totalram_pages_inc();
+       atomic_long_inc(&page_zone(page)->managed_pages);
+       totalhigh_pages_inc();
 }
 #endif
 
@@ -7174,10 +7318,10 @@ void __init mem_init_print_info(const char *str)
                physpages << (PAGE_SHIFT - 10),
                codesize >> 10, datasize >> 10, rosize >> 10,
                (init_data_size + init_code_size) >> 10, bss_size >> 10,
-               (physpages - totalram_pages - totalcma_pages) << (PAGE_SHIFT - 10),
+               (physpages - totalram_pages() - totalcma_pages) << (PAGE_SHIFT - 10),
                totalcma_pages << (PAGE_SHIFT - 10),
 #ifdef CONFIG_HIGHMEM
-               totalhigh_pages << (PAGE_SHIFT - 10),
+               totalhigh_pages() << (PAGE_SHIFT - 10),
 #endif
                str ? ", " : "", str ? str : "");
 }
@@ -7257,6 +7401,7 @@ static void calculate_totalreserve_pages(void)
                for (i = 0; i < MAX_NR_ZONES; i++) {
                        struct zone *zone = pgdat->node_zones + i;
                        long max = 0;
+                       unsigned long managed_pages = zone_managed_pages(zone);
 
                        /* Find valid and maximum lowmem_reserve in the zone */
                        for (j = i; j < MAX_NR_ZONES; j++) {
@@ -7267,8 +7412,8 @@ static void calculate_totalreserve_pages(void)
                        /* we treat the high watermark as reserved pages. */
                        max += high_wmark_pages(zone);
 
-                       if (max > zone->managed_pages)
-                               max = zone->managed_pages;
+                       if (max > managed_pages)
+                               max = managed_pages;
 
                        pgdat->totalreserve_pages += max;
 
@@ -7292,7 +7437,7 @@ static void setup_per_zone_lowmem_reserve(void)
        for_each_online_pgdat(pgdat) {
                for (j = 0; j < MAX_NR_ZONES; j++) {
                        struct zone *zone = pgdat->node_zones + j;
-                       unsigned long managed_pages = zone->managed_pages;
+                       unsigned long managed_pages = zone_managed_pages(zone);
 
                        zone->lowmem_reserve[j] = 0;
 
@@ -7310,7 +7455,7 @@ static void setup_per_zone_lowmem_reserve(void)
                                        lower_zone->lowmem_reserve[j] =
                                                managed_pages / sysctl_lowmem_reserve_ratio[idx];
                                }
-                               managed_pages += lower_zone->managed_pages;
+                               managed_pages += zone_managed_pages(lower_zone);
                        }
                }
        }
@@ -7329,14 +7474,14 @@ static void __setup_per_zone_wmarks(void)
        /* Calculate total number of !ZONE_HIGHMEM pages */
        for_each_zone(zone) {
                if (!is_highmem(zone))
-                       lowmem_pages += zone->managed_pages;
+                       lowmem_pages += zone_managed_pages(zone);
        }
 
        for_each_zone(zone) {
                u64 tmp;
 
                spin_lock_irqsave(&zone->lock, flags);
-               tmp = (u64)pages_min * zone->managed_pages;
+               tmp = (u64)pages_min * zone_managed_pages(zone);
                do_div(tmp, lowmem_pages);
                if (is_highmem(zone)) {
                        /*
@@ -7350,15 +7495,15 @@ static void __setup_per_zone_wmarks(void)
                         */
                        unsigned long min_pages;
 
-                       min_pages = zone->managed_pages / 1024;
+                       min_pages = zone_managed_pages(zone) / 1024;
                        min_pages = clamp(min_pages, SWAP_CLUSTER_MAX, 128UL);
-                       zone->watermark[WMARK_MIN] = min_pages;
+                       zone->_watermark[WMARK_MIN] = min_pages;
                } else {
                        /*
                         * If it's a lowmem zone, reserve a number of pages
                         * proportionate to the zone's size.
                         */
-                       zone->watermark[WMARK_MIN] = tmp;
+                       zone->_watermark[WMARK_MIN] = tmp;
                }
 
                /*
@@ -7367,11 +7512,12 @@ static void __setup_per_zone_wmarks(void)
                 * ensure a minimum size on small systems.
                 */
                tmp = max_t(u64, tmp >> 2,
-                           mult_frac(zone->managed_pages,
+                           mult_frac(zone_managed_pages(zone),
                                      watermark_scale_factor, 10000));
 
-               zone->watermark[WMARK_LOW]  = min_wmark_pages(zone) + tmp;
-               zone->watermark[WMARK_HIGH] = min_wmark_pages(zone) + tmp * 2;
+               zone->_watermark[WMARK_LOW]  = min_wmark_pages(zone) + tmp;
+               zone->_watermark[WMARK_HIGH] = min_wmark_pages(zone) + tmp * 2;
+               zone->watermark_boost = 0;
 
                spin_unlock_irqrestore(&zone->lock, flags);
        }
@@ -7472,6 +7618,18 @@ int min_free_kbytes_sysctl_handler(struct ctl_table *table, int write,
        return 0;
 }
 
+int watermark_boost_factor_sysctl_handler(struct ctl_table *table, int write,
+       void __user *buffer, size_t *length, loff_t *ppos)
+{
+       int rc;
+
+       rc = proc_dointvec_minmax(table, write, buffer, length, ppos);
+       if (rc)
+               return rc;
+
+       return 0;
+}
+
 int watermark_scale_factor_sysctl_handler(struct ctl_table *table, int write,
        void __user *buffer, size_t *length, loff_t *ppos)
 {
@@ -7497,8 +7655,8 @@ static void setup_min_unmapped_ratio(void)
                pgdat->min_unmapped_pages = 0;
 
        for_each_zone(zone)
-               zone->zone_pgdat->min_unmapped_pages += (zone->managed_pages *
-                               sysctl_min_unmapped_ratio) / 100;
+               zone->zone_pgdat->min_unmapped_pages += (zone_managed_pages(zone) *
+                                                        sysctl_min_unmapped_ratio) / 100;
 }
 
 
@@ -7525,8 +7683,8 @@ static void setup_min_slab_ratio(void)
                pgdat->min_slab_pages = 0;
 
        for_each_zone(zone)
-               zone->zone_pgdat->min_slab_pages += (zone->managed_pages *
-                               sysctl_min_slab_ratio) / 100;
+               zone->zone_pgdat->min_slab_pages += (zone_managed_pages(zone) *
+                                                    sysctl_min_slab_ratio) / 100;
 }
 
 int sysctl_min_slab_ratio_sysctl_handler(struct ctl_table *table, int write,
@@ -7766,8 +7924,7 @@ void *__init alloc_large_system_hash(const char *tablename,
  * race condition. So you can't expect this function should be exact.
  */
 bool has_unmovable_pages(struct zone *zone, struct page *page, int count,
-                        int migratetype,
-                        bool skip_hwpoisoned_pages)
+                        int migratetype, int flags)
 {
        unsigned long pfn, iter, found;
 
@@ -7841,7 +7998,7 @@ bool has_unmovable_pages(struct zone *zone, struct page *page, int count,
                 * The HWPoisoned page may be not in buddy system, and
                 * page_count() is not 0.
                 */
-               if (skip_hwpoisoned_pages && PageHWPoison(page))
+               if ((flags & SKIP_HWPOISON) && PageHWPoison(page))
                        continue;
 
                if (__PageMovable(page))
@@ -7868,6 +8025,8 @@ bool has_unmovable_pages(struct zone *zone, struct page *page, int count,
        return false;
 unmovable:
        WARN_ON_ONCE(zone_idx(zone) == ZONE_MOVABLE);
+       if (flags & REPORT_FAILURE)
+               dump_page(pfn_to_page(pfn+iter), "unmovable page");
        return true;
 }
 
@@ -7994,8 +8153,7 @@ int alloc_contig_range(unsigned long start, unsigned long end,
         */
 
        ret = start_isolate_page_range(pfn_max_align_down(start),
-                                      pfn_max_align_up(end), migratetype,
-                                      false);
+                                      pfn_max_align_up(end), migratetype, 0);
        if (ret)
                return ret;
 
index 43e0856088467551ae6bb71090d89469ebe3fb8d..ce323e56b34d6bc43a9e16cc9054f35290bb0b63 100644 (file)
@@ -15,8 +15,7 @@
 #define CREATE_TRACE_POINTS
 #include <trace/events/page_isolation.h>
 
-static int set_migratetype_isolate(struct page *page, int migratetype,
-                               bool skip_hwpoisoned_pages)
+static int set_migratetype_isolate(struct page *page, int migratetype, int isol_flags)
 {
        struct zone *zone;
        unsigned long flags, pfn;
@@ -60,8 +59,7 @@ static int set_migratetype_isolate(struct page *page, int migratetype,
         * FIXME: Now, memory hotplug doesn't call shrink_slab() by itself.
         * We just check MOVABLE pages.
         */
-       if (!has_unmovable_pages(zone, page, arg.pages_found, migratetype,
-                                skip_hwpoisoned_pages))
+       if (!has_unmovable_pages(zone, page, arg.pages_found, migratetype, flags))
                ret = 0;
 
        /*
@@ -185,7 +183,7 @@ __first_valid_page(unsigned long pfn, unsigned long nr_pages)
  * prevents two threads from simultaneously working on overlapping ranges.
  */
 int start_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn,
-                            unsigned migratetype, bool skip_hwpoisoned_pages)
+                            unsigned migratetype, int flags)
 {
        unsigned long pfn;
        unsigned long undo_pfn;
@@ -199,7 +197,7 @@ int start_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn,
             pfn += pageblock_nr_pages) {
                page = __first_valid_page(pfn, pageblock_nr_pages);
                if (page &&
-                   set_migratetype_isolate(page, migratetype, skip_hwpoisoned_pages)) {
+                   set_migratetype_isolate(page, migratetype, flags)) {
                        undo_pfn = pfn;
                        goto undo;
                }
index 87bc0dfdb52b679c19856d19878f2a5838ac3b55..28b06524939fa853307307469c76ac76d7955304 100644 (file)
@@ -351,6 +351,7 @@ print_page_owner(char __user *buf, size_t count, unsigned long pfn,
                .skip = 0
        };
 
+       count = min_t(size_t, count, PAGE_SIZE);
        kbuf = kmalloc(count, GFP_KERNEL);
        if (!kbuf)
                return -ENOMEM;
index f3d6f9656a3cc83c93420210dd938b8d0b54648e..1ae16522412aee1430f112aa0fdf33e63b0c75ad 100644 (file)
@@ -270,17 +270,15 @@ static unsigned long get_init_ra_size(unsigned long size, unsigned long max)
  *  return it as the new window size.
  */
 static unsigned long get_next_ra_size(struct file_ra_state *ra,
-                                               unsigned long max)
+                                     unsigned long max)
 {
        unsigned long cur = ra->size;
-       unsigned long newsize;
 
        if (cur < max / 16)
-               newsize = 4 * cur;
-       else
-               newsize = 2 * cur;
-
-       return min(newsize, max);
+               return 4 * cur;
+       if (cur <= max / 2)
+               return 2 * cur;
+       return max;
 }
 
 /*
index 85b7f94233526acc1863539caae49b6e640b3434..21a26cf51114282330c18c5064deaab230bea770 100644 (file)
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -25,6 +25,7 @@
  *     page->flags PG_locked (lock_page)
  *       hugetlbfs_i_mmap_rwsem_key (in huge_pmd_share)
  *         mapping->i_mmap_rwsem
+ *           hugetlb_fault_mutex (hugetlbfs specific page fault mutex)
  *           anon_vma->rwsem
  *             mm->page_table_lock or pte_lock
  *               zone_lru_lock (in mark_page_accessed, isolate_lru_page)
@@ -889,15 +890,17 @@ static bool page_mkclean_one(struct page *page, struct vm_area_struct *vma,
                .address = address,
                .flags = PVMW_SYNC,
        };
-       unsigned long start = address, end;
+       struct mmu_notifier_range range;
        int *cleaned = arg;
 
        /*
         * We have to assume the worse case ie pmd for invalidation. Note that
         * the page can not be free from this function.
         */
-       end = min(vma->vm_end, start + (PAGE_SIZE << compound_order(page)));
-       mmu_notifier_invalidate_range_start(vma->vm_mm, start, end);
+       mmu_notifier_range_init(&range, vma->vm_mm, address,
+                               min(vma->vm_end, address +
+                                   (PAGE_SIZE << compound_order(page))));
+       mmu_notifier_invalidate_range_start(&range);
 
        while (page_vma_mapped_walk(&pvmw)) {
                unsigned long cstart;
@@ -949,7 +952,7 @@ static bool page_mkclean_one(struct page *page, struct vm_area_struct *vma,
                        (*cleaned)++;
        }
 
-       mmu_notifier_invalidate_range_end(vma->vm_mm, start, end);
+       mmu_notifier_invalidate_range_end(&range);
 
        return true;
 }
@@ -1017,7 +1020,7 @@ void page_move_anon_rmap(struct page *page, struct vm_area_struct *vma)
 
 /**
  * __page_set_anon_rmap - set up new anonymous rmap
- * @page:      Page to add to rmap     
+ * @page:      Page or Hugepage to add to rmap
  * @vma:       VM area to add page to.
  * @address:   User virtual address of the mapping     
  * @exclusive: the page is exclusively owned by the current process
@@ -1345,7 +1348,7 @@ static bool try_to_unmap_one(struct page *page, struct vm_area_struct *vma,
        pte_t pteval;
        struct page *subpage;
        bool ret = true;
-       unsigned long start = address, end;
+       struct mmu_notifier_range range;
        enum ttu_flags flags = (enum ttu_flags)arg;
 
        /* munlock has nothing to gain from examining un-locked vmas */
@@ -1369,15 +1372,21 @@ static bool try_to_unmap_one(struct page *page, struct vm_area_struct *vma,
         * Note that the page can not be free in this function as call of
         * try_to_unmap() must hold a reference on the page.
         */
-       end = min(vma->vm_end, start + (PAGE_SIZE << compound_order(page)));
+       mmu_notifier_range_init(&range, vma->vm_mm, vma->vm_start,
+                               min(vma->vm_end, vma->vm_start +
+                                   (PAGE_SIZE << compound_order(page))));
        if (PageHuge(page)) {
                /*
                 * If sharing is possible, start and end will be adjusted
                 * accordingly.
+                *
+                * If called for a huge page, caller must hold i_mmap_rwsem
+                * in write mode as it is possible to call huge_pmd_unshare.
                 */
-               adjust_range_if_pmd_sharing_possible(vma, &start, &end);
+               adjust_range_if_pmd_sharing_possible(vma, &range.start,
+                                                    &range.end);
        }
-       mmu_notifier_invalidate_range_start(vma->vm_mm, start, end);
+       mmu_notifier_invalidate_range_start(&range);
 
        while (page_vma_mapped_walk(&pvmw)) {
 #ifdef CONFIG_ARCH_ENABLE_THP_MIGRATION
@@ -1428,9 +1437,10 @@ static bool try_to_unmap_one(struct page *page, struct vm_area_struct *vma,
                                 * we must flush them all.  start/end were
                                 * already adjusted above to cover this range.
                                 */
-                               flush_cache_range(vma, start, end);
-                               flush_tlb_range(vma, start, end);
-                               mmu_notifier_invalidate_range(mm, start, end);
+                               flush_cache_range(vma, range.start, range.end);
+                               flush_tlb_range(vma, range.start, range.end);
+                               mmu_notifier_invalidate_range(mm, range.start,
+                                                             range.end);
 
                                /*
                                 * The ref count of the PMD page was dropped
@@ -1650,7 +1660,7 @@ discard:
                put_page(page);
        }
 
-       mmu_notifier_invalidate_range_end(vma->vm_mm, start, end);
+       mmu_notifier_invalidate_range_end(&range);
 
        return ret;
 }
@@ -1910,27 +1920,10 @@ void rmap_walk_locked(struct page *page, struct rmap_walk_control *rwc)
 
 #ifdef CONFIG_HUGETLB_PAGE
 /*
- * The following three functions are for anonymous (private mapped) hugepages.
+ * The following two functions are for anonymous (private mapped) hugepages.
  * Unlike common anonymous pages, anonymous hugepages have no accounting code
  * and no lru code, because we handle hugepages differently from common pages.
  */
-static void __hugepage_set_anon_rmap(struct page *page,
-       struct vm_area_struct *vma, unsigned long address, int exclusive)
-{
-       struct anon_vma *anon_vma = vma->anon_vma;
-
-       BUG_ON(!anon_vma);
-
-       if (PageAnon(page))
-               return;
-       if (!exclusive)
-               anon_vma = anon_vma->root;
-
-       anon_vma = (void *) anon_vma + PAGE_MAPPING_ANON;
-       page->mapping = (struct address_space *) anon_vma;
-       page->index = linear_page_index(vma, address);
-}
-
 void hugepage_add_anon_rmap(struct page *page,
                            struct vm_area_struct *vma, unsigned long address)
 {
@@ -1942,7 +1935,7 @@ void hugepage_add_anon_rmap(struct page *page,
        /* address might be in next vma when migration races vma_adjust */
        first = atomic_inc_and_test(compound_mapcount_ptr(page));
        if (first)
-               __hugepage_set_anon_rmap(page, vma, address, 0);
+               __page_set_anon_rmap(page, vma, address, 0);
 }
 
 void hugepage_add_new_anon_rmap(struct page *page,
@@ -1950,6 +1943,6 @@ void hugepage_add_new_anon_rmap(struct page *page,
 {
        BUG_ON(address < vma->vm_start || address >= vma->vm_end);
        atomic_set(compound_mapcount_ptr(page), 0);
-       __hugepage_set_anon_rmap(page, vma, address, 1);
+       __page_set_anon_rmap(page, vma, address, 1);
 }
 #endif /* CONFIG_HUGETLB_PAGE */
index 375f3ac19bb88c9cd3b132cf0ffc14e84ff771dd..6ece1e2fe76eb6b6670fc95fc9cf50d294e821cc 100644 (file)
@@ -109,12 +109,14 @@ struct shmem_falloc {
 #ifdef CONFIG_TMPFS
 static unsigned long shmem_default_max_blocks(void)
 {
-       return totalram_pages / 2;
+       return totalram_pages() / 2;
 }
 
 static unsigned long shmem_default_max_inodes(void)
 {
-       return min(totalram_pages - totalhigh_pages, totalram_pages / 2);
+       unsigned long nr_pages = totalram_pages();
+
+       return min(nr_pages - totalhigh_pages(), nr_pages / 2);
 }
 #endif
 
@@ -3301,7 +3303,7 @@ static int shmem_parse_options(char *options, struct shmem_sb_info *sbinfo,
                        size = memparse(value,&rest);
                        if (*rest == '%') {
                                size <<= PAGE_SHIFT;
-                               size *= totalram_pages;
+                               size *= totalram_pages();
                                do_div(size, 100);
                                rest++;
                        }
index 3abb9feb3818e5459f4ce658469e835582025b10..73fe23e649c91abb135cd930a48475021b9f54d2 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -406,19 +406,6 @@ static inline void *index_to_obj(struct kmem_cache *cache, struct page *page,
        return page->s_mem + cache->size * idx;
 }
 
-/*
- * We want to avoid an expensive divide : (offset / cache->size)
- *   Using the fact that size is a constant for a particular cache,
- *   we can replace (offset / cache->size) by
- *   reciprocal_divide(offset, cache->reciprocal_buffer_size)
- */
-static inline unsigned int obj_to_index(const struct kmem_cache *cache,
-                                       const struct page *page, void *obj)
-{
-       u32 offset = (obj - page->s_mem);
-       return reciprocal_divide(offset, cache->reciprocal_buffer_size);
-}
-
 #define BOOT_CPUCACHE_ENTRIES  1
 /* internal cache of cache description objs */
 static struct kmem_cache kmem_cache_boot = {
@@ -1248,7 +1235,7 @@ void __init kmem_cache_init(void)
         * page orders on machines with more than 32MB of memory if
         * not overridden on the command line.
         */
-       if (!slab_max_order_set && totalram_pages > (32 << 20) >> PAGE_SHIFT)
+       if (!slab_max_order_set && totalram_pages() > (32 << 20) >> PAGE_SHIFT)
                slab_max_order = SLAB_MAX_ORDER_HI;
 
        /* Bootstrap is tricky, because several objects are allocated
@@ -2370,7 +2357,7 @@ static void *alloc_slabmgmt(struct kmem_cache *cachep,
        void *freelist;
        void *addr = page_address(page);
 
-       page->s_mem = addr + colour_off;
+       page->s_mem = kasan_reset_tag(addr) + colour_off;
        page->active = 0;
 
        if (OBJFREELIST_SLAB(cachep))
@@ -2574,7 +2561,7 @@ static void cache_init_objs(struct kmem_cache *cachep,
 
        for (i = 0; i < cachep->num; i++) {
                objp = index_to_obj(cachep, page, i);
-               kasan_init_slab_obj(cachep, objp);
+               objp = kasan_init_slab_obj(cachep, objp);
 
                /* constructor could break poison info */
                if (DEBUG == 0 && cachep->ctor) {
@@ -3551,7 +3538,7 @@ void *kmem_cache_alloc(struct kmem_cache *cachep, gfp_t flags)
 {
        void *ret = slab_alloc(cachep, flags, _RET_IP_);
 
-       kasan_slab_alloc(cachep, ret, flags);
+       ret = kasan_slab_alloc(cachep, ret, flags);
        trace_kmem_cache_alloc(_RET_IP_, ret,
                               cachep->object_size, cachep->size, flags);
 
@@ -3617,7 +3604,7 @@ kmem_cache_alloc_trace(struct kmem_cache *cachep, gfp_t flags, size_t size)
 
        ret = slab_alloc(cachep, flags, _RET_IP_);
 
-       kasan_kmalloc(cachep, ret, size, flags);
+       ret = kasan_kmalloc(cachep, ret, size, flags);
        trace_kmalloc(_RET_IP_, ret,
                      size, cachep->size, flags);
        return ret;
@@ -3641,7 +3628,7 @@ void *kmem_cache_alloc_node(struct kmem_cache *cachep, gfp_t flags, int nodeid)
 {
        void *ret = slab_alloc_node(cachep, flags, nodeid, _RET_IP_);
 
-       kasan_slab_alloc(cachep, ret, flags);
+       ret = kasan_slab_alloc(cachep, ret, flags);
        trace_kmem_cache_alloc_node(_RET_IP_, ret,
                                    cachep->object_size, cachep->size,
                                    flags, nodeid);
@@ -3660,7 +3647,7 @@ void *kmem_cache_alloc_node_trace(struct kmem_cache *cachep,
 
        ret = slab_alloc_node(cachep, flags, nodeid, _RET_IP_);
 
-       kasan_kmalloc(cachep, ret, size, flags);
+       ret = kasan_kmalloc(cachep, ret, size, flags);
        trace_kmalloc_node(_RET_IP_, ret,
                           size, cachep->size,
                           flags, nodeid);
@@ -3681,7 +3668,7 @@ __do_kmalloc_node(size_t size, gfp_t flags, int node, unsigned long caller)
        if (unlikely(ZERO_OR_NULL_PTR(cachep)))
                return cachep;
        ret = kmem_cache_alloc_node_trace(cachep, flags, node, size);
-       kasan_kmalloc(cachep, ret, size, flags);
+       ret = kasan_kmalloc(cachep, ret, size, flags);
 
        return ret;
 }
@@ -3719,7 +3706,7 @@ static __always_inline void *__do_kmalloc(size_t size, gfp_t flags,
                return cachep;
        ret = slab_alloc(cachep, flags, caller);
 
-       kasan_kmalloc(cachep, ret, size, flags);
+       ret = kasan_kmalloc(cachep, ret, size, flags);
        trace_kmalloc(caller, ret,
                      size, cachep->size, flags);
 
index 58c6c1c2a78ee39f08ace4d4fe6493e4e0911781..4190c24ef0e9dfcce2463f950f750e6c251d7bac 100644 (file)
--- a/mm/slab.h
+++ b/mm/slab.h
@@ -441,7 +441,7 @@ static inline void slab_post_alloc_hook(struct kmem_cache *s, gfp_t flags,
 
                kmemleak_alloc_recursive(object, s->object_size, 1,
                                         s->flags, flags);
-               kasan_slab_alloc(s, object, flags);
+               p[i] = kasan_slab_alloc(s, object, flags);
        }
 
        if (memcg_kmem_enabled())
index 9c11e8a937d2e419b0b89532bfe75d80a25f7fe2..70b0cc85db67f8fcf6f7c78aac745c453624e8e7 100644 (file)
@@ -1029,10 +1029,8 @@ struct kmem_cache *kmalloc_slab(size_t size, gfp_t flags)
 
                index = size_index[size_index_elem(size)];
        } else {
-               if (unlikely(size > KMALLOC_MAX_CACHE_SIZE)) {
-                       WARN_ON(1);
+               if (WARN_ON_ONCE(size > KMALLOC_MAX_CACHE_SIZE))
                        return NULL;
-               }
                index = fls(size - 1);
        }
 
@@ -1204,7 +1202,7 @@ void *kmalloc_order(size_t size, gfp_t flags, unsigned int order)
        page = alloc_pages(flags, order);
        ret = page ? page_address(page) : NULL;
        kmemleak_alloc(ret, size, 1, flags);
-       kasan_kmalloc_large(ret, size, flags);
+       ret = kasan_kmalloc_large(ret, size, flags);
        return ret;
 }
 EXPORT_SYMBOL(kmalloc_order);
@@ -1482,7 +1480,7 @@ static __always_inline void *__do_krealloc(const void *p, size_t new_size,
                ks = ksize(p);
 
        if (ks >= new_size) {
-               kasan_krealloc((void *)p, new_size, flags);
+               p = kasan_krealloc((void *)p, new_size, flags);
                return (void *)p;
        }
 
@@ -1534,7 +1532,7 @@ void *krealloc(const void *p, size_t new_size, gfp_t flags)
        }
 
        ret = __do_krealloc(p, new_size, flags);
-       if (ret && p != ret)
+       if (ret && kasan_reset_tag(p) != kasan_reset_tag(ret))
                kfree(p);
 
        return ret;
index e3629cd7aff1640854ffa30b50ac012f8c78ff68..36c0befeebd8083187f6b869f1aa975d23ee6651 100644 (file)
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -1372,10 +1372,10 @@ static inline void dec_slabs_node(struct kmem_cache *s, int node,
  * Hooks for other subsystems that check memory allocations. In a typical
  * production configuration these hooks all should produce no code at all.
  */
-static inline void kmalloc_large_node_hook(void *ptr, size_t size, gfp_t flags)
+static inline void *kmalloc_large_node_hook(void *ptr, size_t size, gfp_t flags)
 {
        kmemleak_alloc(ptr, size, 1, flags);
-       kasan_kmalloc_large(ptr, size, flags);
+       return kasan_kmalloc_large(ptr, size, flags);
 }
 
 static __always_inline void kfree_hook(void *x)
@@ -1451,16 +1451,17 @@ static inline bool slab_free_freelist_hook(struct kmem_cache *s,
 #endif
 }
 
-static void setup_object(struct kmem_cache *s, struct page *page,
+static void *setup_object(struct kmem_cache *s, struct page *page,
                                void *object)
 {
        setup_object_debug(s, page, object);
-       kasan_init_slab_obj(s, object);
+       object = kasan_init_slab_obj(s, object);
        if (unlikely(s->ctor)) {
                kasan_unpoison_object_data(s, object);
                s->ctor(object);
                kasan_poison_object_data(s, object);
        }
+       return object;
 }
 
 /*
@@ -1568,16 +1569,16 @@ static bool shuffle_freelist(struct kmem_cache *s, struct page *page)
        /* First entry is used as the base of the freelist */
        cur = next_freelist_entry(s, page, &pos, start, page_limit,
                                freelist_count);
+       cur = setup_object(s, page, cur);
        page->freelist = cur;
 
        for (idx = 1; idx < page->objects; idx++) {
-               setup_object(s, page, cur);
                next = next_freelist_entry(s, page, &pos, start, page_limit,
                        freelist_count);
+               next = setup_object(s, page, next);
                set_freepointer(s, cur, next);
                cur = next;
        }
-       setup_object(s, page, cur);
        set_freepointer(s, cur, NULL);
 
        return true;
@@ -1599,7 +1600,7 @@ static struct page *allocate_slab(struct kmem_cache *s, gfp_t flags, int node)
        struct page *page;
        struct kmem_cache_order_objects oo = s->oo;
        gfp_t alloc_gfp;
-       void *start, *p;
+       void *start, *p, *next;
        int idx, order;
        bool shuffle;
 
@@ -1651,13 +1652,16 @@ static struct page *allocate_slab(struct kmem_cache *s, gfp_t flags, int node)
 
        if (!shuffle) {
                for_each_object_idx(p, idx, s, start, page->objects) {
-                       setup_object(s, page, p);
-                       if (likely(idx < page->objects))
-                               set_freepointer(s, p, p + s->size);
-                       else
+                       if (likely(idx < page->objects)) {
+                               next = p + s->size;
+                               next = setup_object(s, page, next);
+                               set_freepointer(s, p, next);
+                       } else
                                set_freepointer(s, p, NULL);
                }
-               page->freelist = fixup_red_left(s, start);
+               start = fixup_red_left(s, start);
+               start = setup_object(s, page, start);
+               page->freelist = start;
        }
 
        page->inuse = page->objects;
@@ -2127,26 +2131,15 @@ redo:
        }
 
        if (l != m) {
-
                if (l == M_PARTIAL)
-
                        remove_partial(n, page);
-
                else if (l == M_FULL)
-
                        remove_full(s, n, page);
 
-               if (m == M_PARTIAL) {
-
+               if (m == M_PARTIAL)
                        add_partial(n, page, tail);
-                       stat(s, tail);
-
-               } else if (m == M_FULL) {
-
-                       stat(s, DEACTIVATE_FULL);
+               else if (m == M_FULL)
                        add_full(s, n, page);
-
-               }
        }
 
        l = m;
@@ -2159,7 +2152,11 @@ redo:
        if (lock)
                spin_unlock(&n->list_lock);
 
-       if (m == M_FREE) {
+       if (m == M_PARTIAL)
+               stat(s, tail);
+       else if (m == M_FULL)
+               stat(s, DEACTIVATE_FULL);
+       else if (m == M_FREE) {
                stat(s, DEACTIVATE_EMPTY);
                discard_slab(s, page);
                stat(s, FREE_SLAB);
@@ -2313,12 +2310,10 @@ static inline void __flush_cpu_slab(struct kmem_cache *s, int cpu)
 {
        struct kmem_cache_cpu *c = per_cpu_ptr(s->cpu_slab, cpu);
 
-       if (likely(c)) {
-               if (c->page)
-                       flush_slab(s, c);
+       if (c->page)
+               flush_slab(s, c);
 
-               unfreeze_partials(s, c);
-       }
+       unfreeze_partials(s, c);
 }
 
 static void flush_cpu_slab(void *d)
@@ -2367,7 +2362,7 @@ static int slub_cpu_dead(unsigned int cpu)
 static inline int node_match(struct page *page, int node)
 {
 #ifdef CONFIG_NUMA
-       if (!page || (node != NUMA_NO_NODE && page_to_nid(page) != node))
+       if (node != NUMA_NO_NODE && page_to_nid(page) != node)
                return 0;
 #endif
        return 1;
@@ -2768,7 +2763,7 @@ void *kmem_cache_alloc_trace(struct kmem_cache *s, gfp_t gfpflags, size_t size)
 {
        void *ret = slab_alloc(s, gfpflags, _RET_IP_);
        trace_kmalloc(_RET_IP_, ret, size, s->size, gfpflags);
-       kasan_kmalloc(s, ret, size, gfpflags);
+       ret = kasan_kmalloc(s, ret, size, gfpflags);
        return ret;
 }
 EXPORT_SYMBOL(kmem_cache_alloc_trace);
@@ -2796,7 +2791,7 @@ void *kmem_cache_alloc_node_trace(struct kmem_cache *s,
        trace_kmalloc_node(_RET_IP_, ret,
                           size, s->size, gfpflags, node);
 
-       kasan_kmalloc(s, ret, size, gfpflags);
+       ret = kasan_kmalloc(s, ret, size, gfpflags);
        return ret;
 }
 EXPORT_SYMBOL(kmem_cache_alloc_node_trace);
@@ -2992,7 +2987,7 @@ static __always_inline void slab_free(struct kmem_cache *s, struct page *page,
                do_slab_free(s, page, head, tail, cnt, addr);
 }
 
-#ifdef CONFIG_KASAN
+#ifdef CONFIG_KASAN_GENERIC
 void ___cache_free(struct kmem_cache *cache, void *x, unsigned long addr)
 {
        do_slab_free(cache, virt_to_head_page(x), x, NULL, 1, addr);
@@ -3364,16 +3359,16 @@ static void early_kmem_cache_node_alloc(int node)
 
        n = page->freelist;
        BUG_ON(!n);
-       page->freelist = get_freepointer(kmem_cache_node, n);
-       page->inuse = 1;
-       page->frozen = 0;
-       kmem_cache_node->node[node] = n;
 #ifdef CONFIG_SLUB_DEBUG
        init_object(kmem_cache_node, n, SLUB_RED_ACTIVE);
        init_tracking(kmem_cache_node, n);
 #endif
-       kasan_kmalloc(kmem_cache_node, n, sizeof(struct kmem_cache_node),
+       n = kasan_kmalloc(kmem_cache_node, n, sizeof(struct kmem_cache_node),
                      GFP_KERNEL);
+       page->freelist = get_freepointer(kmem_cache_node, n);
+       page->inuse = 1;
+       page->frozen = 0;
+       kmem_cache_node->node[node] = n;
        init_kmem_cache_node(n);
        inc_slabs_node(kmem_cache_node, node, page->objects);
 
@@ -3784,7 +3779,7 @@ void *__kmalloc(size_t size, gfp_t flags)
 
        trace_kmalloc(_RET_IP_, ret, size, s->size, flags);
 
-       kasan_kmalloc(s, ret, size, flags);
+       ret = kasan_kmalloc(s, ret, size, flags);
 
        return ret;
 }
@@ -3801,8 +3796,7 @@ static void *kmalloc_large_node(size_t size, gfp_t flags, int node)
        if (page)
                ptr = page_address(page);
 
-       kmalloc_large_node_hook(ptr, size, flags);
-       return ptr;
+       return kmalloc_large_node_hook(ptr, size, flags);
 }
 
 void *__kmalloc_node(size_t size, gfp_t flags, int node)
@@ -3829,7 +3823,7 @@ void *__kmalloc_node(size_t size, gfp_t flags, int node)
 
        trace_kmalloc_node(_RET_IP_, ret, size, s->size, flags, node);
 
-       kasan_kmalloc(s, ret, size, flags);
+       ret = kasan_kmalloc(s, ret, size, flags);
 
        return ret;
 }
index 3abc8cc5020120a3bbeb7c3429d19472fc96d051..7ea5dc6c6b19a1a4fc86432b7a1cce1ca6ea5301 100644 (file)
@@ -678,25 +678,24 @@ static void free_map_bootmem(struct page *memmap)
  * set.  If this is <=0, then that means that the passed-in
  * map was not consumed and must be freed.
  */
-int __meminit sparse_add_one_section(struct pglist_data *pgdat,
-               unsigned long start_pfn, struct vmem_altmap *altmap)
+int __meminit sparse_add_one_section(int nid, unsigned long start_pfn,
+                                    struct vmem_altmap *altmap)
 {
        unsigned long section_nr = pfn_to_section_nr(start_pfn);
        struct mem_section *ms;
        struct page *memmap;
        unsigned long *usemap;
-       unsigned long flags;
        int ret;
 
        /*
         * no locking for this, because it does its own
         * plus, it does a kmalloc
         */
-       ret = sparse_index_init(section_nr, pgdat->node_id);
+       ret = sparse_index_init(section_nr, nid);
        if (ret < 0 && ret != -EEXIST)
                return ret;
        ret = 0;
-       memmap = kmalloc_section_memmap(section_nr, pgdat->node_id, altmap);
+       memmap = kmalloc_section_memmap(section_nr, nid, altmap);
        if (!memmap)
                return -ENOMEM;
        usemap = __kmalloc_section_usemap();
@@ -705,8 +704,6 @@ int __meminit sparse_add_one_section(struct pglist_data *pgdat,
                return -ENOMEM;
        }
 
-       pgdat_resize_lock(pgdat, &flags);
-
        ms = __pfn_to_section(start_pfn);
        if (ms->section_mem_map & SECTION_MARKED_PRESENT) {
                ret = -EEXIST;
@@ -723,7 +720,6 @@ int __meminit sparse_add_one_section(struct pglist_data *pgdat,
        sparse_init_one_section(ms, section_nr, memmap, usemap);
 
 out:
-       pgdat_resize_unlock(pgdat, &flags);
        if (ret < 0) {
                kfree(usemap);
                __kfree_section_memmap(memmap, altmap);
@@ -740,6 +736,15 @@ static void clear_hwpoisoned_pages(struct page *memmap, int nr_pages)
        if (!memmap)
                return;
 
+       /*
+        * A further optimization is to have per section refcounted
+        * num_poisoned_pages.  But that would need more space per memmap, so
+        * for now just do a quick global check to speed up this routine in the
+        * absence of bad pages.
+        */
+       if (atomic_long_read(&num_poisoned_pages) == 0)
+               return;
+
        for (i = 0; i < nr_pages; i++) {
                if (PageHWPoison(&memmap[i])) {
                        atomic_long_sub(1, &num_poisoned_pages);
@@ -785,10 +790,8 @@ void sparse_remove_one_section(struct zone *zone, struct mem_section *ms,
                unsigned long map_offset, struct vmem_altmap *altmap)
 {
        struct page *memmap = NULL;
-       unsigned long *usemap = NULL, flags;
-       struct pglist_data *pgdat = zone->zone_pgdat;
+       unsigned long *usemap = NULL;
 
-       pgdat_resize_lock(pgdat, &flags);
        if (ms->section_mem_map) {
                usemap = ms->pageblock_flags;
                memmap = sparse_decode_mem_map(ms->section_mem_map,
@@ -796,7 +799,6 @@ void sparse_remove_one_section(struct zone *zone, struct mem_section *ms,
                ms->section_mem_map = 0;
                ms->pageblock_flags = NULL;
        }
-       pgdat_resize_unlock(pgdat, &flags);
 
        clear_hwpoisoned_pages(memmap + map_offset,
                        PAGES_PER_SECTION - map_offset);
index 5d786019eab957dc3a0160d0accc541894a9fc3f..4d8a1f1afaab44976ce3f4bb1e9efd690276e819 100644 (file)
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -1022,7 +1022,7 @@ EXPORT_SYMBOL(pagevec_lookup_range_nr_tag);
  */
 void __init swap_setup(void)
 {
-       unsigned long megs = totalram_pages >> (20 - PAGE_SHIFT);
+       unsigned long megs = totalram_pages() >> (20 - PAGE_SHIFT);
 
        /* Use a smaller cluster for small-memory machines */
        if (megs < 16)
index 8688ae65ef58ac639b0b2202039fa22577309350..dbac1d49469d47856ee881e01ac88c2812290b64 100644 (file)
@@ -2197,7 +2197,8 @@ int try_to_unuse(unsigned int type, bool frontswap,
                 */
                if (PageSwapCache(page) &&
                    likely(page_private(page) == entry.val) &&
-                   !page_swapped(page))
+                   (!PageTransCompound(page) ||
+                    !swap_page_trans_huge_swapped(si, entry)))
                        delete_from_swap_cache(compound_head(page));
 
                /*
@@ -2812,8 +2813,9 @@ static struct swap_info_struct *alloc_swap_info(void)
        struct swap_info_struct *p;
        unsigned int type;
        int i;
+       int size = sizeof(*p) + nr_node_ids * sizeof(struct plist_node);
 
-       p = kvzalloc(sizeof(*p), GFP_KERNEL);
+       p = kvzalloc(size, GFP_KERNEL);
        if (!p)
                return ERR_PTR(-ENOMEM);
 
index 458acda96f2075472c3afcd6bc8a024684845019..48368589f51990a6ed43a02d49a0d80532a5deb0 100644 (file)
@@ -267,10 +267,14 @@ retry:
                VM_BUG_ON(dst_addr & ~huge_page_mask(h));
 
                /*
-                * Serialize via hugetlb_fault_mutex
+                * Serialize via i_mmap_rwsem and hugetlb_fault_mutex.
+                * i_mmap_rwsem ensures the dst_pte remains valid even
+                * in the case of shared pmds.  fault mutex prevents
+                * races with other faulting threads.
                 */
-               idx = linear_page_index(dst_vma, dst_addr);
                mapping = dst_vma->vm_file->f_mapping;
+               i_mmap_lock_read(mapping);
+               idx = linear_page_index(dst_vma, dst_addr);
                hash = hugetlb_fault_mutex_hash(h, dst_mm, dst_vma, mapping,
                                                                idx, dst_addr);
                mutex_lock(&hugetlb_fault_mutex_table[hash]);
@@ -279,6 +283,7 @@ retry:
                dst_pte = huge_pte_alloc(dst_mm, dst_addr, huge_page_size(h));
                if (!dst_pte) {
                        mutex_unlock(&hugetlb_fault_mutex_table[hash]);
+                       i_mmap_unlock_read(mapping);
                        goto out_unlock;
                }
 
@@ -286,6 +291,7 @@ retry:
                dst_pteval = huge_ptep_get(dst_pte);
                if (!huge_pte_none(dst_pteval)) {
                        mutex_unlock(&hugetlb_fault_mutex_table[hash]);
+                       i_mmap_unlock_read(mapping);
                        goto out_unlock;
                }
 
@@ -293,6 +299,7 @@ retry:
                                                dst_addr, src_addr, &page);
 
                mutex_unlock(&hugetlb_fault_mutex_table[hash]);
+               i_mmap_unlock_read(mapping);
                vm_alloc_shared = vm_shared;
 
                cond_resched();
index 8bf08b5b576061bd68d62d7e5eb15c89f3e1c5ad..4df23d64aac7ae0c4846ba72f31ee1f20a21c143 100644 (file)
--- a/mm/util.c
+++ b/mm/util.c
@@ -593,7 +593,7 @@ unsigned long vm_commit_limit(void)
        if (sysctl_overcommit_kbytes)
                allowed = sysctl_overcommit_kbytes >> (PAGE_SHIFT - 10);
        else
-               allowed = ((totalram_pages - hugetlb_total_pages())
+               allowed = ((totalram_pages() - hugetlb_total_pages())
                           * sysctl_overcommit_ratio / 100);
        allowed += total_swap_pages;
 
index 97d4b25d0373102a197ba1de455a944cf7204061..871e41c55e239afb83051d8e73fde088d746ba37 100644 (file)
@@ -1634,7 +1634,7 @@ void *vmap(struct page **pages, unsigned int count,
 
        might_sleep();
 
-       if (count > totalram_pages)
+       if (count > totalram_pages())
                return NULL;
 
        size = (unsigned long)count << PAGE_SHIFT;
@@ -1739,7 +1739,7 @@ void *__vmalloc_node_range(unsigned long size, unsigned long align,
        unsigned long real_size = size;
 
        size = PAGE_ALIGN(size);
-       if (!size || (size >> PAGE_SHIFT) > totalram_pages)
+       if (!size || (size >> PAGE_SHIFT) > totalram_pages())
                goto fail;
 
        area = __get_vm_area_node(size, align, VM_ALLOC | VM_UNINITIALIZED |
index 24ab1f7394abaafa9e0dccac37597ae65ef77e0f..a714c4f800e9b8d6a449333363469667ee622767 100644 (file)
@@ -88,6 +88,9 @@ struct scan_control {
        /* Can pages be swapped as part of reclaim? */
        unsigned int may_swap:1;
 
+       /* e.g. boosted watermark reclaim leaves slabs alone */
+       unsigned int may_shrinkslab:1;
+
        /*
         * Cgroups are not reclaimed below their configured memory.low,
         * unless we threaten to OOM. If any cgroups are skipped due to
@@ -1457,14 +1460,8 @@ static unsigned long shrink_page_list(struct list_head *page_list,
                        count_memcg_page_event(page, PGLAZYFREED);
                } else if (!mapping || !__remove_mapping(mapping, page, true))
                        goto keep_locked;
-               /*
-                * At this point, we have no other references and there is
-                * no way to pick any more up (removed from LRU, removed
-                * from pagecache). Can use non-atomic bitops now (and
-                * we obviously don't have to worry about waking up a process
-                * waiting on the page lock, because there are no references.
-                */
-               __ClearPageLocked(page);
+
+               unlock_page(page);
 free_it:
                nr_reclaimed++;
 
@@ -2756,8 +2753,10 @@ static bool shrink_node(pg_data_t *pgdat, struct scan_control *sc)
                        shrink_node_memcg(pgdat, memcg, sc, &lru_pages);
                        node_lru_pages += lru_pages;
 
-                       shrink_slab(sc->gfp_mask, pgdat->node_id,
+                       if (sc->may_shrinkslab) {
+                               shrink_slab(sc->gfp_mask, pgdat->node_id,
                                    memcg, sc->priority);
+                       }
 
                        /* Record the group's reclaim efficiency */
                        vmpressure(sc->gfp_mask, memcg, false,
@@ -3239,6 +3238,7 @@ unsigned long try_to_free_pages(struct zonelist *zonelist, int order,
                .may_writepage = !laptop_mode,
                .may_unmap = 1,
                .may_swap = 1,
+               .may_shrinkslab = 1,
        };
 
        /*
@@ -3283,6 +3283,7 @@ unsigned long mem_cgroup_shrink_node(struct mem_cgroup *memcg,
                .may_unmap = 1,
                .reclaim_idx = MAX_NR_ZONES - 1,
                .may_swap = !noswap,
+               .may_shrinkslab = 1,
        };
        unsigned long lru_pages;
 
@@ -3329,6 +3330,7 @@ unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *memcg,
                .may_writepage = !laptop_mode,
                .may_unmap = 1,
                .may_swap = may_swap,
+               .may_shrinkslab = 1,
        };
 
        /*
@@ -3379,6 +3381,30 @@ static void age_active_anon(struct pglist_data *pgdat,
        } while (memcg);
 }
 
+static bool pgdat_watermark_boosted(pg_data_t *pgdat, int classzone_idx)
+{
+       int i;
+       struct zone *zone;
+
+       /*
+        * Check for watermark boosts top-down as the higher zones
+        * are more likely to be boosted. Both watermarks and boosts
+        * should not be checked at the time time as reclaim would
+        * start prematurely when there is no boosting and a lower
+        * zone is balanced.
+        */
+       for (i = classzone_idx; i >= 0; i--) {
+               zone = pgdat->node_zones + i;
+               if (!managed_zone(zone))
+                       continue;
+
+               if (zone->watermark_boost)
+                       return true;
+       }
+
+       return false;
+}
+
 /*
  * Returns true if there is an eligible zone balanced for the request order
  * and classzone_idx
@@ -3389,6 +3415,10 @@ static bool pgdat_balanced(pg_data_t *pgdat, int order, int classzone_idx)
        unsigned long mark = -1;
        struct zone *zone;
 
+       /*
+        * Check watermarks bottom-up as lower zones are more likely to
+        * meet watermarks.
+        */
        for (i = 0; i <= classzone_idx; i++) {
                zone = pgdat->node_zones + i;
 
@@ -3517,14 +3547,14 @@ static int balance_pgdat(pg_data_t *pgdat, int order, int classzone_idx)
        unsigned long nr_soft_reclaimed;
        unsigned long nr_soft_scanned;
        unsigned long pflags;
+       unsigned long nr_boost_reclaim;
+       unsigned long zone_boosts[MAX_NR_ZONES] = { 0, };
+       bool boosted;
        struct zone *zone;
        struct scan_control sc = {
                .gfp_mask = GFP_KERNEL,
                .order = order,
-               .priority = DEF_PRIORITY,
-               .may_writepage = !laptop_mode,
                .may_unmap = 1,
-               .may_swap = 1,
        };
 
        psi_memstall_enter(&pflags);
@@ -3532,9 +3562,28 @@ static int balance_pgdat(pg_data_t *pgdat, int order, int classzone_idx)
 
        count_vm_event(PAGEOUTRUN);
 
+       /*
+        * Account for the reclaim boost. Note that the zone boost is left in
+        * place so that parallel allocations that are near the watermark will
+        * stall or direct reclaim until kswapd is finished.
+        */
+       nr_boost_reclaim = 0;
+       for (i = 0; i <= classzone_idx; i++) {
+               zone = pgdat->node_zones + i;
+               if (!managed_zone(zone))
+                       continue;
+
+               nr_boost_reclaim += zone->watermark_boost;
+               zone_boosts[i] = zone->watermark_boost;
+       }
+       boosted = nr_boost_reclaim;
+
+restart:
+       sc.priority = DEF_PRIORITY;
        do {
                unsigned long nr_reclaimed = sc.nr_reclaimed;
                bool raise_priority = true;
+               bool balanced;
                bool ret;
 
                sc.reclaim_idx = classzone_idx;
@@ -3561,13 +3610,40 @@ static int balance_pgdat(pg_data_t *pgdat, int order, int classzone_idx)
                }
 
                /*
-                * Only reclaim if there are no eligible zones. Note that
-                * sc.reclaim_idx is not used as buffer_heads_over_limit may
-                * have adjusted it.
+                * If the pgdat is imbalanced then ignore boosting and preserve
+                * the watermarks for a later time and restart. Note that the
+                * zone watermarks will be still reset at the end of balancing
+                * on the grounds that the normal reclaim should be enough to
+                * re-evaluate if boosting is required when kswapd next wakes.
                 */
-               if (pgdat_balanced(pgdat, sc.order, classzone_idx))
+               balanced = pgdat_balanced(pgdat, sc.order, classzone_idx);
+               if (!balanced && nr_boost_reclaim) {
+                       nr_boost_reclaim = 0;
+                       goto restart;
+               }
+
+               /*
+                * If boosting is not active then only reclaim if there are no
+                * eligible zones. Note that sc.reclaim_idx is not used as
+                * buffer_heads_over_limit may have adjusted it.
+                */
+               if (!nr_boost_reclaim && balanced)
                        goto out;
 
+               /* Limit the priority of boosting to avoid reclaim writeback */
+               if (nr_boost_reclaim && sc.priority == DEF_PRIORITY - 2)
+                       raise_priority = false;
+
+               /*
+                * Do not writeback or swap pages for boosted reclaim. The
+                * intent is to relieve pressure not issue sub-optimal IO
+                * from reclaim context. If no pages are reclaimed, the
+                * reclaim will be aborted.
+                */
+               sc.may_writepage = !laptop_mode && !nr_boost_reclaim;
+               sc.may_swap = !nr_boost_reclaim;
+               sc.may_shrinkslab = !nr_boost_reclaim;
+
                /*
                 * Do some background aging of the anon list, to give
                 * pages a chance to be referenced before reclaiming. All
@@ -3619,6 +3695,16 @@ static int balance_pgdat(pg_data_t *pgdat, int order, int classzone_idx)
                 * progress in reclaiming pages
                 */
                nr_reclaimed = sc.nr_reclaimed - nr_reclaimed;
+               nr_boost_reclaim -= min(nr_boost_reclaim, nr_reclaimed);
+
+               /*
+                * If reclaim made no progress for a boost, stop reclaim as
+                * IO cannot be queued and it could be an infinite loop in
+                * extreme circumstances.
+                */
+               if (nr_boost_reclaim && !nr_reclaimed)
+                       break;
+
                if (raise_priority || !nr_reclaimed)
                        sc.priority--;
        } while (sc.priority >= 1);
@@ -3627,6 +3713,28 @@ static int balance_pgdat(pg_data_t *pgdat, int order, int classzone_idx)
                pgdat->kswapd_failures++;
 
 out:
+       /* If reclaim was boosted, account for the reclaim done in this pass */
+       if (boosted) {
+               unsigned long flags;
+
+               for (i = 0; i <= classzone_idx; i++) {
+                       if (!zone_boosts[i])
+                               continue;
+
+                       /* Increments are under the zone lock */
+                       zone = pgdat->node_zones + i;
+                       spin_lock_irqsave(&zone->lock, flags);
+                       zone->watermark_boost -= min(zone->watermark_boost, zone_boosts[i]);
+                       spin_unlock_irqrestore(&zone->lock, flags);
+               }
+
+               /*
+                * As there is now likely space, wakeup kcompact to defragment
+                * pageblocks.
+                */
+               wakeup_kcompactd(pgdat, pageblock_order, classzone_idx);
+       }
+
        snapshot_refaults(NULL, pgdat);
        __fs_reclaim_release();
        psi_memstall_leave(&pflags);
@@ -3855,7 +3963,8 @@ void wakeup_kswapd(struct zone *zone, gfp_t gfp_flags, int order,
 
        /* Hopeless node, leave it to direct reclaim if possible */
        if (pgdat->kswapd_failures >= MAX_RECLAIM_RETRIES ||
-           pgdat_balanced(pgdat, order, classzone_idx)) {
+           (pgdat_balanced(pgdat, order, classzone_idx) &&
+            !pgdat_watermark_boosted(pgdat, classzone_idx))) {
                /*
                 * There may be plenty of free memory available, but it's too
                 * fragmented for high-order allocations.  Wake up kcompactd
index 9c624595e90416bc9114fc11721e14d56183a1b6..83b30edc2f7f39eeaf17cd6bbd2fbad863ce1503 100644 (file)
@@ -227,7 +227,7 @@ int calculate_normal_threshold(struct zone *zone)
         * 125          1024            10      16-32 GB        9
         */
 
-       mem = zone->managed_pages >> (27 - PAGE_SHIFT);
+       mem = zone_managed_pages(zone) >> (27 - PAGE_SHIFT);
 
        threshold = 2 * fls(num_online_cpus()) * (1 + fls(mem));
 
@@ -1569,7 +1569,7 @@ static void zoneinfo_show_print(struct seq_file *m, pg_data_t *pgdat,
                   high_wmark_pages(zone),
                   zone->spanned_pages,
                   zone->present_pages,
-                  zone->managed_pages);
+                  zone_managed_pages(zone));
 
        seq_printf(m,
                   "\n        protection: (%ld",
index d46f8c92aa2fe736a1248ae30e0fb73a17b58a3e..dcb994f2acc2e600f39e2338d16f7bd839aefd2d 100644 (file)
@@ -549,7 +549,7 @@ static int __init workingset_init(void)
         * double the initial memory by using totalram_pages as-is.
         */
        timestamp_bits = BITS_PER_LONG - EVICTION_SHIFT;
-       max_order = fls_long(totalram_pages - 1);
+       max_order = fls_long(totalram_pages() - 1);
        if (max_order > timestamp_bits)
                bucket_order = max_order - timestamp_bits;
        pr_info("workingset: timestamp_bits=%d max_order=%d bucket_order=%u\n",
index cd91fd9d96b814d145e378b573dd289fb501e64e..a4e4d36ec085853740b0fc07e2412333990a9a81 100644 (file)
@@ -219,8 +219,8 @@ static const struct zpool_ops zswap_zpool_ops = {
 
 static bool zswap_is_full(void)
 {
-       return totalram_pages * zswap_max_pool_percent / 100 <
-               DIV_ROUND_UP(zswap_pool_total_size, PAGE_SIZE);
+       return totalram_pages() * zswap_max_pool_percent / 100 <
+                       DIV_ROUND_UP(zswap_pool_total_size, PAGE_SIZE);
 }
 
 static void zswap_update_total_size(void)
index 2cc5fbb1b29e98feff80a2526c818e7e47572416..0e2f71ab8367794ac3b059120713cb7495079ee2 100644 (file)
@@ -1131,6 +1131,7 @@ EXPORT_SYMBOL_GPL(dccp_debug);
 static int __init dccp_init(void)
 {
        unsigned long goal;
+       unsigned long nr_pages = totalram_pages();
        int ehash_order, bhash_order, i;
        int rc;
 
@@ -1157,10 +1158,10 @@ static int __init dccp_init(void)
         *
         * The methodology is similar to that of the buffer cache.
         */
-       if (totalram_pages >= (128 * 1024))
-               goal = totalram_pages >> (21 - PAGE_SHIFT);
+       if (nr_pages >= (128 * 1024))
+               goal = nr_pages >> (21 - PAGE_SHIFT);
        else
-               goal = totalram_pages >> (23 - PAGE_SHIFT);
+               goal = nr_pages >> (23 - PAGE_SHIFT);
 
        if (thash_entries)
                goal = (thash_entries *
index 1c002c0fb712a45e20b4e3daa72da4b6d19e935a..950613ee7881bc22ee0ebb106dbbacc4c35b7172 100644 (file)
@@ -1866,7 +1866,7 @@ void __init dn_route_init(void)
        dn_route_timer.expires = jiffies + decnet_dst_gc_interval * HZ;
        add_timer(&dn_route_timer);
 
-       goal = totalram_pages >> (26 - PAGE_SHIFT);
+       goal = totalram_pages() >> (26 - PAGE_SHIFT);
 
        for(order = 0; (1UL << order) < goal; order++)
                /* NOTHING */;
index 03b51cdcc731f5d85cbe51337f864bc8abc40135..b467a7cabf40e6af2ce69649f3ca48635bf06319 100644 (file)
@@ -1000,7 +1000,7 @@ static int __net_init tcp_net_metrics_init(struct net *net)
 
        slots = tcpmhash_entries;
        if (!slots) {
-               if (totalram_pages >= 128 * 1024)
+               if (totalram_pages() >= 128 * 1024)
                        slots = 16 * 1024;
                else
                        slots = 8 * 1024;
index e87c21e47efe1eedcb3c875d77c26cc2f4dd417f..741b533148baedd70cd4184ba47bb507b055c142 100644 (file)
@@ -2248,6 +2248,7 @@ static __always_inline unsigned int total_extension_size(void)
 
 int nf_conntrack_init_start(void)
 {
+       unsigned long nr_pages = totalram_pages();
        int max_factor = 8;
        int ret = -ENOMEM;
        int i;
@@ -2267,11 +2268,11 @@ int nf_conntrack_init_start(void)
                 * >= 4GB machines have 65536 buckets.
                 */
                nf_conntrack_htable_size
-                       = (((totalram_pages << PAGE_SHIFT) / 16384)
+                       = (((nr_pages << PAGE_SHIFT) / 16384)
                           / sizeof(struct hlist_head));
-               if (totalram_pages > (4 * (1024 * 1024 * 1024 / PAGE_SIZE)))
+               if (nr_pages > (4 * (1024 * 1024 * 1024 / PAGE_SIZE)))
                        nf_conntrack_htable_size = 65536;
-               else if (totalram_pages > (1024 * 1024 * 1024 / PAGE_SIZE))
+               else if (nr_pages > (1024 * 1024 * 1024 / PAGE_SIZE))
                        nf_conntrack_htable_size = 16384;
                if (nf_conntrack_htable_size < 32)
                        nf_conntrack_htable_size = 32;
index 28e27a32d9b96dfcf97250a1f6404180943281dc..8d86e39d6280a6112ca37ecd1732da70819b1f98 100644 (file)
@@ -274,14 +274,15 @@ static int htable_create(struct net *net, struct hashlimit_cfg3 *cfg,
        struct xt_hashlimit_htable *hinfo;
        const struct seq_operations *ops;
        unsigned int size, i;
+       unsigned long nr_pages = totalram_pages();
        int ret;
 
        if (cfg->size) {
                size = cfg->size;
        } else {
-               size = (totalram_pages << PAGE_SHIFT) / 16384 /
+               size = (nr_pages << PAGE_SHIFT) / 16384 /
                       sizeof(struct hlist_head);
-               if (totalram_pages > 1024 * 1024 * 1024 / PAGE_SIZE)
+               if (nr_pages > 1024 * 1024 * 1024 / PAGE_SIZE)
                        size = 8192;
                if (size < 16)
                        size = 16;
index 9b277bd36d1ade6acc46260c1d267bed801ee965..d5878ae5584090dbfd2841953a87088538593908 100644 (file)
@@ -1368,6 +1368,7 @@ static __init int sctp_init(void)
        int status = -EINVAL;
        unsigned long goal;
        unsigned long limit;
+       unsigned long nr_pages = totalram_pages();
        int max_share;
        int order;
        int num_entries;
@@ -1426,10 +1427,10 @@ static __init int sctp_init(void)
         * The methodology is similar to that of the tcp hash tables.
         * Though not identical.  Start by getting a goal size
         */
-       if (totalram_pages >= (128 * 1024))
-               goal = totalram_pages >> (22 - PAGE_SHIFT);
+       if (nr_pages >= (128 * 1024))
+               goal = nr_pages >> (22 - PAGE_SHIFT);
        else
-               goal = totalram_pages >> (24 - PAGE_SHIFT);
+               goal = nr_pages >> (24 - PAGE_SHIFT);
 
        /* Then compute the page order for said goal */
        order = get_order(goal);
index 69552a39951d144e9af34a6b70165df175228d70..25c259df8ffab1b108994ac12d78b35f97b65403 100644 (file)
@@ -1,5 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
-ifdef CONFIG_KASAN
+ifdef CONFIG_KASAN_GENERIC
+
 ifdef CONFIG_KASAN_INLINE
        call_threshold := 10000
 else
@@ -12,36 +13,44 @@ CFLAGS_KASAN_MINIMAL := -fsanitize=kernel-address
 
 cc-param = $(call cc-option, -mllvm -$(1), $(call cc-option, --param $(1)))
 
-ifeq ($(call cc-option, $(CFLAGS_KASAN_MINIMAL) -Werror),)
-   ifneq ($(CONFIG_COMPILE_TEST),y)
-        $(warning Cannot use CONFIG_KASAN: \
-            -fsanitize=kernel-address is not supported by compiler)
-   endif
-else
-   # -fasan-shadow-offset fails without -fsanitize
-   CFLAGS_KASAN_SHADOW := $(call cc-option, -fsanitize=kernel-address \
+# -fasan-shadow-offset fails without -fsanitize
+CFLAGS_KASAN_SHADOW := $(call cc-option, -fsanitize=kernel-address \
                        -fasan-shadow-offset=$(KASAN_SHADOW_OFFSET), \
                        $(call cc-option, -fsanitize=kernel-address \
                        -mllvm -asan-mapping-offset=$(KASAN_SHADOW_OFFSET)))
 
-   ifeq ($(strip $(CFLAGS_KASAN_SHADOW)),)
-      CFLAGS_KASAN := $(CFLAGS_KASAN_MINIMAL)
-   else
-      # Now add all the compiler specific options that are valid standalone
-      CFLAGS_KASAN := $(CFLAGS_KASAN_SHADOW) \
-       $(call cc-param,asan-globals=1) \
-       $(call cc-param,asan-instrumentation-with-call-threshold=$(call_threshold)) \
-       $(call cc-param,asan-stack=1) \
-       $(call cc-param,asan-use-after-scope=1) \
-       $(call cc-param,asan-instrument-allocas=1)
-   endif
-
+ifeq ($(strip $(CFLAGS_KASAN_SHADOW)),)
+       CFLAGS_KASAN := $(CFLAGS_KASAN_MINIMAL)
+else
+       # Now add all the compiler specific options that are valid standalone
+       CFLAGS_KASAN := $(CFLAGS_KASAN_SHADOW) \
+        $(call cc-param,asan-globals=1) \
+        $(call cc-param,asan-instrumentation-with-call-threshold=$(call_threshold)) \
+        $(call cc-param,asan-stack=1) \
+        $(call cc-param,asan-use-after-scope=1) \
+        $(call cc-param,asan-instrument-allocas=1)
 endif
 
 ifdef CONFIG_KASAN_EXTRA
 CFLAGS_KASAN += $(call cc-option, -fsanitize-address-use-after-scope)
 endif
 
-CFLAGS_KASAN_NOSANITIZE := -fno-builtin
+endif # CONFIG_KASAN_GENERIC
 
+ifdef CONFIG_KASAN_SW_TAGS
+
+ifdef CONFIG_KASAN_INLINE
+    instrumentation_flags := -mllvm -hwasan-mapping-offset=$(KASAN_SHADOW_OFFSET)
+else
+    instrumentation_flags := -mllvm -hwasan-instrument-with-calls=1
+endif
+
+CFLAGS_KASAN := -fsanitize=kernel-hwaddress \
+               -mllvm -hwasan-instrument-stack=0 \
+               $(instrumentation_flags)
+
+endif # CONFIG_KASAN_SW_TAGS
+
+ifdef CONFIG_KASAN
+CFLAGS_KASAN_NOSANITIZE := -fno-builtin
 endif
index a923f05edb36604579901caf7fa1d1ad0a67c98e..8c965f6a988122f1180d34818dcc8007bf1f944b 100755 (executable)
@@ -32,6 +32,7 @@ def getsizes(file, format):
                 if name.startswith("__mod_"): continue
                 if name.startswith("__se_sys"): continue
                 if name.startswith("__se_compat_sys"): continue
+                if name.startswith("__addressable_"): continue
                 if name == "linux_banner": continue
                 # statics and some other optimizations adds random .NUMBER
                 name = re_NUMBER.sub('', name)
index 34414c6efad6398b68f7e2c331f9e6185469c5c0..122aef5e4e14933f829cacb4442f9e8e293c3e27 100755 (executable)
@@ -48,7 +48,9 @@ my (@stack, $re, $dre, $x, $xs, $funcre);
        $funcre = qr/^$x* <(.*)>:$/;
        if ($arch eq 'aarch64') {
                #ffffffc0006325cc:       a9bb7bfd        stp     x29, x30, [sp, #-80]!
+               #a110:       d11643ff        sub     sp, sp, #0x590
                $re = qr/^.*stp.*sp, \#-([0-9]{1,8})\]\!/o;
+               $dre = qr/^.*sub.*sp, sp, #(0x$x{1,8})/o;
        } elsif ($arch eq 'arm') {
                #c0008ffc:      e24dd064        sub     sp, sp, #100    ; 0x64
                $re = qr/.*sub.*sp, sp, #(([0-9]{2}|[3-9])[0-9]{2})/o;
index 64220e36ce3b92daaf66903360282a47e9dc8818..98a7d63a723e3bf49b8d4542ea5d5da090ca64c3 100755 (executable)
@@ -78,7 +78,7 @@ parse_symbol() {
        fi
 
        # Strip out the base of the path
-       code=${code//$basepath/""}
+       code=${code//^$basepath/""}
 
        # In the case of inlines, move everything to same line
        code=${code//$'\n'/' '}
index 9cef558528aac890dfc2d2545aa9eb2fd8be3934..ba8b8d5834e67922e0028dbec04b9e7cebc2766d 100755 (executable)
@@ -60,6 +60,13 @@ case $width in
 4) type=4byte ;;
 esac
 
+if [ -z "$ARCH" ]; then
+    case `uname -m` in
+       aarch64*) ARCH=arm64 ;;
+       arm*) ARCH=arm ;;
+    esac
+fi
+
 disas() {
        ${CROSS_COMPILE}as $AFLAGS -o $1.o $1.s > /dev/null 2>&1
 
diff --git a/scripts/spdxcheck-test.sh b/scripts/spdxcheck-test.sh
new file mode 100644 (file)
index 0000000..cfea6a0
--- /dev/null
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+for PYTHON in python2 python3; do
+       # run check on a text and a binary file
+       for FILE in Makefile Documentation/logo.gif; do
+               $PYTHON scripts/spdxcheck.py $FILE
+               $PYTHON scripts/spdxcheck.py - < $FILE
+       done
+
+       # run check on complete tree to catch any other issues
+       $PYTHON scripts/spdxcheck.py > /dev/null
+done
index 4fa070f9231ac2e78b5688d11b2463997302b482..f470d9919ed7cef58d142b7407dad3af1083cd2b 100755 (executable)
@@ -191,7 +191,7 @@ regex_c=(
        '/^DEF_PCI_AC_\(\|NO\)RET(\([[:alnum:]_]*\).*/\2/'
        '/^PCI_OP_READ(\(\w*\).*[1-4])/pci_bus_read_config_\1/'
        '/^PCI_OP_WRITE(\(\w*\).*[1-4])/pci_bus_write_config_\1/'
-       '/\<DEFINE_\(MUTEX\|SEMAPHORE\|SPINLOCK\)(\([[:alnum:]_]*\)/\2/v/'
+       '/\<DEFINE_\(RT_MUTEX\|MUTEX\|SEMAPHORE\|SPINLOCK\)(\([[:alnum:]_]*\)/\2/v/'
        '/\<DEFINE_\(RAW_SPINLOCK\|RWLOCK\|SEQLOCK\)(\([[:alnum:]_]*\)/\2/v/'
        '/\<DECLARE_\(RWSEM\|COMPLETION\)(\([[:alnum:]_]\+\)/\2/v/'
        '/\<DECLARE_BITMAP(\([[:alnum:]_]*\)/\1/v/'
@@ -204,6 +204,15 @@ regex_c=(
        '/\(^\s\)OFFSET(\([[:alnum:]_]*\)/\2/v/'
        '/\(^\s\)DEFINE(\([[:alnum:]_]*\)/\2/v/'
        '/\<\(DEFINE\|DECLARE\)_HASHTABLE(\([[:alnum:]_]*\)/\2/v/'
+       '/\<DEFINE_ID\(R\|A\)(\([[:alnum:]_]\+\)/\2/'
+       '/\<DEFINE_WD_CLASS(\([[:alnum:]_]\+\)/\1/'
+       '/\<ATOMIC_NOTIFIER_HEAD(\([[:alnum:]_]\+\)/\1/'
+       '/\<RAW_NOTIFIER_HEAD(\([[:alnum:]_]\+\)/\1/'
+       '/\<DECLARE_FAULT_ATTR(\([[:alnum:]_]\+\)/\1/'
+       '/\<BLOCKING_NOTIFIER_HEAD(\([[:alnum:]_]\+\)/\1/'
+       '/\<DEVICE_ATTR_\(RW\|RO\|WO\)(\([[:alnum:]_]\+\)/dev_attr_\2/'
+       '/\<DRIVER_ATTR_\(RW\|RO\|WO\)(\([[:alnum:]_]\+\)/driver_attr_\2/'
+       '/\<\(DEFINE\|DECLARE\)_STATIC_KEY_\(TRUE\|FALSE\)\(\|_RO\)(\([[:alnum:]_]\+\)/\4/'
 )
 regex_kconfig=(
        '/^[[:blank:]]*\(menu\|\)config[[:blank:]]\+\([[:alnum:]_]\+\)/\2/'
@@ -249,7 +258,7 @@ exuberant()
        -I __initdata,__exitdata,__initconst,__ro_after_init    \
        -I __initdata_memblock                                  \
        -I __refdata,__attribute,__maybe_unused,__always_unused \
-       -I __acquires,__releases,__deprecated                   \
+       -I __acquires,__releases,__deprecated,__always_inline   \
        -I __read_mostly,__aligned,____cacheline_aligned        \
        -I ____cacheline_aligned_in_smp                         \
        -I __cacheline_aligned,__cacheline_aligned_in_smp       \
index 16bd18747cfa0280c400f647854e6cbbe09e6d1d..d6f32807b3479479f68f212d0117ec3fc85f36e9 100644 (file)
@@ -106,7 +106,7 @@ void ima_add_kexec_buffer(struct kimage *image)
                kexec_segment_size = ALIGN(ima_get_binary_runtime_size() +
                                           PAGE_SIZE / 2, PAGE_SIZE);
        if ((kexec_segment_size == ULONG_MAX) ||
-           ((kexec_segment_size >> PAGE_SHIFT) > totalram_pages / 2)) {
+           ((kexec_segment_size >> PAGE_SHIFT) > totalram_pages() / 2)) {
                pr_err("Binary measurement list too large.\n");
                return;
        }
index ff9d3a5825e1f6fbdf4cc7ee89ad7a7cdb9c0fe3..c6635fee27d8c2137cad2206d01208eeddc7b207 100644 (file)
@@ -104,16 +104,29 @@ void *__wrap_devm_memremap(struct device *dev, resource_size_t offset,
 }
 EXPORT_SYMBOL(__wrap_devm_memremap);
 
+static void nfit_test_kill(void *_pgmap)
+{
+       struct dev_pagemap *pgmap = _pgmap;
+
+       pgmap->kill(pgmap->ref);
+}
+
 void *__wrap_devm_memremap_pages(struct device *dev, struct dev_pagemap *pgmap)
 {
        resource_size_t offset = pgmap->res.start;
        struct nfit_test_resource *nfit_res = get_nfit_res(offset);
 
-       if (nfit_res)
+       if (nfit_res) {
+               int rc;
+
+               rc = devm_add_action_or_reset(dev, nfit_test_kill, pgmap);
+               if (rc)
+                       return ERR_PTR(rc);
                return nfit_res->buf + offset - nfit_res->res.start;
+       }
        return devm_memremap_pages(dev, pgmap);
 }
-EXPORT_SYMBOL(__wrap_devm_memremap_pages);
+EXPORT_SYMBOL_GPL(__wrap_devm_memremap_pages);
 
 pfn_t __wrap_phys_to_pfn_t(phys_addr_t addr, unsigned long flags)
 {
index 37908a83ddc27eac33d40f76ea869edf8bdd957d..1ff3a6c0367b087ee4d84e0fa3b0ed0e2752d2b3 100644 (file)
@@ -701,7 +701,7 @@ static void walk_pfn(unsigned long voffset,
                if (kpagecgroup_read(cgi, index, pages) != pages)
                        fatal("kpagecgroup returned fewer pages than expected");
 
-               if (kpagecount_read(cnt, index, batch) != pages)
+               if (kpagecount_read(cnt, index, pages) != pages)
                        fatal("kpagecount returned fewer pages than expected");
 
                for (i = 0; i < pages; i++)
index cf7cc0554094f9f3e84804718b43c8b5df9193bc..666d0155662debc3e1ce7390f0e5ca4603cfa77e 100644 (file)
@@ -363,10 +363,7 @@ static void kvm_mmu_notifier_change_pte(struct mmu_notifier *mn,
 }
 
 static int kvm_mmu_notifier_invalidate_range_start(struct mmu_notifier *mn,
-                                                   struct mm_struct *mm,
-                                                   unsigned long start,
-                                                   unsigned long end,
-                                                   bool blockable)
+                                       const struct mmu_notifier_range *range)
 {
        struct kvm *kvm = mmu_notifier_to_kvm(mn);
        int need_tlb_flush = 0, idx;
@@ -380,7 +377,7 @@ static int kvm_mmu_notifier_invalidate_range_start(struct mmu_notifier *mn,
         * count is also read inside the mmu_lock critical section.
         */
        kvm->mmu_notifier_count++;
-       need_tlb_flush = kvm_unmap_hva_range(kvm, start, end);
+       need_tlb_flush = kvm_unmap_hva_range(kvm, range->start, range->end);
        need_tlb_flush |= kvm->tlbs_dirty;
        /* we've to flush the tlb before the pages can be freed */
        if (need_tlb_flush)
@@ -388,7 +385,8 @@ static int kvm_mmu_notifier_invalidate_range_start(struct mmu_notifier *mn,
 
        spin_unlock(&kvm->mmu_lock);
 
-       ret = kvm_arch_mmu_notifier_invalidate_range(kvm, start, end, blockable);
+       ret = kvm_arch_mmu_notifier_invalidate_range(kvm, range->start,
+                                       range->end, range->blockable);
 
        srcu_read_unlock(&kvm->srcu, idx);
 
@@ -396,9 +394,7 @@ static int kvm_mmu_notifier_invalidate_range_start(struct mmu_notifier *mn,
 }
 
 static void kvm_mmu_notifier_invalidate_range_end(struct mmu_notifier *mn,
-                                                 struct mm_struct *mm,
-                                                 unsigned long start,
-                                                 unsigned long end)
+                                       const struct mmu_notifier_range *range)
 {
        struct kvm *kvm = mmu_notifier_to_kvm(mn);