Merge branch 'akpm' (patches from Andrew)
Merge misc updates from Andrew Morton: "191 patches. Subsystems affected by this patch series: kthread, ia64, scripts, ntfs, squashfs, ocfs2, kernel/watchdog, and mm (gup, pagealloc, slab, slub, kmemleak, dax, debug, pagecache, gup, swap, memcg, pagemap, mprotect, bootmem, dma, tracing, vmalloc, kasan, initialization, pagealloc, and memory-failure)" * emailed patches from Andrew Morton <akpm@linux-foundation.org>: (191 commits) mm,hwpoison: make get_hwpoison_page() call get_any_page() mm,hwpoison: send SIGBUS with error virutal address mm/page_alloc: split pcp->high across all online CPUs for cpuless nodes mm/page_alloc: allow high-order pages to be stored on the per-cpu lists mm: replace CONFIG_FLAT_NODE_MEM_MAP with CONFIG_FLATMEM mm: replace CONFIG_NEED_MULTIPLE_NODES with CONFIG_NUMA docs: remove description of DISCONTIGMEM arch, mm: remove stale mentions of DISCONIGMEM mm: remove CONFIG_DISCONTIGMEM m68k: remove support for DISCONTIGMEM arc: remove support for DISCONTIGMEM arc: update comment about HIGHMEM implementation alpha: remove DISCONTIGMEM and NUMA mm/page_alloc: move free_the_page mm/page_alloc: fix counting of managed_pages mm/page_alloc: improve memmap_pages dbg msg mm: drop SECTION_SHIFT in code comments mm/page_alloc: introduce vm.percpu_pagelist_high_fraction mm/page_alloc: limit the number of pages on PCP lists when reclaim is active mm/page_alloc: scale the number of pages that are batch freed ...
This commit is contained in:
Коммит
65090f30ab
|
@ -3591,6 +3591,12 @@
|
|||
off: turn off poisoning (default)
|
||||
on: turn on poisoning
|
||||
|
||||
page_reporting.page_reporting_order=
|
||||
[KNL] Minimal page reporting order
|
||||
Format: <integer>
|
||||
Adjust the minimal page reporting order. The page
|
||||
reporting is disabled when it exceeds (MAX_ORDER-1).
|
||||
|
||||
panic= [KNL] Kernel behaviour on panic: delay <timeout>
|
||||
timeout > 0: seconds before rebooting
|
||||
timeout = 0: wait forever
|
||||
|
|
|
@ -39,7 +39,7 @@ in principle, they should work in any architecture where these
|
|||
subsystems are present.
|
||||
|
||||
A periodic hrtimer runs to generate interrupts and kick the watchdog
|
||||
task. An NMI perf event is generated every "watchdog_thresh"
|
||||
job. An NMI perf event is generated every "watchdog_thresh"
|
||||
(compile-time initialized to 10 and configurable through sysctl of the
|
||||
same name) seconds to check for hardlockups. If any CPU in the system
|
||||
does not receive any hrtimer interrupt during that time the
|
||||
|
@ -47,7 +47,7 @@ does not receive any hrtimer interrupt during that time the
|
|||
generate a kernel warning or call panic, depending on the
|
||||
configuration.
|
||||
|
||||
The watchdog task is a high priority kernel thread that updates a
|
||||
The watchdog job runs in a stop scheduling thread that updates a
|
||||
timestamp every time it is scheduled. If that timestamp is not updated
|
||||
for 2*watchdog_thresh seconds (the softlockup threshold) the
|
||||
'softlockup detector' (coded inside the hrtimer callback function)
|
||||
|
|
|
@ -1297,11 +1297,11 @@ This parameter can be used to control the soft lockup detector.
|
|||
= =================================
|
||||
|
||||
The soft lockup detector monitors CPUs for threads that are hogging the CPUs
|
||||
without rescheduling voluntarily, and thus prevent the 'watchdog/N' threads
|
||||
from running. The mechanism depends on the CPUs ability to respond to timer
|
||||
interrupts which are needed for the 'watchdog/N' threads to be woken up by
|
||||
the watchdog timer function, otherwise the NMI watchdog — if enabled — can
|
||||
detect a hard lockup condition.
|
||||
without rescheduling voluntarily, and thus prevent the 'migration/N' threads
|
||||
from running, causing the watchdog work fail to execute. The mechanism depends
|
||||
on the CPUs ability to respond to timer interrupts which are needed for the
|
||||
watchdog work to be queued by the watchdog timer function, otherwise the NMI
|
||||
watchdog — if enabled — can detect a hard lockup condition.
|
||||
|
||||
|
||||
stack_erasing
|
||||
|
|
|
@ -64,7 +64,7 @@ Currently, these files are in /proc/sys/vm:
|
|||
- overcommit_ratio
|
||||
- page-cluster
|
||||
- panic_on_oom
|
||||
- percpu_pagelist_fraction
|
||||
- percpu_pagelist_high_fraction
|
||||
- stat_interval
|
||||
- stat_refresh
|
||||
- numa_stat
|
||||
|
@ -790,22 +790,24 @@ panic_on_oom=2+kdump gives you very strong tool to investigate
|
|||
why oom happens. You can get snapshot.
|
||||
|
||||
|
||||
percpu_pagelist_fraction
|
||||
========================
|
||||
percpu_pagelist_high_fraction
|
||||
=============================
|
||||
|
||||
This is the fraction of pages at most (high mark pcp->high) in each zone that
|
||||
are allocated for each per cpu page list. The min value for this is 8. It
|
||||
means that we don't allow more than 1/8th of pages in each zone to be
|
||||
allocated in any single per_cpu_pagelist. This entry only changes the value
|
||||
of hot per cpu pagelists. User can specify a number like 100 to allocate
|
||||
1/100th of each zone to each per cpu page list.
|
||||
This is the fraction of pages in each zone that are can be stored to
|
||||
per-cpu page lists. It is an upper boundary that is divided depending
|
||||
on the number of online CPUs. The min value for this is 8 which means
|
||||
that we do not allow more than 1/8th of pages in each zone to be stored
|
||||
on per-cpu page lists. This entry only changes the value of hot per-cpu
|
||||
page lists. A user can specify a number like 100 to allocate 1/100th of
|
||||
each zone between per-cpu lists.
|
||||
|
||||
The batch value of each per cpu pagelist is also updated as a result. It is
|
||||
set to pcp->high/4. The upper limit of batch is (PAGE_SHIFT * 8)
|
||||
The batch value of each per-cpu page list remains the same regardless of
|
||||
the value of the high fraction so allocation latencies are unaffected.
|
||||
|
||||
The initial value is zero. Kernel does not use this value at boot time to set
|
||||
the high water marks for each per cpu page list. If the user writes '0' to this
|
||||
sysctl, it will revert to this default behavior.
|
||||
The initial value is zero. Kernel uses this value to set the high pcp->high
|
||||
mark based on the low watermark for the zone and the number of local
|
||||
online CPUs. If the user writes '0' to this sysctl, it will revert to
|
||||
this default behavior.
|
||||
|
||||
|
||||
stat_interval
|
||||
|
@ -936,12 +938,12 @@ allocations, THP and hugetlbfs pages.
|
|||
|
||||
To make it sensible with respect to the watermark_scale_factor
|
||||
parameter, the unit is in fractions of 10,000. The default value of
|
||||
15,000 on !DISCONTIGMEM configurations means that up to 150% of the high
|
||||
watermark will be reclaimed in the event of a pageblock being mixed due
|
||||
to fragmentation. The level of reclaim is determined by the number of
|
||||
fragmentation events that occurred in the recent past. If this value is
|
||||
smaller than a pageblock then a pageblocks worth of pages will be reclaimed
|
||||
(e.g. 2MB on 64-bit x86). A boost factor of 0 will disable the feature.
|
||||
15,000 means that up to 150% of the high watermark will be reclaimed in the
|
||||
event of a pageblock being mixed due to fragmentation. The level of reclaim
|
||||
is determined by the number of fragmentation events that occurred in the
|
||||
recent past. If this value is smaller than a pageblock then a pageblocks
|
||||
worth of pages will be reclaimed (e.g. 2MB on 64-bit x86). A boost factor
|
||||
of 0 will disable the feature.
|
||||
|
||||
|
||||
watermark_scale_factor
|
||||
|
|
|
@ -447,11 +447,10 @@ When a test fails due to a failed ``kmalloc``::
|
|||
|
||||
When a test fails due to a missing KASAN report::
|
||||
|
||||
# kmalloc_double_kzfree: EXPECTATION FAILED at lib/test_kasan.c:629
|
||||
Expected kasan_data->report_expected == kasan_data->report_found, but
|
||||
kasan_data->report_expected == 1
|
||||
kasan_data->report_found == 0
|
||||
not ok 28 - kmalloc_double_kzfree
|
||||
# kmalloc_double_kzfree: EXPECTATION FAILED at lib/test_kasan.c:974
|
||||
KASAN failure expected in "kfree_sensitive(ptr)", but none occurred
|
||||
not ok 44 - kmalloc_double_kzfree
|
||||
|
||||
|
||||
At the end the cumulative status of all KASAN tests is printed. On success::
|
||||
|
||||
|
|
|
@ -14,15 +14,11 @@ for the CPU. Then there could be several contiguous ranges at
|
|||
completely distinct addresses. And, don't forget about NUMA, where
|
||||
different memory banks are attached to different CPUs.
|
||||
|
||||
Linux abstracts this diversity using one of the three memory models:
|
||||
FLATMEM, DISCONTIGMEM and SPARSEMEM. Each architecture defines what
|
||||
Linux abstracts this diversity using one of the two memory models:
|
||||
FLATMEM and SPARSEMEM. Each architecture defines what
|
||||
memory models it supports, what the default memory model is and
|
||||
whether it is possible to manually override that default.
|
||||
|
||||
.. note::
|
||||
At time of this writing, DISCONTIGMEM is considered deprecated,
|
||||
although it is still in use by several architectures.
|
||||
|
||||
All the memory models track the status of physical page frames using
|
||||
struct page arranged in one or more arrays.
|
||||
|
||||
|
@ -63,43 +59,6 @@ straightforward: `PFN - ARCH_PFN_OFFSET` is an index to the
|
|||
The `ARCH_PFN_OFFSET` defines the first page frame number for
|
||||
systems with physical memory starting at address different from 0.
|
||||
|
||||
DISCONTIGMEM
|
||||
============
|
||||
|
||||
The DISCONTIGMEM model treats the physical memory as a collection of
|
||||
`nodes` similarly to how Linux NUMA support does. For each node Linux
|
||||
constructs an independent memory management subsystem represented by
|
||||
`struct pglist_data` (or `pg_data_t` for short). Among other
|
||||
things, `pg_data_t` holds the `node_mem_map` array that maps
|
||||
physical pages belonging to that node. The `node_start_pfn` field of
|
||||
`pg_data_t` is the number of the first page frame belonging to that
|
||||
node.
|
||||
|
||||
The architecture setup code should call :c:func:`free_area_init_node` for
|
||||
each node in the system to initialize the `pg_data_t` object and its
|
||||
`node_mem_map`.
|
||||
|
||||
Every `node_mem_map` behaves exactly as FLATMEM's `mem_map` -
|
||||
every physical page frame in a node has a `struct page` entry in the
|
||||
`node_mem_map` array. When DISCONTIGMEM is enabled, a portion of the
|
||||
`flags` field of the `struct page` encodes the node number of the
|
||||
node hosting that page.
|
||||
|
||||
The conversion between a PFN and the `struct page` in the
|
||||
DISCONTIGMEM model became slightly more complex as it has to determine
|
||||
which node hosts the physical page and which `pg_data_t` object
|
||||
holds the `struct page`.
|
||||
|
||||
Architectures that support DISCONTIGMEM provide :c:func:`pfn_to_nid`
|
||||
to convert PFN to the node number. The opposite conversion helper
|
||||
:c:func:`page_to_nid` is generic as it uses the node number encoded in
|
||||
page->flags.
|
||||
|
||||
Once the node number is known, the PFN can be used to index
|
||||
appropriate `node_mem_map` array to access the `struct page` and
|
||||
the offset of the `struct page` from the `node_mem_map` plus
|
||||
`node_start_pfn` is the PFN of that page.
|
||||
|
||||
SPARSEMEM
|
||||
=========
|
||||
|
||||
|
|
|
@ -549,29 +549,12 @@ config NR_CPUS
|
|||
MARVEL support can handle a maximum of 32 CPUs, all the others
|
||||
with working support have a maximum of 4 CPUs.
|
||||
|
||||
config ARCH_DISCONTIGMEM_ENABLE
|
||||
bool "Discontiguous Memory Support"
|
||||
depends on BROKEN
|
||||
help
|
||||
Say Y to support efficient handling of discontiguous physical memory,
|
||||
for architectures which are either NUMA (Non-Uniform Memory Access)
|
||||
or have huge holes in the physical address space for other reasons.
|
||||
See <file:Documentation/vm/numa.rst> for more.
|
||||
|
||||
config ARCH_SPARSEMEM_ENABLE
|
||||
bool "Sparse Memory Support"
|
||||
help
|
||||
Say Y to support efficient handling of discontiguous physical memory,
|
||||
for systems that have huge holes in the physical address space.
|
||||
|
||||
config NUMA
|
||||
bool "NUMA Support (EXPERIMENTAL)"
|
||||
depends on DISCONTIGMEM && BROKEN
|
||||
help
|
||||
Say Y to compile the kernel to support NUMA (Non-Uniform Memory
|
||||
Access). This option is for configuring high-end multiprocessor
|
||||
server machines. If in doubt, say N.
|
||||
|
||||
config ALPHA_WTINT
|
||||
bool "Use WTINT" if ALPHA_SRM || ALPHA_GENERIC
|
||||
default y if ALPHA_QEMU
|
||||
|
@ -596,11 +579,6 @@ config ALPHA_WTINT
|
|||
|
||||
If unsure, say N.
|
||||
|
||||
config NODES_SHIFT
|
||||
int
|
||||
default "7"
|
||||
depends on NEED_MULTIPLE_NODES
|
||||
|
||||
# LARGE_VMALLOC is racy, if you *really* need it then fix it first
|
||||
config ALPHA_LARGE_VMALLOC
|
||||
bool
|
||||
|
|
|
@ -99,12 +99,6 @@ struct alpha_machine_vector
|
|||
|
||||
const char *vector_name;
|
||||
|
||||
/* NUMA information */
|
||||
int (*pa_to_nid)(unsigned long);
|
||||
int (*cpuid_to_nid)(int);
|
||||
unsigned long (*node_mem_start)(int);
|
||||
unsigned long (*node_mem_size)(int);
|
||||
|
||||
/* System specific parameters. */
|
||||
union {
|
||||
struct {
|
||||
|
|
|
@ -1,100 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Written by Kanoj Sarcar (kanoj@sgi.com) Aug 99
|
||||
* Adapted for the alpha wildfire architecture Jan 2001.
|
||||
*/
|
||||
#ifndef _ASM_MMZONE_H_
|
||||
#define _ASM_MMZONE_H_
|
||||
|
||||
#ifdef CONFIG_DISCONTIGMEM
|
||||
|
||||
#include <asm/smp.h>
|
||||
|
||||
/*
|
||||
* Following are macros that are specific to this numa platform.
|
||||
*/
|
||||
|
||||
extern pg_data_t node_data[];
|
||||
|
||||
#define alpha_pa_to_nid(pa) \
|
||||
(alpha_mv.pa_to_nid \
|
||||
? alpha_mv.pa_to_nid(pa) \
|
||||
: (0))
|
||||
#define node_mem_start(nid) \
|
||||
(alpha_mv.node_mem_start \
|
||||
? alpha_mv.node_mem_start(nid) \
|
||||
: (0UL))
|
||||
#define node_mem_size(nid) \
|
||||
(alpha_mv.node_mem_size \
|
||||
? alpha_mv.node_mem_size(nid) \
|
||||
: ((nid) ? (0UL) : (~0UL)))
|
||||
|
||||
#define pa_to_nid(pa) alpha_pa_to_nid(pa)
|
||||
#define NODE_DATA(nid) (&node_data[(nid)])
|
||||
|
||||
#define node_localnr(pfn, nid) ((pfn) - NODE_DATA(nid)->node_start_pfn)
|
||||
|
||||
#if 1
|
||||
#define PLAT_NODE_DATA_LOCALNR(p, n) \
|
||||
(((p) >> PAGE_SHIFT) - PLAT_NODE_DATA(n)->gendata.node_start_pfn)
|
||||
#else
|
||||
static inline unsigned long
|
||||
PLAT_NODE_DATA_LOCALNR(unsigned long p, int n)
|
||||
{
|
||||
unsigned long temp;
|
||||
temp = p >> PAGE_SHIFT;
|
||||
return temp - PLAT_NODE_DATA(n)->gendata.node_start_pfn;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Following are macros that each numa implementation must define.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Given a kernel address, find the home node of the underlying memory.
|
||||
*/
|
||||
#define kvaddr_to_nid(kaddr) pa_to_nid(__pa(kaddr))
|
||||
|
||||
/*
|
||||
* Given a kaddr, LOCAL_BASE_ADDR finds the owning node of the memory
|
||||
* and returns the kaddr corresponding to first physical page in the
|
||||
* node's mem_map.
|
||||
*/
|
||||
#define LOCAL_BASE_ADDR(kaddr) \
|
||||
((unsigned long)__va(NODE_DATA(kvaddr_to_nid(kaddr))->node_start_pfn \
|
||||
<< PAGE_SHIFT))
|
||||
|
||||
/* XXX: FIXME -- nyc */
|
||||
#define kern_addr_valid(kaddr) (0)
|
||||
|
||||
#define mk_pte(page, pgprot) \
|
||||
({ \
|
||||
pte_t pte; \
|
||||
unsigned long pfn; \
|
||||
\
|
||||
pfn = page_to_pfn(page) << 32; \
|
||||
pte_val(pte) = pfn | pgprot_val(pgprot); \
|
||||
\
|
||||
pte; \
|
||||
})
|
||||
|
||||
#define pte_page(x) \
|
||||
({ \
|
||||
unsigned long kvirt; \
|
||||
struct page * __xx; \
|
||||
\
|
||||
kvirt = (unsigned long)__va(pte_val(x) >> (32-PAGE_SHIFT)); \
|
||||
__xx = virt_to_page(kvirt); \
|
||||
\
|
||||
__xx; \
|
||||
})
|
||||
|
||||
#define pfn_to_nid(pfn) pa_to_nid(((u64)(pfn) << PAGE_SHIFT))
|
||||
#define pfn_valid(pfn) \
|
||||
(((pfn) - node_start_pfn(pfn_to_nid(pfn))) < \
|
||||
node_spanned_pages(pfn_to_nid(pfn))) \
|
||||
|
||||
#endif /* CONFIG_DISCONTIGMEM */
|
||||
|
||||
#endif /* _ASM_MMZONE_H_ */
|
|
@ -206,7 +206,6 @@ extern unsigned long __zero_page(void);
|
|||
#define page_to_pa(page) (page_to_pfn(page) << PAGE_SHIFT)
|
||||
#define pte_pfn(pte) (pte_val(pte) >> 32)
|
||||
|
||||
#ifndef CONFIG_DISCONTIGMEM
|
||||
#define pte_page(pte) pfn_to_page(pte_pfn(pte))
|
||||
#define mk_pte(page, pgprot) \
|
||||
({ \
|
||||
|
@ -215,7 +214,6 @@ extern unsigned long __zero_page(void);
|
|||
pte_val(pte) = (page_to_pfn(page) << 32) | pgprot_val(pgprot); \
|
||||
pte; \
|
||||
})
|
||||
#endif
|
||||
|
||||
extern inline pte_t pfn_pte(unsigned long physpfn, pgprot_t pgprot)
|
||||
{ pte_t pte; pte_val(pte) = (PHYS_TWIDDLE(physpfn) << 32) | pgprot_val(pgprot); return pte; }
|
||||
|
@ -330,9 +328,7 @@ extern inline pte_t mk_swap_pte(unsigned long type, unsigned long offset)
|
|||
#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) })
|
||||
#define __swp_entry_to_pte(x) ((pte_t) { (x).val })
|
||||
|
||||
#ifndef CONFIG_DISCONTIGMEM
|
||||
#define kern_addr_valid(addr) (1)
|
||||
#endif
|
||||
|
||||
#define pte_ERROR(e) \
|
||||
printk("%s:%d: bad pte %016lx.\n", __FILE__, __LINE__, pte_val(e))
|
||||
|
|
|
@ -7,45 +7,6 @@
|
|||
#include <linux/numa.h>
|
||||
#include <asm/machvec.h>
|
||||
|
||||
#ifdef CONFIG_NUMA
|
||||
static inline int cpu_to_node(int cpu)
|
||||
{
|
||||
int node;
|
||||
|
||||
if (!alpha_mv.cpuid_to_nid)
|
||||
return 0;
|
||||
|
||||
node = alpha_mv.cpuid_to_nid(cpu);
|
||||
|
||||
#ifdef DEBUG_NUMA
|
||||
BUG_ON(node < 0);
|
||||
#endif
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
extern struct cpumask node_to_cpumask_map[];
|
||||
/* FIXME: This is dumb, recalculating every time. But simple. */
|
||||
static const struct cpumask *cpumask_of_node(int node)
|
||||
{
|
||||
int cpu;
|
||||
|
||||
if (node == NUMA_NO_NODE)
|
||||
return cpu_all_mask;
|
||||
|
||||
cpumask_clear(&node_to_cpumask_map[node]);
|
||||
|
||||
for_each_online_cpu(cpu) {
|
||||
if (cpu_to_node(cpu) == node)
|
||||
cpumask_set_cpu(cpu, node_to_cpumask_map[node]);
|
||||
}
|
||||
|
||||
return &node_to_cpumask_map[node];
|
||||
}
|
||||
|
||||
#define cpumask_of_pcibus(bus) (cpu_online_mask)
|
||||
|
||||
#endif /* !CONFIG_NUMA */
|
||||
# include <asm-generic/topology.h>
|
||||
|
||||
#endif /* _ASM_ALPHA_TOPOLOGY_H */
|
||||
|
|
|
@ -287,8 +287,7 @@ io7_init_hose(struct io7 *io7, int port)
|
|||
/*
|
||||
* Set up window 0 for scatter-gather 8MB at 8MB.
|
||||
*/
|
||||
hose->sg_isa = iommu_arena_new_node(marvel_cpuid_to_nid(io7->pe),
|
||||
hose, 0x00800000, 0x00800000, 0);
|
||||
hose->sg_isa = iommu_arena_new_node(0, hose, 0x00800000, 0x00800000, 0);
|
||||
hose->sg_isa->align_entry = 8; /* cache line boundary */
|
||||
csrs->POx_WBASE[0].csr =
|
||||
hose->sg_isa->dma_base | wbase_m_ena | wbase_m_sg;
|
||||
|
@ -305,8 +304,7 @@ io7_init_hose(struct io7 *io7, int port)
|
|||
/*
|
||||
* Set up window 2 for scatter-gather (up-to) 1GB at 3GB.
|
||||
*/
|
||||
hose->sg_pci = iommu_arena_new_node(marvel_cpuid_to_nid(io7->pe),
|
||||
hose, 0xc0000000, 0x40000000, 0);
|
||||
hose->sg_pci = iommu_arena_new_node(0, hose, 0xc0000000, 0x40000000, 0);
|
||||
hose->sg_pci->align_entry = 8; /* cache line boundary */
|
||||
csrs->POx_WBASE[2].csr =
|
||||
hose->sg_pci->dma_base | wbase_m_ena | wbase_m_sg;
|
||||
|
@ -843,53 +841,8 @@ EXPORT_SYMBOL(marvel_ioportmap);
|
|||
EXPORT_SYMBOL(marvel_ioread8);
|
||||
EXPORT_SYMBOL(marvel_iowrite8);
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* NUMA Support
|
||||
*/
|
||||
/**********
|
||||
* FIXME - for now each cpu is a node by itself
|
||||
* -- no real support for striped mode
|
||||
**********
|
||||
*/
|
||||
int
|
||||
marvel_pa_to_nid(unsigned long pa)
|
||||
{
|
||||
int cpuid;
|
||||
|
||||
if ((pa >> 43) & 1) /* I/O */
|
||||
cpuid = (~(pa >> 35) & 0xff);
|
||||
else /* mem */
|
||||
cpuid = ((pa >> 34) & 0x3) | ((pa >> (37 - 2)) & (0x1f << 2));
|
||||
|
||||
return marvel_cpuid_to_nid(cpuid);
|
||||
}
|
||||
|
||||
int
|
||||
marvel_cpuid_to_nid(int cpuid)
|
||||
{
|
||||
return cpuid;
|
||||
}
|
||||
|
||||
unsigned long
|
||||
marvel_node_mem_start(int nid)
|
||||
{
|
||||
unsigned long pa;
|
||||
|
||||
pa = (nid & 0x3) | ((nid & (0x1f << 2)) << 1);
|
||||
pa <<= 34;
|
||||
|
||||
return pa;
|
||||
}
|
||||
|
||||
unsigned long
|
||||
marvel_node_mem_size(int nid)
|
||||
{
|
||||
return 16UL * 1024 * 1024 * 1024; /* 16GB */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* AGP GART Support.
|
||||
*/
|
||||
#include <linux/agp_backend.h>
|
||||
|
|
|
@ -434,39 +434,12 @@ wildfire_write_config(struct pci_bus *bus, unsigned int devfn, int where,
|
|||
return PCIBIOS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
struct pci_ops wildfire_pci_ops =
|
||||
struct pci_ops wildfire_pci_ops =
|
||||
{
|
||||
.read = wildfire_read_config,
|
||||
.write = wildfire_write_config,
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* NUMA Support
|
||||
*/
|
||||
int wildfire_pa_to_nid(unsigned long pa)
|
||||
{
|
||||
return pa >> 36;
|
||||
}
|
||||
|
||||
int wildfire_cpuid_to_nid(int cpuid)
|
||||
{
|
||||
/* assume 4 CPUs per node */
|
||||
return cpuid >> 2;
|
||||
}
|
||||
|
||||
unsigned long wildfire_node_mem_start(int nid)
|
||||
{
|
||||
/* 64GB per node */
|
||||
return (unsigned long)nid * (64UL * 1024 * 1024 * 1024);
|
||||
}
|
||||
|
||||
unsigned long wildfire_node_mem_size(int nid)
|
||||
{
|
||||
/* 64GB per node */
|
||||
return 64UL * 1024 * 1024 * 1024;
|
||||
}
|
||||
|
||||
#if DEBUG_DUMP_REGS
|
||||
|
||||
static void __init
|
||||
|
|
|
@ -71,33 +71,6 @@ iommu_arena_new_node(int nid, struct pci_controller *hose, dma_addr_t base,
|
|||
if (align < mem_size)
|
||||
align = mem_size;
|
||||
|
||||
|
||||
#ifdef CONFIG_DISCONTIGMEM
|
||||
|
||||
arena = memblock_alloc_node(sizeof(*arena), align, nid);
|
||||
if (!NODE_DATA(nid) || !arena) {
|
||||
printk("%s: couldn't allocate arena from node %d\n"
|
||||
" falling back to system-wide allocation\n",
|
||||
__func__, nid);
|
||||
arena = memblock_alloc(sizeof(*arena), SMP_CACHE_BYTES);
|
||||
if (!arena)
|
||||
panic("%s: Failed to allocate %zu bytes\n", __func__,
|
||||
sizeof(*arena));
|
||||
}
|
||||
|
||||
arena->ptes = memblock_alloc_node(sizeof(*arena), align, nid);
|
||||
if (!NODE_DATA(nid) || !arena->ptes) {
|
||||
printk("%s: couldn't allocate arena ptes from node %d\n"
|
||||
" falling back to system-wide allocation\n",
|
||||
__func__, nid);
|
||||
arena->ptes = memblock_alloc(mem_size, align);
|
||||
if (!arena->ptes)
|
||||
panic("%s: Failed to allocate %lu bytes align=0x%lx\n",
|
||||
__func__, mem_size, align);
|
||||
}
|
||||
|
||||
#else /* CONFIG_DISCONTIGMEM */
|
||||
|
||||
arena = memblock_alloc(sizeof(*arena), SMP_CACHE_BYTES);
|
||||
if (!arena)
|
||||
panic("%s: Failed to allocate %zu bytes\n", __func__,
|
||||
|
@ -107,8 +80,6 @@ iommu_arena_new_node(int nid, struct pci_controller *hose, dma_addr_t base,
|
|||
panic("%s: Failed to allocate %lu bytes align=0x%lx\n",
|
||||
__func__, mem_size, align);
|
||||
|
||||
#endif /* CONFIG_DISCONTIGMEM */
|
||||
|
||||
spin_lock_init(&arena->lock);
|
||||
arena->hose = hose;
|
||||
arena->dma_base = base;
|
||||
|
|
|
@ -49,10 +49,6 @@ extern void marvel_init_arch(void);
|
|||
extern void marvel_kill_arch(int);
|
||||
extern void marvel_machine_check(unsigned long, unsigned long);
|
||||
extern void marvel_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t);
|
||||
extern int marvel_pa_to_nid(unsigned long);
|
||||
extern int marvel_cpuid_to_nid(int);
|
||||
extern unsigned long marvel_node_mem_start(int);
|
||||
extern unsigned long marvel_node_mem_size(int);
|
||||
extern struct _alpha_agp_info *marvel_agp_info(void);
|
||||
struct io7 *marvel_find_io7(int pe);
|
||||
struct io7 *marvel_next_io7(struct io7 *prev);
|
||||
|
@ -101,10 +97,6 @@ extern void wildfire_init_arch(void);
|
|||
extern void wildfire_kill_arch(int);
|
||||
extern void wildfire_machine_check(unsigned long vector, unsigned long la_ptr);
|
||||
extern void wildfire_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t);
|
||||
extern int wildfire_pa_to_nid(unsigned long);
|
||||
extern int wildfire_cpuid_to_nid(int);
|
||||
extern unsigned long wildfire_node_mem_start(int);
|
||||
extern unsigned long wildfire_node_mem_size(int);
|
||||
|
||||
/* console.c */
|
||||
#ifdef CONFIG_VGA_HOSE
|
||||
|
|
|
@ -79,11 +79,6 @@ int alpha_l3_cacheshape;
|
|||
unsigned long alpha_verbose_mcheck = CONFIG_VERBOSE_MCHECK_ON;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NUMA
|
||||
struct cpumask node_to_cpumask_map[MAX_NUMNODES] __read_mostly;
|
||||
EXPORT_SYMBOL(node_to_cpumask_map);
|
||||
#endif
|
||||
|
||||
/* Which processor we booted from. */
|
||||
int boot_cpuid;
|
||||
|
||||
|
@ -305,7 +300,6 @@ move_initrd(unsigned long mem_limit)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_DISCONTIGMEM
|
||||
static void __init
|
||||
setup_memory(void *kernel_end)
|
||||
{
|
||||
|
@ -389,9 +383,6 @@ setup_memory(void *kernel_end)
|
|||
}
|
||||
#endif /* CONFIG_BLK_DEV_INITRD */
|
||||
}
|
||||
#else
|
||||
extern void setup_memory(void *);
|
||||
#endif /* !CONFIG_DISCONTIGMEM */
|
||||
|
||||
int __init
|
||||
page_is_ram(unsigned long pfn)
|
||||
|
@ -618,13 +609,6 @@ setup_arch(char **cmdline_p)
|
|||
"VERBOSE_MCHECK "
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_DISCONTIGMEM
|
||||
"DISCONTIGMEM "
|
||||
#ifdef CONFIG_NUMA
|
||||
"NUMA "
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_DEBUG_SPINLOCK
|
||||
"DEBUG_SPINLOCK "
|
||||
#endif
|
||||
|
|
|
@ -461,10 +461,5 @@ struct alpha_machine_vector marvel_ev7_mv __initmv = {
|
|||
.kill_arch = marvel_kill_arch,
|
||||
.pci_map_irq = marvel_map_irq,
|
||||
.pci_swizzle = common_swizzle,
|
||||
|
||||
.pa_to_nid = marvel_pa_to_nid,
|
||||
.cpuid_to_nid = marvel_cpuid_to_nid,
|
||||
.node_mem_start = marvel_node_mem_start,
|
||||
.node_mem_size = marvel_node_mem_size,
|
||||
};
|
||||
ALIAS_MV(marvel_ev7)
|
||||
|
|
|
@ -337,10 +337,5 @@ struct alpha_machine_vector wildfire_mv __initmv = {
|
|||
.kill_arch = wildfire_kill_arch,
|
||||
.pci_map_irq = wildfire_map_irq,
|
||||
.pci_swizzle = common_swizzle,
|
||||
|
||||
.pa_to_nid = wildfire_pa_to_nid,
|
||||
.cpuid_to_nid = wildfire_cpuid_to_nid,
|
||||
.node_mem_start = wildfire_node_mem_start,
|
||||
.node_mem_size = wildfire_node_mem_size,
|
||||
};
|
||||
ALIAS_MV(wildfire)
|
||||
|
|
|
@ -6,5 +6,3 @@
|
|||
ccflags-y := -Werror
|
||||
|
||||
obj-y := init.o fault.o
|
||||
|
||||
obj-$(CONFIG_DISCONTIGMEM) += numa.o
|
||||
|
|
|
@ -235,8 +235,6 @@ callback_init(void * kernel_end)
|
|||
return kernel_end;
|
||||
}
|
||||
|
||||
|
||||
#ifndef CONFIG_DISCONTIGMEM
|
||||
/*
|
||||
* paging_init() sets up the memory map.
|
||||
*/
|
||||
|
@ -257,7 +255,6 @@ void __init paging_init(void)
|
|||
/* Initialize the kernel's ZERO_PGE. */
|
||||
memset((void *)ZERO_PGE, 0, PAGE_SIZE);
|
||||
}
|
||||
#endif /* CONFIG_DISCONTIGMEM */
|
||||
|
||||
#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM)
|
||||
void
|
||||
|
|
|
@ -1,223 +0,0 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* linux/arch/alpha/mm/numa.c
|
||||
*
|
||||
* DISCONTIGMEM NUMA alpha support.
|
||||
*
|
||||
* Copyright (C) 2001 Andrea Arcangeli <andrea@suse.de> SuSE
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/memblock.h>
|
||||
#include <linux/swap.h>
|
||||
#include <linux/initrd.h>
|
||||
#include <linux/pfn.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <asm/hwrpb.h>
|
||||
#include <asm/sections.h>
|
||||
|
||||
pg_data_t node_data[MAX_NUMNODES];
|
||||
EXPORT_SYMBOL(node_data);
|
||||
|
||||
#undef DEBUG_DISCONTIG
|
||||
#ifdef DEBUG_DISCONTIG
|
||||
#define DBGDCONT(args...) printk(args)
|
||||
#else
|
||||
#define DBGDCONT(args...)
|
||||
#endif
|
||||
|
||||
#define for_each_mem_cluster(memdesc, _cluster, i) \
|
||||
for ((_cluster) = (memdesc)->cluster, (i) = 0; \
|
||||
(i) < (memdesc)->numclusters; (i)++, (_cluster)++)
|
||||
|
||||
static void __init show_mem_layout(void)
|
||||
{
|
||||
struct memclust_struct * cluster;
|
||||
struct memdesc_struct * memdesc;
|
||||
int i;
|
||||
|
||||
/* Find free clusters, and init and free the bootmem accordingly. */
|
||||
memdesc = (struct memdesc_struct *)
|
||||
(hwrpb->mddt_offset + (unsigned long) hwrpb);
|
||||
|
||||
printk("Raw memory layout:\n");
|
||||
for_each_mem_cluster(memdesc, cluster, i) {
|
||||
printk(" memcluster %2d, usage %1lx, start %8lu, end %8lu\n",
|
||||
i, cluster->usage, cluster->start_pfn,
|
||||
cluster->start_pfn + cluster->numpages);
|
||||
}
|
||||
}
|
||||
|
||||
static void __init
|
||||
setup_memory_node(int nid, void *kernel_end)
|
||||
{
|
||||
extern unsigned long mem_size_limit;
|
||||
struct memclust_struct * cluster;
|
||||
struct memdesc_struct * memdesc;
|
||||
unsigned long start_kernel_pfn, end_kernel_pfn;
|
||||
unsigned long start, end;
|
||||
unsigned long node_pfn_start, node_pfn_end;
|
||||
unsigned long node_min_pfn, node_max_pfn;
|
||||
int i;
|
||||
int show_init = 0;
|
||||
|
||||
/* Find the bounds of current node */
|
||||
node_pfn_start = (node_mem_start(nid)) >> PAGE_SHIFT;
|
||||
node_pfn_end = node_pfn_start + (node_mem_size(nid) >> PAGE_SHIFT);
|
||||
|
||||
/* Find free clusters, and init and free the bootmem accordingly. */
|
||||
memdesc = (struct memdesc_struct *)
|
||||
(hwrpb->mddt_offset + (unsigned long) hwrpb);
|
||||
|
||||
/* find the bounds of this node (node_min_pfn/node_max_pfn) */
|
||||
node_min_pfn = ~0UL;
|
||||
node_max_pfn = 0UL;
|
||||
for_each_mem_cluster(memdesc, cluster, i) {
|
||||
/* Bit 0 is console/PALcode reserved. Bit 1 is
|
||||
non-volatile memory -- we might want to mark
|
||||
this for later. */
|
||||
if (cluster->usage & 3)
|
||||
continue;
|
||||
|
||||
start = cluster->start_pfn;
|
||||
end = start + cluster->numpages;
|
||||
|
||||
if (start >= node_pfn_end || end <= node_pfn_start)
|
||||
continue;
|
||||
|
||||
if (!show_init) {
|
||||
show_init = 1;
|
||||
printk("Initializing bootmem allocator on Node ID %d\n", nid);
|
||||
}
|
||||
printk(" memcluster %2d, usage %1lx, start %8lu, end %8lu\n",
|
||||
i, cluster->usage, cluster->start_pfn,
|
||||
cluster->start_pfn + cluster->numpages);
|
||||
|
||||
if (start < node_pfn_start)
|
||||
start = node_pfn_start;
|
||||
if (end > node_pfn_end)
|
||||
end = node_pfn_end;
|
||||
|
||||
if (start < node_min_pfn)
|
||||
node_min_pfn = start;
|
||||
if (end > node_max_pfn)
|
||||
node_max_pfn = end;
|
||||
}
|
||||
|
||||
if (mem_size_limit && node_max_pfn > mem_size_limit) {
|
||||
static int msg_shown = 0;
|
||||
if (!msg_shown) {
|
||||
msg_shown = 1;
|
||||
printk("setup: forcing memory size to %ldK (from %ldK).\n",
|
||||
mem_size_limit << (PAGE_SHIFT - 10),
|
||||
node_max_pfn << (PAGE_SHIFT - 10));
|
||||
}
|
||||
node_max_pfn = mem_size_limit;
|
||||
}
|
||||
|
||||
if (node_min_pfn >= node_max_pfn)
|
||||
return;
|
||||
|
||||
/* Update global {min,max}_low_pfn from node information. */
|
||||
if (node_min_pfn < min_low_pfn)
|
||||
min_low_pfn = node_min_pfn;
|
||||
if (node_max_pfn > max_low_pfn)
|
||||
max_pfn = max_low_pfn = node_max_pfn;
|
||||
|
||||
#if 0 /* we'll try this one again in a little while */
|
||||
/* 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
|
||||
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));
|
||||
|
||||
/* Find the bounds of kernel memory. */
|
||||
start_kernel_pfn = PFN_DOWN(KERNEL_START_PHYS);
|
||||
end_kernel_pfn = PFN_UP(virt_to_phys(kernel_end));
|
||||
|
||||
if (!nid && (node_max_pfn < end_kernel_pfn || node_min_pfn > start_kernel_pfn))
|
||||
panic("kernel loaded out of ram");
|
||||
|
||||
memblock_add_node(PFN_PHYS(node_min_pfn),
|
||||
(node_max_pfn - node_min_pfn) << PAGE_SHIFT, nid);
|
||||
|
||||
/* Zone start phys-addr must be 2^(MAX_ORDER-1) aligned.
|
||||
Note that we round this down, not up - node memory
|
||||
has much larger alignment than 8Mb, so it's safe. */
|
||||
node_min_pfn &= ~((1UL << (MAX_ORDER-1))-1);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void __init
|
||||
setup_memory(void *kernel_end)
|
||||
{
|
||||
unsigned long kernel_size;
|
||||
int nid;
|
||||
|
||||
show_mem_layout();
|
||||
|
||||
nodes_clear(node_online_map);
|
||||
|
||||
min_low_pfn = ~0UL;
|
||||
max_low_pfn = 0UL;
|
||||
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) {
|
||||
extern void *move_initrd(unsigned long);
|
||||
|
||||
initrd_end = initrd_start+INITRD_SIZE;
|
||||
printk("Initial ramdisk at: 0x%p (%lu bytes)\n",
|
||||
(void *) initrd_start, INITRD_SIZE);
|
||||
|
||||
if ((void *)initrd_end > phys_to_virt(PFN_PHYS(max_low_pfn))) {
|
||||
if (!move_initrd(PFN_PHYS(max_low_pfn)))
|
||||
printk("initrd extends beyond end of memory "
|
||||
"(0x%08lx > 0x%p)\ndisabling initrd\n",
|
||||
initrd_end,
|
||||
phys_to_virt(PFN_PHYS(max_low_pfn)));
|
||||
} else {
|
||||
nid = kvaddr_to_nid(initrd_start);
|
||||
memblock_reserve(virt_to_phys((void *)initrd_start),
|
||||
INITRD_SIZE);
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_BLK_DEV_INITRD */
|
||||
}
|
||||
|
||||
void __init paging_init(void)
|
||||
{
|
||||
unsigned long max_zone_pfn[MAX_NR_ZONES] = {0, };
|
||||
unsigned long dma_local_pfn;
|
||||
|
||||
/*
|
||||
* The old global MAX_DMA_ADDRESS per-arch API doesn't fit
|
||||
* in the NUMA model, for now we convert it to a pfn and
|
||||
* we interpret this pfn as a local per-node information.
|
||||
* This issue isn't very important since none of these machines
|
||||
* have legacy ISA slots anyways.
|
||||
*/
|
||||
dma_local_pfn = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
|
||||
|
||||
max_zone_pfn[ZONE_DMA] = dma_local_pfn;
|
||||
max_zone_pfn[ZONE_NORMAL] = max_pfn;
|
||||
|
||||
free_area_init(max_zone_pfn);
|
||||
|
||||
/* Initialize the kernel's ZERO_PGE. */
|
||||
memset((void *)ZERO_PGE, 0, PAGE_SIZE);
|
||||
}
|
|
@ -62,10 +62,6 @@ config SCHED_OMIT_FRAME_POINTER
|
|||
config GENERIC_CSUM
|
||||
def_bool y
|
||||
|
||||
config ARCH_DISCONTIGMEM_ENABLE
|
||||
def_bool n
|
||||
depends on BROKEN
|
||||
|
||||
config ARCH_FLATMEM_ENABLE
|
||||
def_bool y
|
||||
|
||||
|
@ -344,15 +340,6 @@ config ARC_HUGEPAGE_16M
|
|||
|
||||
endchoice
|
||||
|
||||
config NODES_SHIFT
|
||||
int "Maximum NUMA Nodes (as a power of 2)"
|
||||
default "0" if !DISCONTIGMEM
|
||||
default "1" if DISCONTIGMEM
|
||||
depends on NEED_MULTIPLE_NODES
|
||||
help
|
||||
Accessing memory beyond 1GB (with or w/o PAE) requires 2 memory
|
||||
zones.
|
||||
|
||||
config ARC_COMPACT_IRQ_LEVELS
|
||||
depends on ISA_ARCOMPACT
|
||||
bool "Setup Timer IRQ as high Priority"
|
||||
|
|
|
@ -1,40 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (C) 2016 Synopsys, Inc. (www.synopsys.com)
|
||||
*/
|
||||
|
||||
#ifndef _ASM_ARC_MMZONE_H
|
||||
#define _ASM_ARC_MMZONE_H
|
||||
|
||||
#ifdef CONFIG_DISCONTIGMEM
|
||||
|
||||
extern struct pglist_data node_data[];
|
||||
#define NODE_DATA(nid) (&node_data[nid])
|
||||
|
||||
static inline int pfn_to_nid(unsigned long pfn)
|
||||
{
|
||||
int is_end_low = 1;
|
||||
|
||||
if (IS_ENABLED(CONFIG_ARC_HAS_PAE40))
|
||||
is_end_low = pfn <= virt_to_pfn(0xFFFFFFFFUL);
|
||||
|
||||
/*
|
||||
* node 0: lowmem: 0x8000_0000 to 0xFFFF_FFFF
|
||||
* node 1: HIGHMEM w/o PAE40: 0x0 to 0x7FFF_FFFF
|
||||
* HIGHMEM with PAE40: 0x1_0000_0000 to ...
|
||||
*/
|
||||
if (pfn >= ARCH_PFN_OFFSET && is_end_low)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int pfn_valid(unsigned long pfn)
|
||||
{
|
||||
int nid = pfn_to_nid(pfn);
|
||||
|
||||
return (pfn <= node_end_pfn(nid));
|
||||
}
|
||||
#endif /* CONFIG_DISCONTIGMEM */
|
||||
|
||||
#endif
|
|
@ -83,12 +83,12 @@ static void show_faulting_vma(unsigned long address)
|
|||
* non-inclusive vma
|
||||
*/
|
||||
mmap_read_lock(active_mm);
|
||||
vma = find_vma(active_mm, address);
|
||||
vma = vma_lookup(active_mm, address);
|
||||
|
||||
/* check against the find_vma( ) behaviour which returns the next VMA
|
||||
* if the container VMA is not found
|
||||
/* Lookup the vma at the address and report if the container VMA is not
|
||||
* found
|
||||
*/
|
||||
if (vma && (vma->vm_start <= address)) {
|
||||
if (vma) {
|
||||
char buf[ARC_PATH_MAX];
|
||||
char *nm = "?";
|
||||
|
||||
|
|
|
@ -32,11 +32,6 @@ unsigned long arch_pfn_offset;
|
|||
EXPORT_SYMBOL(arch_pfn_offset);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_DISCONTIGMEM
|
||||
struct pglist_data node_data[MAX_NUMNODES] __read_mostly;
|
||||
EXPORT_SYMBOL(node_data);
|
||||
#endif
|
||||
|
||||
long __init arc_get_mem_sz(void)
|
||||
{
|
||||
return low_mem_sz;
|
||||
|
@ -139,20 +134,14 @@ void __init setup_arch_memory(void)
|
|||
|
||||
#ifdef CONFIG_HIGHMEM
|
||||
/*
|
||||
* Populate a new node with highmem
|
||||
*
|
||||
* On ARC (w/o PAE) HIGHMEM addresses are actually smaller (0 based)
|
||||
* than addresses in normal ala low memory (0x8000_0000 based).
|
||||
* than addresses in normal aka low memory (0x8000_0000 based).
|
||||
* Even with PAE, the huge peripheral space hole would waste a lot of
|
||||
* mem with single mem_map[]. This warrants a mem_map per region design.
|
||||
* Thus HIGHMEM on ARC is imlemented with DISCONTIGMEM.
|
||||
*
|
||||
* DISCONTIGMEM in turns requires multiple nodes. node 0 above is
|
||||
* populated with normal memory zone while node 1 only has highmem
|
||||
* mem with single contiguous mem_map[].
|
||||
* Thus when HIGHMEM on ARC is enabled the memory map corresponding
|
||||
* to the hole is freed and ARC specific version of pfn_valid()
|
||||
* handles the hole in the memory map.
|
||||
*/
|
||||
#ifdef CONFIG_DISCONTIGMEM
|
||||
node_set_online(1);
|
||||
#endif
|
||||
|
||||
min_high_pfn = PFN_DOWN(high_mem_start);
|
||||
max_high_pfn = PFN_DOWN(high_mem_start + high_mem_sz);
|
||||
|
|
|
@ -253,7 +253,7 @@ extern struct cpu_tlb_fns cpu_tlb;
|
|||
* space.
|
||||
* - mm - mm_struct describing address space
|
||||
*
|
||||
* flush_tlb_range(mm,start,end)
|
||||
* flush_tlb_range(vma,start,end)
|
||||
*
|
||||
* Invalidate a range of TLB entries in the specified
|
||||
* address space.
|
||||
|
@ -261,18 +261,11 @@ extern struct cpu_tlb_fns cpu_tlb;
|
|||
* - start - start address (may not be aligned)
|
||||
* - end - end address (exclusive, may not be aligned)
|
||||
*
|
||||
* flush_tlb_page(vaddr,vma)
|
||||
* flush_tlb_page(vma, uaddr)
|
||||
*
|
||||
* Invalidate the specified page in the specified address range.
|
||||
* - vma - vm_area_struct describing address range
|
||||
* - vaddr - virtual address (may not be aligned)
|
||||
* - vma - vma_struct describing address range
|
||||
*
|
||||
* flush_kern_tlb_page(kaddr)
|
||||
*
|
||||
* Invalidate the TLB entry for the specified page. The address
|
||||
* will be in the kernels virtual memory space. Current uses
|
||||
* only require the D-TLB to be invalidated.
|
||||
* - kaddr - Kernel virtual memory address
|
||||
*/
|
||||
|
||||
/*
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
*
|
||||
* - start - start address (may not be aligned)
|
||||
* - end - end address (exclusive, may not be aligned)
|
||||
* - vma - vma_struct describing address range
|
||||
* - vma - vm_area_struct describing address range
|
||||
*
|
||||
* It is assumed that:
|
||||
* - the "Invalidate single entry" instruction will invalidate
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
*
|
||||
* - start - start address (may not be aligned)
|
||||
* - end - end address (exclusive, may not be aligned)
|
||||
* - vma - vma_struct describing address range
|
||||
* - vma - vm_area_struct describing address range
|
||||
*
|
||||
* It is assumed that:
|
||||
* - the "Invalidate single entry" instruction will invalidate
|
||||
|
|
|
@ -1035,7 +1035,7 @@ config NODES_SHIFT
|
|||
int "Maximum NUMA Nodes (as a power of 2)"
|
||||
range 1 10
|
||||
default "4"
|
||||
depends on NEED_MULTIPLE_NODES
|
||||
depends on NUMA
|
||||
help
|
||||
Specify the maximum number of NUMA Nodes available on the target
|
||||
system. Increases memory reserved to accommodate various tables.
|
||||
|
|
|
@ -929,7 +929,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
|
|||
* get block mapping for device MMIO region.
|
||||
*/
|
||||
mmap_read_lock(current->mm);
|
||||
vma = find_vma_intersection(current->mm, hva, hva + 1);
|
||||
vma = vma_lookup(current->mm, hva);
|
||||
if (unlikely(!vma)) {
|
||||
kvm_err("Failed to find VMA for hva 0x%lx\n", hva);
|
||||
mmap_read_unlock(current->mm);
|
||||
|
|
|
@ -69,8 +69,6 @@ void __init h8300_fdt_init(void *fdt, char *bootargs)
|
|||
|
||||
static void __init bootmem_init(void)
|
||||
{
|
||||
struct memblock_region *region;
|
||||
|
||||
memory_end = memory_start = 0;
|
||||
|
||||
/* Find main memory where is the kernel */
|
||||
|
|
|
@ -302,7 +302,7 @@ config NODES_SHIFT
|
|||
int "Max num nodes shift(3-10)"
|
||||
range 3 10
|
||||
default "10"
|
||||
depends on NEED_MULTIPLE_NODES
|
||||
depends on NUMA
|
||||
help
|
||||
This option specifies the maximum number of nodes in your SSI system.
|
||||
MAX_NUMNODES will be 2^(This value).
|
||||
|
|
|
@ -1086,7 +1086,7 @@ static inline long ia64_pal_freq_base(unsigned long *platform_base_freq)
|
|||
|
||||
/*
|
||||
* Get the ratios for processor frequency, bus frequency and interval timer to
|
||||
* to base frequency of the platform
|
||||
* the base frequency of the platform
|
||||
*/
|
||||
static inline s64
|
||||
ia64_pal_freq_ratios (struct pal_freq_ratio *proc_ratio, struct pal_freq_ratio *bus_ratio,
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
* the queue, and the other indicating the current tail. The lock is acquired
|
||||
* by atomically noting the tail and incrementing it by one (thus adding
|
||||
* ourself to the queue and noting our position), then waiting until the head
|
||||
* becomes equal to the the initial value of the tail.
|
||||
* becomes equal to the initial value of the tail.
|
||||
* The pad bits in the middle are used to prevent the next_ticket number
|
||||
* overflowing into the now_serving number.
|
||||
*
|
||||
|
|
|
@ -257,7 +257,7 @@ static inline int uv_numa_blade_id(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Convert a cpu number to the the UV blade number */
|
||||
/* Convert a cpu number to the UV blade number */
|
||||
static inline int uv_cpu_to_blade_id(int cpu)
|
||||
{
|
||||
return 0;
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*
|
||||
* This stub allows us to make EFI calls in physical mode with interrupts
|
||||
* turned off. We need this because we can't call SetVirtualMap() until
|
||||
* the kernel has booted far enough to allow allocation of struct vma_struct
|
||||
* the kernel has booted far enough to allow allocation of struct vm_area_struct
|
||||
* entries (which we would need to map stuff with memory attributes other
|
||||
* than uncached or writeback...). Since the GetTime() service gets called
|
||||
* earlier than that, we need to be able to make physical mode EFI calls from
|
||||
|
|
|
@ -343,7 +343,7 @@ init_record_index_pools(void)
|
|||
|
||||
/* - 2 - */
|
||||
sect_min_size = sal_log_sect_min_sizes[0];
|
||||
for (i = 1; i < sizeof sal_log_sect_min_sizes/sizeof(size_t); i++)
|
||||
for (i = 1; i < ARRAY_SIZE(sal_log_sect_min_sizes); i++)
|
||||
if (sect_min_size > sal_log_sect_min_sizes[i])
|
||||
sect_min_size = sal_log_sect_min_sizes[i];
|
||||
|
||||
|
|
|
@ -3,9 +3,8 @@
|
|||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*
|
||||
* This file contains NUMA specific variables and functions which can
|
||||
* be split away from DISCONTIGMEM and are used on NUMA machines with
|
||||
* contiguous memory.
|
||||
* This file contains NUMA specific variables and functions which are used on
|
||||
* NUMA machines with contiguous memory.
|
||||
* 2002/08/07 Erich Focht <efocht@ess.nec.de>
|
||||
* Populate cpu entries in sysfs for non-numa systems as well
|
||||
* Intel Corporation - Ashok Raj
|
||||
|
|
|
@ -3,9 +3,8 @@
|
|||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*
|
||||
* This file contains NUMA specific variables and functions which can
|
||||
* be split away from DISCONTIGMEM and are used on NUMA machines with
|
||||
* contiguous memory.
|
||||
* This file contains NUMA specific variables and functions which are used on
|
||||
* NUMA machines with contiguous memory.
|
||||
*
|
||||
* 2002/08/07 Erich Focht <efocht@ess.nec.de>
|
||||
*/
|
||||
|
|
|
@ -408,10 +408,6 @@ config SINGLE_MEMORY_CHUNK
|
|||
order" to save memory that could be wasted for unused memory map.
|
||||
Say N if not sure.
|
||||
|
||||
config ARCH_DISCONTIGMEM_ENABLE
|
||||
depends on BROKEN
|
||||
def_bool MMU && !SINGLE_MEMORY_CHUNK
|
||||
|
||||
config FORCE_MAX_ZONEORDER
|
||||
int "Maximum zone order" if ADVANCED
|
||||
depends on !SINGLE_MEMORY_CHUNK
|
||||
|
@ -451,11 +447,6 @@ config M68K_L2_CACHE
|
|||
depends on MAC
|
||||
default y
|
||||
|
||||
config NODES_SHIFT
|
||||
int
|
||||
default "3"
|
||||
depends on DISCONTIGMEM
|
||||
|
||||
config CPU_HAS_NO_BITFIELDS
|
||||
bool
|
||||
|
||||
|
@ -553,4 +544,3 @@ config CACHE_COPYBACK
|
|||
The ColdFire CPU cache is set into Copy-back mode.
|
||||
endchoice
|
||||
endif
|
||||
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _ASM_M68K_MMZONE_H_
|
||||
#define _ASM_M68K_MMZONE_H_
|
||||
|
||||
extern pg_data_t pg_data_map[];
|
||||
|
||||
#define NODE_DATA(nid) (&pg_data_map[nid])
|
||||
#define NODE_MEM_MAP(nid) (NODE_DATA(nid)->node_mem_map)
|
||||
|
||||
#endif /* _ASM_M68K_MMZONE_H_ */
|
|
@ -62,7 +62,7 @@ extern unsigned long _ramend;
|
|||
#include <asm/page_no.h>
|
||||
#endif
|
||||
|
||||
#if !defined(CONFIG_MMU) || defined(CONFIG_DISCONTIGMEM)
|
||||
#ifndef CONFIG_MMU
|
||||
#define __phys_to_pfn(paddr) ((unsigned long)((paddr) >> PAGE_SHIFT))
|
||||
#define __pfn_to_phys(pfn) PFN_PHYS(pfn)
|
||||
#endif
|
||||
|
|
|
@ -126,26 +126,6 @@ static inline void *__va(unsigned long x)
|
|||
|
||||
extern int m68k_virt_to_node_shift;
|
||||
|
||||
#ifndef CONFIG_DISCONTIGMEM
|
||||
#define __virt_to_node(addr) (&pg_data_map[0])
|
||||
#else
|
||||
extern struct pglist_data *pg_data_table[];
|
||||
|
||||
static inline __attribute_const__ int __virt_to_node_shift(void)
|
||||
{
|
||||
int shift;
|
||||
|
||||
asm (
|
||||
"1: moveq #0,%0\n"
|
||||
m68k_fixup(%c1, 1b)
|
||||
: "=d" (shift)
|
||||
: "i" (m68k_fixup_vnode_shift));
|
||||
return shift;
|
||||
}
|
||||
|
||||
#define __virt_to_node(addr) (pg_data_table[(unsigned long)(addr) >> __virt_to_node_shift()])
|
||||
#endif
|
||||
|
||||
#define virt_to_page(addr) ({ \
|
||||
pfn_to_page(virt_to_pfn(addr)); \
|
||||
})
|
||||
|
@ -153,23 +133,8 @@ static inline __attribute_const__ int __virt_to_node_shift(void)
|
|||
pfn_to_virt(page_to_pfn(page)); \
|
||||
})
|
||||
|
||||
#ifdef CONFIG_DISCONTIGMEM
|
||||
#define pfn_to_page(pfn) ({ \
|
||||
unsigned long __pfn = (pfn); \
|
||||
struct pglist_data *pgdat; \
|
||||
pgdat = __virt_to_node((unsigned long)pfn_to_virt(__pfn)); \
|
||||
pgdat->node_mem_map + (__pfn - pgdat->node_start_pfn); \
|
||||
})
|
||||
#define page_to_pfn(_page) ({ \
|
||||
const struct page *__p = (_page); \
|
||||
struct pglist_data *pgdat; \
|
||||
pgdat = &pg_data_map[page_to_nid(__p)]; \
|
||||
((__p) - pgdat->node_mem_map) + pgdat->node_start_pfn; \
|
||||
})
|
||||
#else
|
||||
#define ARCH_PFN_OFFSET (m68k_memory[0].addr >> PAGE_SHIFT)
|
||||
#include <asm-generic/memory_model.h>
|
||||
#endif
|
||||
|
||||
#define virt_addr_valid(kaddr) ((unsigned long)(kaddr) >= PAGE_OFFSET && (unsigned long)(kaddr) < (unsigned long)high_memory)
|
||||
#define pfn_valid(pfn) virt_addr_valid(pfn_to_virt(pfn))
|
||||
|
|
|
@ -263,7 +263,7 @@ static inline void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr
|
|||
BUG();
|
||||
}
|
||||
|
||||
static inline void flush_tlb_range(struct mm_struct *mm,
|
||||
static inline void flush_tlb_range(struct vm_area_struct *vma,
|
||||
unsigned long start, unsigned long end)
|
||||
{
|
||||
BUG();
|
||||
|
|
|
@ -402,8 +402,8 @@ sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
|
|||
* to this process.
|
||||
*/
|
||||
mmap_read_lock(current->mm);
|
||||
vma = find_vma(current->mm, addr);
|
||||
if (!vma || addr < vma->vm_start || addr + len > vma->vm_end)
|
||||
vma = vma_lookup(current->mm, addr);
|
||||
if (!vma || addr + len > vma->vm_end)
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
|
|
|
@ -44,28 +44,8 @@ EXPORT_SYMBOL(empty_zero_page);
|
|||
|
||||
int m68k_virt_to_node_shift;
|
||||
|
||||
#ifdef CONFIG_DISCONTIGMEM
|
||||
pg_data_t pg_data_map[MAX_NUMNODES];
|
||||
EXPORT_SYMBOL(pg_data_map);
|
||||
|
||||
pg_data_t *pg_data_table[65];
|
||||
EXPORT_SYMBOL(pg_data_table);
|
||||
#endif
|
||||
|
||||
void __init m68k_setup_node(int node)
|
||||
{
|
||||
#ifdef CONFIG_DISCONTIGMEM
|
||||
struct m68k_mem_info *info = m68k_memory + node;
|
||||
int i, end;
|
||||
|
||||
i = (unsigned long)phys_to_virt(info->addr) >> __virt_to_node_shift();
|
||||
end = (unsigned long)phys_to_virt(info->addr + info->size - 1) >> __virt_to_node_shift();
|
||||
for (; i <= end; i++) {
|
||||
if (pg_data_table[i])
|
||||
pr_warn("overlap at %u for chunk %u\n", i, node);
|
||||
pg_data_table[i] = pg_data_map + node;
|
||||
}
|
||||
#endif
|
||||
node_set_online(node);
|
||||
}
|
||||
|
||||
|
|
|
@ -2867,7 +2867,7 @@ config RANDOMIZE_BASE_MAX_OFFSET
|
|||
config NODES_SHIFT
|
||||
int
|
||||
default "6"
|
||||
depends on NEED_MULTIPLE_NODES
|
||||
depends on NUMA
|
||||
|
||||
config HW_PERF_EVENTS
|
||||
bool "Enable hardware performance counter support for perf events"
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
#include <asm/page.h>
|
||||
|
||||
#ifdef CONFIG_NEED_MULTIPLE_NODES
|
||||
#ifdef CONFIG_NUMA
|
||||
# include <mmzone.h>
|
||||
#endif
|
||||
|
||||
|
@ -20,10 +20,4 @@
|
|||
#define nid_to_addrbase(nid) 0
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_DISCONTIGMEM
|
||||
|
||||
#define pfn_to_nid(pfn) pa_to_nid((pfn) << PAGE_SHIFT)
|
||||
|
||||
#endif /* CONFIG_DISCONTIGMEM */
|
||||
|
||||
#endif /* _ASM_MMZONE_H_ */
|
||||
|
|
|
@ -239,7 +239,7 @@ static inline int pfn_valid(unsigned long pfn)
|
|||
|
||||
/* pfn_valid is defined in linux/mmzone.h */
|
||||
|
||||
#elif defined(CONFIG_NEED_MULTIPLE_NODES)
|
||||
#elif defined(CONFIG_NUMA)
|
||||
|
||||
#define pfn_valid(pfn) \
|
||||
({ \
|
||||
|
|
|
@ -784,7 +784,6 @@ void force_fcr31_sig(unsigned long fcr31, void __user *fault_addr,
|
|||
int process_fpemu_return(int sig, void __user *fault_addr, unsigned long fcr31)
|
||||
{
|
||||
int si_code;
|
||||
struct vm_area_struct *vma;
|
||||
|
||||
switch (sig) {
|
||||
case 0:
|
||||
|
@ -800,8 +799,7 @@ int process_fpemu_return(int sig, void __user *fault_addr, unsigned long fcr31)
|
|||
|
||||
case SIGSEGV:
|
||||
mmap_read_lock(current->mm);
|
||||
vma = find_vma(current->mm, (unsigned long)fault_addr);
|
||||
if (vma && (vma->vm_start <= (unsigned long)fault_addr))
|
||||
if (vma_lookup(current->mm, (unsigned long)fault_addr))
|
||||
si_code = SEGV_ACCERR;
|
||||
else
|
||||
si_code = SEGV_MAPERR;
|
||||
|
|
|
@ -394,7 +394,7 @@ void maar_init(void)
|
|||
}
|
||||
}
|
||||
|
||||
#ifndef CONFIG_NEED_MULTIPLE_NODES
|
||||
#ifndef CONFIG_NUMA
|
||||
void __init paging_init(void)
|
||||
{
|
||||
unsigned long max_zone_pfns[MAX_NR_ZONES];
|
||||
|
@ -454,9 +454,6 @@ void __init mem_init(void)
|
|||
BUILD_BUG_ON(IS_ENABLED(CONFIG_32BIT) && (_PFN_SHIFT > PAGE_SHIFT));
|
||||
|
||||
#ifdef CONFIG_HIGHMEM
|
||||
#ifdef CONFIG_DISCONTIGMEM
|
||||
#error "CONFIG_HIGHMEM and CONFIG_DISCONTIGMEM dont work together yet"
|
||||
#endif
|
||||
max_mapnr = highend_pfn ? highend_pfn : max_low_pfn;
|
||||
#else
|
||||
max_mapnr = max_low_pfn;
|
||||
|
@ -476,7 +473,7 @@ void __init mem_init(void)
|
|||
0x80000000 - 4, KCORE_TEXT);
|
||||
#endif
|
||||
}
|
||||
#endif /* !CONFIG_NEED_MULTIPLE_NODES */
|
||||
#endif /* !CONFIG_NUMA */
|
||||
|
||||
void free_init_pages(const char *what, unsigned long begin, unsigned long end)
|
||||
{
|
||||
|
|
|
@ -76,18 +76,12 @@
|
|||
* virt_to_page(k) convert a _valid_ virtual address to struct page *
|
||||
* virt_addr_valid(k) indicates whether a virtual address is valid
|
||||
*/
|
||||
#ifndef CONFIG_DISCONTIGMEM
|
||||
|
||||
#define ARCH_PFN_OFFSET PHYS_PFN_OFFSET
|
||||
#define pfn_valid(pfn) ((pfn) >= PHYS_PFN_OFFSET && (pfn) < (PHYS_PFN_OFFSET + max_mapnr))
|
||||
|
||||
#define virt_to_page(kaddr) (pfn_to_page(__pa(kaddr) >> PAGE_SHIFT))
|
||||
#define virt_addr_valid(kaddr) ((unsigned long)(kaddr) >= PAGE_OFFSET && (unsigned long)(kaddr) < (unsigned long)high_memory)
|
||||
|
||||
#else /* CONFIG_DISCONTIGMEM */
|
||||
#error CONFIG_DISCONTIGMEM is not supported yet.
|
||||
#endif /* !CONFIG_DISCONTIGMEM */
|
||||
|
||||
#define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT)
|
||||
|
||||
#endif
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
* - flush_tlb_all() flushes all processes TLBs
|
||||
* - flush_tlb_mm(mm) flushes the specified mm context TLB's
|
||||
* - flush_tlb_page(vma, vmaddr) flushes one page
|
||||
* - flush_tlb_range(mm, start, end) flushes a range of pages
|
||||
* - flush_tlb_range(vma, start, end) flushes a range of pages
|
||||
*/
|
||||
extern void local_flush_tlb_all(void);
|
||||
extern void local_flush_tlb_mm(struct mm_struct *mm);
|
||||
|
|
|
@ -671,7 +671,7 @@ config NODES_SHIFT
|
|||
int
|
||||
default "8" if PPC64
|
||||
default "4"
|
||||
depends on NEED_MULTIPLE_NODES
|
||||
depends on NUMA
|
||||
|
||||
config USE_PERCPU_NUMA_NODE_ID
|
||||
def_bool y
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
* flags field of the struct page
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_NEED_MULTIPLE_NODES
|
||||
#ifdef CONFIG_NUMA
|
||||
|
||||
extern struct pglist_data *node_data[];
|
||||
/*
|
||||
|
@ -41,7 +41,7 @@ u64 memory_hotplug_max(void);
|
|||
|
||||
#else
|
||||
#define memory_hotplug_max() memblock_end_of_DRAM()
|
||||
#endif /* CONFIG_NEED_MULTIPLE_NODES */
|
||||
#endif /* CONFIG_NUMA */
|
||||
#ifdef CONFIG_FA_DUMP
|
||||
#define __HAVE_ARCH_RESERVED_KERNEL_PAGES
|
||||
#endif
|
||||
|
|
|
@ -788,7 +788,7 @@ static void * __init pcpu_alloc_bootmem(unsigned int cpu, size_t size,
|
|||
size_t align)
|
||||
{
|
||||
const unsigned long goal = __pa(MAX_DMA_ADDRESS);
|
||||
#ifdef CONFIG_NEED_MULTIPLE_NODES
|
||||
#ifdef CONFIG_NUMA
|
||||
int node = early_cpu_to_node(cpu);
|
||||
void *ptr;
|
||||
|
||||
|
|
|
@ -1047,7 +1047,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
|
|||
zalloc_cpumask_var_node(&per_cpu(cpu_coregroup_map, cpu),
|
||||
GFP_KERNEL, cpu_to_node(cpu));
|
||||
|
||||
#ifdef CONFIG_NEED_MULTIPLE_NODES
|
||||
#ifdef CONFIG_NUMA
|
||||
/*
|
||||
* numa_node_id() works after this.
|
||||
*/
|
||||
|
|
|
@ -68,11 +68,11 @@ void machine_kexec_cleanup(struct kimage *image)
|
|||
void arch_crash_save_vmcoreinfo(void)
|
||||
{
|
||||
|
||||
#ifdef CONFIG_NEED_MULTIPLE_NODES
|
||||
#ifdef CONFIG_NUMA
|
||||
VMCOREINFO_SYMBOL(node_data);
|
||||
VMCOREINFO_LENGTH(node_data, MAX_NUMNODES);
|
||||
#endif
|
||||
#ifndef CONFIG_NEED_MULTIPLE_NODES
|
||||
#ifndef CONFIG_NUMA
|
||||
VMCOREINFO_SYMBOL(contig_page_data);
|
||||
#endif
|
||||
#if defined(CONFIG_PPC64) && defined(CONFIG_SPARSEMEM_VMEMMAP)
|
||||
|
|
|
@ -4924,8 +4924,8 @@ static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu)
|
|||
/* Look up the VMA for the start of this memory slot */
|
||||
hva = memslot->userspace_addr;
|
||||
mmap_read_lock(kvm->mm);
|
||||
vma = find_vma(kvm->mm, hva);
|
||||
if (!vma || vma->vm_start > hva || (vma->vm_flags & VM_IO))
|
||||
vma = vma_lookup(kvm->mm, hva);
|
||||
if (!vma || (vma->vm_flags & VM_IO))
|
||||
goto up_out;
|
||||
|
||||
psize = vma_kernel_pagesize(vma);
|
||||
|
|
|
@ -615,7 +615,7 @@ void kvmppc_uvmem_drop_pages(const struct kvm_memory_slot *slot,
|
|||
|
||||
/* Fetch the VMA if addr is not in the latest fetched one */
|
||||
if (!vma || addr >= vma->vm_end) {
|
||||
vma = find_vma_intersection(kvm->mm, addr, addr+1);
|
||||
vma = vma_lookup(kvm->mm, addr);
|
||||
if (!vma) {
|
||||
pr_err("Can't find VMA for gfn:0x%lx\n", gfn);
|
||||
break;
|
||||
|
|
|
@ -13,7 +13,7 @@ obj-y := fault.o mem.o pgtable.o mmap.o maccess.o \
|
|||
obj-$(CONFIG_PPC_MMU_NOHASH) += nohash/
|
||||
obj-$(CONFIG_PPC_BOOK3S_32) += book3s32/
|
||||
obj-$(CONFIG_PPC_BOOK3S_64) += book3s64/
|
||||
obj-$(CONFIG_NEED_MULTIPLE_NODES) += numa.o
|
||||
obj-$(CONFIG_NUMA) += numa.o
|
||||
obj-$(CONFIG_PPC_MM_SLICES) += slice.o
|
||||
obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
|
||||
obj-$(CONFIG_NOT_COHERENT_CACHE) += dma-noncoherent.o
|
||||
|
|
|
@ -127,7 +127,7 @@ void __ref arch_remove_memory(int nid, u64 start, u64 size,
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_NEED_MULTIPLE_NODES
|
||||
#ifndef CONFIG_NUMA
|
||||
void __init mem_topology_setup(void)
|
||||
{
|
||||
max_low_pfn = max_pfn = memblock_end_of_DRAM() >> PAGE_SHIFT;
|
||||
|
@ -162,7 +162,7 @@ static int __init mark_nonram_nosave(void)
|
|||
|
||||
return 0;
|
||||
}
|
||||
#else /* CONFIG_NEED_MULTIPLE_NODES */
|
||||
#else /* CONFIG_NUMA */
|
||||
static int __init mark_nonram_nosave(void)
|
||||
{
|
||||
return 0;
|
||||
|
|
|
@ -332,7 +332,7 @@ config NODES_SHIFT
|
|||
int "Maximum NUMA Nodes (as a power of 2)"
|
||||
range 1 10
|
||||
default "2"
|
||||
depends on NEED_MULTIPLE_NODES
|
||||
depends on NUMA
|
||||
help
|
||||
Specify the maximum number of NUMA Nodes available on the target
|
||||
system. Increases memory reserved to accommodate various tables.
|
||||
|
|
|
@ -475,7 +475,7 @@ config NUMA
|
|||
|
||||
config NODES_SHIFT
|
||||
int
|
||||
depends on NEED_MULTIPLE_NODES
|
||||
depends on NUMA
|
||||
default "1"
|
||||
|
||||
config SCHED_SMT
|
||||
|
|
|
@ -344,8 +344,6 @@ static inline int is_module_addr(void *addr)
|
|||
#define PTRS_PER_P4D _CRST_ENTRIES
|
||||
#define PTRS_PER_PGD _CRST_ENTRIES
|
||||
|
||||
#define MAX_PTRS_PER_P4D PTRS_PER_P4D
|
||||
|
||||
/*
|
||||
* Segment table and region3 table entry encoding
|
||||
* (R = read-only, I = invalid, y = young bit):
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#ifndef __ASM_SH_MMZONE_H
|
||||
#define __ASM_SH_MMZONE_H
|
||||
|
||||
#ifdef CONFIG_NEED_MULTIPLE_NODES
|
||||
#ifdef CONFIG_NUMA
|
||||
#include <linux/numa.h>
|
||||
|
||||
extern struct pglist_data *node_data[];
|
||||
|
@ -31,7 +31,7 @@ static inline void
|
|||
setup_bootmem_node(int nid, unsigned long start, unsigned long end)
|
||||
{
|
||||
}
|
||||
#endif /* CONFIG_NEED_MULTIPLE_NODES */
|
||||
#endif /* CONFIG_NUMA */
|
||||
|
||||
/* Platform specific mem init */
|
||||
void __init plat_mem_setup(void);
|
||||
|
|
|
@ -46,7 +46,7 @@ static int __init topology_init(void)
|
|||
{
|
||||
int i, ret;
|
||||
|
||||
#ifdef CONFIG_NEED_MULTIPLE_NODES
|
||||
#ifdef CONFIG_NUMA
|
||||
for_each_online_node(i)
|
||||
register_one_node(i);
|
||||
#endif
|
||||
|
|
|
@ -120,7 +120,7 @@ config NODES_SHIFT
|
|||
int
|
||||
default "3" if CPU_SUBTYPE_SHX3
|
||||
default "1"
|
||||
depends on NEED_MULTIPLE_NODES
|
||||
depends on NUMA
|
||||
|
||||
config ARCH_FLATMEM_ENABLE
|
||||
def_bool y
|
||||
|
|
|
@ -211,7 +211,7 @@ void __init allocate_pgdat(unsigned int nid)
|
|||
|
||||
get_pfn_range_for_nid(nid, &start_pfn, &end_pfn);
|
||||
|
||||
#ifdef CONFIG_NEED_MULTIPLE_NODES
|
||||
#ifdef CONFIG_NUMA
|
||||
NODE_DATA(nid) = memblock_alloc_try_nid(
|
||||
sizeof(struct pglist_data),
|
||||
SMP_CACHE_BYTES, MEMBLOCK_LOW_LIMIT,
|
||||
|
|
|
@ -265,7 +265,7 @@ config NODES_SHIFT
|
|||
int "Maximum NUMA Nodes (as a power of 2)"
|
||||
range 4 5 if SPARC64
|
||||
default "5"
|
||||
depends on NEED_MULTIPLE_NODES
|
||||
depends on NUMA
|
||||
help
|
||||
Specify the maximum number of NUMA Nodes available on the target
|
||||
system. Increases memory reserved to accommodate various tables.
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#ifndef _SPARC64_MMZONE_H
|
||||
#define _SPARC64_MMZONE_H
|
||||
|
||||
#ifdef CONFIG_NEED_MULTIPLE_NODES
|
||||
#ifdef CONFIG_NUMA
|
||||
|
||||
#include <linux/cpumask.h>
|
||||
|
||||
|
@ -13,6 +13,6 @@ extern struct pglist_data *node_data[];
|
|||
extern int numa_cpu_lookup_table[];
|
||||
extern cpumask_t numa_cpumask_lookup_table[];
|
||||
|
||||
#endif /* CONFIG_NEED_MULTIPLE_NODES */
|
||||
#endif /* CONFIG_NUMA */
|
||||
|
||||
#endif /* _SPARC64_MMZONE_H */
|
||||
|
|
|
@ -1543,7 +1543,7 @@ static void * __init pcpu_alloc_bootmem(unsigned int cpu, size_t size,
|
|||
size_t align)
|
||||
{
|
||||
const unsigned long goal = __pa(MAX_DMA_ADDRESS);
|
||||
#ifdef CONFIG_NEED_MULTIPLE_NODES
|
||||
#ifdef CONFIG_NUMA
|
||||
int node = cpu_to_node(cpu);
|
||||
void *ptr;
|
||||
|
||||
|
|
|
@ -903,7 +903,7 @@ struct node_mem_mask {
|
|||
static struct node_mem_mask node_masks[MAX_NUMNODES];
|
||||
static int num_node_masks;
|
||||
|
||||
#ifdef CONFIG_NEED_MULTIPLE_NODES
|
||||
#ifdef CONFIG_NUMA
|
||||
|
||||
struct mdesc_mlgroup {
|
||||
u64 node;
|
||||
|
@ -1059,7 +1059,7 @@ static void __init allocate_node_data(int nid)
|
|||
{
|
||||
struct pglist_data *p;
|
||||
unsigned long start_pfn, end_pfn;
|
||||
#ifdef CONFIG_NEED_MULTIPLE_NODES
|
||||
#ifdef CONFIG_NUMA
|
||||
|
||||
NODE_DATA(nid) = memblock_alloc_node(sizeof(struct pglist_data),
|
||||
SMP_CACHE_BYTES, nid);
|
||||
|
@ -1080,7 +1080,7 @@ static void __init allocate_node_data(int nid)
|
|||
|
||||
static void init_node_masks_nonnuma(void)
|
||||
{
|
||||
#ifdef CONFIG_NEED_MULTIPLE_NODES
|
||||
#ifdef CONFIG_NUMA
|
||||
int i;
|
||||
#endif
|
||||
|
||||
|
@ -1090,7 +1090,7 @@ static void init_node_masks_nonnuma(void)
|
|||
node_masks[0].match = 0;
|
||||
num_node_masks = 1;
|
||||
|
||||
#ifdef CONFIG_NEED_MULTIPLE_NODES
|
||||
#ifdef CONFIG_NUMA
|
||||
for (i = 0; i < NR_CPUS; i++)
|
||||
numa_cpu_lookup_table[i] = 0;
|
||||
|
||||
|
@ -1098,7 +1098,7 @@ static void init_node_masks_nonnuma(void)
|
|||
#endif
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NEED_MULTIPLE_NODES
|
||||
#ifdef CONFIG_NUMA
|
||||
struct pglist_data *node_data[MAX_NUMNODES];
|
||||
|
||||
EXPORT_SYMBOL(numa_cpu_lookup_table);
|
||||
|
@ -2487,7 +2487,7 @@ int page_in_phys_avail(unsigned long paddr)
|
|||
|
||||
static void __init register_page_bootmem_info(void)
|
||||
{
|
||||
#ifdef CONFIG_NEED_MULTIPLE_NODES
|
||||
#ifdef CONFIG_NUMA
|
||||
int i;
|
||||
|
||||
for_each_online_node(i)
|
||||
|
|
|
@ -1597,7 +1597,7 @@ config NODES_SHIFT
|
|||
default "10" if MAXSMP
|
||||
default "6" if X86_64
|
||||
default "3"
|
||||
depends on NEED_MULTIPLE_NODES
|
||||
depends on NUMA
|
||||
help
|
||||
Specify the maximum number of NUMA Nodes available on the target
|
||||
system. Increases memory reserved to accommodate various tables.
|
||||
|
|
|
@ -203,7 +203,7 @@ static int load_aout_binary(struct linux_binprm *bprm)
|
|||
error = vm_mmap(bprm->file, N_TXTADDR(ex), ex.a_text,
|
||||
PROT_READ | PROT_EXEC,
|
||||
MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE |
|
||||
MAP_EXECUTABLE | MAP_32BIT,
|
||||
MAP_32BIT,
|
||||
fd_offset);
|
||||
|
||||
if (error != N_TXTADDR(ex))
|
||||
|
@ -212,7 +212,7 @@ static int load_aout_binary(struct linux_binprm *bprm)
|
|||
error = vm_mmap(bprm->file, N_DATADDR(ex), ex.a_data,
|
||||
PROT_READ | PROT_WRITE | PROT_EXEC,
|
||||
MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE |
|
||||
MAP_EXECUTABLE | MAP_32BIT,
|
||||
MAP_32BIT,
|
||||
fd_offset + ex.a_text);
|
||||
if (error != N_DATADDR(ex))
|
||||
return error;
|
||||
|
|
|
@ -1257,19 +1257,28 @@ static void kill_me_maybe(struct callback_head *cb)
|
|||
{
|
||||
struct task_struct *p = container_of(cb, struct task_struct, mce_kill_me);
|
||||
int flags = MF_ACTION_REQUIRED;
|
||||
int ret;
|
||||
|
||||
pr_err("Uncorrected hardware memory error in user-access at %llx", p->mce_addr);
|
||||
|
||||
if (!p->mce_ripv)
|
||||
flags |= MF_MUST_KILL;
|
||||
|
||||
if (!memory_failure(p->mce_addr >> PAGE_SHIFT, flags) &&
|
||||
!(p->mce_kflags & MCE_IN_KERNEL_COPYIN)) {
|
||||
ret = memory_failure(p->mce_addr >> PAGE_SHIFT, flags);
|
||||
if (!ret && !(p->mce_kflags & MCE_IN_KERNEL_COPYIN)) {
|
||||
set_mce_nospec(p->mce_addr >> PAGE_SHIFT, p->mce_whole_page);
|
||||
sync_core();
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* -EHWPOISON from memory_failure() means that it already sent SIGBUS
|
||||
* to the current process with the proper error info, so no need to
|
||||
* send SIGBUS here again.
|
||||
*/
|
||||
if (ret == -EHWPOISON)
|
||||
return;
|
||||
|
||||
if (p->mce_vaddr != (void __user *)-1l) {
|
||||
force_sig_mceerr(BUS_MCEERR_AR, p->mce_vaddr, PAGE_SHIFT);
|
||||
} else {
|
||||
|
|
|
@ -91,8 +91,8 @@ static inline int sgx_encl_find(struct mm_struct *mm, unsigned long addr,
|
|||
{
|
||||
struct vm_area_struct *result;
|
||||
|
||||
result = find_vma(mm, addr);
|
||||
if (!result || result->vm_ops != &sgx_vm_ops || addr < result->vm_start)
|
||||
result = vma_lookup(mm, addr);
|
||||
if (!result || result->vm_ops != &sgx_vm_ops)
|
||||
return -EINVAL;
|
||||
|
||||
*vma = result;
|
||||
|
|
|
@ -66,7 +66,7 @@ EXPORT_SYMBOL(__per_cpu_offset);
|
|||
*/
|
||||
static bool __init pcpu_need_numa(void)
|
||||
{
|
||||
#ifdef CONFIG_NEED_MULTIPLE_NODES
|
||||
#ifdef CONFIG_NUMA
|
||||
pg_data_t *last = NULL;
|
||||
unsigned int cpu;
|
||||
|
||||
|
@ -101,7 +101,7 @@ static void * __init pcpu_alloc_bootmem(unsigned int cpu, unsigned long size,
|
|||
unsigned long align)
|
||||
{
|
||||
const unsigned long goal = __pa(MAX_DMA_ADDRESS);
|
||||
#ifdef CONFIG_NEED_MULTIPLE_NODES
|
||||
#ifdef CONFIG_NUMA
|
||||
int node = early_cpu_to_node(cpu);
|
||||
void *ptr;
|
||||
|
||||
|
@ -140,7 +140,7 @@ static void __init pcpu_fc_free(void *ptr, size_t size)
|
|||
|
||||
static int __init pcpu_cpu_distance(unsigned int from, unsigned int to)
|
||||
{
|
||||
#ifdef CONFIG_NEED_MULTIPLE_NODES
|
||||
#ifdef CONFIG_NUMA
|
||||
if (early_cpu_to_node(from) == early_cpu_to_node(to))
|
||||
return LOCAL_DISTANCE;
|
||||
else
|
||||
|
|
|
@ -651,7 +651,7 @@ void __init find_low_pfn_range(void)
|
|||
highmem_pfn_init();
|
||||
}
|
||||
|
||||
#ifndef CONFIG_NEED_MULTIPLE_NODES
|
||||
#ifndef CONFIG_NUMA
|
||||
void __init initmem_init(void)
|
||||
{
|
||||
#ifdef CONFIG_HIGHMEM
|
||||
|
@ -677,7 +677,7 @@ void __init initmem_init(void)
|
|||
|
||||
setup_bootmem_allocator();
|
||||
}
|
||||
#endif /* !CONFIG_NEED_MULTIPLE_NODES */
|
||||
#endif /* !CONFIG_NUMA */
|
||||
|
||||
void __init setup_bootmem_allocator(void)
|
||||
{
|
||||
|
|
|
@ -192,10 +192,6 @@ static inline unsigned long ___pa(unsigned long va)
|
|||
#define pfn_valid(pfn) \
|
||||
((pfn) >= ARCH_PFN_OFFSET && ((pfn) - ARCH_PFN_OFFSET) < max_mapnr)
|
||||
|
||||
#ifdef CONFIG_DISCONTIGMEM
|
||||
# error CONFIG_DISCONTIGMEM not supported
|
||||
#endif
|
||||
|
||||
#define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
|
||||
#define page_to_virt(page) __va(page_to_pfn(page) << PAGE_SHIFT)
|
||||
#define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
|
||||
|
|
|
@ -26,8 +26,8 @@
|
|||
*
|
||||
* - flush_tlb_all() flushes all processes TLB entries
|
||||
* - flush_tlb_mm(mm) flushes the specified mm context TLB entries
|
||||
* - flush_tlb_page(mm, vmaddr) flushes a single page
|
||||
* - flush_tlb_range(mm, start, end) flushes a range of pages
|
||||
* - flush_tlb_page(vma, page) flushes a single page
|
||||
* - flush_tlb_range(vma, vmaddr, end) flushes a range of pages
|
||||
*/
|
||||
|
||||
void local_flush_tlb_all(void);
|
||||
|
|
|
@ -482,6 +482,7 @@ static DEVICE_ATTR(meminfo, 0444, node_read_meminfo, NULL);
|
|||
static ssize_t node_read_numastat(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
fold_vm_numa_events();
|
||||
return sysfs_emit(buf,
|
||||
"numa_hit %lu\n"
|
||||
"numa_miss %lu\n"
|
||||
|
@ -489,12 +490,12 @@ static ssize_t node_read_numastat(struct device *dev,
|
|||
"interleave_hit %lu\n"
|
||||
"local_node %lu\n"
|
||||
"other_node %lu\n",
|
||||
sum_zone_numa_state(dev->id, NUMA_HIT),
|
||||
sum_zone_numa_state(dev->id, NUMA_MISS),
|
||||
sum_zone_numa_state(dev->id, NUMA_FOREIGN),
|
||||
sum_zone_numa_state(dev->id, NUMA_INTERLEAVE_HIT),
|
||||
sum_zone_numa_state(dev->id, NUMA_LOCAL),
|
||||
sum_zone_numa_state(dev->id, NUMA_OTHER));
|
||||
sum_zone_numa_event_state(dev->id, NUMA_HIT),
|
||||
sum_zone_numa_event_state(dev->id, NUMA_MISS),
|
||||
sum_zone_numa_event_state(dev->id, NUMA_FOREIGN),
|
||||
sum_zone_numa_event_state(dev->id, NUMA_INTERLEAVE_HIT),
|
||||
sum_zone_numa_event_state(dev->id, NUMA_LOCAL),
|
||||
sum_zone_numa_event_state(dev->id, NUMA_OTHER));
|
||||
}
|
||||
static DEVICE_ATTR(numastat, 0444, node_read_numastat, NULL);
|
||||
|
||||
|
@ -512,10 +513,11 @@ static ssize_t node_read_vmstat(struct device *dev,
|
|||
sum_zone_node_page_state(nid, i));
|
||||
|
||||
#ifdef CONFIG_NUMA
|
||||
for (i = 0; i < NR_VM_NUMA_STAT_ITEMS; i++)
|
||||
fold_vm_numa_events();
|
||||
for (i = 0; i < NR_VM_NUMA_EVENT_ITEMS; i++)
|
||||
len += sysfs_emit_at(buf, len, "%s %lu\n",
|
||||
numa_stat_name(i),
|
||||
sum_zone_numa_state(nid, i));
|
||||
sum_zone_numa_event_state(nid, i));
|
||||
|
||||
#endif
|
||||
for (i = 0; i < NR_VM_NODE_STAT_ITEMS; i++) {
|
||||
|
|
|
@ -71,7 +71,6 @@
|
|||
#include <linux/writeback.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/highmem.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/splice.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/miscdevice.h>
|
||||
|
@ -79,11 +78,14 @@
|
|||
#include <linux/uio.h>
|
||||
#include <linux/ioprio.h>
|
||||
#include <linux/blk-cgroup.h>
|
||||
#include <linux/sched/mm.h>
|
||||
|
||||
#include "loop.h"
|
||||
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#define LOOP_IDLE_WORKER_TIMEOUT (60 * HZ)
|
||||
|
||||
static DEFINE_IDR(loop_index_idr);
|
||||
static DEFINE_MUTEX(loop_ctl_mutex);
|
||||
|
||||
|
@ -515,8 +517,6 @@ static void lo_rw_aio_complete(struct kiocb *iocb, long ret, long ret2)
|
|||
{
|
||||
struct loop_cmd *cmd = container_of(iocb, struct loop_cmd, iocb);
|
||||
|
||||
if (cmd->css)
|
||||
css_put(cmd->css);
|
||||
cmd->ret = ret;
|
||||
lo_rw_aio_do_completion(cmd);
|
||||
}
|
||||
|
@ -577,8 +577,6 @@ static int lo_rw_aio(struct loop_device *lo, struct loop_cmd *cmd,
|
|||
cmd->iocb.ki_complete = lo_rw_aio_complete;
|
||||
cmd->iocb.ki_flags = IOCB_DIRECT;
|
||||
cmd->iocb.ki_ioprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_NONE, 0);
|
||||
if (cmd->css)
|
||||
kthread_associate_blkcg(cmd->css);
|
||||
|
||||
if (rw == WRITE)
|
||||
ret = call_write_iter(file, &cmd->iocb, &iter);
|
||||
|
@ -586,7 +584,6 @@ static int lo_rw_aio(struct loop_device *lo, struct loop_cmd *cmd,
|
|||
ret = call_read_iter(file, &cmd->iocb, &iter);
|
||||
|
||||
lo_rw_aio_do_completion(cmd);
|
||||
kthread_associate_blkcg(NULL);
|
||||
|
||||
if (ret != -EIOCBQUEUED)
|
||||
cmd->iocb.ki_complete(&cmd->iocb, ret, 0);
|
||||
|
@ -921,27 +918,100 @@ static void loop_config_discard(struct loop_device *lo)
|
|||
q->limits.discard_alignment = 0;
|
||||
}
|
||||
|
||||
static void loop_unprepare_queue(struct loop_device *lo)
|
||||
{
|
||||
kthread_flush_worker(&lo->worker);
|
||||
kthread_stop(lo->worker_task);
|
||||
}
|
||||
struct loop_worker {
|
||||
struct rb_node rb_node;
|
||||
struct work_struct work;
|
||||
struct list_head cmd_list;
|
||||
struct list_head idle_list;
|
||||
struct loop_device *lo;
|
||||
struct cgroup_subsys_state *blkcg_css;
|
||||
unsigned long last_ran_at;
|
||||
};
|
||||
|
||||
static int loop_kthread_worker_fn(void *worker_ptr)
|
||||
{
|
||||
current->flags |= PF_LOCAL_THROTTLE | PF_MEMALLOC_NOIO;
|
||||
return kthread_worker_fn(worker_ptr);
|
||||
}
|
||||
static void loop_workfn(struct work_struct *work);
|
||||
static void loop_rootcg_workfn(struct work_struct *work);
|
||||
static void loop_free_idle_workers(struct timer_list *timer);
|
||||
|
||||
static int loop_prepare_queue(struct loop_device *lo)
|
||||
#ifdef CONFIG_BLK_CGROUP
|
||||
static inline int queue_on_root_worker(struct cgroup_subsys_state *css)
|
||||
{
|
||||
kthread_init_worker(&lo->worker);
|
||||
lo->worker_task = kthread_run(loop_kthread_worker_fn,
|
||||
&lo->worker, "loop%d", lo->lo_number);
|
||||
if (IS_ERR(lo->worker_task))
|
||||
return -ENOMEM;
|
||||
set_user_nice(lo->worker_task, MIN_NICE);
|
||||
return 0;
|
||||
return !css || css == blkcg_root_css;
|
||||
}
|
||||
#else
|
||||
static inline int queue_on_root_worker(struct cgroup_subsys_state *css)
|
||||
{
|
||||
return !css;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void loop_queue_work(struct loop_device *lo, struct loop_cmd *cmd)
|
||||
{
|
||||
struct rb_node **node = &(lo->worker_tree.rb_node), *parent = NULL;
|
||||
struct loop_worker *cur_worker, *worker = NULL;
|
||||
struct work_struct *work;
|
||||
struct list_head *cmd_list;
|
||||
|
||||
spin_lock_irq(&lo->lo_work_lock);
|
||||
|
||||
if (queue_on_root_worker(cmd->blkcg_css))
|
||||
goto queue_work;
|
||||
|
||||
node = &lo->worker_tree.rb_node;
|
||||
|
||||
while (*node) {
|
||||
parent = *node;
|
||||
cur_worker = container_of(*node, struct loop_worker, rb_node);
|
||||
if (cur_worker->blkcg_css == cmd->blkcg_css) {
|
||||
worker = cur_worker;
|
||||
break;
|
||||
} else if ((long)cur_worker->blkcg_css < (long)cmd->blkcg_css) {
|
||||
node = &(*node)->rb_left;
|
||||
} else {
|
||||
node = &(*node)->rb_right;
|
||||
}
|
||||
}
|
||||
if (worker)
|
||||
goto queue_work;
|
||||
|
||||
worker = kzalloc(sizeof(struct loop_worker), GFP_NOWAIT | __GFP_NOWARN);
|
||||
/*
|
||||
* In the event we cannot allocate a worker, just queue on the
|
||||
* rootcg worker and issue the I/O as the rootcg
|
||||
*/
|
||||
if (!worker) {
|
||||
cmd->blkcg_css = NULL;
|
||||
if (cmd->memcg_css)
|
||||
css_put(cmd->memcg_css);
|
||||
cmd->memcg_css = NULL;
|
||||
goto queue_work;
|
||||
}
|
||||
|
||||
worker->blkcg_css = cmd->blkcg_css;
|
||||
css_get(worker->blkcg_css);
|
||||
INIT_WORK(&worker->work, loop_workfn);
|
||||
INIT_LIST_HEAD(&worker->cmd_list);
|
||||
INIT_LIST_HEAD(&worker->idle_list);
|
||||
worker->lo = lo;
|
||||
rb_link_node(&worker->rb_node, parent, node);
|
||||
rb_insert_color(&worker->rb_node, &lo->worker_tree);
|
||||
queue_work:
|
||||
if (worker) {
|
||||
/*
|
||||
* We need to remove from the idle list here while
|
||||
* holding the lock so that the idle timer doesn't
|
||||
* free the worker
|
||||
*/
|
||||
if (!list_empty(&worker->idle_list))
|
||||
list_del_init(&worker->idle_list);
|
||||
work = &worker->work;
|
||||
cmd_list = &worker->cmd_list;
|
||||
} else {
|
||||
work = &lo->rootcg_work;
|
||||
cmd_list = &lo->rootcg_cmd_list;
|
||||
}
|
||||
list_add_tail(&cmd->list_entry, cmd_list);
|
||||
queue_work(lo->workqueue, work);
|
||||
spin_unlock_irq(&lo->lo_work_lock);
|
||||
}
|
||||
|
||||
static void loop_update_rotational(struct loop_device *lo)
|
||||
|
@ -1127,12 +1197,23 @@ static int loop_configure(struct loop_device *lo, fmode_t mode,
|
|||
!file->f_op->write_iter)
|
||||
lo->lo_flags |= LO_FLAGS_READ_ONLY;
|
||||
|
||||
error = loop_prepare_queue(lo);
|
||||
if (error)
|
||||
lo->workqueue = alloc_workqueue("loop%d",
|
||||
WQ_UNBOUND | WQ_FREEZABLE,
|
||||
0,
|
||||
lo->lo_number);
|
||||
if (!lo->workqueue) {
|
||||
error = -ENOMEM;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
set_disk_ro(lo->lo_disk, (lo->lo_flags & LO_FLAGS_READ_ONLY) != 0);
|
||||
|
||||
INIT_WORK(&lo->rootcg_work, loop_rootcg_workfn);
|
||||
INIT_LIST_HEAD(&lo->rootcg_cmd_list);
|
||||
INIT_LIST_HEAD(&lo->idle_worker_list);
|
||||
lo->worker_tree = RB_ROOT;
|
||||
timer_setup(&lo->timer, loop_free_idle_workers,
|
||||
TIMER_DEFERRABLE);
|
||||
lo->use_dio = lo->lo_flags & LO_FLAGS_DIRECT_IO;
|
||||
lo->lo_device = bdev;
|
||||
lo->lo_backing_file = file;
|
||||
|
@ -1200,6 +1281,7 @@ static int __loop_clr_fd(struct loop_device *lo, bool release)
|
|||
int err = 0;
|
||||
bool partscan = false;
|
||||
int lo_number;
|
||||
struct loop_worker *pos, *worker;
|
||||
|
||||
mutex_lock(&lo->lo_mutex);
|
||||
if (WARN_ON_ONCE(lo->lo_state != Lo_rundown)) {
|
||||
|
@ -1219,6 +1301,18 @@ static int __loop_clr_fd(struct loop_device *lo, bool release)
|
|||
/* freeze request queue during the transition */
|
||||
blk_mq_freeze_queue(lo->lo_queue);
|
||||
|
||||
destroy_workqueue(lo->workqueue);
|
||||
spin_lock_irq(&lo->lo_work_lock);
|
||||
list_for_each_entry_safe(worker, pos, &lo->idle_worker_list,
|
||||
idle_list) {
|
||||
list_del(&worker->idle_list);
|
||||
rb_erase(&worker->rb_node, &lo->worker_tree);
|
||||
css_put(worker->blkcg_css);
|
||||
kfree(worker);
|
||||
}
|
||||
spin_unlock_irq(&lo->lo_work_lock);
|
||||
del_timer_sync(&lo->timer);
|
||||
|
||||
spin_lock_irq(&lo->lo_lock);
|
||||
lo->lo_backing_file = NULL;
|
||||
spin_unlock_irq(&lo->lo_lock);
|
||||
|
@ -1255,7 +1349,6 @@ static int __loop_clr_fd(struct loop_device *lo, bool release)
|
|||
|
||||
partscan = lo->lo_flags & LO_FLAGS_PARTSCAN && bdev;
|
||||
lo_number = lo->lo_number;
|
||||
loop_unprepare_queue(lo);
|
||||
out_unlock:
|
||||
mutex_unlock(&lo->lo_mutex);
|
||||
if (partscan) {
|
||||
|
@ -2008,14 +2101,19 @@ static blk_status_t loop_queue_rq(struct blk_mq_hw_ctx *hctx,
|
|||
}
|
||||
|
||||
/* always use the first bio's css */
|
||||
cmd->blkcg_css = NULL;
|
||||
cmd->memcg_css = NULL;
|
||||
#ifdef CONFIG_BLK_CGROUP
|
||||
if (cmd->use_aio && rq->bio && rq->bio->bi_blkg) {
|
||||
cmd->css = &bio_blkcg(rq->bio)->css;
|
||||
css_get(cmd->css);
|
||||
} else
|
||||
if (rq->bio && rq->bio->bi_blkg) {
|
||||
cmd->blkcg_css = &bio_blkcg(rq->bio)->css;
|
||||
#ifdef CONFIG_MEMCG
|
||||
cmd->memcg_css =
|
||||
cgroup_get_e_css(cmd->blkcg_css->cgroup,
|
||||
&memory_cgrp_subsys);
|
||||
#endif
|
||||
cmd->css = NULL;
|
||||
kthread_queue_work(&lo->worker, &cmd->work);
|
||||
}
|
||||
#endif
|
||||
loop_queue_work(lo, cmd);
|
||||
|
||||
return BLK_STS_OK;
|
||||
}
|
||||
|
@ -2026,13 +2124,28 @@ static void loop_handle_cmd(struct loop_cmd *cmd)
|
|||
const bool write = op_is_write(req_op(rq));
|
||||
struct loop_device *lo = rq->q->queuedata;
|
||||
int ret = 0;
|
||||
struct mem_cgroup *old_memcg = NULL;
|
||||
|
||||
if (write && (lo->lo_flags & LO_FLAGS_READ_ONLY)) {
|
||||
ret = -EIO;
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if (cmd->blkcg_css)
|
||||
kthread_associate_blkcg(cmd->blkcg_css);
|
||||
if (cmd->memcg_css)
|
||||
old_memcg = set_active_memcg(
|
||||
mem_cgroup_from_css(cmd->memcg_css));
|
||||
|
||||
ret = do_req_filebacked(lo, rq);
|
||||
|
||||
if (cmd->blkcg_css)
|
||||
kthread_associate_blkcg(NULL);
|
||||
|
||||
if (cmd->memcg_css) {
|
||||
set_active_memcg(old_memcg);
|
||||
css_put(cmd->memcg_css);
|
||||
}
|
||||
failed:
|
||||
/* complete non-aio request */
|
||||
if (!cmd->use_aio || ret) {
|
||||
|
@ -2045,26 +2158,82 @@ static void loop_handle_cmd(struct loop_cmd *cmd)
|
|||
}
|
||||
}
|
||||
|
||||
static void loop_queue_work(struct kthread_work *work)
|
||||
static void loop_set_timer(struct loop_device *lo)
|
||||
{
|
||||
struct loop_cmd *cmd =
|
||||
container_of(work, struct loop_cmd, work);
|
||||
|
||||
loop_handle_cmd(cmd);
|
||||
timer_reduce(&lo->timer, jiffies + LOOP_IDLE_WORKER_TIMEOUT);
|
||||
}
|
||||
|
||||
static int loop_init_request(struct blk_mq_tag_set *set, struct request *rq,
|
||||
unsigned int hctx_idx, unsigned int numa_node)
|
||||
static void loop_process_work(struct loop_worker *worker,
|
||||
struct list_head *cmd_list, struct loop_device *lo)
|
||||
{
|
||||
struct loop_cmd *cmd = blk_mq_rq_to_pdu(rq);
|
||||
int orig_flags = current->flags;
|
||||
struct loop_cmd *cmd;
|
||||
|
||||
kthread_init_work(&cmd->work, loop_queue_work);
|
||||
return 0;
|
||||
current->flags |= PF_LOCAL_THROTTLE | PF_MEMALLOC_NOIO;
|
||||
spin_lock_irq(&lo->lo_work_lock);
|
||||
while (!list_empty(cmd_list)) {
|
||||
cmd = container_of(
|
||||
cmd_list->next, struct loop_cmd, list_entry);
|
||||
list_del(cmd_list->next);
|
||||
spin_unlock_irq(&lo->lo_work_lock);
|
||||
|
||||
loop_handle_cmd(cmd);
|
||||
cond_resched();
|
||||
|
||||
spin_lock_irq(&lo->lo_work_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* We only add to the idle list if there are no pending cmds
|
||||
* *and* the worker will not run again which ensures that it
|
||||
* is safe to free any worker on the idle list
|
||||
*/
|
||||
if (worker && !work_pending(&worker->work)) {
|
||||
worker->last_ran_at = jiffies;
|
||||
list_add_tail(&worker->idle_list, &lo->idle_worker_list);
|
||||
loop_set_timer(lo);
|
||||
}
|
||||
spin_unlock_irq(&lo->lo_work_lock);
|
||||
current->flags = orig_flags;
|
||||
}
|
||||
|
||||
static void loop_workfn(struct work_struct *work)
|
||||
{
|
||||
struct loop_worker *worker =
|
||||
container_of(work, struct loop_worker, work);
|
||||
loop_process_work(worker, &worker->cmd_list, worker->lo);
|
||||
}
|
||||
|
||||
static void loop_rootcg_workfn(struct work_struct *work)
|
||||
{
|
||||
struct loop_device *lo =
|
||||
container_of(work, struct loop_device, rootcg_work);
|
||||
loop_process_work(NULL, &lo->rootcg_cmd_list, lo);
|
||||
}
|
||||
|
||||
static void loop_free_idle_workers(struct timer_list *timer)
|
||||
{
|
||||
struct loop_device *lo = container_of(timer, struct loop_device, timer);
|
||||
struct loop_worker *pos, *worker;
|
||||
|
||||
spin_lock_irq(&lo->lo_work_lock);
|
||||
list_for_each_entry_safe(worker, pos, &lo->idle_worker_list,
|
||||
idle_list) {
|
||||
if (time_is_after_jiffies(worker->last_ran_at +
|
||||
LOOP_IDLE_WORKER_TIMEOUT))
|
||||
break;
|
||||
list_del(&worker->idle_list);
|
||||
rb_erase(&worker->rb_node, &lo->worker_tree);
|
||||
css_put(worker->blkcg_css);
|
||||
kfree(worker);
|
||||
}
|
||||
if (!list_empty(&lo->idle_worker_list))
|
||||
loop_set_timer(lo);
|
||||
spin_unlock_irq(&lo->lo_work_lock);
|
||||
}
|
||||
|
||||
static const struct blk_mq_ops loop_mq_ops = {
|
||||
.queue_rq = loop_queue_rq,
|
||||
.init_request = loop_init_request,
|
||||
.complete = lo_complete_rq,
|
||||
};
|
||||
|
||||
|
@ -2153,6 +2322,7 @@ static int loop_add(struct loop_device **l, int i)
|
|||
mutex_init(&lo->lo_mutex);
|
||||
lo->lo_number = i;
|
||||
spin_lock_init(&lo->lo_lock);
|
||||
spin_lock_init(&lo->lo_work_lock);
|
||||
disk->major = LOOP_MAJOR;
|
||||
disk->first_minor = i << part_shift;
|
||||
disk->fops = &lo_fops;
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
#include <linux/blk-mq.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <uapi/linux/loop.h>
|
||||
|
||||
/* Possible states of device */
|
||||
|
@ -55,8 +54,13 @@ struct loop_device {
|
|||
|
||||
spinlock_t lo_lock;
|
||||
int lo_state;
|
||||
struct kthread_worker worker;
|
||||
struct task_struct *worker_task;
|
||||
spinlock_t lo_work_lock;
|
||||
struct workqueue_struct *workqueue;
|
||||
struct work_struct rootcg_work;
|
||||
struct list_head rootcg_cmd_list;
|
||||
struct list_head idle_worker_list;
|
||||
struct rb_root worker_tree;
|
||||
struct timer_list timer;
|
||||
bool use_dio;
|
||||
bool sysfs_inited;
|
||||
|
||||
|
@ -67,13 +71,14 @@ struct loop_device {
|
|||
};
|
||||
|
||||
struct loop_cmd {
|
||||
struct kthread_work work;
|
||||
struct list_head list_entry;
|
||||
bool use_aio; /* use AIO interface to handle I/O */
|
||||
atomic_t ref; /* only for aio */
|
||||
long ret;
|
||||
struct kiocb iocb;
|
||||
struct bio_vec *bvec;
|
||||
struct cgroup_subsys_state *css;
|
||||
struct cgroup_subsys_state *blkcg_css;
|
||||
struct cgroup_subsys_state *memcg_css;
|
||||
};
|
||||
|
||||
/* Support for loadable transfer modules */
|
||||
|
|
|
@ -337,7 +337,7 @@ static unsigned long dax_get_unmapped_area(struct file *filp,
|
|||
}
|
||||
|
||||
static const struct address_space_operations dev_dax_aops = {
|
||||
.set_page_dirty = noop_set_page_dirty,
|
||||
.set_page_dirty = __set_page_dirty_no_writeback,
|
||||
.invalidatepage = noop_invalidatepage,
|
||||
};
|
||||
|
||||
|
|
|
@ -709,8 +709,8 @@ int amdgpu_ttm_tt_get_user_pages(struct amdgpu_bo *bo, struct page **pages)
|
|||
}
|
||||
|
||||
mmap_read_lock(mm);
|
||||
vma = find_vma(mm, start);
|
||||
if (unlikely(!vma || start < vma->vm_start)) {
|
||||
vma = vma_lookup(mm, start);
|
||||
if (unlikely(!vma)) {
|
||||
r = -EFAULT;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
|
|
@ -871,7 +871,7 @@ static int __igt_mmap(struct drm_i915_private *i915,
|
|||
|
||||
pr_debug("igt_mmap(%s, %d) @ %lx\n", obj->mm.region->name, type, addr);
|
||||
|
||||
area = find_vma(current->mm, addr);
|
||||
area = vma_lookup(current->mm, addr);
|
||||
if (!area) {
|
||||
pr_err("%s: Did not create a vm_area_struct for the mmap\n",
|
||||
obj->mm.region->name);
|
||||
|
|
|
@ -64,7 +64,7 @@ int get_vaddr_frames(unsigned long start, unsigned int nr_frames,
|
|||
do {
|
||||
unsigned long *nums = frame_vector_pfns(vec);
|
||||
|
||||
vma = find_vma_intersection(mm, start, start + 1);
|
||||
vma = vma_lookup(mm, start);
|
||||
if (!vma)
|
||||
break;
|
||||
|
||||
|
|
|
@ -49,8 +49,8 @@ struct vm_area_struct *gru_find_vma(unsigned long vaddr)
|
|||
{
|
||||
struct vm_area_struct *vma;
|
||||
|
||||
vma = find_vma(current->mm, vaddr);
|
||||
if (vma && vma->vm_start <= vaddr && vma->vm_ops == &gru_vm_ops)
|
||||
vma = vma_lookup(current->mm, vaddr);
|
||||
if (vma && vma->vm_ops == &gru_vm_ops)
|
||||
return vma;
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -567,7 +567,7 @@ static int vaddr_get_pfns(struct mm_struct *mm, unsigned long vaddr,
|
|||
vaddr = untagged_addr(vaddr);
|
||||
|
||||
retry:
|
||||
vma = find_vma_intersection(mm, vaddr, vaddr + 1);
|
||||
vma = vma_lookup(mm, vaddr);
|
||||
|
||||
if (vma && vma->vm_flags & VM_PFNMAP) {
|
||||
ret = follow_fault_pfn(vma, mm, vaddr, pfn, prot & IOMMU_WRITE);
|
||||
|
|
|
@ -993,6 +993,23 @@ static int virtballoon_probe(struct virtio_device *vdev)
|
|||
goto out_unregister_oom;
|
||||
}
|
||||
|
||||
/*
|
||||
* The default page reporting order is @pageblock_order, which
|
||||
* corresponds to 512MB in size on ARM64 when 64KB base page
|
||||
* size is used. The page reporting won't be triggered if the
|
||||
* freeing page can't come up with a free area like that huge.
|
||||
* So we specify the page reporting order to 5, corresponding
|
||||
* to 2MB. It helps to avoid THP splitting if 4KB base page
|
||||
* size is used by host.
|
||||
*
|
||||
* Ideally, the page reporting order is selected based on the
|
||||
* host's base page size. However, it needs more work to report
|
||||
* that value. The hard-coded order would be fine currently.
|
||||
*/
|
||||
#if defined(CONFIG_ARM64) && defined(CONFIG_ARM64_64K_PAGES)
|
||||
vb->pr_dev_info.order = 5;
|
||||
#endif
|
||||
|
||||
err = page_reporting_register(&vb->pr_dev_info);
|
||||
if (err)
|
||||
goto out_unregister_oom;
|
||||
|
|
|
@ -73,6 +73,7 @@ static sector_t _adfs_bmap(struct address_space *mapping, sector_t block)
|
|||
}
|
||||
|
||||
static const struct address_space_operations adfs_aops = {
|
||||
.set_page_dirty = __set_page_dirty_buffers,
|
||||
.readpage = adfs_readpage,
|
||||
.writepage = adfs_writepage,
|
||||
.write_begin = adfs_write_begin,
|
||||
|
|
|
@ -453,6 +453,7 @@ static sector_t _affs_bmap(struct address_space *mapping, sector_t block)
|
|||
}
|
||||
|
||||
const struct address_space_operations affs_aops = {
|
||||
.set_page_dirty = __set_page_dirty_buffers,
|
||||
.readpage = affs_readpage,
|
||||
.writepage = affs_writepage,
|
||||
.write_begin = affs_write_begin,
|
||||
|
@ -833,6 +834,7 @@ err_bh:
|
|||
}
|
||||
|
||||
const struct address_space_operations affs_aops_ofs = {
|
||||
.set_page_dirty = __set_page_dirty_buffers,
|
||||
.readpage = affs_readpage_ofs,
|
||||
//.writepage = affs_writepage_ofs,
|
||||
.write_begin = affs_write_begin_ofs,
|
||||
|
|
|
@ -188,6 +188,7 @@ static sector_t bfs_bmap(struct address_space *mapping, sector_t block)
|
|||
}
|
||||
|
||||
const struct address_space_operations bfs_aops = {
|
||||
.set_page_dirty = __set_page_dirty_buffers,
|
||||
.readpage = bfs_readpage,
|
||||
.writepage = bfs_writepage,
|
||||
.write_begin = bfs_write_begin,
|
||||
|
|
|
@ -222,7 +222,7 @@ static int load_aout_binary(struct linux_binprm * bprm)
|
|||
|
||||
error = vm_mmap(bprm->file, N_TXTADDR(ex), ex.a_text,
|
||||
PROT_READ | PROT_EXEC,
|
||||
MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
|
||||
MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,
|
||||
fd_offset);
|
||||
|
||||
if (error != N_TXTADDR(ex))
|
||||
|
@ -230,7 +230,7 @@ static int load_aout_binary(struct linux_binprm * bprm)
|
|||
|
||||
error = vm_mmap(bprm->file, N_DATADDR(ex), ex.a_data,
|
||||
PROT_READ | PROT_WRITE | PROT_EXEC,
|
||||
MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
|
||||
MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,
|
||||
fd_offset + ex.a_text);
|
||||
if (error != N_DATADDR(ex))
|
||||
return error;
|
||||
|
|
|
@ -1070,7 +1070,7 @@ out_free_interp:
|
|||
elf_prot = make_prot(elf_ppnt->p_flags, &arch_state,
|
||||
!!interpreter, false);
|
||||
|
||||
elf_flags = MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE;
|
||||
elf_flags = MAP_PRIVATE | MAP_DENYWRITE;
|
||||
|
||||
vaddr = elf_ppnt->p_vaddr;
|
||||
/*
|
||||
|
|
|
@ -928,7 +928,7 @@ static int elf_fdpic_map_file_constdisp_on_uclinux(
|
|||
{
|
||||
struct elf32_fdpic_loadseg *seg;
|
||||
struct elf32_phdr *phdr;
|
||||
unsigned long load_addr, base = ULONG_MAX, top = 0, maddr = 0, mflags;
|
||||
unsigned long load_addr, base = ULONG_MAX, top = 0, maddr = 0;
|
||||
int loop, ret;
|
||||
|
||||
load_addr = params->load_addr;
|
||||
|
@ -948,12 +948,8 @@ static int elf_fdpic_map_file_constdisp_on_uclinux(
|
|||
}
|
||||
|
||||
/* allocate one big anon block for everything */
|
||||
mflags = MAP_PRIVATE;
|
||||
if (params->flags & ELF_FDPIC_FLAG_EXECUTABLE)
|
||||
mflags |= MAP_EXECUTABLE;
|
||||
|
||||
maddr = vm_mmap(NULL, load_addr, top - base,
|
||||
PROT_READ | PROT_WRITE | PROT_EXEC, mflags, 0);
|
||||
PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, 0);
|
||||
if (IS_ERR_VALUE(maddr))
|
||||
return (int) maddr;
|
||||
|
||||
|
@ -1046,9 +1042,6 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params,
|
|||
if (phdr->p_flags & PF_X) prot |= PROT_EXEC;
|
||||
|
||||
flags = MAP_PRIVATE | MAP_DENYWRITE;
|
||||
if (params->flags & ELF_FDPIC_FLAG_EXECUTABLE)
|
||||
flags |= MAP_EXECUTABLE;
|
||||
|
||||
maddr = 0;
|
||||
|
||||
switch (params->flags & ELF_FDPIC_FLAG_ARRANGEMENT) {
|
||||
|
|
|
@ -573,7 +573,7 @@ static int load_flat_file(struct linux_binprm *bprm,
|
|||
pr_debug("ROM mapping of file (we hope)\n");
|
||||
|
||||
textpos = vm_mmap(bprm->file, 0, text_len, PROT_READ|PROT_EXEC,
|
||||
MAP_PRIVATE|MAP_EXECUTABLE, 0);
|
||||
MAP_PRIVATE, 0);
|
||||
if (!textpos || IS_ERR_VALUE(textpos)) {
|
||||
ret = textpos;
|
||||
if (!textpos)
|
||||
|
|
|
@ -1754,6 +1754,7 @@ static int blkdev_writepages(struct address_space *mapping,
|
|||
}
|
||||
|
||||
static const struct address_space_operations def_blk_aops = {
|
||||
.set_page_dirty = __set_page_dirty_buffers,
|
||||
.readpage = blkdev_readpage,
|
||||
.readahead = blkdev_readahead,
|
||||
.writepage = blkdev_writepage,
|
||||
|
|
25
fs/buffer.c
25
fs/buffer.c
|
@ -588,31 +588,6 @@ void mark_buffer_dirty_inode(struct buffer_head *bh, struct inode *inode)
|
|||
}
|
||||
EXPORT_SYMBOL(mark_buffer_dirty_inode);
|
||||
|
||||
/*
|
||||
* Mark the page dirty, and set it dirty in the page cache, and mark the inode
|
||||
* dirty.
|
||||
*
|
||||
* If warn is true, then emit a warning if the page is not uptodate and has
|
||||
* not been truncated.
|
||||
*
|
||||
* The caller must hold lock_page_memcg().
|
||||
*/
|
||||
void __set_page_dirty(struct page *page, struct address_space *mapping,
|
||||
int warn)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
xa_lock_irqsave(&mapping->i_pages, flags);
|
||||
if (page->mapping) { /* Race with truncate? */
|
||||
WARN_ON_ONCE(warn && !PageUptodate(page));
|
||||
account_page_dirtied(page, mapping);
|
||||
__xa_set_mark(&mapping->i_pages, page_index(page),
|
||||
PAGECACHE_TAG_DIRTY);
|
||||
}
|
||||
xa_unlock_irqrestore(&mapping->i_pages, flags);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__set_page_dirty);
|
||||
|
||||
/*
|
||||
* Add a page to the dirty page list.
|
||||
*
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче