* Re: [PATCH] x86: Deprecate a.out support
From: Måns Rullgård @ 2019-03-11 18:08 UTC (permalink / raw)
To: Linus Torvalds
Cc: Matt Turner, Borislav Petkov, Alan Cox, Matthew Wilcox, Jann Horn,
Al Viro, Thomas Gleixner, kernel list, linux-fsdevel,
the arch/x86 maintainers, Linux API, Andrew Morton,
Richard Weinberger, Anton Ivanov, linux-alpha, linux-m68k
In-Reply-To: <CAHk-=whD1SumZUBQeuMT-GcciwPxg_jW_TsPAmokYp3sGGCGhA@mail.gmail.com>
Linus Torvalds <torvalds@linux-foundation.org> writes:
> On Mon, Mar 11, 2019 at 9:26 AM Måns Rullgård <mans@mansr.com> wrote:
>>
>> Anyone running an Alpha machine likely also has some old OSF/1 binaries
>> they may wish to use. It would be a shame to remove this feature, IMO.
>
> If that's the case then we'd have to keep a.out alive for alpha, since
> that's the OSF/1 binary format (at least the only one we support - I'm
> not sure if later versions of OSF/1 ended up getting ELF).
The latest version I have is 5.1, and that uses ECOFF.
> Which I guess we could do, but the question is whether people really
> do have OSF/1 binaries. It was really useful early on as a source of
> known-good binaries to test with, but I'm not convinced it's still in
> use.
>
> It's not like there were OSF/1 binaries that we didn't havce access to
> natively (well, there _were_ special ones that didn't have open source
> versions, but most of them required more system-side support than
> Linux ever implemented, afaik).
I don't have any specific examples, but I can well imagine people
keeping an Alpha machine for no other reason than the ability to run
some (old) application only available (to them) for OSF/1. Running them
on Linux rather than Tru64 brings the advantage of being a modern system
in other regards.
For anything open source, there's little reason to keep the Alpha at
all.
--
Måns Rullgård
^ permalink raw reply
* Re: [PATCH] x86: Deprecate a.out support
From: Linus Torvalds @ 2019-03-11 16:45 UTC (permalink / raw)
To: Måns Rullgård
Cc: Matt Turner, Borislav Petkov, Alan Cox, Matthew Wilcox, Jann Horn,
Al Viro, Thomas Gleixner, kernel list, linux-fsdevel,
the arch/x86 maintainers, Linux API, Andrew Morton,
Richard Weinberger, Anton Ivanov, linux-alpha, linux-m68k
In-Reply-To: <yw1xa7i14btw.fsf@mansr.com>
On Mon, Mar 11, 2019 at 9:26 AM Måns Rullgård <mans@mansr.com> wrote:
>
> Anyone running an Alpha machine likely also has some old OSF/1 binaries
> they may wish to use. It would be a shame to remove this feature, IMO.
If that's the case then we'd have to keep a.out alive for alpha, since
that's the OSF/1 binary format (at least the only one we support - I'm
not sure if later versions of OSF/1 ended up getting ELF).
Which I guess we could do, but the question is whether people really
do have OSF/1 binaries. It was really useful early on as a source of
known-good binaries to test with, but I'm not convinced it's still in
use.
It's not like there were OSF/1 binaries that we didn't havce access to
natively (well, there _were_ special ones that didn't have open source
versions, but most of them required more system-side support than
Linux ever implemented, afaik).
Linus
^ permalink raw reply
* Re: [PATCH] x86: Deprecate a.out support
From: Måns Rullgård @ 2019-03-11 16:26 UTC (permalink / raw)
To: Linus Torvalds
Cc: Matt Turner, Borislav Petkov, Alan Cox, Matthew Wilcox, Jann Horn,
Al Viro, Thomas Gleixner, kernel list, linux-fsdevel,
the arch/x86 maintainers, Linux API, Andrew Morton,
Richard Weinberger, Anton Ivanov, linux-alpha, linux-m68k
In-Reply-To: <CAHk-=wgt7M6yA5BJCJo0nF22WgPJnN8CvViL9CAJmd+S+Civ6w@mail.gmail.com>
Linus Torvalds <torvalds@linux-foundation.org> writes:
> On Sun, Mar 10, 2019 at 2:37 PM Matt Turner <mattst88@gmail.com> wrote:
>>
>> I'm not aware of a reason to keep a.out support on alpha.
>
> Hmm. I was looking at removing a.out support entirely, but it's
> actually fairly incestuous on alpha.
>
> For example, arch/alpha/boot/tools/objstrip.c very much has some a.out
> support in it. Maybe it can just be removed entirely.
>
> There's also an a.out.h include in arch/alpha/kernel/binfmt_loader.c.
>
> Finally, note that CONFIG_OSF4_COMPAT also no longer makes sense
> without a.out support.
Anyone running an Alpha machine likely also has some old OSF/1 binaries
they may wish to use. It would be a shame to remove this feature, IMO.
--
Måns Rullgård
^ permalink raw reply
* Re: [PATCHv7 00/10] Heterogenous memory node attributes
From: Jonathan Cameron @ 2019-03-11 11:47 UTC (permalink / raw)
To: Keith Busch
Cc: linux-kernel, linux-acpi, linux-mm, linux-api, Greg Kroah-Hartman,
Rafael Wysocki, Dave Hansen, Dan Williams, linuxarm
In-Reply-To: <20190227225038.20438-1-keith.busch@intel.com>
On Wed, 27 Feb 2019 15:50:28 -0700
Keith Busch <keith.busch@intel.com> wrote:
> == Changes since v6 ==
>
> Updated to linux-next, which has a change to the HMAT structures to
> account for ACPI revision 6.3.
>
> Changed memory-side cache "associativity" attribute to "indexing"
>
>
> Regarding the Kconfig, I am having the implementation specific as a user
> selectable option, and the generic interface, HMEM_REPORTING, is not a
> user prompt. I just wanted to clarify the point that there's only one.
>
>
> == Background ==
>
> Platforms may provide multiple types of cpu attached system memory. The
> memory ranges for each type may have different characteristics that
> applications may wish to know about when considering what node they want
> their memory allocated from.
>
> It had previously been difficult to describe these setups as memory
> rangers were generally lumped into the NUMA node of the CPUs. New
> platform attributes have been created and in use today that describe
> the more complex memory hierarchies that can be created.
>
> This series' objective is to provide the attributes from such systems
> that are useful for applications to know about, and readily usable with
> existing tools and libraries. Those applications may query performance
> attributes relative to a particular CPU they're running on in order to
> make more informed choices for where they want to allocate hot and cold
> data. This works with mbind() or the numactl library.
Hi Keith,
Great to see this 'nearly' good to go.
For those that were too small / trivial to deserve a reviewed-by
Acked-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Subject to that one tweak in patch 7,
Tested-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Note that my tests were very limited for the memory-side caches
and not exactly comprehensive for the access attributes either.
They focused on the cases I care about rather than putting together
a fuller test suite. That is probably worth doing at some point though
not sure I'll get to it any time soon.
Thanks,
Jonathan
>
> Keith Busch (10):
> acpi: Create subtable parsing infrastructure
> acpi: Add HMAT to generic parsing tables
> acpi/hmat: Parse and report heterogeneous memory
> node: Link memory nodes to their compute nodes
> node: Add heterogenous memory access attributes
> node: Add memory-side caching attributes
> acpi/hmat: Register processor domain to its memory
> acpi/hmat: Register performance attributes
> acpi/hmat: Register memory side cache attributes
> doc/mm: New documentation for memory performance
>
> Documentation/ABI/stable/sysfs-devices-node | 87 +++-
> Documentation/admin-guide/mm/numaperf.rst | 164 +++++++
> arch/arm64/kernel/acpi_numa.c | 2 +-
> arch/arm64/kernel/smp.c | 4 +-
> arch/ia64/kernel/acpi.c | 14 +-
> arch/x86/kernel/acpi/boot.c | 36 +-
> drivers/acpi/Kconfig | 1 +
> drivers/acpi/Makefile | 1 +
> drivers/acpi/hmat/Kconfig | 11 +
> drivers/acpi/hmat/Makefile | 1 +
> drivers/acpi/hmat/hmat.c | 670 ++++++++++++++++++++++++++
> drivers/acpi/numa.c | 16 +-
> drivers/acpi/scan.c | 4 +-
> drivers/acpi/tables.c | 76 ++-
> drivers/base/Kconfig | 8 +
> drivers/base/node.c | 352 +++++++++++++-
> drivers/irqchip/irq-gic-v2m.c | 2 +-
> drivers/irqchip/irq-gic-v3-its-pci-msi.c | 2 +-
> drivers/irqchip/irq-gic-v3-its-platform-msi.c | 2 +-
> drivers/irqchip/irq-gic-v3-its.c | 6 +-
> drivers/irqchip/irq-gic-v3.c | 10 +-
> drivers/irqchip/irq-gic.c | 4 +-
> drivers/mailbox/pcc.c | 2 +-
> include/linux/acpi.h | 6 +-
> include/linux/node.h | 72 ++-
> 25 files changed, 1487 insertions(+), 66 deletions(-)
> create mode 100644 Documentation/admin-guide/mm/numaperf.rst
> create mode 100644 drivers/acpi/hmat/Kconfig
> create mode 100644 drivers/acpi/hmat/Makefile
> create mode 100644 drivers/acpi/hmat/hmat.c
>
^ permalink raw reply
* Re: [PATCHv7 10/10] doc/mm: New documentation for memory performance
From: Jonathan Cameron @ 2019-03-11 11:38 UTC (permalink / raw)
To: Keith Busch
Cc: linux-kernel, linux-acpi, linux-mm, linux-api, Greg Kroah-Hartman,
Rafael Wysocki, Dave Hansen, Dan Williams
In-Reply-To: <20190227225038.20438-11-keith.busch@intel.com>
On Wed, 27 Feb 2019 15:50:38 -0700
Keith Busch <keith.busch@intel.com> wrote:
> Platforms may provide system memory where some physical address ranges
> perform differently than others, or is side cached by the system.
The magic 'side cached' term still here in the patch description, ideally
wants cleaning up.
>
> Add documentation describing a high level overview of such systems and the
> perforamnce and caching attributes the kernel provides for applications
performance
> wishing to query this information.
>
> Reviewed-by: Mike Rapoport <rppt@linux.ibm.com>
> Signed-off-by: Keith Busch <keith.busch@intel.com>
A few comments inline. Mostly the weird corner cases that I miss understood
in one of the earlier versions of the code.
Whilst I think perhaps that one section could be tweaked a tiny bit I'm basically
happy with this if you don't want to.
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> ---
> Documentation/admin-guide/mm/numaperf.rst | 164 ++++++++++++++++++++++++++++++
> 1 file changed, 164 insertions(+)
> create mode 100644 Documentation/admin-guide/mm/numaperf.rst
>
> diff --git a/Documentation/admin-guide/mm/numaperf.rst b/Documentation/admin-guide/mm/numaperf.rst
> new file mode 100644
> index 000000000000..d32756b9be48
> --- /dev/null
> +++ b/Documentation/admin-guide/mm/numaperf.rst
> @@ -0,0 +1,164 @@
> +.. _numaperf:
> +
> +=============
> +NUMA Locality
> +=============
> +
> +Some platforms may have multiple types of memory attached to a compute
> +node. These disparate memory ranges may share some characteristics, such
> +as CPU cache coherence, but may have different performance. For example,
> +different media types and buses affect bandwidth and latency.
> +
> +A system supports such heterogeneous memory by grouping each memory type
> +under different domains, or "nodes", based on locality and performance
> +characteristics. Some memory may share the same node as a CPU, and others
> +are provided as memory only nodes. While memory only nodes do not provide
> +CPUs, they may still be local to one or more compute nodes relative to
> +other nodes. The following diagram shows one such example of two compute
> +nodes with local memory and a memory only node for each of compute node:
> +
> + +------------------+ +------------------+
> + | Compute Node 0 +-----+ Compute Node 1 |
> + | Local Node0 Mem | | Local Node1 Mem |
> + +--------+---------+ +--------+---------+
> + | |
> + +--------+---------+ +--------+---------+
> + | Slower Node2 Mem | | Slower Node3 Mem |
> + +------------------+ +--------+---------+
> +
> +A "memory initiator" is a node containing one or more devices such as
> +CPUs or separate memory I/O devices that can initiate memory requests.
> +A "memory target" is a node containing one or more physical address
> +ranges accessible from one or more memory initiators.
> +
> +When multiple memory initiators exist, they may not all have the same
> +performance when accessing a given memory target. Each initiator-target
> +pair may be organized into different ranked access classes to represent
> +this relationship.
This concept is a bit vague at the moment. Largely because only access0
is actually defined. We should definitely keep a close eye on any others
that are defined in future to make sure this text is still valid.
I can certainly see it being used for different ideas of 'best' rather
than simply best and second best etc.
> The highest performing initiator to a given target
> +is considered to be one of that target's local initiators, and given
> +the highest access class, 0. Any given target may have one or more
> +local initiators, and any given initiator may have multiple local
> +memory targets.
> +
> +To aid applications matching memory targets with their initiators, the
> +kernel provides symlinks to each other. The following example lists the
> +relationship for the access class "0" memory initiators and targets, which is
> +the of nodes with the highest performing access relationship::
> +
> + # symlinks -v /sys/devices/system/node/nodeX/access0/targets/
> + relative: /sys/devices/system/node/nodeX/access0/targets/nodeY -> ../../nodeY
So this one perhaps needs a bit more description - I would put it after initiators
which precisely fits the description you have here now.
"targets contains those nodes for which this initiator is the best possible initiator."
which is subtly different form
"targets contains those nodes to which this node has the highest
performing access characteristics."
For example in my test case:
* 4 nodes with local memory and cpu, 1 node remote and equal distant from all of the
initiators,
targets for the compute nodes contains both themselves and the remote node, to which
the characteristics are of course worse. As you point out before, we need to look
in
node0/access0/targets/node0/access0/initiators
node0/access0/targets/node4/access0/initiators
to get the relevant characteristics and work out that node0 is 'nearer' itself
(obviously this is a bit of a silly case, but we could have no memory node0 and
be talking about node4 and node5.
I am happy with the actual interface, this is just a question about whether we can tweak
this text to be slightly clearer.
> +
> + # symlinks -v /sys/devices/system/node/nodeY/access0/initiators/
> + relative: /sys/devices/system/node/nodeY/access0/initiators/nodeX -> ../../nodeX
> +
> +================
> +NUMA Performance
> +================
> +
> +Applications may wish to consider which node they want their memory to
> +be allocated from based on the node's performance characteristics. If
> +the system provides these attributes, the kernel exports them under the
> +node sysfs hierarchy by appending the attributes directory under the
> +memory node's access class 0 initiators as follows::
> +
> + /sys/devices/system/node/nodeY/access0/initiators/
> +
> +These attributes apply only when accessed from nodes that have the
> +are linked under the this access's inititiators.
> +
> +The performance characteristics the kernel provides for the local initiators
> +are exported are as follows::
> +
> + # tree -P "read*|write*" /sys/devices/system/node/nodeY/access0/initiators/
> + /sys/devices/system/node/nodeY/access0/initiators/
> + |-- read_bandwidth
> + |-- read_latency
> + |-- write_bandwidth
> + `-- write_latency
> +
> +The bandwidth attributes are provided in MiB/second.
> +
> +The latency attributes are provided in nanoseconds.
> +
> +The values reported here correspond to the rated latency and bandwidth
> +for the platform.
> +
> +==========
> +NUMA Cache
> +==========
> +
> +System memory may be constructed in a hierarchy of elements with various
> +performance characteristics in order to provide large address space of
> +slower performing memory cached by a smaller higher performing memory. The
> +system physical addresses memory initiators are aware of are provided
> +by the last memory level in the hierarchy. The system meanwhile uses
> +higher performing memory to transparently cache access to progressively
> +slower levels.
> +
> +The term "far memory" is used to denote the last level memory in the
> +hierarchy. Each increasing cache level provides higher performing
> +initiator access, and the term "near memory" represents the fastest
> +cache provided by the system.
> +
> +This numbering is different than CPU caches where the cache level (ex:
> +L1, L2, L3) uses the CPU-side view where each increased level is lower
> +performing. In contrast, the memory cache level is centric to the last
> +level memory, so the higher numbered cache level corresponds to memory
> +nearer to the CPU, and further from far memory.
> +
> +The memory-side caches are not directly addressable by software. When
> +software accesses a system address, the system will return it from the
> +near memory cache if it is present. If it is not present, the system
> +accesses the next level of memory until there is either a hit in that
> +cache level, or it reaches far memory.
> +
> +An application does not need to know about caching attributes in order
> +to use the system. Software may optionally query the memory cache
> +attributes in order to maximize the performance out of such a setup.
> +If the system provides a way for the kernel to discover this information,
> +for example with ACPI HMAT (Heterogeneous Memory Attribute Table),
> +the kernel will append these attributes to the NUMA node memory target.
> +
> +When the kernel first registers a memory cache with a node, the kernel
> +will create the following directory::
Real nitpick but more precisely, "If relevant, the kernel..." Otherwise
we say it's always there but then say it isn't below.
> +
> + /sys/devices/system/node/nodeX/memory_side_cache/
> +
> +If that directory is not present, the system either does not not provide
> +a memory-side cache, or that information is not accessible to the kernel.
> +
> +The attributes for each level of cache is provided under its cache
> +level index::
> +
> + /sys/devices/system/node/nodeX/memory_side_cache/indexA/
> + /sys/devices/system/node/nodeX/memory_side_cache/indexB/
> + /sys/devices/system/node/nodeX/memory_side_cache/indexC/
> +
> +Each cache level's directory provides its attributes. For example, the
> +following shows a single cache level and the attributes available for
> +software to query::
> +
> + # tree sys/devices/system/node/node0/memory_side_cache/
> + /sys/devices/system/node/node0/memory_side_cache/
> + |-- index1
> + | |-- indexing
> + | |-- line_size
> + | |-- size
> + | `-- write_policy
> +
> +The "indexing" will be 0 if it is a direct-mapped cache, and non-zero
> +for any other indexed based, multi-way associativity.
> +
> +The "line_size" is the number of bytes accessed from the next cache
> +level on a miss.
> +
> +The "size" is the number of bytes provided by this cache level.
> +
> +The "write_policy" will be 0 for write-back, and non-zero for
> +write-through caching.
> +
> +========
> +See Also
> +========
> +.. [1] https://www.uefi.org/sites/default/files/resources/ACPI_6_2.pdf
> + Section 5.2.27
^ permalink raw reply
* Re: [PATCHv7 08/10] acpi/hmat: Register performance attributes
From: Jonathan Cameron @ 2019-03-11 11:21 UTC (permalink / raw)
To: Keith Busch
Cc: linux-kernel, linux-acpi, linux-mm, linux-api, Greg Kroah-Hartman,
Rafael Wysocki, Dave Hansen, Dan Williams
In-Reply-To: <20190227225038.20438-9-keith.busch@intel.com>
On Wed, 27 Feb 2019 15:50:36 -0700
Keith Busch <keith.busch@intel.com> wrote:
> Save the best performace access attributes and register these with the
performance
> memory's node if HMAT provides the locality table. While HMAT does make
> it possible to know performance for all possible initiator-target
> pairings, we export only the local pairings at this time.
>
> Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> Signed-off-by: Keith Busch <keith.busch@intel.com>
Jonathan
> ---
> drivers/acpi/hmat/Kconfig | 5 ++++-
> drivers/acpi/hmat/hmat.c | 10 +++++++++-
> 2 files changed, 13 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/acpi/hmat/Kconfig b/drivers/acpi/hmat/Kconfig
> index 13cddd612a52..95a29964dbea 100644
> --- a/drivers/acpi/hmat/Kconfig
> +++ b/drivers/acpi/hmat/Kconfig
> @@ -2,7 +2,10 @@
> config ACPI_HMAT
> bool "ACPI Heterogeneous Memory Attribute Table Support"
> depends on ACPI_NUMA
> + select HMEM_REPORTING
> help
> If set, this option has the kernel parse and report the
> platform's ACPI HMAT (Heterogeneous Memory Attributes Table),
> - and register memory initiators with their targets.
> + register memory initiators with their targets, and export
> + performance attributes through the node's sysfs device if
> + provided.
> diff --git a/drivers/acpi/hmat/hmat.c b/drivers/acpi/hmat/hmat.c
> index bb6a11653729..5b469c98a454 100644
> --- a/drivers/acpi/hmat/hmat.c
> +++ b/drivers/acpi/hmat/hmat.c
> @@ -549,12 +549,20 @@ static __init void hmat_register_target_initiators(struct memory_target *target)
> }
> }
>
> +static __init void hmat_register_target_perf(struct memory_target *target)
> +{
> + unsigned mem_nid = pxm_to_node(target->memory_pxm);
> + node_set_perf_attrs(mem_nid, &target->hmem_attrs, 0);
> +}
> +
> static __init void hmat_register_targets(void)
> {
> struct memory_target *target;
>
> - list_for_each_entry(target, &targets, node)
> + list_for_each_entry(target, &targets, node) {
> hmat_register_target_initiators(target);
> + hmat_register_target_perf(target);
> + }
> }
>
> static __init void hmat_free_structures(void)
^ permalink raw reply
* Re: [PATCHv7 07/10] acpi/hmat: Register processor domain to its memory
From: Jonathan Cameron @ 2019-03-11 11:20 UTC (permalink / raw)
To: Keith Busch
Cc: linux-kernel, linux-acpi, linux-mm, linux-api, Greg Kroah-Hartman,
Rafael Wysocki, Dave Hansen, Dan Williams
In-Reply-To: <20190227225038.20438-8-keith.busch@intel.com>
On Wed, 27 Feb 2019 15:50:35 -0700
Keith Busch <keith.busch@intel.com> wrote:
> If the HMAT Subsystem Address Range provides a valid processor proximity
> domain for a memory domain, or a processor domain matches the performance
> access of the valid processor proximity domain, register the memory
> target with that initiator so this relationship will be visible under
> the node's sysfs directory.
>
> Since HMAT requires valid address ranges have an equivalent SRAT entry,
> verify each memory target satisfies this requirement.
>
> Signed-off-by: Keith Busch <keith.busch@intel.com>
Hi Keith,
I have that test case with a single remote memory only node and it is ending
up with no associated initiators.
I made a minor modification inline and it works as expected.
With that change
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Jonathan
> ---
> drivers/acpi/hmat/Kconfig | 3 +-
> drivers/acpi/hmat/hmat.c | 395 +++++++++++++++++++++++++++++++++++++++++++++-
> 2 files changed, 396 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/acpi/hmat/Kconfig b/drivers/acpi/hmat/Kconfig
> index 2f7111b7af62..13cddd612a52 100644
> --- a/drivers/acpi/hmat/Kconfig
> +++ b/drivers/acpi/hmat/Kconfig
> @@ -4,4 +4,5 @@ config ACPI_HMAT
> depends on ACPI_NUMA
> help
> If set, this option has the kernel parse and report the
> - platform's ACPI HMAT (Heterogeneous Memory Attributes Table).
> + platform's ACPI HMAT (Heterogeneous Memory Attributes Table),
> + and register memory initiators with their targets.
> diff --git a/drivers/acpi/hmat/hmat.c b/drivers/acpi/hmat/hmat.c
> index 99f711420f6d..bb6a11653729 100644
> --- a/drivers/acpi/hmat/hmat.c
> +++ b/drivers/acpi/hmat/hmat.c
> @@ -13,11 +13,105 @@
> #include <linux/device.h>
> #include <linux/init.h>
> #include <linux/list.h>
> +#include <linux/list_sort.h>
> #include <linux/node.h>
> #include <linux/sysfs.h>
>
> static __initdata u8 hmat_revision;
>
> +static __initdata LIST_HEAD(targets);
> +static __initdata LIST_HEAD(initiators);
> +static __initdata LIST_HEAD(localities);
> +
> +/*
> + * The defined enum order is used to prioritize attributes to break ties when
> + * selecting the best performing node.
> + */
> +enum locality_types {
> + WRITE_LATENCY,
> + READ_LATENCY,
> + WRITE_BANDWIDTH,
> + READ_BANDWIDTH,
> +};
> +
> +static struct memory_locality *localities_types[4];
> +
> +struct memory_target {
> + struct list_head node;
> + unsigned int memory_pxm;
> + unsigned int processor_pxm;
> + struct node_hmem_attrs hmem_attrs;
> +};
> +
> +struct memory_initiator {
> + struct list_head node;
> + unsigned int processor_pxm;
> +};
> +
> +struct memory_locality {
> + struct list_head node;
> + struct acpi_hmat_locality *hmat_loc;
> +};
> +
> +static __init struct memory_initiator *find_mem_initiator(unsigned int cpu_pxm)
> +{
> + struct memory_initiator *intitator;
> +
> + list_for_each_entry(intitator, &initiators, node)
> + if (intitator->processor_pxm == cpu_pxm)
> + return intitator;
> + return NULL;
> +}
> +
> +static __init struct memory_target *find_mem_target(unsigned int mem_pxm)
> +{
> + struct memory_target *target;
> +
> + list_for_each_entry(target, &targets, node)
> + if (target->memory_pxm == mem_pxm)
> + return target;
> + return NULL;
> +}
> +
> +static __init void alloc_memory_initiator(unsigned int cpu_pxm)
> +{
> + struct memory_initiator *intitator;
> +
> + if (pxm_to_node(cpu_pxm) == NUMA_NO_NODE)
> + return;
> +
> + intitator = find_mem_initiator(cpu_pxm);
> + if (intitator)
> + return;
> +
> + intitator = kzalloc(sizeof(*intitator), GFP_KERNEL);
> + if (!intitator)
> + return;
> +
> + intitator->processor_pxm = cpu_pxm;
> + list_add_tail(&intitator->node, &initiators);
> +}
> +
> +static __init void alloc_memory_target(unsigned int mem_pxm)
> +{
> + struct memory_target *target;
> +
> + if (pxm_to_node(mem_pxm) == NUMA_NO_NODE)
> + return;
> +
> + target = find_mem_target(mem_pxm);
> + if (target)
> + return;
> +
> + target = kzalloc(sizeof(*target), GFP_KERNEL);
> + if (!target)
> + return;
> +
> + target->memory_pxm = mem_pxm;
> + target->processor_pxm = PXM_INVAL;
> + list_add_tail(&target->node, &targets);
> +}
> +
> static __init const char *hmat_data_type(u8 type)
> {
> switch (type) {
> @@ -89,14 +183,83 @@ static __init u32 hmat_normalize(u16 entry, u64 base, u8 type)
> return value;
> }
>
> +static __init void hmat_update_target_access(struct memory_target *target,
> + u8 type, u32 value)
> +{
> + switch (type) {
> + case ACPI_HMAT_ACCESS_LATENCY:
> + target->hmem_attrs.read_latency = value;
> + target->hmem_attrs.write_latency = value;
> + break;
> + case ACPI_HMAT_READ_LATENCY:
> + target->hmem_attrs.read_latency = value;
> + break;
> + case ACPI_HMAT_WRITE_LATENCY:
> + target->hmem_attrs.write_latency = value;
> + break;
> + case ACPI_HMAT_ACCESS_BANDWIDTH:
> + target->hmem_attrs.read_bandwidth = value;
> + target->hmem_attrs.write_bandwidth = value;
> + break;
> + case ACPI_HMAT_READ_BANDWIDTH:
> + target->hmem_attrs.read_bandwidth = value;
> + break;
> + case ACPI_HMAT_WRITE_BANDWIDTH:
> + target->hmem_attrs.write_bandwidth = value;
> + break;
> + default:
> + break;
> + }
> +}
> +
> +static __init void hmat_add_locality(struct acpi_hmat_locality *hmat_loc)
> +{
> + struct memory_locality *loc;
> +
> + loc = kzalloc(sizeof(*loc), GFP_KERNEL);
> + if (!loc) {
> + pr_notice_once("Failed to allocate HMAT locality\n");
> + return;
> + }
> +
> + loc->hmat_loc = hmat_loc;
> + list_add_tail(&loc->node, &localities);
> +
> + switch (hmat_loc->data_type) {
> + case ACPI_HMAT_ACCESS_LATENCY:
> + localities_types[READ_LATENCY] = loc;
> + localities_types[WRITE_LATENCY] = loc;
> + break;
> + case ACPI_HMAT_READ_LATENCY:
> + localities_types[READ_LATENCY] = loc;
> + break;
> + case ACPI_HMAT_WRITE_LATENCY:
> + localities_types[WRITE_LATENCY] = loc;
> + break;
> + case ACPI_HMAT_ACCESS_BANDWIDTH:
> + localities_types[READ_BANDWIDTH] = loc;
> + localities_types[WRITE_BANDWIDTH] = loc;
> + break;
> + case ACPI_HMAT_READ_BANDWIDTH:
> + localities_types[READ_BANDWIDTH] = loc;
> + break;
> + case ACPI_HMAT_WRITE_BANDWIDTH:
> + localities_types[WRITE_BANDWIDTH] = loc;
> + break;
> + default:
> + break;
> + }
> +}
> +
> static __init int hmat_parse_locality(union acpi_subtable_headers *header,
> const unsigned long end)
> {
> struct acpi_hmat_locality *hmat_loc = (void *)header;
> + struct memory_target *target;
> unsigned int init, targ, total_size, ipds, tpds;
> u32 *inits, *targs, value;
> u16 *entries;
> - u8 type;
> + u8 type, mem_hier;
>
> if (hmat_loc->header.length < sizeof(*hmat_loc)) {
> pr_notice("HMAT: Unexpected locality header length: %d\n",
> @@ -105,6 +268,7 @@ static __init int hmat_parse_locality(union acpi_subtable_headers *header,
> }
>
> type = hmat_loc->data_type;
> + mem_hier = hmat_loc->flags & ACPI_HMAT_MEMORY_HIERARCHY;
> ipds = hmat_loc->number_of_initiator_Pds;
> tpds = hmat_loc->number_of_target_Pds;
> total_size = sizeof(*hmat_loc) + sizeof(*entries) * ipds * tpds +
> @@ -123,6 +287,7 @@ static __init int hmat_parse_locality(union acpi_subtable_headers *header,
> targs = inits + ipds;
> entries = (u16 *)(targs + tpds);
> for (init = 0; init < ipds; init++) {
> + alloc_memory_initiator(inits[init]);
> for (targ = 0; targ < tpds; targ++) {
> value = hmat_normalize(entries[init * tpds + targ],
> hmat_loc->entry_base_unit,
> @@ -130,9 +295,18 @@ static __init int hmat_parse_locality(union acpi_subtable_headers *header,
> pr_info(" Initiator-Target[%d-%d]:%d%s\n",
> inits[init], targs[targ], value,
> hmat_data_type_suffix(type));
> +
> + if (mem_hier == ACPI_HMAT_MEMORY) {
> + target = find_mem_target(targs[targ]);
> + if (target && target->processor_pxm == inits[init])
> + hmat_update_target_access(target, type, value);
> + }
> }
> }
>
> + if (mem_hier == ACPI_HMAT_MEMORY)
> + hmat_add_locality(hmat_loc);
> +
> return 0;
> }
>
> @@ -176,6 +350,23 @@ static int __init hmat_parse_address_range(union acpi_subtable_headers *header,
> pr_info("HMAT: Memory Flags:%04x Processor Domain:%d Memory Domain:%d\n",
> p->flags, p->processor_PD, p->memory_PD);
>
> + if (p->flags & ACPI_HMAT_MEMORY_PD_VALID) {
> + target = find_mem_target(p->memory_PD);
> + if (!target) {
> + pr_debug("HMAT: Memory Domain missing from SRAT\n");
> + return -EINVAL;
> + }
> + }
> + if (target && p->flags & ACPI_HMAT_PROCESSOR_PD_VALID) {
> + int p_node = pxm_to_node(p->processor_PD);
> +
> + if (p_node == NUMA_NO_NODE) {
> + pr_debug("HMAT: Invalid Processor Domain\n");
> + return -EINVAL;
> + }
> + target->processor_pxm = p_node;
> + }
> +
> return 0;
> }
>
> @@ -199,6 +390,195 @@ static int __init hmat_parse_subtable(union acpi_subtable_headers *header,
> }
> }
>
> +static __init int srat_parse_mem_affinity(union acpi_subtable_headers *header,
> + const unsigned long end)
> +{
> + struct acpi_srat_mem_affinity *ma = (void *)header;
> +
> + if (!ma)
> + return -EINVAL;
> + if (!(ma->flags & ACPI_SRAT_MEM_ENABLED))
> + return 0;
> + alloc_memory_target(ma->proximity_domain);
> + return 0;
> +}
> +
> +static __init u32 hmat_initiator_perf(struct memory_target *target,
> + struct memory_initiator *initiator,
> + struct acpi_hmat_locality *hmat_loc)
> +{
> + unsigned int ipds, tpds, i, idx = 0, tdx = 0;
> + u32 *inits, *targs;
> + u16 *entries;
> +
> + ipds = hmat_loc->number_of_initiator_Pds;
> + tpds = hmat_loc->number_of_target_Pds;
> + inits = (u32 *)(hmat_loc + 1);
> + targs = inits + ipds;
> + entries = (u16 *)(targs + tpds);
> +
> + for (i = 0; i < ipds; i++) {
> + if (inits[i] == initiator->processor_pxm) {
> + idx = i;
> + break;
> + }
> + }
> +
> + if (i == ipds)
> + return 0;
> +
> + for (i = 0; i < tpds; i++) {
> + if (targs[i] == target->memory_pxm) {
> + tdx = i;
> + break;
> + }
> + }
> + if (i == tpds)
> + return 0;
> +
> + return hmat_normalize(entries[idx * tpds + tdx],
> + hmat_loc->entry_base_unit,
> + hmat_loc->data_type);
> +}
> +
> +static __init bool hmat_update_best(u8 type, u32 value, u32 *best)
> +{
> + bool updated = false;
> +
> + if (!value)
> + return false;
> +
> + switch (type) {
> + case ACPI_HMAT_ACCESS_LATENCY:
> + case ACPI_HMAT_READ_LATENCY:
> + case ACPI_HMAT_WRITE_LATENCY:
> + if (!*best || *best > value) {
> + *best = value;
> + updated = true;
> + }
> + break;
> + case ACPI_HMAT_ACCESS_BANDWIDTH:
> + case ACPI_HMAT_READ_BANDWIDTH:
> + case ACPI_HMAT_WRITE_BANDWIDTH:
> + if (!*best || *best < value) {
> + *best = value;
> + updated = true;
> + }
> + break;
> + }
> +
> + return updated;
> +}
> +
> +static int initiator_cmp(void *priv, struct list_head *a, struct list_head *b)
> +{
> + struct memory_initiator *ia;
> + struct memory_initiator *ib;
> + unsigned long *p_nodes = priv;
> +
> + ia = list_entry(a, struct memory_initiator, node);
> + ib = list_entry(b, struct memory_initiator, node);
> +
> + set_bit(ia->processor_pxm, p_nodes);
> + set_bit(ib->processor_pxm, p_nodes);
> +
> + return ia->processor_pxm - ib->processor_pxm;
> +}
> +
> +static __init void hmat_register_target_initiators(struct memory_target *target)
> +{
> + static DECLARE_BITMAP(p_nodes, MAX_NUMNODES);
> + struct memory_initiator *initiator;
> + unsigned int mem_nid, cpu_nid;
> + struct memory_locality *loc = NULL;
> + u32 best = 0;
> + int i;
> +
(upshot of the below is I removed this test :)
> + if (target->processor_pxm == PXM_INVAL)
> + return;
This doesn't look right. We check first if it is invalid and return....
> +
> + mem_nid = pxm_to_node(target->memory_pxm);
> +
> + /*
> + * If the Address Range Structure provides a local processor pxm, link
> + * only that one. Otherwise, find the best performance attribtes and
> + * register all initiators that match.
> + */
> + if (target->processor_pxm != PXM_INVAL) {
Here we check the other path...
> + cpu_nid = pxm_to_node(target->processor_pxm);
> + register_memory_node_under_compute_node(mem_nid, cpu_nid, 0);
> + return;
> + }
> +
So we can't get here.
> + if (list_empty(&localities))
> + return;
> +
> + /*
> + * We need the initiator list iteration sorted so we can use
> + * bitmap_clear for previously set initiators when we find a better
> + * memory accessor. We'll also use the sorting to prime the candidate
> + * nodes with known initiators.
> + */
> + bitmap_zero(p_nodes, MAX_NUMNODES);
> + list_sort(p_nodes, &initiators, initiator_cmp);
> + for (i = WRITE_LATENCY; i <= READ_BANDWIDTH; i++) {
> + loc = localities_types[i];
> + if (!loc)
> + continue;
> +
> + best = 0;
> + list_for_each_entry(initiator, &initiators, node) {
> + u32 value;
> +
> + if (!test_bit(initiator->processor_pxm, p_nodes))
> + continue;
> +
> + value = hmat_initiator_perf(target, initiator, loc->hmat_loc);
> + if (hmat_update_best(loc->hmat_loc->data_type, value, &best))
> + bitmap_clear(p_nodes, 0, initiator->processor_pxm);
> + if (value != best)
> + clear_bit(initiator->processor_pxm, p_nodes);
> + }
> + if (best)
> + hmat_update_target_access(target, loc->hmat_loc->data_type, best);
> + }
> +
> + for_each_set_bit(i, p_nodes, MAX_NUMNODES) {
> + cpu_nid = pxm_to_node(i);
> + register_memory_node_under_compute_node(mem_nid, cpu_nid, 0);
> + }
> +}
> +
> +static __init void hmat_register_targets(void)
> +{
> + struct memory_target *target;
> +
> + list_for_each_entry(target, &targets, node)
> + hmat_register_target_initiators(target);
> +}
> +
> +static __init void hmat_free_structures(void)
> +{
> + struct memory_target *target, *tnext;
> + struct memory_locality *loc, *lnext;
> + struct memory_initiator *intitator, *inext;
> +
> + list_for_each_entry_safe(target, tnext, &targets, node) {
> + list_del(&target->node);
> + kfree(target);
> + }
> +
> + list_for_each_entry_safe(intitator, inext, &initiators, node) {
> + list_del(&intitator->node);
> + kfree(intitator);
> + }
> +
> + list_for_each_entry_safe(loc, lnext, &localities, node) {
> + list_del(&loc->node);
> + kfree(loc);
> + }
> +}
> +
> static __init int hmat_init(void)
> {
> struct acpi_table_header *tbl;
> @@ -208,6 +588,17 @@ static __init int hmat_init(void)
> if (srat_disabled())
> return 0;
>
> + status = acpi_get_table(ACPI_SIG_SRAT, 0, &tbl);
> + if (ACPI_FAILURE(status))
> + return 0;
> +
> + if (acpi_table_parse_entries(ACPI_SIG_SRAT,
> + sizeof(struct acpi_table_srat),
> + ACPI_SRAT_TYPE_MEMORY_AFFINITY,
> + srat_parse_mem_affinity, 0) < 0)
> + goto out_put;
> + acpi_put_table(tbl);
> +
> status = acpi_get_table(ACPI_SIG_HMAT, 0, &tbl);
> if (ACPI_FAILURE(status))
> return 0;
> @@ -230,7 +621,9 @@ static __init int hmat_init(void)
> goto out_put;
> }
> }
> + hmat_register_targets();
> out_put:
> + hmat_free_structures();
> acpi_put_table(tbl);
> return 0;
> }
^ permalink raw reply
* Re: [PATCH] x86: Deprecate a.out support
From: Arnd Bergmann @ 2019-03-11 11:02 UTC (permalink / raw)
To: Linus Torvalds
Cc: Matt Turner, Borislav Petkov, Alan Cox, Matthew Wilcox, Jann Horn,
Al Viro, Thomas Gleixner, kernel list, linux-fsdevel,
the arch/x86 maintainers, Linux API, Andrew Morton,
Richard Weinberger, Anton Ivanov, linux-alpha, linux-m68k
In-Reply-To: <CAHk-=wgt7M6yA5BJCJo0nF22WgPJnN8CvViL9CAJmd+S+Civ6w@mail.gmail.com>
On Sun, Mar 10, 2019 at 11:46 PM Linus Torvalds
<torvalds@linux-foundation.org> wrote:
>
> On Sun, Mar 10, 2019 at 2:37 PM Matt Turner <mattst88@gmail.com> wrote:
> >
> > I'm not aware of a reason to keep a.out support on alpha.
>
> Hmm. I was looking at removing a.out support entirely, but it's
> actually fairly incestuous on alpha.
>
> For example, arch/alpha/boot/tools/objstrip.c very much has some a.out
> support in it. Maybe it can just be removed entirely.
>
> There's also an a.out.h include in arch/alpha/kernel/binfmt_loader.c.
>
> Finally, note that CONFIG_OSF4_COMPAT also no longer makes sense
> without a.out support.
>
> So this attached patch does not compile on alpha, but it's been many
> many years since I had an alpha to test with, so I'm stuck.
>
> Matt, can you fill in the details and complete this patch?
I wonder if we could remove the osf time32 compat code as well,
this was one of the areas that kept causing problems with the y2038
rework. (I think it's all good now, but it's never been tested as far as I
can tell).
For some syscalls (e.g. brk, mmap, getxuid, ...) we definitely need to
keep the osf1 version, since it is the only supported ABI.
I just looked up some really old source trees and found that glibc-2.1
was the first release to use 64-bit time_t the way we do it today,
as implemented in [1], so all Debian and SuSE releases for alpha
had it, but any ELF binaries built on Red Hat Linux 4.x and 5.x
(released 1996 through 1998) or earlier would use 32-bit time_t
osf1 syscalls. Red Hat 2.x and 3.x were a.out based on alpha.
Arnd
[1] https://repo.or.cz/glibc/history.git/commitdiff/64819b5c3a94e81e4
^ permalink raw reply
* Re: [PATCHv7 04/10] node: Link memory nodes to their compute nodes
From: Jonathan Cameron @ 2019-03-11 10:34 UTC (permalink / raw)
To: Keith Busch
Cc: linux-kernel, linux-acpi, linux-mm, linux-api, Greg Kroah-Hartman,
Rafael Wysocki, Dave Hansen, Dan Williams
In-Reply-To: <20190227225038.20438-5-keith.busch@intel.com>
On Wed, 27 Feb 2019 15:50:32 -0700
Keith Busch <keith.busch@intel.com> wrote:
> Systems may be constructed with various specialized nodes. Some nodes
> may provide memory, some provide compute devices that access and use
> that memory, and others may provide both. Nodes that provide memory are
> referred to as memory targets, and nodes that can initiate memory access
> are referred to as memory initiators.
>
> Memory targets will often have varying access characteristics from
> different initiators, and platforms may have ways to express those
> relationships. In preparation for these systems, provide interfaces for
> the kernel to export the memory relationship among different nodes memory
> targets and their initiators with symlinks to each other.
>
> If a system provides access locality for each initiator-target pair, nodes
> may be grouped into ranked access classes relative to other nodes. The
> new interface allows a subsystem to register relationships of varying
> classes if available and desired to be exported.
>
> A memory initiator may have multiple memory targets in the same access
> class. The target memory's initiators in a given class indicate the
> nodes access characteristics share the same performance relative to other
> linked initiator nodes. Each target within an initiator's access class,
> though, do not necessarily perform the same as each other.
>
> A memory target node may have multiple memory initiators. All linked
> initiators in a target's class have the same access characteristics to
> that target.
>
> The following example show the nodes' new sysfs hierarchy for a memory
> target node 'Y' with access class 0 from initiator node 'X':
>
> # symlinks -v /sys/devices/system/node/nodeX/access0/
> relative: /sys/devices/system/node/nodeX/access0/targets/nodeY -> ../../nodeY
>
> # symlinks -v /sys/devices/system/node/nodeY/access0/
> relative: /sys/devices/system/node/nodeY/access0/initiators/nodeX -> ../../nodeX
>
> The new attributes are added to the sysfs stable documentation.
>
> Signed-off-by: Keith Busch <keith.busch@intel.com>
A couple of minor bits inline. With those tidied up.
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Thanks,
> ---
> Documentation/ABI/stable/sysfs-devices-node | 25 ++++-
> drivers/base/node.c | 142 +++++++++++++++++++++++++++-
> include/linux/node.h | 7 +-
> 3 files changed, 171 insertions(+), 3 deletions(-)
>
> diff --git a/Documentation/ABI/stable/sysfs-devices-node b/Documentation/ABI/stable/sysfs-devices-node
> index 3e90e1f3bf0a..fb843222a281 100644
> --- a/Documentation/ABI/stable/sysfs-devices-node
> +++ b/Documentation/ABI/stable/sysfs-devices-node
> @@ -90,4 +90,27 @@ Date: December 2009
> Contact: Lee Schermerhorn <lee.schermerhorn@hp.com>
> Description:
> The node's huge page size control/query attributes.
> - See Documentation/admin-guide/mm/hugetlbpage.rst
> \ No newline at end of file
> + See Documentation/admin-guide/mm/hugetlbpage.rst
> +
> +What: /sys/devices/system/node/nodeX/accessY/
> +Date: December 2018
> +Contact: Keith Busch <keith.busch@intel.com>
> +Description:
> + The node's relationship to other nodes for access class "Y".
> +
> +What: /sys/devices/system/node/nodeX/accessY/initiators/
> +Date: December 2018
> +Contact: Keith Busch <keith.busch@intel.com>
> +Description:
> + The directory containing symlinks to memory initiator
> + nodes that have class "Y" access to this target node's
> + memory. CPUs and other memory initiators in nodes not in
> + the list accessing this node's memory may have different
> + performance.
> +
> +What: /sys/devices/system/node/nodeX/classY/targets/
accessY
> +Date: December 2018
> +Contact: Keith Busch <keith.busch@intel.com>
> +Description:
> + The directory containing symlinks to memory targets that
> + this initiator node has class "Y" access.
> diff --git a/drivers/base/node.c b/drivers/base/node.c
> index 86d6cd92ce3d..6f4097680580 100644
> --- a/drivers/base/node.c
> +++ b/drivers/base/node.c
> @@ -17,6 +17,7 @@
> #include <linux/nodemask.h>
> #include <linux/cpu.h>
> #include <linux/device.h>
> +#include <linux/pm_runtime.h>
> #include <linux/swap.h>
> #include <linux/slab.h>
>
> @@ -59,6 +60,94 @@ static inline ssize_t node_read_cpulist(struct device *dev,
> static DEVICE_ATTR(cpumap, S_IRUGO, node_read_cpumask, NULL);
> static DEVICE_ATTR(cpulist, S_IRUGO, node_read_cpulist, NULL);
>
> +/**
> + * struct node_access_nodes - Access class device to hold user visible
> + * relationships to other nodes.
> + * @dev: Device for this memory access class
> + * @list_node: List element in the node's access list
> + * @access: The access class rank
> + */
> +struct node_access_nodes {
> + struct device dev;
> + struct list_head list_node;
> + unsigned access;
> +};
> +#define to_access_nodes(dev) container_of(dev, struct node_access_nodes, dev)
> +
> +static struct attribute *node_init_access_node_attrs[] = {
> + NULL,
> +};
> +
> +static struct attribute *node_targ_access_node_attrs[] = {
> + NULL,
> +};
> +
> +static const struct attribute_group initiators = {
> + .name = "initiators",
> + .attrs = node_init_access_node_attrs,
> +};
> +
> +static const struct attribute_group targets = {
> + .name = "targets",
> + .attrs = node_targ_access_node_attrs,
> +};
> +
> +static const struct attribute_group *node_access_node_groups[] = {
> + &initiators,
> + &targets,
> + NULL,
> +};
> +
> +static void node_remove_accesses(struct node *node)
> +{
> + struct node_access_nodes *c, *cnext;
> +
> + list_for_each_entry_safe(c, cnext, &node->access_list, list_node) {
> + list_del(&c->list_node);
> + device_unregister(&c->dev);
> + }
> +}
> +
> +static void node_access_release(struct device *dev)
> +{
> + kfree(to_access_nodes(dev));
> +}
> +
> +static struct node_access_nodes *node_init_node_access(struct node *node,
> + unsigned access)
> +{
> + struct node_access_nodes *access_node;
> + struct device *dev;
> +
> + list_for_each_entry(access_node, &node->access_list, list_node)
> + if (access_node->access == access)
> + return access_node;
> +
> + access_node = kzalloc(sizeof(*access_node), GFP_KERNEL);
> + if (!access_node)
> + return NULL;
> +
> + access_node->access = access;
> + dev = &access_node->dev;
> + dev->parent = &node->dev;
> + dev->release = node_access_release;
> + dev->groups = node_access_node_groups;
> + if (dev_set_name(dev, "access%u", access))
> + goto free;
> +
> + if (device_register(dev))
> + goto free_name;
> +
> + pm_runtime_no_callbacks(dev);
> + list_add_tail(&access_node->list_node, &node->access_list);
> + return access_node;
> +free_name:
> + kfree_const(dev->kobj.name);
> +free:
> + kfree(access_node);
> + return NULL;
> +}
> +
> #define K(x) ((x) << (PAGE_SHIFT - 10))
> static ssize_t node_read_meminfo(struct device *dev,
> struct device_attribute *attr, char *buf)
> @@ -340,7 +429,7 @@ static int register_node(struct node *node, int num)
> void unregister_node(struct node *node)
> {
> hugetlb_unregister_node(node); /* no-op, if memoryless node */
> -
> + node_remove_accesses(node);
> device_unregister(&node->dev);
> }
>
> @@ -372,6 +461,56 @@ int register_cpu_under_node(unsigned int cpu, unsigned int nid)
> kobject_name(&node_devices[nid]->dev.kobj));
> }
>
> +/**
> + * register_memory_node_under_compute_node - link memory node to its compute
> + * node for a given access class.
> + * @mem_node: Memory node number
> + * @cpu_node: Cpu node number
> + * @access: Access class to register
> + *
> + * Description:
> + * For use with platforms that may have separate memory and compute nodes.
> + * This function will export node relationships linking which memory
> + * initiator nodes can access memory targets at a given ranked access
> + * class.
> + */
> +int register_memory_node_under_compute_node(unsigned int mem_nid,
> + unsigned int cpu_nid,
> + unsigned access)
> +{
> + struct node *init_node, *targ_node;
> + struct node_access_nodes *initiator, *target;
> + int ret;
> +
> + if (!node_online(cpu_nid) || !node_online(mem_nid))
> + return -ENODEV;
> +
> + init_node = node_devices[cpu_nid];
> + targ_node = node_devices[mem_nid];
> + initiator = node_init_node_access(init_node, access);
> + target = node_init_node_access(targ_node, access);
> + if (!initiator || !target)
> + return -ENOMEM;
> +
> + ret = sysfs_add_link_to_group(&initiator->dev.kobj, "targets",
> + &targ_node->dev.kobj,
> + dev_name(&targ_node->dev));
> + if (ret)
> + return ret;
> +
> + ret = sysfs_add_link_to_group(&target->dev.kobj, "initiators",
> + &init_node->dev.kobj,
> + dev_name(&init_node->dev));
> + if (ret)
> + goto err;
> +
> + return 0;
> + err:
> + sysfs_remove_link_from_group(&initiator->dev.kobj, "targets",
> + dev_name(&targ_node->dev));
> + return ret;
> +}
> +
> int unregister_cpu_under_node(unsigned int cpu, unsigned int nid)
> {
> struct device *obj;
> @@ -580,6 +719,7 @@ int __register_one_node(int nid)
> register_cpu_under_node(cpu, nid);
> }
>
> + INIT_LIST_HEAD(&node_devices[nid]->access_list);
> /* initialize work queue for memory hot plug */
> init_node_hugetlb_work(nid);
>
> diff --git a/include/linux/node.h b/include/linux/node.h
> index 257bb3d6d014..f34688a203c1 100644
> --- a/include/linux/node.h
> +++ b/include/linux/node.h
> @@ -17,11 +17,12 @@
>
> #include <linux/device.h>
> #include <linux/cpumask.h>
> +#include <linux/list.h>
> #include <linux/workqueue.h>
>
> struct node {
> struct device dev;
> -
> + struct list_head access_list;
Nitpick if you are rerolling for some reason. The separation before
the ifdef was nice from a readability point of view.
> #if defined(CONFIG_MEMORY_HOTPLUG_SPARSE) && defined(CONFIG_HUGETLBFS)
> struct work_struct node_work;
> #endif
> @@ -75,6 +76,10 @@ extern int register_mem_sect_under_node(struct memory_block *mem_blk,
> extern int unregister_mem_sect_under_nodes(struct memory_block *mem_blk,
> unsigned long phys_index);
>
> +extern int register_memory_node_under_compute_node(unsigned int mem_nid,
> + unsigned int cpu_nid,
> + unsigned access);
> +
> #ifdef CONFIG_HUGETLBFS
> extern void register_hugetlbfs_with_node(node_registration_func_t doregister,
> node_registration_func_t unregister);
^ permalink raw reply
* Re: [PATCHv7 03/10] acpi/hmat: Parse and report heterogeneous memory
From: Jonathan Cameron @ 2019-03-11 10:28 UTC (permalink / raw)
To: Keith Busch
Cc: linux-kernel, linux-acpi, linux-mm, linux-api, Greg Kroah-Hartman,
Rafael Wysocki, Dave Hansen, Dan Williams
In-Reply-To: <20190227225038.20438-4-keith.busch@intel.com>
On Wed, 27 Feb 2019 15:50:31 -0700
Keith Busch <keith.busch@intel.com> wrote:
> Systems may provide different memory types and export this information
> in the ACPI Heterogeneous Memory Attribute Table (HMAT). Parse these
> tables provided by the platform and report the memory access and caching
> attributes to the kernel messages.
>
> Reviewed-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> Signed-off-by: Keith Busch <keith.busch@intel.com>
Hi Keith
A few trivial comments in this one. All stuff we can fix if a firmware
runs into the limits of representation.
One other question that comes to mind is:
The move to picoseconds was perhaps optimistic on the part of the
ACPI spec, but do we want to go for future proofing and go with them?
Costs us a few more zeros in a sysfs file after all. Internal storage
could stay at nano seconds perhaps.
All small things though so either way...
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> ---
> drivers/acpi/Kconfig | 1 +
> drivers/acpi/Makefile | 1 +
> drivers/acpi/hmat/Kconfig | 7 ++
> drivers/acpi/hmat/Makefile | 1 +
> drivers/acpi/hmat/hmat.c | 237 +++++++++++++++++++++++++++++++++++++++++++++
> 5 files changed, 247 insertions(+)
> create mode 100644 drivers/acpi/hmat/Kconfig
> create mode 100644 drivers/acpi/hmat/Makefile
> create mode 100644 drivers/acpi/hmat/hmat.c
>
> diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
> index 4e015c77e48e..283ee94224c6 100644
> --- a/drivers/acpi/Kconfig
> +++ b/drivers/acpi/Kconfig
> @@ -475,6 +475,7 @@ config ACPI_REDUCED_HARDWARE_ONLY
> If you are unsure what to do, do not enable this option.
>
> source "drivers/acpi/nfit/Kconfig"
> +source "drivers/acpi/hmat/Kconfig"
>
> source "drivers/acpi/apei/Kconfig"
> source "drivers/acpi/dptf/Kconfig"
> diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
> index bb857421c2e8..5d361e4e3405 100644
> --- a/drivers/acpi/Makefile
> +++ b/drivers/acpi/Makefile
> @@ -80,6 +80,7 @@ obj-$(CONFIG_ACPI_PROCESSOR) += processor.o
> obj-$(CONFIG_ACPI) += container.o
> obj-$(CONFIG_ACPI_THERMAL) += thermal.o
> obj-$(CONFIG_ACPI_NFIT) += nfit/
> +obj-$(CONFIG_ACPI_HMAT) += hmat/
> obj-$(CONFIG_ACPI) += acpi_memhotplug.o
> obj-$(CONFIG_ACPI_HOTPLUG_IOAPIC) += ioapic.o
> obj-$(CONFIG_ACPI_BATTERY) += battery.o
> diff --git a/drivers/acpi/hmat/Kconfig b/drivers/acpi/hmat/Kconfig
> new file mode 100644
> index 000000000000..2f7111b7af62
> --- /dev/null
> +++ b/drivers/acpi/hmat/Kconfig
> @@ -0,0 +1,7 @@
> +# SPDX-License-Identifier: GPL-2.0
> +config ACPI_HMAT
> + bool "ACPI Heterogeneous Memory Attribute Table Support"
> + depends on ACPI_NUMA
> + help
> + If set, this option has the kernel parse and report the
> + platform's ACPI HMAT (Heterogeneous Memory Attributes Table).
> diff --git a/drivers/acpi/hmat/Makefile b/drivers/acpi/hmat/Makefile
> new file mode 100644
> index 000000000000..e909051d3d00
> --- /dev/null
> +++ b/drivers/acpi/hmat/Makefile
> @@ -0,0 +1 @@
> +obj-$(CONFIG_ACPI_HMAT) := hmat.o
> diff --git a/drivers/acpi/hmat/hmat.c b/drivers/acpi/hmat/hmat.c
> new file mode 100644
> index 000000000000..99f711420f6d
> --- /dev/null
> +++ b/drivers/acpi/hmat/hmat.c
> @@ -0,0 +1,237 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2019, Intel Corporation.
> + *
> + * Heterogeneous Memory Attributes Table (HMAT) representation
> + *
> + * This program parses and reports the platform's HMAT tables, and registers
> + * the applicable attributes with the node's interfaces.
> + */
> +
> +#include <linux/acpi.h>
> +#include <linux/bitops.h>
> +#include <linux/device.h>
> +#include <linux/init.h>
> +#include <linux/list.h>
> +#include <linux/node.h>
> +#include <linux/sysfs.h>
> +
> +static __initdata u8 hmat_revision;
> +
> +static __init const char *hmat_data_type(u8 type)
> +{
> + switch (type) {
> + case ACPI_HMAT_ACCESS_LATENCY:
> + return "Access Latency";
> + case ACPI_HMAT_READ_LATENCY:
> + return "Read Latency";
> + case ACPI_HMAT_WRITE_LATENCY:
> + return "Write Latency";
> + case ACPI_HMAT_ACCESS_BANDWIDTH:
> + return "Access Bandwidth";
> + case ACPI_HMAT_READ_BANDWIDTH:
> + return "Read Bandwidth";
> + case ACPI_HMAT_WRITE_BANDWIDTH:
> + return "Write Bandwidth";
> + default:
> + return "Reserved";
> + }
> +}
> +
> +static __init const char *hmat_data_type_suffix(u8 type)
> +{
> + switch (type) {
> + case ACPI_HMAT_ACCESS_LATENCY:
> + case ACPI_HMAT_READ_LATENCY:
> + case ACPI_HMAT_WRITE_LATENCY:
> + return " nsec";
> + case ACPI_HMAT_ACCESS_BANDWIDTH:
> + case ACPI_HMAT_READ_BANDWIDTH:
> + case ACPI_HMAT_WRITE_BANDWIDTH:
> + return " MB/s";
> + default:
> + return "";
> + }
> +}
> +
> +static __init u32 hmat_normalize(u16 entry, u64 base, u8 type)
> +{
> + u32 value;
> +
> + /*
> + * Check for invalid and overflow values
> + */
> + if (entry == 0xffff || !entry)
> + return 0;
> + else if (base > (UINT_MAX / (entry)))
In this particular case, the issue is not that the value provided is impossible
but rather that the kernel is currently using too small a type to hold it.
If I've understood that right, perhaps a warning here would make sense?
Also, for consistency, U32_MAX.
> + return 0;
> +
> + /*
> + * Divide by the base unit for version 1, convert latency from
> + * picosenonds to nanoseconds if revision 2.
> + */
> + value = entry * base;
> + if (hmat_revision == 1) {
> + if (value < 10)
> + return 0;
> + value = DIV_ROUND_UP(value, 10);
> + } else if (hmat_revision == 2) {
> + switch (type) {
> + case ACPI_HMAT_ACCESS_LATENCY:
> + case ACPI_HMAT_READ_LATENCY:
> + case ACPI_HMAT_WRITE_LATENCY:
> + value = DIV_ROUND_UP(value, 1000);
In this case our use of a u32 is resulting in a value that is clamped
way below the full u32 range. Perhaps locally do the computation at
higher precision then clamp down at the end?
> + break;
> + default:
> + break;
> + }
> + }
> + return value;
> +}
> +
> +static __init int hmat_parse_locality(union acpi_subtable_headers *header,
> + const unsigned long end)
> +{
> + struct acpi_hmat_locality *hmat_loc = (void *)header;
> + unsigned int init, targ, total_size, ipds, tpds;
> + u32 *inits, *targs, value;
> + u16 *entries;
> + u8 type;
> +
> + if (hmat_loc->header.length < sizeof(*hmat_loc)) {
> + pr_notice("HMAT: Unexpected locality header length: %d\n",
> + hmat_loc->header.length);
> + return -EINVAL;
> + }
> +
> + type = hmat_loc->data_type;
> + ipds = hmat_loc->number_of_initiator_Pds;
> + tpds = hmat_loc->number_of_target_Pds;
> + total_size = sizeof(*hmat_loc) + sizeof(*entries) * ipds * tpds +
> + sizeof(*inits) * ipds + sizeof(*targs) * tpds;
> + if (hmat_loc->header.length < total_size) {
Perhaps overly paranoid, but could we make that a != to catch potential
broken tables?
> + pr_notice("HMAT: Unexpected locality header length:%d, minimum required:%d\n",
> + hmat_loc->header.length, total_size);
> + return -EINVAL;
> + }
> +
> + pr_info("HMAT: Locality: Flags:%02x Type:%s Initiator Domains:%d Target Domains:%d Base:%lld\n",
> + hmat_loc->flags, hmat_data_type(type), ipds, tpds,
> + hmat_loc->entry_base_unit);
> +
> + inits = (u32 *)(hmat_loc + 1);
> + targs = inits + ipds;
> + entries = (u16 *)(targs + tpds);
> + for (init = 0; init < ipds; init++) {
> + for (targ = 0; targ < tpds; targ++) {
> + value = hmat_normalize(entries[init * tpds + targ],
> + hmat_loc->entry_base_unit,
> + type);
> + pr_info(" Initiator-Target[%d-%d]:%d%s\n",
> + inits[init], targs[targ], value,
> + hmat_data_type_suffix(type));
> + }
> + }
> +
> + return 0;
> +}
> +
> +static __init int hmat_parse_cache(union acpi_subtable_headers *header,
> + const unsigned long end)
> +{
> + struct acpi_hmat_cache *cache = (void *)header;
> + u32 attrs;
> +
> + if (cache->header.length < sizeof(*cache)) {
> + pr_notice("HMAT: Unexpected cache header length: %d\n",
> + cache->header.length);
> + return -EINVAL;
> + }
> +
> + attrs = cache->cache_attributes;
> + pr_info("HMAT: Cache: Domain:%d Size:%llu Attrs:%08x SMBIOS Handles:%d\n",
> + cache->memory_PD, cache->cache_size, attrs,
> + cache->number_of_SMBIOShandles);
> +
> + return 0;
> +}
> +
> +static int __init hmat_parse_address_range(union acpi_subtable_headers *header,
> + const unsigned long end)
> +{
> + struct acpi_hmat_proximity_domain *p = (void *)header;
> + struct memory_target *target = NULL;
> +
> + if (p->header.length != sizeof(*p)) {
> + pr_notice("HMAT: Unexpected address range header length: %d\n",
> + p->header.length);
> + return -EINVAL;
> + }
> +
> + if (hmat_revision == 1)
> + pr_info("HMAT: Memory (%#llx length %#llx) Flags:%04x Processor Domain:%d Memory Domain:%d\n",
> + p->reserved3, p->reserved4, p->flags, p->processor_PD,
> + p->memory_PD);
> + else
> + pr_info("HMAT: Memory Flags:%04x Processor Domain:%d Memory Domain:%d\n",
> + p->flags, p->processor_PD, p->memory_PD);
> +
> + return 0;
> +}
> +
> +static int __init hmat_parse_subtable(union acpi_subtable_headers *header,
> + const unsigned long end)
> +{
> + struct acpi_hmat_structure *hdr = (void *)header;
> +
> + if (!hdr)
> + return -EINVAL;
> +
> + switch (hdr->type) {
> + case ACPI_HMAT_TYPE_ADDRESS_RANGE:
> + return hmat_parse_address_range(header, end);
> + case ACPI_HMAT_TYPE_LOCALITY:
> + return hmat_parse_locality(header, end);
> + case ACPI_HMAT_TYPE_CACHE:
> + return hmat_parse_cache(header, end);
> + default:
> + return -EINVAL;
> + }
> +}
> +
> +static __init int hmat_init(void)
> +{
> + struct acpi_table_header *tbl;
> + enum acpi_hmat_type i;
> + acpi_status status;
> +
> + if (srat_disabled())
> + return 0;
> +
> + status = acpi_get_table(ACPI_SIG_HMAT, 0, &tbl);
> + if (ACPI_FAILURE(status))
> + return 0;
> +
> + hmat_revision = tbl->revision;
> + switch (hmat_revision) {
> + case 1:
> + case 2:
> + break;
> + default:
> + pr_notice("Ignoring HMAT: Unknown revision:%d\n", hmat_revision);
> + goto out_put;
> + }
> +
> + for (i = ACPI_HMAT_TYPE_ADDRESS_RANGE; i < ACPI_HMAT_TYPE_RESERVED; i++) {
> + if (acpi_table_parse_entries(ACPI_SIG_HMAT,
> + sizeof(struct acpi_table_hmat), i,
> + hmat_parse_subtable, 0) < 0) {
> + pr_notice("Ignoring HMAT: Invalid table");
> + goto out_put;
> + }
> + }
> +out_put:
> + acpi_put_table(tbl);
> + return 0;
> +}
> +subsys_initcall(hmat_init);
^ permalink raw reply
* Re: [PATCH] x86: Deprecate a.out support
From: John Paul Adrian Glaubitz @ 2019-03-11 7:20 UTC (permalink / raw)
To: Linus Torvalds, Matt Turner
Cc: Borislav Petkov, Alan Cox, Matthew Wilcox, Jann Horn, Al Viro,
Thomas Gleixner, kernel list, linux-fsdevel,
the arch/x86 maintainers, Linux API, Andrew Morton,
Richard Weinberger, Anton Ivanov, linux-alpha, linux-m68k,
Michael Cree
In-Reply-To: <CAHk-=wgt7M6yA5BJCJo0nF22WgPJnN8CvViL9CAJmd+S+Civ6w@mail.gmail.com>
Hi Linus!
On 3/11/19 7:40 AM, Linus Torvalds wrote:
> So this attached patch does not compile on alpha, but it's been many
> many years since I had an alpha to test with, so I'm stuck.
Michael Cree (CC'ed) has several Alpha servers running which are also used
for building Debian packages and testing kernels.
I also have four AlphaStations (233, 433au and XP-1000) on which I could
test any patch. But I'm currently in Japan until Friday next week, so
I don't have any means to access the machines.
Adrian
--
.''`. John Paul Adrian Glaubitz
: :' : Debian Developer - glaubitz@debian.org
`. `' Freie Universitaet Berlin - glaubitz@physik.fu-berlin.de
`- GPG: 62FF 8A75 84E0 2956 9546 0006 7426 3B37 F5B5 F913
^ permalink raw reply
* Re: [PATCH] x86: Deprecate a.out support
From: Al Viro @ 2019-03-10 23:19 UTC (permalink / raw)
To: Linus Torvalds
Cc: Matt Turner, Borislav Petkov, Alan Cox, Matthew Wilcox, Jann Horn,
Thomas Gleixner, kernel list, linux-fsdevel,
the arch/x86 maintainers, Linux API, Andrew Morton,
Richard Weinberger, Anton Ivanov, linux-alpha, linux-m68k
In-Reply-To: <CAHk-=wgt7M6yA5BJCJo0nF22WgPJnN8CvViL9CAJmd+S+Civ6w@mail.gmail.com>
On Sun, Mar 10, 2019 at 03:40:20PM -0700, Linus Torvalds wrote:
> SYSCALL_DEFINE3(osf_readv, unsigned long, fd,
> const struct iovec __user *, vector, unsigned long, count)
> {
> -#ifdef CONFIG_OSF4_COMPAT
> - if (unlikely(personality(current->personality) == PER_OSF4))
> - if (osf_fix_iov_len(vector, count))
> - return -EFAULT;
> -#endif
> -
> return sys_readv(fd, vector, count);
> }
>
> SYSCALL_DEFINE3(osf_writev, unsigned long, fd,
> const struct iovec __user *, vector, unsigned long, count)
> {
> -#ifdef CONFIG_OSF4_COMPAT
> - if (unlikely(personality(current->personality) == PER_OSF4))
> - if (osf_fix_iov_len(vector, count))
> - return -EFAULT;
> -#endif
> return sys_writev(fd, vector, count);
> }
Might as well kill those two off, while we are at it - just use sys_readv/sys_writev
in arch/alpha/kernel/syscalls/syscall.tbl and be done with that...
^ permalink raw reply
* Re: [PATCH] x86: Deprecate a.out support
From: Linus Torvalds @ 2019-03-10 22:40 UTC (permalink / raw)
To: Matt Turner
Cc: Borislav Petkov, Alan Cox, Matthew Wilcox, Jann Horn, Al Viro,
Thomas Gleixner, kernel list, linux-fsdevel,
the arch/x86 maintainers, Linux API, Andrew Morton,
Richard Weinberger, Anton Ivanov, linux-alpha, linux-m68k
In-Reply-To: <CAEdQ38G5M3vq9pGBV1iyEViO7JhFuXk5g+VCs-vUH+Z62kNqgQ@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 741 bytes --]
On Sun, Mar 10, 2019 at 2:37 PM Matt Turner <mattst88@gmail.com> wrote:
>
> I'm not aware of a reason to keep a.out support on alpha.
Hmm. I was looking at removing a.out support entirely, but it's
actually fairly incestuous on alpha.
For example, arch/alpha/boot/tools/objstrip.c very much has some a.out
support in it. Maybe it can just be removed entirely.
There's also an a.out.h include in arch/alpha/kernel/binfmt_loader.c.
Finally, note that CONFIG_OSF4_COMPAT also no longer makes sense
without a.out support.
So this attached patch does not compile on alpha, but it's been many
many years since I had an alpha to test with, so I'm stuck.
Matt, can you fill in the details and complete this patch?
Linus
[-- Attachment #2: patch.diff --]
[-- Type: text/x-patch, Size: 23855 bytes --]
arch/alpha/Kconfig | 1 -
arch/alpha/kernel/osf_sys.c | 30 ----
arch/m68k/Kconfig | 1 -
arch/x86/Kconfig | 7 -
arch/x86/ia32/Makefile | 2 -
arch/x86/ia32/ia32_aout.c | 330 ------------------------------------------
fs/Kconfig.binfmt | 33 -----
fs/Makefile | 1 -
fs/binfmt_aout.c | 343 --------------------------------------------
include/linux/a.out.h | 18 ---
10 files changed, 766 deletions(-)
diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig
index 584a6e114853..9b9770b45f36 100644
--- a/arch/alpha/Kconfig
+++ b/arch/alpha/Kconfig
@@ -10,7 +10,6 @@ config ALPHA
select FORCE_PCI if !ALPHA_JENSEN
select PCI_DOMAINS if PCI
select PCI_SYSCALL if PCI
- select HAVE_AOUT
select HAVE_IDE
select HAVE_OPROFILE
select HAVE_PCSPKR_PLATFORM
diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c
index bf497b8b0ec6..09a0746c9681 100644
--- a/arch/alpha/kernel/osf_sys.c
+++ b/arch/alpha/kernel/osf_sys.c
@@ -1342,45 +1342,15 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
return addr;
}
-#ifdef CONFIG_OSF4_COMPAT
-/* Clear top 32 bits of iov_len in the user's buffer for
- compatibility with old versions of OSF/1 where iov_len
- was defined as int. */
-static int
-osf_fix_iov_len(const struct iovec __user *iov, unsigned long count)
-{
- unsigned long i;
-
- for (i = 0 ; i < count ; i++) {
- int __user *iov_len_high = (int __user *)&iov[i].iov_len + 1;
-
- if (put_user(0, iov_len_high))
- return -EFAULT;
- }
- return 0;
-}
-#endif
-
SYSCALL_DEFINE3(osf_readv, unsigned long, fd,
const struct iovec __user *, vector, unsigned long, count)
{
-#ifdef CONFIG_OSF4_COMPAT
- if (unlikely(personality(current->personality) == PER_OSF4))
- if (osf_fix_iov_len(vector, count))
- return -EFAULT;
-#endif
-
return sys_readv(fd, vector, count);
}
SYSCALL_DEFINE3(osf_writev, unsigned long, fd,
const struct iovec __user *, vector, unsigned long, count)
{
-#ifdef CONFIG_OSF4_COMPAT
- if (unlikely(personality(current->personality) == PER_OSF4))
- if (osf_fix_iov_len(vector, count))
- return -EFAULT;
-#endif
return sys_writev(fd, vector, count);
}
diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig
index b54206408f91..65d263c60669 100644
--- a/arch/m68k/Kconfig
+++ b/arch/m68k/Kconfig
@@ -8,7 +8,6 @@ config M68K
select ARCH_NO_COHERENT_DMA_MMAP if !MMU
select ARCH_NO_PREEMPT if !COLDFIRE
select HAVE_IDE
- select HAVE_AOUT if MMU
select HAVE_DEBUG_BUGVERBOSE
select GENERIC_IRQ_SHOW
select GENERIC_ATOMIC64
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index c1f9b3cf437c..4a9438e4fba6 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -2836,13 +2836,6 @@ config IA32_EMULATION
64-bit kernel. You should likely turn this on, unless you're
100% sure that you don't have any 32-bit programs left.
-config IA32_AOUT
- tristate "IA32 a.out support"
- depends on IA32_EMULATION
- depends on BROKEN
- ---help---
- Support old a.out binaries in the 32bit emulation.
-
config X86_X32
bool "x32 ABI for 64-bit mode"
depends on X86_64
diff --git a/arch/x86/ia32/Makefile b/arch/x86/ia32/Makefile
index cd4339bae066..b98fedaa7642 100644
--- a/arch/x86/ia32/Makefile
+++ b/arch/x86/ia32/Makefile
@@ -4,7 +4,5 @@
obj-$(CONFIG_IA32_EMULATION) := sys_ia32.o ia32_signal.o
-obj-$(CONFIG_IA32_AOUT) += ia32_aout.o
-
audit-class-$(CONFIG_AUDIT) := audit.o
obj-$(CONFIG_IA32_EMULATION) += $(audit-class-y)
diff --git a/arch/x86/ia32/ia32_aout.c b/arch/x86/ia32/ia32_aout.c
deleted file mode 100644
index 3c135084e1eb..000000000000
--- a/arch/x86/ia32/ia32_aout.c
+++ /dev/null
@@ -1,330 +0,0 @@
-/*
- * a.out loader for x86-64
- *
- * Copyright (C) 1991, 1992, 1996 Linus Torvalds
- * Hacked together by Andi Kleen
- */
-
-#include <linux/module.h>
-
-#include <linux/time.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/mman.h>
-#include <linux/a.out.h>
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/string.h>
-#include <linux/fs.h>
-#include <linux/file.h>
-#include <linux/stat.h>
-#include <linux/fcntl.h>
-#include <linux/ptrace.h>
-#include <linux/user.h>
-#include <linux/binfmts.h>
-#include <linux/personality.h>
-#include <linux/init.h>
-#include <linux/jiffies.h>
-#include <linux/perf_event.h>
-#include <linux/sched/task_stack.h>
-
-#include <linux/uaccess.h>
-#include <asm/pgalloc.h>
-#include <asm/cacheflush.h>
-#include <asm/user32.h>
-#include <asm/ia32.h>
-
-#undef WARN_OLD
-
-static int load_aout_binary(struct linux_binprm *);
-static int load_aout_library(struct file *);
-
-static struct linux_binfmt aout_format = {
- .module = THIS_MODULE,
- .load_binary = load_aout_binary,
- .load_shlib = load_aout_library,
-};
-
-static int set_brk(unsigned long start, unsigned long end)
-{
- start = PAGE_ALIGN(start);
- end = PAGE_ALIGN(end);
- if (end <= start)
- return 0;
- return vm_brk(start, end - start);
-}
-
-
-/*
- * create_aout_tables() parses the env- and arg-strings in new user
- * memory and creates the pointer tables from them, and puts their
- * addresses on the "stack", returning the new stack pointer value.
- */
-static u32 __user *create_aout_tables(char __user *p, struct linux_binprm *bprm)
-{
- u32 __user *argv, *envp, *sp;
- int argc = bprm->argc, envc = bprm->envc;
-
- sp = (u32 __user *) ((-(unsigned long)sizeof(u32)) & (unsigned long) p);
- sp -= envc+1;
- envp = sp;
- sp -= argc+1;
- argv = sp;
- put_user((unsigned long) envp, --sp);
- put_user((unsigned long) argv, --sp);
- put_user(argc, --sp);
- current->mm->arg_start = (unsigned long) p;
- while (argc-- > 0) {
- char c;
-
- put_user((u32)(unsigned long)p, argv++);
- do {
- get_user(c, p++);
- } while (c);
- }
- put_user(0, argv);
- current->mm->arg_end = current->mm->env_start = (unsigned long) p;
- while (envc-- > 0) {
- char c;
-
- put_user((u32)(unsigned long)p, envp++);
- do {
- get_user(c, p++);
- } while (c);
- }
- put_user(0, envp);
- current->mm->env_end = (unsigned long) p;
- return sp;
-}
-
-/*
- * These are the functions used to load a.out style executables and shared
- * libraries. There is no binary dependent code anywhere else.
- */
-static int load_aout_binary(struct linux_binprm *bprm)
-{
- unsigned long error, fd_offset, rlim;
- struct pt_regs *regs = current_pt_regs();
- struct exec ex;
- int retval;
-
- ex = *((struct exec *) bprm->buf); /* exec-header */
- if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != OMAGIC &&
- N_MAGIC(ex) != QMAGIC && N_MAGIC(ex) != NMAGIC) ||
- N_TRSIZE(ex) || N_DRSIZE(ex) ||
- i_size_read(file_inode(bprm->file)) <
- ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {
- return -ENOEXEC;
- }
-
- fd_offset = N_TXTOFF(ex);
-
- /* Check initial limits. This avoids letting people circumvent
- * size limits imposed on them by creating programs with large
- * arrays in the data or bss.
- */
- rlim = rlimit(RLIMIT_DATA);
- if (rlim >= RLIM_INFINITY)
- rlim = ~0;
- if (ex.a_data + ex.a_bss > rlim)
- return -ENOMEM;
-
- /* Flush all traces of the currently running executable */
- retval = flush_old_exec(bprm);
- if (retval)
- return retval;
-
- /* OK, This is the point of no return */
- set_personality(PER_LINUX);
- set_personality_ia32(false);
-
- setup_new_exec(bprm);
-
- regs->cs = __USER32_CS;
- regs->r8 = regs->r9 = regs->r10 = regs->r11 = regs->r12 =
- regs->r13 = regs->r14 = regs->r15 = 0;
-
- current->mm->end_code = ex.a_text +
- (current->mm->start_code = N_TXTADDR(ex));
- current->mm->end_data = ex.a_data +
- (current->mm->start_data = N_DATADDR(ex));
- current->mm->brk = ex.a_bss +
- (current->mm->start_brk = N_BSSADDR(ex));
-
- retval = setup_arg_pages(bprm, IA32_STACK_TOP, EXSTACK_DEFAULT);
- if (retval < 0)
- return retval;
-
- install_exec_creds(bprm);
-
- if (N_MAGIC(ex) == OMAGIC) {
- unsigned long text_addr, map_size;
-
- text_addr = N_TXTADDR(ex);
- map_size = ex.a_text+ex.a_data;
-
- error = vm_brk(text_addr & PAGE_MASK, map_size);
-
- if (error)
- return error;
-
- error = read_code(bprm->file, text_addr, 32,
- ex.a_text + ex.a_data);
- if ((signed long)error < 0)
- return error;
- } else {
-#ifdef WARN_OLD
- static unsigned long error_time, error_time2;
- if ((ex.a_text & 0xfff || ex.a_data & 0xfff) &&
- (N_MAGIC(ex) != NMAGIC) &&
- time_after(jiffies, error_time2 + 5*HZ)) {
- printk(KERN_NOTICE "executable not page aligned\n");
- error_time2 = jiffies;
- }
-
- if ((fd_offset & ~PAGE_MASK) != 0 &&
- time_after(jiffies, error_time + 5*HZ)) {
- printk(KERN_WARNING
- "fd_offset is not page aligned. Please convert "
- "program: %pD\n",
- bprm->file);
- error_time = jiffies;
- }
-#endif
-
- if (!bprm->file->f_op->mmap || (fd_offset & ~PAGE_MASK) != 0) {
- error = vm_brk(N_TXTADDR(ex), ex.a_text+ex.a_data);
- if (error)
- return error;
-
- read_code(bprm->file, N_TXTADDR(ex), fd_offset,
- ex.a_text+ex.a_data);
- goto beyond_if;
- }
-
- 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,
- fd_offset);
-
- if (error != N_TXTADDR(ex))
- return error;
-
- 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,
- fd_offset + ex.a_text);
- if (error != N_DATADDR(ex))
- return error;
- }
-
-beyond_if:
- error = set_brk(current->mm->start_brk, current->mm->brk);
- if (error)
- return error;
-
- set_binfmt(&aout_format);
-
- current->mm->start_stack =
- (unsigned long)create_aout_tables((char __user *)bprm->p, bprm);
- /* start thread */
- loadsegment(fs, 0);
- loadsegment(ds, __USER32_DS);
- loadsegment(es, __USER32_DS);
- load_gs_index(0);
- (regs)->ip = ex.a_entry;
- (regs)->sp = current->mm->start_stack;
- (regs)->flags = 0x200;
- (regs)->cs = __USER32_CS;
- (regs)->ss = __USER32_DS;
- regs->r8 = regs->r9 = regs->r10 = regs->r11 =
- regs->r12 = regs->r13 = regs->r14 = regs->r15 = 0;
- set_fs(USER_DS);
- return 0;
-}
-
-static int load_aout_library(struct file *file)
-{
- unsigned long bss, start_addr, len, error;
- int retval;
- struct exec ex;
- loff_t pos = 0;
-
- retval = -ENOEXEC;
- error = kernel_read(file, &ex, sizeof(ex), &pos);
- if (error != sizeof(ex))
- goto out;
-
- /* We come in here for the regular a.out style of shared libraries */
- if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != QMAGIC) || N_TRSIZE(ex) ||
- N_DRSIZE(ex) || ((ex.a_entry & 0xfff) && N_MAGIC(ex) == ZMAGIC) ||
- i_size_read(file_inode(file)) <
- ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {
- goto out;
- }
-
- if (N_FLAGS(ex))
- goto out;
-
- /* For QMAGIC, the starting address is 0x20 into the page. We mask
- this off to get the starting address for the page */
-
- start_addr = ex.a_entry & 0xfffff000;
-
- if ((N_TXTOFF(ex) & ~PAGE_MASK) != 0) {
-#ifdef WARN_OLD
- static unsigned long error_time;
- if (time_after(jiffies, error_time + 5*HZ)) {
- printk(KERN_WARNING
- "N_TXTOFF is not page aligned. Please convert "
- "library: %pD\n",
- file);
- error_time = jiffies;
- }
-#endif
- retval = vm_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss);
- if (retval)
- goto out;
-
- read_code(file, start_addr, N_TXTOFF(ex),
- ex.a_text + ex.a_data);
- retval = 0;
- goto out;
- }
- /* Now use mmap to map the library into memory. */
- error = vm_mmap(file, start_addr, ex.a_text + ex.a_data,
- PROT_READ | PROT_WRITE | PROT_EXEC,
- MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_32BIT,
- N_TXTOFF(ex));
- retval = error;
- if (error != start_addr)
- goto out;
-
- len = PAGE_ALIGN(ex.a_text + ex.a_data);
- bss = ex.a_text + ex.a_data + ex.a_bss;
- if (bss > len) {
- retval = vm_brk(start_addr + len, bss - len);
- if (retval)
- goto out;
- }
- retval = 0;
-out:
- return retval;
-}
-
-static int __init init_aout_binfmt(void)
-{
- register_binfmt(&aout_format);
- return 0;
-}
-
-static void __exit exit_aout_binfmt(void)
-{
- unregister_binfmt(&aout_format);
-}
-
-module_init(init_aout_binfmt);
-module_exit(exit_aout_binfmt);
-MODULE_LICENSE("GPL");
diff --git a/fs/Kconfig.binfmt b/fs/Kconfig.binfmt
index b795f8da81f3..b4dfd2a92d95 100644
--- a/fs/Kconfig.binfmt
+++ b/fs/Kconfig.binfmt
@@ -109,39 +109,6 @@ config BINFMT_SHARED_FLAT
help
Support FLAT shared libraries
-config HAVE_AOUT
- def_bool n
-
-config BINFMT_AOUT
- tristate "Kernel support for a.out and ECOFF binaries"
- depends on HAVE_AOUT
- ---help---
- A.out (Assembler.OUTput) is a set of formats for libraries and
- executables used in the earliest versions of UNIX. Linux used
- the a.out formats QMAGIC and ZMAGIC until they were replaced
- with the ELF format.
-
- The conversion to ELF started in 1995. This option is primarily
- provided for historical interest and for the benefit of those
- who need to run binaries from that era.
-
- Most people should answer N here. If you think you may have
- occasional use for this format, enable module support above
- and answer M here to compile this support as a module called
- binfmt_aout.
-
- If any crucial components of your system (such as /sbin/init
- or /lib/ld.so) are still in a.out format, you will have to
- say Y here.
-
-config OSF4_COMPAT
- bool "OSF/1 v4 readv/writev compatibility"
- depends on ALPHA && BINFMT_AOUT
- help
- Say Y if you are using OSF/1 binaries (like Netscape and Acrobat)
- with v4 shared libraries freely available from Compaq. If you're
- going to use shared libraries from Tru64 version 5.0 or later, say N.
-
config BINFMT_EM86
tristate "Kernel support for Linux/Intel ELF binaries"
depends on ALPHA
diff --git a/fs/Makefile b/fs/Makefile
index 7bff9abecfa4..0105e3496259 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -36,7 +36,6 @@ obj-$(CONFIG_FS_DAX) += dax.o
obj-$(CONFIG_FS_ENCRYPTION) += crypto/
obj-$(CONFIG_FILE_LOCKING) += locks.o
obj-$(CONFIG_COMPAT) += compat.o compat_ioctl.o
-obj-$(CONFIG_BINFMT_AOUT) += binfmt_aout.o
obj-$(CONFIG_BINFMT_EM86) += binfmt_em86.o
obj-$(CONFIG_BINFMT_MISC) += binfmt_misc.o
obj-$(CONFIG_BINFMT_SCRIPT) += binfmt_script.o
diff --git a/fs/binfmt_aout.c b/fs/binfmt_aout.c
deleted file mode 100644
index 1fefd87eb4b4..000000000000
--- a/fs/binfmt_aout.c
+++ /dev/null
@@ -1,343 +0,0 @@
-/*
- * linux/fs/binfmt_aout.c
- *
- * Copyright (C) 1991, 1992, 1996 Linus Torvalds
- */
-
-#include <linux/module.h>
-
-#include <linux/time.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/mman.h>
-#include <linux/a.out.h>
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/string.h>
-#include <linux/fs.h>
-#include <linux/file.h>
-#include <linux/stat.h>
-#include <linux/fcntl.h>
-#include <linux/ptrace.h>
-#include <linux/user.h>
-#include <linux/binfmts.h>
-#include <linux/personality.h>
-#include <linux/init.h>
-#include <linux/coredump.h>
-#include <linux/slab.h>
-#include <linux/sched/task_stack.h>
-
-#include <linux/uaccess.h>
-#include <asm/cacheflush.h>
-
-static int load_aout_binary(struct linux_binprm *);
-static int load_aout_library(struct file*);
-
-static struct linux_binfmt aout_format = {
- .module = THIS_MODULE,
- .load_binary = load_aout_binary,
- .load_shlib = load_aout_library,
-};
-
-#define BAD_ADDR(x) ((unsigned long)(x) >= TASK_SIZE)
-
-static int set_brk(unsigned long start, unsigned long end)
-{
- start = PAGE_ALIGN(start);
- end = PAGE_ALIGN(end);
- if (end > start)
- return vm_brk(start, end - start);
- return 0;
-}
-
-/*
- * create_aout_tables() parses the env- and arg-strings in new user
- * memory and creates the pointer tables from them, and puts their
- * addresses on the "stack", returning the new stack pointer value.
- */
-static unsigned long __user *create_aout_tables(char __user *p, struct linux_binprm * bprm)
-{
- char __user * __user *argv;
- char __user * __user *envp;
- unsigned long __user *sp;
- int argc = bprm->argc;
- int envc = bprm->envc;
-
- sp = (void __user *)((-(unsigned long)sizeof(char *)) & (unsigned long) p);
-#ifdef __alpha__
-/* whee.. test-programs are so much fun. */
- put_user(0, --sp);
- put_user(0, --sp);
- if (bprm->loader) {
- put_user(0, --sp);
- put_user(1003, --sp);
- put_user(bprm->loader, --sp);
- put_user(1002, --sp);
- }
- put_user(bprm->exec, --sp);
- put_user(1001, --sp);
-#endif
- sp -= envc+1;
- envp = (char __user * __user *) sp;
- sp -= argc+1;
- argv = (char __user * __user *) sp;
-#ifndef __alpha__
- put_user((unsigned long) envp,--sp);
- put_user((unsigned long) argv,--sp);
-#endif
- put_user(argc,--sp);
- current->mm->arg_start = (unsigned long) p;
- while (argc-->0) {
- char c;
- put_user(p,argv++);
- do {
- get_user(c,p++);
- } while (c);
- }
- put_user(NULL,argv);
- current->mm->arg_end = current->mm->env_start = (unsigned long) p;
- while (envc-->0) {
- char c;
- put_user(p,envp++);
- do {
- get_user(c,p++);
- } while (c);
- }
- put_user(NULL,envp);
- current->mm->env_end = (unsigned long) p;
- return sp;
-}
-
-/*
- * These are the functions used to load a.out style executables and shared
- * libraries. There is no binary dependent code anywhere else.
- */
-
-static int load_aout_binary(struct linux_binprm * bprm)
-{
- struct pt_regs *regs = current_pt_regs();
- struct exec ex;
- unsigned long error;
- unsigned long fd_offset;
- unsigned long rlim;
- int retval;
-
- ex = *((struct exec *) bprm->buf); /* exec-header */
- if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != OMAGIC &&
- N_MAGIC(ex) != QMAGIC && N_MAGIC(ex) != NMAGIC) ||
- N_TRSIZE(ex) || N_DRSIZE(ex) ||
- i_size_read(file_inode(bprm->file)) < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {
- return -ENOEXEC;
- }
-
- /*
- * Requires a mmap handler. This prevents people from using a.out
- * as part of an exploit attack against /proc-related vulnerabilities.
- */
- if (!bprm->file->f_op->mmap)
- return -ENOEXEC;
-
- fd_offset = N_TXTOFF(ex);
-
- /* Check initial limits. This avoids letting people circumvent
- * size limits imposed on them by creating programs with large
- * arrays in the data or bss.
- */
- rlim = rlimit(RLIMIT_DATA);
- if (rlim >= RLIM_INFINITY)
- rlim = ~0;
- if (ex.a_data + ex.a_bss > rlim)
- return -ENOMEM;
-
- /* Flush all traces of the currently running executable */
- retval = flush_old_exec(bprm);
- if (retval)
- return retval;
-
- /* OK, This is the point of no return */
-#ifdef __alpha__
- SET_AOUT_PERSONALITY(bprm, ex);
-#else
- set_personality(PER_LINUX);
-#endif
- setup_new_exec(bprm);
-
- current->mm->end_code = ex.a_text +
- (current->mm->start_code = N_TXTADDR(ex));
- current->mm->end_data = ex.a_data +
- (current->mm->start_data = N_DATADDR(ex));
- current->mm->brk = ex.a_bss +
- (current->mm->start_brk = N_BSSADDR(ex));
-
- retval = setup_arg_pages(bprm, STACK_TOP, EXSTACK_DEFAULT);
- if (retval < 0)
- return retval;
-
- install_exec_creds(bprm);
-
- if (N_MAGIC(ex) == OMAGIC) {
- unsigned long text_addr, map_size;
- loff_t pos;
-
- text_addr = N_TXTADDR(ex);
-
-#ifdef __alpha__
- pos = fd_offset;
- map_size = ex.a_text+ex.a_data + PAGE_SIZE - 1;
-#else
- pos = 32;
- map_size = ex.a_text+ex.a_data;
-#endif
- error = vm_brk(text_addr & PAGE_MASK, map_size);
- if (error)
- return error;
-
- error = read_code(bprm->file, text_addr, pos,
- ex.a_text+ex.a_data);
- if ((signed long)error < 0)
- return error;
- } else {
- if ((ex.a_text & 0xfff || ex.a_data & 0xfff) &&
- (N_MAGIC(ex) != NMAGIC) && printk_ratelimit())
- {
- printk(KERN_NOTICE "executable not page aligned\n");
- }
-
- if ((fd_offset & ~PAGE_MASK) != 0 && printk_ratelimit())
- {
- printk(KERN_WARNING
- "fd_offset is not page aligned. Please convert program: %pD\n",
- bprm->file);
- }
-
- if (!bprm->file->f_op->mmap||((fd_offset & ~PAGE_MASK) != 0)) {
- error = vm_brk(N_TXTADDR(ex), ex.a_text+ex.a_data);
- if (error)
- return error;
-
- read_code(bprm->file, N_TXTADDR(ex), fd_offset,
- ex.a_text + ex.a_data);
- goto beyond_if;
- }
-
- error = vm_mmap(bprm->file, N_TXTADDR(ex), ex.a_text,
- PROT_READ | PROT_EXEC,
- MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
- fd_offset);
-
- if (error != N_TXTADDR(ex))
- return error;
-
- 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,
- fd_offset + ex.a_text);
- if (error != N_DATADDR(ex))
- return error;
- }
-beyond_if:
- set_binfmt(&aout_format);
-
- retval = set_brk(current->mm->start_brk, current->mm->brk);
- if (retval < 0)
- return retval;
-
- current->mm->start_stack =
- (unsigned long) create_aout_tables((char __user *) bprm->p, bprm);
-#ifdef __alpha__
- regs->gp = ex.a_gpvalue;
-#endif
- finalize_exec(bprm);
- start_thread(regs, ex.a_entry, current->mm->start_stack);
- return 0;
-}
-
-static int load_aout_library(struct file *file)
-{
- struct inode * inode;
- unsigned long bss, start_addr, len;
- unsigned long error;
- int retval;
- struct exec ex;
- loff_t pos = 0;
-
- inode = file_inode(file);
-
- retval = -ENOEXEC;
- error = kernel_read(file, &ex, sizeof(ex), &pos);
- if (error != sizeof(ex))
- goto out;
-
- /* We come in here for the regular a.out style of shared libraries */
- if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != QMAGIC) || N_TRSIZE(ex) ||
- N_DRSIZE(ex) || ((ex.a_entry & 0xfff) && N_MAGIC(ex) == ZMAGIC) ||
- i_size_read(inode) < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {
- goto out;
- }
-
- /*
- * Requires a mmap handler. This prevents people from using a.out
- * as part of an exploit attack against /proc-related vulnerabilities.
- */
- if (!file->f_op->mmap)
- goto out;
-
- if (N_FLAGS(ex))
- goto out;
-
- /* For QMAGIC, the starting address is 0x20 into the page. We mask
- this off to get the starting address for the page */
-
- start_addr = ex.a_entry & 0xfffff000;
-
- if ((N_TXTOFF(ex) & ~PAGE_MASK) != 0) {
- if (printk_ratelimit())
- {
- printk(KERN_WARNING
- "N_TXTOFF is not page aligned. Please convert library: %pD\n",
- file);
- }
- retval = vm_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss);
- if (retval)
- goto out;
-
- read_code(file, start_addr, N_TXTOFF(ex),
- ex.a_text + ex.a_data);
- retval = 0;
- goto out;
- }
- /* Now use mmap to map the library into memory. */
- error = vm_mmap(file, start_addr, ex.a_text + ex.a_data,
- PROT_READ | PROT_WRITE | PROT_EXEC,
- MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,
- N_TXTOFF(ex));
- retval = error;
- if (error != start_addr)
- goto out;
-
- len = PAGE_ALIGN(ex.a_text + ex.a_data);
- bss = ex.a_text + ex.a_data + ex.a_bss;
- if (bss > len) {
- retval = vm_brk(start_addr + len, bss - len);
- if (retval)
- goto out;
- }
- retval = 0;
-out:
- return retval;
-}
-
-static int __init init_aout_binfmt(void)
-{
- register_binfmt(&aout_format);
- return 0;
-}
-
-static void __exit exit_aout_binfmt(void)
-{
- unregister_binfmt(&aout_format);
-}
-
-core_initcall(init_aout_binfmt);
-module_exit(exit_aout_binfmt);
-MODULE_LICENSE("GPL");
diff --git a/include/linux/a.out.h b/include/linux/a.out.h
deleted file mode 100644
index 600cf45645c6..000000000000
--- a/include/linux/a.out.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef __A_OUT_GNU_H__
-#define __A_OUT_GNU_H__
-
-#include <uapi/linux/a.out.h>
-
-#ifndef __ASSEMBLY__
-#ifdef linux
-#include <asm/page.h>
-#if defined(__i386__) || defined(__mc68000__)
-#else
-#ifndef SEGMENT_SIZE
-#define SEGMENT_SIZE PAGE_SIZE
-#endif
-#endif
-#endif
-#endif /*__ASSEMBLY__ */
-#endif /* __A_OUT_GNU_H__ */
^ permalink raw reply related
* Re: [PATCH] x86: Deprecate a.out support
From: Matt Turner @ 2019-03-10 21:37 UTC (permalink / raw)
To: Borislav Petkov
Cc: Linus Torvalds, Alan Cox, Matthew Wilcox, Jann Horn, Al Viro,
Thomas Gleixner, kernel list, linux-fsdevel,
the arch/x86 maintainers, Linux API, Andrew Morton,
Richard Weinberger, Anton Ivanov, linux-alpha, linux-m68k
In-Reply-To: <20190305181808.GH8256@zn.tnic>
On Tue, Mar 5, 2019 at 11:04 AM Borislav Petkov <bp@alien8.de> wrote:
>
> On Tue, Mar 05, 2019 at 07:11:38PM +0100, Borislav Petkov wrote:
> > I guess you could Cc arch maintainers with the a.out-core.h removal
> > patch to see if anyone screams.
>
> And they're like two for which we need confirmation:
>
> $ git ls-files | grep a.out-core.h
> arch/alpha/include/asm/a.out-core.h
> arch/m68k/include/asm/a.out-core.h
> arch/um/include/asm/a.out-core.h
> arch/x86/include/asm/a.out-core.h
>
> um and x86 are clear.
>
> Adding alpha and m68k MLs to Cc.
I'm not aware of a reason to keep a.out support on alpha.
^ permalink raw reply
* Re: [PATCH RESEND v5 2/5] namei: O_BENEATH-style path resolution flags
From: Aleksa Sarai @ 2019-03-10 12:12 UTC (permalink / raw)
To: Linus Torvalds
Cc: Christian Brauner, Al Viro, Jeff Layton, J. Bruce Fields,
Arnd Bergmann, David Howells, Eric Biederman, Kees Cook,
David Drysdale, Andy Lutomirski, Andrew Morton,
Alexei Starovoitov, Jann Horn, Chanho Min, Oleg Nesterov,
Aleksa Sarai, containers, linux-fsdevel, Linux API,
Linux List Kernel Mailing
In-Reply-To: <CAHk-=whMuk-b6rzhbF2=vVNOuEZk8-opRJ1fD07a9ztQ+V97Aw@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 1103 bytes --]
On 2019-03-09, Linus Torvalds <torvalds@linux-foundation.org> wrote:
> On Sat, Mar 9, 2019 at 9:26 AM Christian Brauner <christian@brauner.io> wrote:
> > Aside from that I want to point out that it is non-trivial to do this in
> > user space.
>
> Oh, absolutely agreed. It's easy to do it in the kernel, and doing it
> anywhere else ends up having horrible races that the kernel has to
> deal with and has long solved anyway.
We've seen in the past few years, there are also plenty of CVEs from the
container runtime side of things which show that some of these races are
also exploitable. Even with some of the most convoluted O_PATH "fd
re-opening" trickery, it's incredibly difficult to both scope symlinks
inside a container and safely detect cases where you've been tricked by
a malicious actor.
> I've only seen this (2/5) patch, so I won't comment on the other ones,
> but this still makes sense to me.
I'll make sure to add you to the series Cc if/when there's a v6.
--
Aleksa Sarai
Senior Software Engineer (Containers)
SUSE Linux GmbH
<https://www.cyphar.com/>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply
* Re: [PATCH RESEND v5 2/5] namei: O_BENEATH-style path resolution flags
From: Linus Torvalds @ 2019-03-09 18:08 UTC (permalink / raw)
To: Christian Brauner
Cc: Aleksa Sarai, Al Viro, Jeff Layton, J. Bruce Fields,
Arnd Bergmann, David Howells, Eric Biederman, Kees Cook,
David Drysdale, Andy Lutomirski, Andrew Morton,
Alexei Starovoitov, Jann Horn, Chanho Min, Oleg Nesterov,
Aleksa Sarai, containers, linux-fsdevel, Linux API,
Linux List Kernel Mailing
In-Reply-To: <20190309172631.ygfdhrn4rcwkgfmk@brauner.io>
On Sat, Mar 9, 2019 at 9:26 AM Christian Brauner <christian@brauner.io> wrote:
>
> Aside from that I want to point out that it is non-trivial to do this in
> user space.
Oh, absolutely agreed. It's easy to do it in the kernel, and doing it
anywhere else ends up having horrible races that the kernel has to
deal with and has long solved anyway.
I've only seen this (2/5) patch, so I won't comment on the other ones,
but this still makes sense to me.
Al, comments?
Linus
^ permalink raw reply
* Re: [PATCH RESEND v5 2/5] namei: O_BENEATH-style path resolution flags
From: Christian Brauner @ 2019-03-09 17:26 UTC (permalink / raw)
To: Linus Torvalds
Cc: Aleksa Sarai, Al Viro, Jeff Layton, J. Bruce Fields,
Arnd Bergmann, David Howells, Eric Biederman, Kees Cook,
David Drysdale, Andy Lutomirski, Andrew Morton,
Alexei Starovoitov, Jann Horn, Chanho Min, Oleg Nesterov,
Aleksa Sarai, containers, linux-fsdevel, Linux API,
Linux List Kernel Mailing
In-Reply-To: <CAHk-=wgGKWRTgSYKkgMEf1QOg0PZSpmBha+2LCHCBOar0e8cug@mail.gmail.com>
On Sat, Mar 09, 2019 at 09:00:58AM -0800, Linus Torvalds wrote:
> On Wed, Mar 6, 2019 at 11:14 AM Aleksa Sarai <cyphar@cyphar.com> wrote:
> >
> > This is a refresh of Al's AT_NO_JUMPS patchset[1] (which was a variation
> > on David Drysdale's O_BENEATH patchset[2], which in turn was based on
> > the Capsicum project[3]). Input from Linus and Andy in the AT_NO_JUMPS
> > thread[4] determined most of the API changes made in this refresh.
>
> So I still think this is likely a good idea... BUT.
>
> The absolutely huge BUT here is "are user space people actually
> interested in using it, or do they already have other solutions to
> this anyway?"
>
> The intent is obviously to make it easy and cheap to to the simple
> pathname lookup in a controlled manner, and then let user space fall
> back to "let's check things much more carefully" for paths that look
> iffy.
>
> But maybe the people who care already have their own solutions, and/or
> need something more anyway (ie samba looking up all names in user
> space first _anyway_ due to ICASE issues or whatever)?
>
> So this is easy and straightforward to do in the kernel, and it
> _feels_ like something that can be useful, and I'm not all that
> concerned about the maintenance overhead either because of the trivial
> semantics.
>
> But I'd still like to actually have some user space person say "yeah,
> we'd actually use this" since quite often non-portable solutions don't
So if I may put my user space hat on. I maintain a container runtime LXC
and Aleksa maintains runC another container runtime. We both have
(horrible) code in our respective projects that tries to ensure that a
given path doesn't escape a given dirfd. Symlink resolution, and then
using crazy things such as mounting through /proc/<pid>/fd/<nr> etc. pp.
It works and we have been living with this state for a long time. But we
would both definitely use this feature. We've been discussing this and
had this on our wishlist for quite a long time and it would be good to
have this patchset.
Aside from that I want to point out that it is non-trivial to do this in
user space. The original code for restricted path resolution in our
codebase was done and is maintained by people like Serge and myself who
are involved in kernel development and it honestly required some pretty
intricate knowledge. I think having this feature work out of the box in
the kernel is a great win for quite a lot projects. Definitely for LXC
and runC.
Christian
^ permalink raw reply
* Re: [PATCH RESEND v5 2/5] namei: O_BENEATH-style path resolution flags
From: Linus Torvalds @ 2019-03-09 17:00 UTC (permalink / raw)
To: Aleksa Sarai
Cc: Al Viro, Jeff Layton, J. Bruce Fields, Arnd Bergmann,
David Howells, Eric Biederman, Christian Brauner, Kees Cook,
David Drysdale, Andy Lutomirski, Andrew Morton,
Alexei Starovoitov, Jann Horn, Chanho Min, Oleg Nesterov,
Aleksa Sarai, containers, linux-fsdevel, Linux API,
Linux List Kernel Mailing
In-Reply-To: <20190306191244.8691-3-cyphar@cyphar.com>
On Wed, Mar 6, 2019 at 11:14 AM Aleksa Sarai <cyphar@cyphar.com> wrote:
>
> This is a refresh of Al's AT_NO_JUMPS patchset[1] (which was a variation
> on David Drysdale's O_BENEATH patchset[2], which in turn was based on
> the Capsicum project[3]). Input from Linus and Andy in the AT_NO_JUMPS
> thread[4] determined most of the API changes made in this refresh.
So I still think this is likely a good idea... BUT.
The absolutely huge BUT here is "are user space people actually
interested in using it, or do they already have other solutions to
this anyway?"
The intent is obviously to make it easy and cheap to to the simple
pathname lookup in a controlled manner, and then let user space fall
back to "let's check things much more carefully" for paths that look
iffy.
But maybe the people who care already have their own solutions, and/or
need something more anyway (ie samba looking up all names in user
space first _anyway_ due to ICASE issues or whatever)?
So this is easy and straightforward to do in the kernel, and it
_feels_ like something that can be useful, and I'm not all that
concerned about the maintenance overhead either because of the trivial
semantics.
But I'd still like to actually have some user space person say "yeah,
we'd actually use this" since quite often non-portable solutions don't
really end up being used simply because it's not worth the maintenance
headache in user space..
Linus
^ permalink raw reply
* Re: [PATCH 0/3] mincore() and IOCB_NOWAIT adjustments
From: Linus Torvalds @ 2019-03-09 16:53 UTC (permalink / raw)
To: Andrew Morton
Cc: Dominique Martinet, Jiri Kosina, Vlastimil Babka,
Linux List Kernel Mailing, Linux-MM, Linux API, Peter Zijlstra,
Greg KH, Jann Horn, Andy Lutomirski, Cyril Hrubis, Daniel Gruss,
Dave Chinner, Kevin Easton, Kirill A. Shutemov, Matthew Wilcox,
Tejun Heo
In-Reply-To: <20190306153819.3510a19ffe510b674a7890ce@linux-foundation.org>
On Wed, Mar 6, 2019 at 3:38 PM Andrew Morton <akpm@linux-foundation.org> wrote:
>
> Linus, do you have thoughts on
> http://lkml.kernel.org/r/20190130124420.1834-4-vbabka@suse.cz ?
I think that's fine, and probably the right thing to do, but I also
suspect that nobody actually cares ;(
Linus
^ permalink raw reply
* Re: [PATCH v6] pidns: introduce syscall translate_pid
From: Nagarathnam Muthusamy @ 2019-03-08 18:55 UTC (permalink / raw)
To: Konstantin Khlebnikov, linux-api, linux-kernel, Jann Horn,
Serge Hallyn, Prakash Sangappa, Oleg Nesterov, Eric W. Biederman,
Andrew Morton, Andy Lutomirski, Michael Kerrisk (man-pages),
Dhaval Giani
In-Reply-To: <20181109034919.GA21681@altlinux.org>
On 11/8/18 7:49 PM, Dmitry V. Levin wrote:
> Hi,
>
> On Mon, Jul 16, 2018 at 10:57:48AM -0700, Nagarathnam Muthusamy wrote:
>> On 06/01/2018 12:18 PM, Konstantin Khlebnikov wrote:
>>> Each process have different pids, one for each pid namespace it belongs.
>>> When interaction happens within single pid-ns translation isn't required.
>>> More complicated scenarios needs special handling.
>>>
>>> For example:
>>> - reading pid-files or logs written inside container with pid namespace
>>> - writing logs with internal pids outside container for pushing them into
>>> - attaching with ptrace to tasks from different pid namespace
>>>
>>> Generally speaking, any cross pid-ns API with pids needs translation.
>>>
>>> Currently there are several interfaces that could be used here:
>>>
>>> Pid namespaces are identified by device and inode of /proc/[pid]/ns/pid.
>>>
>>> Pids for nested pid namespaces are shown in file /proc/[pid]/status.
>>> In some cases pid translation could be easily done using this information.
>>> Backward translation requires scanning all tasks and becomes really
>>> complicated for deeper namespace nesting.
>>>
>>> Unix socket automatically translates pid attached to SCM_CREDENTIALS.
>>> This requires CAP_SYS_ADMIN for sending arbitrary pids and entering
>>> into pid namespace, this expose process and could be insecure.
>>>
>>> This patch adds new syscall for converting pids between pid namespaces:
>>>
>>> pid_t translate_pid(pid_t pid, int source, int target);
>>>
>>> Pid-namespaces are referred file descriptors opened to proc files
>>> /proc/[pid]/ns/pid or /proc/[pid]/ns/pid_for_children.
>>> Negative argument points to current pid namespace.
>>>
>>> Syscall returns pid in target pid-ns or zero if task have no pid there.
>>>
>>> Error codes:
>>> EBADF - file descriptor is closed
>>> EINVAL - file descriptor isn't pid namespace
>>> ESRCH - task not found in @source namespace
>>>
>>> Translation could breach pid-ns isolation and return pids from outer pid
>>> namespaces iff process already has file descriptor for these namespaces.
>>>
>>> Examples:
>>> translate_pid(pid, ns, -1) - get pid in our pid namespace
>>> translate_pid(pid, -1, ns) - get pid in other pid namespace
>>> translate_pid(1, ns, -1) - get pid of init task for namespace
>>> translate_pid(pid, -1, ns) > 0 - is pid is reachable from ns?
>>> translate_pid(1, ns1, ns2) > 0 - is ns1 inside ns2?
>>> translate_pid(1, ns1, ns2) == 0 - is ns1 outside ns2?
>>> translate_pid(1, ns1, ns2) == 1 - is ns1 equal ns2?
>>>
>>> Signed-off-by: Konstantin Khlebnikov <khlebnikov@yandex-team.ru>
>>> Reanimated-by: Nagarathnam Muthusamy <nagarathnam.muthusamy@oracle.com>
>>>
>>> ---
>>>
>>> v1: https://lkml.org/lkml/2015/9/15/411
>>> v2: https://lkml.org/lkml/2015/9/24/278
>>> * use namespace-fd as second/third argument
>>> * add -pid for getting parent pid
>>> * move code into kernel/sys.c next to getppid
>>> * drop ifdef CONFIG_PID_NS
>>> * add generic syscall
>>> v3: https://lkml.org/lkml/2015/9/28/3
>>> * use proc_ns_fdget()
>>> * update description
>>> * rebase to next-20150925
>>> * fix conflict with mlock2
>>> v4: https://lkml.org/lkml/2017/10/13/177
>>> * rename from getvpid() into translate_pid()
>>> * remove syscall if CONFIG_PID_NS=n
>>> * drop -pid for parent task
>>> * drop fget-fdget optimizations
>>> * add helper get_pid_ns_by_fd()
>>> * wire only into x86
>>> v5: https://lkml.org/lkml/2018/4/4/677
>>> * rewrite commit message
>>> * resolve pidns by task pid or by pidns fd
>>> * add arguments source_type and target_type
>>> v6:
>>> * revert back minimized v4 design
>>> * rebase to next-20180601
>>> * fix COND_SYSCALL stub
>>> * use next syscall number, old used for io_pgetevents
>>>
>>> --- sample tool ---
>>>
>>> #define _GNU_SOURCE
>>> #include <sys/syscall.h>
>>> #include <sys/types.h>
>>> #include <fcntl.h>
>>> #include <unistd.h>
>>> #include <stdlib.h>
>>> #include <stdio.h>
>>> #include <err.h>
>>>
>>> #ifndef SYS_translate_pid
>>> #ifdef __x86_64__
>>> #define SYS_translate_pid 334
>>> #elif defined __i386__
>>> #define SYS_translate_pid 386
>>> #endif
>>> #endif
>>>
>>> pid_t translate_pid(pid_t pid, int source, int target) {
>>> return syscall(SYS_translate_pid, pid, source, target);
>>> }
>>>
>>> int main(int argc, char **argv) {
>>> int pid, source, target;
>>> char buf[64];
>>>
>>> if (argc != 4)
>>> errx(1, "usage: %s <pid> <source> <target>", argv[0]);
>>>
>>> pid = atoi(argv[1]);
>>> source = atoi(argv[2]);
>>> target = atoi(argv[3]);
>>>
>>> if (source > 0) {
>>> snprintf(buf, sizeof(buf), "/proc/%d/ns/pid", source);
>>> source = open(buf, O_RDONLY);
>>> if (source < 0)
>>> err(2, "open source %s", buf);
>>> }
>>>
>>> if (target > 0) {
>>> snprintf(buf, sizeof(buf), "/proc/%d/ns/pid", target);
>>> target = open(buf, O_RDONLY);
>>> if (target < 0)
>>> err(2, "open target %s", buf);
>>> }
>>>
>>> pid = translate_pid(pid, source, target);
>>> if (pid < 0)
>>> err(2, "translate_pid");
>>>
>>> printf("%d\n", pid);
>>> return 0;
>>> }
>>>
>>> ---
>>> ---
>>> arch/x86/entry/syscalls/syscall_32.tbl | 1
>>> arch/x86/entry/syscalls/syscall_64.tbl | 1
>>> include/linux/syscalls.h | 1
>>> kernel/pid_namespace.c | 66 ++++++++++++++++++++++++++++++++
>>> kernel/sys_ni.c | 3 +
>>> 5 files changed, 72 insertions(+)
>>>
>>> diff --git a/arch/x86/entry/syscalls/syscall_32.tbl b/arch/x86/entry/syscalls/syscall_32.tbl
>>> index 14a2f996e543..e70685750d43 100644
>>> --- a/arch/x86/entry/syscalls/syscall_32.tbl
>>> +++ b/arch/x86/entry/syscalls/syscall_32.tbl
>>> @@ -397,3 +397,4 @@
>>> 383 i386 statx sys_statx __ia32_sys_statx
>>> 384 i386 arch_prctl sys_arch_prctl __ia32_compat_sys_arch_prctl
>>> 385 i386 io_pgetevents sys_io_pgetevents __ia32_compat_sys_io_pgetevents
>>> +386 i386 translate_pid sys_translate_pid __ia32_sys_translate_pid
>>> diff --git a/arch/x86/entry/syscalls/syscall_64.tbl b/arch/x86/entry/syscalls/syscall_64.tbl
>>> index cd36232ab62f..ebfd89055424 100644
>>> --- a/arch/x86/entry/syscalls/syscall_64.tbl
>>> +++ b/arch/x86/entry/syscalls/syscall_64.tbl
>>> @@ -342,6 +342,7 @@
>>> 331 common pkey_free __x64_sys_pkey_free
>>> 332 common statx __x64_sys_statx
>>> 333 common io_pgetevents __x64_sys_io_pgetevents
>>> +334 common translate_pid __x64_sys_translate_pid
>>>
>>> #
>>> # x32-specific system call numbers start at 512 to avoid cache impact
>>> diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
>>> index 390e814fdc8d..3f33971cf1c8 100644
>>> --- a/include/linux/syscalls.h
>>> +++ b/include/linux/syscalls.h
>>> @@ -843,6 +843,7 @@ asmlinkage long sys_clock_adjtime(clockid_t which_clock,
>>> struct timex __user *tx);
>>> asmlinkage long sys_syncfs(int fd);
>>> asmlinkage long sys_setns(int fd, int nstype);
>>> +asmlinkage long sys_translate_pid(pid_t pid, int source, int target);
>>> asmlinkage long sys_sendmmsg(int fd, struct mmsghdr __user *msg,
>>> unsigned int vlen, unsigned flags);
>>> asmlinkage long sys_process_vm_readv(pid_t pid,
>>> diff --git a/kernel/pid_namespace.c b/kernel/pid_namespace.c
>>> index 2a2ac53d8b8b..3b872cbbe264 100644
>>> --- a/kernel/pid_namespace.c
>>> +++ b/kernel/pid_namespace.c
>>> @@ -13,6 +13,7 @@
>>> #include <linux/user_namespace.h>
>>> #include <linux/syscalls.h>
>>> #include <linux/cred.h>
>>> +#include <linux/file.h>
>>> #include <linux/err.h>
>>> #include <linux/acct.h>
>>> #include <linux/slab.h>
>>> @@ -380,6 +381,71 @@ static void pidns_put(struct ns_common *ns)
>>> put_pid_ns(to_pid_ns(ns));
>>> }
>>>
>>> +static struct pid_namespace *get_pid_ns_by_fd(int fd)
>>> +{
>>> + struct pid_namespace *pidns;
>>> + struct ns_common *ns;
>>> + struct file *file;
>>> +
>>> + file = proc_ns_fget(fd);
>>> + if (IS_ERR(file))
>>> + return ERR_CAST(file);
>>> +
>>> + ns = get_proc_ns(file_inode(file));
>>> + if (ns->ops->type == CLONE_NEWPID)
>>> + pidns = get_pid_ns(to_pid_ns(ns));
>>> + else
>>> + pidns = ERR_PTR(-EINVAL);
>>> +
>>> + fput(file);
>>> + return pidns;
>>> +}
>>> +
>>> +/*
>>> + * translate_pid - convert pid in source pid-ns into target pid-ns.
>>> + * @pid: pid for translation
>>> + * @source: pid-ns file descriptor or -1 for active namespace
>>> + * @target: pid-ns file descriptor or -1 for active namesapce
>>> + *
>>> + * Returns pid in @target pid-ns, zero if task have no pid there,
>>> + * or -ESRCH if task with @pid does not found in @source pid-ns.
>>> + */
>>> +SYSCALL_DEFINE3(translate_pid, pid_t, pid, int, source, int, target)
>>> +{
>>> + struct pid_namespace *source_ns, *target_ns;
>>> + struct pid *struct_pid;
>>> + pid_t result;
>>> +
>>> + if (source >= 0) {
>>> + source_ns = get_pid_ns_by_fd(source);
>>> + result = PTR_ERR(source_ns);
>>> + if (IS_ERR(source_ns))
>>> + goto err_source;
>>> + } else
>>> + source_ns = task_active_pid_ns(current);
>>> +
>>> + if (target >= 0) {
>>> + target_ns = get_pid_ns_by_fd(target);
>>> + result = PTR_ERR(target_ns);
>>> + if (IS_ERR(target_ns))
>>> + goto err_target;
>>> + } else
>>> + target_ns = task_active_pid_ns(current);
>>> +
>>> + rcu_read_lock();
>>> + struct_pid = find_pid_ns(pid, source_ns);
>>> + result = struct_pid ? pid_nr_ns(struct_pid, target_ns) : -ESRCH;
>>> + rcu_read_unlock();
>>> +
>>> + if (target >= 0)
>>> + put_pid_ns(target_ns);
>>> +err_target:
>>> + if (source >= 0)
>>> + put_pid_ns(source_ns);
>>> +err_source:
>>> + return result;
>>> +}
>>> +
>>> static int pidns_install(struct nsproxy *nsproxy, struct ns_common *ns)
>>> {
>>> struct pid_namespace *active = task_active_pid_ns(current);
>>> diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c
>>> index 06b4ccee0047..bf276e9ace9a 100644
>>> --- a/kernel/sys_ni.c
>>> +++ b/kernel/sys_ni.c
>>> @@ -153,6 +153,9 @@ COND_SYSCALL_COMPAT(kexec_load);
>>> COND_SYSCALL(init_module);
>>> COND_SYSCALL(delete_module);
>>>
>>> +/* kernel/pid_namespace.c */
>>> +COND_SYSCALL(translate_pid);
>>> +
>>> /* kernel/posix-timers.c */
>>>
>>> /* kernel/printk.c */
>>>
>> Ping :-) Checking back again for Ack or comments.
> JFYI, I'll try to attract more attention to this proposal
> by mentioning it in my talk at the LPC 2018 as a potential solution
> for one of several problems we have in strace, see
> https://www.linuxplumbersconf.org/event/2/contributions/78/
The patch has been picked up by Eric and it is in his tree. Not sure why
it has not made to a linux release.
Thanks,
Nagarathnam.
>
^ permalink raw reply
* Re: [PATCHv7 03/10] acpi/hmat: Parse and report heterogeneous memory
From: Jonathan Cameron @ 2019-03-08 17:25 UTC (permalink / raw)
To: Keith Busch
Cc: linux-kernel, linux-acpi, linux-mm, linux-api, Greg Kroah-Hartman,
Rafael Wysocki, Dave Hansen, Dan Williams
In-Reply-To: <20190227225038.20438-4-keith.busch@intel.com>
On Wed, 27 Feb 2019 15:50:31 -0700
Keith Busch <keith.busch@intel.com> wrote:
> Systems may provide different memory types and export this information
> in the ACPI Heterogeneous Memory Attribute Table (HMAT). Parse these
> tables provided by the platform and report the memory access and caching
> attributes to the kernel messages.
>
> Reviewed-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> Signed-off-by: Keith Busch <keith.busch@intel.com>
Hi Keith,
Trivial unused variable that could do with tidying up...
Thanks,
Jonathan
> ---
> drivers/acpi/Kconfig | 1 +
> drivers/acpi/Makefile | 1 +
> drivers/acpi/hmat/Kconfig | 7 ++
> drivers/acpi/hmat/Makefile | 1 +
> drivers/acpi/hmat/hmat.c | 237 +++++++++++++++++++++++++++++++++++++++++++++
> 5 files changed, 247 insertions(+)
> create mode 100644 drivers/acpi/hmat/Kconfig
> create mode 100644 drivers/acpi/hmat/Makefile
> create mode 100644 drivers/acpi/hmat/hmat.c
>
> diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
> index 4e015c77e48e..283ee94224c6 100644
> --- a/drivers/acpi/Kconfig
> +++ b/drivers/acpi/Kconfig
> @@ -475,6 +475,7 @@ config ACPI_REDUCED_HARDWARE_ONLY
> If you are unsure what to do, do not enable this option.
>
> source "drivers/acpi/nfit/Kconfig"
> +source "drivers/acpi/hmat/Kconfig"
>
> source "drivers/acpi/apei/Kconfig"
> source "drivers/acpi/dptf/Kconfig"
> diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
> index bb857421c2e8..5d361e4e3405 100644
> --- a/drivers/acpi/Makefile
> +++ b/drivers/acpi/Makefile
> @@ -80,6 +80,7 @@ obj-$(CONFIG_ACPI_PROCESSOR) += processor.o
> obj-$(CONFIG_ACPI) += container.o
> obj-$(CONFIG_ACPI_THERMAL) += thermal.o
> obj-$(CONFIG_ACPI_NFIT) += nfit/
> +obj-$(CONFIG_ACPI_HMAT) += hmat/
> obj-$(CONFIG_ACPI) += acpi_memhotplug.o
> obj-$(CONFIG_ACPI_HOTPLUG_IOAPIC) += ioapic.o
> obj-$(CONFIG_ACPI_BATTERY) += battery.o
> diff --git a/drivers/acpi/hmat/Kconfig b/drivers/acpi/hmat/Kconfig
> new file mode 100644
> index 000000000000..2f7111b7af62
> --- /dev/null
> +++ b/drivers/acpi/hmat/Kconfig
> @@ -0,0 +1,7 @@
> +# SPDX-License-Identifier: GPL-2.0
> +config ACPI_HMAT
> + bool "ACPI Heterogeneous Memory Attribute Table Support"
> + depends on ACPI_NUMA
> + help
> + If set, this option has the kernel parse and report the
> + platform's ACPI HMAT (Heterogeneous Memory Attributes Table).
> diff --git a/drivers/acpi/hmat/Makefile b/drivers/acpi/hmat/Makefile
> new file mode 100644
> index 000000000000..e909051d3d00
> --- /dev/null
> +++ b/drivers/acpi/hmat/Makefile
> @@ -0,0 +1 @@
> +obj-$(CONFIG_ACPI_HMAT) := hmat.o
> diff --git a/drivers/acpi/hmat/hmat.c b/drivers/acpi/hmat/hmat.c
> new file mode 100644
> index 000000000000..99f711420f6d
> --- /dev/null
> +++ b/drivers/acpi/hmat/hmat.c
> @@ -0,0 +1,237 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2019, Intel Corporation.
> + *
> + * Heterogeneous Memory Attributes Table (HMAT) representation
> + *
> + * This program parses and reports the platform's HMAT tables, and registers
> + * the applicable attributes with the node's interfaces.
> + */
> +
> +#include <linux/acpi.h>
> +#include <linux/bitops.h>
> +#include <linux/device.h>
> +#include <linux/init.h>
> +#include <linux/list.h>
> +#include <linux/node.h>
> +#include <linux/sysfs.h>
> +
> +static __initdata u8 hmat_revision;
> +
> +static __init const char *hmat_data_type(u8 type)
> +{
> + switch (type) {
> + case ACPI_HMAT_ACCESS_LATENCY:
> + return "Access Latency";
> + case ACPI_HMAT_READ_LATENCY:
> + return "Read Latency";
> + case ACPI_HMAT_WRITE_LATENCY:
> + return "Write Latency";
> + case ACPI_HMAT_ACCESS_BANDWIDTH:
> + return "Access Bandwidth";
> + case ACPI_HMAT_READ_BANDWIDTH:
> + return "Read Bandwidth";
> + case ACPI_HMAT_WRITE_BANDWIDTH:
> + return "Write Bandwidth";
> + default:
> + return "Reserved";
> + }
> +}
> +
> +static __init const char *hmat_data_type_suffix(u8 type)
> +{
> + switch (type) {
> + case ACPI_HMAT_ACCESS_LATENCY:
> + case ACPI_HMAT_READ_LATENCY:
> + case ACPI_HMAT_WRITE_LATENCY:
> + return " nsec";
> + case ACPI_HMAT_ACCESS_BANDWIDTH:
> + case ACPI_HMAT_READ_BANDWIDTH:
> + case ACPI_HMAT_WRITE_BANDWIDTH:
> + return " MB/s";
> + default:
> + return "";
> + }
> +}
> +
> +static __init u32 hmat_normalize(u16 entry, u64 base, u8 type)
> +{
> + u32 value;
> +
> + /*
> + * Check for invalid and overflow values
> + */
> + if (entry == 0xffff || !entry)
> + return 0;
> + else if (base > (UINT_MAX / (entry)))
> + return 0;
> +
> + /*
> + * Divide by the base unit for version 1, convert latency from
> + * picosenonds to nanoseconds if revision 2.
> + */
> + value = entry * base;
> + if (hmat_revision == 1) {
> + if (value < 10)
> + return 0;
> + value = DIV_ROUND_UP(value, 10);
> + } else if (hmat_revision == 2) {
> + switch (type) {
> + case ACPI_HMAT_ACCESS_LATENCY:
> + case ACPI_HMAT_READ_LATENCY:
> + case ACPI_HMAT_WRITE_LATENCY:
> + value = DIV_ROUND_UP(value, 1000);
> + break;
> + default:
> + break;
> + }
> + }
> + return value;
> +}
> +
> +static __init int hmat_parse_locality(union acpi_subtable_headers *header,
> + const unsigned long end)
> +{
> + struct acpi_hmat_locality *hmat_loc = (void *)header;
> + unsigned int init, targ, total_size, ipds, tpds;
> + u32 *inits, *targs, value;
> + u16 *entries;
> + u8 type;
> +
> + if (hmat_loc->header.length < sizeof(*hmat_loc)) {
> + pr_notice("HMAT: Unexpected locality header length: %d\n",
> + hmat_loc->header.length);
> + return -EINVAL;
> + }
> +
> + type = hmat_loc->data_type;
> + ipds = hmat_loc->number_of_initiator_Pds;
> + tpds = hmat_loc->number_of_target_Pds;
> + total_size = sizeof(*hmat_loc) + sizeof(*entries) * ipds * tpds +
> + sizeof(*inits) * ipds + sizeof(*targs) * tpds;
> + if (hmat_loc->header.length < total_size) {
> + pr_notice("HMAT: Unexpected locality header length:%d, minimum required:%d\n",
> + hmat_loc->header.length, total_size);
> + return -EINVAL;
> + }
> +
> + pr_info("HMAT: Locality: Flags:%02x Type:%s Initiator Domains:%d Target Domains:%d Base:%lld\n",
> + hmat_loc->flags, hmat_data_type(type), ipds, tpds,
> + hmat_loc->entry_base_unit);
> +
> + inits = (u32 *)(hmat_loc + 1);
> + targs = inits + ipds;
> + entries = (u16 *)(targs + tpds);
> + for (init = 0; init < ipds; init++) {
> + for (targ = 0; targ < tpds; targ++) {
> + value = hmat_normalize(entries[init * tpds + targ],
> + hmat_loc->entry_base_unit,
> + type);
> + pr_info(" Initiator-Target[%d-%d]:%d%s\n",
> + inits[init], targs[targ], value,
> + hmat_data_type_suffix(type));
> + }
> + }
> +
> + return 0;
> +}
> +
> +static __init int hmat_parse_cache(union acpi_subtable_headers *header,
> + const unsigned long end)
> +{
> + struct acpi_hmat_cache *cache = (void *)header;
> + u32 attrs;
> +
> + if (cache->header.length < sizeof(*cache)) {
> + pr_notice("HMAT: Unexpected cache header length: %d\n",
> + cache->header.length);
> + return -EINVAL;
> + }
> +
> + attrs = cache->cache_attributes;
> + pr_info("HMAT: Cache: Domain:%d Size:%llu Attrs:%08x SMBIOS Handles:%d\n",
> + cache->memory_PD, cache->cache_size, attrs,
> + cache->number_of_SMBIOShandles);
> +
> + return 0;
> +}
> +
> +static int __init hmat_parse_address_range(union acpi_subtable_headers *header,
> + const unsigned long end)
> +{
> + struct acpi_hmat_proximity_domain *p = (void *)header;
> + struct memory_target *target = NULL;
Not used anywhere.
> +
> + if (p->header.length != sizeof(*p)) {
> + pr_notice("HMAT: Unexpected address range header length: %d\n",
> + p->header.length);
> + return -EINVAL;
> + }
> +
> + if (hmat_revision == 1)
> + pr_info("HMAT: Memory (%#llx length %#llx) Flags:%04x Processor Domain:%d Memory Domain:%d\n",
> + p->reserved3, p->reserved4, p->flags, p->processor_PD,
> + p->memory_PD);
> + else
> + pr_info("HMAT: Memory Flags:%04x Processor Domain:%d Memory Domain:%d\n",
> + p->flags, p->processor_PD, p->memory_PD);
> +
> + return 0;
> +}
> +
> +static int __init hmat_parse_subtable(union acpi_subtable_headers *header,
> + const unsigned long end)
> +{
> + struct acpi_hmat_structure *hdr = (void *)header;
> +
> + if (!hdr)
> + return -EINVAL;
> +
> + switch (hdr->type) {
> + case ACPI_HMAT_TYPE_ADDRESS_RANGE:
> + return hmat_parse_address_range(header, end);
> + case ACPI_HMAT_TYPE_LOCALITY:
> + return hmat_parse_locality(header, end);
> + case ACPI_HMAT_TYPE_CACHE:
> + return hmat_parse_cache(header, end);
> + default:
> + return -EINVAL;
> + }
> +}
> +
> +static __init int hmat_init(void)
> +{
> + struct acpi_table_header *tbl;
> + enum acpi_hmat_type i;
> + acpi_status status;
> +
> + if (srat_disabled())
> + return 0;
> +
> + status = acpi_get_table(ACPI_SIG_HMAT, 0, &tbl);
> + if (ACPI_FAILURE(status))
> + return 0;
> +
> + hmat_revision = tbl->revision;
> + switch (hmat_revision) {
> + case 1:
> + case 2:
> + break;
> + default:
> + pr_notice("Ignoring HMAT: Unknown revision:%d\n", hmat_revision);
> + goto out_put;
> + }
> +
> + for (i = ACPI_HMAT_TYPE_ADDRESS_RANGE; i < ACPI_HMAT_TYPE_RESERVED; i++) {
> + if (acpi_table_parse_entries(ACPI_SIG_HMAT,
> + sizeof(struct acpi_table_hmat), i,
> + hmat_parse_subtable, 0) < 0) {
> + pr_notice("Ignoring HMAT: Invalid table");
> + goto out_put;
> + }
> + }
> +out_put:
> + acpi_put_table(tbl);
> + return 0;
> +}
> +subsys_initcall(hmat_init);
^ permalink raw reply
* Re: [PATCHv7 06/10] node: Add memory-side caching attributes
From: Jonathan Cameron @ 2019-03-08 16:21 UTC (permalink / raw)
To: Keith Busch
Cc: linux-kernel, linux-acpi, linux-mm, linux-api, Greg Kroah-Hartman,
Rafael Wysocki, Dave Hansen, Dan Williams
In-Reply-To: <20190227225038.20438-7-keith.busch@intel.com>
On Wed, 27 Feb 2019 15:50:34 -0700
Keith Busch <keith.busch@intel.com> wrote:
> System memory may have caches to help improve access speed to frequently
> requested address ranges. While the system provided cache is transparent
> to the software accessing these memory ranges, applications can optimize
> their own access based on cache attributes.
>
> Provide a new API for the kernel to register these memory-side caches
> under the memory node that provides it.
>
> The new sysfs representation is modeled from the existing cpu cacheinfo
> attributes, as seen from /sys/devices/system/cpu/<cpu>/cache/. Unlike CPU
> cacheinfo though, the node cache level is reported from the view of the
> memory. A higher level number is nearer to the CPU, while lower levels
> are closer to the last level memory.
>
> The exported attributes are the cache size, the line size, associativity
> indexing, and write back policy, and add the attributes for the system
> memory caches to sysfs stable documentation.
>
> Signed-off-by: Keith Busch <keith.busch@intel.com>
One utterly trivial point inline that git am pointed out.
J
> ---
> Documentation/ABI/stable/sysfs-devices-node | 34 +++++++
> drivers/base/node.c | 151 ++++++++++++++++++++++++++++
> include/linux/node.h | 39 +++++++
> 3 files changed, 224 insertions(+)
>
> diff --git a/Documentation/ABI/stable/sysfs-devices-node b/Documentation/ABI/stable/sysfs-devices-node
> index 41cb9345e1e0..970fef47e6cd 100644
> --- a/Documentation/ABI/stable/sysfs-devices-node
> +++ b/Documentation/ABI/stable/sysfs-devices-node
> @@ -142,3 +142,37 @@ Contact: Keith Busch <keith.busch@intel.com>
> Description:
> This node's write latency in nanoseconds when access
> from nodes found in this class's linked initiators.
> +
> +What: /sys/devices/system/node/nodeX/memory_side_cache/indexY/
> +Date: December 2018
> +Contact: Keith Busch <keith.busch@intel.com>
> +Description:
> + The directory containing attributes for the memory-side cache
> + level 'Y'.
> +
> +What: /sys/devices/system/node/nodeX/memory_side_cache/indexY/indexing
> +Date: December 2018
> +Contact: Keith Busch <keith.busch@intel.com>
> +Description:
> + The caches associativity indexing: 0 for direct mapped,
> + non-zero if indexed.
> +
> +What: /sys/devices/system/node/nodeX/memory_side_cache/indexY/line_size
> +Date: December 2018
> +Contact: Keith Busch <keith.busch@intel.com>
> +Description:
> + The number of bytes accessed from the next cache level on a
> + cache miss.
> +
> +What: /sys/devices/system/node/nodeX/memory_side_cache/indexY/size
> +Date: December 2018
> +Contact: Keith Busch <keith.busch@intel.com>
> +Description:
> + The size of this memory side cache in bytes.
> +
> +What: /sys/devices/system/node/nodeX/memory_side_cache/indexY/write_policy
> +Date: December 2018
> +Contact: Keith Busch <keith.busch@intel.com>
> +Description:
> + The cache write policy: 0 for write-back, 1 for write-through,
> + other or unknown.
> diff --git a/drivers/base/node.c b/drivers/base/node.c
> index 2de546a040a5..8598fcbd2a17 100644
> --- a/drivers/base/node.c
> +++ b/drivers/base/node.c
> @@ -205,6 +205,155 @@ void node_set_perf_attrs(unsigned int nid, struct node_hmem_attrs *hmem_attrs,
> }
> }
> }
> +
> +/**
> + * struct node_cache_info - Internal tracking for memory node caches
> + * @dev: Device represeting the cache level
> + * @node: List element for tracking in the node
> + * @cache_attrs:Attributes for this cache level
> + */
> +struct node_cache_info {
> + struct device dev;
> + struct list_head node;
> + struct node_cache_attrs cache_attrs;
> +};
> +#define to_cache_info(device) container_of(device, struct node_cache_info, dev)
> +
> +#define CACHE_ATTR(name, fmt) \
> +static ssize_t name##_show(struct device *dev, \
> + struct device_attribute *attr, \
> + char *buf) \
> +{ \
> + return sprintf(buf, fmt "\n", to_cache_info(dev)->cache_attrs.name);\
> +} \
> +DEVICE_ATTR_RO(name);
> +
> +CACHE_ATTR(size, "%llu")
> +CACHE_ATTR(line_size, "%u")
> +CACHE_ATTR(indexing, "%u")
> +CACHE_ATTR(write_policy, "%u")
> +
> +static struct attribute *cache_attrs[] = {
> + &dev_attr_indexing.attr,
> + &dev_attr_size.attr,
> + &dev_attr_line_size.attr,
> + &dev_attr_write_policy.attr,
> + NULL,
> +};
> +ATTRIBUTE_GROUPS(cache);
> +
> +static void node_cache_release(struct device *dev)
> +{
> + kfree(dev);
> +}
> +
> +static void node_cacheinfo_release(struct device *dev)
> +{
> + struct node_cache_info *info = to_cache_info(dev);
> + kfree(info);
> +}
> +
> +static void node_init_cache_dev(struct node *node)
> +{
> + struct device *dev;
> +
> + dev = kzalloc(sizeof(*dev), GFP_KERNEL);
> + if (!dev)
> + return;
> +
> + dev->parent = &node->dev;
> + dev->release = node_cache_release;
> + if (dev_set_name(dev, "memory_side_cache"))
> + goto free_dev;
> +
> + if (device_register(dev))
> + goto free_name;
> +
> + pm_runtime_no_callbacks(dev);
> + node->cache_dev = dev;
> + return;
> +free_name:
> + kfree_const(dev->kobj.name);
> +free_dev:
> + kfree(dev);
> +}
> +
> +/**
> + * node_add_cache() - add cache attribute to a memory node
> + * @nid: Node identifier that has new cache attributes
> + * @cache_attrs: Attributes for the cache being added
> + */
> +void node_add_cache(unsigned int nid, struct node_cache_attrs *cache_attrs)
> +{
> + struct node_cache_info *info;
> + struct device *dev;
> + struct node *node;
> +
> + if (!node_online(nid) || !node_devices[nid])
> + return;
> +
> + node = node_devices[nid];
> + list_for_each_entry(info, &node->cache_attrs, node) {
> + if (info->cache_attrs.level == cache_attrs->level) {
> + dev_warn(&node->dev,
> + "attempt to add duplicate cache level:%d\n",
> + cache_attrs->level);
> + return;
> + }
> + }
> +
> + if (!node->cache_dev)
> + node_init_cache_dev(node);
> + if (!node->cache_dev)
> + return;
> +
> + info = kzalloc(sizeof(*info), GFP_KERNEL);
> + if (!info)
> + return;
> +
> + dev = &info->dev;
> + dev->parent = node->cache_dev;
> + dev->release = node_cacheinfo_release;
> + dev->groups = cache_groups;
> + if (dev_set_name(dev, "index%d", cache_attrs->level))
> + goto free_cache;
> +
> + info->cache_attrs = *cache_attrs;
> + if (device_register(dev)) {
> + dev_warn(&node->dev, "failed to add cache level:%d\n",
> + cache_attrs->level);
> + goto free_name;
> + }
> + pm_runtime_no_callbacks(dev);
> + list_add_tail(&info->node, &node->cache_attrs);
> + return;
> +free_name:
> + kfree_const(dev->kobj.name);
> +free_cache:
> + kfree(info);
> +}
> +
> +static void node_remove_caches(struct node *node)
> +{
> + struct node_cache_info *info, *next;
> +
> + if (!node->cache_dev)
> + return;
> +
> + list_for_each_entry_safe(info, next, &node->cache_attrs, node) {
> + list_del(&info->node);
> + device_unregister(&info->dev);
> + }
> + device_unregister(node->cache_dev);
> +}
> +
> +static void node_init_caches(unsigned int nid)
> +{
> + INIT_LIST_HEAD(&node_devices[nid]->cache_attrs);
> +}
> +#else
> +static void node_init_caches(unsigned int nid) { }
> +static void node_remove_caches(struct node *node) { }
> #endif
>
> #define K(x) ((x) << (PAGE_SHIFT - 10))
> @@ -489,6 +638,7 @@ void unregister_node(struct node *node)
> {
> hugetlb_unregister_node(node); /* no-op, if memoryless node */
> node_remove_accesses(node);
> + node_remove_caches(node);
> device_unregister(&node->dev);
> }
>
> @@ -781,6 +931,7 @@ int __register_one_node(int nid)
> INIT_LIST_HEAD(&node_devices[nid]->access_list);
> /* initialize work queue for memory hot plug */
> init_node_hugetlb_work(nid);
> + node_init_caches(nid);
>
> return error;
> }
> diff --git a/include/linux/node.h b/include/linux/node.h
> index 45e14e1e0c18..8fa350e01acc 100644
> --- a/include/linux/node.h
> +++ b/include/linux/node.h
> @@ -35,10 +35,45 @@ struct node_hmem_attrs {
> unsigned int write_latency;
> };
>
> +enum cache_indexing {
> + NODE_CACHE_DIRECT_MAP,
> + NODE_CACHE_INDEXED,
> + NODE_CACHE_OTHER,
> +};
> +
> +enum cache_write_policy {
> + NODE_CACHE_WRITE_BACK,
> + NODE_CACHE_WRITE_THROUGH,
> + NODE_CACHE_WRITE_OTHER,
> +};
> +
> +/**
> + * struct node_cache_attrs - system memory caching attributes
> + *
> + * @indexing: The ways memory blocks may be placed in cache
> + * @write_policy: Write back or write through policy
> + * @size: Total size of cache in bytes
> + * @line_size: Number of bytes fetched on a cache miss
> + * @level: The cache hierarchy level
> + */
> +struct node_cache_attrs {
> + enum cache_indexing indexing;
> + enum cache_write_policy write_policy;
> + u64 size;
> + u16 line_size;
> + u8 level;
> +};
> +
> #ifdef CONFIG_HMEM_REPORTING
> +void node_add_cache(unsigned int nid, struct node_cache_attrs *cache_attrs);
> void node_set_perf_attrs(unsigned int nid, struct node_hmem_attrs *hmem_attrs,
> unsigned access);
> #else
> +static inline void node_add_cache(unsigned int nid,
> + struct node_cache_attrs *cache_attrs)
> +{
> +}
There is a stray space at the end of the line above...
> +
> static inline void node_set_perf_attrs(unsigned int nid,
> struct node_hmem_attrs *hmem_attrs,
> unsigned access)
> @@ -52,6 +87,10 @@ struct node {
> #if defined(CONFIG_MEMORY_HOTPLUG_SPARSE) && defined(CONFIG_HUGETLBFS)
> struct work_struct node_work;
> #endif
> +#ifdef CONFIG_HMEM_REPORTING
> + struct list_head cache_attrs;
> + struct device *cache_dev;
> +#endif
> };
>
> struct memory_block;
^ permalink raw reply
* Re: [PATCH 11/19] block: implement bio helper to add iter bvec pages to bio
From: Ming Lei @ 2019-03-08 9:12 UTC (permalink / raw)
To: Christoph Hellwig
Cc: Jens Axboe, Ming Lei, Eric Biggers, open list:AIO, linux-block,
linux-api, Jeff Moyer, Avi Kivity, jannh, Al Viro
In-Reply-To: <20190308075522.GA12445@lst.de>
On Fri, Mar 08, 2019 at 08:55:22AM +0100, Christoph Hellwig wrote:
> On Tue, Feb 26, 2019 at 07:28:54PM -0700, Jens Axboe wrote:
> > On 2/26/19 7:21 PM, Ming Lei wrote:
> > > On Tue, Feb 26, 2019 at 06:57:16PM -0700, Jens Axboe wrote:
> > >> On 2/26/19 6:53 PM, Ming Lei wrote:
> > >>> On Tue, Feb 26, 2019 at 06:47:54PM -0700, Jens Axboe wrote:
> > >>>> On 2/26/19 6:21 PM, Ming Lei wrote:
> > >>>>> On Tue, Feb 26, 2019 at 11:56 PM Jens Axboe <axboe@kernel.dk> wrote:
> > >>>>>>
> > >>>>>> On 2/25/19 9:34 PM, Jens Axboe wrote:
> > >>>>>>> On 2/25/19 8:46 PM, Eric Biggers wrote:
> > >>>>>>>> Hi Jens,
> > >>>>>>>>
> > >>>>>>>> On Thu, Feb 21, 2019 at 10:45:27AM -0700, Jens Axboe wrote:
> > >>>>>>>>> On 2/20/19 3:58 PM, Ming Lei wrote:
> > >>>>>>>>>> On Mon, Feb 11, 2019 at 12:00:41PM -0700, Jens Axboe wrote:
> > >>>>>>>>>>> For an ITER_BVEC, we can just iterate the iov and add the pages
> > >>>>>>>>>>> to the bio directly. This requires that the caller doesn't releases
> > >>>>>>>>>>> the pages on IO completion, we add a BIO_NO_PAGE_REF flag for that.
> > >>>>>>>>>>>
> > >>>>>>>>>>> The current two callers of bio_iov_iter_get_pages() are updated to
> > >>>>>>>>>>> check if they need to release pages on completion. This makes them
> > >>>>>>>>>>> work with bvecs that contain kernel mapped pages already.
> > >>>>>>>>>>>
> > >>>>>>>>>>> Reviewed-by: Hannes Reinecke <hare@suse.com>
> > >>>>>>>>>>> Reviewed-by: Christoph Hellwig <hch@lst.de>
> > >>>>>>>>>>> Signed-off-by: Jens Axboe <axboe@kernel.dk>
> > >>>>>>>>>>> ---
> > >>>>>>>>>>> block/bio.c | 59 ++++++++++++++++++++++++++++++++-------
> > >>>>>>>>>>> fs/block_dev.c | 5 ++--
> > >>>>>>>>>>> fs/iomap.c | 5 ++--
> > >>>>>>>>>>> include/linux/blk_types.h | 1 +
> > >>>>>>>>>>> 4 files changed, 56 insertions(+), 14 deletions(-)
> > >>>>>>>>>>>
> > >>>>>>>>>>> diff --git a/block/bio.c b/block/bio.c
> > >>>>>>>>>>> index 4db1008309ed..330df572cfb8 100644
> > >>>>>>>>>>> --- a/block/bio.c
> > >>>>>>>>>>> +++ b/block/bio.c
> > >>>>>>>>>>> @@ -828,6 +828,23 @@ int bio_add_page(struct bio *bio, struct page *page,
> > >>>>>>>>>>> }
> > >>>>>>>>>>> EXPORT_SYMBOL(bio_add_page);
> > >>>>>>>>>>>
> > >>>>>>>>>>> +static int __bio_iov_bvec_add_pages(struct bio *bio, struct iov_iter *iter)
> > >>>>>>>>>>> +{
> > >>>>>>>>>>> + const struct bio_vec *bv = iter->bvec;
> > >>>>>>>>>>> + unsigned int len;
> > >>>>>>>>>>> + size_t size;
> > >>>>>>>>>>> +
> > >>>>>>>>>>> + len = min_t(size_t, bv->bv_len, iter->count);
> > >>>>>>>>>>> + size = bio_add_page(bio, bv->bv_page, len,
> > >>>>>>>>>>> + bv->bv_offset + iter->iov_offset);
> > >>>>>>>>>>
> > >>>>>>>>>> iter->iov_offset needs to be subtracted from 'len', looks
> > >>>>>>>>>> the following delta change[1] is required, otherwise memory corruption
> > >>>>>>>>>> can be observed when running xfstests over loop/dio.
> > >>>>>>>>>
> > >>>>>>>>> Thanks, I folded this in.
> > >>>>>>>>>
> > >>>>>>>>> --
> > >>>>>>>>> Jens Axboe
> > >>>>>>>>>
> > >>>>>>>>
> > >>>>>>>> syzkaller started hitting a crash on linux-next starting with this commit, and
> > >>>>>>>> it still occurs even with your latest version that has Ming's fix folded in.
> > >>>>>>>> Specifically, commit a566653ab5ab80a from your io_uring branch with commit date
> > >>>>>>>> Sun Feb 24 08:20:53 2019 -0700.
> > >>>>>>>>
> > >>>>>>>> Reproducer:
> > >>>>>>>>
> > >>>>>>>> #define _GNU_SOURCE
> > >>>>>>>> #include <fcntl.h>
> > >>>>>>>> #include <linux/loop.h>
> > >>>>>>>> #include <sys/ioctl.h>
> > >>>>>>>> #include <sys/sendfile.h>
> > >>>>>>>> #include <sys/syscall.h>
> > >>>>>>>> #include <unistd.h>
> > >>>>>>>>
> > >>>>>>>> int main(void)
> > >>>>>>>> {
> > >>>>>>>> int memfd, loopfd;
> > >>>>>>>>
> > >>>>>>>> memfd = syscall(__NR_memfd_create, "foo", 0);
> > >>>>>>>>
> > >>>>>>>> pwrite(memfd, "\xa8", 1, 4096);
> > >>>>>>>>
> > >>>>>>>> loopfd = open("/dev/loop0", O_RDWR|O_DIRECT);
> > >>>>>>>>
> > >>>>>>>> ioctl(loopfd, LOOP_SET_FD, memfd);
> > >>>>>>>>
> > >>>>>>>> sendfile(loopfd, loopfd, NULL, 1000000);
> > >>>>>>>> }
> > >>>>>>>>
> > >>>>>>>>
> > >>>>>>>> Crash:
> > >>>>>>>>
> > >>>>>>>> page:ffffea0001a6aab8 count:0 mapcount:0 mapping:0000000000000000 index:0x0
> > >>>>>>>> flags: 0x100000000000000()
> > >>>>>>>> raw: 0100000000000000 ffffea0001ad2c50 ffff88807fca49d0 0000000000000000
> > >>>>>>>> raw: 0000000000000000 0000000000000000 00000000ffffffff
> > >>>>>>>> page dumped because: VM_BUG_ON_PAGE(page_ref_count(page) == 0)
> > >>>>>>>
> > >>>>>>> I see what this is, I'll cut a fix for this tomorrow.
> > >>>>>>
> > >>>>>> Folded in a fix for this, it's in my current io_uring branch and my for-next
> > >>>>>> branch.
> > >>>>>
> > >>>>> Hi Jens,
> > >>>>>
> > >>>>> I saw the following change is added:
> > >>>>>
> > >>>>> + if (size == len) {
> > >>>>> + /*
> > >>>>> + * For the normal O_DIRECT case, we could skip grabbing this
> > >>>>> + * reference and then not have to put them again when IO
> > >>>>> + * completes. But this breaks some in-kernel users, like
> > >>>>> + * splicing to/from a loop device, where we release the pipe
> > >>>>> + * pages unconditionally. If we can fix that case, we can
> > >>>>> + * get rid of the get here and the need to call
> > >>>>> + * bio_release_pages() at IO completion time.
> > >>>>> + */
> > >>>>> + get_page(bv->bv_page);
> > >>>>>
> > >>>>> Now the 'bv' may point to more than one page, so the following one may be
> > >>>>> needed:
> > >>>>>
> > >>>>> int i;
> > >>>>> struct bvec_iter_all iter_all;
> > >>>>> struct bio_vec *tmp;
> > >>>>>
> > >>>>> mp_bvec_for_each_segment(tmp, bv, i, iter_all)
> > >>>>> get_page(tmp->bv_page);
> > >>>>
> > > Some following optimization can be done, such as removing
> > > biovec_phys_mergeable() from blk_bio_segment_split().
> >
> > I think we really need a fast path for <= PAGE_SIZE IOs, to the extent
> > that it is possible. But iteration startup cost is a problem in a lot of
> > spots, and a split fast path will only help a bit for that specific
> > case.
>
> FYI, I've got a nice fast path for the driver side in nvme here, but
> I'll need to do some more testing before submitting it:
>
> http://git.infradead.org/users/hch/block.git/shortlog/refs/heads/nvme-optimize-single-segment-io
>
> But in the block layer I think one major issue is all the phys_segments
> crap. What we really should do is to remove bi_phys_segments and all
> the front/back segment crap and only do the calculation of the actual
> per-bio segments once, just before adding the bio to the segment.
I have enabled multi-page bvec for passthrough IO in the following:
https://github.com/ming1/linux/commits/v5.0-blk-for-blk_post_mp
in which .bi_phys_segments becomes same with .bi_vcnt for passthrough bio.
Also intra-bvec merging in one bio has been killed, then only the merge
between bios is required, and seems we still need front/back segment size,
especially some use cases(such as mkfs) may make lots of small mergeable bios.
>
> And don't bother with it at all unless the driver has weird segment
> size or boundary limitations.
It should be easy to observe that .bv_len is bigger than max segment
size.
Thanks,
Ming
--
To unsubscribe, send a message with 'unsubscribe linux-aio' in
the body to majordomo@kvack.org. For more info on Linux AIO,
see: http://www.kvack.org/aio/
Don't email: <a href=mailto:"aart@kvack.org">aart@kvack.org</a>
^ permalink raw reply
* Re: [PATCH 11/19] block: implement bio helper to add iter bvec pages to bio
From: Christoph Hellwig @ 2019-03-08 8:18 UTC (permalink / raw)
To: Jens Axboe
Cc: Ming Lei, Ming Lei, Eric Biggers, open list:AIO, linux-block,
linux-api, Christoph Hellwig, Jeff Moyer, Avi Kivity, jannh,
Al Viro
In-Reply-To: <e4dace7b-6a6f-2606-9a7e-8ae3c97c26b0@kernel.dk>
On Tue, Feb 26, 2019 at 06:57:16PM -0700, Jens Axboe wrote:
> Speaking of this, I took a quick look at why we've now regressed a lot
> on IOPS perf with the multipage work. It looks like it's all related to
> the (much) fatter setup around iteration, which is related to this very
> topic too.
> Basically setup of things like bio_for_each_bvec() and indexing through
> nth_page() is MUCH slower than before.
I haven't quite figure out what the point of nth_page is. If we
physically merge the page structures should also be consecuite
in memory in general. The only case where this could theoretically
not be the case is with CONFIG_DISCONTIGMEM, but in that case we should
check this once in biovec_phys_mergeable, and only for that case.
Does this patch make a difference for you on x86?
--- a/include/linux/bvec.h
+++ b/include/linux/bvec.h
@@ -53,7 +53,7 @@ struct bvec_iter_all {
static inline struct page *bvec_nth_page(struct page *page, int idx)
{
- return idx == 0 ? page : nth_page(page, idx);
+ return page + idx;
}
/*
--
To unsubscribe, send a message with 'unsubscribe linux-aio' in
the body to majordomo@kvack.org. For more info on Linux AIO,
see: http://www.kvack.org/aio/
Don't email: <a href=mailto:"aart@kvack.org">aart@kvack.org</a>
^ permalink raw reply
* Re: [PATCH 11/19] block: implement bio helper to add iter bvec pages to bio
From: Christoph Hellwig @ 2019-03-08 7:55 UTC (permalink / raw)
To: Jens Axboe
Cc: Ming Lei, Ming Lei, Eric Biggers, open list:AIO, linux-block,
linux-api, Christoph Hellwig, Jeff Moyer, Avi Kivity, jannh,
Al Viro
In-Reply-To: <b54683e8-fbff-01ab-db98-c35de8e00e9f@kernel.dk>
On Tue, Feb 26, 2019 at 07:28:54PM -0700, Jens Axboe wrote:
> On 2/26/19 7:21 PM, Ming Lei wrote:
> > On Tue, Feb 26, 2019 at 06:57:16PM -0700, Jens Axboe wrote:
> >> On 2/26/19 6:53 PM, Ming Lei wrote:
> >>> On Tue, Feb 26, 2019 at 06:47:54PM -0700, Jens Axboe wrote:
> >>>> On 2/26/19 6:21 PM, Ming Lei wrote:
> >>>>> On Tue, Feb 26, 2019 at 11:56 PM Jens Axboe <axboe@kernel.dk> wrote:
> >>>>>>
> >>>>>> On 2/25/19 9:34 PM, Jens Axboe wrote:
> >>>>>>> On 2/25/19 8:46 PM, Eric Biggers wrote:
> >>>>>>>> Hi Jens,
> >>>>>>>>
> >>>>>>>> On Thu, Feb 21, 2019 at 10:45:27AM -0700, Jens Axboe wrote:
> >>>>>>>>> On 2/20/19 3:58 PM, Ming Lei wrote:
> >>>>>>>>>> On Mon, Feb 11, 2019 at 12:00:41PM -0700, Jens Axboe wrote:
> >>>>>>>>>>> For an ITER_BVEC, we can just iterate the iov and add the pages
> >>>>>>>>>>> to the bio directly. This requires that the caller doesn't releases
> >>>>>>>>>>> the pages on IO completion, we add a BIO_NO_PAGE_REF flag for that.
> >>>>>>>>>>>
> >>>>>>>>>>> The current two callers of bio_iov_iter_get_pages() are updated to
> >>>>>>>>>>> check if they need to release pages on completion. This makes them
> >>>>>>>>>>> work with bvecs that contain kernel mapped pages already.
> >>>>>>>>>>>
> >>>>>>>>>>> Reviewed-by: Hannes Reinecke <hare@suse.com>
> >>>>>>>>>>> Reviewed-by: Christoph Hellwig <hch@lst.de>
> >>>>>>>>>>> Signed-off-by: Jens Axboe <axboe@kernel.dk>
> >>>>>>>>>>> ---
> >>>>>>>>>>> block/bio.c | 59 ++++++++++++++++++++++++++++++++-------
> >>>>>>>>>>> fs/block_dev.c | 5 ++--
> >>>>>>>>>>> fs/iomap.c | 5 ++--
> >>>>>>>>>>> include/linux/blk_types.h | 1 +
> >>>>>>>>>>> 4 files changed, 56 insertions(+), 14 deletions(-)
> >>>>>>>>>>>
> >>>>>>>>>>> diff --git a/block/bio.c b/block/bio.c
> >>>>>>>>>>> index 4db1008309ed..330df572cfb8 100644
> >>>>>>>>>>> --- a/block/bio.c
> >>>>>>>>>>> +++ b/block/bio.c
> >>>>>>>>>>> @@ -828,6 +828,23 @@ int bio_add_page(struct bio *bio, struct page *page,
> >>>>>>>>>>> }
> >>>>>>>>>>> EXPORT_SYMBOL(bio_add_page);
> >>>>>>>>>>>
> >>>>>>>>>>> +static int __bio_iov_bvec_add_pages(struct bio *bio, struct iov_iter *iter)
> >>>>>>>>>>> +{
> >>>>>>>>>>> + const struct bio_vec *bv = iter->bvec;
> >>>>>>>>>>> + unsigned int len;
> >>>>>>>>>>> + size_t size;
> >>>>>>>>>>> +
> >>>>>>>>>>> + len = min_t(size_t, bv->bv_len, iter->count);
> >>>>>>>>>>> + size = bio_add_page(bio, bv->bv_page, len,
> >>>>>>>>>>> + bv->bv_offset + iter->iov_offset);
> >>>>>>>>>>
> >>>>>>>>>> iter->iov_offset needs to be subtracted from 'len', looks
> >>>>>>>>>> the following delta change[1] is required, otherwise memory corruption
> >>>>>>>>>> can be observed when running xfstests over loop/dio.
> >>>>>>>>>
> >>>>>>>>> Thanks, I folded this in.
> >>>>>>>>>
> >>>>>>>>> --
> >>>>>>>>> Jens Axboe
> >>>>>>>>>
> >>>>>>>>
> >>>>>>>> syzkaller started hitting a crash on linux-next starting with this commit, and
> >>>>>>>> it still occurs even with your latest version that has Ming's fix folded in.
> >>>>>>>> Specifically, commit a566653ab5ab80a from your io_uring branch with commit date
> >>>>>>>> Sun Feb 24 08:20:53 2019 -0700.
> >>>>>>>>
> >>>>>>>> Reproducer:
> >>>>>>>>
> >>>>>>>> #define _GNU_SOURCE
> >>>>>>>> #include <fcntl.h>
> >>>>>>>> #include <linux/loop.h>
> >>>>>>>> #include <sys/ioctl.h>
> >>>>>>>> #include <sys/sendfile.h>
> >>>>>>>> #include <sys/syscall.h>
> >>>>>>>> #include <unistd.h>
> >>>>>>>>
> >>>>>>>> int main(void)
> >>>>>>>> {
> >>>>>>>> int memfd, loopfd;
> >>>>>>>>
> >>>>>>>> memfd = syscall(__NR_memfd_create, "foo", 0);
> >>>>>>>>
> >>>>>>>> pwrite(memfd, "\xa8", 1, 4096);
> >>>>>>>>
> >>>>>>>> loopfd = open("/dev/loop0", O_RDWR|O_DIRECT);
> >>>>>>>>
> >>>>>>>> ioctl(loopfd, LOOP_SET_FD, memfd);
> >>>>>>>>
> >>>>>>>> sendfile(loopfd, loopfd, NULL, 1000000);
> >>>>>>>> }
> >>>>>>>>
> >>>>>>>>
> >>>>>>>> Crash:
> >>>>>>>>
> >>>>>>>> page:ffffea0001a6aab8 count:0 mapcount:0 mapping:0000000000000000 index:0x0
> >>>>>>>> flags: 0x100000000000000()
> >>>>>>>> raw: 0100000000000000 ffffea0001ad2c50 ffff88807fca49d0 0000000000000000
> >>>>>>>> raw: 0000000000000000 0000000000000000 00000000ffffffff
> >>>>>>>> page dumped because: VM_BUG_ON_PAGE(page_ref_count(page) == 0)
> >>>>>>>
> >>>>>>> I see what this is, I'll cut a fix for this tomorrow.
> >>>>>>
> >>>>>> Folded in a fix for this, it's in my current io_uring branch and my for-next
> >>>>>> branch.
> >>>>>
> >>>>> Hi Jens,
> >>>>>
> >>>>> I saw the following change is added:
> >>>>>
> >>>>> + if (size == len) {
> >>>>> + /*
> >>>>> + * For the normal O_DIRECT case, we could skip grabbing this
> >>>>> + * reference and then not have to put them again when IO
> >>>>> + * completes. But this breaks some in-kernel users, like
> >>>>> + * splicing to/from a loop device, where we release the pipe
> >>>>> + * pages unconditionally. If we can fix that case, we can
> >>>>> + * get rid of the get here and the need to call
> >>>>> + * bio_release_pages() at IO completion time.
> >>>>> + */
> >>>>> + get_page(bv->bv_page);
> >>>>>
> >>>>> Now the 'bv' may point to more than one page, so the following one may be
> >>>>> needed:
> >>>>>
> >>>>> int i;
> >>>>> struct bvec_iter_all iter_all;
> >>>>> struct bio_vec *tmp;
> >>>>>
> >>>>> mp_bvec_for_each_segment(tmp, bv, i, iter_all)
> >>>>> get_page(tmp->bv_page);
> >>>>
> > Some following optimization can be done, such as removing
> > biovec_phys_mergeable() from blk_bio_segment_split().
>
> I think we really need a fast path for <= PAGE_SIZE IOs, to the extent
> that it is possible. But iteration startup cost is a problem in a lot of
> spots, and a split fast path will only help a bit for that specific
> case.
FYI, I've got a nice fast path for the driver side in nvme here, but
I'll need to do some more testing before submitting it:
http://git.infradead.org/users/hch/block.git/shortlog/refs/heads/nvme-optimize-single-segment-io
But in the block layer I think one major issue is all the phys_segments
crap. What we really should do is to remove bi_phys_segments and all
the front/back segment crap and only do the calculation of the actual
per-bio segments once, just before adding the bio to the segment.
And don't bother with it at all unless the driver has weird segment
size or boundary limitations.
--
To unsubscribe, send a message with 'unsubscribe linux-aio' in
the body to majordomo@kvack.org. For more info on Linux AIO,
see: http://www.kvack.org/aio/
Don't email: <a href=mailto:"aart@kvack.org">aart@kvack.org</a>
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox