mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07:00
Merge branch 'akpm' (patches from Andrew)
Merge misc updates from Andrew Morton: "146 patches. Subsystems affected by this patch series: kthread, ia64, scripts, ntfs, squashfs, ocfs2, vfs, and mm (slab-generic, slab, kmemleak, dax, kasan, debug, pagecache, gup, shmem, frontswap, memremap, memcg, selftests, pagemap, dma, vmalloc, memory-failure, hugetlb, userfaultfd, vmscan, mempolicy, oom-kill, hugetlbfs, migration, thp, ksm, page-poison, percpu, rmap, zswap, zram, cleanups, hmm, and damon)" * emailed patches from Andrew Morton <akpm@linux-foundation.org>: (146 commits) mm/damon: hide kernel pointer from tracepoint event mm/damon/vaddr: hide kernel pointer from damon_va_three_regions() failure log mm/damon/vaddr: use pr_debug() for damon_va_three_regions() failure logging mm/damon/dbgfs: remove an unnecessary variable mm/damon: move the implementation of damon_insert_region to damon.h mm/damon: add access checking for hugetlb pages Docs/admin-guide/mm/damon/usage: update for schemes statistics mm/damon/dbgfs: support all DAMOS stats Docs/admin-guide/mm/damon/reclaim: document statistics parameters mm/damon/reclaim: provide reclamation statistics mm/damon/schemes: account how many times quota limit has exceeded mm/damon/schemes: account scheme actions that successfully applied mm/damon: remove a mistakenly added comment for a future feature Docs/admin-guide/mm/damon/usage: update for kdamond_pid and (mk|rm)_contexts Docs/admin-guide/mm/damon/usage: mention tracepoint at the beginning Docs/admin-guide/mm/damon/usage: remove redundant information Docs/admin-guide/mm/damon/usage: update for scheme quotas and watermarks mm/damon: convert macro functions to static inline functions mm/damon: modify damon_rand() macro to static inline function mm/damon: move damon_rand() definition into damon.h ...
This commit is contained in:
@@ -29,12 +29,14 @@ Brief summary of control files::
|
||||
hugetlb.<hugepagesize>.max_usage_in_bytes # show max "hugepagesize" hugetlb usage recorded
|
||||
hugetlb.<hugepagesize>.usage_in_bytes # show current usage for "hugepagesize" hugetlb
|
||||
hugetlb.<hugepagesize>.failcnt # show the number of allocation failure due to HugeTLB usage limit
|
||||
hugetlb.<hugepagesize>.numa_stat # show the numa information of the hugetlb memory charged to this cgroup
|
||||
|
||||
For a system supporting three hugepage sizes (64k, 32M and 1G), the control
|
||||
files include::
|
||||
|
||||
hugetlb.1GB.limit_in_bytes
|
||||
hugetlb.1GB.max_usage_in_bytes
|
||||
hugetlb.1GB.numa_stat
|
||||
hugetlb.1GB.usage_in_bytes
|
||||
hugetlb.1GB.failcnt
|
||||
hugetlb.1GB.rsvd.limit_in_bytes
|
||||
@@ -43,6 +45,7 @@ files include::
|
||||
hugetlb.1GB.rsvd.failcnt
|
||||
hugetlb.64KB.limit_in_bytes
|
||||
hugetlb.64KB.max_usage_in_bytes
|
||||
hugetlb.64KB.numa_stat
|
||||
hugetlb.64KB.usage_in_bytes
|
||||
hugetlb.64KB.failcnt
|
||||
hugetlb.64KB.rsvd.limit_in_bytes
|
||||
@@ -51,6 +54,7 @@ files include::
|
||||
hugetlb.64KB.rsvd.failcnt
|
||||
hugetlb.32MB.limit_in_bytes
|
||||
hugetlb.32MB.max_usage_in_bytes
|
||||
hugetlb.32MB.numa_stat
|
||||
hugetlb.32MB.usage_in_bytes
|
||||
hugetlb.32MB.failcnt
|
||||
hugetlb.32MB.rsvd.limit_in_bytes
|
||||
|
||||
@@ -1268,6 +1268,9 @@ PAGE_SIZE multiple when read back.
|
||||
The number of processes belonging to this cgroup
|
||||
killed by any kind of OOM killer.
|
||||
|
||||
oom_group_kill
|
||||
The number of times a group OOM has occurred.
|
||||
|
||||
memory.events.local
|
||||
Similar to memory.events but the fields in the file are local
|
||||
to the cgroup i.e. not hierarchical. The file modified event
|
||||
@@ -1311,6 +1314,9 @@ PAGE_SIZE multiple when read back.
|
||||
sock (npn)
|
||||
Amount of memory used in network transmission buffers
|
||||
|
||||
vmalloc (npn)
|
||||
Amount of memory used for vmap backed memory.
|
||||
|
||||
shmem
|
||||
Amount of cached filesystem data that is swap-backed,
|
||||
such as tmpfs, shm segments, shared anonymous mmap()s
|
||||
@@ -2260,6 +2266,11 @@ HugeTLB Interface Files
|
||||
are local to the cgroup i.e. not hierarchical. The file modified event
|
||||
generated on this file reflects only the local events.
|
||||
|
||||
hugetlb.<hugepagesize>.numa_stat
|
||||
Similar to memory.numa_stat, it shows the numa information of the
|
||||
hugetlb pages of <hugepagesize> in this cgroup. Only active in
|
||||
use hugetlb pages are included. The per-node values are in bytes.
|
||||
|
||||
Misc
|
||||
----
|
||||
|
||||
|
||||
@@ -208,6 +208,31 @@ PID of the DAMON thread.
|
||||
If DAMON_RECLAIM is enabled, this becomes the PID of the worker thread. Else,
|
||||
-1.
|
||||
|
||||
nr_reclaim_tried_regions
|
||||
------------------------
|
||||
|
||||
Number of memory regions that tried to be reclaimed by DAMON_RECLAIM.
|
||||
|
||||
bytes_reclaim_tried_regions
|
||||
---------------------------
|
||||
|
||||
Total bytes of memory regions that tried to be reclaimed by DAMON_RECLAIM.
|
||||
|
||||
nr_reclaimed_regions
|
||||
--------------------
|
||||
|
||||
Number of memory regions that successfully be reclaimed by DAMON_RECLAIM.
|
||||
|
||||
bytes_reclaimed_regions
|
||||
-----------------------
|
||||
|
||||
Total bytes of memory regions that successfully be reclaimed by DAMON_RECLAIM.
|
||||
|
||||
nr_quota_exceeds
|
||||
----------------
|
||||
|
||||
Number of times that the time/space quota limits have exceeded.
|
||||
|
||||
Example
|
||||
=======
|
||||
|
||||
|
||||
@@ -7,37 +7,40 @@ Detailed Usages
|
||||
DAMON provides below three interfaces for different users.
|
||||
|
||||
- *DAMON user space tool.*
|
||||
This is for privileged people such as system administrators who want a
|
||||
just-working human-friendly interface. Using this, users can use the DAMON’s
|
||||
major features in a human-friendly way. It may not be highly tuned for
|
||||
special cases, though. It supports both virtual and physical address spaces
|
||||
monitoring.
|
||||
`This <https://github.com/awslabs/damo>`_ is for privileged people such as
|
||||
system administrators who want a just-working human-friendly interface.
|
||||
Using this, users can use the DAMON’s major features in a human-friendly way.
|
||||
It may not be highly tuned for special cases, though. It supports both
|
||||
virtual and physical address spaces monitoring. For more detail, please
|
||||
refer to its `usage document
|
||||
<https://github.com/awslabs/damo/blob/next/USAGE.md>`_.
|
||||
- *debugfs interface.*
|
||||
This is for privileged user space programmers who want more optimized use of
|
||||
DAMON. Using this, users can use DAMON’s major features by reading
|
||||
from and writing to special debugfs files. Therefore, you can write and use
|
||||
your personalized DAMON debugfs wrapper programs that reads/writes the
|
||||
debugfs files instead of you. The DAMON user space tool is also a reference
|
||||
implementation of such programs. It supports both virtual and physical
|
||||
address spaces monitoring.
|
||||
:ref:`This <debugfs_interface>` is for privileged user space programmers who
|
||||
want more optimized use of DAMON. Using this, users can use DAMON’s major
|
||||
features by reading from and writing to special debugfs files. Therefore,
|
||||
you can write and use your personalized DAMON debugfs wrapper programs that
|
||||
reads/writes the debugfs files instead of you. The `DAMON user space tool
|
||||
<https://github.com/awslabs/damo>`_ is one example of such programs. It
|
||||
supports both virtual and physical address spaces monitoring. Note that this
|
||||
interface provides only simple :ref:`statistics <damos_stats>` for the
|
||||
monitoring results. For detailed monitoring results, DAMON provides a
|
||||
:ref:`tracepoint <tracepoint>`.
|
||||
- *Kernel Space Programming Interface.*
|
||||
This is for kernel space programmers. Using this, users can utilize every
|
||||
feature of DAMON most flexibly and efficiently by writing kernel space
|
||||
DAMON application programs for you. You can even extend DAMON for various
|
||||
address spaces.
|
||||
:doc:`This </vm/damon/api>` is for kernel space programmers. Using this,
|
||||
users can utilize every feature of DAMON most flexibly and efficiently by
|
||||
writing kernel space DAMON application programs for you. You can even extend
|
||||
DAMON for various address spaces. For detail, please refer to the interface
|
||||
:doc:`document </vm/damon/api>`.
|
||||
|
||||
Nevertheless, you could write your own user space tool using the debugfs
|
||||
interface. A reference implementation is available at
|
||||
https://github.com/awslabs/damo. If you are a kernel programmer, you could
|
||||
refer to :doc:`/vm/damon/api` for the kernel space programming interface. For
|
||||
the reason, this document describes only the debugfs interface
|
||||
|
||||
.. _debugfs_interface:
|
||||
|
||||
debugfs Interface
|
||||
=================
|
||||
|
||||
DAMON exports five files, ``attrs``, ``target_ids``, ``init_regions``,
|
||||
``schemes`` and ``monitor_on`` under its debugfs directory,
|
||||
``<debugfs>/damon/``.
|
||||
DAMON exports eight files, ``attrs``, ``target_ids``, ``init_regions``,
|
||||
``schemes``, ``monitor_on``, ``kdamond_pid``, ``mk_contexts`` and
|
||||
``rm_contexts`` under its debugfs directory, ``<debugfs>/damon/``.
|
||||
|
||||
|
||||
Attributes
|
||||
@@ -131,24 +134,38 @@ Schemes
|
||||
|
||||
For usual DAMON-based data access aware memory management optimizations, users
|
||||
would simply want the system to apply a memory management action to a memory
|
||||
region of a specific size having a specific access frequency for a specific
|
||||
time. DAMON receives such formalized operation schemes from the user and
|
||||
applies those to the target processes. It also counts the total number and
|
||||
size of regions that each scheme is applied. This statistics can be used for
|
||||
online analysis or tuning of the schemes.
|
||||
region of a specific access pattern. DAMON receives such formalized operation
|
||||
schemes from the user and applies those to the target processes.
|
||||
|
||||
Users can get and set the schemes by reading from and writing to ``schemes``
|
||||
debugfs file. Reading the file also shows the statistics of each scheme. To
|
||||
the file, each of the schemes should be represented in each line in below form:
|
||||
the file, each of the schemes should be represented in each line in below
|
||||
form::
|
||||
|
||||
min-size max-size min-acc max-acc min-age max-age action
|
||||
<target access pattern> <action> <quota> <watermarks>
|
||||
|
||||
Note that the ranges are closed interval. Bytes for the size of regions
|
||||
(``min-size`` and ``max-size``), number of monitored accesses per aggregate
|
||||
interval for access frequency (``min-acc`` and ``max-acc``), number of
|
||||
aggregate intervals for the age of regions (``min-age`` and ``max-age``), and a
|
||||
predefined integer for memory management actions should be used. The supported
|
||||
numbers and their meanings are as below.
|
||||
You can disable schemes by simply writing an empty string to the file.
|
||||
|
||||
Target Access Pattern
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The ``<target access pattern>`` is constructed with three ranges in below
|
||||
form::
|
||||
|
||||
min-size max-size min-acc max-acc min-age max-age
|
||||
|
||||
Specifically, bytes for the size of regions (``min-size`` and ``max-size``),
|
||||
number of monitored accesses per aggregate interval for access frequency
|
||||
(``min-acc`` and ``max-acc``), number of aggregate intervals for the age of
|
||||
regions (``min-age`` and ``max-age``) are specified. Note that the ranges are
|
||||
closed interval.
|
||||
|
||||
Action
|
||||
~~~~~~
|
||||
|
||||
The ``<action>`` is a predefined integer for memory management actions, which
|
||||
DAMON will apply to the regions having the target access pattern. The
|
||||
supported numbers and their meanings are as below.
|
||||
|
||||
- 0: Call ``madvise()`` for the region with ``MADV_WILLNEED``
|
||||
- 1: Call ``madvise()`` for the region with ``MADV_COLD``
|
||||
@@ -157,20 +174,82 @@ numbers and their meanings are as below.
|
||||
- 4: Call ``madvise()`` for the region with ``MADV_NOHUGEPAGE``
|
||||
- 5: Do nothing but count the statistics
|
||||
|
||||
You can disable schemes by simply writing an empty string to the file. For
|
||||
example, below commands applies a scheme saying "If a memory region of size in
|
||||
[4KiB, 8KiB] is showing accesses per aggregate interval in [0, 5] for aggregate
|
||||
interval in [10, 20], page out the region", check the entered scheme again, and
|
||||
finally remove the scheme. ::
|
||||
Quota
|
||||
~~~~~
|
||||
|
||||
Optimal ``target access pattern`` for each ``action`` is workload dependent, so
|
||||
not easy to find. Worse yet, setting a scheme of some action too aggressive
|
||||
can cause severe overhead. To avoid such overhead, users can limit time and
|
||||
size quota for the scheme via the ``<quota>`` in below form::
|
||||
|
||||
<ms> <sz> <reset interval> <priority weights>
|
||||
|
||||
This makes DAMON to try to use only up to ``<ms>`` milliseconds for applying
|
||||
the action to memory regions of the ``target access pattern`` within the
|
||||
``<reset interval>`` milliseconds, and to apply the action to only up to
|
||||
``<sz>`` bytes of memory regions within the ``<reset interval>``. Setting both
|
||||
``<ms>`` and ``<sz>`` zero disables the quota limits.
|
||||
|
||||
When the quota limit is expected to be exceeded, DAMON prioritizes found memory
|
||||
regions of the ``target access pattern`` based on their size, access frequency,
|
||||
and age. For personalized prioritization, users can set the weights for the
|
||||
three properties in ``<priority weights>`` in below form::
|
||||
|
||||
<size weight> <access frequency weight> <age weight>
|
||||
|
||||
Watermarks
|
||||
~~~~~~~~~~
|
||||
|
||||
Some schemes would need to run based on current value of the system's specific
|
||||
metrics like free memory ratio. For such cases, users can specify watermarks
|
||||
for the condition.::
|
||||
|
||||
<metric> <check interval> <high mark> <middle mark> <low mark>
|
||||
|
||||
``<metric>`` is a predefined integer for the metric to be checked. The
|
||||
supported numbers and their meanings are as below.
|
||||
|
||||
- 0: Ignore the watermarks
|
||||
- 1: System's free memory rate (per thousand)
|
||||
|
||||
The value of the metric is checked every ``<check interval>`` microseconds.
|
||||
|
||||
If the value is higher than ``<high mark>`` or lower than ``<low mark>``, the
|
||||
scheme is deactivated. If the value is lower than ``<mid mark>``, the scheme
|
||||
is activated.
|
||||
|
||||
.. _damos_stats:
|
||||
|
||||
Statistics
|
||||
~~~~~~~~~~
|
||||
|
||||
It also counts the total number and bytes of regions that each scheme is tried
|
||||
to be applied, the two numbers for the regions that each scheme is successfully
|
||||
applied, and the total number of the quota limit exceeds. This statistics can
|
||||
be used for online analysis or tuning of the schemes.
|
||||
|
||||
The statistics can be shown by reading the ``schemes`` file. Reading the file
|
||||
will show each scheme you entered in each line, and the five numbers for the
|
||||
statistics will be added at the end of each line.
|
||||
|
||||
Example
|
||||
~~~~~~~
|
||||
|
||||
Below commands applies a scheme saying "If a memory region of size in [4KiB,
|
||||
8KiB] is showing accesses per aggregate interval in [0, 5] for aggregate
|
||||
interval in [10, 20], page out the region. For the paging out, use only up to
|
||||
10ms per second, and also don't page out more than 1GiB per second. Under the
|
||||
limitation, page out memory regions having longer age first. Also, check the
|
||||
free memory rate of the system every 5 seconds, start the monitoring and paging
|
||||
out when the free memory rate becomes lower than 50%, but stop it if the free
|
||||
memory rate becomes larger than 60%, or lower than 30%".::
|
||||
|
||||
# cd <debugfs>/damon
|
||||
# echo "4096 8192 0 5 10 20 2" > schemes
|
||||
# cat schemes
|
||||
4096 8192 0 5 10 20 2 0 0
|
||||
# echo > schemes
|
||||
|
||||
The last two integers in the 4th line of above example is the total number and
|
||||
the total size of the regions that the scheme is applied.
|
||||
# scheme="4096 8192 0 5 10 20 2" # target access pattern and action
|
||||
# scheme+=" 10 $((1024*1024*1024)) 1000" # quotas
|
||||
# scheme+=" 0 0 100" # prioritization weights
|
||||
# scheme+=" 1 5000000 600 500 300" # watermarks
|
||||
# echo "$scheme" > schemes
|
||||
|
||||
|
||||
Turning On/Off
|
||||
@@ -195,6 +274,54 @@ the monitoring is turned on. If you write to the files while DAMON is running,
|
||||
an error code such as ``-EBUSY`` will be returned.
|
||||
|
||||
|
||||
Monitoring Thread PID
|
||||
---------------------
|
||||
|
||||
DAMON does requested monitoring with a kernel thread called ``kdamond``. You
|
||||
can get the pid of the thread by reading the ``kdamond_pid`` file. When the
|
||||
monitoring is turned off, reading the file returns ``none``. ::
|
||||
|
||||
# cd <debugfs>/damon
|
||||
# cat monitor_on
|
||||
off
|
||||
# cat kdamond_pid
|
||||
none
|
||||
# echo on > monitor_on
|
||||
# cat kdamond_pid
|
||||
18594
|
||||
|
||||
|
||||
Using Multiple Monitoring Threads
|
||||
---------------------------------
|
||||
|
||||
One ``kdamond`` thread is created for each monitoring context. You can create
|
||||
and remove monitoring contexts for multiple ``kdamond`` required use case using
|
||||
the ``mk_contexts`` and ``rm_contexts`` files.
|
||||
|
||||
Writing the name of the new context to the ``mk_contexts`` file creates a
|
||||
directory of the name on the DAMON debugfs directory. The directory will have
|
||||
DAMON debugfs files for the context. ::
|
||||
|
||||
# cd <debugfs>/damon
|
||||
# ls foo
|
||||
# ls: cannot access 'foo': No such file or directory
|
||||
# echo foo > mk_contexts
|
||||
# ls foo
|
||||
# attrs init_regions kdamond_pid schemes target_ids
|
||||
|
||||
If the context is not needed anymore, you can remove it and the corresponding
|
||||
directory by putting the name of the context to the ``rm_contexts`` file. ::
|
||||
|
||||
# echo foo > rm_contexts
|
||||
# ls foo
|
||||
# ls: cannot access 'foo': No such file or directory
|
||||
|
||||
Note that ``mk_contexts``, ``rm_contexts``, and ``monitor_on`` files are in the
|
||||
root directory only.
|
||||
|
||||
|
||||
.. _tracepoint:
|
||||
|
||||
Tracepoint for Monitoring Results
|
||||
=================================
|
||||
|
||||
|
||||
@@ -408,7 +408,7 @@ follows:
|
||||
Memory Policy APIs
|
||||
==================
|
||||
|
||||
Linux supports 3 system calls for controlling memory policy. These APIS
|
||||
Linux supports 4 system calls for controlling memory policy. These APIS
|
||||
always affect only the calling task, the calling task's address space, or
|
||||
some shared object mapped into the calling task's address space.
|
||||
|
||||
@@ -460,6 +460,20 @@ requested via the 'flags' argument.
|
||||
|
||||
See the mbind(2) man page for more details.
|
||||
|
||||
Set home node for a Range of Task's Address Spacec::
|
||||
|
||||
long sys_set_mempolicy_home_node(unsigned long start, unsigned long len,
|
||||
unsigned long home_node,
|
||||
unsigned long flags);
|
||||
|
||||
sys_set_mempolicy_home_node set the home node for a VMA policy present in the
|
||||
task's address range. The system call updates the home node only for the existing
|
||||
mempolicy range. Other address ranges are ignored. A home node is the NUMA node
|
||||
closest to which page allocation will come from. Specifying the home node override
|
||||
the default allocation policy to allocate memory close to the local node for an
|
||||
executing CPU.
|
||||
|
||||
|
||||
Memory Policy Command Line Interface
|
||||
====================================
|
||||
|
||||
|
||||
@@ -948,7 +948,7 @@ how much memory needs to be free before kswapd goes back to sleep.
|
||||
|
||||
The unit is in fractions of 10,000. The default value of 10 means the
|
||||
distances between watermarks are 0.1% of the available memory in the
|
||||
node/system. The maximum value is 1000, or 10% of memory.
|
||||
node/system. The maximum value is 3000, or 30% of memory.
|
||||
|
||||
A high rate of threads entering direct reclaim (allocstall) or kswapd
|
||||
going to sleep prematurely (kswapd_low_wmark_hit_quickly) can indicate
|
||||
|
||||
@@ -426,12 +426,14 @@ with the memory region, as the case would be with BSS (uninitialized data).
|
||||
The "pathname" shows the name associated file for this mapping. If the mapping
|
||||
is not associated with a file:
|
||||
|
||||
======= ====================================
|
||||
============= ====================================
|
||||
[heap] the heap of the program
|
||||
[stack] the stack of the main process
|
||||
[vdso] the "virtual dynamic shared object",
|
||||
the kernel system call handler
|
||||
======= ====================================
|
||||
[anon:<name>] an anonymous mapping that has been
|
||||
named by userspace
|
||||
============= ====================================
|
||||
|
||||
or if empty, the mapping is anonymous.
|
||||
|
||||
|
||||
@@ -66,9 +66,11 @@ PTE Page Table Helpers
|
||||
+---------------------------+--------------------------------------------------+
|
||||
| pte_mknotpresent | Invalidates a mapped PTE |
|
||||
+---------------------------+--------------------------------------------------+
|
||||
| ptep_get_and_clear | Clears a PTE |
|
||||
| ptep_clear | Clears a PTE |
|
||||
+---------------------------+--------------------------------------------------+
|
||||
| ptep_get_and_clear_full | Clears a PTE |
|
||||
| ptep_get_and_clear | Clears and returns PTE |
|
||||
+---------------------------+--------------------------------------------------+
|
||||
| ptep_get_and_clear_full | Clears and returns PTE (batched PTE unmap) |
|
||||
+---------------------------+--------------------------------------------------+
|
||||
| ptep_test_and_clear_young | Clears young from a PTE |
|
||||
+---------------------------+--------------------------------------------------+
|
||||
@@ -247,12 +249,12 @@ SWAP Page Table Helpers
|
||||
| __swp_to_pmd_entry | Creates a mapped PMD from a swapped entry (arch) |
|
||||
+---------------------------+--------------------------------------------------+
|
||||
| is_migration_entry | Tests a migration (read or write) swapped entry |
|
||||
+---------------------------+--------------------------------------------------+
|
||||
| is_write_migration_entry | Tests a write migration swapped entry |
|
||||
+---------------------------+--------------------------------------------------+
|
||||
| make_migration_entry_read | Converts into read migration swapped entry |
|
||||
+---------------------------+--------------------------------------------------+
|
||||
| make_migration_entry | Creates a migration swapped entry (read or write)|
|
||||
+---------------------------+--------------------------------------------------+
|
||||
+-------------------------------+----------------------------------------------+
|
||||
| is_writable_migration_entry | Tests a write migration swapped entry |
|
||||
+-------------------------------+----------------------------------------------+
|
||||
| make_readable_migration_entry | Creates a read migration swapped entry |
|
||||
+-------------------------------+----------------------------------------------+
|
||||
| make_writable_migration_entry | Creates a write migration swapped entry |
|
||||
+-------------------------------+----------------------------------------------+
|
||||
|
||||
[1] https://lore.kernel.org/linux-mm/20181017020930.GN30832@redhat.com/
|
||||
|
||||
@@ -31,10 +31,12 @@ algorithms. If you are looking for advice on simply allocating memory, see the
|
||||
page_migration
|
||||
page_frags
|
||||
page_owner
|
||||
page_table_check
|
||||
remap_file_pages
|
||||
slub
|
||||
split_page_table_lock
|
||||
transhuge
|
||||
unevictable-lru
|
||||
vmalloced-kernel-stacks
|
||||
z3fold
|
||||
zsmalloc
|
||||
|
||||
@@ -263,15 +263,15 @@ Monitoring Migration
|
||||
The following events (counters) can be used to monitor page migration.
|
||||
|
||||
1. PGMIGRATE_SUCCESS: Normal page migration success. Each count means that a
|
||||
page was migrated. If the page was a non-THP page, then this counter is
|
||||
increased by one. If the page was a THP, then this counter is increased by
|
||||
the number of THP subpages. For example, migration of a single 2MB THP that
|
||||
has 4KB-size base pages (subpages) will cause this counter to increase by
|
||||
512.
|
||||
page was migrated. If the page was a non-THP and non-hugetlb page, then
|
||||
this counter is increased by one. If the page was a THP or hugetlb, then
|
||||
this counter is increased by the number of THP or hugetlb subpages.
|
||||
For example, migration of a single 2MB THP that has 4KB-size base pages
|
||||
(subpages) will cause this counter to increase by 512.
|
||||
|
||||
2. PGMIGRATE_FAIL: Normal page migration failure. Same counting rules as for
|
||||
PGMIGRATE_SUCCESS, above: this will be increased by the number of subpages,
|
||||
if it was a THP.
|
||||
if it was a THP or hugetlb.
|
||||
|
||||
3. THP_MIGRATION_SUCCESS: A THP was migrated without being split.
|
||||
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
.. _page_table_check:
|
||||
|
||||
================
|
||||
Page Table Check
|
||||
================
|
||||
|
||||
Introduction
|
||||
============
|
||||
|
||||
Page table check allows to hardern the kernel by ensuring that some types of
|
||||
the memory corruptions are prevented.
|
||||
|
||||
Page table check performs extra verifications at the time when new pages become
|
||||
accessible from the userspace by getting their page table entries (PTEs PMDs
|
||||
etc.) added into the table.
|
||||
|
||||
In case of detected corruption, the kernel is crashed. There is a small
|
||||
performance and memory overhead associated with the page table check. Therefore,
|
||||
it is disabled by default, but can be optionally enabled on systems where the
|
||||
extra hardening outweighs the performance costs. Also, because page table check
|
||||
is synchronous, it can help with debugging double map memory corruption issues,
|
||||
by crashing kernel at the time wrong mapping occurs instead of later which is
|
||||
often the case with memory corruptions bugs.
|
||||
|
||||
Double mapping detection logic
|
||||
==============================
|
||||
|
||||
+-------------------+-------------------+-------------------+------------------+
|
||||
| Current Mapping | New mapping | Permissions | Rule |
|
||||
+===================+===================+===================+==================+
|
||||
| Anonymous | Anonymous | Read | Allow |
|
||||
+-------------------+-------------------+-------------------+------------------+
|
||||
| Anonymous | Anonymous | Read / Write | Prohibit |
|
||||
+-------------------+-------------------+-------------------+------------------+
|
||||
| Anonymous | Named | Any | Prohibit |
|
||||
+-------------------+-------------------+-------------------+------------------+
|
||||
| Named | Anonymous | Any | Prohibit |
|
||||
+-------------------+-------------------+-------------------+------------------+
|
||||
| Named | Named | Any | Allow |
|
||||
+-------------------+-------------------+-------------------+------------------+
|
||||
|
||||
Enabling Page Table Check
|
||||
=========================
|
||||
|
||||
Build kernel with:
|
||||
|
||||
- PAGE_TABLE_CHECK=y
|
||||
Note, it can only be enabled on platforms where ARCH_SUPPORTS_PAGE_TABLE_CHECK
|
||||
is available.
|
||||
|
||||
- Boot with 'page_table_check=on' kernel parameter.
|
||||
|
||||
Optionally, build kernel with PAGE_TABLE_CHECK_ENFORCED in order to have page
|
||||
table support without extra kernel parameter.
|
||||
@@ -0,0 +1,153 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
=====================================
|
||||
Virtually Mapped Kernel Stack Support
|
||||
=====================================
|
||||
|
||||
:Author: Shuah Khan <skhan@linuxfoundation.org>
|
||||
|
||||
.. contents:: :local:
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
||||
This is a compilation of information from the code and original patch
|
||||
series that introduced the `Virtually Mapped Kernel Stacks feature
|
||||
<https://lwn.net/Articles/694348/>`
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
Kernel stack overflows are often hard to debug and make the kernel
|
||||
susceptible to exploits. Problems could show up at a later time making
|
||||
it difficult to isolate and root-cause.
|
||||
|
||||
Virtually-mapped kernel stacks with guard pages causes kernel stack
|
||||
overflows to be caught immediately rather than causing difficult to
|
||||
diagnose corruptions.
|
||||
|
||||
HAVE_ARCH_VMAP_STACK and VMAP_STACK configuration options enable
|
||||
support for virtually mapped stacks with guard pages. This feature
|
||||
causes reliable faults when the stack overflows. The usability of
|
||||
the stack trace after overflow and response to the overflow itself
|
||||
is architecture dependent.
|
||||
|
||||
.. note::
|
||||
As of this writing, arm64, powerpc, riscv, s390, um, and x86 have
|
||||
support for VMAP_STACK.
|
||||
|
||||
HAVE_ARCH_VMAP_STACK
|
||||
--------------------
|
||||
|
||||
Architectures that can support Virtually Mapped Kernel Stacks should
|
||||
enable this bool configuration option. The requirements are:
|
||||
|
||||
- vmalloc space must be large enough to hold many kernel stacks. This
|
||||
may rule out many 32-bit architectures.
|
||||
- Stacks in vmalloc space need to work reliably. For example, if
|
||||
vmap page tables are created on demand, either this mechanism
|
||||
needs to work while the stack points to a virtual address with
|
||||
unpopulated page tables or arch code (switch_to() and switch_mm(),
|
||||
most likely) needs to ensure that the stack's page table entries
|
||||
are populated before running on a possibly unpopulated stack.
|
||||
- If the stack overflows into a guard page, something reasonable
|
||||
should happen. The definition of "reasonable" is flexible, but
|
||||
instantly rebooting without logging anything would be unfriendly.
|
||||
|
||||
VMAP_STACK
|
||||
----------
|
||||
|
||||
VMAP_STACK bool configuration option when enabled allocates virtually
|
||||
mapped task stacks. This option depends on HAVE_ARCH_VMAP_STACK.
|
||||
|
||||
- Enable this if you want the use virtually-mapped kernel stacks
|
||||
with guard pages. This causes kernel stack overflows to be caught
|
||||
immediately rather than causing difficult-to-diagnose corruption.
|
||||
|
||||
.. note::
|
||||
|
||||
Using this feature with KASAN requires architecture support
|
||||
for backing virtual mappings with real shadow memory, and
|
||||
KASAN_VMALLOC must be enabled.
|
||||
|
||||
.. note::
|
||||
|
||||
VMAP_STACK is enabled, it is not possible to run DMA on stack
|
||||
allocated data.
|
||||
|
||||
Kernel configuration options and dependencies keep changing. Refer to
|
||||
the latest code base:
|
||||
|
||||
`Kconfig <https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/Kconfig>`
|
||||
|
||||
Allocation
|
||||
-----------
|
||||
|
||||
When a new kernel thread is created, thread stack is allocated from
|
||||
virtually contiguous memory pages from the page level allocator. These
|
||||
pages are mapped into contiguous kernel virtual space with PAGE_KERNEL
|
||||
protections.
|
||||
|
||||
alloc_thread_stack_node() calls __vmalloc_node_range() to allocate stack
|
||||
with PAGE_KERNEL protections.
|
||||
|
||||
- Allocated stacks are cached and later reused by new threads, so memcg
|
||||
accounting is performed manually on assigning/releasing stacks to tasks.
|
||||
Hence, __vmalloc_node_range is called without __GFP_ACCOUNT.
|
||||
- vm_struct is cached to be able to find when thread free is initiated
|
||||
in interrupt context. free_thread_stack() can be called in interrupt
|
||||
context.
|
||||
- On arm64, all VMAP's stacks need to have the same alignment to ensure
|
||||
that VMAP'd stack overflow detection works correctly. Arch specific
|
||||
vmap stack allocator takes care of this detail.
|
||||
- This does not address interrupt stacks - according to the original patch
|
||||
|
||||
Thread stack allocation is initiated from clone(), fork(), vfork(),
|
||||
kernel_thread() via kernel_clone(). Leaving a few hints for searching
|
||||
the code base to understand when and how thread stack is allocated.
|
||||
|
||||
Bulk of the code is in:
|
||||
`kernel/fork.c <https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/kernel/fork.c>`.
|
||||
|
||||
stack_vm_area pointer in task_struct keeps track of the virtually allocated
|
||||
stack and a non-null stack_vm_area pointer serves as a indication that the
|
||||
virtually mapped kernel stacks are enabled.
|
||||
|
||||
::
|
||||
|
||||
struct vm_struct *stack_vm_area;
|
||||
|
||||
Stack overflow handling
|
||||
-----------------------
|
||||
|
||||
Leading and trailing guard pages help detect stack overflows. When stack
|
||||
overflows into the guard pages, handlers have to be careful not overflow
|
||||
the stack again. When handlers are called, it is likely that very little
|
||||
stack space is left.
|
||||
|
||||
On x86, this is done by handling the page fault indicating the kernel
|
||||
stack overflow on the double-fault stack.
|
||||
|
||||
Testing VMAP allocation with guard pages
|
||||
----------------------------------------
|
||||
|
||||
How do we ensure that VMAP_STACK is actually allocating with a leading
|
||||
and trailing guard page? The following lkdtm tests can help detect any
|
||||
regressions.
|
||||
|
||||
::
|
||||
|
||||
void lkdtm_STACK_GUARD_PAGE_LEADING()
|
||||
void lkdtm_STACK_GUARD_PAGE_TRAILING()
|
||||
|
||||
Conclusions
|
||||
-----------
|
||||
|
||||
- A percpu cache of vmalloced stacks appears to be a bit faster than a
|
||||
high-order stack allocation, at least when the cache hits.
|
||||
- THREAD_INFO_IN_TASK gets rid of arch-specific thread_info entirely and
|
||||
simply embed the thread_info (containing only flags) and 'int cpu' into
|
||||
task_struct.
|
||||
- The thread stack can be free'ed as soon as the task is dead (without
|
||||
waiting for RCU) and then, if vmapped stacks are in use, cache the
|
||||
entire stack for reuse on the same cpu.
|
||||
@@ -14541,6 +14541,15 @@ F: include/net/page_pool.h
|
||||
F: include/trace/events/page_pool.h
|
||||
F: net/core/page_pool.c
|
||||
|
||||
PAGE TABLE CHECK
|
||||
M: Pasha Tatashin <pasha.tatashin@soleen.com>
|
||||
M: Andrew Morton <akpm@linux-foundation.org>
|
||||
L: linux-mm@kvack.org
|
||||
S: Maintained
|
||||
F: Documentation/vm/page_table_check.rst
|
||||
F: include/linux/page_table_check.h
|
||||
F: mm/page_table_check.c
|
||||
|
||||
PANASONIC LAPTOP ACPI EXTRAS DRIVER
|
||||
M: Kenneth Chan <kenneth.t.chan@gmail.com>
|
||||
L: platform-driver-x86@vger.kernel.org
|
||||
|
||||
@@ -1297,6 +1297,9 @@ config HAVE_ARCH_PFN_VALID
|
||||
config ARCH_SUPPORTS_DEBUG_PAGEALLOC
|
||||
bool
|
||||
|
||||
config ARCH_SUPPORTS_PAGE_TABLE_CHECK
|
||||
bool
|
||||
|
||||
config ARCH_SPLIT_ARG64
|
||||
bool
|
||||
help
|
||||
|
||||
@@ -489,3 +489,4 @@
|
||||
# 557 reserved for memfd_secret
|
||||
558 common process_mrelease sys_process_mrelease
|
||||
559 common futex_waitv sys_futex_waitv
|
||||
560 common set_mempolicy_home_node sys_ni_syscall
|
||||
|
||||
@@ -165,17 +165,15 @@ retry:
|
||||
BUG();
|
||||
}
|
||||
|
||||
if (flags & FAULT_FLAG_ALLOW_RETRY) {
|
||||
if (fault & VM_FAULT_RETRY) {
|
||||
flags |= FAULT_FLAG_TRIED;
|
||||
if (fault & VM_FAULT_RETRY) {
|
||||
flags |= FAULT_FLAG_TRIED;
|
||||
|
||||
/* No need to mmap_read_unlock(mm) as we would
|
||||
* have already released it in __lock_page_or_retry
|
||||
* in mm/filemap.c.
|
||||
*/
|
||||
/* No need to mmap_read_unlock(mm) as we would
|
||||
* have already released it in __lock_page_or_retry
|
||||
* in mm/filemap.c.
|
||||
*/
|
||||
|
||||
goto retry;
|
||||
}
|
||||
goto retry;
|
||||
}
|
||||
|
||||
mmap_read_unlock(mm);
|
||||
|
||||
+1
-2
@@ -149,8 +149,7 @@ retry:
|
||||
/*
|
||||
* Fault retry nuances, mmap_lock already relinquished by core mm
|
||||
*/
|
||||
if (unlikely((fault & VM_FAULT_RETRY) &&
|
||||
(flags & FAULT_FLAG_ALLOW_RETRY))) {
|
||||
if (unlikely(fault & VM_FAULT_RETRY)) {
|
||||
flags |= FAULT_FLAG_TRIED;
|
||||
goto retry;
|
||||
}
|
||||
|
||||
+1
-1
@@ -322,7 +322,7 @@ retry:
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(fault & VM_FAULT_ERROR) && flags & FAULT_FLAG_ALLOW_RETRY) {
|
||||
if (!(fault & VM_FAULT_ERROR)) {
|
||||
if (fault & VM_FAULT_RETRY) {
|
||||
flags |= FAULT_FLAG_TRIED;
|
||||
goto retry;
|
||||
|
||||
@@ -463,3 +463,4 @@
|
||||
# 447 reserved for memfd_secret
|
||||
448 common process_mrelease sys_process_mrelease
|
||||
449 common futex_waitv sys_futex_waitv
|
||||
450 common set_mempolicy_home_node sys_set_mempolicy_home_node
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
#define __ARM_NR_compat_set_tls (__ARM_NR_COMPAT_BASE + 5)
|
||||
#define __ARM_NR_COMPAT_END (__ARM_NR_COMPAT_BASE + 0x800)
|
||||
|
||||
#define __NR_compat_syscalls 450
|
||||
#define __NR_compat_syscalls 451
|
||||
#endif
|
||||
|
||||
#define __ARCH_WANT_SYS_CLONE
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user