2019-03-12 04:55:59 +08:00
|
|
|
// 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.
|
|
|
|
*/
|
|
|
|
|
ACPI: NUMA: HMAT: Register "soft reserved" memory as an "hmem" device
Memory that has been tagged EFI_MEMORY_SP, and has performance
properties described by the ACPI HMAT is expected to have an application
specific consumer.
Those consumers may want 100% of the memory capacity to be reserved from
any usage by the kernel. By default, with this enabling, a platform
device is created to represent this differentiated resource.
The device-dax "hmem" driver claims these devices by default and
provides an mmap interface for the target application. If the
administrator prefers, the hmem resource range can be made available to
the core-mm via the device-dax hotplug facility, kmem, to online the
memory with its own numa node.
This was tested with an emulated HMAT produced by qemu (with the pending
HMAT enabling patches), and "efi_fake_mem=8G@9G:0x40000" on the kernel
command line to mark the memory ranges associated with node2 and node3
as EFI_MEMORY_SP.
qemu numa configuration options:
-numa node,mem=4G,cpus=0-19,nodeid=0
-numa node,mem=4G,cpus=20-39,nodeid=1
-numa node,mem=4G,nodeid=2
-numa node,mem=4G,nodeid=3
-numa dist,src=0,dst=0,val=10
-numa dist,src=0,dst=1,val=21
-numa dist,src=0,dst=2,val=21
-numa dist,src=0,dst=3,val=21
-numa dist,src=1,dst=0,val=21
-numa dist,src=1,dst=1,val=10
-numa dist,src=1,dst=2,val=21
-numa dist,src=1,dst=3,val=21
-numa dist,src=2,dst=0,val=21
-numa dist,src=2,dst=1,val=21
-numa dist,src=2,dst=2,val=10
-numa dist,src=2,dst=3,val=21
-numa dist,src=3,dst=0,val=21
-numa dist,src=3,dst=1,val=21
-numa dist,src=3,dst=2,val=21
-numa dist,src=3,dst=3,val=10
-numa hmat-lb,initiator=0,target=0,hierarchy=memory,data-type=access-latency,base-lat=10,latency=5
-numa hmat-lb,initiator=0,target=0,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=5
-numa hmat-lb,initiator=0,target=1,hierarchy=memory,data-type=access-latency,base-lat=10,latency=10
-numa hmat-lb,initiator=0,target=1,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=10
-numa hmat-lb,initiator=0,target=2,hierarchy=memory,data-type=access-latency,base-lat=10,latency=15
-numa hmat-lb,initiator=0,target=2,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=15
-numa hmat-lb,initiator=0,target=3,hierarchy=memory,data-type=access-latency,base-lat=10,latency=20
-numa hmat-lb,initiator=0,target=3,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=20
-numa hmat-lb,initiator=1,target=0,hierarchy=memory,data-type=access-latency,base-lat=10,latency=10
-numa hmat-lb,initiator=1,target=0,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=10
-numa hmat-lb,initiator=1,target=1,hierarchy=memory,data-type=access-latency,base-lat=10,latency=5
-numa hmat-lb,initiator=1,target=1,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=5
-numa hmat-lb,initiator=1,target=2,hierarchy=memory,data-type=access-latency,base-lat=10,latency=15
-numa hmat-lb,initiator=1,target=2,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=15
-numa hmat-lb,initiator=1,target=3,hierarchy=memory,data-type=access-latency,base-lat=10,latency=20
-numa hmat-lb,initiator=1,target=3,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=20
Result:
[
{
"path":"\/platform\/hmem.1",
"id":1,
"size":"4.00 GiB (4.29 GB)",
"align":2097152,
"devices":[
{
"chardev":"dax1.0",
"size":"4.00 GiB (4.29 GB)"
}
]
},
{
"path":"\/platform\/hmem.0",
"id":0,
"size":"4.00 GiB (4.29 GB)",
"align":2097152,
"devices":[
{
"chardev":"dax0.0",
"size":"4.00 GiB (4.29 GB)"
}
]
}
]
[..]
240000000-43fffffff : Soft Reserved
240000000-33fffffff : hmem.0
240000000-33fffffff : dax0.0
340000000-43fffffff : hmem.1
340000000-43fffffff : dax1.0
Reviewed-by: Dave Hansen <dave.hansen@linux.intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Acked-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2019-11-07 09:43:55 +08:00
|
|
|
#define pr_fmt(fmt) "acpi/hmat: " fmt
|
|
|
|
#define dev_fmt(fmt) "acpi/hmat: " fmt
|
|
|
|
|
2019-03-12 04:55:59 +08:00
|
|
|
#include <linux/acpi.h>
|
|
|
|
#include <linux/bitops.h>
|
|
|
|
#include <linux/device.h>
|
|
|
|
#include <linux/init.h>
|
|
|
|
#include <linux/list.h>
|
ACPI: NUMA: HMAT: Register "soft reserved" memory as an "hmem" device
Memory that has been tagged EFI_MEMORY_SP, and has performance
properties described by the ACPI HMAT is expected to have an application
specific consumer.
Those consumers may want 100% of the memory capacity to be reserved from
any usage by the kernel. By default, with this enabling, a platform
device is created to represent this differentiated resource.
The device-dax "hmem" driver claims these devices by default and
provides an mmap interface for the target application. If the
administrator prefers, the hmem resource range can be made available to
the core-mm via the device-dax hotplug facility, kmem, to online the
memory with its own numa node.
This was tested with an emulated HMAT produced by qemu (with the pending
HMAT enabling patches), and "efi_fake_mem=8G@9G:0x40000" on the kernel
command line to mark the memory ranges associated with node2 and node3
as EFI_MEMORY_SP.
qemu numa configuration options:
-numa node,mem=4G,cpus=0-19,nodeid=0
-numa node,mem=4G,cpus=20-39,nodeid=1
-numa node,mem=4G,nodeid=2
-numa node,mem=4G,nodeid=3
-numa dist,src=0,dst=0,val=10
-numa dist,src=0,dst=1,val=21
-numa dist,src=0,dst=2,val=21
-numa dist,src=0,dst=3,val=21
-numa dist,src=1,dst=0,val=21
-numa dist,src=1,dst=1,val=10
-numa dist,src=1,dst=2,val=21
-numa dist,src=1,dst=3,val=21
-numa dist,src=2,dst=0,val=21
-numa dist,src=2,dst=1,val=21
-numa dist,src=2,dst=2,val=10
-numa dist,src=2,dst=3,val=21
-numa dist,src=3,dst=0,val=21
-numa dist,src=3,dst=1,val=21
-numa dist,src=3,dst=2,val=21
-numa dist,src=3,dst=3,val=10
-numa hmat-lb,initiator=0,target=0,hierarchy=memory,data-type=access-latency,base-lat=10,latency=5
-numa hmat-lb,initiator=0,target=0,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=5
-numa hmat-lb,initiator=0,target=1,hierarchy=memory,data-type=access-latency,base-lat=10,latency=10
-numa hmat-lb,initiator=0,target=1,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=10
-numa hmat-lb,initiator=0,target=2,hierarchy=memory,data-type=access-latency,base-lat=10,latency=15
-numa hmat-lb,initiator=0,target=2,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=15
-numa hmat-lb,initiator=0,target=3,hierarchy=memory,data-type=access-latency,base-lat=10,latency=20
-numa hmat-lb,initiator=0,target=3,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=20
-numa hmat-lb,initiator=1,target=0,hierarchy=memory,data-type=access-latency,base-lat=10,latency=10
-numa hmat-lb,initiator=1,target=0,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=10
-numa hmat-lb,initiator=1,target=1,hierarchy=memory,data-type=access-latency,base-lat=10,latency=5
-numa hmat-lb,initiator=1,target=1,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=5
-numa hmat-lb,initiator=1,target=2,hierarchy=memory,data-type=access-latency,base-lat=10,latency=15
-numa hmat-lb,initiator=1,target=2,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=15
-numa hmat-lb,initiator=1,target=3,hierarchy=memory,data-type=access-latency,base-lat=10,latency=20
-numa hmat-lb,initiator=1,target=3,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=20
Result:
[
{
"path":"\/platform\/hmem.1",
"id":1,
"size":"4.00 GiB (4.29 GB)",
"align":2097152,
"devices":[
{
"chardev":"dax1.0",
"size":"4.00 GiB (4.29 GB)"
}
]
},
{
"path":"\/platform\/hmem.0",
"id":0,
"size":"4.00 GiB (4.29 GB)",
"align":2097152,
"devices":[
{
"chardev":"dax0.0",
"size":"4.00 GiB (4.29 GB)"
}
]
}
]
[..]
240000000-43fffffff : Soft Reserved
240000000-33fffffff : hmem.0
240000000-33fffffff : dax0.0
340000000-43fffffff : hmem.1
340000000-43fffffff : dax1.0
Reviewed-by: Dave Hansen <dave.hansen@linux.intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Acked-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2019-11-07 09:43:55 +08:00
|
|
|
#include <linux/mm.h>
|
|
|
|
#include <linux/platform_device.h>
|
2019-03-12 04:56:03 +08:00
|
|
|
#include <linux/list_sort.h>
|
ACPI: NUMA: HMAT: Register "soft reserved" memory as an "hmem" device
Memory that has been tagged EFI_MEMORY_SP, and has performance
properties described by the ACPI HMAT is expected to have an application
specific consumer.
Those consumers may want 100% of the memory capacity to be reserved from
any usage by the kernel. By default, with this enabling, a platform
device is created to represent this differentiated resource.
The device-dax "hmem" driver claims these devices by default and
provides an mmap interface for the target application. If the
administrator prefers, the hmem resource range can be made available to
the core-mm via the device-dax hotplug facility, kmem, to online the
memory with its own numa node.
This was tested with an emulated HMAT produced by qemu (with the pending
HMAT enabling patches), and "efi_fake_mem=8G@9G:0x40000" on the kernel
command line to mark the memory ranges associated with node2 and node3
as EFI_MEMORY_SP.
qemu numa configuration options:
-numa node,mem=4G,cpus=0-19,nodeid=0
-numa node,mem=4G,cpus=20-39,nodeid=1
-numa node,mem=4G,nodeid=2
-numa node,mem=4G,nodeid=3
-numa dist,src=0,dst=0,val=10
-numa dist,src=0,dst=1,val=21
-numa dist,src=0,dst=2,val=21
-numa dist,src=0,dst=3,val=21
-numa dist,src=1,dst=0,val=21
-numa dist,src=1,dst=1,val=10
-numa dist,src=1,dst=2,val=21
-numa dist,src=1,dst=3,val=21
-numa dist,src=2,dst=0,val=21
-numa dist,src=2,dst=1,val=21
-numa dist,src=2,dst=2,val=10
-numa dist,src=2,dst=3,val=21
-numa dist,src=3,dst=0,val=21
-numa dist,src=3,dst=1,val=21
-numa dist,src=3,dst=2,val=21
-numa dist,src=3,dst=3,val=10
-numa hmat-lb,initiator=0,target=0,hierarchy=memory,data-type=access-latency,base-lat=10,latency=5
-numa hmat-lb,initiator=0,target=0,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=5
-numa hmat-lb,initiator=0,target=1,hierarchy=memory,data-type=access-latency,base-lat=10,latency=10
-numa hmat-lb,initiator=0,target=1,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=10
-numa hmat-lb,initiator=0,target=2,hierarchy=memory,data-type=access-latency,base-lat=10,latency=15
-numa hmat-lb,initiator=0,target=2,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=15
-numa hmat-lb,initiator=0,target=3,hierarchy=memory,data-type=access-latency,base-lat=10,latency=20
-numa hmat-lb,initiator=0,target=3,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=20
-numa hmat-lb,initiator=1,target=0,hierarchy=memory,data-type=access-latency,base-lat=10,latency=10
-numa hmat-lb,initiator=1,target=0,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=10
-numa hmat-lb,initiator=1,target=1,hierarchy=memory,data-type=access-latency,base-lat=10,latency=5
-numa hmat-lb,initiator=1,target=1,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=5
-numa hmat-lb,initiator=1,target=2,hierarchy=memory,data-type=access-latency,base-lat=10,latency=15
-numa hmat-lb,initiator=1,target=2,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=15
-numa hmat-lb,initiator=1,target=3,hierarchy=memory,data-type=access-latency,base-lat=10,latency=20
-numa hmat-lb,initiator=1,target=3,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=20
Result:
[
{
"path":"\/platform\/hmem.1",
"id":1,
"size":"4.00 GiB (4.29 GB)",
"align":2097152,
"devices":[
{
"chardev":"dax1.0",
"size":"4.00 GiB (4.29 GB)"
}
]
},
{
"path":"\/platform\/hmem.0",
"id":0,
"size":"4.00 GiB (4.29 GB)",
"align":2097152,
"devices":[
{
"chardev":"dax0.0",
"size":"4.00 GiB (4.29 GB)"
}
]
}
]
[..]
240000000-43fffffff : Soft Reserved
240000000-33fffffff : hmem.0
240000000-33fffffff : dax0.0
340000000-43fffffff : hmem.1
340000000-43fffffff : dax1.0
Reviewed-by: Dave Hansen <dave.hansen@linux.intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Acked-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2019-11-07 09:43:55 +08:00
|
|
|
#include <linux/memregion.h>
|
2019-08-05 22:27:05 +08:00
|
|
|
#include <linux/memory.h>
|
|
|
|
#include <linux/mutex.h>
|
2019-03-12 04:55:59 +08:00
|
|
|
#include <linux/node.h>
|
|
|
|
#include <linux/sysfs.h>
|
2020-10-14 07:49:13 +08:00
|
|
|
#include <linux/dax.h>
|
2019-03-12 04:55:59 +08:00
|
|
|
|
2019-08-05 22:27:05 +08:00
|
|
|
static u8 hmat_revision;
|
2020-10-14 07:49:02 +08:00
|
|
|
static int hmat_disable __initdata;
|
|
|
|
|
|
|
|
void __init disable_hmat(void)
|
|
|
|
{
|
|
|
|
hmat_disable = 1;
|
|
|
|
}
|
2019-03-12 04:55:59 +08:00
|
|
|
|
2019-08-05 22:27:05 +08:00
|
|
|
static LIST_HEAD(targets);
|
|
|
|
static LIST_HEAD(initiators);
|
|
|
|
static LIST_HEAD(localities);
|
|
|
|
|
|
|
|
static DEFINE_MUTEX(target_lock);
|
2019-03-12 04:56:03 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* 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];
|
|
|
|
|
2019-08-05 22:27:04 +08:00
|
|
|
struct target_cache {
|
|
|
|
struct list_head node;
|
|
|
|
struct node_cache_attrs cache_attrs;
|
|
|
|
};
|
|
|
|
|
2019-03-12 04:56:03 +08:00
|
|
|
struct memory_target {
|
|
|
|
struct list_head node;
|
|
|
|
unsigned int memory_pxm;
|
|
|
|
unsigned int processor_pxm;
|
ACPI: NUMA: HMAT: Register "soft reserved" memory as an "hmem" device
Memory that has been tagged EFI_MEMORY_SP, and has performance
properties described by the ACPI HMAT is expected to have an application
specific consumer.
Those consumers may want 100% of the memory capacity to be reserved from
any usage by the kernel. By default, with this enabling, a platform
device is created to represent this differentiated resource.
The device-dax "hmem" driver claims these devices by default and
provides an mmap interface for the target application. If the
administrator prefers, the hmem resource range can be made available to
the core-mm via the device-dax hotplug facility, kmem, to online the
memory with its own numa node.
This was tested with an emulated HMAT produced by qemu (with the pending
HMAT enabling patches), and "efi_fake_mem=8G@9G:0x40000" on the kernel
command line to mark the memory ranges associated with node2 and node3
as EFI_MEMORY_SP.
qemu numa configuration options:
-numa node,mem=4G,cpus=0-19,nodeid=0
-numa node,mem=4G,cpus=20-39,nodeid=1
-numa node,mem=4G,nodeid=2
-numa node,mem=4G,nodeid=3
-numa dist,src=0,dst=0,val=10
-numa dist,src=0,dst=1,val=21
-numa dist,src=0,dst=2,val=21
-numa dist,src=0,dst=3,val=21
-numa dist,src=1,dst=0,val=21
-numa dist,src=1,dst=1,val=10
-numa dist,src=1,dst=2,val=21
-numa dist,src=1,dst=3,val=21
-numa dist,src=2,dst=0,val=21
-numa dist,src=2,dst=1,val=21
-numa dist,src=2,dst=2,val=10
-numa dist,src=2,dst=3,val=21
-numa dist,src=3,dst=0,val=21
-numa dist,src=3,dst=1,val=21
-numa dist,src=3,dst=2,val=21
-numa dist,src=3,dst=3,val=10
-numa hmat-lb,initiator=0,target=0,hierarchy=memory,data-type=access-latency,base-lat=10,latency=5
-numa hmat-lb,initiator=0,target=0,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=5
-numa hmat-lb,initiator=0,target=1,hierarchy=memory,data-type=access-latency,base-lat=10,latency=10
-numa hmat-lb,initiator=0,target=1,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=10
-numa hmat-lb,initiator=0,target=2,hierarchy=memory,data-type=access-latency,base-lat=10,latency=15
-numa hmat-lb,initiator=0,target=2,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=15
-numa hmat-lb,initiator=0,target=3,hierarchy=memory,data-type=access-latency,base-lat=10,latency=20
-numa hmat-lb,initiator=0,target=3,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=20
-numa hmat-lb,initiator=1,target=0,hierarchy=memory,data-type=access-latency,base-lat=10,latency=10
-numa hmat-lb,initiator=1,target=0,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=10
-numa hmat-lb,initiator=1,target=1,hierarchy=memory,data-type=access-latency,base-lat=10,latency=5
-numa hmat-lb,initiator=1,target=1,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=5
-numa hmat-lb,initiator=1,target=2,hierarchy=memory,data-type=access-latency,base-lat=10,latency=15
-numa hmat-lb,initiator=1,target=2,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=15
-numa hmat-lb,initiator=1,target=3,hierarchy=memory,data-type=access-latency,base-lat=10,latency=20
-numa hmat-lb,initiator=1,target=3,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=20
Result:
[
{
"path":"\/platform\/hmem.1",
"id":1,
"size":"4.00 GiB (4.29 GB)",
"align":2097152,
"devices":[
{
"chardev":"dax1.0",
"size":"4.00 GiB (4.29 GB)"
}
]
},
{
"path":"\/platform\/hmem.0",
"id":0,
"size":"4.00 GiB (4.29 GB)",
"align":2097152,
"devices":[
{
"chardev":"dax0.0",
"size":"4.00 GiB (4.29 GB)"
}
]
}
]
[..]
240000000-43fffffff : Soft Reserved
240000000-33fffffff : hmem.0
240000000-33fffffff : dax0.0
340000000-43fffffff : hmem.1
340000000-43fffffff : dax1.0
Reviewed-by: Dave Hansen <dave.hansen@linux.intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Acked-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2019-11-07 09:43:55 +08:00
|
|
|
struct resource memregions;
|
2020-09-30 22:05:46 +08:00
|
|
|
struct node_hmem_attrs hmem_attrs[2];
|
2019-08-05 22:27:04 +08:00
|
|
|
struct list_head caches;
|
2019-08-05 22:27:05 +08:00
|
|
|
struct node_cache_attrs cache_attrs;
|
|
|
|
bool registered;
|
2019-03-12 04:56:03 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
struct memory_initiator {
|
|
|
|
struct list_head node;
|
|
|
|
unsigned int processor_pxm;
|
2020-09-30 22:05:46 +08:00
|
|
|
bool has_cpu;
|
2019-03-12 04:56:03 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
struct memory_locality {
|
|
|
|
struct list_head node;
|
|
|
|
struct acpi_hmat_locality *hmat_loc;
|
|
|
|
};
|
|
|
|
|
2019-08-05 22:27:05 +08:00
|
|
|
static struct memory_initiator *find_mem_initiator(unsigned int cpu_pxm)
|
2019-03-12 04:56:03 +08:00
|
|
|
{
|
|
|
|
struct memory_initiator *initiator;
|
|
|
|
|
|
|
|
list_for_each_entry(initiator, &initiators, node)
|
|
|
|
if (initiator->processor_pxm == cpu_pxm)
|
|
|
|
return initiator;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2019-08-05 22:27:05 +08:00
|
|
|
static struct memory_target *find_mem_target(unsigned int mem_pxm)
|
2019-03-12 04:56:03 +08:00
|
|
|
{
|
|
|
|
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 *initiator;
|
|
|
|
|
|
|
|
if (pxm_to_node(cpu_pxm) == NUMA_NO_NODE)
|
|
|
|
return;
|
|
|
|
|
|
|
|
initiator = find_mem_initiator(cpu_pxm);
|
|
|
|
if (initiator)
|
|
|
|
return;
|
|
|
|
|
|
|
|
initiator = kzalloc(sizeof(*initiator), GFP_KERNEL);
|
|
|
|
if (!initiator)
|
|
|
|
return;
|
|
|
|
|
|
|
|
initiator->processor_pxm = cpu_pxm;
|
2020-09-30 22:05:46 +08:00
|
|
|
initiator->has_cpu = node_state(pxm_to_node(cpu_pxm), N_CPU);
|
2019-03-12 04:56:03 +08:00
|
|
|
list_add_tail(&initiator->node, &initiators);
|
|
|
|
}
|
|
|
|
|
ACPI: NUMA: HMAT: Register "soft reserved" memory as an "hmem" device
Memory that has been tagged EFI_MEMORY_SP, and has performance
properties described by the ACPI HMAT is expected to have an application
specific consumer.
Those consumers may want 100% of the memory capacity to be reserved from
any usage by the kernel. By default, with this enabling, a platform
device is created to represent this differentiated resource.
The device-dax "hmem" driver claims these devices by default and
provides an mmap interface for the target application. If the
administrator prefers, the hmem resource range can be made available to
the core-mm via the device-dax hotplug facility, kmem, to online the
memory with its own numa node.
This was tested with an emulated HMAT produced by qemu (with the pending
HMAT enabling patches), and "efi_fake_mem=8G@9G:0x40000" on the kernel
command line to mark the memory ranges associated with node2 and node3
as EFI_MEMORY_SP.
qemu numa configuration options:
-numa node,mem=4G,cpus=0-19,nodeid=0
-numa node,mem=4G,cpus=20-39,nodeid=1
-numa node,mem=4G,nodeid=2
-numa node,mem=4G,nodeid=3
-numa dist,src=0,dst=0,val=10
-numa dist,src=0,dst=1,val=21
-numa dist,src=0,dst=2,val=21
-numa dist,src=0,dst=3,val=21
-numa dist,src=1,dst=0,val=21
-numa dist,src=1,dst=1,val=10
-numa dist,src=1,dst=2,val=21
-numa dist,src=1,dst=3,val=21
-numa dist,src=2,dst=0,val=21
-numa dist,src=2,dst=1,val=21
-numa dist,src=2,dst=2,val=10
-numa dist,src=2,dst=3,val=21
-numa dist,src=3,dst=0,val=21
-numa dist,src=3,dst=1,val=21
-numa dist,src=3,dst=2,val=21
-numa dist,src=3,dst=3,val=10
-numa hmat-lb,initiator=0,target=0,hierarchy=memory,data-type=access-latency,base-lat=10,latency=5
-numa hmat-lb,initiator=0,target=0,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=5
-numa hmat-lb,initiator=0,target=1,hierarchy=memory,data-type=access-latency,base-lat=10,latency=10
-numa hmat-lb,initiator=0,target=1,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=10
-numa hmat-lb,initiator=0,target=2,hierarchy=memory,data-type=access-latency,base-lat=10,latency=15
-numa hmat-lb,initiator=0,target=2,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=15
-numa hmat-lb,initiator=0,target=3,hierarchy=memory,data-type=access-latency,base-lat=10,latency=20
-numa hmat-lb,initiator=0,target=3,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=20
-numa hmat-lb,initiator=1,target=0,hierarchy=memory,data-type=access-latency,base-lat=10,latency=10
-numa hmat-lb,initiator=1,target=0,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=10
-numa hmat-lb,initiator=1,target=1,hierarchy=memory,data-type=access-latency,base-lat=10,latency=5
-numa hmat-lb,initiator=1,target=1,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=5
-numa hmat-lb,initiator=1,target=2,hierarchy=memory,data-type=access-latency,base-lat=10,latency=15
-numa hmat-lb,initiator=1,target=2,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=15
-numa hmat-lb,initiator=1,target=3,hierarchy=memory,data-type=access-latency,base-lat=10,latency=20
-numa hmat-lb,initiator=1,target=3,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=20
Result:
[
{
"path":"\/platform\/hmem.1",
"id":1,
"size":"4.00 GiB (4.29 GB)",
"align":2097152,
"devices":[
{
"chardev":"dax1.0",
"size":"4.00 GiB (4.29 GB)"
}
]
},
{
"path":"\/platform\/hmem.0",
"id":0,
"size":"4.00 GiB (4.29 GB)",
"align":2097152,
"devices":[
{
"chardev":"dax0.0",
"size":"4.00 GiB (4.29 GB)"
}
]
}
]
[..]
240000000-43fffffff : Soft Reserved
240000000-33fffffff : hmem.0
240000000-33fffffff : dax0.0
340000000-43fffffff : hmem.1
340000000-43fffffff : dax1.0
Reviewed-by: Dave Hansen <dave.hansen@linux.intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Acked-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2019-11-07 09:43:55 +08:00
|
|
|
static __init void alloc_memory_target(unsigned int mem_pxm,
|
|
|
|
resource_size_t start, resource_size_t len)
|
2019-03-12 04:56:03 +08:00
|
|
|
{
|
|
|
|
struct memory_target *target;
|
|
|
|
|
|
|
|
target = find_mem_target(mem_pxm);
|
ACPI: NUMA: HMAT: Register "soft reserved" memory as an "hmem" device
Memory that has been tagged EFI_MEMORY_SP, and has performance
properties described by the ACPI HMAT is expected to have an application
specific consumer.
Those consumers may want 100% of the memory capacity to be reserved from
any usage by the kernel. By default, with this enabling, a platform
device is created to represent this differentiated resource.
The device-dax "hmem" driver claims these devices by default and
provides an mmap interface for the target application. If the
administrator prefers, the hmem resource range can be made available to
the core-mm via the device-dax hotplug facility, kmem, to online the
memory with its own numa node.
This was tested with an emulated HMAT produced by qemu (with the pending
HMAT enabling patches), and "efi_fake_mem=8G@9G:0x40000" on the kernel
command line to mark the memory ranges associated with node2 and node3
as EFI_MEMORY_SP.
qemu numa configuration options:
-numa node,mem=4G,cpus=0-19,nodeid=0
-numa node,mem=4G,cpus=20-39,nodeid=1
-numa node,mem=4G,nodeid=2
-numa node,mem=4G,nodeid=3
-numa dist,src=0,dst=0,val=10
-numa dist,src=0,dst=1,val=21
-numa dist,src=0,dst=2,val=21
-numa dist,src=0,dst=3,val=21
-numa dist,src=1,dst=0,val=21
-numa dist,src=1,dst=1,val=10
-numa dist,src=1,dst=2,val=21
-numa dist,src=1,dst=3,val=21
-numa dist,src=2,dst=0,val=21
-numa dist,src=2,dst=1,val=21
-numa dist,src=2,dst=2,val=10
-numa dist,src=2,dst=3,val=21
-numa dist,src=3,dst=0,val=21
-numa dist,src=3,dst=1,val=21
-numa dist,src=3,dst=2,val=21
-numa dist,src=3,dst=3,val=10
-numa hmat-lb,initiator=0,target=0,hierarchy=memory,data-type=access-latency,base-lat=10,latency=5
-numa hmat-lb,initiator=0,target=0,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=5
-numa hmat-lb,initiator=0,target=1,hierarchy=memory,data-type=access-latency,base-lat=10,latency=10
-numa hmat-lb,initiator=0,target=1,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=10
-numa hmat-lb,initiator=0,target=2,hierarchy=memory,data-type=access-latency,base-lat=10,latency=15
-numa hmat-lb,initiator=0,target=2,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=15
-numa hmat-lb,initiator=0,target=3,hierarchy=memory,data-type=access-latency,base-lat=10,latency=20
-numa hmat-lb,initiator=0,target=3,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=20
-numa hmat-lb,initiator=1,target=0,hierarchy=memory,data-type=access-latency,base-lat=10,latency=10
-numa hmat-lb,initiator=1,target=0,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=10
-numa hmat-lb,initiator=1,target=1,hierarchy=memory,data-type=access-latency,base-lat=10,latency=5
-numa hmat-lb,initiator=1,target=1,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=5
-numa hmat-lb,initiator=1,target=2,hierarchy=memory,data-type=access-latency,base-lat=10,latency=15
-numa hmat-lb,initiator=1,target=2,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=15
-numa hmat-lb,initiator=1,target=3,hierarchy=memory,data-type=access-latency,base-lat=10,latency=20
-numa hmat-lb,initiator=1,target=3,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=20
Result:
[
{
"path":"\/platform\/hmem.1",
"id":1,
"size":"4.00 GiB (4.29 GB)",
"align":2097152,
"devices":[
{
"chardev":"dax1.0",
"size":"4.00 GiB (4.29 GB)"
}
]
},
{
"path":"\/platform\/hmem.0",
"id":0,
"size":"4.00 GiB (4.29 GB)",
"align":2097152,
"devices":[
{
"chardev":"dax0.0",
"size":"4.00 GiB (4.29 GB)"
}
]
}
]
[..]
240000000-43fffffff : Soft Reserved
240000000-33fffffff : hmem.0
240000000-33fffffff : dax0.0
340000000-43fffffff : hmem.1
340000000-43fffffff : dax1.0
Reviewed-by: Dave Hansen <dave.hansen@linux.intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Acked-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2019-11-07 09:43:55 +08:00
|
|
|
if (!target) {
|
|
|
|
target = kzalloc(sizeof(*target), GFP_KERNEL);
|
|
|
|
if (!target)
|
|
|
|
return;
|
|
|
|
target->memory_pxm = mem_pxm;
|
|
|
|
target->processor_pxm = PXM_INVAL;
|
|
|
|
target->memregions = (struct resource) {
|
|
|
|
.name = "ACPI mem",
|
|
|
|
.start = 0,
|
|
|
|
.end = -1,
|
|
|
|
.flags = IORESOURCE_MEM,
|
|
|
|
};
|
|
|
|
list_add_tail(&target->node, &targets);
|
|
|
|
INIT_LIST_HEAD(&target->caches);
|
|
|
|
}
|
2019-03-12 04:56:03 +08:00
|
|
|
|
ACPI: NUMA: HMAT: Register "soft reserved" memory as an "hmem" device
Memory that has been tagged EFI_MEMORY_SP, and has performance
properties described by the ACPI HMAT is expected to have an application
specific consumer.
Those consumers may want 100% of the memory capacity to be reserved from
any usage by the kernel. By default, with this enabling, a platform
device is created to represent this differentiated resource.
The device-dax "hmem" driver claims these devices by default and
provides an mmap interface for the target application. If the
administrator prefers, the hmem resource range can be made available to
the core-mm via the device-dax hotplug facility, kmem, to online the
memory with its own numa node.
This was tested with an emulated HMAT produced by qemu (with the pending
HMAT enabling patches), and "efi_fake_mem=8G@9G:0x40000" on the kernel
command line to mark the memory ranges associated with node2 and node3
as EFI_MEMORY_SP.
qemu numa configuration options:
-numa node,mem=4G,cpus=0-19,nodeid=0
-numa node,mem=4G,cpus=20-39,nodeid=1
-numa node,mem=4G,nodeid=2
-numa node,mem=4G,nodeid=3
-numa dist,src=0,dst=0,val=10
-numa dist,src=0,dst=1,val=21
-numa dist,src=0,dst=2,val=21
-numa dist,src=0,dst=3,val=21
-numa dist,src=1,dst=0,val=21
-numa dist,src=1,dst=1,val=10
-numa dist,src=1,dst=2,val=21
-numa dist,src=1,dst=3,val=21
-numa dist,src=2,dst=0,val=21
-numa dist,src=2,dst=1,val=21
-numa dist,src=2,dst=2,val=10
-numa dist,src=2,dst=3,val=21
-numa dist,src=3,dst=0,val=21
-numa dist,src=3,dst=1,val=21
-numa dist,src=3,dst=2,val=21
-numa dist,src=3,dst=3,val=10
-numa hmat-lb,initiator=0,target=0,hierarchy=memory,data-type=access-latency,base-lat=10,latency=5
-numa hmat-lb,initiator=0,target=0,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=5
-numa hmat-lb,initiator=0,target=1,hierarchy=memory,data-type=access-latency,base-lat=10,latency=10
-numa hmat-lb,initiator=0,target=1,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=10
-numa hmat-lb,initiator=0,target=2,hierarchy=memory,data-type=access-latency,base-lat=10,latency=15
-numa hmat-lb,initiator=0,target=2,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=15
-numa hmat-lb,initiator=0,target=3,hierarchy=memory,data-type=access-latency,base-lat=10,latency=20
-numa hmat-lb,initiator=0,target=3,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=20
-numa hmat-lb,initiator=1,target=0,hierarchy=memory,data-type=access-latency,base-lat=10,latency=10
-numa hmat-lb,initiator=1,target=0,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=10
-numa hmat-lb,initiator=1,target=1,hierarchy=memory,data-type=access-latency,base-lat=10,latency=5
-numa hmat-lb,initiator=1,target=1,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=5
-numa hmat-lb,initiator=1,target=2,hierarchy=memory,data-type=access-latency,base-lat=10,latency=15
-numa hmat-lb,initiator=1,target=2,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=15
-numa hmat-lb,initiator=1,target=3,hierarchy=memory,data-type=access-latency,base-lat=10,latency=20
-numa hmat-lb,initiator=1,target=3,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=20
Result:
[
{
"path":"\/platform\/hmem.1",
"id":1,
"size":"4.00 GiB (4.29 GB)",
"align":2097152,
"devices":[
{
"chardev":"dax1.0",
"size":"4.00 GiB (4.29 GB)"
}
]
},
{
"path":"\/platform\/hmem.0",
"id":0,
"size":"4.00 GiB (4.29 GB)",
"align":2097152,
"devices":[
{
"chardev":"dax0.0",
"size":"4.00 GiB (4.29 GB)"
}
]
}
]
[..]
240000000-43fffffff : Soft Reserved
240000000-33fffffff : hmem.0
240000000-33fffffff : dax0.0
340000000-43fffffff : hmem.1
340000000-43fffffff : dax1.0
Reviewed-by: Dave Hansen <dave.hansen@linux.intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Acked-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2019-11-07 09:43:55 +08:00
|
|
|
/*
|
|
|
|
* There are potentially multiple ranges per PXM, so record each
|
|
|
|
* in the per-target memregions resource tree.
|
|
|
|
*/
|
|
|
|
if (!__request_region(&target->memregions, start, len, "memory target",
|
|
|
|
IORESOURCE_MEM))
|
|
|
|
pr_warn("failed to reserve %#llx - %#llx in pxm: %d\n",
|
|
|
|
start, start + len, mem_pxm);
|
2019-03-12 04:56:03 +08:00
|
|
|
}
|
|
|
|
|
2019-03-12 04:55:59 +08:00
|
|
|
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 "";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-05 22:27:05 +08:00
|
|
|
static u32 hmat_normalize(u16 entry, u64 base, u8 type)
|
2019-03-12 04:55:59 +08:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2019-08-05 22:27:05 +08:00
|
|
|
static void hmat_update_target_access(struct memory_target *target,
|
2020-09-30 22:05:46 +08:00
|
|
|
u8 type, u32 value, int access)
|
2019-03-12 04:56:03 +08:00
|
|
|
{
|
|
|
|
switch (type) {
|
|
|
|
case ACPI_HMAT_ACCESS_LATENCY:
|
2020-09-30 22:05:46 +08:00
|
|
|
target->hmem_attrs[access].read_latency = value;
|
|
|
|
target->hmem_attrs[access].write_latency = value;
|
2019-03-12 04:56:03 +08:00
|
|
|
break;
|
|
|
|
case ACPI_HMAT_READ_LATENCY:
|
2020-09-30 22:05:46 +08:00
|
|
|
target->hmem_attrs[access].read_latency = value;
|
2019-03-12 04:56:03 +08:00
|
|
|
break;
|
|
|
|
case ACPI_HMAT_WRITE_LATENCY:
|
2020-09-30 22:05:46 +08:00
|
|
|
target->hmem_attrs[access].write_latency = value;
|
2019-03-12 04:56:03 +08:00
|
|
|
break;
|
|
|
|
case ACPI_HMAT_ACCESS_BANDWIDTH:
|
2020-09-30 22:05:46 +08:00
|
|
|
target->hmem_attrs[access].read_bandwidth = value;
|
|
|
|
target->hmem_attrs[access].write_bandwidth = value;
|
2019-03-12 04:56:03 +08:00
|
|
|
break;
|
|
|
|
case ACPI_HMAT_READ_BANDWIDTH:
|
2020-09-30 22:05:46 +08:00
|
|
|
target->hmem_attrs[access].read_bandwidth = value;
|
2019-03-12 04:56:03 +08:00
|
|
|
break;
|
|
|
|
case ACPI_HMAT_WRITE_BANDWIDTH:
|
2020-09-30 22:05:46 +08:00
|
|
|
target->hmem_attrs[access].write_bandwidth = value;
|
2019-03-12 04:56:03 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-12 04:55:59 +08:00
|
|
|
static __init int hmat_parse_locality(union acpi_subtable_headers *header,
|
|
|
|
const unsigned long end)
|
|
|
|
{
|
|
|
|
struct acpi_hmat_locality *hmat_loc = (void *)header;
|
2019-03-12 04:56:03 +08:00
|
|
|
struct memory_target *target;
|
2019-03-12 04:55:59 +08:00
|
|
|
unsigned int init, targ, total_size, ipds, tpds;
|
|
|
|
u32 *inits, *targs, value;
|
|
|
|
u16 *entries;
|
2019-03-12 04:56:03 +08:00
|
|
|
u8 type, mem_hier;
|
2019-03-12 04:55:59 +08:00
|
|
|
|
|
|
|
if (hmat_loc->header.length < sizeof(*hmat_loc)) {
|
2019-10-30 14:34:03 +08:00
|
|
|
pr_notice("HMAT: Unexpected locality header length: %u\n",
|
2019-03-12 04:55:59 +08:00
|
|
|
hmat_loc->header.length);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
type = hmat_loc->data_type;
|
2019-03-12 04:56:03 +08:00
|
|
|
mem_hier = hmat_loc->flags & ACPI_HMAT_MEMORY_HIERARCHY;
|
2019-03-12 04:55:59 +08:00
|
|
|
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) {
|
2019-10-30 14:34:03 +08:00
|
|
|
pr_notice("HMAT: Unexpected locality header length:%u, minimum required:%u\n",
|
2019-03-12 04:55:59 +08:00
|
|
|
hmat_loc->header.length, total_size);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2019-10-30 14:34:03 +08:00
|
|
|
pr_info("HMAT: Locality: Flags:%02x Type:%s Initiator Domains:%u Target Domains:%u Base:%lld\n",
|
2019-03-12 04:55:59 +08:00
|
|
|
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++) {
|
2019-03-12 04:56:03 +08:00
|
|
|
alloc_memory_initiator(inits[init]);
|
2019-03-12 04:55:59 +08:00
|
|
|
for (targ = 0; targ < tpds; targ++) {
|
|
|
|
value = hmat_normalize(entries[init * tpds + targ],
|
|
|
|
hmat_loc->entry_base_unit,
|
|
|
|
type);
|
2019-10-30 14:34:03 +08:00
|
|
|
pr_info(" Initiator-Target[%u-%u]:%u%s\n",
|
2019-03-12 04:55:59 +08:00
|
|
|
inits[init], targs[targ], value,
|
|
|
|
hmat_data_type_suffix(type));
|
2019-03-12 04:56:03 +08:00
|
|
|
|
|
|
|
if (mem_hier == ACPI_HMAT_MEMORY) {
|
|
|
|
target = find_mem_target(targs[targ]);
|
2020-09-30 22:05:46 +08:00
|
|
|
if (target && target->processor_pxm == inits[init]) {
|
|
|
|
hmat_update_target_access(target, type, value, 0);
|
|
|
|
/* If the node has a CPU, update access 1 */
|
|
|
|
if (node_state(pxm_to_node(inits[init]), N_CPU))
|
|
|
|
hmat_update_target_access(target, type, value, 1);
|
|
|
|
}
|
2019-03-12 04:56:03 +08:00
|
|
|
}
|
2019-03-12 04:55:59 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-12 04:56:03 +08:00
|
|
|
if (mem_hier == ACPI_HMAT_MEMORY)
|
|
|
|
hmat_add_locality(hmat_loc);
|
|
|
|
|
2019-03-12 04:55:59 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static __init int hmat_parse_cache(union acpi_subtable_headers *header,
|
|
|
|
const unsigned long end)
|
|
|
|
{
|
|
|
|
struct acpi_hmat_cache *cache = (void *)header;
|
2019-08-05 22:27:04 +08:00
|
|
|
struct memory_target *target;
|
|
|
|
struct target_cache *tcache;
|
2019-03-12 04:55:59 +08:00
|
|
|
u32 attrs;
|
|
|
|
|
|
|
|
if (cache->header.length < sizeof(*cache)) {
|
2019-10-30 14:34:03 +08:00
|
|
|
pr_notice("HMAT: Unexpected cache header length: %u\n",
|
2019-03-12 04:55:59 +08:00
|
|
|
cache->header.length);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
attrs = cache->cache_attributes;
|
2019-10-30 14:34:03 +08:00
|
|
|
pr_info("HMAT: Cache: Domain:%u Size:%llu Attrs:%08x SMBIOS Handles:%d\n",
|
2019-03-12 04:55:59 +08:00
|
|
|
cache->memory_PD, cache->cache_size, attrs,
|
|
|
|
cache->number_of_SMBIOShandles);
|
|
|
|
|
2019-08-05 22:27:04 +08:00
|
|
|
target = find_mem_target(cache->memory_PD);
|
|
|
|
if (!target)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
tcache = kzalloc(sizeof(*tcache), GFP_KERNEL);
|
|
|
|
if (!tcache) {
|
|
|
|
pr_notice_once("Failed to allocate HMAT cache info\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
tcache->cache_attrs.size = cache->cache_size;
|
|
|
|
tcache->cache_attrs.level = (attrs & ACPI_HMAT_CACHE_LEVEL) >> 4;
|
|
|
|
tcache->cache_attrs.line_size = (attrs & ACPI_HMAT_CACHE_LINE_SIZE) >> 16;
|
2019-03-12 04:56:05 +08:00
|
|
|
|
|
|
|
switch ((attrs & ACPI_HMAT_CACHE_ASSOCIATIVITY) >> 8) {
|
|
|
|
case ACPI_HMAT_CA_DIRECT_MAPPED:
|
2019-08-05 22:27:04 +08:00
|
|
|
tcache->cache_attrs.indexing = NODE_CACHE_DIRECT_MAP;
|
2019-03-12 04:56:05 +08:00
|
|
|
break;
|
|
|
|
case ACPI_HMAT_CA_COMPLEX_CACHE_INDEXING:
|
2019-08-05 22:27:04 +08:00
|
|
|
tcache->cache_attrs.indexing = NODE_CACHE_INDEXED;
|
2019-03-12 04:56:05 +08:00
|
|
|
break;
|
|
|
|
case ACPI_HMAT_CA_NONE:
|
|
|
|
default:
|
2019-08-05 22:27:04 +08:00
|
|
|
tcache->cache_attrs.indexing = NODE_CACHE_OTHER;
|
2019-03-12 04:56:05 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch ((attrs & ACPI_HMAT_WRITE_POLICY) >> 12) {
|
|
|
|
case ACPI_HMAT_CP_WB:
|
2019-08-05 22:27:04 +08:00
|
|
|
tcache->cache_attrs.write_policy = NODE_CACHE_WRITE_BACK;
|
2019-03-12 04:56:05 +08:00
|
|
|
break;
|
|
|
|
case ACPI_HMAT_CP_WT:
|
2019-08-05 22:27:04 +08:00
|
|
|
tcache->cache_attrs.write_policy = NODE_CACHE_WRITE_THROUGH;
|
2019-03-12 04:56:05 +08:00
|
|
|
break;
|
|
|
|
case ACPI_HMAT_CP_NONE:
|
|
|
|
default:
|
2019-08-05 22:27:04 +08:00
|
|
|
tcache->cache_attrs.write_policy = NODE_CACHE_WRITE_OTHER;
|
2019-03-12 04:56:05 +08:00
|
|
|
break;
|
|
|
|
}
|
2019-08-05 22:27:04 +08:00
|
|
|
list_add_tail(&tcache->node, &target->caches);
|
2019-03-12 04:56:05 +08:00
|
|
|
|
2019-03-12 04:55:59 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int __init hmat_parse_proximity_domain(union acpi_subtable_headers *header,
|
|
|
|
const unsigned long end)
|
|
|
|
{
|
|
|
|
struct acpi_hmat_proximity_domain *p = (void *)header;
|
2019-04-07 09:12:22 +08:00
|
|
|
struct memory_target *target = NULL;
|
2019-03-12 04:55:59 +08:00
|
|
|
|
|
|
|
if (p->header.length != sizeof(*p)) {
|
2019-10-30 14:34:03 +08:00
|
|
|
pr_notice("HMAT: Unexpected address range header length: %u\n",
|
2019-03-12 04:55:59 +08:00
|
|
|
p->header.length);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (hmat_revision == 1)
|
2019-10-30 14:34:03 +08:00
|
|
|
pr_info("HMAT: Memory (%#llx length %#llx) Flags:%04x Processor Domain:%u Memory Domain:%u\n",
|
2019-03-12 04:55:59 +08:00
|
|
|
p->reserved3, p->reserved4, p->flags, p->processor_PD,
|
|
|
|
p->memory_PD);
|
|
|
|
else
|
2019-10-30 14:34:03 +08:00
|
|
|
pr_info("HMAT: Memory Flags:%04x Processor Domain:%u Memory Domain:%u\n",
|
2019-03-12 04:55:59 +08:00
|
|
|
p->flags, p->processor_PD, p->memory_PD);
|
|
|
|
|
2020-09-30 22:05:45 +08:00
|
|
|
if ((hmat_revision == 1 && p->flags & ACPI_HMAT_MEMORY_PD_VALID) ||
|
|
|
|
hmat_revision > 1) {
|
2019-03-12 04:56:03 +08:00
|
|
|
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;
|
|
|
|
}
|
2019-10-28 17:11:18 +08:00
|
|
|
target->processor_pxm = p->processor_PD;
|
2019-03-12 04:56:03 +08:00
|
|
|
}
|
|
|
|
|
2019-03-12 04:55:59 +08:00
|
|
|
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) {
|
2019-04-18 02:13:10 +08:00
|
|
|
case ACPI_HMAT_TYPE_PROXIMITY:
|
2019-03-12 04:55:59 +08:00
|
|
|
return hmat_parse_proximity_domain(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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-12 04:56:03 +08:00
|
|
|
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;
|
ACPI: NUMA: HMAT: Register "soft reserved" memory as an "hmem" device
Memory that has been tagged EFI_MEMORY_SP, and has performance
properties described by the ACPI HMAT is expected to have an application
specific consumer.
Those consumers may want 100% of the memory capacity to be reserved from
any usage by the kernel. By default, with this enabling, a platform
device is created to represent this differentiated resource.
The device-dax "hmem" driver claims these devices by default and
provides an mmap interface for the target application. If the
administrator prefers, the hmem resource range can be made available to
the core-mm via the device-dax hotplug facility, kmem, to online the
memory with its own numa node.
This was tested with an emulated HMAT produced by qemu (with the pending
HMAT enabling patches), and "efi_fake_mem=8G@9G:0x40000" on the kernel
command line to mark the memory ranges associated with node2 and node3
as EFI_MEMORY_SP.
qemu numa configuration options:
-numa node,mem=4G,cpus=0-19,nodeid=0
-numa node,mem=4G,cpus=20-39,nodeid=1
-numa node,mem=4G,nodeid=2
-numa node,mem=4G,nodeid=3
-numa dist,src=0,dst=0,val=10
-numa dist,src=0,dst=1,val=21
-numa dist,src=0,dst=2,val=21
-numa dist,src=0,dst=3,val=21
-numa dist,src=1,dst=0,val=21
-numa dist,src=1,dst=1,val=10
-numa dist,src=1,dst=2,val=21
-numa dist,src=1,dst=3,val=21
-numa dist,src=2,dst=0,val=21
-numa dist,src=2,dst=1,val=21
-numa dist,src=2,dst=2,val=10
-numa dist,src=2,dst=3,val=21
-numa dist,src=3,dst=0,val=21
-numa dist,src=3,dst=1,val=21
-numa dist,src=3,dst=2,val=21
-numa dist,src=3,dst=3,val=10
-numa hmat-lb,initiator=0,target=0,hierarchy=memory,data-type=access-latency,base-lat=10,latency=5
-numa hmat-lb,initiator=0,target=0,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=5
-numa hmat-lb,initiator=0,target=1,hierarchy=memory,data-type=access-latency,base-lat=10,latency=10
-numa hmat-lb,initiator=0,target=1,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=10
-numa hmat-lb,initiator=0,target=2,hierarchy=memory,data-type=access-latency,base-lat=10,latency=15
-numa hmat-lb,initiator=0,target=2,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=15
-numa hmat-lb,initiator=0,target=3,hierarchy=memory,data-type=access-latency,base-lat=10,latency=20
-numa hmat-lb,initiator=0,target=3,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=20
-numa hmat-lb,initiator=1,target=0,hierarchy=memory,data-type=access-latency,base-lat=10,latency=10
-numa hmat-lb,initiator=1,target=0,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=10
-numa hmat-lb,initiator=1,target=1,hierarchy=memory,data-type=access-latency,base-lat=10,latency=5
-numa hmat-lb,initiator=1,target=1,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=5
-numa hmat-lb,initiator=1,target=2,hierarchy=memory,data-type=access-latency,base-lat=10,latency=15
-numa hmat-lb,initiator=1,target=2,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=15
-numa hmat-lb,initiator=1,target=3,hierarchy=memory,data-type=access-latency,base-lat=10,latency=20
-numa hmat-lb,initiator=1,target=3,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=20
Result:
[
{
"path":"\/platform\/hmem.1",
"id":1,
"size":"4.00 GiB (4.29 GB)",
"align":2097152,
"devices":[
{
"chardev":"dax1.0",
"size":"4.00 GiB (4.29 GB)"
}
]
},
{
"path":"\/platform\/hmem.0",
"id":0,
"size":"4.00 GiB (4.29 GB)",
"align":2097152,
"devices":[
{
"chardev":"dax0.0",
"size":"4.00 GiB (4.29 GB)"
}
]
}
]
[..]
240000000-43fffffff : Soft Reserved
240000000-33fffffff : hmem.0
240000000-33fffffff : dax0.0
340000000-43fffffff : hmem.1
340000000-43fffffff : dax1.0
Reviewed-by: Dave Hansen <dave.hansen@linux.intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Acked-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2019-11-07 09:43:55 +08:00
|
|
|
alloc_memory_target(ma->proximity_domain, ma->base_address, ma->length);
|
2019-03-12 04:56:03 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-08-05 22:27:05 +08:00
|
|
|
static u32 hmat_initiator_perf(struct memory_target *target,
|
2019-03-12 04:56:03 +08:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2019-08-05 22:27:05 +08:00
|
|
|
static bool hmat_update_best(u8 type, u32 value, u32 *best)
|
2019-03-12 04:56:03 +08:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2021-04-09 02:28:34 +08:00
|
|
|
static int initiator_cmp(void *priv, const struct list_head *a,
|
|
|
|
const struct list_head *b)
|
2019-03-12 04:56:03 +08:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2019-08-05 22:27:05 +08:00
|
|
|
static void hmat_register_target_initiators(struct memory_target *target)
|
2019-03-12 04:56:03 +08:00
|
|
|
{
|
|
|
|
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;
|
2020-09-30 22:05:46 +08:00
|
|
|
bool access0done = false;
|
2019-03-12 04:56:03 +08:00
|
|
|
int i;
|
|
|
|
|
|
|
|
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 attributes and
|
|
|
|
* register all initiators that match.
|
|
|
|
*/
|
|
|
|
if (target->processor_pxm != PXM_INVAL) {
|
|
|
|
cpu_nid = pxm_to_node(target->processor_pxm);
|
|
|
|
register_memory_node_under_compute_node(mem_nid, cpu_nid, 0);
|
2020-09-30 22:05:46 +08:00
|
|
|
access0done = true;
|
|
|
|
if (node_state(cpu_nid, N_CPU)) {
|
|
|
|
register_memory_node_under_compute_node(mem_nid, cpu_nid, 1);
|
|
|
|
return;
|
|
|
|
}
|
2019-03-12 04:56:03 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (list_empty(&localities))
|
|
|
|
return;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We need the initiator list 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);
|
2020-09-30 22:05:46 +08:00
|
|
|
if (!access0done) {
|
|
|
|
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, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Access 1 ignores Generic Initiators */
|
|
|
|
bitmap_zero(p_nodes, MAX_NUMNODES);
|
|
|
|
list_sort(p_nodes, &initiators, initiator_cmp);
|
|
|
|
best = 0;
|
2019-03-12 04:56:03 +08:00
|
|
|
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;
|
|
|
|
|
2020-09-30 22:05:46 +08:00
|
|
|
if (!initiator->has_cpu) {
|
|
|
|
clear_bit(initiator->processor_pxm, p_nodes);
|
|
|
|
continue;
|
|
|
|
}
|
2019-03-12 04:56:03 +08:00
|
|
|
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)
|
2020-09-30 22:05:46 +08:00
|
|
|
hmat_update_target_access(target, loc->hmat_loc->data_type, best, 1);
|
2019-03-12 04:56:03 +08:00
|
|
|
}
|
|
|
|
for_each_set_bit(i, p_nodes, MAX_NUMNODES) {
|
|
|
|
cpu_nid = pxm_to_node(i);
|
2020-09-30 22:05:46 +08:00
|
|
|
register_memory_node_under_compute_node(mem_nid, cpu_nid, 1);
|
2019-03-12 04:56:03 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-05 22:27:05 +08:00
|
|
|
static void hmat_register_target_cache(struct memory_target *target)
|
2019-08-05 22:27:04 +08:00
|
|
|
{
|
|
|
|
unsigned mem_nid = pxm_to_node(target->memory_pxm);
|
|
|
|
struct target_cache *tcache;
|
|
|
|
|
|
|
|
list_for_each_entry(tcache, &target->caches, node)
|
|
|
|
node_add_cache(mem_nid, &tcache->cache_attrs);
|
|
|
|
}
|
|
|
|
|
2020-09-30 22:05:46 +08:00
|
|
|
static void hmat_register_target_perf(struct memory_target *target, int access)
|
2019-03-12 04:56:04 +08:00
|
|
|
{
|
|
|
|
unsigned mem_nid = pxm_to_node(target->memory_pxm);
|
2020-09-30 22:05:46 +08:00
|
|
|
node_set_perf_attrs(mem_nid, &target->hmem_attrs[access], access);
|
2019-03-12 04:56:04 +08:00
|
|
|
}
|
|
|
|
|
2019-11-12 05:34:26 +08:00
|
|
|
static void hmat_register_target_devices(struct memory_target *target)
|
ACPI: NUMA: HMAT: Register "soft reserved" memory as an "hmem" device
Memory that has been tagged EFI_MEMORY_SP, and has performance
properties described by the ACPI HMAT is expected to have an application
specific consumer.
Those consumers may want 100% of the memory capacity to be reserved from
any usage by the kernel. By default, with this enabling, a platform
device is created to represent this differentiated resource.
The device-dax "hmem" driver claims these devices by default and
provides an mmap interface for the target application. If the
administrator prefers, the hmem resource range can be made available to
the core-mm via the device-dax hotplug facility, kmem, to online the
memory with its own numa node.
This was tested with an emulated HMAT produced by qemu (with the pending
HMAT enabling patches), and "efi_fake_mem=8G@9G:0x40000" on the kernel
command line to mark the memory ranges associated with node2 and node3
as EFI_MEMORY_SP.
qemu numa configuration options:
-numa node,mem=4G,cpus=0-19,nodeid=0
-numa node,mem=4G,cpus=20-39,nodeid=1
-numa node,mem=4G,nodeid=2
-numa node,mem=4G,nodeid=3
-numa dist,src=0,dst=0,val=10
-numa dist,src=0,dst=1,val=21
-numa dist,src=0,dst=2,val=21
-numa dist,src=0,dst=3,val=21
-numa dist,src=1,dst=0,val=21
-numa dist,src=1,dst=1,val=10
-numa dist,src=1,dst=2,val=21
-numa dist,src=1,dst=3,val=21
-numa dist,src=2,dst=0,val=21
-numa dist,src=2,dst=1,val=21
-numa dist,src=2,dst=2,val=10
-numa dist,src=2,dst=3,val=21
-numa dist,src=3,dst=0,val=21
-numa dist,src=3,dst=1,val=21
-numa dist,src=3,dst=2,val=21
-numa dist,src=3,dst=3,val=10
-numa hmat-lb,initiator=0,target=0,hierarchy=memory,data-type=access-latency,base-lat=10,latency=5
-numa hmat-lb,initiator=0,target=0,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=5
-numa hmat-lb,initiator=0,target=1,hierarchy=memory,data-type=access-latency,base-lat=10,latency=10
-numa hmat-lb,initiator=0,target=1,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=10
-numa hmat-lb,initiator=0,target=2,hierarchy=memory,data-type=access-latency,base-lat=10,latency=15
-numa hmat-lb,initiator=0,target=2,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=15
-numa hmat-lb,initiator=0,target=3,hierarchy=memory,data-type=access-latency,base-lat=10,latency=20
-numa hmat-lb,initiator=0,target=3,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=20
-numa hmat-lb,initiator=1,target=0,hierarchy=memory,data-type=access-latency,base-lat=10,latency=10
-numa hmat-lb,initiator=1,target=0,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=10
-numa hmat-lb,initiator=1,target=1,hierarchy=memory,data-type=access-latency,base-lat=10,latency=5
-numa hmat-lb,initiator=1,target=1,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=5
-numa hmat-lb,initiator=1,target=2,hierarchy=memory,data-type=access-latency,base-lat=10,latency=15
-numa hmat-lb,initiator=1,target=2,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=15
-numa hmat-lb,initiator=1,target=3,hierarchy=memory,data-type=access-latency,base-lat=10,latency=20
-numa hmat-lb,initiator=1,target=3,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=20
Result:
[
{
"path":"\/platform\/hmem.1",
"id":1,
"size":"4.00 GiB (4.29 GB)",
"align":2097152,
"devices":[
{
"chardev":"dax1.0",
"size":"4.00 GiB (4.29 GB)"
}
]
},
{
"path":"\/platform\/hmem.0",
"id":0,
"size":"4.00 GiB (4.29 GB)",
"align":2097152,
"devices":[
{
"chardev":"dax0.0",
"size":"4.00 GiB (4.29 GB)"
}
]
}
]
[..]
240000000-43fffffff : Soft Reserved
240000000-33fffffff : hmem.0
240000000-33fffffff : dax0.0
340000000-43fffffff : hmem.1
340000000-43fffffff : dax1.0
Reviewed-by: Dave Hansen <dave.hansen@linux.intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Acked-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2019-11-07 09:43:55 +08:00
|
|
|
{
|
|
|
|
struct resource *res;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Do not bother creating devices if no driver is available to
|
|
|
|
* consume them.
|
|
|
|
*/
|
|
|
|
if (!IS_ENABLED(CONFIG_DEV_DAX_HMEM))
|
|
|
|
return;
|
|
|
|
|
2020-10-14 07:49:13 +08:00
|
|
|
for (res = target->memregions.child; res; res = res->sibling) {
|
ACPI updates for 5.10-rc1
- Add support for generic initiator-only proximity domains to
the ACPI NUMA code and the architectures using it (Jonathan
Cameron).
- Clean up some non-ACPICA code referring to debug facilities from
ACPICA that are not actually used in there (Hanjun Guo).
- Add new DPTF driver for the PCH FIVR participant (Srinivas
Pandruvada).
- Reduce overhead related to accessing GPE registers in ACPICA and
the OS interface layer and make it possible to access GPE registers
using logical addresses if they are memory-mapped (Rafael Wysocki).
- Update the ACPICA code in the kernel to upstream revision 20200925
including changes as follows:
* Add predefined names from the SMBus sepcification (Bob Moore).
* Update acpi_help UUID list (Bob Moore).
* Return exceptions for string-to-integer conversions in iASL (Bob
Moore).
* Add a new "ALL <NameSeg>" debugger command (Bob Moore).
* Add support for 64 bit risc-v compilation (Colin Ian King).
* Do assorted cleanups (Bob Moore, Colin Ian King, Randy Dunlap).
- Add new ACPI backlight whitelist entry for HP 635 Notebook (Alex
Hung).
- Move TPS68470 OpRegion driver to drivers/acpi/pmic/ and split out
Kconfig and Makefile specific for ACPI PMIC (Andy Shevchenko).
- Clean up the ACPI SoC driver for AMD SoCs (Hanjun Guo).
- Add missing config_item_put() to fix refcount leak (Hanjun Guo).
- Drop lefrover field from struct acpi_memory_device (Hanjun Guo).
- Make the ACPI extlog driver check for RDMSR failures (Ben
Hutchings).
- Fix handling of lid state changes in the ACPI button driver when
input device is closed (Dmitry Torokhov).
- Fix several assorted build issues (Barnabás Pőcze, John Garry,
Nathan Chancellor, Tian Tao).
- Drop unused inline functions and reduce code duplication by using
kobj_to_dev() in the NFIT parsing code (YueHaibing, Wang Qing).
- Serialize tools/power/acpi Makefile (Thomas Renninger).
-----BEGIN PGP SIGNATURE-----
iQJGBAABCAAwFiEE4fcc61cGeeHD/fCwgsRv/nhiVHEFAl+F4IkSHHJqd0Byand5
c29ja2kubmV0AAoJEILEb/54YlRx1gIQAIZrt09fquEIZhYulGZAkuYhSX2U/DZt
poow5+TiGk36JNHlbZS19kZ3F0tJ1wA6CKSfF/bYyULxL+gYaUjdLXzv2kArTSAj
nzDXQ2CystpySZI/sEkl4QjsMg0xuZlBhlnCfNHzJw049TgdsJHnxMkJXb8T90A+
l2JKm2OpBkNvQGNpwd3djLg8xSDnHUmuevsWZPHDp92/fLMF9DUBk8dVuEwa0ndF
hAUpWm+EL1tJQnhNwtfV/Akd9Ypqgk/7ROFWFHGDtHMZGnBjpyXZw68vHMX7SL6N
Ej90GWGPHSJs/7Fsg4Hiaxxcph9WFNLPcpck5lVAMIrNHMKANjqQzCsmHavV/WTG
STC9/qwJauA1EOjovlmlCFHctjKE/ya6Hm299WTlfBqB+Lu1L3oMR2CC+Uj0YfyG
sv3264rJCsaSw610iwQOG807qHENopASO2q5DuKG0E9JpcaBUwn1N4qP5svvQciq
4aA8Ma6xM/QHCO4CS0Se9C0+WSVtxWwOUichRqQmU4E6u1sXvKJxTeWo79rV7PAh
L6BwoOxBLabEiyzpi6HPGs6DoKj/N6tOQenBh4ibdwpAwMtq7hIlBFa0bp19c2wT
vx8F2Raa8vbQ2zZ1QEiPZnPLJUoy2DgaCtKJ6E0FTDXNs3VFlWgyhIUlIRqk5BS9
OnAwVAUrTMkJ
=feLU
-----END PGP SIGNATURE-----
Merge tag 'acpi-5.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull ACPI updates from Rafael Wysocki:
"These add support for generic initiator-only proximity domains to the
ACPI NUMA code and the architectures using it, clean up some
non-ACPICA code referring to debug facilities from ACPICA, reduce the
overhead related to accessing GPE registers, add a new DPTF (Dynamic
Power and Thermal Framework) participant driver, update the ACPICA
code in the kernel to upstream revision 20200925, add a new ACPI
backlight whitelist entry, fix a few assorted issues and clean up some
code.
Specifics:
- Add support for generic initiator-only proximity domains to the
ACPI NUMA code and the architectures using it (Jonathan Cameron)
- Clean up some non-ACPICA code referring to debug facilities from
ACPICA that are not actually used in there (Hanjun Guo)
- Add new DPTF driver for the PCH FIVR participant (Srinivas
Pandruvada)
- Reduce overhead related to accessing GPE registers in ACPICA and
the OS interface layer and make it possible to access GPE registers
using logical addresses if they are memory-mapped (Rafael Wysocki)
- Update the ACPICA code in the kernel to upstream revision 20200925
including changes as follows:
+ Add predefined names from the SMBus sepcification (Bob Moore)
+ Update acpi_help UUID list (Bob Moore)
+ Return exceptions for string-to-integer conversions in iASL (Bob
Moore)
+ Add a new "ALL <NameSeg>" debugger command (Bob Moore)
+ Add support for 64 bit risc-v compilation (Colin Ian King)
+ Do assorted cleanups (Bob Moore, Colin Ian King, Randy Dunlap)
- Add new ACPI backlight whitelist entry for HP 635 Notebook (Alex
Hung)
- Move TPS68470 OpRegion driver to drivers/acpi/pmic/ and split out
Kconfig and Makefile specific for ACPI PMIC (Andy Shevchenko)
- Clean up the ACPI SoC driver for AMD SoCs (Hanjun Guo)
- Add missing config_item_put() to fix refcount leak (Hanjun Guo)
- Drop lefrover field from struct acpi_memory_device (Hanjun Guo)
- Make the ACPI extlog driver check for RDMSR failures (Ben
Hutchings)
- Fix handling of lid state changes in the ACPI button driver when
input device is closed (Dmitry Torokhov)
- Fix several assorted build issues (Barnabás Pőcze, John Garry,
Nathan Chancellor, Tian Tao)
- Drop unused inline functions and reduce code duplication by using
kobj_to_dev() in the NFIT parsing code (YueHaibing, Wang Qing)
- Serialize tools/power/acpi Makefile (Thomas Renninger)"
* tag 'acpi-5.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (64 commits)
ACPICA: Update version to 20200925 Version 20200925
ACPICA: Remove unnecessary semicolon
ACPICA: Debugger: Add a new command: "ALL <NameSeg>"
ACPICA: iASL: Return exceptions for string-to-integer conversions
ACPICA: acpi_help: Update UUID list
ACPICA: Add predefined names found in the SMBus sepcification
ACPICA: Tree-wide: fix various typos and spelling mistakes
ACPICA: Drop the repeated word "an" in a comment
ACPICA: Add support for 64 bit risc-v compilation
ACPI: button: fix handling lid state changes when input device closed
tools/power/acpi: Serialize Makefile
ACPI: scan: Replace ACPI_DEBUG_PRINT() with pr_debug()
ACPI: memhotplug: Remove 'state' from struct acpi_memory_device
ACPI / extlog: Check for RDMSR failure
ACPI: Make acpi_evaluate_dsm() prototype consistent
docs: mm: numaperf.rst Add brief description for access class 1.
node: Add access1 class to represent CPU to memory characteristics
ACPI: HMAT: Fix handling of changes from ACPI 6.2 to ACPI 6.3
ACPI: Let ACPI know we support Generic Initiator Affinity Structures
x86: Support Generic Initiator only proximity domains
...
2020-10-15 02:42:04 +08:00
|
|
|
int target_nid = pxm_to_node(target->memory_pxm);
|
2020-10-14 07:49:13 +08:00
|
|
|
|
|
|
|
hmem_register_device(target_nid, res);
|
|
|
|
}
|
ACPI: NUMA: HMAT: Register "soft reserved" memory as an "hmem" device
Memory that has been tagged EFI_MEMORY_SP, and has performance
properties described by the ACPI HMAT is expected to have an application
specific consumer.
Those consumers may want 100% of the memory capacity to be reserved from
any usage by the kernel. By default, with this enabling, a platform
device is created to represent this differentiated resource.
The device-dax "hmem" driver claims these devices by default and
provides an mmap interface for the target application. If the
administrator prefers, the hmem resource range can be made available to
the core-mm via the device-dax hotplug facility, kmem, to online the
memory with its own numa node.
This was tested with an emulated HMAT produced by qemu (with the pending
HMAT enabling patches), and "efi_fake_mem=8G@9G:0x40000" on the kernel
command line to mark the memory ranges associated with node2 and node3
as EFI_MEMORY_SP.
qemu numa configuration options:
-numa node,mem=4G,cpus=0-19,nodeid=0
-numa node,mem=4G,cpus=20-39,nodeid=1
-numa node,mem=4G,nodeid=2
-numa node,mem=4G,nodeid=3
-numa dist,src=0,dst=0,val=10
-numa dist,src=0,dst=1,val=21
-numa dist,src=0,dst=2,val=21
-numa dist,src=0,dst=3,val=21
-numa dist,src=1,dst=0,val=21
-numa dist,src=1,dst=1,val=10
-numa dist,src=1,dst=2,val=21
-numa dist,src=1,dst=3,val=21
-numa dist,src=2,dst=0,val=21
-numa dist,src=2,dst=1,val=21
-numa dist,src=2,dst=2,val=10
-numa dist,src=2,dst=3,val=21
-numa dist,src=3,dst=0,val=21
-numa dist,src=3,dst=1,val=21
-numa dist,src=3,dst=2,val=21
-numa dist,src=3,dst=3,val=10
-numa hmat-lb,initiator=0,target=0,hierarchy=memory,data-type=access-latency,base-lat=10,latency=5
-numa hmat-lb,initiator=0,target=0,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=5
-numa hmat-lb,initiator=0,target=1,hierarchy=memory,data-type=access-latency,base-lat=10,latency=10
-numa hmat-lb,initiator=0,target=1,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=10
-numa hmat-lb,initiator=0,target=2,hierarchy=memory,data-type=access-latency,base-lat=10,latency=15
-numa hmat-lb,initiator=0,target=2,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=15
-numa hmat-lb,initiator=0,target=3,hierarchy=memory,data-type=access-latency,base-lat=10,latency=20
-numa hmat-lb,initiator=0,target=3,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=20
-numa hmat-lb,initiator=1,target=0,hierarchy=memory,data-type=access-latency,base-lat=10,latency=10
-numa hmat-lb,initiator=1,target=0,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=10
-numa hmat-lb,initiator=1,target=1,hierarchy=memory,data-type=access-latency,base-lat=10,latency=5
-numa hmat-lb,initiator=1,target=1,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=5
-numa hmat-lb,initiator=1,target=2,hierarchy=memory,data-type=access-latency,base-lat=10,latency=15
-numa hmat-lb,initiator=1,target=2,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=15
-numa hmat-lb,initiator=1,target=3,hierarchy=memory,data-type=access-latency,base-lat=10,latency=20
-numa hmat-lb,initiator=1,target=3,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=20
Result:
[
{
"path":"\/platform\/hmem.1",
"id":1,
"size":"4.00 GiB (4.29 GB)",
"align":2097152,
"devices":[
{
"chardev":"dax1.0",
"size":"4.00 GiB (4.29 GB)"
}
]
},
{
"path":"\/platform\/hmem.0",
"id":0,
"size":"4.00 GiB (4.29 GB)",
"align":2097152,
"devices":[
{
"chardev":"dax0.0",
"size":"4.00 GiB (4.29 GB)"
}
]
}
]
[..]
240000000-43fffffff : Soft Reserved
240000000-33fffffff : hmem.0
240000000-33fffffff : dax0.0
340000000-43fffffff : hmem.1
340000000-43fffffff : dax1.0
Reviewed-by: Dave Hansen <dave.hansen@linux.intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Acked-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2019-11-07 09:43:55 +08:00
|
|
|
}
|
|
|
|
|
2019-08-05 22:27:05 +08:00
|
|
|
static void hmat_register_target(struct memory_target *target)
|
2019-08-05 22:27:04 +08:00
|
|
|
{
|
2019-08-05 22:27:06 +08:00
|
|
|
int nid = pxm_to_node(target->memory_pxm);
|
|
|
|
|
ACPI: NUMA: HMAT: Register "soft reserved" memory as an "hmem" device
Memory that has been tagged EFI_MEMORY_SP, and has performance
properties described by the ACPI HMAT is expected to have an application
specific consumer.
Those consumers may want 100% of the memory capacity to be reserved from
any usage by the kernel. By default, with this enabling, a platform
device is created to represent this differentiated resource.
The device-dax "hmem" driver claims these devices by default and
provides an mmap interface for the target application. If the
administrator prefers, the hmem resource range can be made available to
the core-mm via the device-dax hotplug facility, kmem, to online the
memory with its own numa node.
This was tested with an emulated HMAT produced by qemu (with the pending
HMAT enabling patches), and "efi_fake_mem=8G@9G:0x40000" on the kernel
command line to mark the memory ranges associated with node2 and node3
as EFI_MEMORY_SP.
qemu numa configuration options:
-numa node,mem=4G,cpus=0-19,nodeid=0
-numa node,mem=4G,cpus=20-39,nodeid=1
-numa node,mem=4G,nodeid=2
-numa node,mem=4G,nodeid=3
-numa dist,src=0,dst=0,val=10
-numa dist,src=0,dst=1,val=21
-numa dist,src=0,dst=2,val=21
-numa dist,src=0,dst=3,val=21
-numa dist,src=1,dst=0,val=21
-numa dist,src=1,dst=1,val=10
-numa dist,src=1,dst=2,val=21
-numa dist,src=1,dst=3,val=21
-numa dist,src=2,dst=0,val=21
-numa dist,src=2,dst=1,val=21
-numa dist,src=2,dst=2,val=10
-numa dist,src=2,dst=3,val=21
-numa dist,src=3,dst=0,val=21
-numa dist,src=3,dst=1,val=21
-numa dist,src=3,dst=2,val=21
-numa dist,src=3,dst=3,val=10
-numa hmat-lb,initiator=0,target=0,hierarchy=memory,data-type=access-latency,base-lat=10,latency=5
-numa hmat-lb,initiator=0,target=0,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=5
-numa hmat-lb,initiator=0,target=1,hierarchy=memory,data-type=access-latency,base-lat=10,latency=10
-numa hmat-lb,initiator=0,target=1,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=10
-numa hmat-lb,initiator=0,target=2,hierarchy=memory,data-type=access-latency,base-lat=10,latency=15
-numa hmat-lb,initiator=0,target=2,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=15
-numa hmat-lb,initiator=0,target=3,hierarchy=memory,data-type=access-latency,base-lat=10,latency=20
-numa hmat-lb,initiator=0,target=3,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=20
-numa hmat-lb,initiator=1,target=0,hierarchy=memory,data-type=access-latency,base-lat=10,latency=10
-numa hmat-lb,initiator=1,target=0,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=10
-numa hmat-lb,initiator=1,target=1,hierarchy=memory,data-type=access-latency,base-lat=10,latency=5
-numa hmat-lb,initiator=1,target=1,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=5
-numa hmat-lb,initiator=1,target=2,hierarchy=memory,data-type=access-latency,base-lat=10,latency=15
-numa hmat-lb,initiator=1,target=2,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=15
-numa hmat-lb,initiator=1,target=3,hierarchy=memory,data-type=access-latency,base-lat=10,latency=20
-numa hmat-lb,initiator=1,target=3,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=20
Result:
[
{
"path":"\/platform\/hmem.1",
"id":1,
"size":"4.00 GiB (4.29 GB)",
"align":2097152,
"devices":[
{
"chardev":"dax1.0",
"size":"4.00 GiB (4.29 GB)"
}
]
},
{
"path":"\/platform\/hmem.0",
"id":0,
"size":"4.00 GiB (4.29 GB)",
"align":2097152,
"devices":[
{
"chardev":"dax0.0",
"size":"4.00 GiB (4.29 GB)"
}
]
}
]
[..]
240000000-43fffffff : Soft Reserved
240000000-33fffffff : hmem.0
240000000-33fffffff : dax0.0
340000000-43fffffff : hmem.1
340000000-43fffffff : dax1.0
Reviewed-by: Dave Hansen <dave.hansen@linux.intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Acked-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2019-11-07 09:43:55 +08:00
|
|
|
/*
|
|
|
|
* Devices may belong to either an offline or online
|
|
|
|
* node, so unconditionally add them.
|
|
|
|
*/
|
|
|
|
hmat_register_target_devices(target);
|
|
|
|
|
2019-08-05 22:27:06 +08:00
|
|
|
/*
|
|
|
|
* Skip offline nodes. This can happen when memory
|
|
|
|
* marked EFI_MEMORY_SP, "specific purpose", is applied
|
2021-03-13 09:55:35 +08:00
|
|
|
* to all the memory in a proximity domain leading to
|
2019-08-05 22:27:06 +08:00
|
|
|
* the node being marked offline / unplugged, or if
|
|
|
|
* memory-only "hotplug" node is offline.
|
|
|
|
*/
|
|
|
|
if (nid == NUMA_NO_NODE || !node_online(nid))
|
2019-08-05 22:27:04 +08:00
|
|
|
return;
|
|
|
|
|
2019-08-05 22:27:05 +08:00
|
|
|
mutex_lock(&target_lock);
|
|
|
|
if (!target->registered) {
|
|
|
|
hmat_register_target_initiators(target);
|
|
|
|
hmat_register_target_cache(target);
|
2020-09-30 22:05:46 +08:00
|
|
|
hmat_register_target_perf(target, 0);
|
|
|
|
hmat_register_target_perf(target, 1);
|
2019-08-05 22:27:05 +08:00
|
|
|
target->registered = true;
|
|
|
|
}
|
|
|
|
mutex_unlock(&target_lock);
|
2019-08-05 22:27:04 +08:00
|
|
|
}
|
|
|
|
|
2019-08-05 22:27:05 +08:00
|
|
|
static void hmat_register_targets(void)
|
2019-03-12 04:56:03 +08:00
|
|
|
{
|
|
|
|
struct memory_target *target;
|
|
|
|
|
2019-08-05 22:27:04 +08:00
|
|
|
list_for_each_entry(target, &targets, node)
|
|
|
|
hmat_register_target(target);
|
2019-03-12 04:56:03 +08:00
|
|
|
}
|
|
|
|
|
2019-08-05 22:27:05 +08:00
|
|
|
static int hmat_callback(struct notifier_block *self,
|
|
|
|
unsigned long action, void *arg)
|
|
|
|
{
|
|
|
|
struct memory_target *target;
|
|
|
|
struct memory_notify *mnb = arg;
|
|
|
|
int pxm, nid = mnb->status_change_nid;
|
|
|
|
|
|
|
|
if (nid == NUMA_NO_NODE || action != MEM_ONLINE)
|
|
|
|
return NOTIFY_OK;
|
|
|
|
|
|
|
|
pxm = node_to_pxm(nid);
|
|
|
|
target = find_mem_target(pxm);
|
|
|
|
if (!target)
|
|
|
|
return NOTIFY_OK;
|
|
|
|
|
|
|
|
hmat_register_target(target);
|
|
|
|
return NOTIFY_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct notifier_block hmat_callback_nb = {
|
|
|
|
.notifier_call = hmat_callback,
|
|
|
|
.priority = 2,
|
|
|
|
};
|
|
|
|
|
2019-03-12 04:56:03 +08:00
|
|
|
static __init void hmat_free_structures(void)
|
|
|
|
{
|
|
|
|
struct memory_target *target, *tnext;
|
|
|
|
struct memory_locality *loc, *lnext;
|
|
|
|
struct memory_initiator *initiator, *inext;
|
2019-08-05 22:27:04 +08:00
|
|
|
struct target_cache *tcache, *cnext;
|
2019-03-12 04:56:03 +08:00
|
|
|
|
|
|
|
list_for_each_entry_safe(target, tnext, &targets, node) {
|
ACPI: NUMA: HMAT: Register "soft reserved" memory as an "hmem" device
Memory that has been tagged EFI_MEMORY_SP, and has performance
properties described by the ACPI HMAT is expected to have an application
specific consumer.
Those consumers may want 100% of the memory capacity to be reserved from
any usage by the kernel. By default, with this enabling, a platform
device is created to represent this differentiated resource.
The device-dax "hmem" driver claims these devices by default and
provides an mmap interface for the target application. If the
administrator prefers, the hmem resource range can be made available to
the core-mm via the device-dax hotplug facility, kmem, to online the
memory with its own numa node.
This was tested with an emulated HMAT produced by qemu (with the pending
HMAT enabling patches), and "efi_fake_mem=8G@9G:0x40000" on the kernel
command line to mark the memory ranges associated with node2 and node3
as EFI_MEMORY_SP.
qemu numa configuration options:
-numa node,mem=4G,cpus=0-19,nodeid=0
-numa node,mem=4G,cpus=20-39,nodeid=1
-numa node,mem=4G,nodeid=2
-numa node,mem=4G,nodeid=3
-numa dist,src=0,dst=0,val=10
-numa dist,src=0,dst=1,val=21
-numa dist,src=0,dst=2,val=21
-numa dist,src=0,dst=3,val=21
-numa dist,src=1,dst=0,val=21
-numa dist,src=1,dst=1,val=10
-numa dist,src=1,dst=2,val=21
-numa dist,src=1,dst=3,val=21
-numa dist,src=2,dst=0,val=21
-numa dist,src=2,dst=1,val=21
-numa dist,src=2,dst=2,val=10
-numa dist,src=2,dst=3,val=21
-numa dist,src=3,dst=0,val=21
-numa dist,src=3,dst=1,val=21
-numa dist,src=3,dst=2,val=21
-numa dist,src=3,dst=3,val=10
-numa hmat-lb,initiator=0,target=0,hierarchy=memory,data-type=access-latency,base-lat=10,latency=5
-numa hmat-lb,initiator=0,target=0,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=5
-numa hmat-lb,initiator=0,target=1,hierarchy=memory,data-type=access-latency,base-lat=10,latency=10
-numa hmat-lb,initiator=0,target=1,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=10
-numa hmat-lb,initiator=0,target=2,hierarchy=memory,data-type=access-latency,base-lat=10,latency=15
-numa hmat-lb,initiator=0,target=2,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=15
-numa hmat-lb,initiator=0,target=3,hierarchy=memory,data-type=access-latency,base-lat=10,latency=20
-numa hmat-lb,initiator=0,target=3,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=20
-numa hmat-lb,initiator=1,target=0,hierarchy=memory,data-type=access-latency,base-lat=10,latency=10
-numa hmat-lb,initiator=1,target=0,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=10
-numa hmat-lb,initiator=1,target=1,hierarchy=memory,data-type=access-latency,base-lat=10,latency=5
-numa hmat-lb,initiator=1,target=1,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=5
-numa hmat-lb,initiator=1,target=2,hierarchy=memory,data-type=access-latency,base-lat=10,latency=15
-numa hmat-lb,initiator=1,target=2,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=15
-numa hmat-lb,initiator=1,target=3,hierarchy=memory,data-type=access-latency,base-lat=10,latency=20
-numa hmat-lb,initiator=1,target=3,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=20
Result:
[
{
"path":"\/platform\/hmem.1",
"id":1,
"size":"4.00 GiB (4.29 GB)",
"align":2097152,
"devices":[
{
"chardev":"dax1.0",
"size":"4.00 GiB (4.29 GB)"
}
]
},
{
"path":"\/platform\/hmem.0",
"id":0,
"size":"4.00 GiB (4.29 GB)",
"align":2097152,
"devices":[
{
"chardev":"dax0.0",
"size":"4.00 GiB (4.29 GB)"
}
]
}
]
[..]
240000000-43fffffff : Soft Reserved
240000000-33fffffff : hmem.0
240000000-33fffffff : dax0.0
340000000-43fffffff : hmem.1
340000000-43fffffff : dax1.0
Reviewed-by: Dave Hansen <dave.hansen@linux.intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Acked-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2019-11-07 09:43:55 +08:00
|
|
|
struct resource *res, *res_next;
|
|
|
|
|
2019-08-05 22:27:04 +08:00
|
|
|
list_for_each_entry_safe(tcache, cnext, &target->caches, node) {
|
|
|
|
list_del(&tcache->node);
|
|
|
|
kfree(tcache);
|
|
|
|
}
|
ACPI: NUMA: HMAT: Register "soft reserved" memory as an "hmem" device
Memory that has been tagged EFI_MEMORY_SP, and has performance
properties described by the ACPI HMAT is expected to have an application
specific consumer.
Those consumers may want 100% of the memory capacity to be reserved from
any usage by the kernel. By default, with this enabling, a platform
device is created to represent this differentiated resource.
The device-dax "hmem" driver claims these devices by default and
provides an mmap interface for the target application. If the
administrator prefers, the hmem resource range can be made available to
the core-mm via the device-dax hotplug facility, kmem, to online the
memory with its own numa node.
This was tested with an emulated HMAT produced by qemu (with the pending
HMAT enabling patches), and "efi_fake_mem=8G@9G:0x40000" on the kernel
command line to mark the memory ranges associated with node2 and node3
as EFI_MEMORY_SP.
qemu numa configuration options:
-numa node,mem=4G,cpus=0-19,nodeid=0
-numa node,mem=4G,cpus=20-39,nodeid=1
-numa node,mem=4G,nodeid=2
-numa node,mem=4G,nodeid=3
-numa dist,src=0,dst=0,val=10
-numa dist,src=0,dst=1,val=21
-numa dist,src=0,dst=2,val=21
-numa dist,src=0,dst=3,val=21
-numa dist,src=1,dst=0,val=21
-numa dist,src=1,dst=1,val=10
-numa dist,src=1,dst=2,val=21
-numa dist,src=1,dst=3,val=21
-numa dist,src=2,dst=0,val=21
-numa dist,src=2,dst=1,val=21
-numa dist,src=2,dst=2,val=10
-numa dist,src=2,dst=3,val=21
-numa dist,src=3,dst=0,val=21
-numa dist,src=3,dst=1,val=21
-numa dist,src=3,dst=2,val=21
-numa dist,src=3,dst=3,val=10
-numa hmat-lb,initiator=0,target=0,hierarchy=memory,data-type=access-latency,base-lat=10,latency=5
-numa hmat-lb,initiator=0,target=0,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=5
-numa hmat-lb,initiator=0,target=1,hierarchy=memory,data-type=access-latency,base-lat=10,latency=10
-numa hmat-lb,initiator=0,target=1,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=10
-numa hmat-lb,initiator=0,target=2,hierarchy=memory,data-type=access-latency,base-lat=10,latency=15
-numa hmat-lb,initiator=0,target=2,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=15
-numa hmat-lb,initiator=0,target=3,hierarchy=memory,data-type=access-latency,base-lat=10,latency=20
-numa hmat-lb,initiator=0,target=3,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=20
-numa hmat-lb,initiator=1,target=0,hierarchy=memory,data-type=access-latency,base-lat=10,latency=10
-numa hmat-lb,initiator=1,target=0,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=10
-numa hmat-lb,initiator=1,target=1,hierarchy=memory,data-type=access-latency,base-lat=10,latency=5
-numa hmat-lb,initiator=1,target=1,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=5
-numa hmat-lb,initiator=1,target=2,hierarchy=memory,data-type=access-latency,base-lat=10,latency=15
-numa hmat-lb,initiator=1,target=2,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=15
-numa hmat-lb,initiator=1,target=3,hierarchy=memory,data-type=access-latency,base-lat=10,latency=20
-numa hmat-lb,initiator=1,target=3,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=20
Result:
[
{
"path":"\/platform\/hmem.1",
"id":1,
"size":"4.00 GiB (4.29 GB)",
"align":2097152,
"devices":[
{
"chardev":"dax1.0",
"size":"4.00 GiB (4.29 GB)"
}
]
},
{
"path":"\/platform\/hmem.0",
"id":0,
"size":"4.00 GiB (4.29 GB)",
"align":2097152,
"devices":[
{
"chardev":"dax0.0",
"size":"4.00 GiB (4.29 GB)"
}
]
}
]
[..]
240000000-43fffffff : Soft Reserved
240000000-33fffffff : hmem.0
240000000-33fffffff : dax0.0
340000000-43fffffff : hmem.1
340000000-43fffffff : dax1.0
Reviewed-by: Dave Hansen <dave.hansen@linux.intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Acked-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2019-11-07 09:43:55 +08:00
|
|
|
|
2019-03-12 04:56:03 +08:00
|
|
|
list_del(&target->node);
|
ACPI: NUMA: HMAT: Register "soft reserved" memory as an "hmem" device
Memory that has been tagged EFI_MEMORY_SP, and has performance
properties described by the ACPI HMAT is expected to have an application
specific consumer.
Those consumers may want 100% of the memory capacity to be reserved from
any usage by the kernel. By default, with this enabling, a platform
device is created to represent this differentiated resource.
The device-dax "hmem" driver claims these devices by default and
provides an mmap interface for the target application. If the
administrator prefers, the hmem resource range can be made available to
the core-mm via the device-dax hotplug facility, kmem, to online the
memory with its own numa node.
This was tested with an emulated HMAT produced by qemu (with the pending
HMAT enabling patches), and "efi_fake_mem=8G@9G:0x40000" on the kernel
command line to mark the memory ranges associated with node2 and node3
as EFI_MEMORY_SP.
qemu numa configuration options:
-numa node,mem=4G,cpus=0-19,nodeid=0
-numa node,mem=4G,cpus=20-39,nodeid=1
-numa node,mem=4G,nodeid=2
-numa node,mem=4G,nodeid=3
-numa dist,src=0,dst=0,val=10
-numa dist,src=0,dst=1,val=21
-numa dist,src=0,dst=2,val=21
-numa dist,src=0,dst=3,val=21
-numa dist,src=1,dst=0,val=21
-numa dist,src=1,dst=1,val=10
-numa dist,src=1,dst=2,val=21
-numa dist,src=1,dst=3,val=21
-numa dist,src=2,dst=0,val=21
-numa dist,src=2,dst=1,val=21
-numa dist,src=2,dst=2,val=10
-numa dist,src=2,dst=3,val=21
-numa dist,src=3,dst=0,val=21
-numa dist,src=3,dst=1,val=21
-numa dist,src=3,dst=2,val=21
-numa dist,src=3,dst=3,val=10
-numa hmat-lb,initiator=0,target=0,hierarchy=memory,data-type=access-latency,base-lat=10,latency=5
-numa hmat-lb,initiator=0,target=0,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=5
-numa hmat-lb,initiator=0,target=1,hierarchy=memory,data-type=access-latency,base-lat=10,latency=10
-numa hmat-lb,initiator=0,target=1,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=10
-numa hmat-lb,initiator=0,target=2,hierarchy=memory,data-type=access-latency,base-lat=10,latency=15
-numa hmat-lb,initiator=0,target=2,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=15
-numa hmat-lb,initiator=0,target=3,hierarchy=memory,data-type=access-latency,base-lat=10,latency=20
-numa hmat-lb,initiator=0,target=3,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=20
-numa hmat-lb,initiator=1,target=0,hierarchy=memory,data-type=access-latency,base-lat=10,latency=10
-numa hmat-lb,initiator=1,target=0,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=10
-numa hmat-lb,initiator=1,target=1,hierarchy=memory,data-type=access-latency,base-lat=10,latency=5
-numa hmat-lb,initiator=1,target=1,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=5
-numa hmat-lb,initiator=1,target=2,hierarchy=memory,data-type=access-latency,base-lat=10,latency=15
-numa hmat-lb,initiator=1,target=2,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=15
-numa hmat-lb,initiator=1,target=3,hierarchy=memory,data-type=access-latency,base-lat=10,latency=20
-numa hmat-lb,initiator=1,target=3,hierarchy=memory,data-type=access-bandwidth,base-bw=20,bandwidth=20
Result:
[
{
"path":"\/platform\/hmem.1",
"id":1,
"size":"4.00 GiB (4.29 GB)",
"align":2097152,
"devices":[
{
"chardev":"dax1.0",
"size":"4.00 GiB (4.29 GB)"
}
]
},
{
"path":"\/platform\/hmem.0",
"id":0,
"size":"4.00 GiB (4.29 GB)",
"align":2097152,
"devices":[
{
"chardev":"dax0.0",
"size":"4.00 GiB (4.29 GB)"
}
]
}
]
[..]
240000000-43fffffff : Soft Reserved
240000000-33fffffff : hmem.0
240000000-33fffffff : dax0.0
340000000-43fffffff : hmem.1
340000000-43fffffff : dax1.0
Reviewed-by: Dave Hansen <dave.hansen@linux.intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Acked-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2019-11-07 09:43:55 +08:00
|
|
|
res = target->memregions.child;
|
|
|
|
while (res) {
|
|
|
|
res_next = res->sibling;
|
|
|
|
__release_region(&target->memregions, res->start,
|
|
|
|
resource_size(res));
|
|
|
|
res = res_next;
|
|
|
|
}
|
2019-03-12 04:56:03 +08:00
|
|
|
kfree(target);
|
|
|
|
}
|
|
|
|
|
|
|
|
list_for_each_entry_safe(initiator, inext, &initiators, node) {
|
|
|
|
list_del(&initiator->node);
|
|
|
|
kfree(initiator);
|
|
|
|
}
|
|
|
|
|
|
|
|
list_for_each_entry_safe(loc, lnext, &localities, node) {
|
|
|
|
list_del(&loc->node);
|
|
|
|
kfree(loc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-12 04:55:59 +08:00
|
|
|
static __init int hmat_init(void)
|
|
|
|
{
|
|
|
|
struct acpi_table_header *tbl;
|
|
|
|
enum acpi_hmat_type i;
|
|
|
|
acpi_status status;
|
|
|
|
|
2020-10-14 07:49:02 +08:00
|
|
|
if (srat_disabled() || hmat_disable)
|
2019-03-12 04:55:59 +08:00
|
|
|
return 0;
|
|
|
|
|
2019-03-12 04:56:03 +08:00
|
|
|
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);
|
|
|
|
|
2019-03-12 04:55:59 +08:00
|
|
|
status = acpi_get_table(ACPI_SIG_HMAT, 0, &tbl);
|
|
|
|
if (ACPI_FAILURE(status))
|
2019-04-10 10:14:50 +08:00
|
|
|
goto out_put;
|
2019-03-12 04:55:59 +08:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2019-04-18 02:13:10 +08:00
|
|
|
for (i = ACPI_HMAT_TYPE_PROXIMITY; i < ACPI_HMAT_TYPE_RESERVED; i++) {
|
2019-03-12 04:55:59 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
2019-03-12 04:56:03 +08:00
|
|
|
hmat_register_targets();
|
2019-08-05 22:27:05 +08:00
|
|
|
|
|
|
|
/* Keep the table and structures if the notifier may use them */
|
|
|
|
if (!register_hotmemory_notifier(&hmat_callback_nb))
|
|
|
|
return 0;
|
2019-03-12 04:55:59 +08:00
|
|
|
out_put:
|
2019-03-12 04:56:03 +08:00
|
|
|
hmat_free_structures();
|
2019-03-12 04:55:59 +08:00
|
|
|
acpi_put_table(tbl);
|
|
|
|
return 0;
|
|
|
|
}
|
2019-11-07 09:43:49 +08:00
|
|
|
device_initcall(hmat_init);
|