Merge branch 'akpm' (patches from Andrew)
Merge more updates from Andrew Morton: "More mm/ work, plenty more to come Subsystems affected by this patch series: slub, memcg, gup, kasan, pagealloc, hugetlb, vmscan, tools, mempolicy, memblock, hugetlbfs, thp, mmap, kconfig" * akpm: (131 commits) arm64: mm: use ARCH_HAS_DEBUG_WX instead of arch defined x86: mm: use ARCH_HAS_DEBUG_WX instead of arch defined riscv: support DEBUG_WX mm: add DEBUG_WX support drivers/base/memory.c: cache memory blocks in xarray to accelerate lookup mm/thp: rename pmd_mknotpresent() as pmd_mkinvalid() powerpc/mm: drop platform defined pmd_mknotpresent() mm: thp: don't need to drain lru cache when splitting and mlocking THP hugetlbfs: get unmapped area below TASK_UNMAPPED_BASE for hugetlbfs sparc32: register memory occupied by kernel as memblock.memory include/linux/memblock.h: fix minor typo and unclear comment mm, mempolicy: fix up gup usage in lookup_node tools/vm/page_owner_sort.c: filter out unneeded line mm: swap: memcg: fix memcg stats for huge pages mm: swap: fix vmstats for huge pages mm: vmscan: limit the range of LRU type balancing mm: vmscan: reclaim writepage is IO cost mm: vmscan: determine anon/file pressure balance at the reclaim root mm: balance LRU lists based on relative thrashing mm: only count actual rotations as LRU reclaim cost ...
This commit is contained in:
@@ -199,11 +199,11 @@ An RSS page is unaccounted when it's fully unmapped. A PageCache page is
|
|||||||
unaccounted when it's removed from radix-tree. Even if RSS pages are fully
|
unaccounted when it's removed from radix-tree. Even if RSS pages are fully
|
||||||
unmapped (by kswapd), they may exist as SwapCache in the system until they
|
unmapped (by kswapd), they may exist as SwapCache in the system until they
|
||||||
are really freed. Such SwapCaches are also accounted.
|
are really freed. Such SwapCaches are also accounted.
|
||||||
A swapped-in page is not accounted until it's mapped.
|
A swapped-in page is accounted after adding into swapcache.
|
||||||
|
|
||||||
Note: The kernel does swapin-readahead and reads multiple swaps at once.
|
Note: The kernel does swapin-readahead and reads multiple swaps at once.
|
||||||
This means swapped-in pages may contain pages for other tasks than a task
|
Since page's memcg recorded into swap whatever memsw enabled, the page will
|
||||||
causing page fault. So, we avoid accounting at swap-in I/O.
|
be accounted after swapin.
|
||||||
|
|
||||||
At page migration, accounting information is kept.
|
At page migration, accounting information is kept.
|
||||||
|
|
||||||
@@ -222,18 +222,13 @@ the cgroup that brought it in -- this will happen on memory pressure).
|
|||||||
But see section 8.2: when moving a task to another cgroup, its pages may
|
But see section 8.2: when moving a task to another cgroup, its pages may
|
||||||
be recharged to the new cgroup, if move_charge_at_immigrate has been chosen.
|
be recharged to the new cgroup, if move_charge_at_immigrate has been chosen.
|
||||||
|
|
||||||
Exception: If CONFIG_MEMCG_SWAP is not used.
|
2.4 Swap Extension
|
||||||
When you do swapoff and make swapped-out pages of shmem(tmpfs) to
|
|
||||||
be backed into memory in force, charges for pages are accounted against the
|
|
||||||
caller of swapoff rather than the users of shmem.
|
|
||||||
|
|
||||||
2.4 Swap Extension (CONFIG_MEMCG_SWAP)
|
|
||||||
--------------------------------------
|
--------------------------------------
|
||||||
|
|
||||||
Swap Extension allows you to record charge for swap. A swapped-in page is
|
Swap usage is always recorded for each of cgroup. Swap Extension allows you to
|
||||||
charged back to original page allocator if possible.
|
read and limit it.
|
||||||
|
|
||||||
When swap is accounted, following files are added.
|
When CONFIG_SWAP is enabled, following files are added.
|
||||||
|
|
||||||
- memory.memsw.usage_in_bytes.
|
- memory.memsw.usage_in_bytes.
|
||||||
- memory.memsw.limit_in_bytes.
|
- memory.memsw.limit_in_bytes.
|
||||||
|
@@ -834,12 +834,15 @@
|
|||||||
See also Documentation/networking/decnet.rst.
|
See also Documentation/networking/decnet.rst.
|
||||||
|
|
||||||
default_hugepagesz=
|
default_hugepagesz=
|
||||||
[same as hugepagesz=] The size of the default
|
[HW] The size of the default HugeTLB page. This is
|
||||||
HugeTLB page size. This is the size represented by
|
the size represented by the legacy /proc/ hugepages
|
||||||
the legacy /proc/ hugepages APIs, used for SHM, and
|
APIs. In addition, this is the default hugetlb size
|
||||||
default size when mounting hugetlbfs filesystems.
|
used for shmget(), mmap() and mounting hugetlbfs
|
||||||
Defaults to the default architecture's huge page size
|
filesystems. If not specified, defaults to the
|
||||||
if not specified.
|
architecture's default huge page size. Huge page
|
||||||
|
sizes are architecture dependent. See also
|
||||||
|
Documentation/admin-guide/mm/hugetlbpage.rst.
|
||||||
|
Format: size[KMG]
|
||||||
|
|
||||||
deferred_probe_timeout=
|
deferred_probe_timeout=
|
||||||
[KNL] Debugging option to set a timeout in seconds for
|
[KNL] Debugging option to set a timeout in seconds for
|
||||||
@@ -1484,13 +1487,24 @@
|
|||||||
hugepages using the cma allocator. If enabled, the
|
hugepages using the cma allocator. If enabled, the
|
||||||
boot-time allocation of gigantic hugepages is skipped.
|
boot-time allocation of gigantic hugepages is skipped.
|
||||||
|
|
||||||
hugepages= [HW,X86-32,IA-64] HugeTLB pages to allocate at boot.
|
hugepages= [HW] Number of HugeTLB pages to allocate at boot.
|
||||||
hugepagesz= [HW,IA-64,PPC,X86-64] The size of the HugeTLB pages.
|
If this follows hugepagesz (below), it specifies
|
||||||
On x86-64 and powerpc, this option can be specified
|
the number of pages of hugepagesz to be allocated.
|
||||||
multiple times interleaved with hugepages= to reserve
|
If this is the first HugeTLB parameter on the command
|
||||||
huge pages of different sizes. Valid pages sizes on
|
line, it specifies the number of pages to allocate for
|
||||||
x86-64 are 2M (when the CPU supports "pse") and 1G
|
the default huge page size. See also
|
||||||
(when the CPU supports the "pdpe1gb" cpuinfo flag).
|
Documentation/admin-guide/mm/hugetlbpage.rst.
|
||||||
|
Format: <integer>
|
||||||
|
|
||||||
|
hugepagesz=
|
||||||
|
[HW] The size of the HugeTLB pages. This is used in
|
||||||
|
conjunction with hugepages (above) to allocate huge
|
||||||
|
pages of a specific size at boot. The pair
|
||||||
|
hugepagesz=X hugepages=Y can be specified once for
|
||||||
|
each supported huge page size. Huge page sizes are
|
||||||
|
architecture dependent. See also
|
||||||
|
Documentation/admin-guide/mm/hugetlbpage.rst.
|
||||||
|
Format: size[KMG]
|
||||||
|
|
||||||
hung_task_panic=
|
hung_task_panic=
|
||||||
[KNL] Should the hung task detector generate panics.
|
[KNL] Should the hung task detector generate panics.
|
||||||
|
@@ -100,6 +100,41 @@ with a huge page size selection parameter "hugepagesz=<size>". <size> must
|
|||||||
be specified in bytes with optional scale suffix [kKmMgG]. The default huge
|
be specified in bytes with optional scale suffix [kKmMgG]. The default huge
|
||||||
page size may be selected with the "default_hugepagesz=<size>" boot parameter.
|
page size may be selected with the "default_hugepagesz=<size>" boot parameter.
|
||||||
|
|
||||||
|
Hugetlb boot command line parameter semantics
|
||||||
|
hugepagesz - Specify a huge page size. Used in conjunction with hugepages
|
||||||
|
parameter to preallocate a number of huge pages of the specified
|
||||||
|
size. Hence, hugepagesz and hugepages are typically specified in
|
||||||
|
pairs such as:
|
||||||
|
hugepagesz=2M hugepages=512
|
||||||
|
hugepagesz can only be specified once on the command line for a
|
||||||
|
specific huge page size. Valid huge page sizes are architecture
|
||||||
|
dependent.
|
||||||
|
hugepages - Specify the number of huge pages to preallocate. This typically
|
||||||
|
follows a valid hugepagesz or default_hugepagesz parameter. However,
|
||||||
|
if hugepages is the first or only hugetlb command line parameter it
|
||||||
|
implicitly specifies the number of huge pages of default size to
|
||||||
|
allocate. If the number of huge pages of default size is implicitly
|
||||||
|
specified, it can not be overwritten by a hugepagesz,hugepages
|
||||||
|
parameter pair for the default size.
|
||||||
|
For example, on an architecture with 2M default huge page size:
|
||||||
|
hugepages=256 hugepagesz=2M hugepages=512
|
||||||
|
will result in 256 2M huge pages being allocated and a warning message
|
||||||
|
indicating that the hugepages=512 parameter is ignored. If a hugepages
|
||||||
|
parameter is preceded by an invalid hugepagesz parameter, it will
|
||||||
|
be ignored.
|
||||||
|
default_hugepagesz - Specify the default huge page size. This parameter can
|
||||||
|
only be specified once on the command line. default_hugepagesz can
|
||||||
|
optionally be followed by the hugepages parameter to preallocate a
|
||||||
|
specific number of huge pages of default size. The number of default
|
||||||
|
sized huge pages to preallocate can also be implicitly specified as
|
||||||
|
mentioned in the hugepages section above. Therefore, on an
|
||||||
|
architecture with 2M default huge page size:
|
||||||
|
hugepages=256
|
||||||
|
default_hugepagesz=2M hugepages=256
|
||||||
|
hugepages=256 default_hugepagesz=2M
|
||||||
|
will all result in 256 2M huge pages being allocated. Valid default
|
||||||
|
huge page size is architecture dependent.
|
||||||
|
|
||||||
When multiple huge page sizes are supported, ``/proc/sys/vm/nr_hugepages``
|
When multiple huge page sizes are supported, ``/proc/sys/vm/nr_hugepages``
|
||||||
indicates the current number of pre-allocated huge pages of the default size.
|
indicates the current number of pre-allocated huge pages of the default size.
|
||||||
Thus, one can use the following command to dynamically allocate/deallocate
|
Thus, one can use the following command to dynamically allocate/deallocate
|
||||||
|
@@ -220,6 +220,13 @@ memory. A lower value can prevent THPs from being
|
|||||||
collapsed, resulting fewer pages being collapsed into
|
collapsed, resulting fewer pages being collapsed into
|
||||||
THPs, and lower memory access performance.
|
THPs, and lower memory access performance.
|
||||||
|
|
||||||
|
``max_ptes_shared`` specifies how many pages can be shared across multiple
|
||||||
|
processes. Exceeding the number would block the collapse::
|
||||||
|
|
||||||
|
/sys/kernel/mm/transparent_hugepage/khugepaged/max_ptes_shared
|
||||||
|
|
||||||
|
A higher value may increase memory footprint for some workloads.
|
||||||
|
|
||||||
Boot parameter
|
Boot parameter
|
||||||
==============
|
==============
|
||||||
|
|
||||||
|
@@ -831,14 +831,27 @@ tooling to work, you can do::
|
|||||||
swappiness
|
swappiness
|
||||||
==========
|
==========
|
||||||
|
|
||||||
This control is used to define how aggressive the kernel will swap
|
This control is used to define the rough relative IO cost of swapping
|
||||||
memory pages. Higher values will increase aggressiveness, lower values
|
and filesystem paging, as a value between 0 and 200. At 100, the VM
|
||||||
decrease the amount of swap. A value of 0 instructs the kernel not to
|
assumes equal IO cost and will thus apply memory pressure to the page
|
||||||
initiate swap until the amount of free and file-backed pages is less
|
cache and swap-backed pages equally; lower values signify more
|
||||||
than the high water mark in a zone.
|
expensive swap IO, higher values indicates cheaper.
|
||||||
|
|
||||||
|
Keep in mind that filesystem IO patterns under memory pressure tend to
|
||||||
|
be more efficient than swap's random IO. An optimal value will require
|
||||||
|
experimentation and will also be workload-dependent.
|
||||||
|
|
||||||
The default value is 60.
|
The default value is 60.
|
||||||
|
|
||||||
|
For in-memory swap, like zram or zswap, as well as hybrid setups that
|
||||||
|
have swap on faster devices than the filesystem, values beyond 100 can
|
||||||
|
be considered. For example, if the random IO against the swap device
|
||||||
|
is on average 2x faster than IO from the filesystem, swappiness should
|
||||||
|
be 133 (x + 2x = 200, 2x = 133.33).
|
||||||
|
|
||||||
|
At 0, the kernel will not initiate swap until the amount of free and
|
||||||
|
file-backed pages is less than the high watermark in a zone.
|
||||||
|
|
||||||
|
|
||||||
unprivileged_userfaultfd
|
unprivileged_userfaultfd
|
||||||
========================
|
========================
|
||||||
|
@@ -4,23 +4,26 @@
|
|||||||
The padata parallel execution mechanism
|
The padata parallel execution mechanism
|
||||||
=======================================
|
=======================================
|
||||||
|
|
||||||
:Date: December 2019
|
:Date: May 2020
|
||||||
|
|
||||||
Padata is a mechanism by which the kernel can farm jobs out to be done in
|
Padata is a mechanism by which the kernel can farm jobs out to be done in
|
||||||
parallel on multiple CPUs while retaining their ordering. It was developed for
|
parallel on multiple CPUs while optionally retaining their ordering.
|
||||||
use with the IPsec code, which needs to be able to perform encryption and
|
|
||||||
decryption on large numbers of packets without reordering those packets. The
|
|
||||||
crypto developers made a point of writing padata in a sufficiently general
|
|
||||||
fashion that it could be put to other uses as well.
|
|
||||||
|
|
||||||
Usage
|
It was originally developed for IPsec, which needs to perform encryption and
|
||||||
=====
|
decryption on large numbers of packets without reordering those packets. This
|
||||||
|
is currently the sole consumer of padata's serialized job support.
|
||||||
|
|
||||||
|
Padata also supports multithreaded jobs, splitting up the job evenly while load
|
||||||
|
balancing and coordinating between threads.
|
||||||
|
|
||||||
|
Running Serialized Jobs
|
||||||
|
=======================
|
||||||
|
|
||||||
Initializing
|
Initializing
|
||||||
------------
|
------------
|
||||||
|
|
||||||
The first step in using padata is to set up a padata_instance structure for
|
The first step in using padata to run serialized jobs is to set up a
|
||||||
overall control of how jobs are to be run::
|
padata_instance structure for overall control of how jobs are to be run::
|
||||||
|
|
||||||
#include <linux/padata.h>
|
#include <linux/padata.h>
|
||||||
|
|
||||||
@@ -162,6 +165,24 @@ functions that correspond to the allocation in reverse::
|
|||||||
It is the user's responsibility to ensure all outstanding jobs are complete
|
It is the user's responsibility to ensure all outstanding jobs are complete
|
||||||
before any of the above are called.
|
before any of the above are called.
|
||||||
|
|
||||||
|
Running Multithreaded Jobs
|
||||||
|
==========================
|
||||||
|
|
||||||
|
A multithreaded job has a main thread and zero or more helper threads, with the
|
||||||
|
main thread participating in the job and then waiting until all helpers have
|
||||||
|
finished. padata splits the job into units called chunks, where a chunk is a
|
||||||
|
piece of the job that one thread completes in one call to the thread function.
|
||||||
|
|
||||||
|
A user has to do three things to run a multithreaded job. First, describe the
|
||||||
|
job by defining a padata_mt_job structure, which is explained in the Interface
|
||||||
|
section. This includes a pointer to the thread function, which padata will
|
||||||
|
call each time it assigns a job chunk to a thread. Then, define the thread
|
||||||
|
function, which accepts three arguments, ``start``, ``end``, and ``arg``, where
|
||||||
|
the first two delimit the range that the thread operates on and the last is a
|
||||||
|
pointer to the job's shared state, if any. Prepare the shared state, which is
|
||||||
|
typically allocated on the main thread's stack. Last, call
|
||||||
|
padata_do_multithreaded(), which will return once the job is finished.
|
||||||
|
|
||||||
Interface
|
Interface
|
||||||
=========
|
=========
|
||||||
|
|
||||||
|
@@ -1,34 +0,0 @@
|
|||||||
#
|
|
||||||
# Feature name: numa-memblock
|
|
||||||
# Kconfig: HAVE_MEMBLOCK_NODE_MAP
|
|
||||||
# description: arch supports NUMA aware memblocks
|
|
||||||
#
|
|
||||||
-----------------------
|
|
||||||
| arch |status|
|
|
||||||
-----------------------
|
|
||||||
| alpha: | TODO |
|
|
||||||
| arc: | .. |
|
|
||||||
| arm: | .. |
|
|
||||||
| arm64: | ok |
|
|
||||||
| c6x: | .. |
|
|
||||||
| csky: | .. |
|
|
||||||
| h8300: | .. |
|
|
||||||
| hexagon: | .. |
|
|
||||||
| ia64: | ok |
|
|
||||||
| m68k: | .. |
|
|
||||||
| microblaze: | ok |
|
|
||||||
| mips: | ok |
|
|
||||||
| nds32: | TODO |
|
|
||||||
| nios2: | .. |
|
|
||||||
| openrisc: | .. |
|
|
||||||
| parisc: | .. |
|
|
||||||
| powerpc: | ok |
|
|
||||||
| riscv: | ok |
|
|
||||||
| s390: | ok |
|
|
||||||
| sh: | ok |
|
|
||||||
| sparc: | ok |
|
|
||||||
| um: | .. |
|
|
||||||
| unicore32: | .. |
|
|
||||||
| x86: | ok |
|
|
||||||
| xtensa: | .. |
|
|
||||||
-----------------------
|
|
@@ -46,11 +46,10 @@ maps the entire physical memory. For most architectures, the holes
|
|||||||
have entries in the `mem_map` array. The `struct page` objects
|
have entries in the `mem_map` array. The `struct page` objects
|
||||||
corresponding to the holes are never fully initialized.
|
corresponding to the holes are never fully initialized.
|
||||||
|
|
||||||
To allocate the `mem_map` array, architecture specific setup code
|
To allocate the `mem_map` array, architecture specific setup code should
|
||||||
should call :c:func:`free_area_init_node` function or its convenience
|
call :c:func:`free_area_init` function. Yet, the mappings array is not
|
||||||
wrapper :c:func:`free_area_init`. Yet, the mappings array is not
|
usable until the call to :c:func:`memblock_free_all` that hands all the
|
||||||
usable until the call to :c:func:`memblock_free_all` that hands all
|
memory to the page allocator.
|
||||||
the memory to the page allocator.
|
|
||||||
|
|
||||||
If an architecture enables `CONFIG_ARCH_HAS_HOLES_MEMORYMODEL` option,
|
If an architecture enables `CONFIG_ARCH_HAS_HOLES_MEMORYMODEL` option,
|
||||||
it may free parts of the `mem_map` array that do not cover the
|
it may free parts of the `mem_map` array that do not cover the
|
||||||
|
@@ -83,8 +83,7 @@ Usage
|
|||||||
4) Analyze information from page owner::
|
4) Analyze information from page owner::
|
||||||
|
|
||||||
cat /sys/kernel/debug/page_owner > page_owner_full.txt
|
cat /sys/kernel/debug/page_owner > page_owner_full.txt
|
||||||
grep -v ^PFN page_owner_full.txt > page_owner.txt
|
./page_owner_sort page_owner_full.txt sorted_page_owner.txt
|
||||||
./page_owner_sort page_owner.txt sorted_page_owner.txt
|
|
||||||
|
|
||||||
See the result about who allocated each page
|
See the result about who allocated each page
|
||||||
in the ``sorted_page_owner.txt``.
|
in the ``sorted_page_owner.txt``.
|
||||||
|
@@ -243,21 +243,17 @@ callback_init(void * kernel_end)
|
|||||||
*/
|
*/
|
||||||
void __init paging_init(void)
|
void __init paging_init(void)
|
||||||
{
|
{
|
||||||
unsigned long zones_size[MAX_NR_ZONES] = {0, };
|
unsigned long max_zone_pfn[MAX_NR_ZONES] = {0, };
|
||||||
unsigned long dma_pfn, high_pfn;
|
unsigned long dma_pfn;
|
||||||
|
|
||||||
dma_pfn = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
|
dma_pfn = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
|
||||||
high_pfn = max_pfn = max_low_pfn;
|
max_pfn = max_low_pfn;
|
||||||
|
|
||||||
if (dma_pfn >= high_pfn)
|
max_zone_pfn[ZONE_DMA] = dma_pfn;
|
||||||
zones_size[ZONE_DMA] = high_pfn;
|
max_zone_pfn[ZONE_NORMAL] = max_pfn;
|
||||||
else {
|
|
||||||
zones_size[ZONE_DMA] = dma_pfn;
|
|
||||||
zones_size[ZONE_NORMAL] = high_pfn - dma_pfn;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Initialize mem_map[]. */
|
/* Initialize mem_map[]. */
|
||||||
free_area_init(zones_size);
|
free_area_init(max_zone_pfn);
|
||||||
|
|
||||||
/* Initialize the kernel's ZERO_PGE. */
|
/* Initialize the kernel's ZERO_PGE. */
|
||||||
memset((void *)ZERO_PGE, 0, PAGE_SIZE);
|
memset((void *)ZERO_PGE, 0, PAGE_SIZE);
|
||||||
|
@@ -144,8 +144,8 @@ setup_memory_node(int nid, void *kernel_end)
|
|||||||
if (!nid && (node_max_pfn < end_kernel_pfn || node_min_pfn > start_kernel_pfn))
|
if (!nid && (node_max_pfn < end_kernel_pfn || node_min_pfn > start_kernel_pfn))
|
||||||
panic("kernel loaded out of ram");
|
panic("kernel loaded out of ram");
|
||||||
|
|
||||||
memblock_add(PFN_PHYS(node_min_pfn),
|
memblock_add_node(PFN_PHYS(node_min_pfn),
|
||||||
(node_max_pfn - node_min_pfn) << PAGE_SHIFT);
|
(node_max_pfn - node_min_pfn) << PAGE_SHIFT, nid);
|
||||||
|
|
||||||
/* Zone start phys-addr must be 2^(MAX_ORDER-1) aligned.
|
/* Zone start phys-addr must be 2^(MAX_ORDER-1) aligned.
|
||||||
Note that we round this down, not up - node memory
|
Note that we round this down, not up - node memory
|
||||||
@@ -202,8 +202,7 @@ setup_memory(void *kernel_end)
|
|||||||
|
|
||||||
void __init paging_init(void)
|
void __init paging_init(void)
|
||||||
{
|
{
|
||||||
unsigned int nid;
|
unsigned long max_zone_pfn[MAX_NR_ZONES] = {0, };
|
||||||
unsigned long zones_size[MAX_NR_ZONES] = {0, };
|
|
||||||
unsigned long dma_local_pfn;
|
unsigned long dma_local_pfn;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -215,19 +214,10 @@ void __init paging_init(void)
|
|||||||
*/
|
*/
|
||||||
dma_local_pfn = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
|
dma_local_pfn = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
|
||||||
|
|
||||||
for_each_online_node(nid) {
|
max_zone_pfn[ZONE_DMA] = dma_local_pfn;
|
||||||
unsigned long start_pfn = NODE_DATA(nid)->node_start_pfn;
|
max_zone_pfn[ZONE_NORMAL] = max_pfn;
|
||||||
unsigned long end_pfn = start_pfn + NODE_DATA(nid)->node_present_pages;
|
|
||||||
|
|
||||||
if (dma_local_pfn >= end_pfn - start_pfn)
|
free_area_init(max_zone_pfn);
|
||||||
zones_size[ZONE_DMA] = end_pfn - start_pfn;
|
|
||||||
else {
|
|
||||||
zones_size[ZONE_DMA] = dma_local_pfn;
|
|
||||||
zones_size[ZONE_NORMAL] = (end_pfn - start_pfn) - dma_local_pfn;
|
|
||||||
}
|
|
||||||
node_set_state(nid, N_NORMAL_MEMORY);
|
|
||||||
free_area_init_node(nid, zones_size, start_pfn, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Initialize the kernel's ZERO_PGE. */
|
/* Initialize the kernel's ZERO_PGE. */
|
||||||
memset((void *)ZERO_PGE, 0, PAGE_SIZE);
|
memset((void *)ZERO_PGE, 0, PAGE_SIZE);
|
||||||
|
@@ -26,7 +26,7 @@ static inline pmd_t pte_pmd(pte_t pte)
|
|||||||
#define pmd_mkold(pmd) pte_pmd(pte_mkold(pmd_pte(pmd)))
|
#define pmd_mkold(pmd) pte_pmd(pte_mkold(pmd_pte(pmd)))
|
||||||
#define pmd_mkyoung(pmd) pte_pmd(pte_mkyoung(pmd_pte(pmd)))
|
#define pmd_mkyoung(pmd) pte_pmd(pte_mkyoung(pmd_pte(pmd)))
|
||||||
#define pmd_mkhuge(pmd) pte_pmd(pte_mkhuge(pmd_pte(pmd)))
|
#define pmd_mkhuge(pmd) pte_pmd(pte_mkhuge(pmd_pte(pmd)))
|
||||||
#define pmd_mknotpresent(pmd) pte_pmd(pte_mknotpresent(pmd_pte(pmd)))
|
#define pmd_mkinvalid(pmd) pte_pmd(pte_mknotpresent(pmd_pte(pmd)))
|
||||||
#define pmd_mkclean(pmd) pte_pmd(pte_mkclean(pmd_pte(pmd)))
|
#define pmd_mkclean(pmd) pte_pmd(pte_mkclean(pmd_pte(pmd)))
|
||||||
|
|
||||||
#define pmd_write(pmd) pte_write(pmd_pte(pmd))
|
#define pmd_write(pmd) pte_write(pmd_pte(pmd))
|
||||||
|
@@ -63,11 +63,13 @@ void __init early_init_dt_add_memory_arch(u64 base, u64 size)
|
|||||||
|
|
||||||
low_mem_sz = size;
|
low_mem_sz = size;
|
||||||
in_use = 1;
|
in_use = 1;
|
||||||
|
memblock_add_node(base, size, 0);
|
||||||
} else {
|
} else {
|
||||||
#ifdef CONFIG_HIGHMEM
|
#ifdef CONFIG_HIGHMEM
|
||||||
high_mem_start = base;
|
high_mem_start = base;
|
||||||
high_mem_sz = size;
|
high_mem_sz = size;
|
||||||
in_use = 1;
|
in_use = 1;
|
||||||
|
memblock_add_node(base, size, 1);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,6 +77,11 @@ void __init early_init_dt_add_memory_arch(u64 base, u64 size)
|
|||||||
base, TO_MB(size), !in_use ? "Not used":"");
|
base, TO_MB(size), !in_use ? "Not used":"");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool arch_has_descending_max_zone_pfns(void)
|
||||||
|
{
|
||||||
|
return !IS_ENABLED(CONFIG_ARC_HAS_PAE40);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* First memory setup routine called from setup_arch()
|
* First memory setup routine called from setup_arch()
|
||||||
* 1. setup swapper's mm @init_mm
|
* 1. setup swapper's mm @init_mm
|
||||||
@@ -83,8 +90,7 @@ void __init early_init_dt_add_memory_arch(u64 base, u64 size)
|
|||||||
*/
|
*/
|
||||||
void __init setup_arch_memory(void)
|
void __init setup_arch_memory(void)
|
||||||
{
|
{
|
||||||
unsigned long zones_size[MAX_NR_ZONES];
|
unsigned long max_zone_pfn[MAX_NR_ZONES] = { 0 };
|
||||||
unsigned long zones_holes[MAX_NR_ZONES];
|
|
||||||
|
|
||||||
init_mm.start_code = (unsigned long)_text;
|
init_mm.start_code = (unsigned long)_text;
|
||||||
init_mm.end_code = (unsigned long)_etext;
|
init_mm.end_code = (unsigned long)_etext;
|
||||||
@@ -115,7 +121,6 @@ void __init setup_arch_memory(void)
|
|||||||
* the crash
|
* the crash
|
||||||
*/
|
*/
|
||||||
|
|
||||||
memblock_add_node(low_mem_start, low_mem_sz, 0);
|
|
||||||
memblock_reserve(CONFIG_LINUX_LINK_BASE,
|
memblock_reserve(CONFIG_LINUX_LINK_BASE,
|
||||||
__pa(_end) - CONFIG_LINUX_LINK_BASE);
|
__pa(_end) - CONFIG_LINUX_LINK_BASE);
|
||||||
|
|
||||||
@@ -133,22 +138,7 @@ void __init setup_arch_memory(void)
|
|||||||
memblock_dump_all();
|
memblock_dump_all();
|
||||||
|
|
||||||
/*----------------- node/zones setup --------------------------*/
|
/*----------------- node/zones setup --------------------------*/
|
||||||
memset(zones_size, 0, sizeof(zones_size));
|
max_zone_pfn[ZONE_NORMAL] = max_low_pfn;
|
||||||
memset(zones_holes, 0, sizeof(zones_holes));
|
|
||||||
|
|
||||||
zones_size[ZONE_NORMAL] = max_low_pfn - min_low_pfn;
|
|
||||||
zones_holes[ZONE_NORMAL] = 0;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We can't use the helper free_area_init(zones[]) because it uses
|
|
||||||
* PAGE_OFFSET to compute the @min_low_pfn which would be wrong
|
|
||||||
* when our kernel doesn't start at PAGE_OFFSET, i.e.
|
|
||||||
* PAGE_OFFSET != CONFIG_LINUX_RAM_BASE
|
|
||||||
*/
|
|
||||||
free_area_init_node(0, /* node-id */
|
|
||||||
zones_size, /* num pages per zone */
|
|
||||||
min_low_pfn, /* first pfn of node */
|
|
||||||
zones_holes); /* holes */
|
|
||||||
|
|
||||||
#ifdef CONFIG_HIGHMEM
|
#ifdef CONFIG_HIGHMEM
|
||||||
/*
|
/*
|
||||||
@@ -168,20 +158,13 @@ void __init setup_arch_memory(void)
|
|||||||
min_high_pfn = PFN_DOWN(high_mem_start);
|
min_high_pfn = PFN_DOWN(high_mem_start);
|
||||||
max_high_pfn = PFN_DOWN(high_mem_start + high_mem_sz);
|
max_high_pfn = PFN_DOWN(high_mem_start + high_mem_sz);
|
||||||
|
|
||||||
zones_size[ZONE_NORMAL] = 0;
|
max_zone_pfn[ZONE_HIGHMEM] = max_high_pfn;
|
||||||
zones_holes[ZONE_NORMAL] = 0;
|
|
||||||
|
|
||||||
zones_size[ZONE_HIGHMEM] = max_high_pfn - min_high_pfn;
|
|
||||||
zones_holes[ZONE_HIGHMEM] = 0;
|
|
||||||
|
|
||||||
free_area_init_node(1, /* node-id */
|
|
||||||
zones_size, /* num pages per zone */
|
|
||||||
min_high_pfn, /* first pfn of node */
|
|
||||||
zones_holes); /* holes */
|
|
||||||
|
|
||||||
high_memory = (void *)(min_high_pfn << PAGE_SHIFT);
|
high_memory = (void *)(min_high_pfn << PAGE_SHIFT);
|
||||||
kmap_init();
|
kmap_init();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
free_area_init(max_zone_pfn);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -14,15 +14,10 @@
|
|||||||
#include <asm/hugetlb-3level.h>
|
#include <asm/hugetlb-3level.h>
|
||||||
#include <asm-generic/hugetlb.h>
|
#include <asm-generic/hugetlb.h>
|
||||||
|
|
||||||
static inline int is_hugepage_only_range(struct mm_struct *mm,
|
|
||||||
unsigned long addr, unsigned long len)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void arch_clear_hugepage_flags(struct page *page)
|
static inline void arch_clear_hugepage_flags(struct page *page)
|
||||||
{
|
{
|
||||||
clear_bit(PG_dcache_clean, &page->flags);
|
clear_bit(PG_dcache_clean, &page->flags);
|
||||||
}
|
}
|
||||||
|
#define arch_clear_hugepage_flags arch_clear_hugepage_flags
|
||||||
|
|
||||||
#endif /* _ASM_ARM_HUGETLB_H */
|
#endif /* _ASM_ARM_HUGETLB_H */
|
||||||
|
@@ -221,7 +221,7 @@ PMD_BIT_FUNC(mkyoung, |= PMD_SECT_AF);
|
|||||||
#define pmdp_establish generic_pmdp_establish
|
#define pmdp_establish generic_pmdp_establish
|
||||||
|
|
||||||
/* represent a notpresent pmd by faulting entry, this is used by pmdp_invalidate */
|
/* represent a notpresent pmd by faulting entry, this is used by pmdp_invalidate */
|
||||||
static inline pmd_t pmd_mknotpresent(pmd_t pmd)
|
static inline pmd_t pmd_mkinvalid(pmd_t pmd)
|
||||||
{
|
{
|
||||||
return __pmd(pmd_val(pmd) & ~L_PMD_SECT_VALID);
|
return __pmd(pmd_val(pmd) & ~L_PMD_SECT_VALID);
|
||||||
}
|
}
|
||||||
|
@@ -92,18 +92,6 @@ EXPORT_SYMBOL(arm_dma_zone_size);
|
|||||||
*/
|
*/
|
||||||
phys_addr_t arm_dma_limit;
|
phys_addr_t arm_dma_limit;
|
||||||
unsigned long arm_dma_pfn_limit;
|
unsigned long arm_dma_pfn_limit;
|
||||||
|
|
||||||
static void __init arm_adjust_dma_zone(unsigned long *size, unsigned long *hole,
|
|
||||||
unsigned long dma_size)
|
|
||||||
{
|
|
||||||
if (size[0] <= dma_size)
|
|
||||||
return;
|
|
||||||
|
|
||||||
size[ZONE_NORMAL] = size[0] - dma_size;
|
|
||||||
size[ZONE_DMA] = dma_size;
|
|
||||||
hole[ZONE_NORMAL] = hole[0];
|
|
||||||
hole[ZONE_DMA] = 0;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void __init setup_dma_zone(const struct machine_desc *mdesc)
|
void __init setup_dma_zone(const struct machine_desc *mdesc)
|
||||||
@@ -121,56 +109,16 @@ void __init setup_dma_zone(const struct machine_desc *mdesc)
|
|||||||
static void __init zone_sizes_init(unsigned long min, unsigned long max_low,
|
static void __init zone_sizes_init(unsigned long min, unsigned long max_low,
|
||||||
unsigned long max_high)
|
unsigned long max_high)
|
||||||
{
|
{
|
||||||
unsigned long zone_size[MAX_NR_ZONES], zhole_size[MAX_NR_ZONES];
|
unsigned long max_zone_pfn[MAX_NR_ZONES] = { 0 };
|
||||||
struct memblock_region *reg;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* initialise the zones.
|
|
||||||
*/
|
|
||||||
memset(zone_size, 0, sizeof(zone_size));
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The memory size has already been determined. If we need
|
|
||||||
* to do anything fancy with the allocation of this memory
|
|
||||||
* to the zones, now is the time to do it.
|
|
||||||
*/
|
|
||||||
zone_size[0] = max_low - min;
|
|
||||||
#ifdef CONFIG_HIGHMEM
|
|
||||||
zone_size[ZONE_HIGHMEM] = max_high - max_low;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Calculate the size of the holes.
|
|
||||||
* holes = node_size - sum(bank_sizes)
|
|
||||||
*/
|
|
||||||
memcpy(zhole_size, zone_size, sizeof(zhole_size));
|
|
||||||
for_each_memblock(memory, reg) {
|
|
||||||
unsigned long start = memblock_region_memory_base_pfn(reg);
|
|
||||||
unsigned long end = memblock_region_memory_end_pfn(reg);
|
|
||||||
|
|
||||||
if (start < max_low) {
|
|
||||||
unsigned long low_end = min(end, max_low);
|
|
||||||
zhole_size[0] -= low_end - start;
|
|
||||||
}
|
|
||||||
#ifdef CONFIG_HIGHMEM
|
|
||||||
if (end > max_low) {
|
|
||||||
unsigned long high_start = max(start, max_low);
|
|
||||||
zhole_size[ZONE_HIGHMEM] -= end - high_start;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CONFIG_ZONE_DMA
|
#ifdef CONFIG_ZONE_DMA
|
||||||
/*
|
max_zone_pfn[ZONE_DMA] = min(arm_dma_pfn_limit, max_low);
|
||||||
* Adjust the sizes according to any special requirements for
|
|
||||||
* this machine type.
|
|
||||||
*/
|
|
||||||
if (arm_dma_zone_size)
|
|
||||||
arm_adjust_dma_zone(zone_size, zhole_size,
|
|
||||||
arm_dma_zone_size >> PAGE_SHIFT);
|
|
||||||
#endif
|
#endif
|
||||||
|
max_zone_pfn[ZONE_NORMAL] = max_low;
|
||||||
free_area_init_node(0, zone_size, min, zhole_size);
|
#ifdef CONFIG_HIGHMEM
|
||||||
|
max_zone_pfn[ZONE_HIGHMEM] = max_high;
|
||||||
|
#endif
|
||||||
|
free_area_init(max_zone_pfn);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_HAVE_ARCH_PFN_VALID
|
#ifdef CONFIG_HAVE_ARCH_PFN_VALID
|
||||||
@@ -306,7 +254,7 @@ void __init bootmem_init(void)
|
|||||||
sparse_init();
|
sparse_init();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now free the memory - free_area_init_node needs
|
* Now free the memory - free_area_init needs
|
||||||
* the sparse mem_map arrays initialized by sparse_init()
|
* the sparse mem_map arrays initialized by sparse_init()
|
||||||
* for memmap_init_zone(), otherwise all PFNs are invalid.
|
* for memmap_init_zone(), otherwise all PFNs are invalid.
|
||||||
*/
|
*/
|
||||||
|
@@ -9,6 +9,7 @@ config ARM64
|
|||||||
select ACPI_MCFG if (ACPI && PCI)
|
select ACPI_MCFG if (ACPI && PCI)
|
||||||
select ACPI_SPCR_TABLE if ACPI
|
select ACPI_SPCR_TABLE if ACPI
|
||||||
select ACPI_PPTT if ACPI
|
select ACPI_PPTT if ACPI
|
||||||
|
select ARCH_HAS_DEBUG_WX
|
||||||
select ARCH_BINFMT_ELF_STATE
|
select ARCH_BINFMT_ELF_STATE
|
||||||
select ARCH_HAS_DEBUG_VIRTUAL
|
select ARCH_HAS_DEBUG_VIRTUAL
|
||||||
select ARCH_HAS_DEVMEM_IS_ALLOWED
|
select ARCH_HAS_DEVMEM_IS_ALLOWED
|
||||||
@@ -162,7 +163,6 @@ config ARM64
|
|||||||
select HAVE_GCC_PLUGINS
|
select HAVE_GCC_PLUGINS
|
||||||
select HAVE_HW_BREAKPOINT if PERF_EVENTS
|
select HAVE_HW_BREAKPOINT if PERF_EVENTS
|
||||||
select HAVE_IRQ_TIME_ACCOUNTING
|
select HAVE_IRQ_TIME_ACCOUNTING
|
||||||
select HAVE_MEMBLOCK_NODE_MAP if NUMA
|
|
||||||
select HAVE_NMI
|
select HAVE_NMI
|
||||||
select HAVE_PATA_PLATFORM
|
select HAVE_PATA_PLATFORM
|
||||||
select HAVE_PERF_EVENTS
|
select HAVE_PERF_EVENTS
|
||||||
|
@@ -23,35 +23,6 @@ config ARM64_RANDOMIZE_TEXT_OFFSET
|
|||||||
of TEXT_OFFSET and platforms must not require a specific
|
of TEXT_OFFSET and platforms must not require a specific
|
||||||
value.
|
value.
|
||||||
|
|
||||||
config DEBUG_WX
|
|
||||||
bool "Warn on W+X mappings at boot"
|
|
||||||
select PTDUMP_CORE
|
|
||||||
---help---
|
|
||||||
Generate a warning if any W+X mappings are found at boot.
|
|
||||||
|
|
||||||
This is useful for discovering cases where the kernel is leaving
|
|
||||||
W+X mappings after applying NX, as such mappings are a security risk.
|
|
||||||
This check also includes UXN, which should be set on all kernel
|
|
||||||
mappings.
|
|
||||||
|
|
||||||
Look for a message in dmesg output like this:
|
|
||||||
|
|
||||||
arm64/mm: Checked W+X mappings: passed, no W+X pages found.
|
|
||||||
|
|
||||||
or like this, if the check failed:
|
|
||||||
|
|
||||||
arm64/mm: Checked W+X mappings: FAILED, <N> W+X pages found.
|
|
||||||
|
|
||||||
Note that even if the check fails, your kernel is possibly
|
|
||||||
still fine, as W+X mappings are not a security hole in
|
|
||||||
themselves, what they do is that they make the exploitation
|
|
||||||
of other unfixed kernel bugs easier.
|
|
||||||
|
|
||||||
There is no runtime or memory usage effect of this option
|
|
||||||
once the kernel has booted up - it's a one time check.
|
|
||||||
|
|
||||||
If in doubt, say "Y".
|
|
||||||
|
|
||||||
config DEBUG_EFI
|
config DEBUG_EFI
|
||||||
depends on EFI && DEBUG_INFO
|
depends on EFI && DEBUG_INFO
|
||||||
bool "UEFI debugging"
|
bool "UEFI debugging"
|
||||||
|
@@ -17,22 +17,11 @@
|
|||||||
extern bool arch_hugetlb_migration_supported(struct hstate *h);
|
extern bool arch_hugetlb_migration_supported(struct hstate *h);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define __HAVE_ARCH_HUGE_PTEP_GET
|
|
||||||
static inline pte_t huge_ptep_get(pte_t *ptep)
|
|
||||||
{
|
|
||||||
return READ_ONCE(*ptep);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int is_hugepage_only_range(struct mm_struct *mm,
|
|
||||||
unsigned long addr, unsigned long len)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void arch_clear_hugepage_flags(struct page *page)
|
static inline void arch_clear_hugepage_flags(struct page *page)
|
||||||
{
|
{
|
||||||
clear_bit(PG_dcache_clean, &page->flags);
|
clear_bit(PG_dcache_clean, &page->flags);
|
||||||
}
|
}
|
||||||
|
#define arch_clear_hugepage_flags arch_clear_hugepage_flags
|
||||||
|
|
||||||
extern pte_t arch_make_huge_pte(pte_t entry, struct vm_area_struct *vma,
|
extern pte_t arch_make_huge_pte(pte_t entry, struct vm_area_struct *vma,
|
||||||
struct page *page, int writable);
|
struct page *page, int writable);
|
||||||
|
@@ -366,7 +366,7 @@ static inline int pmd_protnone(pmd_t pmd)
|
|||||||
#define pmd_mkclean(pmd) pte_pmd(pte_mkclean(pmd_pte(pmd)))
|
#define pmd_mkclean(pmd) pte_pmd(pte_mkclean(pmd_pte(pmd)))
|
||||||
#define pmd_mkdirty(pmd) pte_pmd(pte_mkdirty(pmd_pte(pmd)))
|
#define pmd_mkdirty(pmd) pte_pmd(pte_mkdirty(pmd_pte(pmd)))
|
||||||
#define pmd_mkyoung(pmd) pte_pmd(pte_mkyoung(pmd_pte(pmd)))
|
#define pmd_mkyoung(pmd) pte_pmd(pte_mkyoung(pmd_pte(pmd)))
|
||||||
#define pmd_mknotpresent(pmd) (__pmd(pmd_val(pmd) & ~PMD_SECT_VALID))
|
#define pmd_mkinvalid(pmd) (__pmd(pmd_val(pmd) & ~PMD_SECT_VALID))
|
||||||
|
|
||||||
#define pmd_thp_or_huge(pmd) (pmd_huge(pmd) || pmd_trans_huge(pmd))
|
#define pmd_thp_or_huge(pmd) (pmd_huge(pmd) || pmd_trans_huge(pmd))
|
||||||
|
|
||||||
|
@@ -443,44 +443,30 @@ void huge_ptep_clear_flush(struct vm_area_struct *vma,
|
|||||||
clear_flush(vma->vm_mm, addr, ptep, pgsize, ncontig);
|
clear_flush(vma->vm_mm, addr, ptep, pgsize, ncontig);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __init add_huge_page_size(unsigned long size)
|
|
||||||
{
|
|
||||||
if (size_to_hstate(size))
|
|
||||||
return;
|
|
||||||
|
|
||||||
hugetlb_add_hstate(ilog2(size) - PAGE_SHIFT);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int __init hugetlbpage_init(void)
|
static int __init hugetlbpage_init(void)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_ARM64_4K_PAGES
|
#ifdef CONFIG_ARM64_4K_PAGES
|
||||||
add_huge_page_size(PUD_SIZE);
|
hugetlb_add_hstate(PUD_SHIFT - PAGE_SHIFT);
|
||||||
#endif
|
#endif
|
||||||
add_huge_page_size(CONT_PMD_SIZE);
|
hugetlb_add_hstate((CONT_PMD_SHIFT + PMD_SHIFT) - PAGE_SHIFT);
|
||||||
add_huge_page_size(PMD_SIZE);
|
hugetlb_add_hstate(PMD_SHIFT - PAGE_SHIFT);
|
||||||
add_huge_page_size(CONT_PTE_SIZE);
|
hugetlb_add_hstate((CONT_PTE_SHIFT + PAGE_SHIFT) - PAGE_SHIFT);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
arch_initcall(hugetlbpage_init);
|
arch_initcall(hugetlbpage_init);
|
||||||
|
|
||||||
static __init int setup_hugepagesz(char *opt)
|
bool __init arch_hugetlb_valid_size(unsigned long size)
|
||||||
{
|
{
|
||||||
unsigned long ps = memparse(opt, &opt);
|
switch (size) {
|
||||||
|
|
||||||
switch (ps) {
|
|
||||||
#ifdef CONFIG_ARM64_4K_PAGES
|
#ifdef CONFIG_ARM64_4K_PAGES
|
||||||
case PUD_SIZE:
|
case PUD_SIZE:
|
||||||
#endif
|
#endif
|
||||||
case CONT_PMD_SIZE:
|
case CONT_PMD_SIZE:
|
||||||
case PMD_SIZE:
|
case PMD_SIZE:
|
||||||
case CONT_PTE_SIZE:
|
case CONT_PTE_SIZE:
|
||||||
add_huge_page_size(ps);
|
return true;
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hugetlb_bad_size();
|
return false;
|
||||||
pr_err("hugepagesz: Unsupported page size %lu K\n", ps >> 10);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
__setup("hugepagesz=", setup_hugepagesz);
|
|
||||||
|
@@ -192,8 +192,6 @@ static phys_addr_t __init max_zone_phys(unsigned int zone_bits)
|
|||||||
return min(offset + (1ULL << zone_bits), memblock_end_of_DRAM());
|
return min(offset + (1ULL << zone_bits), memblock_end_of_DRAM());
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_NUMA
|
|
||||||
|
|
||||||
static void __init zone_sizes_init(unsigned long min, unsigned long max)
|
static void __init zone_sizes_init(unsigned long min, unsigned long max)
|
||||||
{
|
{
|
||||||
unsigned long max_zone_pfns[MAX_NR_ZONES] = {0};
|
unsigned long max_zone_pfns[MAX_NR_ZONES] = {0};
|
||||||
@@ -206,61 +204,9 @@ static void __init zone_sizes_init(unsigned long min, unsigned long max)
|
|||||||
#endif
|
#endif
|
||||||
max_zone_pfns[ZONE_NORMAL] = max;
|
max_zone_pfns[ZONE_NORMAL] = max;
|
||||||
|
|
||||||
free_area_init_nodes(max_zone_pfns);
|
free_area_init(max_zone_pfns);
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
static void __init zone_sizes_init(unsigned long min, unsigned long max)
|
|
||||||
{
|
|
||||||
struct memblock_region *reg;
|
|
||||||
unsigned long zone_size[MAX_NR_ZONES], zhole_size[MAX_NR_ZONES];
|
|
||||||
unsigned long __maybe_unused max_dma, max_dma32;
|
|
||||||
|
|
||||||
memset(zone_size, 0, sizeof(zone_size));
|
|
||||||
|
|
||||||
max_dma = max_dma32 = min;
|
|
||||||
#ifdef CONFIG_ZONE_DMA
|
|
||||||
max_dma = max_dma32 = PFN_DOWN(arm64_dma_phys_limit);
|
|
||||||
zone_size[ZONE_DMA] = max_dma - min;
|
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_ZONE_DMA32
|
|
||||||
max_dma32 = PFN_DOWN(arm64_dma32_phys_limit);
|
|
||||||
zone_size[ZONE_DMA32] = max_dma32 - max_dma;
|
|
||||||
#endif
|
|
||||||
zone_size[ZONE_NORMAL] = max - max_dma32;
|
|
||||||
|
|
||||||
memcpy(zhole_size, zone_size, sizeof(zhole_size));
|
|
||||||
|
|
||||||
for_each_memblock(memory, reg) {
|
|
||||||
unsigned long start = memblock_region_memory_base_pfn(reg);
|
|
||||||
unsigned long end = memblock_region_memory_end_pfn(reg);
|
|
||||||
|
|
||||||
#ifdef CONFIG_ZONE_DMA
|
|
||||||
if (start >= min && start < max_dma) {
|
|
||||||
unsigned long dma_end = min(end, max_dma);
|
|
||||||
zhole_size[ZONE_DMA] -= dma_end - start;
|
|
||||||
start = dma_end;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_ZONE_DMA32
|
|
||||||
if (start >= max_dma && start < max_dma32) {
|
|
||||||
unsigned long dma32_end = min(end, max_dma32);
|
|
||||||
zhole_size[ZONE_DMA32] -= dma32_end - start;
|
|
||||||
start = dma32_end;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (start >= max_dma32 && start < max) {
|
|
||||||
unsigned long normal_end = min(end, max);
|
|
||||||
zhole_size[ZONE_NORMAL] -= normal_end - start;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
free_area_init_node(0, zone_size, min, zhole_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* CONFIG_NUMA */
|
|
||||||
|
|
||||||
int pfn_valid(unsigned long pfn)
|
int pfn_valid(unsigned long pfn)
|
||||||
{
|
{
|
||||||
phys_addr_t addr = pfn << PAGE_SHIFT;
|
phys_addr_t addr = pfn << PAGE_SHIFT;
|
||||||
|
@@ -350,13 +350,16 @@ static int __init numa_register_nodes(void)
|
|||||||
struct memblock_region *mblk;
|
struct memblock_region *mblk;
|
||||||
|
|
||||||
/* Check that valid nid is set to memblks */
|
/* Check that valid nid is set to memblks */
|
||||||
for_each_memblock(memory, mblk)
|
for_each_memblock(memory, mblk) {
|
||||||
if (mblk->nid == NUMA_NO_NODE || mblk->nid >= MAX_NUMNODES) {
|
int mblk_nid = memblock_get_region_node(mblk);
|
||||||
|
|
||||||
|
if (mblk_nid == NUMA_NO_NODE || mblk_nid >= MAX_NUMNODES) {
|
||||||
pr_warn("Warning: invalid memblk node %d [mem %#010Lx-%#010Lx]\n",
|
pr_warn("Warning: invalid memblk node %d [mem %#010Lx-%#010Lx]\n",
|
||||||
mblk->nid, mblk->base,
|
mblk_nid, mblk->base,
|
||||||
mblk->base + mblk->size - 1);
|
mblk->base + mblk->size - 1);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Finally register nodes. */
|
/* Finally register nodes. */
|
||||||
for_each_node_mask(nid, numa_nodes_parsed) {
|
for_each_node_mask(nid, numa_nodes_parsed) {
|
||||||
|
@@ -33,7 +33,7 @@ EXPORT_SYMBOL(empty_zero_page);
|
|||||||
void __init paging_init(void)
|
void __init paging_init(void)
|
||||||
{
|
{
|
||||||
struct pglist_data *pgdat = NODE_DATA(0);
|
struct pglist_data *pgdat = NODE_DATA(0);
|
||||||
unsigned long zones_size[MAX_NR_ZONES] = {0, };
|
unsigned long max_zone_pfn[MAX_NR_ZONES] = {0, };
|
||||||
|
|
||||||
empty_zero_page = (unsigned long) memblock_alloc(PAGE_SIZE,
|
empty_zero_page = (unsigned long) memblock_alloc(PAGE_SIZE,
|
||||||
PAGE_SIZE);
|
PAGE_SIZE);
|
||||||
@@ -49,11 +49,9 @@ void __init paging_init(void)
|
|||||||
/*
|
/*
|
||||||
* Define zones
|
* Define zones
|
||||||
*/
|
*/
|
||||||
zones_size[ZONE_NORMAL] = (memory_end - PAGE_OFFSET) >> PAGE_SHIFT;
|
max_zone_pfn[ZONE_NORMAL] = memory_end >> PAGE_SHIFT;
|
||||||
pgdat->node_zones[ZONE_NORMAL].zone_start_pfn =
|
|
||||||
__pa(PAGE_OFFSET) >> PAGE_SHIFT;
|
|
||||||
|
|
||||||
free_area_init(zones_size);
|
free_area_init(max_zone_pfn);
|
||||||
}
|
}
|
||||||
|
|
||||||
void __init mem_init(void)
|
void __init mem_init(void)
|
||||||
|
@@ -26,7 +26,9 @@ struct screen_info screen_info = {
|
|||||||
|
|
||||||
static void __init csky_memblock_init(void)
|
static void __init csky_memblock_init(void)
|
||||||
{
|
{
|
||||||
unsigned long zone_size[MAX_NR_ZONES];
|
unsigned long lowmem_size = PFN_DOWN(LOWMEM_LIMIT - PHYS_OFFSET_OFFSET);
|
||||||
|
unsigned long sseg_size = PFN_DOWN(SSEG_SIZE - PHYS_OFFSET_OFFSET);
|
||||||
|
unsigned long max_zone_pfn[MAX_NR_ZONES] = { 0 };
|
||||||
signed long size;
|
signed long size;
|
||||||
|
|
||||||
memblock_reserve(__pa(_stext), _end - _stext);
|
memblock_reserve(__pa(_stext), _end - _stext);
|
||||||
@@ -36,28 +38,22 @@ static void __init csky_memblock_init(void)
|
|||||||
|
|
||||||
memblock_dump_all();
|
memblock_dump_all();
|
||||||
|
|
||||||
memset(zone_size, 0, sizeof(zone_size));
|
|
||||||
|
|
||||||
min_low_pfn = PFN_UP(memblock_start_of_DRAM());
|
min_low_pfn = PFN_UP(memblock_start_of_DRAM());
|
||||||
max_low_pfn = max_pfn = PFN_DOWN(memblock_end_of_DRAM());
|
max_low_pfn = max_pfn = PFN_DOWN(memblock_end_of_DRAM());
|
||||||
|
|
||||||
size = max_pfn - min_low_pfn;
|
size = max_pfn - min_low_pfn;
|
||||||
|
|
||||||
if (size <= PFN_DOWN(SSEG_SIZE - PHYS_OFFSET_OFFSET))
|
if (size >= lowmem_size) {
|
||||||
zone_size[ZONE_NORMAL] = size;
|
max_low_pfn = min_low_pfn + lowmem_size;
|
||||||
else if (size < PFN_DOWN(LOWMEM_LIMIT - PHYS_OFFSET_OFFSET)) {
|
|
||||||
zone_size[ZONE_NORMAL] =
|
|
||||||
PFN_DOWN(SSEG_SIZE - PHYS_OFFSET_OFFSET);
|
|
||||||
max_low_pfn = min_low_pfn + zone_size[ZONE_NORMAL];
|
|
||||||
} else {
|
|
||||||
zone_size[ZONE_NORMAL] =
|
|
||||||
PFN_DOWN(LOWMEM_LIMIT - PHYS_OFFSET_OFFSET);
|
|
||||||
max_low_pfn = min_low_pfn + zone_size[ZONE_NORMAL];
|
|
||||||
write_mmu_msa1(read_mmu_msa0() + SSEG_SIZE);
|
write_mmu_msa1(read_mmu_msa0() + SSEG_SIZE);
|
||||||
|
} else if (size > sseg_size) {
|
||||||
|
max_low_pfn = min_low_pfn + sseg_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
max_zone_pfn[ZONE_NORMAL] = max_low_pfn;
|
||||||
|
|
||||||
#ifdef CONFIG_HIGHMEM
|
#ifdef CONFIG_HIGHMEM
|
||||||
zone_size[ZONE_HIGHMEM] = max_pfn - max_low_pfn;
|
max_zone_pfn[ZONE_HIGHMEM] = max_pfn;
|
||||||
|
|
||||||
highstart_pfn = max_low_pfn;
|
highstart_pfn = max_low_pfn;
|
||||||
highend_pfn = max_pfn;
|
highend_pfn = max_pfn;
|
||||||
@@ -66,7 +62,7 @@ static void __init csky_memblock_init(void)
|
|||||||
|
|
||||||
dma_contiguous_reserve(0);
|
dma_contiguous_reserve(0);
|
||||||
|
|
||||||
free_area_init_node(0, zone_size, min_low_pfn, NULL);
|
free_area_init(max_zone_pfn);
|
||||||
}
|
}
|
||||||
|
|
||||||
void __init setup_arch(char **cmdline_p)
|
void __init setup_arch(char **cmdline_p)
|
||||||
|
@@ -83,10 +83,10 @@ void __init paging_init(void)
|
|||||||
start_mem, end_mem);
|
start_mem, end_mem);
|
||||||
|
|
||||||
{
|
{
|
||||||
unsigned long zones_size[MAX_NR_ZONES] = {0, };
|
unsigned long max_zone_pfn[MAX_NR_ZONES] = {0, };
|
||||||
|
|
||||||
zones_size[ZONE_NORMAL] = (end_mem - PAGE_OFFSET) >> PAGE_SHIFT;
|
max_zone_pfn[ZONE_NORMAL] = end_mem >> PAGE_SHIFT;
|
||||||
free_area_init(zones_size);
|
free_area_init(max_zone_pfn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -91,7 +91,7 @@ void sync_icache_dcache(pte_t pte)
|
|||||||
*/
|
*/
|
||||||
void __init paging_init(void)
|
void __init paging_init(void)
|
||||||
{
|
{
|
||||||
unsigned long zones_sizes[MAX_NR_ZONES] = {0, };
|
unsigned long max_zone_pfn[MAX_NR_ZONES] = {0, };
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is not particularly well documented anywhere, but
|
* This is not particularly well documented anywhere, but
|
||||||
@@ -101,9 +101,9 @@ void __init paging_init(void)
|
|||||||
* adjust accordingly.
|
* adjust accordingly.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
zones_sizes[ZONE_NORMAL] = max_low_pfn;
|
max_zone_pfn[ZONE_NORMAL] = max_low_pfn;
|
||||||
|
|
||||||
free_area_init(zones_sizes); /* sets up the zonelists and mem_map */
|
free_area_init(max_zone_pfn); /* sets up the zonelists and mem_map */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Start of high memory area. Will probably need something more
|
* Start of high memory area. Will probably need something more
|
||||||
|
@@ -31,7 +31,6 @@ config IA64
|
|||||||
select HAVE_FUNCTION_TRACER
|
select HAVE_FUNCTION_TRACER
|
||||||
select TTY
|
select TTY
|
||||||
select HAVE_ARCH_TRACEHOOK
|
select HAVE_ARCH_TRACEHOOK
|
||||||
select HAVE_MEMBLOCK_NODE_MAP
|
|
||||||
select HAVE_VIRT_CPU_ACCOUNTING
|
select HAVE_VIRT_CPU_ACCOUNTING
|
||||||
select DMA_NONCOHERENT_MMAP
|
select DMA_NONCOHERENT_MMAP
|
||||||
select ARCH_HAS_SYNC_DMA_FOR_CPU
|
select ARCH_HAS_SYNC_DMA_FOR_CPU
|
||||||
|
@@ -20,6 +20,7 @@ static inline int is_hugepage_only_range(struct mm_struct *mm,
|
|||||||
return (REGION_NUMBER(addr) == RGN_HPAGE ||
|
return (REGION_NUMBER(addr) == RGN_HPAGE ||
|
||||||
REGION_NUMBER((addr)+(len)-1) == RGN_HPAGE);
|
REGION_NUMBER((addr)+(len)-1) == RGN_HPAGE);
|
||||||
}
|
}
|
||||||
|
#define is_hugepage_only_range is_hugepage_only_range
|
||||||
|
|
||||||
#define __HAVE_ARCH_HUGE_PTEP_CLEAR_FLUSH
|
#define __HAVE_ARCH_HUGE_PTEP_CLEAR_FLUSH
|
||||||
static inline void huge_ptep_clear_flush(struct vm_area_struct *vma,
|
static inline void huge_ptep_clear_flush(struct vm_area_struct *vma,
|
||||||
@@ -27,10 +28,6 @@ static inline void huge_ptep_clear_flush(struct vm_area_struct *vma,
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void arch_clear_hugepage_flags(struct page *page)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
#include <asm-generic/hugetlb.h>
|
#include <asm-generic/hugetlb.h>
|
||||||
|
|
||||||
#endif /* _ASM_IA64_HUGETLB_H */
|
#endif /* _ASM_IA64_HUGETLB_H */
|
||||||
|
@@ -210,6 +210,6 @@ paging_init (void)
|
|||||||
printk("Virtual mem_map starts at 0x%p\n", mem_map);
|
printk("Virtual mem_map starts at 0x%p\n", mem_map);
|
||||||
}
|
}
|
||||||
#endif /* !CONFIG_VIRTUAL_MEM_MAP */
|
#endif /* !CONFIG_VIRTUAL_MEM_MAP */
|
||||||
free_area_init_nodes(max_zone_pfns);
|
free_area_init(max_zone_pfns);
|
||||||
zero_page_memmap_ptr = virt_to_page(ia64_imva(empty_zero_page));
|
zero_page_memmap_ptr = virt_to_page(ia64_imva(empty_zero_page));
|
||||||
}
|
}
|
||||||
|
@@ -627,7 +627,7 @@ void __init paging_init(void)
|
|||||||
max_zone_pfns[ZONE_DMA32] = max_dma;
|
max_zone_pfns[ZONE_DMA32] = max_dma;
|
||||||
#endif
|
#endif
|
||||||
max_zone_pfns[ZONE_NORMAL] = max_pfn;
|
max_zone_pfns[ZONE_NORMAL] = max_pfn;
|
||||||
free_area_init_nodes(max_zone_pfns);
|
free_area_init(max_zone_pfns);
|
||||||
|
|
||||||
zero_page_memmap_ptr = virt_to_page(ia64_imva(empty_zero_page));
|
zero_page_memmap_ptr = virt_to_page(ia64_imva(empty_zero_page));
|
||||||
}
|
}
|
||||||
|
@@ -84,7 +84,7 @@ void __init paging_init(void)
|
|||||||
* page_alloc get different views of the world.
|
* page_alloc get different views of the world.
|
||||||
*/
|
*/
|
||||||
unsigned long end_mem = memory_end & PAGE_MASK;
|
unsigned long end_mem = memory_end & PAGE_MASK;
|
||||||
unsigned long zones_size[MAX_NR_ZONES] = { 0, };
|
unsigned long max_zone_pfn[MAX_NR_ZONES] = { 0, };
|
||||||
|
|
||||||
high_memory = (void *) end_mem;
|
high_memory = (void *) end_mem;
|
||||||
|
|
||||||
@@ -98,8 +98,8 @@ void __init paging_init(void)
|
|||||||
*/
|
*/
|
||||||
set_fs (USER_DS);
|
set_fs (USER_DS);
|
||||||
|
|
||||||
zones_size[ZONE_DMA] = (end_mem - PAGE_OFFSET) >> PAGE_SHIFT;
|
max_zone_pfn[ZONE_DMA] = end_mem >> PAGE_SHIFT;
|
||||||
free_area_init(zones_size);
|
free_area_init(max_zone_pfn);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_MMU */
|
#endif /* CONFIG_MMU */
|
||||||
|
@@ -39,7 +39,7 @@ void __init paging_init(void)
|
|||||||
pte_t *pg_table;
|
pte_t *pg_table;
|
||||||
unsigned long address, size;
|
unsigned long address, size;
|
||||||
unsigned long next_pgtable, bootmem_end;
|
unsigned long next_pgtable, bootmem_end;
|
||||||
unsigned long zones_size[MAX_NR_ZONES];
|
unsigned long max_zone_pfn[MAX_NR_ZONES] = { 0 };
|
||||||
enum zone_type zone;
|
enum zone_type zone;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@@ -80,11 +80,8 @@ void __init paging_init(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
current->mm = NULL;
|
current->mm = NULL;
|
||||||
|
max_zone_pfn[ZONE_DMA] = PFN_DOWN(_ramend);
|
||||||
for (zone = 0; zone < MAX_NR_ZONES; zone++)
|
free_area_init(max_zone_pfn);
|
||||||
zones_size[zone] = 0x0;
|
|
||||||
zones_size[ZONE_DMA] = num_pages;
|
|
||||||
free_area_init(zones_size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int cf_tlb_miss(struct pt_regs *regs, int write, int dtlb, int extension_word)
|
int cf_tlb_miss(struct pt_regs *regs, int write, int dtlb, int extension_word)
|
||||||
|
@@ -365,7 +365,7 @@ static void __init map_node(int node)
|
|||||||
*/
|
*/
|
||||||
void __init paging_init(void)
|
void __init paging_init(void)
|
||||||
{
|
{
|
||||||
unsigned long zones_size[MAX_NR_ZONES] = { 0, };
|
unsigned long max_zone_pfn[MAX_NR_ZONES] = { 0, };
|
||||||
unsigned long min_addr, max_addr;
|
unsigned long min_addr, max_addr;
|
||||||
unsigned long addr;
|
unsigned long addr;
|
||||||
int i;
|
int i;
|
||||||
@@ -386,7 +386,7 @@ void __init paging_init(void)
|
|||||||
|
|
||||||
min_addr = m68k_memory[0].addr;
|
min_addr = m68k_memory[0].addr;
|
||||||
max_addr = min_addr + m68k_memory[0].size;
|
max_addr = min_addr + m68k_memory[0].size;
|
||||||
memblock_add(m68k_memory[0].addr, m68k_memory[0].size);
|
memblock_add_node(m68k_memory[0].addr, m68k_memory[0].size, 0);
|
||||||
for (i = 1; i < m68k_num_memory;) {
|
for (i = 1; i < m68k_num_memory;) {
|
||||||
if (m68k_memory[i].addr < min_addr) {
|
if (m68k_memory[i].addr < min_addr) {
|
||||||
printk("Ignoring memory chunk at 0x%lx:0x%lx before the first chunk\n",
|
printk("Ignoring memory chunk at 0x%lx:0x%lx before the first chunk\n",
|
||||||
@@ -397,7 +397,7 @@ void __init paging_init(void)
|
|||||||
(m68k_num_memory - i) * sizeof(struct m68k_mem_info));
|
(m68k_num_memory - i) * sizeof(struct m68k_mem_info));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
memblock_add(m68k_memory[i].addr, m68k_memory[i].size);
|
memblock_add_node(m68k_memory[i].addr, m68k_memory[i].size, i);
|
||||||
addr = m68k_memory[i].addr + m68k_memory[i].size;
|
addr = m68k_memory[i].addr + m68k_memory[i].size;
|
||||||
if (addr > max_addr)
|
if (addr > max_addr)
|
||||||
max_addr = addr;
|
max_addr = addr;
|
||||||
@@ -448,11 +448,10 @@ void __init paging_init(void)
|
|||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
printk ("before free_area_init\n");
|
printk ("before free_area_init\n");
|
||||||
#endif
|
#endif
|
||||||
for (i = 0; i < m68k_num_memory; i++) {
|
for (i = 0; i < m68k_num_memory; i++)
|
||||||
zones_size[ZONE_DMA] = m68k_memory[i].size >> PAGE_SHIFT;
|
|
||||||
free_area_init_node(i, zones_size,
|
|
||||||
m68k_memory[i].addr >> PAGE_SHIFT, NULL);
|
|
||||||
if (node_present_pages(i))
|
if (node_present_pages(i))
|
||||||
node_set_state(i, N_NORMAL_MEMORY);
|
node_set_state(i, N_NORMAL_MEMORY);
|
||||||
}
|
|
||||||
|
max_zone_pfn[ZONE_DMA] = memblock_end_of_DRAM();
|
||||||
|
free_area_init(max_zone_pfn);
|
||||||
}
|
}
|
||||||
|
@@ -42,7 +42,7 @@ void __init paging_init(void)
|
|||||||
unsigned long address;
|
unsigned long address;
|
||||||
unsigned long next_pgtable;
|
unsigned long next_pgtable;
|
||||||
unsigned long bootmem_end;
|
unsigned long bootmem_end;
|
||||||
unsigned long zones_size[MAX_NR_ZONES] = { 0, };
|
unsigned long max_zone_pfn[MAX_NR_ZONES] = { 0, };
|
||||||
unsigned long size;
|
unsigned long size;
|
||||||
|
|
||||||
empty_zero_page = memblock_alloc(PAGE_SIZE, PAGE_SIZE);
|
empty_zero_page = memblock_alloc(PAGE_SIZE, PAGE_SIZE);
|
||||||
@@ -89,14 +89,10 @@ void __init paging_init(void)
|
|||||||
current->mm = NULL;
|
current->mm = NULL;
|
||||||
|
|
||||||
/* memory sizing is a hack stolen from motorola.c.. hope it works for us */
|
/* memory sizing is a hack stolen from motorola.c.. hope it works for us */
|
||||||
zones_size[ZONE_DMA] = ((unsigned long)high_memory - PAGE_OFFSET) >> PAGE_SHIFT;
|
max_zone_pfn[ZONE_DMA] = ((unsigned long)high_memory) >> PAGE_SHIFT;
|
||||||
|
|
||||||
/* I really wish I knew why the following change made things better... -- Sam */
|
/* I really wish I knew why the following change made things better... -- Sam */
|
||||||
/* free_area_init(zones_size); */
|
free_area_init(max_zone_pfn);
|
||||||
free_area_init_node(0, zones_size,
|
|
||||||
(__pa(PAGE_OFFSET) >> PAGE_SHIFT) + 1, NULL);
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -32,7 +32,6 @@ config MICROBLAZE
|
|||||||
select HAVE_FTRACE_MCOUNT_RECORD
|
select HAVE_FTRACE_MCOUNT_RECORD
|
||||||
select HAVE_FUNCTION_GRAPH_TRACER
|
select HAVE_FUNCTION_GRAPH_TRACER
|
||||||
select HAVE_FUNCTION_TRACER
|
select HAVE_FUNCTION_TRACER
|
||||||
select HAVE_MEMBLOCK_NODE_MAP
|
|
||||||
select HAVE_OPROFILE
|
select HAVE_OPROFILE
|
||||||
select HAVE_PCI
|
select HAVE_PCI
|
||||||
select IRQ_DOMAIN
|
select IRQ_DOMAIN
|
||||||
|
@@ -112,7 +112,7 @@ static void __init paging_init(void)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* We don't have holes in memory map */
|
/* We don't have holes in memory map */
|
||||||
free_area_init_nodes(zones_size);
|
free_area_init(zones_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void __init setup_memory(void)
|
void __init setup_memory(void)
|
||||||
|
@@ -72,7 +72,6 @@ config MIPS
|
|||||||
select HAVE_KPROBES
|
select HAVE_KPROBES
|
||||||
select HAVE_KRETPROBES
|
select HAVE_KRETPROBES
|
||||||
select HAVE_LD_DEAD_CODE_DATA_ELIMINATION
|
select HAVE_LD_DEAD_CODE_DATA_ELIMINATION
|
||||||
select HAVE_MEMBLOCK_NODE_MAP
|
|
||||||
select HAVE_MOD_ARCH_SPECIFIC
|
select HAVE_MOD_ARCH_SPECIFIC
|
||||||
select HAVE_NMI
|
select HAVE_NMI
|
||||||
select HAVE_OPROFILE
|
select HAVE_OPROFILE
|
||||||
|
@@ -11,13 +11,6 @@
|
|||||||
|
|
||||||
#include <asm/page.h>
|
#include <asm/page.h>
|
||||||
|
|
||||||
static inline int is_hugepage_only_range(struct mm_struct *mm,
|
|
||||||
unsigned long addr,
|
|
||||||
unsigned long len)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define __HAVE_ARCH_PREPARE_HUGEPAGE_RANGE
|
#define __HAVE_ARCH_PREPARE_HUGEPAGE_RANGE
|
||||||
static inline int prepare_hugepage_range(struct file *file,
|
static inline int prepare_hugepage_range(struct file *file,
|
||||||
unsigned long addr,
|
unsigned long addr,
|
||||||
@@ -82,10 +75,6 @@ static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma,
|
|||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void arch_clear_hugepage_flags(struct page *page)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
#include <asm-generic/hugetlb.h>
|
#include <asm-generic/hugetlb.h>
|
||||||
|
|
||||||
#endif /* __ASM_HUGETLB_H */
|
#endif /* __ASM_HUGETLB_H */
|
||||||
|
@@ -705,7 +705,7 @@ static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
|
|||||||
return pmd;
|
return pmd;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline pmd_t pmd_mknotpresent(pmd_t pmd)
|
static inline pmd_t pmd_mkinvalid(pmd_t pmd)
|
||||||
{
|
{
|
||||||
pmd_val(pmd) &= ~(_PAGE_PRESENT | _PAGE_VALID | _PAGE_DIRTY);
|
pmd_val(pmd) &= ~(_PAGE_PRESENT | _PAGE_VALID | _PAGE_DIRTY);
|
||||||
|
|
||||||
|
@@ -247,7 +247,7 @@ void __init paging_init(void)
|
|||||||
zones_size[ZONE_DMA32] = MAX_DMA32_PFN;
|
zones_size[ZONE_DMA32] = MAX_DMA32_PFN;
|
||||||
#endif
|
#endif
|
||||||
zones_size[ZONE_NORMAL] = max_low_pfn;
|
zones_size[ZONE_NORMAL] = max_low_pfn;
|
||||||
free_area_init_nodes(zones_size);
|
free_area_init(zones_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void __init mem_init(void)
|
void __init mem_init(void)
|
||||||
|
@@ -424,7 +424,7 @@ void __init paging_init(void)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
free_area_init_nodes(max_zone_pfns);
|
free_area_init(max_zone_pfns);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_64BIT
|
#ifdef CONFIG_64BIT
|
||||||
|
@@ -419,7 +419,7 @@ void __init paging_init(void)
|
|||||||
|
|
||||||
pagetable_init();
|
pagetable_init();
|
||||||
zones_size[ZONE_NORMAL] = max_low_pfn;
|
zones_size[ZONE_NORMAL] = max_low_pfn;
|
||||||
free_area_init_nodes(zones_size);
|
free_area_init(zones_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void __init mem_init(void)
|
void __init mem_init(void)
|
||||||
|
@@ -31,16 +31,13 @@ EXPORT_SYMBOL(empty_zero_page);
|
|||||||
|
|
||||||
static void __init zone_sizes_init(void)
|
static void __init zone_sizes_init(void)
|
||||||
{
|
{
|
||||||
unsigned long zones_size[MAX_NR_ZONES];
|
unsigned long max_zone_pfn[MAX_NR_ZONES] = { 0 };
|
||||||
|
|
||||||
/* Clear the zone sizes */
|
max_zone_pfn[ZONE_NORMAL] = max_low_pfn;
|
||||||
memset(zones_size, 0, sizeof(zones_size));
|
|
||||||
|
|
||||||
zones_size[ZONE_NORMAL] = max_low_pfn;
|
|
||||||
#ifdef CONFIG_HIGHMEM
|
#ifdef CONFIG_HIGHMEM
|
||||||
zones_size[ZONE_HIGHMEM] = max_pfn;
|
max_zone_pfn[ZONE_HIGHMEM] = max_pfn;
|
||||||
#endif
|
#endif
|
||||||
free_area_init(zones_size);
|
free_area_init(max_zone_pfn);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -46,17 +46,15 @@ pgd_t *pgd_current;
|
|||||||
*/
|
*/
|
||||||
void __init paging_init(void)
|
void __init paging_init(void)
|
||||||
{
|
{
|
||||||
unsigned long zones_size[MAX_NR_ZONES];
|
unsigned long max_zone_pfn[MAX_NR_ZONES] = { 0 };
|
||||||
|
|
||||||
memset(zones_size, 0, sizeof(zones_size));
|
|
||||||
|
|
||||||
pagetable_init();
|
pagetable_init();
|
||||||
pgd_current = swapper_pg_dir;
|
pgd_current = swapper_pg_dir;
|
||||||
|
|
||||||
zones_size[ZONE_NORMAL] = max_mapnr;
|
max_zone_pfn[ZONE_NORMAL] = max_mapnr;
|
||||||
|
|
||||||
/* pass the memory from the bootmem allocator to the main allocator */
|
/* pass the memory from the bootmem allocator to the main allocator */
|
||||||
free_area_init(zones_size);
|
free_area_init(max_zone_pfn);
|
||||||
|
|
||||||
flush_dcache_range((unsigned long)empty_zero_page,
|
flush_dcache_range((unsigned long)empty_zero_page,
|
||||||
(unsigned long)empty_zero_page + PAGE_SIZE);
|
(unsigned long)empty_zero_page + PAGE_SIZE);
|
||||||
|
@@ -45,17 +45,14 @@ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
|
|||||||
|
|
||||||
static void __init zone_sizes_init(void)
|
static void __init zone_sizes_init(void)
|
||||||
{
|
{
|
||||||
unsigned long zones_size[MAX_NR_ZONES];
|
unsigned long max_zone_pfn[MAX_NR_ZONES] = { 0 };
|
||||||
|
|
||||||
/* Clear the zone sizes */
|
|
||||||
memset(zones_size, 0, sizeof(zones_size));
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We use only ZONE_NORMAL
|
* We use only ZONE_NORMAL
|
||||||
*/
|
*/
|
||||||
zones_size[ZONE_NORMAL] = max_low_pfn;
|
max_zone_pfn[ZONE_NORMAL] = max_low_pfn;
|
||||||
|
|
||||||
free_area_init(zones_size);
|
free_area_init(max_zone_pfn);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern const char _s_kernel_ro[], _e_kernel_ro[];
|
extern const char _s_kernel_ro[], _e_kernel_ro[];
|
||||||
|
@@ -12,12 +12,6 @@ void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
|
|||||||
pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
|
pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
|
||||||
pte_t *ptep);
|
pte_t *ptep);
|
||||||
|
|
||||||
static inline int is_hugepage_only_range(struct mm_struct *mm,
|
|
||||||
unsigned long addr,
|
|
||||||
unsigned long len) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the arch doesn't supply something else, assume that hugepage
|
* If the arch doesn't supply something else, assume that hugepage
|
||||||
* size aligned regions are ok without further preparation.
|
* size aligned regions are ok without further preparation.
|
||||||
@@ -48,10 +42,6 @@ int huge_ptep_set_access_flags(struct vm_area_struct *vma,
|
|||||||
unsigned long addr, pte_t *ptep,
|
unsigned long addr, pte_t *ptep,
|
||||||
pte_t pte, int dirty);
|
pte_t pte, int dirty);
|
||||||
|
|
||||||
static inline void arch_clear_hugepage_flags(struct page *page)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
#include <asm-generic/hugetlb.h>
|
#include <asm-generic/hugetlb.h>
|
||||||
|
|
||||||
#endif /* _ASM_PARISC64_HUGETLB_H */
|
#endif /* _ASM_PARISC64_HUGETLB_H */
|
||||||
|
@@ -675,27 +675,11 @@ static void __init gateway_init(void)
|
|||||||
|
|
||||||
static void __init parisc_bootmem_free(void)
|
static void __init parisc_bootmem_free(void)
|
||||||
{
|
{
|
||||||
unsigned long zones_size[MAX_NR_ZONES] = { 0, };
|
unsigned long max_zone_pfn[MAX_NR_ZONES] = { 0, };
|
||||||
unsigned long holes_size[MAX_NR_ZONES] = { 0, };
|
|
||||||
unsigned long mem_start_pfn = ~0UL, mem_end_pfn = 0, mem_size_pfn = 0;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < npmem_ranges; i++) {
|
max_zone_pfn[0] = memblock_end_of_DRAM();
|
||||||
unsigned long start = pmem_ranges[i].start_pfn;
|
|
||||||
unsigned long size = pmem_ranges[i].pages;
|
|
||||||
unsigned long end = start + size;
|
|
||||||
|
|
||||||
if (mem_start_pfn > start)
|
free_area_init(max_zone_pfn);
|
||||||
mem_start_pfn = start;
|
|
||||||
if (mem_end_pfn < end)
|
|
||||||
mem_end_pfn = end;
|
|
||||||
mem_size_pfn += size;
|
|
||||||
}
|
|
||||||
|
|
||||||
zones_size[0] = mem_end_pfn - mem_start_pfn;
|
|
||||||
holes_size[0] = zones_size[0] - mem_size_pfn;
|
|
||||||
|
|
||||||
free_area_init_node(0, zones_size, mem_start_pfn, holes_size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void __init paging_init(void)
|
void __init paging_init(void)
|
||||||
|
@@ -211,7 +211,6 @@ config PPC
|
|||||||
select HAVE_KRETPROBES
|
select HAVE_KRETPROBES
|
||||||
select HAVE_LD_DEAD_CODE_DATA_ELIMINATION
|
select HAVE_LD_DEAD_CODE_DATA_ELIMINATION
|
||||||
select HAVE_LIVEPATCH if HAVE_DYNAMIC_FTRACE_WITH_REGS
|
select HAVE_LIVEPATCH if HAVE_DYNAMIC_FTRACE_WITH_REGS
|
||||||
select HAVE_MEMBLOCK_NODE_MAP
|
|
||||||
select HAVE_MOD_ARCH_SPECIFIC
|
select HAVE_MOD_ARCH_SPECIFIC
|
||||||
select HAVE_NMI if PERF_EVENTS || (PPC64 && PPC_BOOK3S)
|
select HAVE_NMI if PERF_EVENTS || (PPC64 && PPC_BOOK3S)
|
||||||
select HAVE_HARDLOCKUP_DETECTOR_ARCH if (PPC64 && PPC_BOOK3S)
|
select HAVE_HARDLOCKUP_DETECTOR_ARCH if (PPC64 && PPC_BOOK3S)
|
||||||
@@ -687,15 +686,6 @@ config ARCH_MEMORY_PROBE
|
|||||||
def_bool y
|
def_bool y
|
||||||
depends on MEMORY_HOTPLUG
|
depends on MEMORY_HOTPLUG
|
||||||
|
|
||||||
# Some NUMA nodes have memory ranges that span
|
|
||||||
# other nodes. Even though a pfn is valid and
|
|
||||||
# between a node's start and end pfns, it may not
|
|
||||||
# reside on that node. See memmap_init_zone()
|
|
||||||
# for details.
|
|
||||||
config NODES_SPAN_OTHER_NODES
|
|
||||||
def_bool y
|
|
||||||
depends on NEED_MULTIPLE_NODES
|
|
||||||
|
|
||||||
config STDBINUTILS
|
config STDBINUTILS
|
||||||
bool "Using standard binutils settings"
|
bool "Using standard binutils settings"
|
||||||
depends on 44x
|
depends on 44x
|
||||||
|
@@ -1168,10 +1168,6 @@ static inline int pmd_large(pmd_t pmd)
|
|||||||
return !!(pmd_raw(pmd) & cpu_to_be64(_PAGE_PTE));
|
return !!(pmd_raw(pmd) & cpu_to_be64(_PAGE_PTE));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline pmd_t pmd_mknotpresent(pmd_t pmd)
|
|
||||||
{
|
|
||||||
return __pmd(pmd_val(pmd) & ~_PAGE_PRESENT);
|
|
||||||
}
|
|
||||||
/*
|
/*
|
||||||
* For radix we should always find H_PAGE_HASHPTE zero. Hence
|
* For radix we should always find H_PAGE_HASHPTE zero. Hence
|
||||||
* the below will work for radix too
|
* the below will work for radix too
|
||||||
|
@@ -30,6 +30,7 @@ static inline int is_hugepage_only_range(struct mm_struct *mm,
|
|||||||
return slice_is_hugepage_only_range(mm, addr, len);
|
return slice_is_hugepage_only_range(mm, addr, len);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#define is_hugepage_only_range is_hugepage_only_range
|
||||||
|
|
||||||
#define __HAVE_ARCH_HUGETLB_FREE_PGD_RANGE
|
#define __HAVE_ARCH_HUGETLB_FREE_PGD_RANGE
|
||||||
void hugetlb_free_pgd_range(struct mmu_gather *tlb, unsigned long addr,
|
void hugetlb_free_pgd_range(struct mmu_gather *tlb, unsigned long addr,
|
||||||
@@ -60,10 +61,6 @@ int huge_ptep_set_access_flags(struct vm_area_struct *vma,
|
|||||||
unsigned long addr, pte_t *ptep,
|
unsigned long addr, pte_t *ptep,
|
||||||
pte_t pte, int dirty);
|
pte_t pte, int dirty);
|
||||||
|
|
||||||
static inline void arch_clear_hugepage_flags(struct page *page)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
#include <asm-generic/hugetlb.h>
|
#include <asm-generic/hugetlb.h>
|
||||||
|
|
||||||
#else /* ! CONFIG_HUGETLB_PAGE */
|
#else /* ! CONFIG_HUGETLB_PAGE */
|
||||||
|
@@ -558,7 +558,7 @@ unsigned long vma_mmu_pagesize(struct vm_area_struct *vma)
|
|||||||
return vma_kernel_pagesize(vma);
|
return vma_kernel_pagesize(vma);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __init add_huge_page_size(unsigned long long size)
|
bool __init arch_hugetlb_valid_size(unsigned long size)
|
||||||
{
|
{
|
||||||
int shift = __ffs(size);
|
int shift = __ffs(size);
|
||||||
int mmu_psize;
|
int mmu_psize;
|
||||||
@@ -566,38 +566,28 @@ static int __init add_huge_page_size(unsigned long long size)
|
|||||||
/* Check that it is a page size supported by the hardware and
|
/* Check that it is a page size supported by the hardware and
|
||||||
* that it fits within pagetable and slice limits. */
|
* that it fits within pagetable and slice limits. */
|
||||||
if (size <= PAGE_SIZE || !is_power_of_2(size))
|
if (size <= PAGE_SIZE || !is_power_of_2(size))
|
||||||
return -EINVAL;
|
return false;
|
||||||
|
|
||||||
mmu_psize = check_and_get_huge_psize(shift);
|
mmu_psize = check_and_get_huge_psize(shift);
|
||||||
if (mmu_psize < 0)
|
if (mmu_psize < 0)
|
||||||
return -EINVAL;
|
return false;
|
||||||
|
|
||||||
BUG_ON(mmu_psize_defs[mmu_psize].shift != shift);
|
BUG_ON(mmu_psize_defs[mmu_psize].shift != shift);
|
||||||
|
|
||||||
/* Return if huge page size has already been setup */
|
return true;
|
||||||
if (size_to_hstate(size))
|
}
|
||||||
return 0;
|
|
||||||
|
static int __init add_huge_page_size(unsigned long long size)
|
||||||
|
{
|
||||||
|
int shift = __ffs(size);
|
||||||
|
|
||||||
|
if (!arch_hugetlb_valid_size((unsigned long)size))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
hugetlb_add_hstate(shift - PAGE_SHIFT);
|
hugetlb_add_hstate(shift - PAGE_SHIFT);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __init hugepage_setup_sz(char *str)
|
|
||||||
{
|
|
||||||
unsigned long long size;
|
|
||||||
|
|
||||||
size = memparse(str, &str);
|
|
||||||
|
|
||||||
if (add_huge_page_size(size) != 0) {
|
|
||||||
hugetlb_bad_size();
|
|
||||||
pr_err("Invalid huge page size specified(%llu)\n", size);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
__setup("hugepagesz=", hugepage_setup_sz);
|
|
||||||
|
|
||||||
static int __init hugetlbpage_init(void)
|
static int __init hugetlbpage_init(void)
|
||||||
{
|
{
|
||||||
bool configured = false;
|
bool configured = false;
|
||||||
|
@@ -271,7 +271,7 @@ void __init paging_init(void)
|
|||||||
max_zone_pfns[ZONE_HIGHMEM] = max_pfn;
|
max_zone_pfns[ZONE_HIGHMEM] = max_pfn;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
free_area_init_nodes(max_zone_pfns);
|
free_area_init(max_zone_pfns);
|
||||||
|
|
||||||
mark_nonram_nosave();
|
mark_nonram_nosave();
|
||||||
}
|
}
|
||||||
|
@@ -16,6 +16,7 @@ config RISCV
|
|||||||
select OF_EARLY_FLATTREE
|
select OF_EARLY_FLATTREE
|
||||||
select OF_IRQ
|
select OF_IRQ
|
||||||
select ARCH_HAS_BINFMT_FLAT
|
select ARCH_HAS_BINFMT_FLAT
|
||||||
|
select ARCH_HAS_DEBUG_WX
|
||||||
select ARCH_WANT_FRAME_POINTERS
|
select ARCH_WANT_FRAME_POINTERS
|
||||||
select CLONE_BACKWARDS
|
select CLONE_BACKWARDS
|
||||||
select COMMON_CLK
|
select COMMON_CLK
|
||||||
@@ -32,7 +33,6 @@ config RISCV
|
|||||||
select HAVE_ARCH_AUDITSYSCALL
|
select HAVE_ARCH_AUDITSYSCALL
|
||||||
select HAVE_ARCH_SECCOMP_FILTER
|
select HAVE_ARCH_SECCOMP_FILTER
|
||||||
select HAVE_ASM_MODVERSIONS
|
select HAVE_ASM_MODVERSIONS
|
||||||
select HAVE_MEMBLOCK_NODE_MAP
|
|
||||||
select HAVE_DMA_CONTIGUOUS if MMU
|
select HAVE_DMA_CONTIGUOUS if MMU
|
||||||
select HAVE_FUTEX_CMPXCHG if FUTEX
|
select HAVE_FUTEX_CMPXCHG if FUTEX
|
||||||
select HAVE_PERF_EVENTS
|
select HAVE_PERF_EVENTS
|
||||||
|
@@ -5,14 +5,4 @@
|
|||||||
#include <asm-generic/hugetlb.h>
|
#include <asm-generic/hugetlb.h>
|
||||||
#include <asm/page.h>
|
#include <asm/page.h>
|
||||||
|
|
||||||
static inline int is_hugepage_only_range(struct mm_struct *mm,
|
|
||||||
unsigned long addr,
|
|
||||||
unsigned long len) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void arch_clear_hugepage_flags(struct page *page)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* _ASM_RISCV_HUGETLB_H */
|
#endif /* _ASM_RISCV_HUGETLB_H */
|
||||||
|
@@ -8,4 +8,15 @@
|
|||||||
|
|
||||||
void ptdump_check_wx(void);
|
void ptdump_check_wx(void);
|
||||||
|
|
||||||
|
#ifdef CONFIG_DEBUG_WX
|
||||||
|
static inline void debug_checkwx(void)
|
||||||
|
{
|
||||||
|
ptdump_check_wx();
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static inline void debug_checkwx(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* _ASM_RISCV_PTDUMP_H */
|
#endif /* _ASM_RISCV_PTDUMP_H */
|
||||||
|
@@ -12,29 +12,21 @@ int pmd_huge(pmd_t pmd)
|
|||||||
return pmd_leaf(pmd);
|
return pmd_leaf(pmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
static __init int setup_hugepagesz(char *opt)
|
bool __init arch_hugetlb_valid_size(unsigned long size)
|
||||||
{
|
{
|
||||||
unsigned long ps = memparse(opt, &opt);
|
if (size == HPAGE_SIZE)
|
||||||
|
return true;
|
||||||
if (ps == HPAGE_SIZE) {
|
else if (IS_ENABLED(CONFIG_64BIT) && size == PUD_SIZE)
|
||||||
hugetlb_add_hstate(HPAGE_SHIFT - PAGE_SHIFT);
|
return true;
|
||||||
} else if (IS_ENABLED(CONFIG_64BIT) && ps == PUD_SIZE) {
|
else
|
||||||
hugetlb_add_hstate(PUD_SHIFT - PAGE_SHIFT);
|
return false;
|
||||||
} else {
|
|
||||||
hugetlb_bad_size();
|
|
||||||
pr_err("hugepagesz: Unsupported page size %lu M\n", ps >> 20);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
__setup("hugepagesz=", setup_hugepagesz);
|
|
||||||
|
|
||||||
#ifdef CONFIG_CONTIG_ALLOC
|
#ifdef CONFIG_CONTIG_ALLOC
|
||||||
static __init int gigantic_pages_init(void)
|
static __init int gigantic_pages_init(void)
|
||||||
{
|
{
|
||||||
/* With CONTIG_ALLOC, we can allocate gigantic pages at runtime */
|
/* With CONTIG_ALLOC, we can allocate gigantic pages at runtime */
|
||||||
if (IS_ENABLED(CONFIG_64BIT) && !size_to_hstate(1UL << PUD_SHIFT))
|
if (IS_ENABLED(CONFIG_64BIT))
|
||||||
hugetlb_add_hstate(PUD_SHIFT - PAGE_SHIFT);
|
hugetlb_add_hstate(PUD_SHIFT - PAGE_SHIFT);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@@ -19,6 +19,7 @@
|
|||||||
#include <asm/sections.h>
|
#include <asm/sections.h>
|
||||||
#include <asm/pgtable.h>
|
#include <asm/pgtable.h>
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
|
#include <asm/ptdump.h>
|
||||||
|
|
||||||
#include "../kernel/head.h"
|
#include "../kernel/head.h"
|
||||||
|
|
||||||
@@ -39,7 +40,7 @@ static void __init zone_sizes_init(void)
|
|||||||
#endif
|
#endif
|
||||||
max_zone_pfns[ZONE_NORMAL] = max_low_pfn;
|
max_zone_pfns[ZONE_NORMAL] = max_low_pfn;
|
||||||
|
|
||||||
free_area_init_nodes(max_zone_pfns);
|
free_area_init(max_zone_pfns);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void setup_zero_page(void)
|
static void setup_zero_page(void)
|
||||||
@@ -514,6 +515,8 @@ void mark_rodata_ro(void)
|
|||||||
set_memory_ro(rodata_start, (data_start - rodata_start) >> PAGE_SHIFT);
|
set_memory_ro(rodata_start, (data_start - rodata_start) >> PAGE_SHIFT);
|
||||||
set_memory_nx(rodata_start, (data_start - rodata_start) >> PAGE_SHIFT);
|
set_memory_nx(rodata_start, (data_start - rodata_start) >> PAGE_SHIFT);
|
||||||
set_memory_nx(data_start, (max_low - data_start) >> PAGE_SHIFT);
|
set_memory_nx(data_start, (max_low - data_start) >> PAGE_SHIFT);
|
||||||
|
|
||||||
|
debug_checkwx();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@@ -162,7 +162,6 @@ config S390
|
|||||||
select HAVE_LIVEPATCH
|
select HAVE_LIVEPATCH
|
||||||
select HAVE_PERF_REGS
|
select HAVE_PERF_REGS
|
||||||
select HAVE_PERF_USER_STACK_DUMP
|
select HAVE_PERF_USER_STACK_DUMP
|
||||||
select HAVE_MEMBLOCK_NODE_MAP
|
|
||||||
select HAVE_MEMBLOCK_PHYS_MAP
|
select HAVE_MEMBLOCK_PHYS_MAP
|
||||||
select MMU_GATHER_NO_GATHER
|
select MMU_GATHER_NO_GATHER
|
||||||
select HAVE_MOD_ARCH_SPECIFIC
|
select HAVE_MOD_ARCH_SPECIFIC
|
||||||
|
@@ -21,13 +21,6 @@ pte_t huge_ptep_get(pte_t *ptep);
|
|||||||
pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
|
pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
|
||||||
unsigned long addr, pte_t *ptep);
|
unsigned long addr, pte_t *ptep);
|
||||||
|
|
||||||
static inline bool is_hugepage_only_range(struct mm_struct *mm,
|
|
||||||
unsigned long addr,
|
|
||||||
unsigned long len)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the arch doesn't supply something else, assume that hugepage
|
* If the arch doesn't supply something else, assume that hugepage
|
||||||
* size aligned regions are ok without further preparation.
|
* size aligned regions are ok without further preparation.
|
||||||
@@ -46,6 +39,7 @@ static inline void arch_clear_hugepage_flags(struct page *page)
|
|||||||
{
|
{
|
||||||
clear_bit(PG_arch_1, &page->flags);
|
clear_bit(PG_arch_1, &page->flags);
|
||||||
}
|
}
|
||||||
|
#define arch_clear_hugepage_flags arch_clear_hugepage_flags
|
||||||
|
|
||||||
static inline void huge_pte_clear(struct mm_struct *mm, unsigned long addr,
|
static inline void huge_pte_clear(struct mm_struct *mm, unsigned long addr,
|
||||||
pte_t *ptep, unsigned long sz)
|
pte_t *ptep, unsigned long sz)
|
||||||
|
@@ -254,25 +254,15 @@ follow_huge_pud(struct mm_struct *mm, unsigned long address,
|
|||||||
return pud_page(*pud) + ((address & ~PUD_MASK) >> PAGE_SHIFT);
|
return pud_page(*pud) + ((address & ~PUD_MASK) >> PAGE_SHIFT);
|
||||||
}
|
}
|
||||||
|
|
||||||
static __init int setup_hugepagesz(char *opt)
|
bool __init arch_hugetlb_valid_size(unsigned long size)
|
||||||
{
|
{
|
||||||
unsigned long size;
|
if (MACHINE_HAS_EDAT1 && size == PMD_SIZE)
|
||||||
char *string = opt;
|
return true;
|
||||||
|
else if (MACHINE_HAS_EDAT2 && size == PUD_SIZE)
|
||||||
size = memparse(opt, &opt);
|
return true;
|
||||||
if (MACHINE_HAS_EDAT1 && size == PMD_SIZE) {
|
else
|
||||||
hugetlb_add_hstate(PMD_SHIFT - PAGE_SHIFT);
|
return false;
|
||||||
} else if (MACHINE_HAS_EDAT2 && size == PUD_SIZE) {
|
|
||||||
hugetlb_add_hstate(PUD_SHIFT - PAGE_SHIFT);
|
|
||||||
} else {
|
|
||||||
hugetlb_bad_size();
|
|
||||||
pr_err("hugepagesz= specifies an unsupported page size %s\n",
|
|
||||||
string);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
__setup("hugepagesz=", setup_hugepagesz);
|
|
||||||
|
|
||||||
static unsigned long hugetlb_get_unmapped_area_bottomup(struct file *file,
|
static unsigned long hugetlb_get_unmapped_area_bottomup(struct file *file,
|
||||||
unsigned long addr, unsigned long len,
|
unsigned long addr, unsigned long len,
|
||||||
|
@@ -122,7 +122,7 @@ void __init paging_init(void)
|
|||||||
memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
|
memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
|
||||||
max_zone_pfns[ZONE_DMA] = PFN_DOWN(MAX_DMA_ADDRESS);
|
max_zone_pfns[ZONE_DMA] = PFN_DOWN(MAX_DMA_ADDRESS);
|
||||||
max_zone_pfns[ZONE_NORMAL] = max_low_pfn;
|
max_zone_pfns[ZONE_NORMAL] = max_low_pfn;
|
||||||
free_area_init_nodes(max_zone_pfns);
|
free_area_init(max_zone_pfns);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mark_rodata_ro(void)
|
void mark_rodata_ro(void)
|
||||||
|
@@ -9,7 +9,6 @@ config SUPERH
|
|||||||
select CLKDEV_LOOKUP
|
select CLKDEV_LOOKUP
|
||||||
select DMA_DECLARE_COHERENT
|
select DMA_DECLARE_COHERENT
|
||||||
select HAVE_IDE if HAS_IOPORT_MAP
|
select HAVE_IDE if HAS_IOPORT_MAP
|
||||||
select HAVE_MEMBLOCK_NODE_MAP
|
|
||||||
select HAVE_OPROFILE
|
select HAVE_OPROFILE
|
||||||
select HAVE_ARCH_TRACEHOOK
|
select HAVE_ARCH_TRACEHOOK
|
||||||
select HAVE_PERF_EVENTS
|
select HAVE_PERF_EVENTS
|
||||||
|
@@ -5,12 +5,6 @@
|
|||||||
#include <asm/cacheflush.h>
|
#include <asm/cacheflush.h>
|
||||||
#include <asm/page.h>
|
#include <asm/page.h>
|
||||||
|
|
||||||
static inline int is_hugepage_only_range(struct mm_struct *mm,
|
|
||||||
unsigned long addr,
|
|
||||||
unsigned long len) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the arch doesn't supply something else, assume that hugepage
|
* If the arch doesn't supply something else, assume that hugepage
|
||||||
* size aligned regions are ok without further preparation.
|
* size aligned regions are ok without further preparation.
|
||||||
@@ -36,6 +30,7 @@ static inline void arch_clear_hugepage_flags(struct page *page)
|
|||||||
{
|
{
|
||||||
clear_bit(PG_dcache_clean, &page->flags);
|
clear_bit(PG_dcache_clean, &page->flags);
|
||||||
}
|
}
|
||||||
|
#define arch_clear_hugepage_flags arch_clear_hugepage_flags
|
||||||
|
|
||||||
#include <asm-generic/hugetlb.h>
|
#include <asm-generic/hugetlb.h>
|
||||||
|
|
||||||
|
@@ -334,7 +334,7 @@ void __init paging_init(void)
|
|||||||
|
|
||||||
memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
|
memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
|
||||||
max_zone_pfns[ZONE_NORMAL] = max_low_pfn;
|
max_zone_pfns[ZONE_NORMAL] = max_low_pfn;
|
||||||
free_area_init_nodes(max_zone_pfns);
|
free_area_init(max_zone_pfns);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int mem_init_done = 0;
|
unsigned int mem_init_done = 0;
|
||||||
|
@@ -65,7 +65,6 @@ config SPARC64
|
|||||||
select HAVE_KRETPROBES
|
select HAVE_KRETPROBES
|
||||||
select HAVE_KPROBES
|
select HAVE_KPROBES
|
||||||
select MMU_GATHER_RCU_TABLE_FREE if SMP
|
select MMU_GATHER_RCU_TABLE_FREE if SMP
|
||||||
select HAVE_MEMBLOCK_NODE_MAP
|
|
||||||
select HAVE_ARCH_TRANSPARENT_HUGEPAGE
|
select HAVE_ARCH_TRANSPARENT_HUGEPAGE
|
||||||
select HAVE_DYNAMIC_FTRACE
|
select HAVE_DYNAMIC_FTRACE
|
||||||
select HAVE_FTRACE_MCOUNT_RECORD
|
select HAVE_FTRACE_MCOUNT_RECORD
|
||||||
@@ -287,15 +286,6 @@ config NODES_SHIFT
|
|||||||
Specify the maximum number of NUMA Nodes available on the target
|
Specify the maximum number of NUMA Nodes available on the target
|
||||||
system. Increases memory reserved to accommodate various tables.
|
system. Increases memory reserved to accommodate various tables.
|
||||||
|
|
||||||
# Some NUMA nodes have memory ranges that span
|
|
||||||
# other nodes. Even though a pfn is valid and
|
|
||||||
# between a node's start and end pfns, it may not
|
|
||||||
# reside on that node. See memmap_init_zone()
|
|
||||||
# for details.
|
|
||||||
config NODES_SPAN_OTHER_NODES
|
|
||||||
def_bool y
|
|
||||||
depends on NEED_MULTIPLE_NODES
|
|
||||||
|
|
||||||
config ARCH_SPARSEMEM_ENABLE
|
config ARCH_SPARSEMEM_ENABLE
|
||||||
def_bool y if SPARC64
|
def_bool y if SPARC64
|
||||||
select SPARSEMEM_VMEMMAP_ENABLE
|
select SPARSEMEM_VMEMMAP_ENABLE
|
||||||
|
@@ -20,12 +20,6 @@ void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
|
|||||||
pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
|
pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
|
||||||
pte_t *ptep);
|
pte_t *ptep);
|
||||||
|
|
||||||
static inline int is_hugepage_only_range(struct mm_struct *mm,
|
|
||||||
unsigned long addr,
|
|
||||||
unsigned long len) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define __HAVE_ARCH_HUGE_PTEP_CLEAR_FLUSH
|
#define __HAVE_ARCH_HUGE_PTEP_CLEAR_FLUSH
|
||||||
static inline void huge_ptep_clear_flush(struct vm_area_struct *vma,
|
static inline void huge_ptep_clear_flush(struct vm_area_struct *vma,
|
||||||
unsigned long addr, pte_t *ptep)
|
unsigned long addr, pte_t *ptep)
|
||||||
@@ -53,10 +47,6 @@ static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma,
|
|||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void arch_clear_hugepage_flags(struct page *page)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
#define __HAVE_ARCH_HUGETLB_FREE_PGD_RANGE
|
#define __HAVE_ARCH_HUGETLB_FREE_PGD_RANGE
|
||||||
void hugetlb_free_pgd_range(struct mmu_gather *tlb, unsigned long addr,
|
void hugetlb_free_pgd_range(struct mmu_gather *tlb, unsigned long addr,
|
||||||
unsigned long end, unsigned long floor,
|
unsigned long end, unsigned long floor,
|
||||||
|
@@ -193,6 +193,7 @@ unsigned long __init bootmem_init(unsigned long *pages_avail)
|
|||||||
/* Reserve the kernel text/data/bss. */
|
/* Reserve the kernel text/data/bss. */
|
||||||
size = (start_pfn << PAGE_SHIFT) - phys_base;
|
size = (start_pfn << PAGE_SHIFT) - phys_base;
|
||||||
memblock_reserve(phys_base, size);
|
memblock_reserve(phys_base, size);
|
||||||
|
memblock_add(phys_base, size);
|
||||||
|
|
||||||
size = memblock_phys_mem_size() - memblock_reserved_size();
|
size = memblock_phys_mem_size() - memblock_reserved_size();
|
||||||
*pages_avail = (size >> PAGE_SHIFT) - high_pages;
|
*pages_avail = (size >> PAGE_SHIFT) - high_pages;
|
||||||
|
@@ -325,23 +325,12 @@ static void __update_mmu_tsb_insert(struct mm_struct *mm, unsigned long tsb_inde
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_HUGETLB_PAGE
|
#ifdef CONFIG_HUGETLB_PAGE
|
||||||
static void __init add_huge_page_size(unsigned long size)
|
|
||||||
{
|
|
||||||
unsigned int order;
|
|
||||||
|
|
||||||
if (size_to_hstate(size))
|
|
||||||
return;
|
|
||||||
|
|
||||||
order = ilog2(size) - PAGE_SHIFT;
|
|
||||||
hugetlb_add_hstate(order);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int __init hugetlbpage_init(void)
|
static int __init hugetlbpage_init(void)
|
||||||
{
|
{
|
||||||
add_huge_page_size(1UL << HPAGE_64K_SHIFT);
|
hugetlb_add_hstate(HPAGE_64K_SHIFT - PAGE_SHIFT);
|
||||||
add_huge_page_size(1UL << HPAGE_SHIFT);
|
hugetlb_add_hstate(HPAGE_SHIFT - PAGE_SHIFT);
|
||||||
add_huge_page_size(1UL << HPAGE_256MB_SHIFT);
|
hugetlb_add_hstate(HPAGE_256MB_SHIFT - PAGE_SHIFT);
|
||||||
add_huge_page_size(1UL << HPAGE_2GB_SHIFT);
|
hugetlb_add_hstate(HPAGE_2GB_SHIFT - PAGE_SHIFT);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -360,16 +349,11 @@ static void __init pud_huge_patch(void)
|
|||||||
__asm__ __volatile__("flush %0" : : "r" (addr));
|
__asm__ __volatile__("flush %0" : : "r" (addr));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __init setup_hugepagesz(char *string)
|
bool __init arch_hugetlb_valid_size(unsigned long size)
|
||||||
{
|
{
|
||||||
unsigned long long hugepage_size;
|
unsigned int hugepage_shift = ilog2(size);
|
||||||
unsigned int hugepage_shift;
|
|
||||||
unsigned short hv_pgsz_idx;
|
unsigned short hv_pgsz_idx;
|
||||||
unsigned int hv_pgsz_mask;
|
unsigned int hv_pgsz_mask;
|
||||||
int rc = 0;
|
|
||||||
|
|
||||||
hugepage_size = memparse(string, &string);
|
|
||||||
hugepage_shift = ilog2(hugepage_size);
|
|
||||||
|
|
||||||
switch (hugepage_shift) {
|
switch (hugepage_shift) {
|
||||||
case HPAGE_16GB_SHIFT:
|
case HPAGE_16GB_SHIFT:
|
||||||
@@ -397,20 +381,11 @@ static int __init setup_hugepagesz(char *string)
|
|||||||
hv_pgsz_mask = 0;
|
hv_pgsz_mask = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((hv_pgsz_mask & cpu_pgsz_mask) == 0U) {
|
if ((hv_pgsz_mask & cpu_pgsz_mask) == 0U)
|
||||||
hugetlb_bad_size();
|
return false;
|
||||||
pr_err("hugepagesz=%llu not supported by MMU.\n",
|
|
||||||
hugepage_size);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
add_huge_page_size(hugepage_size);
|
return true;
|
||||||
rc = 1;
|
|
||||||
|
|
||||||
out:
|
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
__setup("hugepagesz=", setup_hugepagesz);
|
|
||||||
#endif /* CONFIG_HUGETLB_PAGE */
|
#endif /* CONFIG_HUGETLB_PAGE */
|
||||||
|
|
||||||
void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *ptep)
|
void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *ptep)
|
||||||
@@ -2488,7 +2463,7 @@ void __init paging_init(void)
|
|||||||
|
|
||||||
max_zone_pfns[ZONE_NORMAL] = end_pfn;
|
max_zone_pfns[ZONE_NORMAL] = end_pfn;
|
||||||
|
|
||||||
free_area_init_nodes(max_zone_pfns);
|
free_area_init(max_zone_pfns);
|
||||||
}
|
}
|
||||||
|
|
||||||
printk("Booting Linux...\n");
|
printk("Booting Linux...\n");
|
||||||
|
@@ -1008,24 +1008,13 @@ void __init srmmu_paging_init(void)
|
|||||||
kmap_init();
|
kmap_init();
|
||||||
|
|
||||||
{
|
{
|
||||||
unsigned long zones_size[MAX_NR_ZONES];
|
unsigned long max_zone_pfn[MAX_NR_ZONES] = { 0 };
|
||||||
unsigned long zholes_size[MAX_NR_ZONES];
|
|
||||||
unsigned long npages;
|
|
||||||
int znum;
|
|
||||||
|
|
||||||
for (znum = 0; znum < MAX_NR_ZONES; znum++)
|
max_zone_pfn[ZONE_DMA] = max_low_pfn;
|
||||||
zones_size[znum] = zholes_size[znum] = 0;
|
max_zone_pfn[ZONE_NORMAL] = max_low_pfn;
|
||||||
|
max_zone_pfn[ZONE_HIGHMEM] = highend_pfn;
|
||||||
|
|
||||||
npages = max_low_pfn - pfn_base;
|
free_area_init(max_zone_pfn);
|
||||||
|
|
||||||
zones_size[ZONE_DMA] = npages;
|
|
||||||
zholes_size[ZONE_DMA] = npages - pages_avail;
|
|
||||||
|
|
||||||
npages = highend_pfn - max_low_pfn;
|
|
||||||
zones_size[ZONE_HIGHMEM] = npages;
|
|
||||||
zholes_size[ZONE_HIGHMEM] = npages - calc_highpages();
|
|
||||||
|
|
||||||
free_area_init_node(0, zones_size, pfn_base, zholes_size);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -158,8 +158,8 @@ static void __init fixaddr_user_init( void)
|
|||||||
|
|
||||||
void __init paging_init(void)
|
void __init paging_init(void)
|
||||||
{
|
{
|
||||||
unsigned long zones_size[MAX_NR_ZONES], vaddr;
|
unsigned long max_zone_pfn[MAX_NR_ZONES] = { 0 };
|
||||||
int i;
|
unsigned long vaddr;
|
||||||
|
|
||||||
empty_zero_page = (unsigned long *) memblock_alloc_low(PAGE_SIZE,
|
empty_zero_page = (unsigned long *) memblock_alloc_low(PAGE_SIZE,
|
||||||
PAGE_SIZE);
|
PAGE_SIZE);
|
||||||
@@ -167,12 +167,8 @@ void __init paging_init(void)
|
|||||||
panic("%s: Failed to allocate %lu bytes align=%lx\n",
|
panic("%s: Failed to allocate %lu bytes align=%lx\n",
|
||||||
__func__, PAGE_SIZE, PAGE_SIZE);
|
__func__, PAGE_SIZE, PAGE_SIZE);
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(zones_size); i++)
|
max_zone_pfn[ZONE_NORMAL] = end_iomem >> PAGE_SHIFT;
|
||||||
zones_size[i] = 0;
|
free_area_init(max_zone_pfn);
|
||||||
|
|
||||||
zones_size[ZONE_NORMAL] = (end_iomem >> PAGE_SHIFT) -
|
|
||||||
(uml_physmem >> PAGE_SHIFT);
|
|
||||||
free_area_init(zones_size);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Fixed mappings, only the page table structure has to be
|
* Fixed mappings, only the page table structure has to be
|
||||||
|
@@ -60,7 +60,7 @@
|
|||||||
#ifndef __ASSEMBLY__
|
#ifndef __ASSEMBLY__
|
||||||
|
|
||||||
#ifndef arch_adjust_zones
|
#ifndef arch_adjust_zones
|
||||||
#define arch_adjust_zones(size, holes) do { } while (0)
|
#define arch_adjust_zones(max_zone_pfn) do { } while (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -25,10 +25,10 @@
|
|||||||
|
|
||||||
#if !defined(__ASSEMBLY__) && defined(CONFIG_PCI)
|
#if !defined(__ASSEMBLY__) && defined(CONFIG_PCI)
|
||||||
|
|
||||||
void puv3_pci_adjust_zones(unsigned long *size, unsigned long *holes);
|
void puv3_pci_adjust_zones(unsigned long *max_zone_pfn);
|
||||||
|
|
||||||
#define arch_adjust_zones(size, holes) \
|
#define arch_adjust_zones(max_zone_pfn) \
|
||||||
puv3_pci_adjust_zones(size, holes)
|
puv3_pci_adjust_zones(max_zone_pfn)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@@ -133,21 +133,11 @@ static int pci_puv3_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
|
|||||||
* This is really ugly and we need a better way of specifying
|
* This is really ugly and we need a better way of specifying
|
||||||
* DMA-capable regions of memory.
|
* DMA-capable regions of memory.
|
||||||
*/
|
*/
|
||||||
void __init puv3_pci_adjust_zones(unsigned long *zone_size,
|
void __init puv3_pci_adjust_zones(unsigned long max_zone_pfn)
|
||||||
unsigned long *zhole_size)
|
|
||||||
{
|
{
|
||||||
unsigned int sz = SZ_128M >> PAGE_SHIFT;
|
unsigned int sz = SZ_128M >> PAGE_SHIFT;
|
||||||
|
|
||||||
/*
|
max_zone_pfn[ZONE_DMA] = sz;
|
||||||
* Only adjust if > 128M on current system
|
|
||||||
*/
|
|
||||||
if (zone_size[0] <= sz)
|
|
||||||
return;
|
|
||||||
|
|
||||||
zone_size[1] = zone_size[0] - sz;
|
|
||||||
zone_size[0] = sz;
|
|
||||||
zhole_size[1] = zhole_size[0];
|
|
||||||
zhole_size[0] = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -61,46 +61,21 @@ static void __init find_limits(unsigned long *min, unsigned long *max_low,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __init uc32_bootmem_free(unsigned long min, unsigned long max_low,
|
static void __init uc32_bootmem_free(unsigned long max_low)
|
||||||
unsigned long max_high)
|
|
||||||
{
|
{
|
||||||
unsigned long zone_size[MAX_NR_ZONES], zhole_size[MAX_NR_ZONES];
|
unsigned long max_zone_pfn[MAX_NR_ZONES] = { 0 };
|
||||||
struct memblock_region *reg;
|
|
||||||
|
|
||||||
/*
|
max_zone_pfn[ZONE_DMA] = max_low;
|
||||||
* initialise the zones.
|
max_zone_pfn[ZONE_NORMAL] = max_low;
|
||||||
*/
|
|
||||||
memset(zone_size, 0, sizeof(zone_size));
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The memory size has already been determined. If we need
|
|
||||||
* to do anything fancy with the allocation of this memory
|
|
||||||
* to the zones, now is the time to do it.
|
|
||||||
*/
|
|
||||||
zone_size[0] = max_low - min;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Calculate the size of the holes.
|
|
||||||
* holes = node_size - sum(bank_sizes)
|
|
||||||
*/
|
|
||||||
memcpy(zhole_size, zone_size, sizeof(zhole_size));
|
|
||||||
for_each_memblock(memory, reg) {
|
|
||||||
unsigned long start = memblock_region_memory_base_pfn(reg);
|
|
||||||
unsigned long end = memblock_region_memory_end_pfn(reg);
|
|
||||||
|
|
||||||
if (start < max_low) {
|
|
||||||
unsigned long low_end = min(end, max_low);
|
|
||||||
zhole_size[0] -= low_end - start;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Adjust the sizes according to any special requirements for
|
* Adjust the sizes according to any special requirements for
|
||||||
* this machine type.
|
* this machine type.
|
||||||
|
* This might lower ZONE_DMA limit.
|
||||||
*/
|
*/
|
||||||
arch_adjust_zones(zone_size, zhole_size);
|
arch_adjust_zones(max_zone_pfn);
|
||||||
|
|
||||||
free_area_init_node(0, zone_size, min, zhole_size);
|
free_area_init(max_zone_pfn);
|
||||||
}
|
}
|
||||||
|
|
||||||
int pfn_valid(unsigned long pfn)
|
int pfn_valid(unsigned long pfn)
|
||||||
@@ -176,11 +151,11 @@ void __init bootmem_init(void)
|
|||||||
sparse_init();
|
sparse_init();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now free the memory - free_area_init_node needs
|
* Now free the memory - free_area_init needs
|
||||||
* the sparse mem_map arrays initialized by sparse_init()
|
* the sparse mem_map arrays initialized by sparse_init()
|
||||||
* for memmap_init_zone(), otherwise all PFNs are invalid.
|
* for memmap_init_zone(), otherwise all PFNs are invalid.
|
||||||
*/
|
*/
|
||||||
uc32_bootmem_free(min, max_low, max_high);
|
uc32_bootmem_free(max_low);
|
||||||
|
|
||||||
high_memory = __va((max_low << PAGE_SHIFT) - 1) + 1;
|
high_memory = __va((max_low << PAGE_SHIFT) - 1) + 1;
|
||||||
|
|
||||||
|
@@ -82,6 +82,7 @@ config X86
|
|||||||
select ARCH_HAS_SYNC_CORE_BEFORE_USERMODE
|
select ARCH_HAS_SYNC_CORE_BEFORE_USERMODE
|
||||||
select ARCH_HAS_SYSCALL_WRAPPER
|
select ARCH_HAS_SYSCALL_WRAPPER
|
||||||
select ARCH_HAS_UBSAN_SANITIZE_ALL
|
select ARCH_HAS_UBSAN_SANITIZE_ALL
|
||||||
|
select ARCH_HAS_DEBUG_WX
|
||||||
select ARCH_HAVE_NMI_SAFE_CMPXCHG
|
select ARCH_HAVE_NMI_SAFE_CMPXCHG
|
||||||
select ARCH_MIGHT_HAVE_ACPI_PDC if ACPI
|
select ARCH_MIGHT_HAVE_ACPI_PDC if ACPI
|
||||||
select ARCH_MIGHT_HAVE_PC_PARPORT
|
select ARCH_MIGHT_HAVE_PC_PARPORT
|
||||||
@@ -193,7 +194,6 @@ config X86
|
|||||||
select HAVE_KRETPROBES
|
select HAVE_KRETPROBES
|
||||||
select HAVE_KVM
|
select HAVE_KVM
|
||||||
select HAVE_LIVEPATCH if X86_64
|
select HAVE_LIVEPATCH if X86_64
|
||||||
select HAVE_MEMBLOCK_NODE_MAP
|
|
||||||
select HAVE_MIXED_BREAKPOINTS_REGS
|
select HAVE_MIXED_BREAKPOINTS_REGS
|
||||||
select HAVE_MOD_ARCH_SPECIFIC
|
select HAVE_MOD_ARCH_SPECIFIC
|
||||||
select HAVE_MOVE_PMD
|
select HAVE_MOVE_PMD
|
||||||
@@ -1585,15 +1585,6 @@ config X86_64_ACPI_NUMA
|
|||||||
---help---
|
---help---
|
||||||
Enable ACPI SRAT based node topology detection.
|
Enable ACPI SRAT based node topology detection.
|
||||||
|
|
||||||
# Some NUMA nodes have memory ranges that span
|
|
||||||
# other nodes. Even though a pfn is valid and
|
|
||||||
# between a node's start and end pfns, it may not
|
|
||||||
# reside on that node. See memmap_init_zone()
|
|
||||||
# for details.
|
|
||||||
config NODES_SPAN_OTHER_NODES
|
|
||||||
def_bool y
|
|
||||||
depends on X86_64_ACPI_NUMA
|
|
||||||
|
|
||||||
config NUMA_EMU
|
config NUMA_EMU
|
||||||
bool "NUMA emulation"
|
bool "NUMA emulation"
|
||||||
depends on NUMA
|
depends on NUMA
|
||||||
|
@@ -72,33 +72,6 @@ config EFI_PGT_DUMP
|
|||||||
issues with the mapping of the EFI runtime regions into that
|
issues with the mapping of the EFI runtime regions into that
|
||||||
table.
|
table.
|
||||||
|
|
||||||
config DEBUG_WX
|
|
||||||
bool "Warn on W+X mappings at boot"
|
|
||||||
select PTDUMP_CORE
|
|
||||||
---help---
|
|
||||||
Generate a warning if any W+X mappings are found at boot.
|
|
||||||
|
|
||||||
This is useful for discovering cases where the kernel is leaving
|
|
||||||
W+X mappings after applying NX, as such mappings are a security risk.
|
|
||||||
|
|
||||||
Look for a message in dmesg output like this:
|
|
||||||
|
|
||||||
x86/mm: Checked W+X mappings: passed, no W+X pages found.
|
|
||||||
|
|
||||||
or like this, if the check failed:
|
|
||||||
|
|
||||||
x86/mm: Checked W+X mappings: FAILED, <N> W+X pages found.
|
|
||||||
|
|
||||||
Note that even if the check fails, your kernel is possibly
|
|
||||||
still fine, as W+X mappings are not a security hole in
|
|
||||||
themselves, what they do is that they make the exploitation
|
|
||||||
of other unfixed kernel bugs easier.
|
|
||||||
|
|
||||||
There is no runtime or memory usage effect of this option
|
|
||||||
once the kernel has booted up - it's a one time check.
|
|
||||||
|
|
||||||
If in doubt, say "Y".
|
|
||||||
|
|
||||||
config DEBUG_TLBFLUSH
|
config DEBUG_TLBFLUSH
|
||||||
bool "Set upper limit of TLB entries to flush one-by-one"
|
bool "Set upper limit of TLB entries to flush one-by-one"
|
||||||
depends on DEBUG_KERNEL
|
depends on DEBUG_KERNEL
|
||||||
|
@@ -7,14 +7,4 @@
|
|||||||
|
|
||||||
#define hugepages_supported() boot_cpu_has(X86_FEATURE_PSE)
|
#define hugepages_supported() boot_cpu_has(X86_FEATURE_PSE)
|
||||||
|
|
||||||
static inline int is_hugepage_only_range(struct mm_struct *mm,
|
|
||||||
unsigned long addr,
|
|
||||||
unsigned long len) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void arch_clear_hugepage_flags(struct page *page)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* _ASM_X86_HUGETLB_H */
|
#endif /* _ASM_X86_HUGETLB_H */
|
||||||
|
@@ -624,7 +624,7 @@ static inline pud_t pfn_pud(unsigned long page_nr, pgprot_t pgprot)
|
|||||||
return __pud(pfn | check_pgprot(pgprot));
|
return __pud(pfn | check_pgprot(pgprot));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline pmd_t pmd_mknotpresent(pmd_t pmd)
|
static inline pmd_t pmd_mkinvalid(pmd_t pmd)
|
||||||
{
|
{
|
||||||
return pfn_pmd(pmd_pfn(pmd),
|
return pfn_pmd(pmd_pfn(pmd),
|
||||||
__pgprot(pmd_flags(pmd) & ~(_PAGE_PRESENT|_PAGE_PROTNONE)));
|
__pgprot(pmd_flags(pmd) & ~(_PAGE_PRESENT|_PAGE_PROTNONE)));
|
||||||
|
@@ -181,28 +181,21 @@ get_unmapped_area:
|
|||||||
#endif /* CONFIG_HUGETLB_PAGE */
|
#endif /* CONFIG_HUGETLB_PAGE */
|
||||||
|
|
||||||
#ifdef CONFIG_X86_64
|
#ifdef CONFIG_X86_64
|
||||||
static __init int setup_hugepagesz(char *opt)
|
bool __init arch_hugetlb_valid_size(unsigned long size)
|
||||||
{
|
{
|
||||||
unsigned long ps = memparse(opt, &opt);
|
if (size == PMD_SIZE)
|
||||||
if (ps == PMD_SIZE) {
|
return true;
|
||||||
hugetlb_add_hstate(PMD_SHIFT - PAGE_SHIFT);
|
else if (size == PUD_SIZE && boot_cpu_has(X86_FEATURE_GBPAGES))
|
||||||
} else if (ps == PUD_SIZE && boot_cpu_has(X86_FEATURE_GBPAGES)) {
|
return true;
|
||||||
hugetlb_add_hstate(PUD_SHIFT - PAGE_SHIFT);
|
else
|
||||||
} else {
|
return false;
|
||||||
hugetlb_bad_size();
|
|
||||||
printk(KERN_ERR "hugepagesz: Unsupported page size %lu M\n",
|
|
||||||
ps >> 20);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
__setup("hugepagesz=", setup_hugepagesz);
|
|
||||||
|
|
||||||
#ifdef CONFIG_CONTIG_ALLOC
|
#ifdef CONFIG_CONTIG_ALLOC
|
||||||
static __init int gigantic_pages_init(void)
|
static __init int gigantic_pages_init(void)
|
||||||
{
|
{
|
||||||
/* With compaction or CMA we can allocate gigantic pages at runtime */
|
/* With compaction or CMA we can allocate gigantic pages at runtime */
|
||||||
if (boot_cpu_has(X86_FEATURE_GBPAGES) && !size_to_hstate(1UL << PUD_SHIFT))
|
if (boot_cpu_has(X86_FEATURE_GBPAGES))
|
||||||
hugetlb_add_hstate(PUD_SHIFT - PAGE_SHIFT);
|
hugetlb_add_hstate(PUD_SHIFT - PAGE_SHIFT);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@@ -947,7 +947,7 @@ void __init zone_sizes_init(void)
|
|||||||
max_zone_pfns[ZONE_HIGHMEM] = max_pfn;
|
max_zone_pfns[ZONE_HIGHMEM] = max_pfn;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
free_area_init_nodes(max_zone_pfns);
|
free_area_init(max_zone_pfns);
|
||||||
}
|
}
|
||||||
|
|
||||||
__visible DEFINE_PER_CPU_SHARED_ALIGNED(struct tlb_state, cpu_tlbstate) = {
|
__visible DEFINE_PER_CPU_SHARED_ALIGNED(struct tlb_state, cpu_tlbstate) = {
|
||||||
|
@@ -1265,6 +1265,18 @@ void __init mem_init(void)
|
|||||||
mem_init_print_info(NULL);
|
mem_init_print_info(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_DEFERRED_STRUCT_PAGE_INIT
|
||||||
|
int __init deferred_page_init_max_threads(const struct cpumask *node_cpumask)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* More CPUs always led to greater speedups on tested systems, up to
|
||||||
|
* all the nodes' CPUs. Use all since the system is otherwise idle
|
||||||
|
* now.
|
||||||
|
*/
|
||||||
|
return max_t(int, cpumask_weight(node_cpumask), 1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int kernel_set_to_readonly;
|
int kernel_set_to_readonly;
|
||||||
|
|
||||||
void mark_rodata_ro(void)
|
void mark_rodata_ro(void)
|
||||||
|
@@ -130,7 +130,7 @@ static void clear_pmd_presence(pmd_t *pmd, bool clear, pmdval_t *old)
|
|||||||
pmdval_t v = pmd_val(*pmd);
|
pmdval_t v = pmd_val(*pmd);
|
||||||
if (clear) {
|
if (clear) {
|
||||||
*old = v;
|
*old = v;
|
||||||
new_pmd = pmd_mknotpresent(*pmd);
|
new_pmd = pmd_mkinvalid(*pmd);
|
||||||
} else {
|
} else {
|
||||||
/* Presume this has been called with clear==true previously */
|
/* Presume this has been called with clear==true previously */
|
||||||
new_pmd = __pmd(*old);
|
new_pmd = __pmd(*old);
|
||||||
|
@@ -517,8 +517,10 @@ static void __init numa_clear_kernel_node_hotplug(void)
|
|||||||
* reserve specific pages for Sandy Bridge graphics. ]
|
* reserve specific pages for Sandy Bridge graphics. ]
|
||||||
*/
|
*/
|
||||||
for_each_memblock(reserved, mb_region) {
|
for_each_memblock(reserved, mb_region) {
|
||||||
if (mb_region->nid != MAX_NUMNODES)
|
int nid = memblock_get_region_node(mb_region);
|
||||||
node_set(mb_region->nid, reserved_nodemask);
|
|
||||||
|
if (nid != MAX_NUMNODES)
|
||||||
|
node_set(nid, reserved_nodemask);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -735,12 +737,9 @@ void __init x86_numa_init(void)
|
|||||||
|
|
||||||
static void __init init_memory_less_node(int nid)
|
static void __init init_memory_less_node(int nid)
|
||||||
{
|
{
|
||||||
unsigned long zones_size[MAX_NR_ZONES] = {0};
|
|
||||||
unsigned long zholes_size[MAX_NR_ZONES] = {0};
|
|
||||||
|
|
||||||
/* Allocate and initialize node data. Memory-less node is now online.*/
|
/* Allocate and initialize node data. Memory-less node is now online.*/
|
||||||
alloc_node_data(nid);
|
alloc_node_data(nid);
|
||||||
free_area_init_node(nid, zones_size, 0, zholes_size);
|
free_area_init_memoryless_node(nid);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* All zonelists will be built later in start_kernel() after per cpu
|
* All zonelists will be built later in start_kernel() after per cpu
|
||||||
|
@@ -70,13 +70,13 @@ void __init bootmem_init(void)
|
|||||||
void __init zones_init(void)
|
void __init zones_init(void)
|
||||||
{
|
{
|
||||||
/* All pages are DMA-able, so we put them all in the DMA zone. */
|
/* All pages are DMA-able, so we put them all in the DMA zone. */
|
||||||
unsigned long zones_size[MAX_NR_ZONES] = {
|
unsigned long max_zone_pfn[MAX_NR_ZONES] = {
|
||||||
[ZONE_NORMAL] = max_low_pfn - ARCH_PFN_OFFSET,
|
[ZONE_NORMAL] = max_low_pfn,
|
||||||
#ifdef CONFIG_HIGHMEM
|
#ifdef CONFIG_HIGHMEM
|
||||||
[ZONE_HIGHMEM] = max_pfn - max_low_pfn,
|
[ZONE_HIGHMEM] = max_pfn,
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
free_area_init_node(0, zones_size, ARCH_PFN_OFFSET, NULL);
|
free_area_init(max_zone_pfn);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_HIGHMEM
|
#ifdef CONFIG_HIGHMEM
|
||||||
|
@@ -21,6 +21,7 @@
|
|||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
#include <linux/stat.h>
|
#include <linux/stat.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
|
#include <linux/xarray.h>
|
||||||
|
|
||||||
#include <linux/atomic.h>
|
#include <linux/atomic.h>
|
||||||
#include <linux/uaccess.h>
|
#include <linux/uaccess.h>
|
||||||
@@ -74,6 +75,13 @@ static struct bus_type memory_subsys = {
|
|||||||
.offline = memory_subsys_offline,
|
.offline = memory_subsys_offline,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Memory blocks are cached in a local radix tree to avoid
|
||||||
|
* a costly linear search for the corresponding device on
|
||||||
|
* the subsystem bus.
|
||||||
|
*/
|
||||||
|
static DEFINE_XARRAY(memory_blocks);
|
||||||
|
|
||||||
static BLOCKING_NOTIFIER_HEAD(memory_chain);
|
static BLOCKING_NOTIFIER_HEAD(memory_chain);
|
||||||
|
|
||||||
int register_memory_notifier(struct notifier_block *nb)
|
int register_memory_notifier(struct notifier_block *nb)
|
||||||
@@ -489,22 +497,23 @@ int __weak arch_get_memory_phys_device(unsigned long start_pfn)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* A reference for the returned memory block device is acquired. */
|
/*
|
||||||
|
* A reference for the returned memory block device is acquired.
|
||||||
|
*
|
||||||
|
* Called under device_hotplug_lock.
|
||||||
|
*/
|
||||||
static struct memory_block *find_memory_block_by_id(unsigned long block_id)
|
static struct memory_block *find_memory_block_by_id(unsigned long block_id)
|
||||||
{
|
{
|
||||||
struct device *dev;
|
struct memory_block *mem;
|
||||||
|
|
||||||
dev = subsys_find_device_by_id(&memory_subsys, block_id, NULL);
|
mem = xa_load(&memory_blocks, block_id);
|
||||||
return dev ? to_memory_block(dev) : NULL;
|
if (mem)
|
||||||
|
get_device(&mem->dev);
|
||||||
|
return mem;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For now, we have a linear search to go find the appropriate
|
* Called under device_hotplug_lock.
|
||||||
* memory_block corresponding to a particular phys_index. If
|
|
||||||
* this gets to be a real problem, we can always use a radix
|
|
||||||
* tree or something here.
|
|
||||||
*
|
|
||||||
* This could be made generic for all device subsystems.
|
|
||||||
*/
|
*/
|
||||||
struct memory_block *find_memory_block(struct mem_section *section)
|
struct memory_block *find_memory_block(struct mem_section *section)
|
||||||
{
|
{
|
||||||
@@ -548,9 +557,16 @@ int register_memory(struct memory_block *memory)
|
|||||||
memory->dev.offline = memory->state == MEM_OFFLINE;
|
memory->dev.offline = memory->state == MEM_OFFLINE;
|
||||||
|
|
||||||
ret = device_register(&memory->dev);
|
ret = device_register(&memory->dev);
|
||||||
if (ret)
|
if (ret) {
|
||||||
put_device(&memory->dev);
|
put_device(&memory->dev);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
ret = xa_err(xa_store(&memory_blocks, memory->dev.id, memory,
|
||||||
|
GFP_KERNEL));
|
||||||
|
if (ret) {
|
||||||
|
put_device(&memory->dev);
|
||||||
|
device_unregister(&memory->dev);
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -604,6 +620,8 @@ static void unregister_memory(struct memory_block *memory)
|
|||||||
if (WARN_ON_ONCE(memory->dev.bus != &memory_subsys))
|
if (WARN_ON_ONCE(memory->dev.bus != &memory_subsys))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
WARN_ON(xa_erase(&memory_blocks, memory->dev.id) == NULL);
|
||||||
|
|
||||||
/* drop the ref. we got via find_memory_block() */
|
/* drop the ref. we got via find_memory_block() */
|
||||||
put_device(&memory->dev);
|
put_device(&memory->dev);
|
||||||
device_unregister(&memory->dev);
|
device_unregister(&memory->dev);
|
||||||
@@ -750,6 +768,8 @@ void __init memory_dev_init(void)
|
|||||||
*
|
*
|
||||||
* In case func() returns an error, walking is aborted and the error is
|
* In case func() returns an error, walking is aborted and the error is
|
||||||
* returned.
|
* returned.
|
||||||
|
*
|
||||||
|
* Called under device_hotplug_lock.
|
||||||
*/
|
*/
|
||||||
int walk_memory_blocks(unsigned long start, unsigned long size,
|
int walk_memory_blocks(unsigned long start, unsigned long size,
|
||||||
void *arg, walk_memory_blocks_func_t func)
|
void *arg, walk_memory_blocks_func_t func)
|
||||||
|
@@ -471,7 +471,7 @@ __i915_gem_userptr_get_pages_worker(struct work_struct *_work)
|
|||||||
down_read(&mm->mmap_sem);
|
down_read(&mm->mmap_sem);
|
||||||
locked = 1;
|
locked = 1;
|
||||||
}
|
}
|
||||||
ret = get_user_pages_remote
|
ret = pin_user_pages_remote
|
||||||
(work->task, mm,
|
(work->task, mm,
|
||||||
obj->userptr.ptr + pinned * PAGE_SIZE,
|
obj->userptr.ptr + pinned * PAGE_SIZE,
|
||||||
npages - pinned,
|
npages - pinned,
|
||||||
@@ -507,7 +507,7 @@ __i915_gem_userptr_get_pages_worker(struct work_struct *_work)
|
|||||||
}
|
}
|
||||||
mutex_unlock(&obj->mm.lock);
|
mutex_unlock(&obj->mm.lock);
|
||||||
|
|
||||||
release_pages(pvec, pinned);
|
unpin_user_pages(pvec, pinned);
|
||||||
kvfree(pvec);
|
kvfree(pvec);
|
||||||
|
|
||||||
i915_gem_object_put(obj);
|
i915_gem_object_put(obj);
|
||||||
@@ -564,6 +564,7 @@ static int i915_gem_userptr_get_pages(struct drm_i915_gem_object *obj)
|
|||||||
struct sg_table *pages;
|
struct sg_table *pages;
|
||||||
bool active;
|
bool active;
|
||||||
int pinned;
|
int pinned;
|
||||||
|
unsigned int gup_flags = 0;
|
||||||
|
|
||||||
/* If userspace should engineer that these pages are replaced in
|
/* If userspace should engineer that these pages are replaced in
|
||||||
* the vma between us binding this page into the GTT and completion
|
* the vma between us binding this page into the GTT and completion
|
||||||
@@ -606,12 +607,15 @@ static int i915_gem_userptr_get_pages(struct drm_i915_gem_object *obj)
|
|||||||
*
|
*
|
||||||
* We may or may not care.
|
* We may or may not care.
|
||||||
*/
|
*/
|
||||||
if (pvec) /* defer to worker if malloc fails */
|
if (pvec) {
|
||||||
pinned = __get_user_pages_fast(obj->userptr.ptr,
|
/* defer to worker if malloc fails */
|
||||||
num_pages,
|
if (!i915_gem_object_is_readonly(obj))
|
||||||
!i915_gem_object_is_readonly(obj),
|
gup_flags |= FOLL_WRITE;
|
||||||
|
pinned = pin_user_pages_fast_only(obj->userptr.ptr,
|
||||||
|
num_pages, gup_flags,
|
||||||
pvec);
|
pvec);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
active = false;
|
active = false;
|
||||||
if (pinned < 0) {
|
if (pinned < 0) {
|
||||||
@@ -628,7 +632,7 @@ static int i915_gem_userptr_get_pages(struct drm_i915_gem_object *obj)
|
|||||||
__i915_gem_userptr_set_active(obj, true);
|
__i915_gem_userptr_set_active(obj, true);
|
||||||
|
|
||||||
if (IS_ERR(pages))
|
if (IS_ERR(pages))
|
||||||
release_pages(pvec, pinned);
|
unpin_user_pages(pvec, pinned);
|
||||||
kvfree(pvec);
|
kvfree(pvec);
|
||||||
|
|
||||||
return PTR_ERR_OR_ZERO(pages);
|
return PTR_ERR_OR_ZERO(pages);
|
||||||
@@ -683,7 +687,7 @@ i915_gem_userptr_put_pages(struct drm_i915_gem_object *obj,
|
|||||||
}
|
}
|
||||||
|
|
||||||
mark_page_accessed(page);
|
mark_page_accessed(page);
|
||||||
put_page(page);
|
unpin_user_page(page);
|
||||||
}
|
}
|
||||||
obj->mm.dirty = false;
|
obj->mm.dirty = false;
|
||||||
|
|
||||||
|
@@ -4162,7 +4162,7 @@ cifs_readv_complete(struct work_struct *work)
|
|||||||
for (i = 0; i < rdata->nr_pages; i++) {
|
for (i = 0; i < rdata->nr_pages; i++) {
|
||||||
struct page *page = rdata->pages[i];
|
struct page *page = rdata->pages[i];
|
||||||
|
|
||||||
lru_cache_add_file(page);
|
lru_cache_add(page);
|
||||||
|
|
||||||
if (rdata->result == 0 ||
|
if (rdata->result == 0 ||
|
||||||
(rdata->result == -EAGAIN && got_bytes)) {
|
(rdata->result == -EAGAIN && got_bytes)) {
|
||||||
@@ -4232,7 +4232,7 @@ readpages_fill_pages(struct TCP_Server_Info *server,
|
|||||||
* fill them until the writes are flushed.
|
* fill them until the writes are flushed.
|
||||||
*/
|
*/
|
||||||
zero_user(page, 0, PAGE_SIZE);
|
zero_user(page, 0, PAGE_SIZE);
|
||||||
lru_cache_add_file(page);
|
lru_cache_add(page);
|
||||||
flush_dcache_page(page);
|
flush_dcache_page(page);
|
||||||
SetPageUptodate(page);
|
SetPageUptodate(page);
|
||||||
unlock_page(page);
|
unlock_page(page);
|
||||||
@@ -4242,7 +4242,7 @@ readpages_fill_pages(struct TCP_Server_Info *server,
|
|||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
/* no need to hold page hostage */
|
/* no need to hold page hostage */
|
||||||
lru_cache_add_file(page);
|
lru_cache_add(page);
|
||||||
unlock_page(page);
|
unlock_page(page);
|
||||||
put_page(page);
|
put_page(page);
|
||||||
rdata->pages[i] = NULL;
|
rdata->pages[i] = NULL;
|
||||||
@@ -4437,7 +4437,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
|
|||||||
/* best to give up if we're out of mem */
|
/* best to give up if we're out of mem */
|
||||||
list_for_each_entry_safe(page, tpage, &tmplist, lru) {
|
list_for_each_entry_safe(page, tpage, &tmplist, lru) {
|
||||||
list_del(&page->lru);
|
list_del(&page->lru);
|
||||||
lru_cache_add_file(page);
|
lru_cache_add(page);
|
||||||
unlock_page(page);
|
unlock_page(page);
|
||||||
put_page(page);
|
put_page(page);
|
||||||
}
|
}
|
||||||
@@ -4475,7 +4475,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
|
|||||||
add_credits_and_wake_if(server, &rdata->credits, 0);
|
add_credits_and_wake_if(server, &rdata->credits, 0);
|
||||||
for (i = 0; i < rdata->nr_pages; i++) {
|
for (i = 0; i < rdata->nr_pages; i++) {
|
||||||
page = rdata->pages[i];
|
page = rdata->pages[i];
|
||||||
lru_cache_add_file(page);
|
lru_cache_add(page);
|
||||||
unlock_page(page);
|
unlock_page(page);
|
||||||
put_page(page);
|
put_page(page);
|
||||||
}
|
}
|
||||||
|
@@ -840,7 +840,7 @@ static int fuse_try_move_page(struct fuse_copy_state *cs, struct page **pagep)
|
|||||||
get_page(newpage);
|
get_page(newpage);
|
||||||
|
|
||||||
if (!(buf->flags & PIPE_BUF_FLAG_LRU))
|
if (!(buf->flags & PIPE_BUF_FLAG_LRU))
|
||||||
lru_cache_add_file(newpage);
|
lru_cache_add(newpage);
|
||||||
|
|
||||||
err = 0;
|
err = 0;
|
||||||
spin_lock(&cs->req->waitq.lock);
|
spin_lock(&cs->req->waitq.lock);
|
||||||
|
@@ -38,6 +38,7 @@
|
|||||||
#include <linux/uio.h>
|
#include <linux/uio.h>
|
||||||
|
|
||||||
#include <linux/uaccess.h>
|
#include <linux/uaccess.h>
|
||||||
|
#include <linux/sched/mm.h>
|
||||||
|
|
||||||
static const struct super_operations hugetlbfs_ops;
|
static const struct super_operations hugetlbfs_ops;
|
||||||
static const struct address_space_operations hugetlbfs_aops;
|
static const struct address_space_operations hugetlbfs_aops;
|
||||||
@@ -190,6 +191,54 @@ out:
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef HAVE_ARCH_HUGETLB_UNMAPPED_AREA
|
#ifndef HAVE_ARCH_HUGETLB_UNMAPPED_AREA
|
||||||
|
static unsigned long
|
||||||
|
hugetlb_get_unmapped_area_bottomup(struct file *file, unsigned long addr,
|
||||||
|
unsigned long len, unsigned long pgoff, unsigned long flags)
|
||||||
|
{
|
||||||
|
struct hstate *h = hstate_file(file);
|
||||||
|
struct vm_unmapped_area_info info;
|
||||||
|
|
||||||
|
info.flags = 0;
|
||||||
|
info.length = len;
|
||||||
|
info.low_limit = current->mm->mmap_base;
|
||||||
|
info.high_limit = TASK_SIZE;
|
||||||
|
info.align_mask = PAGE_MASK & ~huge_page_mask(h);
|
||||||
|
info.align_offset = 0;
|
||||||
|
return vm_unmapped_area(&info);
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned long
|
||||||
|
hugetlb_get_unmapped_area_topdown(struct file *file, unsigned long addr,
|
||||||
|
unsigned long len, unsigned long pgoff, unsigned long flags)
|
||||||
|
{
|
||||||
|
struct hstate *h = hstate_file(file);
|
||||||
|
struct vm_unmapped_area_info info;
|
||||||
|
|
||||||
|
info.flags = VM_UNMAPPED_AREA_TOPDOWN;
|
||||||
|
info.length = len;
|
||||||
|
info.low_limit = max(PAGE_SIZE, mmap_min_addr);
|
||||||
|
info.high_limit = current->mm->mmap_base;
|
||||||
|
info.align_mask = PAGE_MASK & ~huge_page_mask(h);
|
||||||
|
info.align_offset = 0;
|
||||||
|
addr = vm_unmapped_area(&info);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A failed mmap() very likely causes application failure,
|
||||||
|
* so fall back to the bottom-up function here. This scenario
|
||||||
|
* can happen with large stack limits and large mmap()
|
||||||
|
* allocations.
|
||||||
|
*/
|
||||||
|
if (unlikely(offset_in_page(addr))) {
|
||||||
|
VM_BUG_ON(addr != -ENOMEM);
|
||||||
|
info.flags = 0;
|
||||||
|
info.low_limit = current->mm->mmap_base;
|
||||||
|
info.high_limit = TASK_SIZE;
|
||||||
|
addr = vm_unmapped_area(&info);
|
||||||
|
}
|
||||||
|
|
||||||
|
return addr;
|
||||||
|
}
|
||||||
|
|
||||||
static unsigned long
|
static unsigned long
|
||||||
hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
|
hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
|
||||||
unsigned long len, unsigned long pgoff, unsigned long flags)
|
unsigned long len, unsigned long pgoff, unsigned long flags)
|
||||||
@@ -197,7 +246,6 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
|
|||||||
struct mm_struct *mm = current->mm;
|
struct mm_struct *mm = current->mm;
|
||||||
struct vm_area_struct *vma;
|
struct vm_area_struct *vma;
|
||||||
struct hstate *h = hstate_file(file);
|
struct hstate *h = hstate_file(file);
|
||||||
struct vm_unmapped_area_info info;
|
|
||||||
|
|
||||||
if (len & ~huge_page_mask(h))
|
if (len & ~huge_page_mask(h))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@@ -218,13 +266,16 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
|
|||||||
return addr;
|
return addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
info.flags = 0;
|
/*
|
||||||
info.length = len;
|
* Use mm->get_unmapped_area value as a hint to use topdown routine.
|
||||||
info.low_limit = TASK_UNMAPPED_BASE;
|
* If architectures have special needs, they should define their own
|
||||||
info.high_limit = TASK_SIZE;
|
* version of hugetlb_get_unmapped_area.
|
||||||
info.align_mask = PAGE_MASK & ~huge_page_mask(h);
|
*/
|
||||||
info.align_offset = 0;
|
if (mm->get_unmapped_area == arch_get_unmapped_area_topdown)
|
||||||
return vm_unmapped_area(&info);
|
return hugetlb_get_unmapped_area_topdown(file, addr, len,
|
||||||
|
pgoff, flags);
|
||||||
|
return hugetlb_get_unmapped_area_bottomup(file, addr, len,
|
||||||
|
pgoff, flags);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@@ -122,7 +122,7 @@ static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma,
|
|||||||
#ifndef __HAVE_ARCH_HUGE_PTEP_GET
|
#ifndef __HAVE_ARCH_HUGE_PTEP_GET
|
||||||
static inline pte_t huge_ptep_get(pte_t *ptep)
|
static inline pte_t huge_ptep_get(pte_t *ptep)
|
||||||
{
|
{
|
||||||
return *ptep;
|
return READ_ONCE(*ptep);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@@ -97,7 +97,7 @@ extern enum compact_result try_to_compact_pages(gfp_t gfp_mask,
|
|||||||
struct page **page);
|
struct page **page);
|
||||||
extern void reset_isolation_suitable(pg_data_t *pgdat);
|
extern void reset_isolation_suitable(pg_data_t *pgdat);
|
||||||
extern enum compact_result compaction_suitable(struct zone *zone, int order,
|
extern enum compact_result compaction_suitable(struct zone *zone, int order,
|
||||||
unsigned int alloc_flags, int classzone_idx);
|
unsigned int alloc_flags, int highest_zoneidx);
|
||||||
|
|
||||||
extern void defer_compaction(struct zone *zone, int order);
|
extern void defer_compaction(struct zone *zone, int order);
|
||||||
extern bool compaction_deferred(struct zone *zone, int order);
|
extern bool compaction_deferred(struct zone *zone, int order);
|
||||||
@@ -182,7 +182,7 @@ bool compaction_zonelist_suitable(struct alloc_context *ac, int order,
|
|||||||
|
|
||||||
extern int kcompactd_run(int nid);
|
extern int kcompactd_run(int nid);
|
||||||
extern void kcompactd_stop(int nid);
|
extern void kcompactd_stop(int nid);
|
||||||
extern void wakeup_kcompactd(pg_data_t *pgdat, int order, int classzone_idx);
|
extern void wakeup_kcompactd(pg_data_t *pgdat, int order, int highest_zoneidx);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
static inline void reset_isolation_suitable(pg_data_t *pgdat)
|
static inline void reset_isolation_suitable(pg_data_t *pgdat)
|
||||||
@@ -190,7 +190,7 @@ static inline void reset_isolation_suitable(pg_data_t *pgdat)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline enum compact_result compaction_suitable(struct zone *zone, int order,
|
static inline enum compact_result compaction_suitable(struct zone *zone, int order,
|
||||||
int alloc_flags, int classzone_idx)
|
int alloc_flags, int highest_zoneidx)
|
||||||
{
|
{
|
||||||
return COMPACT_SKIPPED;
|
return COMPACT_SKIPPED;
|
||||||
}
|
}
|
||||||
@@ -232,7 +232,8 @@ static inline void kcompactd_stop(int nid)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void wakeup_kcompactd(pg_data_t *pgdat, int order, int classzone_idx)
|
static inline void wakeup_kcompactd(pg_data_t *pgdat,
|
||||||
|
int order, int highest_zoneidx)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -110,6 +110,11 @@ struct vm_area_struct;
|
|||||||
* the caller guarantees the allocation will allow more memory to be freed
|
* the caller guarantees the allocation will allow more memory to be freed
|
||||||
* very shortly e.g. process exiting or swapping. Users either should
|
* very shortly e.g. process exiting or swapping. Users either should
|
||||||
* be the MM or co-ordinating closely with the VM (e.g. swap over NFS).
|
* be the MM or co-ordinating closely with the VM (e.g. swap over NFS).
|
||||||
|
* Users of this flag have to be extremely careful to not deplete the reserve
|
||||||
|
* completely and implement a throttling mechanism which controls the
|
||||||
|
* consumption of the reserve based on the amount of freed memory.
|
||||||
|
* Usage of a pre-allocated pool (e.g. mempool) should be always considered
|
||||||
|
* before using this flag.
|
||||||
*
|
*
|
||||||
* %__GFP_NOMEMALLOC is used to explicitly forbid access to emergency reserves.
|
* %__GFP_NOMEMALLOC is used to explicitly forbid access to emergency reserves.
|
||||||
* This takes precedence over the %__GFP_MEMALLOC flag if both are set.
|
* This takes precedence over the %__GFP_MEMALLOC flag if both are set.
|
||||||
@@ -307,7 +312,7 @@ struct vm_area_struct;
|
|||||||
#define GFP_MOVABLE_MASK (__GFP_RECLAIMABLE|__GFP_MOVABLE)
|
#define GFP_MOVABLE_MASK (__GFP_RECLAIMABLE|__GFP_MOVABLE)
|
||||||
#define GFP_MOVABLE_SHIFT 3
|
#define GFP_MOVABLE_SHIFT 3
|
||||||
|
|
||||||
static inline int gfpflags_to_migratetype(const gfp_t gfp_flags)
|
static inline int gfp_migratetype(const gfp_t gfp_flags)
|
||||||
{
|
{
|
||||||
VM_WARN_ON((gfp_flags & GFP_MOVABLE_MASK) == GFP_MOVABLE_MASK);
|
VM_WARN_ON((gfp_flags & GFP_MOVABLE_MASK) == GFP_MOVABLE_MASK);
|
||||||
BUILD_BUG_ON((1UL << GFP_MOVABLE_SHIFT) != ___GFP_MOVABLE);
|
BUILD_BUG_ON((1UL << GFP_MOVABLE_SHIFT) != ___GFP_MOVABLE);
|
||||||
|
@@ -518,8 +518,8 @@ int huge_add_to_page_cache(struct page *page, struct address_space *mapping,
|
|||||||
int __init __alloc_bootmem_huge_page(struct hstate *h);
|
int __init __alloc_bootmem_huge_page(struct hstate *h);
|
||||||
int __init alloc_bootmem_huge_page(struct hstate *h);
|
int __init alloc_bootmem_huge_page(struct hstate *h);
|
||||||
|
|
||||||
void __init hugetlb_bad_size(void);
|
|
||||||
void __init hugetlb_add_hstate(unsigned order);
|
void __init hugetlb_add_hstate(unsigned order);
|
||||||
|
bool __init arch_hugetlb_valid_size(unsigned long size);
|
||||||
struct hstate *size_to_hstate(unsigned long size);
|
struct hstate *size_to_hstate(unsigned long size);
|
||||||
|
|
||||||
#ifndef HUGE_MAX_HSTATE
|
#ifndef HUGE_MAX_HSTATE
|
||||||
@@ -590,6 +590,20 @@ static inline unsigned int blocks_per_huge_page(struct hstate *h)
|
|||||||
|
|
||||||
#include <asm/hugetlb.h>
|
#include <asm/hugetlb.h>
|
||||||
|
|
||||||
|
#ifndef is_hugepage_only_range
|
||||||
|
static inline int is_hugepage_only_range(struct mm_struct *mm,
|
||||||
|
unsigned long addr, unsigned long len)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#define is_hugepage_only_range is_hugepage_only_range
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef arch_clear_hugepage_flags
|
||||||
|
static inline void arch_clear_hugepage_flags(struct page *page) { }
|
||||||
|
#define arch_clear_hugepage_flags arch_clear_hugepage_flags
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef arch_make_huge_pte
|
#ifndef arch_make_huge_pte
|
||||||
static inline pte_t arch_make_huge_pte(pte_t entry, struct vm_area_struct *vma,
|
static inline pte_t arch_make_huge_pte(pte_t entry, struct vm_area_struct *vma,
|
||||||
struct page *page, int writable)
|
struct page *page, int writable)
|
||||||
|
@@ -41,7 +41,7 @@ enum memblock_flags {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* struct memblock_region - represents a memory region
|
* struct memblock_region - represents a memory region
|
||||||
* @base: physical address of the region
|
* @base: base address of the region
|
||||||
* @size: size of the region
|
* @size: size of the region
|
||||||
* @flags: memory region attributes
|
* @flags: memory region attributes
|
||||||
* @nid: NUMA node id
|
* @nid: NUMA node id
|
||||||
@@ -50,7 +50,7 @@ struct memblock_region {
|
|||||||
phys_addr_t base;
|
phys_addr_t base;
|
||||||
phys_addr_t size;
|
phys_addr_t size;
|
||||||
enum memblock_flags flags;
|
enum memblock_flags flags;
|
||||||
#ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
|
#ifdef CONFIG_NEED_MULTIPLE_NODES
|
||||||
int nid;
|
int nid;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
@@ -75,7 +75,7 @@ struct memblock_type {
|
|||||||
* struct memblock - memblock allocator metadata
|
* struct memblock - memblock allocator metadata
|
||||||
* @bottom_up: is bottom up direction?
|
* @bottom_up: is bottom up direction?
|
||||||
* @current_limit: physical address of the current allocation limit
|
* @current_limit: physical address of the current allocation limit
|
||||||
* @memory: usabe memory regions
|
* @memory: usable memory regions
|
||||||
* @reserved: reserved memory regions
|
* @reserved: reserved memory regions
|
||||||
* @physmem: all physical memory
|
* @physmem: all physical memory
|
||||||
*/
|
*/
|
||||||
@@ -215,7 +215,6 @@ static inline bool memblock_is_nomap(struct memblock_region *m)
|
|||||||
return m->flags & MEMBLOCK_NOMAP;
|
return m->flags & MEMBLOCK_NOMAP;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
|
|
||||||
int memblock_search_pfn_nid(unsigned long pfn, unsigned long *start_pfn,
|
int memblock_search_pfn_nid(unsigned long pfn, unsigned long *start_pfn,
|
||||||
unsigned long *end_pfn);
|
unsigned long *end_pfn);
|
||||||
void __next_mem_pfn_range(int *idx, int nid, unsigned long *out_start_pfn,
|
void __next_mem_pfn_range(int *idx, int nid, unsigned long *out_start_pfn,
|
||||||
@@ -234,7 +233,6 @@ void __next_mem_pfn_range(int *idx, int nid, unsigned long *out_start_pfn,
|
|||||||
#define for_each_mem_pfn_range(i, nid, p_start, p_end, p_nid) \
|
#define for_each_mem_pfn_range(i, nid, p_start, p_end, p_nid) \
|
||||||
for (i = -1, __next_mem_pfn_range(&i, nid, p_start, p_end, p_nid); \
|
for (i = -1, __next_mem_pfn_range(&i, nid, p_start, p_end, p_nid); \
|
||||||
i >= 0; __next_mem_pfn_range(&i, nid, p_start, p_end, p_nid))
|
i >= 0; __next_mem_pfn_range(&i, nid, p_start, p_end, p_nid))
|
||||||
#endif /* CONFIG_HAVE_MEMBLOCK_NODE_MAP */
|
|
||||||
|
|
||||||
#ifdef CONFIG_DEFERRED_STRUCT_PAGE_INIT
|
#ifdef CONFIG_DEFERRED_STRUCT_PAGE_INIT
|
||||||
void __next_mem_pfn_range_in_zone(u64 *idx, struct zone *zone,
|
void __next_mem_pfn_range_in_zone(u64 *idx, struct zone *zone,
|
||||||
@@ -275,6 +273,9 @@ void __next_mem_pfn_range_in_zone(u64 *idx, struct zone *zone,
|
|||||||
#define for_each_free_mem_pfn_range_in_zone_from(i, zone, p_start, p_end) \
|
#define for_each_free_mem_pfn_range_in_zone_from(i, zone, p_start, p_end) \
|
||||||
for (; i != U64_MAX; \
|
for (; i != U64_MAX; \
|
||||||
__next_mem_pfn_range_in_zone(&i, zone, p_start, p_end))
|
__next_mem_pfn_range_in_zone(&i, zone, p_start, p_end))
|
||||||
|
|
||||||
|
int __init deferred_page_init_max_threads(const struct cpumask *node_cpumask);
|
||||||
|
|
||||||
#endif /* CONFIG_DEFERRED_STRUCT_PAGE_INIT */
|
#endif /* CONFIG_DEFERRED_STRUCT_PAGE_INIT */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -310,10 +311,10 @@ void __next_mem_pfn_range_in_zone(u64 *idx, struct zone *zone,
|
|||||||
for_each_mem_range_rev(i, &memblock.memory, &memblock.reserved, \
|
for_each_mem_range_rev(i, &memblock.memory, &memblock.reserved, \
|
||||||
nid, flags, p_start, p_end, p_nid)
|
nid, flags, p_start, p_end, p_nid)
|
||||||
|
|
||||||
#ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
|
|
||||||
int memblock_set_node(phys_addr_t base, phys_addr_t size,
|
int memblock_set_node(phys_addr_t base, phys_addr_t size,
|
||||||
struct memblock_type *type, int nid);
|
struct memblock_type *type, int nid);
|
||||||
|
|
||||||
|
#ifdef CONFIG_NEED_MULTIPLE_NODES
|
||||||
static inline void memblock_set_region_node(struct memblock_region *r, int nid)
|
static inline void memblock_set_region_node(struct memblock_region *r, int nid)
|
||||||
{
|
{
|
||||||
r->nid = nid;
|
r->nid = nid;
|
||||||
@@ -332,7 +333,7 @@ static inline int memblock_get_region_node(const struct memblock_region *r)
|
|||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_HAVE_MEMBLOCK_NODE_MAP */
|
#endif /* CONFIG_NEED_MULTIPLE_NODES */
|
||||||
|
|
||||||
/* Flags for memblock allocation APIs */
|
/* Flags for memblock allocation APIs */
|
||||||
#define MEMBLOCK_ALLOC_ANYWHERE (~(phys_addr_t)0)
|
#define MEMBLOCK_ALLOC_ANYWHERE (~(phys_addr_t)0)
|
||||||
|
@@ -29,10 +29,7 @@ struct kmem_cache;
|
|||||||
|
|
||||||
/* Cgroup-specific page state, on top of universal node page state */
|
/* Cgroup-specific page state, on top of universal node page state */
|
||||||
enum memcg_stat_item {
|
enum memcg_stat_item {
|
||||||
MEMCG_CACHE = NR_VM_NODE_STAT_ITEMS,
|
MEMCG_SWAP = NR_VM_NODE_STAT_ITEMS,
|
||||||
MEMCG_RSS,
|
|
||||||
MEMCG_RSS_HUGE,
|
|
||||||
MEMCG_SWAP,
|
|
||||||
MEMCG_SOCK,
|
MEMCG_SOCK,
|
||||||
/* XXX: why are these zone and not node counters? */
|
/* XXX: why are these zone and not node counters? */
|
||||||
MEMCG_KERNEL_STACK_KB,
|
MEMCG_KERNEL_STACK_KB,
|
||||||
@@ -358,16 +355,8 @@ static inline unsigned long mem_cgroup_protection(struct mem_cgroup *memcg,
|
|||||||
enum mem_cgroup_protection mem_cgroup_protected(struct mem_cgroup *root,
|
enum mem_cgroup_protection mem_cgroup_protected(struct mem_cgroup *root,
|
||||||
struct mem_cgroup *memcg);
|
struct mem_cgroup *memcg);
|
||||||
|
|
||||||
int mem_cgroup_try_charge(struct page *page, struct mm_struct *mm,
|
int mem_cgroup_charge(struct page *page, struct mm_struct *mm, gfp_t gfp_mask);
|
||||||
gfp_t gfp_mask, struct mem_cgroup **memcgp,
|
|
||||||
bool compound);
|
|
||||||
int mem_cgroup_try_charge_delay(struct page *page, struct mm_struct *mm,
|
|
||||||
gfp_t gfp_mask, struct mem_cgroup **memcgp,
|
|
||||||
bool compound);
|
|
||||||
void mem_cgroup_commit_charge(struct page *page, struct mem_cgroup *memcg,
|
|
||||||
bool lrucare, bool compound);
|
|
||||||
void mem_cgroup_cancel_charge(struct page *page, struct mem_cgroup *memcg,
|
|
||||||
bool compound);
|
|
||||||
void mem_cgroup_uncharge(struct page *page);
|
void mem_cgroup_uncharge(struct page *page);
|
||||||
void mem_cgroup_uncharge_list(struct list_head *page_list);
|
void mem_cgroup_uncharge_list(struct list_head *page_list);
|
||||||
|
|
||||||
@@ -568,7 +557,7 @@ struct mem_cgroup *mem_cgroup_get_oom_group(struct task_struct *victim,
|
|||||||
void mem_cgroup_print_oom_group(struct mem_cgroup *memcg);
|
void mem_cgroup_print_oom_group(struct mem_cgroup *memcg);
|
||||||
|
|
||||||
#ifdef CONFIG_MEMCG_SWAP
|
#ifdef CONFIG_MEMCG_SWAP
|
||||||
extern int do_swap_account;
|
extern bool cgroup_memory_noswap;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct mem_cgroup *lock_page_memcg(struct page *page);
|
struct mem_cgroup *lock_page_memcg(struct page *page);
|
||||||
@@ -708,16 +697,17 @@ static inline void mod_lruvec_state(struct lruvec *lruvec,
|
|||||||
static inline void __mod_lruvec_page_state(struct page *page,
|
static inline void __mod_lruvec_page_state(struct page *page,
|
||||||
enum node_stat_item idx, int val)
|
enum node_stat_item idx, int val)
|
||||||
{
|
{
|
||||||
|
struct page *head = compound_head(page); /* rmap on tail pages */
|
||||||
pg_data_t *pgdat = page_pgdat(page);
|
pg_data_t *pgdat = page_pgdat(page);
|
||||||
struct lruvec *lruvec;
|
struct lruvec *lruvec;
|
||||||
|
|
||||||
/* Untracked pages have no memcg, no lruvec. Update only the node */
|
/* Untracked pages have no memcg, no lruvec. Update only the node */
|
||||||
if (!page->mem_cgroup) {
|
if (!head->mem_cgroup) {
|
||||||
__mod_node_page_state(pgdat, idx, val);
|
__mod_node_page_state(pgdat, idx, val);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
lruvec = mem_cgroup_lruvec(page->mem_cgroup, pgdat);
|
lruvec = mem_cgroup_lruvec(head->mem_cgroup, pgdat);
|
||||||
__mod_lruvec_state(lruvec, idx, val);
|
__mod_lruvec_state(lruvec, idx, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -847,37 +837,12 @@ static inline enum mem_cgroup_protection mem_cgroup_protected(
|
|||||||
return MEMCG_PROT_NONE;
|
return MEMCG_PROT_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int mem_cgroup_try_charge(struct page *page, struct mm_struct *mm,
|
static inline int mem_cgroup_charge(struct page *page, struct mm_struct *mm,
|
||||||
gfp_t gfp_mask,
|
gfp_t gfp_mask)
|
||||||
struct mem_cgroup **memcgp,
|
|
||||||
bool compound)
|
|
||||||
{
|
{
|
||||||
*memcgp = NULL;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int mem_cgroup_try_charge_delay(struct page *page,
|
|
||||||
struct mm_struct *mm,
|
|
||||||
gfp_t gfp_mask,
|
|
||||||
struct mem_cgroup **memcgp,
|
|
||||||
bool compound)
|
|
||||||
{
|
|
||||||
*memcgp = NULL;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void mem_cgroup_commit_charge(struct page *page,
|
|
||||||
struct mem_cgroup *memcg,
|
|
||||||
bool lrucare, bool compound)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void mem_cgroup_cancel_charge(struct page *page,
|
|
||||||
struct mem_cgroup *memcg,
|
|
||||||
bool compound)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void mem_cgroup_uncharge(struct page *page)
|
static inline void mem_cgroup_uncharge(struct page *page)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -1277,6 +1242,19 @@ static inline void dec_lruvec_page_state(struct page *page,
|
|||||||
mod_lruvec_page_state(page, idx, -1);
|
mod_lruvec_page_state(page, idx, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline struct lruvec *parent_lruvec(struct lruvec *lruvec)
|
||||||
|
{
|
||||||
|
struct mem_cgroup *memcg;
|
||||||
|
|
||||||
|
memcg = lruvec_memcg(lruvec);
|
||||||
|
if (!memcg)
|
||||||
|
return NULL;
|
||||||
|
memcg = parent_mem_cgroup(memcg);
|
||||||
|
if (!memcg)
|
||||||
|
return NULL;
|
||||||
|
return mem_cgroup_lruvec(memcg, lruvec_pgdat(lruvec));
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_CGROUP_WRITEBACK
|
#ifdef CONFIG_CGROUP_WRITEBACK
|
||||||
|
|
||||||
struct wb_domain *mem_cgroup_wb_domain(struct bdi_writeback *wb);
|
struct wb_domain *mem_cgroup_wb_domain(struct bdi_writeback *wb);
|
||||||
|
@@ -501,7 +501,6 @@ struct vm_fault {
|
|||||||
pte_t orig_pte; /* Value of PTE at the time of fault */
|
pte_t orig_pte; /* Value of PTE at the time of fault */
|
||||||
|
|
||||||
struct page *cow_page; /* Page handler may use for COW fault */
|
struct page *cow_page; /* Page handler may use for COW fault */
|
||||||
struct mem_cgroup *memcg; /* Cgroup cow_page belongs to */
|
|
||||||
struct page *page; /* ->fault handlers should return a
|
struct page *page; /* ->fault handlers should return a
|
||||||
* page here, unless VM_FAULT_NOPAGE
|
* page here, unless VM_FAULT_NOPAGE
|
||||||
* is set (which is also implied by
|
* is set (which is also implied by
|
||||||
@@ -867,7 +866,7 @@ enum compound_dtor_id {
|
|||||||
#endif
|
#endif
|
||||||
NR_COMPOUND_DTORS,
|
NR_COMPOUND_DTORS,
|
||||||
};
|
};
|
||||||
extern compound_page_dtor * const compound_page_dtors[];
|
extern compound_page_dtor * const compound_page_dtors[NR_COMPOUND_DTORS];
|
||||||
|
|
||||||
static inline void set_compound_page_dtor(struct page *page,
|
static inline void set_compound_page_dtor(struct page *page,
|
||||||
enum compound_dtor_id compound_dtor)
|
enum compound_dtor_id compound_dtor)
|
||||||
@@ -876,10 +875,10 @@ static inline void set_compound_page_dtor(struct page *page,
|
|||||||
page[1].compound_dtor = compound_dtor;
|
page[1].compound_dtor = compound_dtor;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline compound_page_dtor *get_compound_page_dtor(struct page *page)
|
static inline void destroy_compound_page(struct page *page)
|
||||||
{
|
{
|
||||||
VM_BUG_ON_PAGE(page[1].compound_dtor >= NR_COMPOUND_DTORS, page);
|
VM_BUG_ON_PAGE(page[1].compound_dtor >= NR_COMPOUND_DTORS, page);
|
||||||
return compound_page_dtors[page[1].compound_dtor];
|
compound_page_dtors[page[1].compound_dtor](page);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline unsigned int compound_order(struct page *page)
|
static inline unsigned int compound_order(struct page *page)
|
||||||
@@ -946,8 +945,7 @@ static inline pte_t maybe_mkwrite(pte_t pte, struct vm_area_struct *vma)
|
|||||||
return pte;
|
return pte;
|
||||||
}
|
}
|
||||||
|
|
||||||
vm_fault_t alloc_set_pte(struct vm_fault *vmf, struct mem_cgroup *memcg,
|
vm_fault_t alloc_set_pte(struct vm_fault *vmf, struct page *page);
|
||||||
struct page *page);
|
|
||||||
vm_fault_t finish_fault(struct vm_fault *vmf);
|
vm_fault_t finish_fault(struct vm_fault *vmf);
|
||||||
vm_fault_t finish_mkwrite_fault(struct vm_fault *vmf);
|
vm_fault_t finish_mkwrite_fault(struct vm_fault *vmf);
|
||||||
#endif
|
#endif
|
||||||
@@ -1827,6 +1825,8 @@ extern int mprotect_fixup(struct vm_area_struct *vma,
|
|||||||
*/
|
*/
|
||||||
int __get_user_pages_fast(unsigned long start, int nr_pages, int write,
|
int __get_user_pages_fast(unsigned long start, int nr_pages, int write,
|
||||||
struct page **pages);
|
struct page **pages);
|
||||||
|
int pin_user_pages_fast_only(unsigned long start, int nr_pages,
|
||||||
|
unsigned int gup_flags, struct page **pages);
|
||||||
/*
|
/*
|
||||||
* per-process(per-mm_struct) statistics.
|
* per-process(per-mm_struct) statistics.
|
||||||
*/
|
*/
|
||||||
@@ -2327,9 +2327,7 @@ static inline spinlock_t *pud_lock(struct mm_struct *mm, pud_t *pud)
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern void __init pagecache_init(void);
|
extern void __init pagecache_init(void);
|
||||||
extern void free_area_init(unsigned long * zones_size);
|
extern void __init free_area_init_memoryless_node(int nid);
|
||||||
extern void __init free_area_init_node(int nid, unsigned long * zones_size,
|
|
||||||
unsigned long zone_start_pfn, unsigned long *zholes_size);
|
|
||||||
extern void free_initmem(void);
|
extern void free_initmem(void);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -2399,34 +2397,26 @@ static inline unsigned long get_num_physpages(void)
|
|||||||
return phys_pages;
|
return phys_pages;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
|
|
||||||
/*
|
/*
|
||||||
* With CONFIG_HAVE_MEMBLOCK_NODE_MAP set, an architecture may initialise its
|
* Using memblock node mappings, an architecture may initialise its
|
||||||
* zones, allocate the backing mem_map and account for memory holes in a more
|
* zones, allocate the backing mem_map and account for memory holes in an
|
||||||
* architecture independent manner. This is a substitute for creating the
|
* architecture independent manner.
|
||||||
* zone_sizes[] and zholes_size[] arrays and passing them to
|
|
||||||
* free_area_init_node()
|
|
||||||
*
|
*
|
||||||
* An architecture is expected to register range of page frames backed by
|
* An architecture is expected to register range of page frames backed by
|
||||||
* physical memory with memblock_add[_node]() before calling
|
* physical memory with memblock_add[_node]() before calling
|
||||||
* free_area_init_nodes() passing in the PFN each zone ends at. At a basic
|
* free_area_init() passing in the PFN each zone ends at. At a basic
|
||||||
* usage, an architecture is expected to do something like
|
* usage, an architecture is expected to do something like
|
||||||
*
|
*
|
||||||
* unsigned long max_zone_pfns[MAX_NR_ZONES] = {max_dma, max_normal_pfn,
|
* unsigned long max_zone_pfns[MAX_NR_ZONES] = {max_dma, max_normal_pfn,
|
||||||
* max_highmem_pfn};
|
* max_highmem_pfn};
|
||||||
* for_each_valid_physical_page_range()
|
* for_each_valid_physical_page_range()
|
||||||
* memblock_add_node(base, size, nid)
|
* memblock_add_node(base, size, nid)
|
||||||
* free_area_init_nodes(max_zone_pfns);
|
* free_area_init(max_zone_pfns);
|
||||||
*
|
*
|
||||||
* free_bootmem_with_active_regions() calls free_bootmem_node() for each
|
|
||||||
* registered physical page range. Similarly
|
|
||||||
* sparse_memory_present_with_active_regions() calls memory_present() for
|
* sparse_memory_present_with_active_regions() calls memory_present() for
|
||||||
* each range when SPARSEMEM is enabled.
|
* each range when SPARSEMEM is enabled.
|
||||||
*
|
|
||||||
* See mm/page_alloc.c for more information on each function exposed by
|
|
||||||
* CONFIG_HAVE_MEMBLOCK_NODE_MAP.
|
|
||||||
*/
|
*/
|
||||||
extern void free_area_init_nodes(unsigned long *max_zone_pfn);
|
void free_area_init(unsigned long *max_zone_pfn);
|
||||||
unsigned long node_map_pfn_alignment(void);
|
unsigned long node_map_pfn_alignment(void);
|
||||||
unsigned long __absent_pages_in_range(int nid, unsigned long start_pfn,
|
unsigned long __absent_pages_in_range(int nid, unsigned long start_pfn,
|
||||||
unsigned long end_pfn);
|
unsigned long end_pfn);
|
||||||
@@ -2435,16 +2425,10 @@ extern unsigned long absent_pages_in_range(unsigned long start_pfn,
|
|||||||
extern void get_pfn_range_for_nid(unsigned int nid,
|
extern void get_pfn_range_for_nid(unsigned int nid,
|
||||||
unsigned long *start_pfn, unsigned long *end_pfn);
|
unsigned long *start_pfn, unsigned long *end_pfn);
|
||||||
extern unsigned long find_min_pfn_with_active_regions(void);
|
extern unsigned long find_min_pfn_with_active_regions(void);
|
||||||
extern void free_bootmem_with_active_regions(int nid,
|
|
||||||
unsigned long max_low_pfn);
|
|
||||||
extern void sparse_memory_present_with_active_regions(int nid);
|
extern void sparse_memory_present_with_active_regions(int nid);
|
||||||
|
|
||||||
#endif /* CONFIG_HAVE_MEMBLOCK_NODE_MAP */
|
#ifndef CONFIG_NEED_MULTIPLE_NODES
|
||||||
|
static inline int early_pfn_to_nid(unsigned long pfn)
|
||||||
#if !defined(CONFIG_HAVE_MEMBLOCK_NODE_MAP) && \
|
|
||||||
!defined(CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID)
|
|
||||||
static inline int __early_pfn_to_nid(unsigned long pfn,
|
|
||||||
struct mminit_pfnnid_cache *state)
|
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -2480,6 +2464,7 @@ extern void setup_per_cpu_pageset(void);
|
|||||||
extern int min_free_kbytes;
|
extern int min_free_kbytes;
|
||||||
extern int watermark_boost_factor;
|
extern int watermark_boost_factor;
|
||||||
extern int watermark_scale_factor;
|
extern int watermark_scale_factor;
|
||||||
|
extern bool arch_has_descending_max_zone_pfns(void);
|
||||||
|
|
||||||
/* nommu.c */
|
/* nommu.c */
|
||||||
extern atomic_long_t mmap_pages_allocated;
|
extern atomic_long_t mmap_pages_allocated;
|
||||||
@@ -2816,6 +2801,7 @@ struct page *follow_page(struct vm_area_struct *vma, unsigned long address,
|
|||||||
#define FOLL_LONGTERM 0x10000 /* mapping lifetime is indefinite: see below */
|
#define FOLL_LONGTERM 0x10000 /* mapping lifetime is indefinite: see below */
|
||||||
#define FOLL_SPLIT_PMD 0x20000 /* split huge pmd before returning */
|
#define FOLL_SPLIT_PMD 0x20000 /* split huge pmd before returning */
|
||||||
#define FOLL_PIN 0x40000 /* pages must be released via unpin_user_page */
|
#define FOLL_PIN 0x40000 /* pages must be released via unpin_user_page */
|
||||||
|
#define FOLL_FAST_ONLY 0x80000 /* gup_fast: prevent fall-back to slow gup */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* FOLL_PIN and FOLL_LONGTERM may be used in various combinations with each
|
* FOLL_PIN and FOLL_LONGTERM may be used in various combinations with each
|
||||||
|
@@ -242,19 +242,6 @@ static inline bool is_active_lru(enum lru_list lru)
|
|||||||
return (lru == LRU_ACTIVE_ANON || lru == LRU_ACTIVE_FILE);
|
return (lru == LRU_ACTIVE_ANON || lru == LRU_ACTIVE_FILE);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct zone_reclaim_stat {
|
|
||||||
/*
|
|
||||||
* The pageout code in vmscan.c keeps track of how many of the
|
|
||||||
* mem/swap backed and file backed pages are referenced.
|
|
||||||
* The higher the rotated/scanned ratio, the more valuable
|
|
||||||
* that cache is.
|
|
||||||
*
|
|
||||||
* The anon LRU stats live in [0], file LRU stats in [1]
|
|
||||||
*/
|
|
||||||
unsigned long recent_rotated[2];
|
|
||||||
unsigned long recent_scanned[2];
|
|
||||||
};
|
|
||||||
|
|
||||||
enum lruvec_flags {
|
enum lruvec_flags {
|
||||||
LRUVEC_CONGESTED, /* lruvec has many dirty pages
|
LRUVEC_CONGESTED, /* lruvec has many dirty pages
|
||||||
* backed by a congested BDI
|
* backed by a congested BDI
|
||||||
@@ -263,7 +250,13 @@ enum lruvec_flags {
|
|||||||
|
|
||||||
struct lruvec {
|
struct lruvec {
|
||||||
struct list_head lists[NR_LRU_LISTS];
|
struct list_head lists[NR_LRU_LISTS];
|
||||||
struct zone_reclaim_stat reclaim_stat;
|
/*
|
||||||
|
* These track the cost of reclaiming one LRU - file or anon -
|
||||||
|
* over the other. As the observed cost of reclaiming one LRU
|
||||||
|
* increases, the reclaim scan balance tips toward the other.
|
||||||
|
*/
|
||||||
|
unsigned long anon_cost;
|
||||||
|
unsigned long file_cost;
|
||||||
/* Evictions & activations on the inactive file list */
|
/* Evictions & activations on the inactive file list */
|
||||||
atomic_long_t inactive_age;
|
atomic_long_t inactive_age;
|
||||||
/* Refaults at the time of last reclaim cycle */
|
/* Refaults at the time of last reclaim cycle */
|
||||||
@@ -680,6 +673,8 @@ typedef struct pglist_data {
|
|||||||
/*
|
/*
|
||||||
* Must be held any time you expect node_start_pfn,
|
* Must be held any time you expect node_start_pfn,
|
||||||
* node_present_pages, node_spanned_pages or nr_zones to stay constant.
|
* node_present_pages, node_spanned_pages or nr_zones to stay constant.
|
||||||
|
* Also synchronizes pgdat->first_deferred_pfn during deferred page
|
||||||
|
* init.
|
||||||
*
|
*
|
||||||
* pgdat_resize_lock() and pgdat_resize_unlock() are provided to
|
* pgdat_resize_lock() and pgdat_resize_unlock() are provided to
|
||||||
* manipulate node_size_lock without checking for CONFIG_MEMORY_HOTPLUG
|
* manipulate node_size_lock without checking for CONFIG_MEMORY_HOTPLUG
|
||||||
@@ -699,13 +694,13 @@ typedef struct pglist_data {
|
|||||||
struct task_struct *kswapd; /* Protected by
|
struct task_struct *kswapd; /* Protected by
|
||||||
mem_hotplug_begin/end() */
|
mem_hotplug_begin/end() */
|
||||||
int kswapd_order;
|
int kswapd_order;
|
||||||
enum zone_type kswapd_classzone_idx;
|
enum zone_type kswapd_highest_zoneidx;
|
||||||
|
|
||||||
int kswapd_failures; /* Number of 'reclaimed == 0' runs */
|
int kswapd_failures; /* Number of 'reclaimed == 0' runs */
|
||||||
|
|
||||||
#ifdef CONFIG_COMPACTION
|
#ifdef CONFIG_COMPACTION
|
||||||
int kcompactd_max_order;
|
int kcompactd_max_order;
|
||||||
enum zone_type kcompactd_classzone_idx;
|
enum zone_type kcompactd_highest_zoneidx;
|
||||||
wait_queue_head_t kcompactd_wait;
|
wait_queue_head_t kcompactd_wait;
|
||||||
struct task_struct *kcompactd;
|
struct task_struct *kcompactd;
|
||||||
#endif
|
#endif
|
||||||
@@ -783,15 +778,15 @@ static inline bool pgdat_is_empty(pg_data_t *pgdat)
|
|||||||
|
|
||||||
void build_all_zonelists(pg_data_t *pgdat);
|
void build_all_zonelists(pg_data_t *pgdat);
|
||||||
void wakeup_kswapd(struct zone *zone, gfp_t gfp_mask, int order,
|
void wakeup_kswapd(struct zone *zone, gfp_t gfp_mask, int order,
|
||||||
enum zone_type classzone_idx);
|
enum zone_type highest_zoneidx);
|
||||||
bool __zone_watermark_ok(struct zone *z, unsigned int order, unsigned long mark,
|
bool __zone_watermark_ok(struct zone *z, unsigned int order, unsigned long mark,
|
||||||
int classzone_idx, unsigned int alloc_flags,
|
int highest_zoneidx, unsigned int alloc_flags,
|
||||||
long free_pages);
|
long free_pages);
|
||||||
bool zone_watermark_ok(struct zone *z, unsigned int order,
|
bool zone_watermark_ok(struct zone *z, unsigned int order,
|
||||||
unsigned long mark, int classzone_idx,
|
unsigned long mark, int highest_zoneidx,
|
||||||
unsigned int alloc_flags);
|
unsigned int alloc_flags);
|
||||||
bool zone_watermark_ok_safe(struct zone *z, unsigned int order,
|
bool zone_watermark_ok_safe(struct zone *z, unsigned int order,
|
||||||
unsigned long mark, int classzone_idx);
|
unsigned long mark, int highest_zoneidx);
|
||||||
enum memmap_context {
|
enum memmap_context {
|
||||||
MEMMAP_EARLY,
|
MEMMAP_EARLY,
|
||||||
MEMMAP_HOTPLUG,
|
MEMMAP_HOTPLUG,
|
||||||
@@ -876,7 +871,7 @@ extern int movable_zone;
|
|||||||
#ifdef CONFIG_HIGHMEM
|
#ifdef CONFIG_HIGHMEM
|
||||||
static inline int zone_movable_is_highmem(void)
|
static inline int zone_movable_is_highmem(void)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
|
#ifdef CONFIG_NEED_MULTIPLE_NODES
|
||||||
return movable_zone == ZONE_HIGHMEM;
|
return movable_zone == ZONE_HIGHMEM;
|
||||||
#else
|
#else
|
||||||
return (ZONE_MOVABLE - 1) == ZONE_HIGHMEM;
|
return (ZONE_MOVABLE - 1) == ZONE_HIGHMEM;
|
||||||
@@ -1079,15 +1074,6 @@ static inline struct zoneref *first_zones_zonelist(struct zonelist *zonelist,
|
|||||||
#include <asm/sparsemem.h>
|
#include <asm/sparsemem.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID) && \
|
|
||||||
!defined(CONFIG_HAVE_MEMBLOCK_NODE_MAP)
|
|
||||||
static inline unsigned long early_pfn_to_nid(unsigned long pfn)
|
|
||||||
{
|
|
||||||
BUILD_BUG_ON(IS_ENABLED(CONFIG_NUMA));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef CONFIG_FLATMEM
|
#ifdef CONFIG_FLATMEM
|
||||||
#define pfn_to_nid(pfn) (0)
|
#define pfn_to_nid(pfn) (0)
|
||||||
#endif
|
#endif
|
||||||
|
@@ -4,6 +4,9 @@
|
|||||||
*
|
*
|
||||||
* Copyright (C) 2008, 2009 secunet Security Networks AG
|
* Copyright (C) 2008, 2009 secunet Security Networks AG
|
||||||
* Copyright (C) 2008, 2009 Steffen Klassert <steffen.klassert@secunet.com>
|
* Copyright (C) 2008, 2009 Steffen Klassert <steffen.klassert@secunet.com>
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Oracle and/or its affiliates.
|
||||||
|
* Author: Daniel Jordan <daniel.m.jordan@oracle.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef PADATA_H
|
#ifndef PADATA_H
|
||||||
@@ -24,7 +27,6 @@
|
|||||||
* @list: List entry, to attach to the padata lists.
|
* @list: List entry, to attach to the padata lists.
|
||||||
* @pd: Pointer to the internal control structure.
|
* @pd: Pointer to the internal control structure.
|
||||||
* @cb_cpu: Callback cpu for serializatioon.
|
* @cb_cpu: Callback cpu for serializatioon.
|
||||||
* @cpu: Cpu for parallelization.
|
|
||||||
* @seq_nr: Sequence number of the parallelized data object.
|
* @seq_nr: Sequence number of the parallelized data object.
|
||||||
* @info: Used to pass information from the parallel to the serial function.
|
* @info: Used to pass information from the parallel to the serial function.
|
||||||
* @parallel: Parallel execution function.
|
* @parallel: Parallel execution function.
|
||||||
@@ -34,7 +36,6 @@ struct padata_priv {
|
|||||||
struct list_head list;
|
struct list_head list;
|
||||||
struct parallel_data *pd;
|
struct parallel_data *pd;
|
||||||
int cb_cpu;
|
int cb_cpu;
|
||||||
int cpu;
|
|
||||||
unsigned int seq_nr;
|
unsigned int seq_nr;
|
||||||
int info;
|
int info;
|
||||||
void (*parallel)(struct padata_priv *padata);
|
void (*parallel)(struct padata_priv *padata);
|
||||||
@@ -68,15 +69,11 @@ struct padata_serial_queue {
|
|||||||
/**
|
/**
|
||||||
* struct padata_parallel_queue - The percpu padata parallel queue
|
* struct padata_parallel_queue - The percpu padata parallel queue
|
||||||
*
|
*
|
||||||
* @parallel: List to wait for parallelization.
|
|
||||||
* @reorder: List to wait for reordering after parallel processing.
|
* @reorder: List to wait for reordering after parallel processing.
|
||||||
* @work: work struct for parallelization.
|
|
||||||
* @num_obj: Number of objects that are processed by this cpu.
|
* @num_obj: Number of objects that are processed by this cpu.
|
||||||
*/
|
*/
|
||||||
struct padata_parallel_queue {
|
struct padata_parallel_queue {
|
||||||
struct padata_list parallel;
|
|
||||||
struct padata_list reorder;
|
struct padata_list reorder;
|
||||||
struct work_struct work;
|
|
||||||
atomic_t num_obj;
|
atomic_t num_obj;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -111,7 +108,7 @@ struct parallel_data {
|
|||||||
struct padata_parallel_queue __percpu *pqueue;
|
struct padata_parallel_queue __percpu *pqueue;
|
||||||
struct padata_serial_queue __percpu *squeue;
|
struct padata_serial_queue __percpu *squeue;
|
||||||
atomic_t refcnt;
|
atomic_t refcnt;
|
||||||
atomic_t seq_nr;
|
unsigned int seq_nr;
|
||||||
unsigned int processed;
|
unsigned int processed;
|
||||||
int cpu;
|
int cpu;
|
||||||
struct padata_cpumask cpumask;
|
struct padata_cpumask cpumask;
|
||||||
@@ -136,6 +133,31 @@ struct padata_shell {
|
|||||||
struct list_head list;
|
struct list_head list;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct padata_mt_job - represents one multithreaded job
|
||||||
|
*
|
||||||
|
* @thread_fn: Called for each chunk of work that a padata thread does.
|
||||||
|
* @fn_arg: The thread function argument.
|
||||||
|
* @start: The start of the job (units are job-specific).
|
||||||
|
* @size: size of this node's work (units are job-specific).
|
||||||
|
* @align: Ranges passed to the thread function fall on this boundary, with the
|
||||||
|
* possible exceptions of the beginning and end of the job.
|
||||||
|
* @min_chunk: The minimum chunk size in job-specific units. This allows
|
||||||
|
* the client to communicate the minimum amount of work that's
|
||||||
|
* appropriate for one worker thread to do at once.
|
||||||
|
* @max_threads: Max threads to use for the job, actual number may be less
|
||||||
|
* depending on task size and minimum chunk size.
|
||||||
|
*/
|
||||||
|
struct padata_mt_job {
|
||||||
|
void (*thread_fn)(unsigned long start, unsigned long end, void *arg);
|
||||||
|
void *fn_arg;
|
||||||
|
unsigned long start;
|
||||||
|
unsigned long size;
|
||||||
|
unsigned long align;
|
||||||
|
unsigned long min_chunk;
|
||||||
|
int max_threads;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct padata_instance - The overall control structure.
|
* struct padata_instance - The overall control structure.
|
||||||
*
|
*
|
||||||
@@ -166,6 +188,12 @@ struct padata_instance {
|
|||||||
#define PADATA_INVALID 4
|
#define PADATA_INVALID 4
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef CONFIG_PADATA
|
||||||
|
extern void __init padata_init(void);
|
||||||
|
#else
|
||||||
|
static inline void __init padata_init(void) {}
|
||||||
|
#endif
|
||||||
|
|
||||||
extern struct padata_instance *padata_alloc_possible(const char *name);
|
extern struct padata_instance *padata_alloc_possible(const char *name);
|
||||||
extern void padata_free(struct padata_instance *pinst);
|
extern void padata_free(struct padata_instance *pinst);
|
||||||
extern struct padata_shell *padata_alloc_shell(struct padata_instance *pinst);
|
extern struct padata_shell *padata_alloc_shell(struct padata_instance *pinst);
|
||||||
@@ -173,6 +201,7 @@ extern void padata_free_shell(struct padata_shell *ps);
|
|||||||
extern int padata_do_parallel(struct padata_shell *ps,
|
extern int padata_do_parallel(struct padata_shell *ps,
|
||||||
struct padata_priv *padata, int *cb_cpu);
|
struct padata_priv *padata, int *cb_cpu);
|
||||||
extern void padata_do_serial(struct padata_priv *padata);
|
extern void padata_do_serial(struct padata_priv *padata);
|
||||||
|
extern void __init padata_do_multithreaded(struct padata_mt_job *job);
|
||||||
extern int padata_set_cpumask(struct padata_instance *pinst, int cpumask_type,
|
extern int padata_set_cpumask(struct padata_instance *pinst, int cpumask_type,
|
||||||
cpumask_var_t cpumask);
|
cpumask_var_t cpumask);
|
||||||
extern int padata_start(struct padata_instance *pinst);
|
extern int padata_start(struct padata_instance *pinst);
|
||||||
|
@@ -272,6 +272,31 @@ void __read_overflow3(void) __compiletime_error("detected read beyond size of ob
|
|||||||
void __write_overflow(void) __compiletime_error("detected write beyond size of object passed as 1st parameter");
|
void __write_overflow(void) __compiletime_error("detected write beyond size of object passed as 1st parameter");
|
||||||
|
|
||||||
#if !defined(__NO_FORTIFY) && defined(__OPTIMIZE__) && defined(CONFIG_FORTIFY_SOURCE)
|
#if !defined(__NO_FORTIFY) && defined(__OPTIMIZE__) && defined(CONFIG_FORTIFY_SOURCE)
|
||||||
|
|
||||||
|
#ifdef CONFIG_KASAN
|
||||||
|
extern void *__underlying_memchr(const void *p, int c, __kernel_size_t size) __RENAME(memchr);
|
||||||
|
extern int __underlying_memcmp(const void *p, const void *q, __kernel_size_t size) __RENAME(memcmp);
|
||||||
|
extern void *__underlying_memcpy(void *p, const void *q, __kernel_size_t size) __RENAME(memcpy);
|
||||||
|
extern void *__underlying_memmove(void *p, const void *q, __kernel_size_t size) __RENAME(memmove);
|
||||||
|
extern void *__underlying_memset(void *p, int c, __kernel_size_t size) __RENAME(memset);
|
||||||
|
extern char *__underlying_strcat(char *p, const char *q) __RENAME(strcat);
|
||||||
|
extern char *__underlying_strcpy(char *p, const char *q) __RENAME(strcpy);
|
||||||
|
extern __kernel_size_t __underlying_strlen(const char *p) __RENAME(strlen);
|
||||||
|
extern char *__underlying_strncat(char *p, const char *q, __kernel_size_t count) __RENAME(strncat);
|
||||||
|
extern char *__underlying_strncpy(char *p, const char *q, __kernel_size_t size) __RENAME(strncpy);
|
||||||
|
#else
|
||||||
|
#define __underlying_memchr __builtin_memchr
|
||||||
|
#define __underlying_memcmp __builtin_memcmp
|
||||||
|
#define __underlying_memcpy __builtin_memcpy
|
||||||
|
#define __underlying_memmove __builtin_memmove
|
||||||
|
#define __underlying_memset __builtin_memset
|
||||||
|
#define __underlying_strcat __builtin_strcat
|
||||||
|
#define __underlying_strcpy __builtin_strcpy
|
||||||
|
#define __underlying_strlen __builtin_strlen
|
||||||
|
#define __underlying_strncat __builtin_strncat
|
||||||
|
#define __underlying_strncpy __builtin_strncpy
|
||||||
|
#endif
|
||||||
|
|
||||||
__FORTIFY_INLINE char *strncpy(char *p, const char *q, __kernel_size_t size)
|
__FORTIFY_INLINE char *strncpy(char *p, const char *q, __kernel_size_t size)
|
||||||
{
|
{
|
||||||
size_t p_size = __builtin_object_size(p, 0);
|
size_t p_size = __builtin_object_size(p, 0);
|
||||||
@@ -279,14 +304,14 @@ __FORTIFY_INLINE char *strncpy(char *p, const char *q, __kernel_size_t size)
|
|||||||
__write_overflow();
|
__write_overflow();
|
||||||
if (p_size < size)
|
if (p_size < size)
|
||||||
fortify_panic(__func__);
|
fortify_panic(__func__);
|
||||||
return __builtin_strncpy(p, q, size);
|
return __underlying_strncpy(p, q, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
__FORTIFY_INLINE char *strcat(char *p, const char *q)
|
__FORTIFY_INLINE char *strcat(char *p, const char *q)
|
||||||
{
|
{
|
||||||
size_t p_size = __builtin_object_size(p, 0);
|
size_t p_size = __builtin_object_size(p, 0);
|
||||||
if (p_size == (size_t)-1)
|
if (p_size == (size_t)-1)
|
||||||
return __builtin_strcat(p, q);
|
return __underlying_strcat(p, q);
|
||||||
if (strlcat(p, q, p_size) >= p_size)
|
if (strlcat(p, q, p_size) >= p_size)
|
||||||
fortify_panic(__func__);
|
fortify_panic(__func__);
|
||||||
return p;
|
return p;
|
||||||
@@ -300,7 +325,7 @@ __FORTIFY_INLINE __kernel_size_t strlen(const char *p)
|
|||||||
/* Work around gcc excess stack consumption issue */
|
/* Work around gcc excess stack consumption issue */
|
||||||
if (p_size == (size_t)-1 ||
|
if (p_size == (size_t)-1 ||
|
||||||
(__builtin_constant_p(p[p_size - 1]) && p[p_size - 1] == '\0'))
|
(__builtin_constant_p(p[p_size - 1]) && p[p_size - 1] == '\0'))
|
||||||
return __builtin_strlen(p);
|
return __underlying_strlen(p);
|
||||||
ret = strnlen(p, p_size);
|
ret = strnlen(p, p_size);
|
||||||
if (p_size <= ret)
|
if (p_size <= ret)
|
||||||
fortify_panic(__func__);
|
fortify_panic(__func__);
|
||||||
@@ -333,7 +358,7 @@ __FORTIFY_INLINE size_t strlcpy(char *p, const char *q, size_t size)
|
|||||||
__write_overflow();
|
__write_overflow();
|
||||||
if (len >= p_size)
|
if (len >= p_size)
|
||||||
fortify_panic(__func__);
|
fortify_panic(__func__);
|
||||||
__builtin_memcpy(p, q, len);
|
__underlying_memcpy(p, q, len);
|
||||||
p[len] = '\0';
|
p[len] = '\0';
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
@@ -346,12 +371,12 @@ __FORTIFY_INLINE char *strncat(char *p, const char *q, __kernel_size_t count)
|
|||||||
size_t p_size = __builtin_object_size(p, 0);
|
size_t p_size = __builtin_object_size(p, 0);
|
||||||
size_t q_size = __builtin_object_size(q, 0);
|
size_t q_size = __builtin_object_size(q, 0);
|
||||||
if (p_size == (size_t)-1 && q_size == (size_t)-1)
|
if (p_size == (size_t)-1 && q_size == (size_t)-1)
|
||||||
return __builtin_strncat(p, q, count);
|
return __underlying_strncat(p, q, count);
|
||||||
p_len = strlen(p);
|
p_len = strlen(p);
|
||||||
copy_len = strnlen(q, count);
|
copy_len = strnlen(q, count);
|
||||||
if (p_size < p_len + copy_len + 1)
|
if (p_size < p_len + copy_len + 1)
|
||||||
fortify_panic(__func__);
|
fortify_panic(__func__);
|
||||||
__builtin_memcpy(p + p_len, q, copy_len);
|
__underlying_memcpy(p + p_len, q, copy_len);
|
||||||
p[p_len + copy_len] = '\0';
|
p[p_len + copy_len] = '\0';
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
@@ -363,7 +388,7 @@ __FORTIFY_INLINE void *memset(void *p, int c, __kernel_size_t size)
|
|||||||
__write_overflow();
|
__write_overflow();
|
||||||
if (p_size < size)
|
if (p_size < size)
|
||||||
fortify_panic(__func__);
|
fortify_panic(__func__);
|
||||||
return __builtin_memset(p, c, size);
|
return __underlying_memset(p, c, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
__FORTIFY_INLINE void *memcpy(void *p, const void *q, __kernel_size_t size)
|
__FORTIFY_INLINE void *memcpy(void *p, const void *q, __kernel_size_t size)
|
||||||
@@ -378,7 +403,7 @@ __FORTIFY_INLINE void *memcpy(void *p, const void *q, __kernel_size_t size)
|
|||||||
}
|
}
|
||||||
if (p_size < size || q_size < size)
|
if (p_size < size || q_size < size)
|
||||||
fortify_panic(__func__);
|
fortify_panic(__func__);
|
||||||
return __builtin_memcpy(p, q, size);
|
return __underlying_memcpy(p, q, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
__FORTIFY_INLINE void *memmove(void *p, const void *q, __kernel_size_t size)
|
__FORTIFY_INLINE void *memmove(void *p, const void *q, __kernel_size_t size)
|
||||||
@@ -393,7 +418,7 @@ __FORTIFY_INLINE void *memmove(void *p, const void *q, __kernel_size_t size)
|
|||||||
}
|
}
|
||||||
if (p_size < size || q_size < size)
|
if (p_size < size || q_size < size)
|
||||||
fortify_panic(__func__);
|
fortify_panic(__func__);
|
||||||
return __builtin_memmove(p, q, size);
|
return __underlying_memmove(p, q, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern void *__real_memscan(void *, int, __kernel_size_t) __RENAME(memscan);
|
extern void *__real_memscan(void *, int, __kernel_size_t) __RENAME(memscan);
|
||||||
@@ -419,7 +444,7 @@ __FORTIFY_INLINE int memcmp(const void *p, const void *q, __kernel_size_t size)
|
|||||||
}
|
}
|
||||||
if (p_size < size || q_size < size)
|
if (p_size < size || q_size < size)
|
||||||
fortify_panic(__func__);
|
fortify_panic(__func__);
|
||||||
return __builtin_memcmp(p, q, size);
|
return __underlying_memcmp(p, q, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
__FORTIFY_INLINE void *memchr(const void *p, int c, __kernel_size_t size)
|
__FORTIFY_INLINE void *memchr(const void *p, int c, __kernel_size_t size)
|
||||||
@@ -429,7 +454,7 @@ __FORTIFY_INLINE void *memchr(const void *p, int c, __kernel_size_t size)
|
|||||||
__read_overflow();
|
__read_overflow();
|
||||||
if (p_size < size)
|
if (p_size < size)
|
||||||
fortify_panic(__func__);
|
fortify_panic(__func__);
|
||||||
return __builtin_memchr(p, c, size);
|
return __underlying_memchr(p, c, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *__real_memchr_inv(const void *s, int c, size_t n) __RENAME(memchr_inv);
|
void *__real_memchr_inv(const void *s, int c, size_t n) __RENAME(memchr_inv);
|
||||||
@@ -460,11 +485,22 @@ __FORTIFY_INLINE char *strcpy(char *p, const char *q)
|
|||||||
size_t p_size = __builtin_object_size(p, 0);
|
size_t p_size = __builtin_object_size(p, 0);
|
||||||
size_t q_size = __builtin_object_size(q, 0);
|
size_t q_size = __builtin_object_size(q, 0);
|
||||||
if (p_size == (size_t)-1 && q_size == (size_t)-1)
|
if (p_size == (size_t)-1 && q_size == (size_t)-1)
|
||||||
return __builtin_strcpy(p, q);
|
return __underlying_strcpy(p, q);
|
||||||
memcpy(p, q, strlen(q) + 1);
|
memcpy(p, q, strlen(q) + 1);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Don't use these outside the FORITFY_SOURCE implementation */
|
||||||
|
#undef __underlying_memchr
|
||||||
|
#undef __underlying_memcmp
|
||||||
|
#undef __underlying_memcpy
|
||||||
|
#undef __underlying_memmove
|
||||||
|
#undef __underlying_memset
|
||||||
|
#undef __underlying_strcat
|
||||||
|
#undef __underlying_strcpy
|
||||||
|
#undef __underlying_strlen
|
||||||
|
#undef __underlying_strncat
|
||||||
|
#undef __underlying_strncpy
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user