Merge branch 'akpm' (patches from Andrew)

Merge still more updates from Andrew Morton:
 "Various trees. Mainly those parts of MM whose linux-next dependents
  are now merged. I'm still sitting on ~160 patches which await merges
  from -next.

  Subsystems affected by this patch series: mm/proc, ipc, dynamic-debug,
  panic, lib, sysctl, mm/gup, mm/pagemap"

* emailed patches from Andrew Morton <akpm@linux-foundation.org>: (52 commits)
  doc: cgroup: update note about conditions when oom killer is invoked
  module: move the set_fs hack for flush_icache_range to m68k
  nommu: use flush_icache_user_range in brk and mmap
  binfmt_flat: use flush_icache_user_range
  exec: use flush_icache_user_range in read_code
  exec: only build read_code when needed
  m68k: implement flush_icache_user_range
  arm: rename flush_cache_user_range to flush_icache_user_range
  xtensa: implement flush_icache_user_range
  sh: implement flush_icache_user_range
  asm-generic: add a flush_icache_user_range stub
  mm: rename flush_icache_user_range to flush_icache_user_page
  arm,sparc,unicore32: remove flush_icache_user_range
  riscv: use asm-generic/cacheflush.h
  powerpc: use asm-generic/cacheflush.h
  openrisc: use asm-generic/cacheflush.h
  m68knommu: use asm-generic/cacheflush.h
  microblaze: use asm-generic/cacheflush.h
  ia64: use asm-generic/cacheflush.h
  hexagon: use asm-generic/cacheflush.h
  ...
This commit is contained in:
Linus Torvalds 2020-06-08 11:11:38 -07:00
commit 20b0d06722
75 changed files with 699 additions and 491 deletions

View File

@ -1170,6 +1170,13 @@ PAGE_SIZE multiple when read back.
Under certain circumstances, the usage may go over the limit Under certain circumstances, the usage may go over the limit
temporarily. temporarily.
In default configuration regular 0-order allocations always
succeed unless OOM killer chooses current task as a victim.
Some kinds of allocations don't invoke the OOM killer.
Caller could retry them differently, return into userspace
as -ENOMEM or silently ignore in cases like disk readahead.
This is the ultimate protection mechanism. As long as the This is the ultimate protection mechanism. As long as the
high limit is used and monitored properly, this limit's high limit is used and monitored properly, this limit's
utility is limited to providing the final safety net. utility is limited to providing the final safety net.
@ -1226,17 +1233,9 @@ PAGE_SIZE multiple when read back.
The number of time the cgroup's memory usage was The number of time the cgroup's memory usage was
reached the limit and allocation was about to fail. reached the limit and allocation was about to fail.
Depending on context result could be invocation of OOM
killer and retrying allocation or failing allocation.
Failed allocation in its turn could be returned into
userspace as -ENOMEM or silently ignored in cases like
disk readahead. For now OOM in memory cgroup kills
tasks iff shortage has happened inside page fault.
This event is not raised if the OOM killer is not This event is not raised if the OOM killer is not
considered as an option, e.g. for failed high-order considered as an option, e.g. for failed high-order
allocations. allocations or if caller asked to not retry attempts.
oom_kill oom_kill
The number of processes belonging to this cgroup The number of processes belonging to this cgroup

View File

@ -13,6 +13,11 @@ kernel code to obtain additional kernel information. Currently, if
``print_hex_dump_debug()``/``print_hex_dump_bytes()`` calls can be dynamically ``print_hex_dump_debug()``/``print_hex_dump_bytes()`` calls can be dynamically
enabled per-callsite. enabled per-callsite.
If you do not want to enable dynamic debug globally (i.e. in some embedded
system), you may set ``CONFIG_DYNAMIC_DEBUG_CORE`` as basic support of dynamic
debug and add ``ccflags := -DDYNAMIC_DEBUG_MODULE`` into the Makefile of any
modules which you'd like to dynamically debug later.
If ``CONFIG_DYNAMIC_DEBUG`` is not set, ``print_hex_dump_debug()`` is just If ``CONFIG_DYNAMIC_DEBUG`` is not set, ``print_hex_dump_debug()`` is just
shortcut for ``print_hex_dump(KERN_DEBUG)``. shortcut for ``print_hex_dump(KERN_DEBUG)``.

View File

@ -521,6 +521,14 @@ will cause a kdump to occur at the panic() call. In cases where a user wants
to specify this during runtime, /proc/sys/kernel/panic_on_warn can be set to 1 to specify this during runtime, /proc/sys/kernel/panic_on_warn can be set to 1
to achieve the same behaviour. to achieve the same behaviour.
Trigger Kdump on add_taint()
============================
The kernel parameter panic_on_taint facilitates a conditional call to panic()
from within add_taint() whenever the value set in this bitmask matches with the
bit flag being set by add_taint().
This will cause a kdump to occur at the add_taint()->panic() call.
Contact Contact
======= =======

View File

@ -1445,7 +1445,7 @@
hardlockup_all_cpu_backtrace= hardlockup_all_cpu_backtrace=
[KNL] Should the hard-lockup detector generate [KNL] Should the hard-lockup detector generate
backtraces on all cpus. backtraces on all cpus.
Format: <integer> Format: 0 | 1
hashdist= [KNL,NUMA] Large hashes allocated during boot hashdist= [KNL,NUMA] Large hashes allocated during boot
are distributed across NUMA nodes. Defaults on are distributed across NUMA nodes. Defaults on
@ -1513,9 +1513,9 @@
hung_task_panic= hung_task_panic=
[KNL] Should the hung task detector generate panics. [KNL] Should the hung task detector generate panics.
Format: <integer> Format: 0 | 1
A nonzero value instructs the kernel to panic when a A value of 1 instructs the kernel to panic when a
hung task is detected. The default value is controlled hung task is detected. The default value is controlled
by the CONFIG_BOOTPARAM_HUNG_TASK_PANIC build-time by the CONFIG_BOOTPARAM_HUNG_TASK_PANIC build-time
option. The value selected by this boot parameter can option. The value selected by this boot parameter can
@ -3447,6 +3447,19 @@
bit 4: print ftrace buffer bit 4: print ftrace buffer
bit 5: print all printk messages in buffer bit 5: print all printk messages in buffer
panic_on_taint= Bitmask for conditionally calling panic() in add_taint()
Format: <hex>[,nousertaint]
Hexadecimal bitmask representing the set of TAINT flags
that will cause the kernel to panic when add_taint() is
called with any of the flags in this set.
The optional switch "nousertaint" can be utilized to
prevent userspace forced crashes by writing to sysctl
/proc/sys/kernel/tainted any flagset matching with the
bitmask set on panic_on_taint.
See Documentation/admin-guide/tainted-kernels.rst for
extra details on the taint flags that users can pick
to compose the bitmask to assign to panic_on_taint.
panic_on_warn panic() instead of WARN(). Useful to cause kdump panic_on_warn panic() instead of WARN(). Useful to cause kdump
on a WARN(). on a WARN().
@ -4652,9 +4665,9 @@
softlockup_panic= softlockup_panic=
[KNL] Should the soft-lockup detector generate panics. [KNL] Should the soft-lockup detector generate panics.
Format: <integer> Format: 0 | 1
A nonzero value instructs the soft-lockup detector A value of 1 instructs the soft-lockup detector
to panic the machine when a soft-lockup occurs. It is to panic the machine when a soft-lockup occurs. It is
also controlled by the kernel.softlockup_panic sysctl also controlled by the kernel.softlockup_panic sysctl
and CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC, which is the and CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC, which is the
@ -4663,7 +4676,7 @@
softlockup_all_cpu_backtrace= softlockup_all_cpu_backtrace=
[KNL] Should the soft-lockup detector generate [KNL] Should the soft-lockup detector generate
backtraces on all cpus. backtraces on all cpus.
Format: <integer> Format: 0 | 1
sonypi.*= [HW] Sony Programmable I/O Control Device driver sonypi.*= [HW] Sony Programmable I/O Control Device driver
See Documentation/admin-guide/laptops/sonypi.rst See Documentation/admin-guide/laptops/sonypi.rst
@ -4956,6 +4969,15 @@
switches= [HW,M68k] switches= [HW,M68k]
sysctl.*= [KNL]
Set a sysctl parameter, right before loading the init
process, as if the value was written to the respective
/proc/sys/... file. Both '.' and '/' are recognized as
separators. Unrecognized parameters and invalid values
are reported in the kernel log. Sysctls registered
later by a loaded module cannot be set this way.
Example: sysctl.vm.swappiness=40
sysfs.deprecated=0|1 [KNL] sysfs.deprecated=0|1 [KNL]
Enable/disable old style sysfs layout for old udev Enable/disable old style sysfs layout for old udev
on older distributions. When this option is enabled on older distributions. When this option is enabled

View File

@ -335,6 +335,20 @@ Path for the hotplug policy agent.
Default value is "``/sbin/hotplug``". Default value is "``/sbin/hotplug``".
hung_task_all_cpu_backtrace:
================
If this option is set, the kernel will send an NMI to all CPUs to dump
their backtraces when a hung task is detected. This file shows up if
CONFIG_DETECT_HUNG_TASK and CONFIG_SMP are enabled.
0: Won't show all CPUs backtraces when a hung task is detected.
This is the default behavior.
1: Will non-maskably interrupt all CPUs and dump their backtraces when
a hung task is detected.
hung_task_panic hung_task_panic
=============== ===============
@ -632,6 +646,22 @@ rate for each task.
scanned for a given scan. scanned for a given scan.
oops_all_cpu_backtrace:
================
If this option is set, the kernel will send an NMI to all CPUs to dump
their backtraces when an oops event occurs. It should be used as a last
resort in case a panic cannot be triggered (to protect VMs running, for
example) or kdump can't be collected. This file shows up if CONFIG_SMP
is enabled.
0: Won't show all CPUs backtraces when an oops is detected.
This is the default behavior.
1: Will non-maskably interrupt all CPUs and dump their backtraces when
an oops event is detected.
osrelease, ostype & version osrelease, ostype & version
=========================== ===========================
@ -1239,6 +1269,13 @@ ORed together. The letters are seen in "Tainted" line of Oops reports.
See :doc:`/admin-guide/tainted-kernels` for more information. See :doc:`/admin-guide/tainted-kernels` for more information.
Note:
writes to this sysctl interface will fail with ``EINVAL`` if the kernel is
booted with the command line option ``panic_on_taint=<bitmask>,nousertaint``
and any of the ORed together values being written to ``tainted`` match with
the bitmask declared on panic_on_taint.
See :doc:`/admin-guide/kernel-parameters` for more details on that particular
kernel command line option and its optional ``nousertaint`` switch.
threads-max threads-max
=========== ===========

View File

@ -148,23 +148,46 @@ NOTE: Some pages, such as DAX pages, cannot be pinned with longterm pins. That's
because DAX pages do not have a separate page cache, and so "pinning" implies because DAX pages do not have a separate page cache, and so "pinning" implies
locking down file system blocks, which is not (yet) supported in that way. locking down file system blocks, which is not (yet) supported in that way.
CASE 3: Hardware with page faulting support CASE 3: MMU notifier registration, with or without page faulting hardware
------------------------------------------- -------------------------------------------------------------------------
Here, a well-written driver doesn't normally need to pin pages at all. However, Device drivers can pin pages via get_user_pages*(), and register for mmu
if the driver does choose to do so, it can register MMU notifiers for the range, notifier callbacks for the memory range. Then, upon receiving a notifier
and will be called back upon invalidation. Either way (avoiding page pinning, or "invalidate range" callback , stop the device from using the range, and unpin
using MMU notifiers to unpin upon request), there is proper synchronization with the pages. There may be other possible schemes, such as for example explicitly
both filesystem and mm (page_mkclean(), munmap(), etc). synchronizing against pending IO, that accomplish approximately the same thing.
Therefore, neither flag needs to be set. Or, if the hardware supports replayable page faults, then the device driver can
avoid pinning entirely (this is ideal), as follows: register for mmu notifier
callbacks as above, but instead of stopping the device and unpinning in the
callback, simply remove the range from the device's page tables.
In this case, ideally, neither get_user_pages() nor pin_user_pages() should be Either way, as long as the driver unpins the pages upon mmu notifier callback,
called. Instead, the software should be written so that it does not pin pages. then there is proper synchronization with both filesystem and mm
This allows mm and filesystems to operate more efficiently and reliably. (page_mkclean(), munmap(), etc). Therefore, neither flag needs to be set.
CASE 4: Pinning for struct page manipulation only CASE 4: Pinning for struct page manipulation only
------------------------------------------------- -------------------------------------------------
Here, normal GUP calls are sufficient, so neither flag needs to be set. If only struct page data (as opposed to the actual memory contents that a page
is tracking) is affected, then normal GUP calls are sufficient, and neither flag
needs to be set.
CASE 5: Pinning in order to write to the data within the page
-------------------------------------------------------------
Even though neither DMA nor Direct IO is involved, just a simple case of "pin,
write to a page's data, unpin" can cause a problem. Case 5 may be considered a
superset of Case 1, plus Case 2, plus anything that invokes that pattern. In
other words, if the code is neither Case 1 nor Case 2, it may still require
FOLL_PIN, for patterns like this:
Correct (uses FOLL_PIN calls):
pin_user_pages()
write to the data within the pages
unpin_user_pages()
INCORRECT (uses FOLL_GET calls):
get_user_pages()
write to the data within the pages
put_page()
page_maybe_dma_pinned(): the whole point of pinning page_maybe_dma_pinned(): the whole point of pinning
=================================================== ===================================================

View File

@ -4,19 +4,6 @@
#include <linux/mm.h> #include <linux/mm.h>
/* Caches aren't brain-dead on the Alpha. */
#define flush_cache_all() do { } while (0)
#define flush_cache_mm(mm) do { } while (0)
#define flush_cache_dup_mm(mm) do { } while (0)
#define flush_cache_range(vma, start, end) do { } while (0)
#define flush_cache_page(vma, vmaddr, pfn) do { } while (0)
#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 0
#define flush_dcache_page(page) do { } while (0)
#define flush_dcache_mmap_lock(mapping) do { } while (0)
#define flush_dcache_mmap_unlock(mapping) do { } while (0)
#define flush_cache_vmap(start, end) do { } while (0)
#define flush_cache_vunmap(start, end) do { } while (0)
/* Note that the following two definitions are _highly_ dependent /* Note that the following two definitions are _highly_ dependent
on the contexts in which they are used in the kernel. I personally on the contexts in which they are used in the kernel. I personally
think it is criminal how loosely defined these macros are. */ think it is criminal how loosely defined these macros are. */
@ -48,7 +35,7 @@ extern void smp_imb(void);
extern void __load_new_mm_context(struct mm_struct *); extern void __load_new_mm_context(struct mm_struct *);
static inline void static inline void
flush_icache_user_range(struct vm_area_struct *vma, struct page *page, flush_icache_user_page(struct vm_area_struct *vma, struct page *page,
unsigned long addr, int len) unsigned long addr, int len)
{ {
if (vma->vm_flags & VM_EXEC) { if (vma->vm_flags & VM_EXEC) {
@ -59,20 +46,17 @@ flush_icache_user_range(struct vm_area_struct *vma, struct page *page,
mm->context[smp_processor_id()] = 0; mm->context[smp_processor_id()] = 0;
} }
} }
#else #define flush_icache_user_page flush_icache_user_page
extern void flush_icache_user_range(struct vm_area_struct *vma, #else /* CONFIG_SMP */
extern void flush_icache_user_page(struct vm_area_struct *vma,
struct page *page, unsigned long addr, int len); struct page *page, unsigned long addr, int len);
#endif #define flush_icache_user_page flush_icache_user_page
#endif /* CONFIG_SMP */
/* This is used only in __do_fault and do_swap_page. */ /* This is used only in __do_fault and do_swap_page. */
#define flush_icache_page(vma, page) \ #define flush_icache_page(vma, page) \
flush_icache_user_range((vma), (page), 0, 0) flush_icache_user_page((vma), (page), 0, 0)
#define copy_to_user_page(vma, page, vaddr, dst, src, len) \ #include <asm-generic/cacheflush.h>
do { memcpy(dst, src, len); \
flush_icache_user_range(vma, page, vaddr, len); \
} while (0)
#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
memcpy(dst, src, len)
#endif /* _ALPHA_CACHEFLUSH_H */ #endif /* _ALPHA_CACHEFLUSH_H */

View File

@ -740,7 +740,7 @@ ipi_flush_icache_page(void *x)
} }
void void
flush_icache_user_range(struct vm_area_struct *vma, struct page *page, flush_icache_user_page(struct vm_area_struct *vma, struct page *page,
unsigned long addr, int len) unsigned long addr, int len)
{ {
struct mm_struct *mm = vma->vm_mm; struct mm_struct *mm = vma->vm_mm;

View File

@ -258,11 +258,11 @@ extern void flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr
#define flush_cache_dup_mm(mm) flush_cache_mm(mm) #define flush_cache_dup_mm(mm) flush_cache_mm(mm)
/* /*
* flush_cache_user_range is used when we want to ensure that the * flush_icache_user_range is used when we want to ensure that the
* Harvard caches are synchronised for the user space address range. * Harvard caches are synchronised for the user space address range.
* This is used for the ARM private sys_cacheflush system call. * This is used for the ARM private sys_cacheflush system call.
*/ */
#define flush_cache_user_range(s,e) __cpuc_coherent_user_range(s,e) #define flush_icache_user_range(s,e) __cpuc_coherent_user_range(s,e)
/* /*
* Perform necessary cache operations to ensure that data previously * Perform necessary cache operations to ensure that data previously
@ -318,9 +318,6 @@ extern void flush_kernel_dcache_page(struct page *);
#define flush_dcache_mmap_lock(mapping) xa_lock_irq(&mapping->i_pages) #define flush_dcache_mmap_lock(mapping) xa_lock_irq(&mapping->i_pages)
#define flush_dcache_mmap_unlock(mapping) xa_unlock_irq(&mapping->i_pages) #define flush_dcache_mmap_unlock(mapping) xa_unlock_irq(&mapping->i_pages)
#define flush_icache_user_range(vma,page,addr,len) \
flush_dcache_page(page)
/* /*
* We don't appear to need to do anything here. In fact, if we did, we'd * We don't appear to need to do anything here. In fact, if we did, we'd
* duplicate cache flushing elsewhere performed by flush_dcache_page(). * duplicate cache flushing elsewhere performed by flush_dcache_page().

View File

@ -98,8 +98,8 @@ void set_fiq_handler(void *start, unsigned int length)
memcpy(base + offset, start, length); memcpy(base + offset, start, length);
if (!cache_is_vipt_nonaliasing()) if (!cache_is_vipt_nonaliasing())
flush_icache_range((unsigned long)base + offset, offset + flush_icache_range((unsigned long)base + offset,
length); (unsigned long)base + offset + length);
flush_icache_range(0xffff0000 + offset, 0xffff0000 + offset + length); flush_icache_range(0xffff0000 + offset, 0xffff0000 + offset + length);
} }

View File

@ -566,7 +566,7 @@ __do_cache_op(unsigned long start, unsigned long end)
if (fatal_signal_pending(current)) if (fatal_signal_pending(current))
return 0; return 0;
ret = flush_cache_user_range(start, start + chunk); ret = flush_icache_user_range(start, start + chunk);
if (ret) if (ret)
return ret; return ret;

View File

@ -94,20 +94,7 @@ static inline void flush_icache_range(unsigned long start, unsigned long end)
kick_all_cpus_sync(); kick_all_cpus_sync();
} }
#define flush_icache_range flush_icache_range
static inline void flush_cache_mm(struct mm_struct *mm)
{
}
static inline void flush_cache_page(struct vm_area_struct *vma,
unsigned long user_addr, unsigned long pfn)
{
}
static inline void flush_cache_range(struct vm_area_struct *vma,
unsigned long start, unsigned long end)
{
}
/* /*
* Cache maintenance functions used by the DMA API. No to be used directly. * Cache maintenance functions used by the DMA API. No to be used directly.
@ -123,12 +110,7 @@ extern void __dma_flush_area(const void *, size_t);
*/ */
extern void copy_to_user_page(struct vm_area_struct *, struct page *, extern void copy_to_user_page(struct vm_area_struct *, struct page *,
unsigned long, void *, const void *, unsigned long); unsigned long, void *, const void *, unsigned long);
#define copy_from_user_page(vma, page, vaddr, dst, src, len) \ #define copy_to_user_page copy_to_user_page
do { \
memcpy(dst, src, len); \
} while (0)
#define flush_cache_dup_mm(mm) flush_cache_mm(mm)
/* /*
* flush_dcache_page is used when the kernel has written to the page * flush_dcache_page is used when the kernel has written to the page
@ -154,29 +136,11 @@ static __always_inline void __flush_icache_all(void)
dsb(ish); dsb(ish);
} }
#define flush_dcache_mmap_lock(mapping) do { } while (0)
#define flush_dcache_mmap_unlock(mapping) do { } while (0)
/*
* We don't appear to need to do anything here. In fact, if we did, we'd
* duplicate cache flushing elsewhere performed by flush_dcache_page().
*/
#define flush_icache_page(vma,page) do { } while (0)
/*
* Not required on AArch64 (PIPT or VIPT non-aliasing D-cache).
*/
static inline void flush_cache_vmap(unsigned long start, unsigned long end)
{
}
static inline void flush_cache_vunmap(unsigned long start, unsigned long end)
{
}
int set_memory_valid(unsigned long addr, int numpages, int enable); int set_memory_valid(unsigned long addr, int numpages, int enable);
int set_direct_map_invalid_noflush(struct page *page); int set_direct_map_invalid_noflush(struct page *page);
int set_direct_map_default_noflush(struct page *page); int set_direct_map_default_noflush(struct page *page);
#endif #include <asm-generic/cacheflush.h>
#endif /* __ASM_CACHEFLUSH_H */

View File

@ -16,21 +16,6 @@
#include <asm/page.h> #include <asm/page.h>
#include <asm/string.h> #include <asm/string.h>
/*
* virtually-indexed cache management (our cache is physically indexed)
*/
#define flush_cache_all() do {} while (0)
#define flush_cache_mm(mm) do {} while (0)
#define flush_cache_dup_mm(mm) do {} while (0)
#define flush_cache_range(mm, start, end) do {} while (0)
#define flush_cache_page(vma, vmaddr, pfn) do {} while (0)
#define flush_cache_vmap(start, end) do {} while (0)
#define flush_cache_vunmap(start, end) do {} while (0)
#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 0
#define flush_dcache_page(page) do {} while (0)
#define flush_dcache_mmap_lock(mapping) do {} while (0)
#define flush_dcache_mmap_unlock(mapping) do {} while (0)
/* /*
* physically-indexed cache management * physically-indexed cache management
*/ */
@ -49,14 +34,12 @@ do { \
(unsigned long) page_address(page) + PAGE_SIZE)); \ (unsigned long) page_address(page) + PAGE_SIZE)); \
} while (0) } while (0)
#define copy_to_user_page(vma, page, vaddr, dst, src, len) \ #define copy_to_user_page(vma, page, vaddr, dst, src, len) \
do { \ do { \
memcpy(dst, src, len); \ memcpy(dst, src, len); \
flush_icache_range((unsigned) (dst), (unsigned) (dst) + (len)); \ flush_icache_range((unsigned) (dst), (unsigned) (dst) + (len)); \
} while (0) } while (0)
#define copy_from_user_page(vma, page, vaddr, dst, src, len) \ #include <asm-generic/cacheflush.h>
memcpy(dst, src, len)
#endif /* _ASM_C6X_CACHEFLUSH_H */ #endif /* _ASM_C6X_CACHEFLUSH_H */

View File

@ -25,29 +25,17 @@
#define LINESIZE 32 #define LINESIZE 32
#define LINEBITS 5 #define LINEBITS 5
#define flush_cache_all() do { } while (0)
#define flush_cache_mm(mm) do { } while (0)
#define flush_cache_dup_mm(mm) do { } while (0)
#define flush_cache_range(vma, start, end) do { } while (0)
#define flush_cache_page(vma, vmaddr, pfn) do { } while (0)
#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 0
#define flush_dcache_page(page) do { } while (0)
#define flush_dcache_mmap_lock(mapping) do { } while (0)
#define flush_dcache_mmap_unlock(mapping) do { } while (0)
#define flush_icache_page(vma, pg) do { } while (0)
#define flush_icache_user_range(vma, pg, adr, len) do { } while (0)
#define flush_cache_vmap(start, end) do { } while (0)
#define flush_cache_vunmap(start, end) do { } while (0)
/* /*
* Flush Dcache range through current map. * Flush Dcache range through current map.
*/ */
extern void flush_dcache_range(unsigned long start, unsigned long end); extern void flush_dcache_range(unsigned long start, unsigned long end);
#define flush_dcache_range flush_dcache_range
/* /*
* Flush Icache range through current map. * Flush Icache range through current map.
*/ */
extern void flush_icache_range(unsigned long start, unsigned long end); extern void flush_icache_range(unsigned long start, unsigned long end);
#define flush_icache_range flush_icache_range
/* /*
* Memory-management related flushes are there to ensure in non-physically * Memory-management related flushes are there to ensure in non-physically
@ -78,6 +66,7 @@ static inline void update_mmu_cache(struct vm_area_struct *vma,
void copy_to_user_page(struct vm_area_struct *vma, struct page *page, void copy_to_user_page(struct vm_area_struct *vma, struct page *page,
unsigned long vaddr, void *dst, void *src, int len); unsigned long vaddr, void *dst, void *src, int len);
#define copy_to_user_page copy_to_user_page
#define copy_from_user_page(vma, page, vaddr, dst, src, len) \ #define copy_from_user_page(vma, page, vaddr, dst, src, len) \
memcpy(dst, src, len) memcpy(dst, src, len)
@ -85,4 +74,6 @@ void copy_to_user_page(struct vm_area_struct *vma, struct page *page,
extern void hexagon_inv_dcache_range(unsigned long start, unsigned long end); extern void hexagon_inv_dcache_range(unsigned long start, unsigned long end);
extern void hexagon_clean_dcache_range(unsigned long start, unsigned long end); extern void hexagon_clean_dcache_range(unsigned long start, unsigned long end);
#include <asm-generic/cacheflush.h>
#endif #endif

View File

@ -12,44 +12,22 @@
#include <asm/page.h> #include <asm/page.h>
/*
* Cache flushing routines. This is the kind of stuff that can be very expensive, so try
* to avoid them whenever possible.
*/
#define flush_cache_all() do { } while (0)
#define flush_cache_mm(mm) do { } while (0)
#define flush_cache_dup_mm(mm) do { } while (0)
#define flush_cache_range(vma, start, end) do { } while (0)
#define flush_cache_page(vma, vmaddr, pfn) do { } while (0)
#define flush_icache_page(vma,page) do { } while (0)
#define flush_cache_vmap(start, end) do { } while (0)
#define flush_cache_vunmap(start, end) do { } while (0)
#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1 #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1
#define flush_dcache_page(page) \ #define flush_dcache_page(page) \
do { \ do { \
clear_bit(PG_arch_1, &(page)->flags); \ clear_bit(PG_arch_1, &(page)->flags); \
} while (0) } while (0)
#define flush_dcache_mmap_lock(mapping) do { } while (0) extern void flush_icache_range(unsigned long start, unsigned long end);
#define flush_dcache_mmap_unlock(mapping) do { } while (0) #define flush_icache_range flush_icache_range
extern void flush_icache_range (unsigned long start, unsigned long end);
extern void clflush_cache_range(void *addr, int size); extern void clflush_cache_range(void *addr, int size);
#define flush_icache_user_page(vma, page, user_addr, len) \
#define flush_icache_user_range(vma, page, user_addr, len) \
do { \ do { \
unsigned long _addr = (unsigned long) page_address(page) + ((user_addr) & ~PAGE_MASK); \ unsigned long _addr = (unsigned long) page_address(page) + ((user_addr) & ~PAGE_MASK); \
flush_icache_range(_addr, _addr + (len)); \ flush_icache_range(_addr, _addr + (len)); \
} while (0) } while (0)
#define copy_to_user_page(vma, page, vaddr, dst, src, len) \ #include <asm-generic/cacheflush.h>
do { memcpy(dst, src, len); \
flush_icache_user_range(vma, page, vaddr, len); \
} while (0)
#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
memcpy(dst, src, len)
#endif /* _ASM_IA64_CACHEFLUSH_H */ #endif /* _ASM_IA64_CACHEFLUSH_H */

View File

