mirror of
https://github.com/t2linux/kernel.git
synced 2026-04-30 13:48:59 -07:00
Merge branch 'akpm' (patches from Andrew)
Merge updates from Andrew Morton: - a few misc things - ocfs2 updates - most of MM * emailed patches from Andrew Morton <akpm@linux-foundation.org>: (132 commits) hugetlbfs: dirty pages as they are added to pagecache mm: export add_swap_extent() mm: split SWP_FILE into SWP_ACTIVATED and SWP_FS tools/testing/selftests/vm/map_fixed_noreplace.c: add test for MAP_FIXED_NOREPLACE mm: thp: relocate flush_cache_range() in migrate_misplaced_transhuge_page() mm: thp: fix mmu_notifier in migrate_misplaced_transhuge_page() mm: thp: fix MADV_DONTNEED vs migrate_misplaced_transhuge_page race condition mm/kasan/quarantine.c: make quarantine_lock a raw_spinlock_t mm/gup: cache dev_pagemap while pinning pages Revert "x86/e820: put !E820_TYPE_RAM regions into memblock.reserved" mm: return zero_resv_unavail optimization mm: zero remaining unavailable struct pages tools/testing/selftests/vm/gup_benchmark.c: add MAP_HUGETLB option tools/testing/selftests/vm/gup_benchmark.c: add MAP_SHARED option tools/testing/selftests/vm/gup_benchmark.c: allow user specified file tools/testing/selftests/vm/gup_benchmark.c: fix 'write' flag usage mm/gup_benchmark.c: add additional pinning methods mm/gup_benchmark.c: time put_page() mm: don't raise MEMCG_OOM event due to failed high-order allocation mm/page-writeback.c: fix range_cyclic writeback vs writepages deadlock ...
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
================================
|
||||
PSI - Pressure Stall Information
|
||||
================================
|
||||
|
||||
:Date: April, 2018
|
||||
:Author: Johannes Weiner <hannes@cmpxchg.org>
|
||||
|
||||
When CPU, memory or IO devices are contended, workloads experience
|
||||
latency spikes, throughput losses, and run the risk of OOM kills.
|
||||
|
||||
Without an accurate measure of such contention, users are forced to
|
||||
either play it safe and under-utilize their hardware resources, or
|
||||
roll the dice and frequently suffer the disruptions resulting from
|
||||
excessive overcommit.
|
||||
|
||||
The psi feature identifies and quantifies the disruptions caused by
|
||||
such resource crunches and the time impact it has on complex workloads
|
||||
or even entire systems.
|
||||
|
||||
Having an accurate measure of productivity losses caused by resource
|
||||
scarcity aids users in sizing workloads to hardware--or provisioning
|
||||
hardware according to workload demand.
|
||||
|
||||
As psi aggregates this information in realtime, systems can be managed
|
||||
dynamically using techniques such as load shedding, migrating jobs to
|
||||
other systems or data centers, or strategically pausing or killing low
|
||||
priority or restartable batch jobs.
|
||||
|
||||
This allows maximizing hardware utilization without sacrificing
|
||||
workload health or risking major disruptions such as OOM kills.
|
||||
|
||||
Pressure interface
|
||||
==================
|
||||
|
||||
Pressure information for each resource is exported through the
|
||||
respective file in /proc/pressure/ -- cpu, memory, and io.
|
||||
|
||||
The format for CPU is as such:
|
||||
|
||||
some avg10=0.00 avg60=0.00 avg300=0.00 total=0
|
||||
|
||||
and for memory and IO:
|
||||
|
||||
some avg10=0.00 avg60=0.00 avg300=0.00 total=0
|
||||
full avg10=0.00 avg60=0.00 avg300=0.00 total=0
|
||||
|
||||
The "some" line indicates the share of time in which at least some
|
||||
tasks are stalled on a given resource.
|
||||
|
||||
The "full" line indicates the share of time in which all non-idle
|
||||
tasks are stalled on a given resource simultaneously. In this state
|
||||
actual CPU cycles are going to waste, and a workload that spends
|
||||
extended time in this state is considered to be thrashing. This has
|
||||
severe impact on performance, and it's useful to distinguish this
|
||||
situation from a state where some tasks are stalled but the CPU is
|
||||
still doing productive work. As such, time spent in this subset of the
|
||||
stall state is tracked separately and exported in the "full" averages.
|
||||
|
||||
The ratios are tracked as recent trends over ten, sixty, and three
|
||||
hundred second windows, which gives insight into short term events as
|
||||
well as medium and long term trends. The total absolute stall time is
|
||||
tracked and exported as well, to allow detection of latency spikes
|
||||
which wouldn't necessarily make a dent in the time averages, or to
|
||||
average trends over custom time frames.
|
||||
|
||||
Cgroup2 interface
|
||||
=================
|
||||
|
||||
In a system with a CONFIG_CGROUP=y kernel and the cgroup2 filesystem
|
||||
mounted, pressure stall information is also tracked for tasks grouped
|
||||
into cgroups. Each subdirectory in the cgroupfs mountpoint contains
|
||||
cpu.pressure, memory.pressure, and io.pressure files; the format is
|
||||
the same as the /proc/pressure/ files.
|
||||
@@ -966,6 +966,12 @@ All time durations are in microseconds.
|
||||
$PERIOD duration. "max" for $MAX indicates no limit. If only
|
||||
one number is written, $MAX is updated.
|
||||
|
||||
cpu.pressure
|
||||
A read-only nested-key file which exists on non-root cgroups.
|
||||
|
||||
Shows pressure stall information for CPU. See
|
||||
Documentation/accounting/psi.txt for details.
|
||||
|
||||
|
||||
Memory
|
||||
------
|
||||
@@ -1127,6 +1133,10 @@ PAGE_SIZE multiple when read back.
|
||||
disk readahead. For now OOM in memory cgroup kills
|
||||
tasks iff shortage has happened inside page fault.
|
||||
|
||||
This event is not raised if the OOM killer is not
|
||||
considered as an option, e.g. for failed high-order
|
||||
allocations.
|
||||
|
||||
oom_kill
|
||||
The number of processes belonging to this cgroup
|
||||
killed by any kind of OOM killer.
|
||||
@@ -1271,6 +1281,12 @@ PAGE_SIZE multiple when read back.
|
||||
higher than the limit for an extended period of time. This
|
||||
reduces the impact on the workload and memory management.
|
||||
|
||||
memory.pressure
|
||||
A read-only nested-key file which exists on non-root cgroups.
|
||||
|
||||
Shows pressure stall information for memory. See
|
||||
Documentation/accounting/psi.txt for details.
|
||||
|
||||
|
||||
Usage Guidelines
|
||||
~~~~~~~~~~~~~~~~
|
||||
@@ -1408,6 +1424,12 @@ IO Interface Files
|
||||
|
||||
8:16 rbps=2097152 wbps=max riops=max wiops=max
|
||||
|
||||
io.pressure
|
||||
A read-only nested-key file which exists on non-root cgroups.
|
||||
|
||||
Shows pressure stall information for IO. See
|
||||
Documentation/accounting/psi.txt for details.
|
||||
|
||||
|
||||
Writeback
|
||||
~~~~~~~~~
|
||||
|
||||
@@ -4851,6 +4851,18 @@
|
||||
This is actually a boot loader parameter; the value is
|
||||
passed to the kernel using a special protocol.
|
||||
|
||||
vm_debug[=options] [KNL] Available with CONFIG_DEBUG_VM=y.
|
||||
May slow down system boot speed, especially when
|
||||
enabled on systems with a large amount of memory.
|
||||
All options are enabled by default, and this
|
||||
interface is meant to allow for selectively
|
||||
enabling or disabling specific virtual memory
|
||||
debugging features.
|
||||
|
||||
Available options are:
|
||||
P Enable page structure init time poisoning
|
||||
- Disable all of the above options
|
||||
|
||||
vmalloc=nn[KMG] [KNL,BOOT] Forces the vmalloc area to have an exact
|
||||
size of <nn>. This can be used to increase the
|
||||
minimum size (128MB on x86). It can also be used to
|
||||
|
||||
@@ -858,6 +858,7 @@ Writeback: 0 kB
|
||||
AnonPages: 861800 kB
|
||||
Mapped: 280372 kB
|
||||
Shmem: 644 kB
|
||||
KReclaimable: 168048 kB
|
||||
Slab: 284364 kB
|
||||
SReclaimable: 159856 kB
|
||||
SUnreclaim: 124508 kB
|
||||
@@ -925,6 +926,9 @@ AnonHugePages: Non-file backed huge pages mapped into userspace page tables
|
||||
ShmemHugePages: Memory used by shared memory (shmem) and tmpfs allocated
|
||||
with huge pages
|
||||
ShmemPmdMapped: Shared memory mapped into userspace with huge pages
|
||||
KReclaimable: Kernel allocations that the kernel will attempt to reclaim
|
||||
under memory pressure. Includes SReclaimable (below), and other
|
||||
direct allocations with a shrinker.
|
||||
Slab: in-kernel data structures cache
|
||||
SReclaimable: Part of Slab, that might be reclaimed, such as caches
|
||||
SUnreclaim: Part of Slab, that cannot be reclaimed on memory pressure
|
||||
|
||||
@@ -36,9 +36,10 @@ debugging is enabled. Format:
|
||||
|
||||
slub_debug=<Debug-Options>
|
||||
Enable options for all slabs
|
||||
slub_debug=<Debug-Options>,<slab name>
|
||||
Enable options only for select slabs
|
||||
|
||||
slub_debug=<Debug-Options>,<slab name1>,<slab name2>,...
|
||||
Enable options only for select slabs (no spaces
|
||||
after a comma)
|
||||
|
||||
Possible debug options are::
|
||||
|
||||
@@ -62,7 +63,12 @@ Trying to find an issue in the dentry cache? Try::
|
||||
|
||||
slub_debug=,dentry
|
||||
|
||||
to only enable debugging on the dentry cache.
|
||||
to only enable debugging on the dentry cache. You may use an asterisk at the
|
||||
end of the slab name, in order to cover all slabs with the same prefix. For
|
||||
example, here's how you can poison the dentry cache as well as all kmalloc
|
||||
slabs:
|
||||
|
||||
slub_debug=P,kmalloc-*,dentry
|
||||
|
||||
Red zoning and tracking may realign the slab. We can just apply sanity checks
|
||||
to the dentry cache with::
|
||||
|
||||
@@ -90,12 +90,12 @@ pci proc | -- | -- | WC |
|
||||
Advanced APIs for drivers
|
||||
-------------------------
|
||||
A. Exporting pages to users with remap_pfn_range, io_remap_pfn_range,
|
||||
vm_insert_pfn
|
||||
vmf_insert_pfn
|
||||
|
||||
Drivers wanting to export some pages to userspace do it by using mmap
|
||||
interface and a combination of
|
||||
1) pgprot_noncached()
|
||||
2) io_remap_pfn_range() or remap_pfn_range() or vm_insert_pfn()
|
||||
2) io_remap_pfn_range() or remap_pfn_range() or vmf_insert_pfn()
|
||||
|
||||
With PAT support, a new API pgprot_writecombine is being added. So, drivers can
|
||||
continue to use the above sequence, with either pgprot_noncached() or
|
||||
|
||||
@@ -31,6 +31,8 @@ config ALPHA
|
||||
select ODD_RT_SIGACTION
|
||||
select OLD_SIGSUSPEND
|
||||
select CPU_NO_EFFICIENT_FFS if !ALPHA_EV67
|
||||
select HAVE_MEMBLOCK
|
||||
select NO_BOOTMEM
|
||||
help
|
||||
The Alpha is a 64-bit general-purpose processor designed and
|
||||
marketed by the Digital Equipment Corporation of blessed memory,
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/initrd.h>
|
||||
#include <linux/bootmem.h>
|
||||
#include <linux/memblock.h>
|
||||
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/cacheflush.h>
|
||||
@@ -241,8 +242,7 @@ albacore_init_arch(void)
|
||||
size / 1024);
|
||||
}
|
||||
#endif
|
||||
reserve_bootmem_node(NODE_DATA(0), pci_mem, memtop -
|
||||
pci_mem, BOOTMEM_DEFAULT);
|
||||
memblock_reserve(pci_mem, memtop - pci_mem);
|
||||
printk("irongate_init_arch: temporarily reserving "
|
||||
"region %08lx-%08lx for PCI\n", pci_mem, memtop - 1);
|
||||
}
|
||||
|
||||
+12
-86
@@ -30,6 +30,7 @@
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/bootmem.h>
|
||||
#include <linux/memblock.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/root_dev.h>
|
||||
@@ -312,9 +313,7 @@ setup_memory(void *kernel_end)
|
||||
{
|
||||
struct memclust_struct * cluster;
|
||||
struct memdesc_struct * memdesc;
|
||||
unsigned long start_kernel_pfn, end_kernel_pfn;
|
||||
unsigned long bootmap_size, bootmap_pages, bootmap_start;
|
||||
unsigned long start, end;
|
||||
unsigned long kernel_size;
|
||||
unsigned long i;
|
||||
|
||||
/* Find free clusters, and init and free the bootmem accordingly. */
|
||||
@@ -322,6 +321,8 @@ setup_memory(void *kernel_end)
|
||||
(hwrpb->mddt_offset + (unsigned long) hwrpb);
|
||||
|
||||
for_each_mem_cluster(memdesc, cluster, i) {
|
||||
unsigned long end;
|
||||
|
||||
printk("memcluster %lu, usage %01lx, start %8lu, end %8lu\n",
|
||||
i, cluster->usage, cluster->start_pfn,
|
||||
cluster->start_pfn + cluster->numpages);
|
||||
@@ -335,6 +336,9 @@ setup_memory(void *kernel_end)
|
||||
end = cluster->start_pfn + cluster->numpages;
|
||||
if (end > max_low_pfn)
|
||||
max_low_pfn = end;
|
||||
|
||||
memblock_add(PFN_PHYS(cluster->start_pfn),
|
||||
cluster->numpages << PAGE_SHIFT);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -363,87 +367,9 @@ setup_memory(void *kernel_end)
|
||||
max_low_pfn = mem_size_limit;
|
||||
}
|
||||
|
||||
/* Find the bounds of kernel memory. */
|
||||
start_kernel_pfn = PFN_DOWN(KERNEL_START_PHYS);
|
||||
end_kernel_pfn = PFN_UP(virt_to_phys(kernel_end));
|
||||
bootmap_start = -1;
|
||||
|
||||
try_again:
|
||||
if (max_low_pfn <= end_kernel_pfn)
|
||||
panic("not enough memory to boot");
|
||||
|
||||
/* We need to know how many physically contiguous pages
|
||||
we'll need for the bootmap. */
|
||||
bootmap_pages = bootmem_bootmap_pages(max_low_pfn);
|
||||
|
||||
/* Now find a good region where to allocate the bootmap. */
|
||||
for_each_mem_cluster(memdesc, cluster, i) {
|
||||
if (cluster->usage & 3)
|
||||
continue;
|
||||
|
||||
start = cluster->start_pfn;
|
||||
end = start + cluster->numpages;
|
||||
if (start >= max_low_pfn)
|
||||
continue;
|
||||
if (end > max_low_pfn)
|
||||
end = max_low_pfn;
|
||||
if (start < start_kernel_pfn) {
|
||||
if (end > end_kernel_pfn
|
||||
&& end - end_kernel_pfn >= bootmap_pages) {
|
||||
bootmap_start = end_kernel_pfn;
|
||||
break;
|
||||
} else if (end > start_kernel_pfn)
|
||||
end = start_kernel_pfn;
|
||||
} else if (start < end_kernel_pfn)
|
||||
start = end_kernel_pfn;
|
||||
if (end - start >= bootmap_pages) {
|
||||
bootmap_start = start;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (bootmap_start == ~0UL) {
|
||||
max_low_pfn >>= 1;
|
||||
goto try_again;
|
||||
}
|
||||
|
||||
/* Allocate the bootmap and mark the whole MM as reserved. */
|
||||
bootmap_size = init_bootmem(bootmap_start, max_low_pfn);
|
||||
|
||||
/* Mark the free regions. */
|
||||
for_each_mem_cluster(memdesc, cluster, i) {
|
||||
if (cluster->usage & 3)
|
||||
continue;
|
||||
|
||||
start = cluster->start_pfn;
|
||||
end = cluster->start_pfn + cluster->numpages;
|
||||
if (start >= max_low_pfn)
|
||||
continue;
|
||||
if (end > max_low_pfn)
|
||||
end = max_low_pfn;
|
||||
if (start < start_kernel_pfn) {
|
||||
if (end > end_kernel_pfn) {
|
||||
free_bootmem(PFN_PHYS(start),
|
||||
(PFN_PHYS(start_kernel_pfn)
|
||||
- PFN_PHYS(start)));
|
||||
printk("freeing pages %ld:%ld\n",
|
||||
start, start_kernel_pfn);
|
||||
start = end_kernel_pfn;
|
||||
} else if (end > start_kernel_pfn)
|
||||
end = start_kernel_pfn;
|
||||
} else if (start < end_kernel_pfn)
|
||||
start = end_kernel_pfn;
|
||||
if (start >= end)
|
||||
continue;
|
||||
|
||||
free_bootmem(PFN_PHYS(start), PFN_PHYS(end) - PFN_PHYS(start));
|
||||
printk("freeing pages %ld:%ld\n", start, end);
|
||||
}
|
||||
|
||||
/* Reserve the bootmap memory. */
|
||||
reserve_bootmem(PFN_PHYS(bootmap_start), bootmap_size,
|
||||
BOOTMEM_DEFAULT);
|
||||
printk("reserving pages %ld:%ld\n", bootmap_start, bootmap_start+PFN_UP(bootmap_size));
|
||||
/* Reserve the kernel memory. */
|
||||
kernel_size = virt_to_phys(kernel_end) - KERNEL_START_PHYS;
|
||||
memblock_reserve(KERNEL_START_PHYS, kernel_size);
|
||||
|
||||
#ifdef CONFIG_BLK_DEV_INITRD
|
||||
initrd_start = INITRD_START;
|
||||
@@ -459,8 +385,8 @@ setup_memory(void *kernel_end)
|
||||
initrd_end,
|
||||
phys_to_virt(PFN_PHYS(max_low_pfn)));
|
||||
} else {
|
||||
reserve_bootmem(virt_to_phys((void *)initrd_start),
|
||||
INITRD_SIZE, BOOTMEM_DEFAULT);
|
||||
memblock_reserve(virt_to_phys((void *)initrd_start),
|
||||
INITRD_SIZE);
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_BLK_DEV_INITRD */
|
||||
|
||||
+13
-100
@@ -11,6 +11,7 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/bootmem.h>
|
||||
#include <linux/memblock.h>
|
||||
#include <linux/swap.h>
|
||||
#include <linux/initrd.h>
|
||||
#include <linux/pfn.h>
|
||||
@@ -59,12 +60,10 @@ setup_memory_node(int nid, void *kernel_end)
|
||||
struct memclust_struct * cluster;
|
||||
struct memdesc_struct * memdesc;
|
||||
unsigned long start_kernel_pfn, end_kernel_pfn;
|
||||
unsigned long bootmap_size, bootmap_pages, bootmap_start;
|
||||
unsigned long start, end;
|
||||
unsigned long node_pfn_start, node_pfn_end;
|
||||
unsigned long node_min_pfn, node_max_pfn;
|
||||
int i;
|
||||
unsigned long node_datasz = PFN_UP(sizeof(pg_data_t));
|
||||
int show_init = 0;
|
||||
|
||||
/* Find the bounds of current node */
|
||||
@@ -134,24 +133,14 @@ setup_memory_node(int nid, void *kernel_end)
|
||||
/* Cute trick to make sure our local node data is on local memory */
|
||||
node_data[nid] = (pg_data_t *)(__va(node_min_pfn << PAGE_SHIFT));
|
||||
#endif
|
||||
/* Quasi-mark the pg_data_t as in-use */
|
||||
node_min_pfn += node_datasz;
|
||||
if (node_min_pfn >= node_max_pfn) {
|
||||
printk(" not enough mem to reserve NODE_DATA");
|
||||
return;
|
||||
}
|
||||
NODE_DATA(nid)->bdata = &bootmem_node_data[nid];
|
||||
|
||||
printk(" Detected node memory: start %8lu, end %8lu\n",
|
||||
node_min_pfn, node_max_pfn);
|
||||
|
||||
DBGDCONT(" DISCONTIG: node_data[%d] is at 0x%p\n", nid, NODE_DATA(nid));
|
||||
DBGDCONT(" DISCONTIG: NODE_DATA(%d)->bdata is at 0x%p\n", nid, NODE_DATA(nid)->bdata);
|
||||
|
||||
/* Find the bounds of kernel memory. */
|
||||
start_kernel_pfn = PFN_DOWN(KERNEL_START_PHYS);
|
||||
end_kernel_pfn = PFN_UP(virt_to_phys(kernel_end));
|
||||
bootmap_start = -1;
|
||||
|
||||
if (!nid && (node_max_pfn < end_kernel_pfn || node_min_pfn > start_kernel_pfn))
|
||||
panic("kernel loaded out of ram");
|
||||
@@ -161,89 +150,11 @@ setup_memory_node(int nid, void *kernel_end)
|
||||
has much larger alignment than 8Mb, so it's safe. */
|
||||
node_min_pfn &= ~((1UL << (MAX_ORDER-1))-1);
|
||||
|
||||
/* We need to know how many physically contiguous pages
|
||||
we'll need for the bootmap. */
|
||||
bootmap_pages = bootmem_bootmap_pages(node_max_pfn-node_min_pfn);
|
||||
memblock_add(PFN_PHYS(node_min_pfn),
|
||||
(node_max_pfn - node_min_pfn) << PAGE_SHIFT);
|
||||
|
||||
/* Now find a good region where to allocate the bootmap. */
|
||||
for_each_mem_cluster(memdesc, cluster, i) {
|
||||
if (cluster->usage & 3)
|
||||
continue;
|
||||
|
||||
start = cluster->start_pfn;
|
||||
end = start + cluster->numpages;
|
||||
|
||||
if (start >= node_max_pfn || end <= node_min_pfn)
|
||||
continue;
|
||||
|
||||
if (end > node_max_pfn)
|
||||
end = node_max_pfn;
|
||||
if (start < node_min_pfn)
|
||||
start = node_min_pfn;
|
||||
|
||||
if (start < start_kernel_pfn) {
|
||||
if (end > end_kernel_pfn
|
||||
&& end - end_kernel_pfn >= bootmap_pages) {
|
||||
bootmap_start = end_kernel_pfn;
|
||||
break;
|
||||
} else if (end > start_kernel_pfn)
|
||||
end = start_kernel_pfn;
|
||||
} else if (start < end_kernel_pfn)
|
||||
start = end_kernel_pfn;
|
||||
if (end - start >= bootmap_pages) {
|
||||
bootmap_start = start;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (bootmap_start == -1)
|
||||
panic("couldn't find a contiguous place for the bootmap");
|
||||
|
||||
/* Allocate the bootmap and mark the whole MM as reserved. */
|
||||
bootmap_size = init_bootmem_node(NODE_DATA(nid), bootmap_start,
|
||||
node_min_pfn, node_max_pfn);
|
||||
DBGDCONT(" bootmap_start %lu, bootmap_size %lu, bootmap_pages %lu\n",
|
||||
bootmap_start, bootmap_size, bootmap_pages);
|
||||
|
||||
/* Mark the free regions. */
|
||||
for_each_mem_cluster(memdesc, cluster, i) {
|
||||
if (cluster->usage & 3)
|
||||
continue;
|
||||
|
||||
start = cluster->start_pfn;
|
||||
end = cluster->start_pfn + cluster->numpages;
|
||||
|
||||
if (start >= node_max_pfn || end <= node_min_pfn)
|
||||
continue;
|
||||
|
||||
if (end > node_max_pfn)
|
||||
end = node_max_pfn;
|
||||
if (start < node_min_pfn)
|
||||
start = node_min_pfn;
|
||||
|
||||
if (start < start_kernel_pfn) {
|
||||
if (end > end_kernel_pfn) {
|
||||
free_bootmem_node(NODE_DATA(nid), PFN_PHYS(start),
|
||||
(PFN_PHYS(start_kernel_pfn)
|
||||
- PFN_PHYS(start)));
|
||||
printk(" freeing pages %ld:%ld\n",
|
||||
start, start_kernel_pfn);
|
||||
start = end_kernel_pfn;
|
||||
} else if (end > start_kernel_pfn)
|
||||
end = start_kernel_pfn;
|
||||
} else if (start < end_kernel_pfn)
|
||||
start = end_kernel_pfn;
|
||||
if (start >= end)
|
||||
continue;
|
||||
|
||||
free_bootmem_node(NODE_DATA(nid), PFN_PHYS(start), PFN_PHYS(end) - PFN_PHYS(start));
|
||||
printk(" freeing pages %ld:%ld\n", start, end);
|
||||
}
|
||||
|
||||
/* Reserve the bootmap memory. */
|
||||
reserve_bootmem_node(NODE_DATA(nid), PFN_PHYS(bootmap_start),
|
||||
bootmap_size, BOOTMEM_DEFAULT);
|
||||
printk(" reserving pages %ld:%ld\n", bootmap_start, bootmap_start+PFN_UP(bootmap_size));
|
||||
NODE_DATA(nid)->node_start_pfn = node_min_pfn;
|
||||
NODE_DATA(nid)->node_present_pages = node_max_pfn - node_min_pfn;
|
||||
|
||||
node_set_online(nid);
|
||||
}
|
||||
@@ -251,6 +162,7 @@ setup_memory_node(int nid, void *kernel_end)
|
||||
void __init
|
||||
setup_memory(void *kernel_end)
|
||||
{
|
||||
unsigned long kernel_size;
|
||||
int nid;
|
||||
|
||||
show_mem_layout();
|
||||
@@ -262,6 +174,9 @@ setup_memory(void *kernel_end)
|
||||
for (nid = 0; nid < MAX_NUMNODES; nid++)
|
||||
setup_memory_node(nid, kernel_end);
|
||||
|
||||
kernel_size = virt_to_phys(kernel_end) - KERNEL_START_PHYS;
|
||||
memblock_reserve(KERNEL_START_PHYS, kernel_size);
|
||||
|
||||
#ifdef CONFIG_BLK_DEV_INITRD
|
||||
initrd_start = INITRD_START;
|
||||
if (initrd_start) {
|
||||
@@ -279,9 +194,8 @@ setup_memory(void *kernel_end)
|
||||
phys_to_virt(PFN_PHYS(max_low_pfn)));
|
||||
} else {
|
||||
nid = kvaddr_to_nid(initrd_start);
|
||||
reserve_bootmem_node(NODE_DATA(nid),
|
||||
virt_to_phys((void *)initrd_start),
|
||||
INITRD_SIZE, BOOTMEM_DEFAULT);
|
||||
memblock_reserve(virt_to_phys((void *)initrd_start),
|
||||
INITRD_SIZE);
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_BLK_DEV_INITRD */
|
||||
@@ -303,9 +217,8 @@ void __init paging_init(void)
|
||||
dma_local_pfn = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
|
||||
|
||||
for_each_online_node(nid) {
|
||||
bootmem_data_t *bdata = &bootmem_node_data[nid];
|
||||
unsigned long start_pfn = bdata->node_min_pfn;
|
||||
unsigned long end_pfn = bdata->node_low_pfn;
|
||||
unsigned long start_pfn = NODE_DATA(nid)->node_start_pfn;
|
||||
unsigned long end_pfn = start_pfn + NODE_DATA(nid)->node_present_pages;
|
||||
|
||||
if (dma_local_pfn >= end_pfn - start_pfn)
|
||||
zones_size[ZONE_DMA] = end_pfn - start_pfn;
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
* ptes.
|
||||
* (The valid bit is automatically cleared by set_pte_at for PROT_NONE ptes).
|
||||
*/
|
||||
#define __HAVE_ARCH_HUGE_PTEP_GET
|
||||
static inline pte_t huge_ptep_get(pte_t *ptep)
|
||||
{
|
||||
pte_t retval = *ptep;
|
||||
@@ -37,35 +38,4 @@ static inline pte_t huge_ptep_get(pte_t *ptep)
|
||||
return retval;
|
||||
}
|
||||
|
||||
static inline void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
|
||||
pte_t *ptep, pte_t pte)
|
||||
{
|
||||
set_pte_at(mm, addr, ptep, pte);
|
||||
}
|
||||
|
||||
static inline void huge_ptep_clear_flush(struct vm_area_struct *vma,
|
||||
unsigned long addr, pte_t *ptep)
|
||||
{
|
||||
ptep_clear_flush(vma, addr, ptep);
|
||||
}
|
||||
|
||||
static inline void huge_ptep_set_wrprotect(struct mm_struct *mm,
|
||||
unsigned long addr, pte_t *ptep)
|
||||
{
|
||||
ptep_set_wrprotect(mm, addr, ptep);
|
||||
}
|
||||
|
||||
static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
|
||||
unsigned long addr, pte_t *ptep)
|
||||
{
|
||||
return ptep_get_and_clear(mm, addr, ptep);
|
||||
}
|
||||
|
||||
static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma,
|
||||
unsigned long addr, pte_t *ptep,
|
||||
pte_t pte, int dirty)
|
||||
{
|
||||
return ptep_set_access_flags(vma, addr, ptep, pte, dirty);
|
||||
}
|
||||
|
||||
#endif /* _ASM_ARM_HUGETLB_3LEVEL_H */
|
||||
|
||||
@@ -23,18 +23,8 @@
|
||||
#define _ASM_ARM_HUGETLB_H
|
||||
|
||||
#include <asm/page.h>
|
||||
#include <asm-generic/hugetlb.h>
|
||||
|
||||
#include <asm/hugetlb-3level.h>
|
||||
|
||||
static inline void hugetlb_free_pgd_range(struct mmu_gather *tlb,
|
||||
unsigned long addr, unsigned long end,
|
||||
unsigned long floor,
|
||||
unsigned long ceiling)
|
||||
{
|
||||
free_pgd_range(tlb, addr, end, floor, ceiling);
|
||||
}
|
||||
|
||||
#include <asm-generic/hugetlb.h>
|
||||
|
||||
static inline int is_hugepage_only_range(struct mm_struct *mm,
|
||||
unsigned long addr, unsigned long len)
|
||||
@@ -42,27 +32,6 @@ static inline int is_hugepage_only_range(struct mm_struct *mm,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int prepare_hugepage_range(struct file *file,
|
||||
unsigned long addr, unsigned long len)
|
||||
{
|
||||
struct hstate *h = hstate_file(file);
|
||||
if (len & ~huge_page_mask(h))
|
||||
return -EINVAL;
|
||||
if (addr & ~huge_page_mask(h))
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int huge_pte_none(pte_t pte)
|
||||
{
|
||||
return pte_none(pte);
|
||||
}
|
||||
|
||||
static inline pte_t huge_pte_wrprotect(pte_t pte)
|
||||
{
|
||||
return pte_wrprotect(pte);
|
||||
}
|
||||
|
||||
static inline void arch_clear_hugepage_flags(struct page *page)
|
||||
{
|
||||
clear_bit(PG_dcache_clean, &page->flags);
|
||||
|
||||
@@ -20,48 +20,18 @@
|
||||
|
||||
#include <asm/page.h>
|
||||
|
||||
#define __HAVE_ARCH_HUGE_PTEP_GET
|
||||
static inline pte_t huge_ptep_get(pte_t *ptep)
|
||||
{
|
||||
return READ_ONCE(*ptep);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static inline void hugetlb_free_pgd_range(struct mmu_gather *tlb,
|
||||
unsigned long addr, unsigned long end,
|
||||
unsigned long floor,
|
||||
unsigned long ceiling)
|
||||
{
|
||||
free_pgd_range(tlb, addr, end, floor, ceiling);
|
||||
}
|
||||
|
||||
static inline int is_hugepage_only_range(struct mm_struct *mm,
|
||||
unsigned long addr, unsigned long len)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int prepare_hugepage_range(struct file *file,
|
||||
unsigned long addr, unsigned long len)
|
||||
{
|
||||
struct hstate *h = hstate_file(file);
|
||||
if (len & ~huge_page_mask(h))
|
||||
return -EINVAL;
|
||||
if (addr & ~huge_page_mask(h))
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int huge_pte_none(pte_t pte)
|
||||
{
|
||||
return pte_none(pte);
|
||||
}
|
||||
|
||||
static inline pte_t huge_pte_wrprotect(pte_t pte)
|
||||
{
|
||||
return pte_wrprotect(pte);
|
||||
}
|
||||
|
||||
static inline void arch_clear_hugepage_flags(struct page *page)
|
||||
{
|
||||
clear_bit(PG_dcache_clean, &page->flags);
|
||||
@@ -70,20 +40,25 @@ static inline void arch_clear_hugepage_flags(struct page *page)
|
||||
extern pte_t arch_make_huge_pte(pte_t entry, struct vm_area_struct *vma,
|
||||
struct page *page, int writable);
|
||||
#define arch_make_huge_pte arch_make_huge_pte
|
||||
#define __HAVE_ARCH_HUGE_SET_HUGE_PTE_AT
|
||||
extern void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
|
||||
pte_t *ptep, pte_t pte);
|
||||
#define __HAVE_ARCH_HUGE_PTEP_SET_ACCESS_FLAGS
|
||||
extern int huge_ptep_set_access_flags(struct vm_area_struct *vma,
|
||||
unsigned long addr, pte_t *ptep,
|
||||
pte_t pte, int dirty);
|
||||
#define __HAVE_ARCH_HUGE_PTEP_GET_AND_CLEAR
|
||||
extern pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
|
||||
unsigned long addr, pte_t *ptep);
|
||||
#define __HAVE_ARCH_HUGE_PTEP_SET_WRPROTECT
|
||||
extern void huge_ptep_set_wrprotect(struct mm_struct *mm,
|
||||
unsigned long addr, pte_t *ptep);
|
||||
#define __HAVE_ARCH_HUGE_PTEP_CLEAR_FLUSH
|
||||
extern void huge_ptep_clear_flush(struct vm_area_struct *vma,
|
||||
unsigned long addr, pte_t *ptep);
|
||||
#define __HAVE_ARCH_HUGE_PTE_CLEAR
|
||||
extern void huge_pte_clear(struct mm_struct *mm, unsigned long addr,
|
||||
pte_t *ptep, unsigned long sz);
|
||||
#define huge_pte_clear huge_pte_clear
|
||||
extern void set_huge_swap_pte_at(struct mm_struct *mm, unsigned long addr,
|
||||
pte_t *ptep, pte_t pte, unsigned long sz);
|
||||
#define set_huge_swap_pte_at set_huge_swap_pte_at
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#ifndef __ASM_STRING_H
|
||||
#define __ASM_STRING_H
|
||||
|
||||
#ifndef CONFIG_KASAN
|
||||
#define __HAVE_ARCH_STRRCHR
|
||||
extern char *strrchr(const char *, int c);
|
||||
|
||||
@@ -34,6 +35,13 @@ extern __kernel_size_t strlen(const char *);
|
||||
#define __HAVE_ARCH_STRNLEN
|
||||
extern __kernel_size_t strnlen(const char *, __kernel_size_t);
|
||||
|
||||
#define __HAVE_ARCH_MEMCMP
|
||||
extern int memcmp(const void *, const void *, size_t);
|
||||
|
||||
#define __HAVE_ARCH_MEMCHR
|
||||
extern void *memchr(const void *, int, __kernel_size_t);
|
||||
#endif
|
||||
|
||||
#define __HAVE_ARCH_MEMCPY
|
||||
extern void *memcpy(void *, const void *, __kernel_size_t);
|
||||
extern void *__memcpy(void *, const void *, __kernel_size_t);
|
||||
@@ -42,16 +50,10 @@ extern void *__memcpy(void *, const void *, __kernel_size_t);
|
||||
extern void *memmove(void *, const void *, __kernel_size_t);
|
||||
extern void *__memmove(void *, const void *, __kernel_size_t);
|
||||
|
||||
#define __HAVE_ARCH_MEMCHR
|
||||
extern void *memchr(const void *, int, __kernel_size_t);
|
||||
|
||||
#define __HAVE_ARCH_MEMSET
|
||||
extern void *memset(void *, int, __kernel_size_t);
|
||||
extern void *__memset(void *, int, __kernel_size_t);
|
||||
|
||||
#define __HAVE_ARCH_MEMCMP
|
||||
extern int memcmp(const void *, const void *, size_t);
|
||||
|
||||
#ifdef CONFIG_ARCH_HAS_UACCESS_FLUSHCACHE
|
||||
#define __HAVE_ARCH_MEMCPY_FLUSHCACHE
|
||||
void memcpy_flushcache(void *dst, const void *src, size_t cnt);
|
||||
|
||||
@@ -44,20 +44,23 @@ EXPORT_SYMBOL(__arch_copy_in_user);
|
||||
EXPORT_SYMBOL(memstart_addr);
|
||||
|
||||
/* string / mem functions */
|
||||
#ifndef CONFIG_KASAN
|
||||
EXPORT_SYMBOL(strchr);
|
||||
EXPORT_SYMBOL(strrchr);
|
||||
EXPORT_SYMBOL(strcmp);
|
||||
EXPORT_SYMBOL(strncmp);
|
||||
EXPORT_SYMBOL(strlen);
|
||||
EXPORT_SYMBOL(strnlen);
|
||||
EXPORT_SYMBOL(memcmp);
|
||||
EXPORT_SYMBOL(memchr);
|
||||
#endif
|
||||
|
||||
EXPORT_SYMBOL(memset);
|
||||
EXPORT_SYMBOL(memcpy);
|
||||
EXPORT_SYMBOL(memmove);
|
||||
EXPORT_SYMBOL(__memset);
|
||||
EXPORT_SYMBOL(__memcpy);
|
||||
EXPORT_SYMBOL(__memmove);
|
||||
EXPORT_SYMBOL(memchr);
|
||||
EXPORT_SYMBOL(memcmp);
|
||||
|
||||
/* atomic bitops */
|
||||
EXPORT_SYMBOL(set_bit);
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
* Returns:
|
||||
* x0 - address of first occurrence of 'c' or 0
|
||||
*/
|
||||
ENTRY(memchr)
|
||||
WEAK(memchr)
|
||||
and w1, w1, #0xff
|
||||
1: subs x2, x2, #1
|
||||
b.mi 2f
|
||||
|
||||
@@ -58,7 +58,7 @@ pos .req x11
|
||||
limit_wd .req x12
|
||||
mask .req x13
|
||||
|
||||
ENTRY(memcmp)
|
||||
WEAK(memcmp)
|
||||
cbz limit, .Lret0
|
||||
eor tmp1, src1, src2
|
||||
tst tmp1, #7
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
* Returns:
|
||||
* x0 - address of first occurrence of 'c' or 0
|
||||
*/
|
||||
ENTRY(strchr)
|
||||
WEAK(strchr)
|
||||
and w1, w1, #0xff
|
||||
1: ldrb w2, [x0], #1
|
||||
cmp w2, w1
|
||||
|
||||
@@ -60,7 +60,7 @@ tmp3 .req x9
|
||||
zeroones .req x10
|
||||
pos .req x11
|
||||
|
||||
ENTRY(strcmp)
|
||||
WEAK(strcmp)
|
||||
eor tmp1, src1, src2
|
||||
mov zeroones, #REP8_01
|
||||
tst tmp1, #7
|
||||
|
||||
@@ -56,7 +56,7 @@ pos .req x12
|
||||
#define REP8_7f 0x7f7f7f7f7f7f7f7f
|
||||
#define REP8_80 0x8080808080808080
|
||||
|
||||
ENTRY(strlen)
|
||||
WEAK(strlen)
|
||||
mov zeroones, #REP8_01
|
||||
bic src, srcin, #15
|
||||
ands tmp1, srcin, #15
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user