forked from Minki/linux
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:
commit
20b0d06722
@ -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
|
||||||
|
@ -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)``.
|
||||||
|
|
||||||
|
@ -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
|
||||||
=======
|
=======
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
===========
|
===========
|
||||||
|
@ -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
|
||||||
===================================================
|
===================================================
|
||||||
|
@ -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 */
|
||||||
|
@ -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;
|
||||||
|
@ -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().
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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 */
|
||||||
|
@ -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 */
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
|
||||||
#define flush_dcache_mmap_unlock(mapping) do { } while (0)
|
|
||||||
|
|
||||||
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
|
||||||
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 */
|
||||||
|
@ -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,
|
||||||
|
@ -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 */
|
||||||
|
@ -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) {
|
||||||
|
@ -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 */
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
|
||||||
* indexed or tagged caches. So we can use the default here.
|
|
||||||
*/
|
|
||||||
#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_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) \
|
|
||||||
do { \
|
do { \
|
||||||
memcpy(dst, src, len); \
|
|
||||||
if (vma->vm_flags & VM_EXEC) \
|
if (vma->vm_flags & VM_EXEC) \
|
||||||
sync_icache_dcache(page); \
|
sync_icache_dcache(page); \
|
||||||
} 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_CACHEFLUSH_H */
|
#endif /* __ASM_CACHEFLUSH_H */
|
||||||
|
@ -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 */
|
||||||
|
@ -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 */
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
@ -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 */
|
||||||
|
@ -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 */
|
||||||
|
@ -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);
|
||||||
|
@ -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));\
|
||||||
|
@ -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,
|
||||||
|
@ -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>
|
||||||
|
@ -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().
|
||||||
|
@ -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>
|
||||||
|
@ -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 { \
|
||||||
|
@ -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>
|
||||||
|
@ -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"
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 +
|
||||||
|
@ -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.
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
@ -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 */
|
||||||
|
@ -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 { \
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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 */
|
||||||
|
@ -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.
|
||||||
*/
|
*/
|
||||||
|
@ -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); \
|
||||||
|
@ -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)) \
|
||||||
|
@ -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, \
|
||||||
|
@ -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;
|
||||||
|
@ -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,
|
||||||
|
@ -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)
|
||||||
|
@ -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 { \
|
||||||
|
@ -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)
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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.
|
||||||
|
@ -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,
|
||||||
|
@ -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,
|
||||||
|
@ -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);
|
||||||
|
@ -866,16 +866,24 @@ 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,
|
||||||
|
@ -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);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -1032,9 +1032,14 @@ 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) {
|
||||||
|
if (IS_ENABLED(CONFIG_DYNAMIC_DEBUG)) {
|
||||||
pr_warn("_ddebug table is empty in a CONFIG_DYNAMIC_DEBUG build\n");
|
pr_warn("_ddebug table is empty in a CONFIG_DYNAMIC_DEBUG build\n");
|
||||||
return 1;
|
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;
|
||||||
iter_start = iter;
|
iter_start = iter;
|
||||||
|
@ -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,
|
||||||
|
@ -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;
|
||||||
|
73
mm/gup.c
73
mm/gup.c
@ -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);
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -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;
|
||||||
|
@ -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()
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user