@ -254,9 +254,11 @@ static inline void __flush_page_to_ram(void *vaddr)
#define flush_dcache_mmap_unlock(mapping) do { } while (0) #define flush_dcache_mmap_unlock(mapping) do { } while (0)
#define flush_icache_page(vma, page) __flush_page_to_ram(page_address(page)) #define flush_icache_page(vma, page) __flush_page_to_ram(page_address(page))
extern void flush_icache_user_range(struct vm_area_struct *vma, struct page *page, extern void flush_icache_user_page(struct vm_area_struct *vma, struct page *page,
unsigned long addr, int len); unsigned long addr, int len);
extern void flush_icache_range(unsigned long address, unsigned long endaddr); extern void flush_icache_range(unsigned long address, unsigned long endaddr);
extern void flush_icache_user_range(unsigned long address,
unsigned long endaddr);
static inline void copy_to_user_page(struct vm_area_struct *vma, static inline void copy_to_user_page(struct vm_area_struct *vma,
struct page *page, unsigned long vaddr, struct page *page, unsigned long vaddr,
@ -264,7 +266,7 @@ static inline void copy_to_user_page(struct vm_area_struct *vma,
{ {
flush_cache_page(vma, vaddr, page_to_pfn(page)); flush_cache_page(vma, vaddr, page_to_pfn(page));
memcpy(dst, src, len); memcpy(dst, src, len);
flush_icache_user_range(vma, page, vaddr, len); flush_icache_user_page(vma, page, vaddr, len);
} }
static inline void copy_from_user_page(struct vm_area_struct *vma, static inline void copy_from_user_page(struct vm_area_struct *vma,
struct page *page, unsigned long vaddr, struct page *page, unsigned long vaddr,

View File

@ -9,25 +9,8 @@
#include <asm/mcfsim.h> #include <asm/mcfsim.h>
#define flush_cache_all() __flush_cache_all() #define flush_cache_all() __flush_cache_all()
#define flush_cache_mm(mm) do { } while (0)
#define flush_cache_dup_mm(mm) do { } while (0)
#define flush_cache_range(vma, start, end) do { } while (0)
#define flush_cache_page(vma, vmaddr) do { } while (0)
#define flush_dcache_range(start, len) __flush_dcache_all() #define flush_dcache_range(start, len) __flush_dcache_all()
#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 0
#define flush_dcache_page(page) do { } while (0)
#define flush_dcache_mmap_lock(mapping) do { } while (0)
#define flush_dcache_mmap_unlock(mapping) do { } while (0)
#define flush_icache_range(start, len) __flush_icache_all() #define flush_icache_range(start, len) __flush_icache_all()
#define flush_icache_page(vma,pg) do { } while (0)
#define flush_icache_user_range(vma,pg,adr,len) do { } while (0)
#define flush_cache_vmap(start, end) do { } while (0)
#define flush_cache_vunmap(start, end) do { } while (0)
#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
memcpy(dst, src, len)
#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
memcpy(dst, src, len)
void mcf_cache_push(void); void mcf_cache_push(void);
@ -98,4 +81,6 @@ static inline void cache_clear(unsigned long paddr, int len)
__clear_cache_all(); __clear_cache_all();
} }
#include <asm-generic/cacheflush.h>
#endif /* _M68KNOMMU_CACHEFLUSH_H */ #endif /* _M68KNOMMU_CACHEFLUSH_H */

View File

@ -73,7 +73,7 @@ static unsigned long virt_to_phys_slow(unsigned long vaddr)
/* Push n pages at kernel virtual address and clear the icache */ /* Push n pages at kernel virtual address and clear the icache */
/* RZ: use cpush %bc instead of cpush %dc, cinv %ic */ /* RZ: use cpush %bc instead of cpush %dc, cinv %ic */
void flush_icache_range(unsigned long address, unsigned long endaddr) void flush_icache_user_range(unsigned long address, unsigned long endaddr)
{ {
if (CPU_IS_COLDFIRE) { if (CPU_IS_COLDFIRE) {
unsigned long start, end; unsigned long start, end;
@ -104,9 +104,18 @@ void flush_icache_range(unsigned long address, unsigned long endaddr)
: "di" (FLUSH_I)); : "di" (FLUSH_I));
} }
} }
void flush_icache_range(unsigned long address, unsigned long endaddr)
{
mm_segment_t old_fs = get_fs();
set_fs(KERNEL_DS);
flush_icache_user_range(address, endaddr);
set_fs(old_fs);
}
EXPORT_SYMBOL(flush_icache_range); EXPORT_SYMBOL(flush_icache_range);
void flush_icache_user_range(struct vm_area_struct *vma, struct page *page, void flush_icache_user_page(struct vm_area_struct *vma, struct page *page,
unsigned long addr, int len) unsigned long addr, int len)
{ {
if (CPU_IS_COLDFIRE) { if (CPU_IS_COLDFIRE) {

View File

@ -57,9 +57,6 @@ void microblaze_cache_init(void);
#define invalidate_icache() mbc->iin(); #define invalidate_icache() mbc->iin();
#define invalidate_icache_range(start, end) mbc->iinr(start, end); #define invalidate_icache_range(start, end) mbc->iinr(start, end);
#define flush_icache_user_range(vma, pg, adr, len) flush_icache();
#define flush_icache_page(vma, pg) do { } while (0)
#define enable_dcache() mbc->de(); #define enable_dcache() mbc->de();
#define disable_dcache() mbc->dd(); #define disable_dcache() mbc->dd();
/* FIXME for LL-temac driver */ /* FIXME for LL-temac driver */
@ -77,27 +74,9 @@ do { \
flush_dcache_range((unsigned) (addr), (unsigned) (addr) + PAGE_SIZE); \ flush_dcache_range((unsigned) (addr), (unsigned) (addr) + PAGE_SIZE); \
} while (0); } while (0);
#define flush_dcache_mmap_lock(mapping) do { } while (0)
#define flush_dcache_mmap_unlock(mapping) do { } while (0)
#define flush_cache_dup_mm(mm) do { } while (0)
#define flush_cache_vmap(start, end) do { } while (0)
#define flush_cache_vunmap(start, end) do { } while (0)
#define flush_cache_mm(mm) do { } while (0)
#define flush_cache_page(vma, vmaddr, pfn) \ #define flush_cache_page(vma, vmaddr, pfn) \
flush_dcache_range(pfn << PAGE_SHIFT, (pfn << PAGE_SHIFT) + PAGE_SIZE); flush_dcache_range(pfn << PAGE_SHIFT, (pfn << PAGE_SHIFT) + PAGE_SIZE);
/* MS: kgdb code use this macro, wrong len with FLASH */
#if 0
#define flush_cache_range(vma, start, len) { \
flush_icache_range((unsigned) (start), (unsigned) (start) + (len)); \
flush_dcache_range((unsigned) (start), (unsigned) (start) + (len)); \
}
#endif
#define flush_cache_range(vma, start, len) do { } while (0)
static inline void copy_to_user_page(struct vm_area_struct *vma, static inline void copy_to_user_page(struct vm_area_struct *vma,
struct page *page, unsigned long vaddr, struct page *page, unsigned long vaddr,
void *dst, void *src, int len) void *dst, void *src, int len)
@ -109,12 +88,8 @@ static inline void copy_to_user_page(struct vm_area_struct *vma,
flush_dcache_range(addr, addr + PAGE_SIZE); flush_dcache_range(addr, addr + PAGE_SIZE);
} }
} }
#define copy_to_user_page copy_to_user_page
static inline void copy_from_user_page(struct vm_area_struct *vma, #include <asm-generic/cacheflush.h>
struct page *page, unsigned long vaddr,
void *dst, void *src, int len)
{
memcpy(dst, src, len);
}
#endif /* _ASM_MICROBLAZE_CACHEFLUSH_H */ #endif /* _ASM_MICROBLAZE_CACHEFLUSH_H */

View File

@ -44,9 +44,9 @@ void invalidate_kernel_vmap_range(void *addr, int size);
#define flush_dcache_mmap_unlock(mapping) xa_unlock_irq(&(mapping)->i_pages) #define flush_dcache_mmap_unlock(mapping) xa_unlock_irq(&(mapping)->i_pages)
#else #else
void flush_icache_user_range(struct vm_area_struct *vma, struct page *page, void flush_icache_user_page(struct vm_area_struct *vma, struct page *page,
unsigned long addr, int len); unsigned long addr, int len);
#define flush_icache_user_range flush_icache_user_range #define flush_icache_user_page flush_icache_user_page
#include <asm-generic/cacheflush.h> #include <asm-generic/cacheflush.h>
#endif #endif

View File

@ -35,9 +35,8 @@ void flush_icache_page(struct vm_area_struct *vma, struct page *page)
kunmap_atomic((void *)kaddr); kunmap_atomic((void *)kaddr);
local_irq_restore(flags); local_irq_restore(flags);
} }
EXPORT_SYMBOL(flush_icache_page);
void flush_icache_user_range(struct vm_area_struct *vma, struct page *page, void flush_icache_user_page(struct vm_area_struct *vma, struct page *page,
unsigned long addr, int len) unsigned long addr, int len)
{ {
unsigned long kaddr; unsigned long kaddr;

View File

@ -62,31 +62,12 @@ static inline void flush_dcache_page(struct page *page)
clear_bit(PG_dc_clean, &page->flags); clear_bit(PG_dc_clean, &page->flags);
} }
/* #define flush_icache_user_page(vma, page, addr, len) \
* Other interfaces are not required since we do not have virtually do { \
* indexed or tagged caches. So we can use the default here. if (vma->vm_flags & VM_EXEC) \
*/ sync_icache_dcache(page); \
#define flush_cache_all() do { } while (0) } while (0)
#define flush_cache_mm(mm) do { } while (0)
#define flush_cache_dup_mm(mm) do { } while (0)
#define flush_cache_range(vma, start, end) do { } while (0)
#define flush_cache_page(vma, vmaddr, pfn) do { } while (0)
#define flush_dcache_mmap_lock(mapping) do { } while (0)
#define flush_dcache_mmap_unlock(mapping) do { } while (0)
#define flush_icache_range(start, end) do { } while (0)
#define flush_icache_page(vma, pg) do { } while (0)
#define flush_icache_user_range(vma, pg, adr, len) do { } while (0)
#define flush_cache_vmap(start, end) do { } while (0)
#define flush_cache_vunmap(start, end) do { } while (0)
#define copy_to_user_page(vma, page, vaddr, dst, src, len) \ #include <asm-generic/cacheflush.h>
do { \
memcpy(dst, src, len); \
if (vma->vm_flags & VM_EXEC) \
sync_icache_dcache(page); \
} while (0)
#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
memcpy(dst, src, len)
#endif /* __ASM_CACHEFLUSH_H */ #endif /* __ASM_CACHEFLUSH_H */

View File

@ -4,23 +4,9 @@
#ifndef _ASM_POWERPC_CACHEFLUSH_H #ifndef _ASM_POWERPC_CACHEFLUSH_H
#define _ASM_POWERPC_CACHEFLUSH_H #define _ASM_POWERPC_CACHEFLUSH_H
#ifdef __KERNEL__
#include <linux/mm.h> #include <linux/mm.h>
#include <asm/cputable.h> #include <asm/cputable.h>
/*
* No cache flushing is required when address mappings are changed,
* because the caches on PowerPCs are physically addressed.
*/
#define flush_cache_all() do { } while (0)
#define flush_cache_mm(mm) do { } while (0)
#define flush_cache_dup_mm(mm) do { } while (0)
#define flush_cache_range(vma, start, end) do { } while (0)
#define flush_cache_page(vma, vmaddr, pfn) do { } while (0)
#define flush_icache_page(vma, page) do { } while (0)
#define flush_cache_vunmap(start, end) do { } while (0)
#ifdef CONFIG_PPC_BOOK3S_64 #ifdef CONFIG_PPC_BOOK3S_64
/* /*
* Book3s has no ptesync after setting a pte, so without this ptesync it's * Book3s has no ptesync after setting a pte, so without this ptesync it's
@ -33,20 +19,20 @@ static inline void flush_cache_vmap(unsigned long start, unsigned long end)
{ {
asm volatile("ptesync" ::: "memory"); asm volatile("ptesync" ::: "memory");
} }
#else #define flush_cache_vmap flush_cache_vmap
static inline void flush_cache_vmap(unsigned long start, unsigned long end) { } #endif /* CONFIG_PPC_BOOK3S_64 */
#endif
#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1 #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1
extern void flush_dcache_page(struct page *page); extern void flush_dcache_page(struct page *page);
#define flush_dcache_mmap_lock(mapping) do { } while (0)
#define flush_dcache_mmap_unlock(mapping) do { } while (0)
void flush_icache_range(unsigned long start, unsigned long stop); void flush_icache_range(unsigned long start, unsigned long stop);
extern void flush_icache_user_range(struct vm_area_struct *vma, #define flush_icache_range flush_icache_range
struct page *page, unsigned long addr,
int len); void flush_icache_user_page(struct vm_area_struct *vma, struct page *page,
extern void flush_dcache_icache_page(struct page *page); unsigned long addr, int len);
#define flush_icache_user_page flush_icache_user_page
void flush_dcache_icache_page(struct page *page);
void __flush_dcache_icache(void *page); void __flush_dcache_icache(void *page);
/** /**
@ -111,14 +97,6 @@ static inline void invalidate_dcache_range(unsigned long start,
mb(); /* sync */ mb(); /* sync */
} }
#define copy_to_user_page(vma, page, vaddr, dst, src, len) \ #include <asm-generic/cacheflush.h>
do { \
memcpy(dst, src, len); \
flush_icache_user_range(vma, page, vaddr, len); \
} while (0)
#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
memcpy(dst, src, len)
#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_CACHEFLUSH_H */ #endif /* _ASM_POWERPC_CACHEFLUSH_H */

View File

@ -581,7 +581,7 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
* We always ask for write permission since the common case * We always ask for write permission since the common case
* is that the page is writable. * is that the page is writable.
*/ */
if (__get_user_pages_fast(hva, 1, 1, &page) == 1) { if (get_user_page_fast_only(hva, FOLL_WRITE, &page)) {
write_ok = true; write_ok = true;
} else { } else {
/* Call KVM generic code to do the slow-path check */ /* Call KVM generic code to do the slow-path check */

View File

@ -795,7 +795,7 @@ int kvmppc_book3s_instantiate_page(struct kvm_vcpu *vcpu,
* is that the page is writable. * is that the page is writable.
*/ */
hva = gfn_to_hva_memslot(memslot, gfn); hva = gfn_to_hva_memslot(memslot, gfn);
if (!kvm_ro && __get_user_pages_fast(hva, 1, 1, &page) == 1) { if (!kvm_ro && get_user_page_fast_only(hva, FOLL_WRITE, &page)) {
upgrade_write = true; upgrade_write = true;
} else { } else {
unsigned long pfn; unsigned long pfn;

View File

@ -577,7 +577,7 @@ void copy_user_page(void *vto, void *vfrom, unsigned long vaddr,
flush_dcache_page(pg); flush_dcache_page(pg);
} }
void flush_icache_user_range(struct vm_area_struct *vma, struct page *page, void flush_icache_user_page(struct vm_area_struct *vma, struct page *page,
unsigned long addr, int len) unsigned long addr, int len)
{ {
unsigned long maddr; unsigned long maddr;
@ -586,7 +586,6 @@ void flush_icache_user_range(struct vm_area_struct *vma, struct page *page,
flush_icache_range(maddr, maddr + len); flush_icache_range(maddr, maddr + len);
kunmap(page); kunmap(page);
} }
EXPORT_SYMBOL(flush_icache_user_range);
/* /*
* System memory should not be in /proc/iomem but various tools expect it * System memory should not be in /proc/iomem but various tools expect it

View File

@ -30,11 +30,9 @@ int read_user_stack_slow(void __user *ptr, void *buf, int nb)
unsigned long addr = (unsigned long) ptr; unsigned long addr = (unsigned long) ptr;
unsigned long offset; unsigned long offset;
struct page *page; struct page *page;
int nrpages;
void *kaddr; void *kaddr;
nrpages = __get_user_pages_fast(addr, 1, 1, &page); if (get_user_page_fast_only(addr, FOLL_WRITE, &page)) {
if (nrpages == 1) {
kaddr = page_address(page); kaddr = page_address(page);
/* align address to page boundary */ /* align address to page boundary */

View File

@ -8,65 +8,6 @@
#include <linux/mm.h> #include <linux/mm.h>
#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 0
/*
* The cache doesn't need to be flushed when TLB entries change when
* the cache is mapped to physical memory, not virtual memory
*/
static inline void flush_cache_all(void)
{
}
static inline void flush_cache_mm(struct mm_struct *mm)
{
}
static inline void flush_cache_dup_mm(struct mm_struct *mm)
{
}
static inline void flush_cache_range(struct vm_area_struct *vma,
unsigned long start,
unsigned long end)
{
}
static inline void flush_cache_page(struct vm_area_struct *vma,
unsigned long vmaddr,
unsigned long pfn)
{
}
static inline void flush_dcache_mmap_lock(struct address_space *mapping)
{
}
static inline void flush_dcache_mmap_unlock(struct address_space *mapping)
{
}
static inline void flush_icache_page(struct vm_area_struct *vma,
struct page *page)
{
}
static inline void flush_cache_vmap(unsigned long start, unsigned long end)
{
}
static inline void flush_cache_vunmap(unsigned long start, unsigned long end)
{
}
#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
do { \
memcpy(dst, src, len); \
flush_icache_user_range(vma, page, vaddr, len); \
} while (0)
#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
memcpy(dst, src, len)
static inline void local_flush_icache_all(void) static inline void local_flush_icache_all(void)
{ {
asm volatile ("fence.i" ::: "memory"); asm volatile ("fence.i" ::: "memory");
@ -79,13 +20,15 @@ static inline void flush_dcache_page(struct page *page)
if (test_bit(PG_dcache_clean, &page->flags)) if (test_bit(PG_dcache_clean, &page->flags))
clear_bit(PG_dcache_clean, &page->flags); clear_bit(PG_dcache_clean, &page->flags);
} }
#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1
/* /*
* RISC-V doesn't have an instruction to flush parts of the instruction cache, * RISC-V doesn't have an instruction to flush parts of the instruction cache,
* so instead we just flush the whole thing. * so instead we just flush the whole thing.
*/ */
#define flush_icache_range(start, end) flush_icache_all() #define flush_icache_range(start, end) flush_icache_all()
#define flush_icache_user_range(vma, pg, addr, len) flush_icache_mm(vma->vm_mm, 0) #define flush_icache_user_page(vma, pg, addr, len) \
flush_icache_mm(vma->vm_mm, 0)
#ifndef CONFIG_SMP #ifndef CONFIG_SMP
@ -105,4 +48,6 @@ void flush_icache_mm(struct mm_struct *mm, bool local);
#define SYS_RISCV_FLUSH_ICACHE_LOCAL 1UL #define SYS_RISCV_FLUSH_ICACHE_LOCAL 1UL
#define SYS_RISCV_FLUSH_ICACHE_ALL (SYS_RISCV_FLUSH_ICACHE_LOCAL) #define SYS_RISCV_FLUSH_ICACHE_ALL (SYS_RISCV_FLUSH_ICACHE_LOCAL)
#include <asm-generic/cacheflush.h>
#endif /* _ASM_RISCV_CACHEFLUSH_H */ #endif /* _ASM_RISCV_CACHEFLUSH_H */

View File

@ -46,6 +46,7 @@ extern void flush_cache_range(struct vm_area_struct *vma,
#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1 #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1
extern void flush_dcache_page(struct page *page); extern void flush_dcache_page(struct page *page);
extern void flush_icache_range(unsigned long start, unsigned long end); extern void flush_icache_range(unsigned long start, unsigned long end);
#define flush_icache_user_range flush_icache_range
extern void flush_icache_page(struct vm_area_struct *vma, extern void flush_icache_page(struct vm_area_struct *vma,
struct page *page); struct page *page);
extern void flush_cache_sigtramp(unsigned long address); extern void flush_cache_sigtramp(unsigned long address);

View File

@ -17,8 +17,6 @@
#define flush_icache_range(start, end) do { } while (0) #define flush_icache_range(start, end) do { } while (0)
#define flush_icache_page(vma, pg) do { } while (0) #define flush_icache_page(vma, pg) do { } while (0)
#define flush_icache_user_range(vma,pg,adr,len) do { } while (0)
#define copy_to_user_page(vma, page, vaddr, dst, src, len) \ #define copy_to_user_page(vma, page, vaddr, dst, src, len) \
do { \ do { \
flush_cache_page(vma, vaddr, page_to_pfn(page));\ flush_cache_page(vma, vaddr, page_to_pfn(page));\

View File

@ -49,7 +49,6 @@ void __flush_dcache_range(unsigned long start, unsigned long end);
void flush_dcache_page(struct page *page); void flush_dcache_page(struct page *page);
#define flush_icache_page(vma, pg) do { } while(0) #define flush_icache_page(vma, pg) do { } while(0)
#define flush_icache_user_range(vma,pg,adr,len) do { } while (0)
void flush_ptrace_access(struct vm_area_struct *, struct page *, void flush_ptrace_access(struct vm_area_struct *, struct page *,
unsigned long uaddr, void *kaddr, unsigned long uaddr, void *kaddr,

View File

@ -2,6 +2,8 @@
#ifndef __UM_TLB_H #ifndef __UM_TLB_H
#define __UM_TLB_H #define __UM_TLB_H
#include <linux/mm.h>
#include <asm/tlbflush.h> #include <asm/tlbflush.h>
#include <asm-generic/cacheflush.h> #include <asm-generic/cacheflush.h>
#include <asm-generic/tlb.h> #include <asm-generic/tlb.h>

View File

@ -132,14 +132,6 @@ extern void flush_cache_page(struct vm_area_struct *vma,
#define flush_cache_dup_mm(mm) flush_cache_mm(mm) #define flush_cache_dup_mm(mm) flush_cache_mm(mm)
/*
* flush_cache_user_range is used when we want to ensure that the
* Harvard caches are synchronised for the user space address range.
* This is used for the UniCore private sys_cacheflush system call.
*/
#define flush_cache_user_range(vma, start, end) \
__cpuc_coherent_user_range((start) & PAGE_MASK, PAGE_ALIGN(end))
/* /*
* Perform necessary cache operations to ensure that data previously * Perform necessary cache operations to ensure that data previously
* stored within this range of addresses can be executed by the CPU. * stored within this range of addresses can be executed by the CPU.
@ -170,9 +162,6 @@ extern void flush_dcache_page(struct page *);
#define flush_dcache_mmap_lock(mapping) do { } while (0) #define flush_dcache_mmap_lock(mapping) do { } while (0)
#define flush_dcache_mmap_unlock(mapping) do { } while (0) #define flush_dcache_mmap_unlock(mapping) do { } while (0)
#define flush_icache_user_range(vma, page, addr, len) \
flush_dcache_page(page)
/* /*
* We don't appear to need to do anything here. In fact, if we did, we'd * We don't appear to need to do anything here. In fact, if we did, we'd
* duplicate cache flushing elsewhere performed by flush_dcache_page(). * duplicate cache flushing elsewhere performed by flush_dcache_page().

View File

@ -2,6 +2,8 @@
#ifndef _ASM_X86_CACHEFLUSH_H #ifndef _ASM_X86_CACHEFLUSH_H
#define _ASM_X86_CACHEFLUSH_H #define _ASM_X86_CACHEFLUSH_H
#include <linux/mm.h>
/* Caches aren't brain-dead on the intel. */ /* Caches aren't brain-dead on the intel. */
#include <asm-generic/cacheflush.h> #include <asm-generic/cacheflush.h>
#include <asm/special_insns.h> #include <asm/special_insns.h>

View File

@ -145,6 +145,8 @@ void local_flush_cache_page(struct vm_area_struct *vma,
#endif #endif
#define flush_icache_user_range flush_icache_range
/* Ensure consistency between data and instruction cache. */ /* Ensure consistency between data and instruction cache. */
#define local_flush_icache_range(start, end) \ #define local_flush_icache_range(start, end) \
do { \ do { \

View File

@ -10,7 +10,6 @@
* Sakari Ailus <sakari.ailus@iki.fi> * Sakari Ailus <sakari.ailus@iki.fi>
*/ */
#include <asm/cacheflush.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/module.h> #include <linux/module.h>
@ -19,6 +18,7 @@
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <asm/cacheflush.h>
#include <media/v4l2-dev.h> #include <media/v4l2-dev.h>
#include <media/v4l2-ioctl.h> #include <media/v4l2-ioctl.h>

View File

@ -7,7 +7,6 @@
* Copyright (c) 2015, Boaz Harrosh <boaz@plexistor.com>. * Copyright (c) 2015, Boaz Harrosh <boaz@plexistor.com>.
*/ */
#include <asm/cacheflush.h>
#include <linux/blkdev.h> #include <linux/blkdev.h>
#include <linux/hdreg.h> #include <linux/hdreg.h>
#include <linux/init.h> #include <linux/init.h>
@ -25,6 +24,8 @@
#include <linux/dax.h> #include <linux/dax.h>
#include <linux/nd.h> #include <linux/nd.h>
#include <linux/backing-dev.h> #include <linux/backing-dev.h>
#include <linux/mm.h>
#include <asm/cacheflush.h>
#include "pmem.h" #include "pmem.h"
#include "pfn.h" #include "pfn.h"
#include "nd.h" #include "nd.h"

View File

@ -1762,15 +1762,14 @@ static int set_bit_to_user(int nr, void __user *addr)
int bit = nr + (log % PAGE_SIZE) * 8; int bit = nr + (log % PAGE_SIZE) * 8;
int r; int r;
r = get_user_pages_fast(log, 1, FOLL_WRITE, &page); r = pin_user_pages_fast(log, 1, FOLL_WRITE, &page);
if (r < 0) if (r < 0)
return r; return r;
BUG_ON(r != 1); BUG_ON(r != 1);
base = kmap_atomic(page); base = kmap_atomic(page);
set_bit(bit, base); set_bit(bit, base);
kunmap_atomic(base); kunmap_atomic(base);
set_page_dirty_lock(page); unpin_user_pages_dirty_lock(&page, 1, true);
put_page(page);
return 0; return 0;
} }

View File

@ -854,7 +854,7 @@ static int load_flat_file(struct linux_binprm *bprm,
#endif /* CONFIG_BINFMT_FLAT_OLD */ #endif /* CONFIG_BINFMT_FLAT_OLD */
} }
flush_icache_range(start_code, end_code); flush_icache_user_range(start_code, end_code);
/* zero the BSS, BRK and stack areas */ /* zero the BSS, BRK and stack areas */
if (clear_user((void __user *)(datapos + data_len), bss_len + if (clear_user((void __user *)(datapos + data_len), bss_len +

View File

@ -1053,14 +1053,17 @@ out:
} }
EXPORT_SYMBOL_GPL(kernel_read_file_from_fd); EXPORT_SYMBOL_GPL(kernel_read_file_from_fd);
#if defined(CONFIG_HAVE_AOUT) || defined(CONFIG_BINFMT_FLAT) || \
defined(CONFIG_BINFMT_ELF_FDPIC)
ssize_t read_code(struct file *file, unsigned long addr, loff_t pos, size_t len) ssize_t read_code(struct file *file, unsigned long addr, loff_t pos, size_t len)
{ {
ssize_t res = vfs_read(file, (void __user *)addr, len, &pos); ssize_t res = vfs_read(file, (void __user *)addr, len, &pos);
if (res > 0) if (res > 0)
flush_icache_range(addr, addr + len); flush_icache_user_range(addr, addr + len);
return res; return res;
} }
EXPORT_SYMBOL(read_code); EXPORT_SYMBOL(read_code);
#endif
/* /*
* Maps the mm_struct mm into the current task struct. * Maps the mm_struct mm into the current task struct.

View File

@ -14,6 +14,7 @@
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/bpf-cgroup.h> #include <linux/bpf-cgroup.h>
#include <linux/mount.h>
#include "internal.h" #include "internal.h"
static const struct dentry_operations proc_sys_dentry_operations; static const struct dentry_operations proc_sys_dentry_operations;
@ -1703,3 +1704,147 @@ int __init proc_sys_init(void)
return sysctl_init(); return sysctl_init();
} }
struct sysctl_alias {
const char *kernel_param;
const char *sysctl_param;
};
/*
* Historically some settings had both sysctl and a command line parameter.
* With the generic sysctl. parameter support, we can handle them at a single
* place and only keep the historical name for compatibility. This is not meant
* to add brand new aliases. When adding existing aliases, consider whether
* the possibly different moment of changing the value (e.g. from early_param
* to the moment do_sysctl_args() is called) is an issue for the specific
* parameter.
*/
static const struct sysctl_alias sysctl_aliases[] = {
{"hardlockup_all_cpu_backtrace", "kernel.hardlockup_all_cpu_backtrace" },
{"hung_task_panic", "kernel.hung_task_panic" },
{"numa_zonelist_order", "vm.numa_zonelist_order" },
{"softlockup_all_cpu_backtrace", "kernel.softlockup_all_cpu_backtrace" },
{"softlockup_panic", "kernel.softlockup_panic" },
{ }
};
static const char *sysctl_find_alias(char *param)
{
const struct sysctl_alias *alias;
for (alias = &sysctl_aliases[0]; alias->kernel_param != NULL; alias++) {
if (strcmp(alias->kernel_param, param) == 0)
return alias->sysctl_param;
}
return NULL;
}
/* Set sysctl value passed on kernel command line. */
static int process_sysctl_arg(char *param, char *val,
const char *unused, void *arg)
{
char *path;
struct vfsmount **proc_mnt = arg;
struct file_system_type *proc_fs_type;
struct file *file;
int len;
int err;
loff_t pos = 0;
ssize_t wret;
if (strncmp(param, "sysctl", sizeof("sysctl") - 1) == 0) {
param += sizeof("sysctl") - 1;
if (param[0] != '/' && param[0] != '.')
return 0;
param++;
} else {
param = (char *) sysctl_find_alias(param);
if (!param)
return 0;
}
/*
* To set sysctl options, we use a temporary mount of proc, look up the
* respective sys/ file and write to it. To avoid mounting it when no
* options were given, we mount it only when the first sysctl option is
* found. Why not a persistent mount? There are problems with a
* persistent mount of proc in that it forces userspace not to use any
* proc mount options.
*/
if (!*proc_mnt) {
proc_fs_type = get_fs_type("proc");
if (!proc_fs_type) {
pr_err("Failed to find procfs to set sysctl from command line\n");
return 0;
}
*proc_mnt = kern_mount(proc_fs_type);
put_filesystem(proc_fs_type);
if (IS_ERR(*proc_mnt)) {
pr_err("Failed to mount procfs to set sysctl from command line\n");
return 0;
}
}
path = kasprintf(GFP_KERNEL, "sys/%s", param);
if (!path)
panic("%s: Failed to allocate path for %s\n", __func__, param);
strreplace(path, '.', '/');
file = file_open_root((*proc_mnt)->mnt_root, *proc_mnt, path, O_WRONLY, 0);
if (IS_ERR(file)) {
err = PTR_ERR(file);
if (err == -ENOENT)
pr_err("Failed to set sysctl parameter '%s=%s': parameter not found\n",
param, val);
else if (err == -EACCES)
pr_err("Failed to set sysctl parameter '%s=%s': permission denied (read-only?)\n",
param, val);
else
pr_err("Error %pe opening proc file to set sysctl parameter '%s=%s'\n",
file, param, val);
goto out;
}
len = strlen(val);
wret = kernel_write(file, val, len, &pos);
if (wret < 0) {
err = wret;
if (err == -EINVAL)
pr_err("Failed to set sysctl parameter '%s=%s': invalid value\n",
param, val);
else
pr_err("Error %pe writing to proc file to set sysctl parameter '%s=%s'\n",
ERR_PTR(err), param, val);
} else if (wret != len) {
pr_err("Wrote only %zd bytes of %d writing to proc file %s to set sysctl parameter '%s=%s\n",
wret, len, path, param, val);
}
err = filp_close(file, NULL);
if (err)
pr_err("Error %pe closing proc file to set sysctl parameter '%s=%s\n",
ERR_PTR(err), param, val);
out:
kfree(path);
return 0;
}
void do_sysctl_args(void)
{
char *command_line;
struct vfsmount *proc_mnt = NULL;
command_line = kstrdup(saved_command_line, GFP_KERNEL);
if (!command_line)
panic("%s: Failed to allocate copy of command line\n", __func__);
parse_args("Setting sysctl args", command_line,
NULL, 0, -1, -1, &proc_mnt, process_sysctl_arg);
if (proc_mnt)
kern_unmount(proc_mnt);
kfree(command_line);
}

View File

@ -1,11 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 */ /* SPDX-License-Identifier: GPL-2.0 */
#ifndef __ASM_CACHEFLUSH_H #ifndef _ASM_GENERIC_CACHEFLUSH_H
#define __ASM_CACHEFLUSH_H #define _ASM_GENERIC_CACHEFLUSH_H
/* Keep includes the same across arches. */
#include <linux/mm.h>
#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 0
/* /*
* The cache doesn't need to be flushed when TLB entries change when * The cache doesn't need to be flushed when TLB entries change when
@ -45,12 +40,14 @@ static inline void flush_cache_page(struct vm_area_struct *vma,
} }
#endif #endif
#ifndef flush_dcache_page #ifndef ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE
static inline void flush_dcache_page(struct page *page) static inline void flush_dcache_page(struct page *page)
{ {
} }
#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 0
#endif #endif
#ifndef flush_dcache_mmap_lock #ifndef flush_dcache_mmap_lock
static inline void flush_dcache_mmap_lock(struct address_space *mapping) static inline void flush_dcache_mmap_lock(struct address_space *mapping)
{ {
@ -69,6 +66,10 @@ static inline void flush_icache_range(unsigned long start, unsigned long end)
} }
#endif #endif
#ifndef flush_icache_user_range
#define flush_icache_user_range flush_icache_range
#endif
#ifndef flush_icache_page #ifndef flush_icache_page
static inline void flush_icache_page(struct vm_area_struct *vma, static inline void flush_icache_page(struct vm_area_struct *vma,
struct page *page) struct page *page)
@ -76,8 +77,8 @@ static inline void flush_icache_page(struct vm_area_struct *vma,
} }
#endif #endif
#ifndef flush_icache_user_range #ifndef flush_icache_user_page
static inline void flush_icache_user_range(struct vm_area_struct *vma, static inline void flush_icache_user_page(struct vm_area_struct *vma,
struct page *page, struct page *page,
unsigned long addr, int len) unsigned long addr, int len)
{ {
@ -100,7 +101,7 @@ static inline void flush_cache_vunmap(unsigned long start, unsigned long end)
#define copy_to_user_page(vma, page, vaddr, dst, src, len) \ #define copy_to_user_page(vma, page, vaddr, dst, src, len) \
do { \ do { \
memcpy(dst, src, len); \ memcpy(dst, src, len); \
flush_icache_user_range(vma, page, vaddr, len); \ flush_icache_user_page(vma, page, vaddr, len); \
} while (0) } while (0)
#endif #endif
@ -109,4 +110,4 @@ static inline void flush_cache_vunmap(unsigned long start, unsigned long end)
memcpy(dst, src, len) memcpy(dst, src, len)
#endif #endif
#endif /* __ASM_CACHEFLUSH_H */ #endif /* _ASM_GENERIC_CACHEFLUSH_H */

View File

@ -109,7 +109,8 @@ void _dev_info(const struct device *dev, const char *fmt, ...)
#define dev_info(dev, fmt, ...) \ #define dev_info(dev, fmt, ...) \
_dev_info(dev, dev_fmt(fmt), ##__VA_ARGS__) _dev_info(dev, dev_fmt(fmt), ##__VA_ARGS__)
#if defined(CONFIG_DYNAMIC_DEBUG) #if defined(CONFIG_DYNAMIC_DEBUG) || \
(defined(CONFIG_DYNAMIC_DEBUG_CORE) && defined(DYNAMIC_DEBUG_MODULE))
#define dev_dbg(dev, fmt, ...) \ #define dev_dbg(dev, fmt, ...) \
dynamic_dev_dbg(dev, dev_fmt(fmt), ##__VA_ARGS__) dynamic_dev_dbg(dev, dev_fmt(fmt), ##__VA_ARGS__)
#elif defined(DEBUG) #elif defined(DEBUG)
@ -181,7 +182,8 @@ do { \
dev_level_ratelimited(dev_notice, dev, fmt, ##__VA_ARGS__) dev_level_ratelimited(dev_notice, dev, fmt, ##__VA_ARGS__)
#define dev_info_ratelimited(dev, fmt, ...) \ #define dev_info_ratelimited(dev, fmt, ...) \
dev_level_ratelimited(dev_info, dev, fmt, ##__VA_ARGS__) dev_level_ratelimited(dev_info, dev, fmt, ##__VA_ARGS__)
#if defined(CONFIG_DYNAMIC_DEBUG) #if defined(CONFIG_DYNAMIC_DEBUG) || \
(defined(CONFIG_DYNAMIC_DEBUG_CORE) && defined(DYNAMIC_DEBUG_MODULE))
/* descriptor check is first to prevent flooding with "callbacks suppressed" */ /* descriptor check is first to prevent flooding with "callbacks suppressed" */
#define dev_dbg_ratelimited(dev, fmt, ...) \ #define dev_dbg_ratelimited(dev, fmt, ...) \
do { \ do { \

View File

@ -48,7 +48,7 @@ struct _ddebug {
#if defined(CONFIG_DYNAMIC_DEBUG) #if defined(CONFIG_DYNAMIC_DEBUG_CORE)
int ddebug_add_module(struct _ddebug *tab, unsigned int n, int ddebug_add_module(struct _ddebug *tab, unsigned int n,
const char *modname); const char *modname);
extern int ddebug_remove_module(const char *mod_name); extern int ddebug_remove_module(const char *mod_name);

View File

@ -68,6 +68,8 @@ struct ipc_namespace {
struct user_namespace *user_ns; struct user_namespace *user_ns;
struct ucounts *ucounts; struct ucounts *ucounts;
struct llist_node mnt_llist;
struct ns_common ns; struct ns_common ns;
} __randomize_layout; } __randomize_layout;

View File

@ -520,6 +520,12 @@ static inline u32 int_sqrt64(u64 x)
} }
#endif #endif
#ifdef CONFIG_SMP
extern unsigned int sysctl_oops_all_cpu_backtrace;
#else
#define sysctl_oops_all_cpu_backtrace 0
#endif /* CONFIG_SMP */
extern void bust_spinlocks(int yes); extern void bust_spinlocks(int yes);
extern int oops_in_progress; /* If set, an oops, panic(), BUG() or die() is in progress */ extern int oops_in_progress; /* If set, an oops, panic(), BUG() or die() is in progress */
extern int panic_timeout; extern int panic_timeout;
@ -528,6 +534,8 @@ extern int panic_on_oops;
extern int panic_on_unrecovered_nmi; extern int panic_on_unrecovered_nmi;
extern int panic_on_io_nmi; extern int panic_on_io_nmi;
extern int panic_on_warn; extern int panic_on_warn;
extern unsigned long panic_on_taint;
extern bool panic_on_taint_nousertaint;
extern int sysctl_panic_on_rcu_stall; extern int sysctl_panic_on_rcu_stall;
extern int sysctl_panic_on_stackoverflow; extern int sysctl_panic_on_stackoverflow;
@ -596,6 +604,7 @@ extern enum system_states {
#define TAINT_AUX 16 #define TAINT_AUX 16
#define TAINT_RANDSTRUCT 17 #define TAINT_RANDSTRUCT 17
#define TAINT_FLAGS_COUNT 18 #define TAINT_FLAGS_COUNT 18
#define TAINT_FLAGS_MAX ((1UL << TAINT_FLAGS_COUNT) - 1)
struct taint_flag { struct taint_flag {
char c_true; /* character printed when tainted */ char c_true; /* character printed when tainted */

View File

@ -1706,6 +1706,8 @@ long pin_user_pages(unsigned long start, unsigned long nr_pages,
struct vm_area_struct **vmas); struct vm_area_struct **vmas);
long get_user_pages_locked(unsigned long start, unsigned long nr_pages, long get_user_pages_locked(unsigned long start, unsigned long nr_pages,
unsigned int gup_flags, struct page **pages, int *locked); unsigned int gup_flags, struct page **pages, int *locked);
long pin_user_pages_locked(unsigned long start, unsigned long nr_pages,
unsigned int gup_flags, struct page **pages, int *locked);
long get_user_pages_unlocked(unsigned long start, unsigned long nr_pages, long get_user_pages_unlocked(unsigned long start, unsigned long nr_pages,
struct page **pages, unsigned int gup_flags); struct page **pages, unsigned int gup_flags);
long pin_user_pages_unlocked(unsigned long start, unsigned long nr_pages, long pin_user_pages_unlocked(unsigned long start, unsigned long nr_pages,
@ -1824,10 +1826,16 @@ extern int mprotect_fixup(struct vm_area_struct *vma,
/* /*
* doesn't attempt to fault and will return short. * doesn't attempt to fault and will return short.
*/ */
int __get_user_pages_fast(unsigned long start, int nr_pages, int write, int get_user_pages_fast_only(unsigned long start, int nr_pages,
struct page **pages); unsigned int gup_flags, struct page **pages);
int pin_user_pages_fast_only(unsigned long start, int nr_pages, int pin_user_pages_fast_only(unsigned long start, int nr_pages,
unsigned int gup_flags, struct page **pages); unsigned int gup_flags, struct page **pages);
static inline bool get_user_page_fast_only(unsigned long addr,
unsigned int gup_flags, struct page **pagep)
{
return get_user_pages_fast_only(addr, 1, gup_flags, pagep) == 1;
}
/* /*
* per-process(per-mm_struct) statistics. * per-process(per-mm_struct) statistics.
*/ */

View File

@ -264,7 +264,8 @@ do { \
net_ratelimited_function(pr_warn, fmt, ##__VA_ARGS__) net_ratelimited_function(pr_warn, fmt, ##__VA_ARGS__)
#define net_info_ratelimited(fmt, ...) \ #define net_info_ratelimited(fmt, ...) \
net_ratelimited_function(pr_info, fmt, ##__VA_ARGS__) net_ratelimited_function(pr_info, fmt, ##__VA_ARGS__)
#if defined(CONFIG_DYNAMIC_DEBUG) #if defined(CONFIG_DYNAMIC_DEBUG) || \
(defined(CONFIG_DYNAMIC_DEBUG_CORE) && defined(DYNAMIC_DEBUG_MODULE))
#define net_dbg_ratelimited(fmt, ...) \ #define net_dbg_ratelimited(fmt, ...) \
do { \ do { \
DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, fmt); \ DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, fmt); \

View File

@ -4942,7 +4942,8 @@ do { \
#define MODULE_ALIAS_NETDEV(device) \ #define MODULE_ALIAS_NETDEV(device) \
MODULE_ALIAS("netdev-" device) MODULE_ALIAS("netdev-" device)
#if defined(CONFIG_DYNAMIC_DEBUG) #if defined(CONFIG_DYNAMIC_DEBUG) || \
(defined(CONFIG_DYNAMIC_DEBUG_CORE) && defined(DYNAMIC_DEBUG_MODULE))
#define netdev_dbg(__dev, format, args...) \ #define netdev_dbg(__dev, format, args...) \
do { \ do { \
dynamic_netdev_dbg(__dev, format, ##args); \ dynamic_netdev_dbg(__dev, format, ##args); \
@ -5012,7 +5013,8 @@ do { \
#define netif_info(priv, type, dev, fmt, args...) \ #define netif_info(priv, type, dev, fmt, args...) \
netif_level(info, priv, type, dev, fmt, ##args) netif_level(info, priv, type, dev, fmt, ##args)
#if defined(CONFIG_DYNAMIC_DEBUG) #if defined(CONFIG_DYNAMIC_DEBUG) || \
(defined(CONFIG_DYNAMIC_DEBUG_CORE) && defined(DYNAMIC_DEBUG_MODULE))
#define netif_dbg(priv, type, netdev, format, args...) \ #define netif_dbg(priv, type, netdev, format, args...) \
do { \ do { \
if (netif_msg_##type(priv)) \ if (netif_msg_##type(priv)) \

View File

@ -399,7 +399,8 @@ extern int kptr_restrict;
/* If you are writing a driver, please use dev_dbg instead */ /* If you are writing a driver, please use dev_dbg instead */
#if defined(CONFIG_DYNAMIC_DEBUG) #if defined(CONFIG_DYNAMIC_DEBUG) || \
(defined(CONFIG_DYNAMIC_DEBUG_CORE) && defined(DYNAMIC_DEBUG_MODULE))
#include <linux/dynamic_debug.h> #include <linux/dynamic_debug.h>
/** /**
@ -535,7 +536,8 @@ extern int kptr_restrict;
#endif #endif
/* If you are writing a driver, please use dev_dbg instead */ /* If you are writing a driver, please use dev_dbg instead */
#if defined(CONFIG_DYNAMIC_DEBUG) #if defined(CONFIG_DYNAMIC_DEBUG) || \
(defined(CONFIG_DYNAMIC_DEBUG_CORE) && defined(DYNAMIC_DEBUG_MODULE))
/* descriptor check is first to prevent flooding with "callbacks suppressed" */ /* descriptor check is first to prevent flooding with "callbacks suppressed" */
#define pr_debug_ratelimited(fmt, ...) \ #define pr_debug_ratelimited(fmt, ...) \
do { \ do { \
@ -582,7 +584,8 @@ static inline void print_hex_dump_bytes(const char *prefix_str, int prefix_type,
#endif #endif
#if defined(CONFIG_DYNAMIC_DEBUG) #if defined(CONFIG_DYNAMIC_DEBUG) || \
(defined(CONFIG_DYNAMIC_DEBUG_CORE) && defined(DYNAMIC_DEBUG_MODULE))
#define print_hex_dump_debug(prefix_str, prefix_type, rowsize, \ #define print_hex_dump_debug(prefix_str, prefix_type, rowsize, \
groupsize, buf, len, ascii) \ groupsize, buf, len, ascii) \
dynamic_hex_dump(prefix_str, prefix_type, rowsize, \ dynamic_hex_dump(prefix_str, prefix_type, rowsize, \

View File

@ -7,6 +7,13 @@
struct ctl_table; struct ctl_table;
#ifdef CONFIG_DETECT_HUNG_TASK #ifdef CONFIG_DETECT_HUNG_TASK
#ifdef CONFIG_SMP
extern unsigned int sysctl_hung_task_all_cpu_backtrace;
#else
#define sysctl_hung_task_all_cpu_backtrace 0
#endif /* CONFIG_SMP */
extern int sysctl_hung_task_check_count; extern int sysctl_hung_task_check_count;
extern unsigned int sysctl_hung_task_panic; extern unsigned int sysctl_hung_task_panic;
extern unsigned long sysctl_hung_task_timeout_secs; extern unsigned long sysctl_hung_task_timeout_secs;

View File

@ -197,6 +197,7 @@ struct ctl_table_header *register_sysctl_paths(const struct ctl_path *path,
void unregister_sysctl_table(struct ctl_table_header * table); void unregister_sysctl_table(struct ctl_table_header * table);
extern int sysctl_init(void); extern int sysctl_init(void);
void do_sysctl_args(void);
extern int pwrsw_enabled; extern int pwrsw_enabled;
extern int unaligned_enabled; extern int unaligned_enabled;
@ -235,6 +236,9 @@ static inline void setup_sysctl_set(struct ctl_table_set *p,
{ {
} }
static inline void do_sysctl_args(void)
{
}
#endif /* CONFIG_SYSCTL */ #endif /* CONFIG_SYSCTL */
int sysctl_max_threads(struct ctl_table *table, int write, void *buffer, int sysctl_max_threads(struct ctl_table *table, int write, void *buffer,

View File

@ -576,7 +576,7 @@ void __xa_clear_mark(struct xarray *, unsigned long index, xa_mark_t);
* *
* Context: Any context. Takes and releases the xa_lock while * Context: Any context. Takes and releases the xa_lock while
* disabling softirqs. * disabling softirqs.
* Return: The entry which used to be at this index. * Return: The old entry at this index or xa_err() if an error happened.
*/ */
static inline void *xa_store_bh(struct xarray *xa, unsigned long index, static inline void *xa_store_bh(struct xarray *xa, unsigned long index,
void *entry, gfp_t gfp) void *entry, gfp_t gfp)
@ -602,7 +602,7 @@ static inline void *xa_store_bh(struct xarray *xa, unsigned long index,
* *
* Context: Process context. Takes and releases the xa_lock while * Context: Process context. Takes and releases the xa_lock while
* disabling interrupts. * disabling interrupts.
* Return: The entry which used to be at this index. * Return: The old entry at this index or xa_err() if an error happened.
*/ */
static inline void *xa_store_irq(struct xarray *xa, unsigned long index, static inline void *xa_store_irq(struct xarray *xa, unsigned long index,
void *entry, gfp_t gfp) void *entry, gfp_t gfp)

View File

@ -100,7 +100,8 @@ void ibdev_notice(const struct ib_device *ibdev, const char *format, ...);
__printf(2, 3) __cold __printf(2, 3) __cold
void ibdev_info(const struct ib_device *ibdev, const char *format, ...); void ibdev_info(const struct ib_device *ibdev, const char *format, ...);
#if defined(CONFIG_DYNAMIC_DEBUG) #if defined(CONFIG_DYNAMIC_DEBUG) || \
(defined(CONFIG_DYNAMIC_DEBUG_CORE) && defined(DYNAMIC_DEBUG_MODULE))
#define ibdev_dbg(__dev, format, args...) \ #define ibdev_dbg(__dev, format, args...) \
dynamic_ibdev_dbg(__dev, format, ##args) dynamic_ibdev_dbg(__dev, format, ##args)
#else #else
@ -133,7 +134,8 @@ do { \
#define ibdev_info_ratelimited(ibdev, fmt, ...) \ #define ibdev_info_ratelimited(ibdev, fmt, ...) \
ibdev_level_ratelimited(ibdev_info, ibdev, fmt, ##__VA_ARGS__) ibdev_level_ratelimited(ibdev_info, ibdev, fmt, ##__VA_ARGS__)
#if defined(CONFIG_DYNAMIC_DEBUG) #if defined(CONFIG_DYNAMIC_DEBUG) || \
(defined(CONFIG_DYNAMIC_DEBUG_CORE) && defined(DYNAMIC_DEBUG_MODULE))
/* descriptor check is first to prevent flooding with "callbacks suppressed" */ /* descriptor check is first to prevent flooding with "callbacks suppressed" */
#define ibdev_dbg_ratelimited(ibdev, fmt, ...) \ #define ibdev_dbg_ratelimited(ibdev, fmt, ...) \
do { \ do { \

View File

@ -1412,6 +1412,8 @@ static int __ref kernel_init(void *unused)
rcu_end_inkernel_boot(); rcu_end_inkernel_boot();
do_sysctl_args();
if (ramdisk_execute_command) { if (ramdisk_execute_command) {
ret = run_init_process(ramdisk_execute_command); ret = run_init_process(ramdisk_execute_command);
if (!ret) if (!ret)

View File

@ -268,6 +268,8 @@ static void expunge_all(struct msg_queue *msq, int res,
* before freeque() is called. msg_ids.rwsem remains locked on exit. * before freeque() is called. msg_ids.rwsem remains locked on exit.
*/ */
static void freeque(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp) static void freeque(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp)
__releases(RCU)
__releases(&msq->q_perm)
{ {
struct msg_msg *msg, *t; struct msg_msg *msg, *t;
struct msg_queue *msq = container_of(ipcp, struct msg_queue, q_perm); struct msg_queue *msq = container_of(ipcp, struct msg_queue, q_perm);

View File

@ -117,6 +117,10 @@ void free_ipcs(struct ipc_namespace *ns, struct ipc_ids *ids,
static void free_ipc_ns(struct ipc_namespace *ns) static void free_ipc_ns(struct ipc_namespace *ns)
{ {
/* mq_put_mnt() waits for a grace period as kern_unmount()
* uses synchronize_rcu().
*/
mq_put_mnt(ns);
sem_exit_ns(ns); sem_exit_ns(ns);
msg_exit_ns(ns); msg_exit_ns(ns);
shm_exit_ns(ns); shm_exit_ns(ns);
@ -127,6 +131,21 @@ static void free_ipc_ns(struct ipc_namespace *ns)
kfree(ns); kfree(ns);
} }
static LLIST_HEAD(free_ipc_list);
static void free_ipc(struct work_struct *unused)
{
struct llist_node *node = llist_del_all(&free_ipc_list);
struct ipc_namespace *n, *t;
llist_for_each_entry_safe(n, t, node, mnt_llist)
free_ipc_ns(n);
}
/*
* The work queue is used to avoid the cost of synchronize_rcu in kern_unmount.
*/
static DECLARE_WORK(free_ipc_work, free_ipc);
/* /*
* put_ipc_ns - drop a reference to an ipc namespace. * put_ipc_ns - drop a reference to an ipc namespace.
* @ns: the namespace to put * @ns: the namespace to put
@ -148,8 +167,9 @@ void put_ipc_ns(struct ipc_namespace *ns)
if (refcount_dec_and_lock(&ns->count, &mq_lock)) { if (refcount_dec_and_lock(&ns->count, &mq_lock)) {
mq_clear_sbinfo(ns); mq_clear_sbinfo(ns);
spin_unlock(&mq_lock); spin_unlock(&mq_lock);
mq_put_mnt(ns);
free_ipc_ns(ns); if (llist_add(&ns->mnt_llist, &free_ipc_list))
schedule_work(&free_ipc_work);
} }
} }

View File

@ -6934,12 +6934,12 @@ static u64 perf_virt_to_phys(u64 virt)
* Walking the pages tables for user address. * Walking the pages tables for user address.
* Interrupts are disabled, so it prevents any tear down * Interrupts are disabled, so it prevents any tear down
* of the page tables. * of the page tables.
* Try IRQ-safe __get_user_pages_fast first. * Try IRQ-safe get_user_page_fast_only first.
* If failed, leave phys_addr as 0. * If failed, leave phys_addr as 0.
*/ */
if (current->mm != NULL) { if (current->mm != NULL) {
pagefault_disable(); pagefault_disable();
if (__get_user_pages_fast(virt, 1, 0, &p) == 1) if (get_user_page_fast_only(virt, 0, &p))
phys_addr = page_to_phys(p) + virt % PAGE_SIZE; phys_addr = page_to_phys(p) + virt % PAGE_SIZE;
pagefault_enable(); pagefault_enable();
} }

View File

@ -1668,7 +1668,7 @@ void __weak arch_uprobe_copy_ixol(struct page *page, unsigned long vaddr,
copy_to_page(page, vaddr, src, len); copy_to_page(page, vaddr, src, len);
/* /*
* We probably need flush_icache_user_range() but it needs vma. * We probably need flush_icache_user_page() but it needs vma.
* This should work on most of architectures by default. If * This should work on most of architectures by default. If
* architecture needs to do something different it can define * architecture needs to do something different it can define
* its own version of the function. * its own version of the function.

View File

@ -53,9 +53,18 @@ int __read_mostly sysctl_hung_task_warnings = 10;
static int __read_mostly did_panic; static int __read_mostly did_panic;
static bool hung_task_show_lock; static bool hung_task_show_lock;
static bool hung_task_call_panic; static bool hung_task_call_panic;
static bool hung_task_show_all_bt;
static struct task_struct *watchdog_task; static struct task_struct *watchdog_task;
#ifdef CONFIG_SMP
/*
* Should we dump all CPUs backtraces in a hung task event?
* Defaults to 0, can be changed via sysctl.
*/
unsigned int __read_mostly sysctl_hung_task_all_cpu_backtrace;
#endif /* CONFIG_SMP */
/* /*
* Should we panic (and reboot, if panic_timeout= is set) when a * Should we panic (and reboot, if panic_timeout= is set) when a
* hung task is detected: * hung task is detected:
@ -63,16 +72,6 @@ static struct task_struct *watchdog_task;
unsigned int __read_mostly sysctl_hung_task_panic = unsigned int __read_mostly sysctl_hung_task_panic =
CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE; CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE;
static int __init hung_task_panic_setup(char *str)
{
int rc = kstrtouint(str, 0, &sysctl_hung_task_panic);
if (rc)
return rc;
return 1;
}
__setup("hung_task_panic=", hung_task_panic_setup);
static int static int
hung_task_panic(struct notifier_block *this, unsigned long event, void *ptr) hung_task_panic(struct notifier_block *this, unsigned long event, void *ptr)
{ {
@ -137,6 +136,9 @@ static void check_hung_task(struct task_struct *t, unsigned long timeout)
" disables this message.\n"); " disables this message.\n");
sched_show_task(t); sched_show_task(t);
hung_task_show_lock = true; hung_task_show_lock = true;
if (sysctl_hung_task_all_cpu_backtrace)
hung_task_show_all_bt = true;
} }
touch_nmi_watchdog(); touch_nmi_watchdog();
@ -201,10 +203,14 @@ static void check_hung_uninterruptible_tasks(unsigned long timeout)
rcu_read_unlock(); rcu_read_unlock();
if (hung_task_show_lock) if (hung_task_show_lock)
debug_show_all_locks(); debug_show_all_locks();
if (hung_task_call_panic) {
if (hung_task_show_all_bt) {
hung_task_show_all_bt = false;
trigger_all_cpu_backtrace(); trigger_all_cpu_backtrace();
panic("hung_task: blocked tasks");
} }
if (hung_task_call_panic)
panic("hung_task: blocked tasks");
} }
static long hung_timeout_jiffies(unsigned long last_checked, static long hung_timeout_jiffies(unsigned long last_checked,

View File

@ -3344,12 +3344,6 @@ static int check_module_license_and_versions(struct module *mod)
static void flush_module_icache(const struct module *mod) static void flush_module_icache(const struct module *mod)
{ {
mm_segment_t old_fs;
/* flush the icache in correct context */
old_fs = get_fs();
set_fs(KERNEL_DS);
/* /*
* Flush the instruction cache, since we've played with text. * Flush the instruction cache, since we've played with text.
* Do it before processing of module parameters, so the module * Do it before processing of module parameters, so the module
@ -3361,8 +3355,6 @@ static void flush_module_icache(const struct module *mod)
+ mod->init_layout.size); + mod->init_layout.size);
flush_icache_range((unsigned long)mod->core_layout.base, flush_icache_range((unsigned long)mod->core_layout.base,
(unsigned long)mod->core_layout.base + mod->core_layout.size); (unsigned long)mod->core_layout.base + mod->core_layout.size);
set_fs(old_fs);
} }
int __weak module_frob_arch_sections(Elf_Ehdr *hdr, int __weak module_frob_arch_sections(Elf_Ehdr *hdr,

View File

@ -36,6 +36,14 @@
#define PANIC_TIMER_STEP 100 #define PANIC_TIMER_STEP 100
#define PANIC_BLINK_SPD 18 #define PANIC_BLINK_SPD 18
#ifdef CONFIG_SMP
/*
* Should we dump all CPUs backtraces in an oops event?
* Defaults to 0, can be changed via sysctl.
*/
unsigned int __read_mostly sysctl_oops_all_cpu_backtrace;
#endif /* CONFIG_SMP */
int panic_on_oops = CONFIG_PANIC_ON_OOPS_VALUE; int panic_on_oops = CONFIG_PANIC_ON_OOPS_VALUE;
static unsigned long tainted_mask = static unsigned long tainted_mask =
IS_ENABLED(CONFIG_GCC_PLUGIN_RANDSTRUCT) ? (1 << TAINT_RANDSTRUCT) : 0; IS_ENABLED(CONFIG_GCC_PLUGIN_RANDSTRUCT) ? (1 << TAINT_RANDSTRUCT) : 0;
@ -44,6 +52,8 @@ static int pause_on_oops_flag;
static DEFINE_SPINLOCK(pause_on_oops_lock); static DEFINE_SPINLOCK(pause_on_oops_lock);
bool crash_kexec_post_notifiers; bool crash_kexec_post_notifiers;
int panic_on_warn __read_mostly; int panic_on_warn __read_mostly;
unsigned long panic_on_taint;
bool panic_on_taint_nousertaint = false;
int panic_timeout = CONFIG_PANIC_TIMEOUT; int panic_timeout = CONFIG_PANIC_TIMEOUT;
EXPORT_SYMBOL_GPL(panic_timeout); EXPORT_SYMBOL_GPL(panic_timeout);
@ -434,6 +444,11 @@ void add_taint(unsigned flag, enum lockdep_ok lockdep_ok)
pr_warn("Disabling lock debugging due to kernel taint\n"); pr_warn("Disabling lock debugging due to kernel taint\n");
set_bit(flag, &tainted_mask); set_bit(flag, &tainted_mask);
if (tainted_mask & panic_on_taint) {
panic_on_taint = 0;
panic("panic_on_taint set ...");
}
} }
EXPORT_SYMBOL(add_taint); EXPORT_SYMBOL(add_taint);
@ -515,6 +530,9 @@ void oops_enter(void)
/* can't trust the integrity of the kernel anymore: */ /* can't trust the integrity of the kernel anymore: */
debug_locks_off(); debug_locks_off();
do_oops_enter_exit(); do_oops_enter_exit();
if (sysctl_oops_all_cpu_backtrace)
trigger_all_cpu_backtrace();
} }
/* /*
@ -686,3 +704,30 @@ static int __init oops_setup(char *s)
return 0; return 0;
} }
early_param("oops", oops_setup); early_param("oops", oops_setup);
static int __init panic_on_taint_setup(char *s)
{
char *taint_str;
if (!s)
return -EINVAL;
taint_str = strsep(&s, ",");
if (kstrtoul(taint_str, 16, &panic_on_taint))
return -EINVAL;
/* make sure panic_on_taint doesn't hold out-of-range TAINT flags */
panic_on_taint &= TAINT_FLAGS_MAX;
if (!panic_on_taint)
return -EINVAL;
if (s && !strcmp(s, "nousertaint"))
panic_on_taint_nousertaint = true;
pr_info("panic_on_taint: bitmask=0x%lx nousertaint_mode=%sabled\n",
panic_on_taint, panic_on_taint_nousertaint ? "en" : "dis");
return 0;
}
early_param("panic_on_taint", panic_on_taint_setup);

View File

@ -866,15 +866,23 @@ static int proc_taint(struct ctl_table *table, int write,
return err; return err;
if (write) { if (write) {
int i;
/*
* If we are relying on panic_on_taint not producing
* false positives due to userspace input, bail out
* before setting the requested taint flags.
*/
if (panic_on_taint_nousertaint && (tmptaint & panic_on_taint))
return -EINVAL;
/* /*
* Poor man's atomic or. Not worth adding a primitive * Poor man's atomic or. Not worth adding a primitive
* to everyone's atomic.h for this * to everyone's atomic.h for this
*/ */
int i; for (i = 0; i < TAINT_FLAGS_COUNT; i++)
for (i = 0; i < BITS_PER_LONG && tmptaint >> i; i++) { if ((1UL << i) & tmptaint)
if ((tmptaint >> i) & 1)
add_taint(i, LOCKDEP_STILL_OK); add_taint(i, LOCKDEP_STILL_OK);
}
} }
return err; return err;
@ -2141,6 +2149,17 @@ static struct ctl_table kern_table[] = {
.proc_handler = proc_dointvec, .proc_handler = proc_dointvec,
}, },
#endif #endif
#ifdef CONFIG_SMP
{
.procname = "oops_all_cpu_backtrace",
.data = &sysctl_oops_all_cpu_backtrace,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = proc_dointvec_minmax,
.extra1 = SYSCTL_ZERO,
.extra2 = SYSCTL_ONE,
},
#endif /* CONFIG_SMP */
{ {
.procname = "pid_max", .procname = "pid_max",
.data = &pid_max, .data = &pid_max,
@ -2428,6 +2447,17 @@ static struct ctl_table kern_table[] = {
}, },
#endif #endif
#ifdef CONFIG_DETECT_HUNG_TASK #ifdef CONFIG_DETECT_HUNG_TASK
#ifdef CONFIG_SMP
{
.procname = "hung_task_all_cpu_backtrace",
.data = &sysctl_hung_task_all_cpu_backtrace,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = proc_dointvec_minmax,
.extra1 = SYSCTL_ZERO,
.extra2 = SYSCTL_ONE,
},
#endif /* CONFIG_SMP */
{ {
.procname = "hung_task_panic", .procname = "hung_task_panic",
.data = &sysctl_hung_task_panic, .data = &sysctl_hung_task_panic,

View File

@ -50,6 +50,11 @@ struct cpumask watchdog_cpumask __read_mostly;
unsigned long *watchdog_cpumask_bits = cpumask_bits(&watchdog_cpumask); unsigned long *watchdog_cpumask_bits = cpumask_bits(&watchdog_cpumask);
#ifdef CONFIG_HARDLOCKUP_DETECTOR #ifdef CONFIG_HARDLOCKUP_DETECTOR
# ifdef CONFIG_SMP
int __read_mostly sysctl_hardlockup_all_cpu_backtrace;
# endif /* CONFIG_SMP */
/* /*
* Should we panic when a soft-lockup or hard-lockup occurs: * Should we panic when a soft-lockup or hard-lockup occurs:
*/ */
@ -82,16 +87,6 @@ static int __init hardlockup_panic_setup(char *str)
} }
__setup("nmi_watchdog=", hardlockup_panic_setup); __setup("nmi_watchdog=", hardlockup_panic_setup);
# ifdef CONFIG_SMP
int __read_mostly sysctl_hardlockup_all_cpu_backtrace;
static int __init hardlockup_all_cpu_backtrace_setup(char *str)
{
sysctl_hardlockup_all_cpu_backtrace = !!simple_strtol(str, NULL, 0);
return 1;
}
__setup("hardlockup_all_cpu_backtrace=", hardlockup_all_cpu_backtrace_setup);
# endif /* CONFIG_SMP */
#endif /* CONFIG_HARDLOCKUP_DETECTOR */ #endif /* CONFIG_HARDLOCKUP_DETECTOR */
/* /*
@ -163,6 +158,10 @@ static void lockup_detector_update_enable(void)
#define SOFTLOCKUP_RESET ULONG_MAX #define SOFTLOCKUP_RESET ULONG_MAX
#ifdef CONFIG_SMP
int __read_mostly sysctl_softlockup_all_cpu_backtrace;
#endif
/* Global variables, exported for sysctl */ /* Global variables, exported for sysctl */
unsigned int __read_mostly softlockup_panic = unsigned int __read_mostly softlockup_panic =
CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE; CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE;
@ -178,13 +177,6 @@ static DEFINE_PER_CPU(unsigned long, hrtimer_interrupts);
static DEFINE_PER_CPU(unsigned long, hrtimer_interrupts_saved); static DEFINE_PER_CPU(unsigned long, hrtimer_interrupts_saved);
static unsigned long soft_lockup_nmi_warn; static unsigned long soft_lockup_nmi_warn;
static int __init softlockup_panic_setup(char *str)
{
softlockup_panic = simple_strtoul(str, NULL, 0);
return 1;
}
__setup("softlockup_panic=", softlockup_panic_setup);
static int __init nowatchdog_setup(char *str) static int __init nowatchdog_setup(char *str)
{ {
watchdog_user_enabled = 0; watchdog_user_enabled = 0;
@ -206,17 +198,6 @@ static int __init watchdog_thresh_setup(char *str)
} }
__setup("watchdog_thresh=", watchdog_thresh_setup); __setup("watchdog_thresh=", watchdog_thresh_setup);
#ifdef CONFIG_SMP
int __read_mostly sysctl_softlockup_all_cpu_backtrace;
static int __init softlockup_all_cpu_backtrace_setup(char *str)
{
sysctl_softlockup_all_cpu_backtrace = !!simple_strtol(str, NULL, 0);
return 1;
}
__setup("softlockup_all_cpu_backtrace=", softlockup_all_cpu_backtrace_setup);
#endif
static void __lockup_detector_cleanup(void); static void __lockup_detector_cleanup(void);
/* /*

View File

@ -99,6 +99,7 @@ config DYNAMIC_DEBUG
default n default n
depends on PRINTK depends on PRINTK
depends on (DEBUG_FS || PROC_FS) depends on (DEBUG_FS || PROC_FS)
select DYNAMIC_DEBUG_CORE
help help
Compiles debug level messages into the kernel, which would not Compiles debug level messages into the kernel, which would not
@ -165,6 +166,17 @@ config DYNAMIC_DEBUG
See Documentation/admin-guide/dynamic-debug-howto.rst for additional See Documentation/admin-guide/dynamic-debug-howto.rst for additional
information. information.
config DYNAMIC_DEBUG_CORE
bool "Enable core function of dynamic debug support"
depends on PRINTK
depends on (DEBUG_FS || PROC_FS)
help
Enable core functional support of dynamic debug. It is useful
when you want to tie dynamic debug to your kernel modules with
DYNAMIC_DEBUG_MODULE defined for each of them, especially for
the case of embedded system where the kernel image size is
sensitive for people.
config SYMBOLIC_ERRNAME config SYMBOLIC_ERRNAME
bool "Support symbolic error names in printf" bool "Support symbolic error names in printf"
default y if PRINTK default y if PRINTK

View File

@ -190,7 +190,7 @@ lib-$(CONFIG_GENERIC_BUG) += bug.o
obj-$(CONFIG_HAVE_ARCH_TRACEHOOK) += syscall.o obj-$(CONFIG_HAVE_ARCH_TRACEHOOK) += syscall.o
obj-$(CONFIG_DYNAMIC_DEBUG) += dynamic_debug.o obj-$(CONFIG_DYNAMIC_DEBUG_CORE) += dynamic_debug.o
obj-$(CONFIG_SYMBOLIC_ERRNAME) += errname.o obj-$(CONFIG_SYMBOLIC_ERRNAME) += errname.o
obj-$(CONFIG_NLATTR) += nlattr.o obj-$(CONFIG_NLATTR) += nlattr.o

View File

@ -1032,8 +1032,13 @@ static int __init dynamic_debug_init(void)
int verbose_bytes = 0; int verbose_bytes = 0;
if (&__start___verbose == &__stop___verbose) { if (&__start___verbose == &__stop___verbose) {
pr_warn("_ddebug table is empty in a CONFIG_DYNAMIC_DEBUG build\n"); if (IS_ENABLED(CONFIG_DYNAMIC_DEBUG)) {
return 1; pr_warn("_ddebug table is empty in a CONFIG_DYNAMIC_DEBUG build\n");
return 1;
}
pr_info("Ignore empty _ddebug table in a CONFIG_DYNAMIC_DEBUG_CORE build\n");
ddebug_init_success = 1;
return 0;
} }
iter = __start___verbose; iter = __start___verbose;
modname = iter->modname; modname = iter->modname;

View File

@ -44,6 +44,8 @@ struct test_sysctl_data {
int int_0002; int int_0002;
int int_0003[4]; int int_0003[4];
int boot_int;
unsigned int uint_0001; unsigned int uint_0001;
char string_0001[65]; char string_0001[65];
@ -61,6 +63,8 @@ static struct test_sysctl_data test_data = {
.int_0003[2] = 2, .int_0003[2] = 2,
.int_0003[3] = 3, .int_0003[3] = 3,
.boot_int = 0,
.uint_0001 = 314, .uint_0001 = 314,
.string_0001 = "(none)", .string_0001 = "(none)",
@ -91,6 +95,15 @@ static struct ctl_table test_table[] = {
.mode = 0644, .mode = 0644,
.proc_handler = proc_dointvec, .proc_handler = proc_dointvec,
}, },
{
.procname = "boot_int",
.data = &test_data.boot_int,
.maxlen = sizeof(test_data.boot_int),
.mode = 0644,
.proc_handler = proc_dointvec,
.extra1 = SYSCTL_ZERO,
.extra2 = SYSCTL_ONE,
},
{ {
.procname = "uint_0001", .procname = "uint_0001",
.data = &test_data.uint_0001, .data = &test_data.uint_0001,

View File

@ -72,7 +72,7 @@ int get_vaddr_frames(unsigned long start, unsigned int nr_frames,
if (!(vma->vm_flags & (VM_IO | VM_PFNMAP))) { if (!(vma->vm_flags & (VM_IO | VM_PFNMAP))) {
vec->got_ref = true; vec->got_ref = true;
vec->is_pfns = false; vec->is_pfns = false;
ret = get_user_pages_locked(start, nr_frames, ret = pin_user_pages_locked(start, nr_frames,
gup_flags, (struct page **)(vec->ptrs), &locked); gup_flags, (struct page **)(vec->ptrs), &locked);
goto out; goto out;
} }
@ -122,7 +122,6 @@ EXPORT_SYMBOL(get_vaddr_frames);
*/ */
void put_vaddr_frames(struct frame_vector *vec) void put_vaddr_frames(struct frame_vector *vec)
{ {
int i;
struct page **pages; struct page **pages;
if (!vec->got_ref) if (!vec->got_ref)
@ -135,8 +134,8 @@ void put_vaddr_frames(struct frame_vector *vec)
*/ */
if (WARN_ON(IS_ERR(pages))) if (WARN_ON(IS_ERR(pages)))
goto out; goto out;
for (i = 0; i < vec->nr_frames; i++)
put_page(pages[i]); unpin_user_pages(pages, vec->nr_frames);
vec->got_ref = false; vec->got_ref = false;
out: out:
vec->nr_frames = 0; vec->nr_frames = 0;

View File

@ -2035,6 +2035,12 @@ long get_user_pages_locked(unsigned long start, unsigned long nr_pages,
*/ */
if (WARN_ON_ONCE(gup_flags & FOLL_LONGTERM)) if (WARN_ON_ONCE(gup_flags & FOLL_LONGTERM))
return -EINVAL; return -EINVAL;
/*
* FOLL_PIN must only be set internally by the pin_user_pages*() APIs,
* never directly by the caller, so enforce that:
*/
if (WARN_ON_ONCE(gup_flags & FOLL_PIN))
return -EINVAL;
return __get_user_pages_locked(current, current->mm, start, nr_pages, return __get_user_pages_locked(current, current->mm, start, nr_pages,
pages, NULL, locked, pages, NULL, locked,
@ -2294,7 +2300,7 @@ pte_unmap:
* to be special. * to be special.
* *
* For a futex to be placed on a THP tail page, get_futex_key requires a * For a futex to be placed on a THP tail page, get_futex_key requires a
* __get_user_pages_fast implementation that can pin pages. Thus it's still * get_user_pages_fast_only implementation that can pin pages. Thus it's still
* useful to have gup_huge_pmd even if we can't operate on ptes. * useful to have gup_huge_pmd even if we can't operate on ptes.
*/ */
static int gup_pte_range(pmd_t pmd, unsigned long addr, unsigned long end, static int gup_pte_range(pmd_t pmd, unsigned long addr, unsigned long end,
@ -2699,7 +2705,7 @@ static inline void gup_pgd_range(unsigned long addr, unsigned long end,
#ifndef gup_fast_permitted #ifndef gup_fast_permitted
/* /*
* Check if it's allowed to use __get_user_pages_fast() for the range, or * Check if it's allowed to use get_user_pages_fast_only() for the range, or
* we need to fall back to the slow version: * we need to fall back to the slow version:
*/ */
static bool gup_fast_permitted(unsigned long start, unsigned long end) static bool gup_fast_permitted(unsigned long start, unsigned long end)
@ -2811,8 +2817,14 @@ static int internal_get_user_pages_fast(unsigned long start, int nr_pages,
return ret; return ret;
} }
/**
/* * get_user_pages_fast_only() - pin user pages in memory
* @start: starting user address
* @nr_pages: number of pages from start to pin
* @gup_flags: flags modifying pin behaviour
* @pages: array that receives pointers to the pages pinned.
* Should be at least nr_pages long.
*
* Like get_user_pages_fast() except it's IRQ-safe in that it won't fall back to * Like get_user_pages_fast() except it's IRQ-safe in that it won't fall back to
* the regular GUP. * the regular GUP.
* Note a difference with get_user_pages_fast: this always returns the * Note a difference with get_user_pages_fast: this always returns the
@ -2825,8 +2837,8 @@ static int internal_get_user_pages_fast(unsigned long start, int nr_pages,
* access can get ambiguous page results. If you call this function without * access can get ambiguous page results. If you call this function without
* 'write' set, you'd better be sure that you're ok with that ambiguity. * 'write' set, you'd better be sure that you're ok with that ambiguity.
*/ */
int __get_user_pages_fast(unsigned long start, int nr_pages, int write, int get_user_pages_fast_only(unsigned long start, int nr_pages,
struct page **pages) unsigned int gup_flags, struct page **pages)
{ {
int nr_pinned; int nr_pinned;
/* /*
@ -2836,10 +2848,7 @@ int __get_user_pages_fast(unsigned long start, int nr_pages, int write,
* FOLL_FAST_ONLY is required in order to match the API description of * FOLL_FAST_ONLY is required in order to match the API description of
* this routine: no fall back to regular ("slow") GUP. * this routine: no fall back to regular ("slow") GUP.
*/ */
unsigned int gup_flags = FOLL_GET | FOLL_FAST_ONLY; gup_flags |= FOLL_GET | FOLL_FAST_ONLY;
if (write)
gup_flags |= FOLL_WRITE;
nr_pinned = internal_get_user_pages_fast(start, nr_pages, gup_flags, nr_pinned = internal_get_user_pages_fast(start, nr_pages, gup_flags,
pages); pages);
@ -2855,7 +2864,7 @@ int __get_user_pages_fast(unsigned long start, int nr_pages, int write,
return nr_pinned; return nr_pinned;
} }
EXPORT_SYMBOL_GPL(__get_user_pages_fast); EXPORT_SYMBOL_GPL(get_user_pages_fast_only);
/** /**
* get_user_pages_fast() - pin user pages in memory * get_user_pages_fast() - pin user pages in memory
@ -2909,9 +2918,6 @@ EXPORT_SYMBOL_GPL(get_user_pages_fast);
* *
* FOLL_PIN means that the pages must be released via unpin_user_page(). Please * FOLL_PIN means that the pages must be released via unpin_user_page(). Please
* see Documentation/core-api/pin_user_pages.rst for further details. * see Documentation/core-api/pin_user_pages.rst for further details.
*
* This is intended for Case 1 (DIO) in Documentation/core-api/pin_user_pages.rst. It
* is NOT intended for Case 2 (RDMA: long-term pins).
*/ */
int pin_user_pages_fast(unsigned long start, int nr_pages, int pin_user_pages_fast(unsigned long start, int nr_pages,
unsigned int gup_flags, struct page **pages) unsigned int gup_flags, struct page **pages)
@ -2926,8 +2932,8 @@ int pin_user_pages_fast(unsigned long start, int nr_pages,
EXPORT_SYMBOL_GPL(pin_user_pages_fast); EXPORT_SYMBOL_GPL(pin_user_pages_fast);
/* /*
* This is the FOLL_PIN equivalent of __get_user_pages_fast(). Behavior is the * This is the FOLL_PIN equivalent of get_user_pages_fast_only(). Behavior
* same, except that this one sets FOLL_PIN instead of FOLL_GET. * is the same, except that this one sets FOLL_PIN instead of FOLL_GET.
* *
* The API rules are the same, too: no negative values may be returned. * The API rules are the same, too: no negative values may be returned.
*/ */
@ -2985,9 +2991,6 @@ EXPORT_SYMBOL_GPL(pin_user_pages_fast_only);
* *
* FOLL_PIN means that the pages must be released via unpin_user_page(). Please * FOLL_PIN means that the pages must be released via unpin_user_page(). Please
* see Documentation/core-api/pin_user_pages.rst for details. * see Documentation/core-api/pin_user_pages.rst for details.
*
* This is intended for Case 1 (DIO) in Documentation/core-api/pin_user_pages.rst. It
* is NOT intended for Case 2 (RDMA: long-term pins).
*/ */
long pin_user_pages_remote(struct task_struct *tsk, struct mm_struct *mm, long pin_user_pages_remote(struct task_struct *tsk, struct mm_struct *mm,
unsigned long start, unsigned long nr_pages, unsigned long start, unsigned long nr_pages,
@ -3021,9 +3024,6 @@ EXPORT_SYMBOL(pin_user_pages_remote);
* *
* FOLL_PIN means that the pages must be released via unpin_user_page(). Please * FOLL_PIN means that the pages must be released via unpin_user_page(). Please
* see Documentation/core-api/pin_user_pages.rst for details. * see Documentation/core-api/pin_user_pages.rst for details.
*
* This is intended for Case 1 (DIO) in Documentation/core-api/pin_user_pages.rst. It
* is NOT intended for Case 2 (RDMA: long-term pins).
*/ */
long pin_user_pages(unsigned long start, unsigned long nr_pages, long pin_user_pages(unsigned long start, unsigned long nr_pages,
unsigned int gup_flags, struct page **pages, unsigned int gup_flags, struct page **pages,
@ -3055,3 +3055,32 @@ long pin_user_pages_unlocked(unsigned long start, unsigned long nr_pages,
return get_user_pages_unlocked(start, nr_pages, pages, gup_flags); return get_user_pages_unlocked(start, nr_pages, pages, gup_flags);
} }
EXPORT_SYMBOL(pin_user_pages_unlocked); EXPORT_SYMBOL(pin_user_pages_unlocked);
/*
* pin_user_pages_locked() is the FOLL_PIN variant of get_user_pages_locked().
* Behavior is the same, except that this one sets FOLL_PIN and rejects
* FOLL_GET.
*/
long pin_user_pages_locked(unsigned long start, unsigned long nr_pages,
unsigned int gup_flags, struct page **pages,
int *locked)
{
/*
* FIXME: Current FOLL_LONGTERM behavior is incompatible with
* FAULT_FLAG_ALLOW_RETRY because of the FS DAX check requirement on
* vmas. As there are no users of this flag in this call we simply
* disallow this option for now.
*/
if (WARN_ON_ONCE(gup_flags & FOLL_LONGTERM))
return -EINVAL;
/* FOLL_GET and FOLL_PIN are mutually exclusive. */
if (WARN_ON_ONCE(gup_flags & FOLL_GET))
return -EINVAL;
gup_flags |= FOLL_PIN;
return __get_user_pages_locked(current, current->mm, start, nr_pages,
pages, NULL, locked,
gup_flags | FOLL_TOUCH);
}
EXPORT_SYMBOL(pin_user_pages_locked);

View File

@ -433,7 +433,7 @@ SYSCALL_DEFINE1(brk, unsigned long, brk)
/* /*
* Ok, looks good - let it rip. * Ok, looks good - let it rip.
*/ */
flush_icache_range(mm->brk, brk); flush_icache_user_range(mm->brk, brk);
return mm->brk = brk; return mm->brk = brk;
} }
@ -1277,7 +1277,7 @@ share:
/* we flush the region from the icache only when the first executable /* we flush the region from the icache only when the first executable
* mapping of it is made */ * mapping of it is made */
if (vma->vm_flags & VM_EXEC && !region->vm_icache_flushed) { if (vma->vm_flags & VM_EXEC && !region->vm_icache_flushed) {
flush_icache_range(region->vm_start, region->vm_end); flush_icache_user_range(region->vm_start, region->vm_end);
region->vm_icache_flushed = true; region->vm_icache_flushed = true;
} }

View File

@ -5575,15 +5575,6 @@ static int __parse_numa_zonelist_order(char *s)
return 0; return 0;
} }
static __init int setup_numa_zonelist_order(char *s)
{
if (!s)
return 0;
return __parse_numa_zonelist_order(s);
}
early_param("numa_zonelist_order", setup_numa_zonelist_order);
char numa_zonelist_order[] = "Node"; char numa_zonelist_order[] = "Node";
/* /*

View File

@ -4,6 +4,7 @@
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/sysfs.h> #include <linux/sysfs.h>
#include <linux/kobject.h> #include <linux/kobject.h>
#include <linux/memory_hotplug.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/mmzone.h> #include <linux/mmzone.h>
#include <linux/pagemap.h> #include <linux/pagemap.h>
@ -30,13 +31,9 @@
*/ */
static struct page *page_idle_get_page(unsigned long pfn) static struct page *page_idle_get_page(unsigned long pfn)
{ {
struct page *page; struct page *page = pfn_to_online_page(pfn);
pg_data_t *pgdat; pg_data_t *pgdat;
if (!pfn_valid(pfn))
return NULL;
page = pfn_to_page(pfn);
if (!page || !PageLRU(page) || if (!page || !PageLRU(page) ||
!get_page_unless_zero(page)) !get_page_unless_zero(page))
return NULL; return NULL;

View File

@ -39,6 +39,7 @@ ALL_TESTS="$ALL_TESTS 0003:1:1:int_0002"
ALL_TESTS="$ALL_TESTS 0004:1:1:uint_0001" ALL_TESTS="$ALL_TESTS 0004:1:1:uint_0001"
ALL_TESTS="$ALL_TESTS 0005:3:1:int_0003" ALL_TESTS="$ALL_TESTS 0005:3:1:int_0003"
ALL_TESTS="$ALL_TESTS 0006:50:1:bitmap_0001" ALL_TESTS="$ALL_TESTS 0006:50:1:bitmap_0001"
ALL_TESTS="$ALL_TESTS 0007:1:1:boot_int"
test_modprobe() test_modprobe()
{ {
@ -122,7 +123,7 @@ test_reqs()
function load_req_mod() function load_req_mod()
{ {
if [ ! -d $DIR ]; then if [ ! -d $SYSCTL ]; then
if ! modprobe -q -n $TEST_DRIVER; then if ! modprobe -q -n $TEST_DRIVER; then
echo "$0: module $TEST_DRIVER not found [SKIP]" echo "$0: module $TEST_DRIVER not found [SKIP]"
exit $ksft_skip exit $ksft_skip
@ -752,6 +753,46 @@ sysctl_test_0006()
run_bitmaptest run_bitmaptest
} }
sysctl_test_0007()
{
TARGET="${SYSCTL}/boot_int"
if [ ! -f $TARGET ]; then
echo "Skipping test for $TARGET as it is not present ..."
return $ksft_skip
fi
if [ -d $DIR ]; then
echo "Boot param test only possible sysctl_test is built-in, not module:"
cat $TEST_DIR/config >&2
return $ksft_skip
fi
echo -n "Testing if $TARGET is set to 1 ..."
ORIG=$(cat "${TARGET}")
if [ x$ORIG = "x1" ]; then
echo "ok"
return 0
fi
echo "FAIL"
echo "Checking if /proc/cmdline contains setting of the expected parameter ..."
if [ ! -f /proc/cmdline ]; then
echo "/proc/cmdline does not exist, test inconclusive"
return 0
fi
FOUND=$(grep -c "sysctl[./]debug[./]test_sysctl[./]boot_int=1" /proc/cmdline)
if [ $FOUND = "1" ]; then
echo "Kernel param found but $TARGET is not 1, TEST FAILED"
rc=1
test_rc
fi
echo "Skipping test, expected kernel parameter missing."
echo "To perform this test, make sure kernel is booted with parameter: sysctl.debug.test_sysctl.boot_int=1"
return $ksft_skip
}
list_tests() list_tests()
{ {
echo "Test ID list:" echo "Test ID list:"
@ -766,6 +807,7 @@ list_tests()
echo "0004 x $(get_test_count 0004) - tests proc_douintvec()" echo "0004 x $(get_test_count 0004) - tests proc_douintvec()"
echo "0005 x $(get_test_count 0005) - tests proc_douintvec() array" echo "0005 x $(get_test_count 0005) - tests proc_douintvec() array"
echo "0006 x $(get_test_count 0006) - tests proc_do_large_bitmap()" echo "0006 x $(get_test_count 0006) - tests proc_do_large_bitmap()"
echo "0007 x $(get_test_count 0007) - tests setting sysctl from kernel boot param"
} }
usage() usage()

View File

@ -1740,7 +1740,6 @@ static bool hva_to_pfn_fast(unsigned long addr, bool write_fault,
bool *writable, kvm_pfn_t *pfn) bool *writable, kvm_pfn_t *pfn)
{ {
struct page *page[1]; struct page *page[1];
int npages;
/* /*
* Fast pin a writable pfn only if it is a write fault request * Fast pin a writable pfn only if it is a write fault request
@ -1750,8 +1749,7 @@ static bool hva_to_pfn_fast(unsigned long addr, bool write_fault,
if (!(write_fault || writable)) if (!(write_fault || writable))
return false; return false;
npages = __get_user_pages_fast(addr, 1, 1, page); if (get_user_page_fast_only(addr, FOLL_WRITE, page)) {
if (npages == 1) {
*pfn = page_to_pfn(page[0]); *pfn = page_to_pfn(page[0]);
if (writable) if (writable)
@ -1791,7 +1789,7 @@ static int hva_to_pfn_slow(unsigned long addr, bool *async, bool write_fault,
if (unlikely(!write_fault) && writable) { if (unlikely(!write_fault) && writable) {
struct page *wpage; struct page *wpage;
if (__get_user_pages_fast(addr, 1, 1, &wpage) == 1) { if (get_user_page_fast_only(addr, FOLL_WRITE, &wpage)) {
*writable = true; *writable = true;
put_page(page); put_page(page);
page = wpage; page = wpage;
@ -2003,7 +2001,7 @@ int gfn_to_page_many_atomic(struct kvm_memory_slot *slot, gfn_t gfn,
if (entry < nr_pages) if (entry < nr_pages)
return 0; return 0;
return __get_user_pages_fast(addr, nr_pages, 1, pages); return get_user_pages_fast_only(addr, nr_pages, FOLL_WRITE, pages);
} }
EXPORT_SYMBOL_GPL(gfn_to_page_many_atomic); EXPORT_SYMBOL_GPL(gfn_to_page_many_atomic);