Heterogenous memory node attributes
Subsystems (12)
v6 cover Heterogenous memory node attributes
== Changes since v5 ==
Updated HMAT parsing to account for the recently released ACPI 6.3 changes.
HMAT attribute calculation overflow checks.
Fixed memory leak if HMAT parse fails.
Minor change to the patch order. All the base node attributes occur before HMAT usage for these new node attributes to resolve a dependency on a new struct.
Reporting failures to parse HMAT or allocate structures are elevated to a NOTICE level from DEBUG. Any failure will result in just one print so that it is obvious something may need to be investigated rather than silently fail, but also not to be too alarming either.
Determining the cpu and memory node local relationships is quite different this time (PATCH 7/10). The local relationship to a memory target will be either *only* the node from the Initiator Proximity Domain if provided, or if it is not provided, all the nodes that have the same highest performance. Latency was chosen to take prioirty over bandwidth when ranking performance.
Renamed "side_cache" to "memory_side_cache". The previous name was ambiguous.
Removed "level" as an exported cache attribute. It was redundant with the directory name anyway.
Minor changelog updates, added received reviews, and documentation fixes.
Just want to point out that I am sticking with struct device instead of using struct kobject embedded in the attribute tracking structures. Previous feedback was leaning either way on this point.
== Background ==
Platforms may provide multiple types of cpu attached system memory. The memory ranges for each type may have different characteristics that applications may wish to know about when considering what node they want their memory allocated from.
It had previously been difficult to describe these setups as memory rangers were generally lumped into the NUMA node of the CPUs. New platform attributes have been created and in use today that describe the more complex memory hierarchies that can be created.
This series' objective is to provide the attributes from such systems that are useful for applications to know about, and readily usable with existing tools and libraries. Those applications may query performance attributes relative to a particular CPU they're running on in order to make more informed choices for where they want to allocate hot and cold data. This works with mbind() or the numactl library.
Keith Busch (10):
acpi: Create subtable parsing infrastructure
acpi: Add HMAT to generic parsing tables acpi/hmat: Parse and report heterogeneous memory
node: Link memory nodes to their compute nodes
node: Add heterogenous memory access attributes
node: Add memory-side caching attributes acpi/hmat: Register processor domain to its memory acpi/hmat: Register performance attributes acpi/hmat: Register memory side cache attributes doc/mm: New documentation for memory performance
Documentation/ABI/stable/sysfs-devices-node | 89 +++- Documentation/admin-guide/mm/numaperf.rst | 164 +++++++ arch/arm64/kernel/acpi_numa.c | 2 +- arch/arm64/kernel/smp.c | 4 +- arch/ia64/kernel/acpi.c | 12 +- arch/x86/kernel/acpi/boot.c | 36 +- drivers/acpi/Kconfig | 1 + drivers/acpi/Makefile | 1 + drivers/acpi/hmat/Kconfig | 9 + drivers/acpi/hmat/Makefile | 1 + drivers/acpi/hmat/hmat.c | 677 ++++++++++++++++++++++++++ drivers/acpi/numa.c | 16 +- drivers/acpi/scan.c | 4 +- drivers/acpi/tables.c | 76 ++- drivers/base/Kconfig | 8 + drivers/base/node.c | 351 ++++++++++++- drivers/irqchip/irq-gic-v2m.c | 2 +- drivers/irqchip/irq-gic-v3-its-pci-msi.c | 2 +- drivers/irqchip/irq-gic-v3-its-platform-msi.c | 2 +- drivers/irqchip/irq-gic-v3-its.c | 6 +- drivers/irqchip/irq-gic-v3.c | 10 +- drivers/irqchip/irq-gic.c | 4 +- drivers/mailbox/pcc.c | 2 +- include/linux/acpi.h | 6 +- include/linux/node.h | 60 ++- 25 files changed, 1480 insertions(+), 65 deletions(-) create mode 100644 Documentation/admin-guide/mm/numaperf.rst create mode 100644 drivers/acpi/hmat/Kconfig create mode 100644 drivers/acpi/hmat/Makefile create mode 100644 drivers/acpi/hmat/hmat.c
Signature · 1 line
2.14.4
PATCH v6 1/10 acpi: Create subtable parsing infrastructure
Parsing entries in an ACPI table had assumed a generic header structure. There is no standard ACPI header, though, so less common layouts with different field sizes required custom parsers to go through their subtable entry list.
Create the infrastructure for adding different table types so parsing the entries array may be more reused for all ACPI system tables and the common code doesn't need to be duplicated.
--- arch/arm64/kernel/acpi_numa.c | 2 +- arch/arm64/kernel/smp.c | 4 +- arch/ia64/kernel/acpi.c | 12 ++--- arch/x86/kernel/acpi/boot.c | 36 +++++++------- drivers/acpi/numa.c | 16 +++---- drivers/acpi/scan.c | 4 +- drivers/acpi/tables.c | 67 +++++++++++++++++++++++---- drivers/irqchip/irq-gic-v2m.c | 2 +- drivers/irqchip/irq-gic-v3-its-pci-msi.c | 2 +- drivers/irqchip/irq-gic-v3-its-platform-msi.c | 2 +- drivers/irqchip/irq-gic-v3-its.c | 6 +-- drivers/irqchip/irq-gic-v3.c | 10 ++-- drivers/irqchip/irq-gic.c | 4 +- drivers/mailbox/pcc.c | 2 +- include/linux/acpi.h | 5 +- 15 files changed, 112 insertions(+), 62 deletions(-)
arch/arm64/kernel/acpi_numa.c +1 -1
@@ -45,7 +45,7 @@ static inline int get_cpu_for_acpi_id(u32 uid)return -EINVAL ; } -static int __init acpi_parse_gicc_pxm (struct acpi_subtable_header *header, +static int __init acpi_parse_gicc_pxm (union acpi_subtable_headers *header,const unsigned long end) {struct acpi_srat_gicc_affinity *pa;
arch/arm64/kernel/smp.c +2 -2
@@ -553,7 +553,7 @@ acpi_map_gic_cpu_interface(struct acpi_madt_generic_interrupt *processor) }static int __init -acpi_parse_gic_cpu_interface (struct acpi_subtable_header *header, +acpi_parse_gic_cpu_interface (union acpi_subtable_headers *header,const unsigned long end) {struct acpi_madt_generic_interrupt *processor;
@@ -562,7 +562,7 @@ acpi_parse_gic_cpu_interface(struct acpi_subtable_header *header,if (BAD_MADT_GICC_ENTRY (processor, end))return -EINVAL ; -acpi_table_print_madt_entry (header); +acpi_table_print_madt_entry (&header->common);acpi_map_gic_cpu_interface (processor);
arch/ia64/kernel/acpi.c +6 -6
@@ -177,7 +177,7 @@ struct acpi_table_madt *acpi_madt __initdata;static u8 has_8259;static int __init -acpi_parse_lapic_addr_ovr (struct acpi_subtable_header * header, +acpi_parse_lapic_addr_ovr (union acpi_subtable_headers * header,const unsigned long end) {struct acpi_madt_local_apic_override *lapic;
@@ -216,7 +216,7 @@ acpi_parse_lsapic(struct acpi_subtable_header * header, const unsigned long end) }static int __init -acpi_parse_lapic_nmi (struct acpi_subtable_header * header,const unsigned long end) +acpi_parse_lapic_nmi (union acpi_subtable_headers * header,const unsigned long end) {struct acpi_madt_local_apic_nmi *lacpi_nmi;
@@ -230,7 +230,7 @@ acpi_parse_lapic_nmi(struct acpi_subtable_header * header, const unsigned long e }static int __init -acpi_parse_iosapic (struct acpi_subtable_header * header,const unsigned long end) +acpi_parse_iosapic (union acpi_subtable_headers * header,const unsigned long end) {struct acpi_madt_io_sapic *iosapic;
@@ -245,7 +245,7 @@ acpi_parse_iosapic(struct acpi_subtable_header * header, const unsigned long endstatic unsigned int __initdata acpi_madt_rev;static int __init -acpi_parse_plat_int_src (struct acpi_subtable_header * header, +acpi_parse_plat_int_src (union acpi_subtable_headers * header,const unsigned long end) {struct acpi_madt_interrupt_source *plintsrc;
@@ -329,7 +329,7 @@ unsigned int get_cpei_target_cpu(void) }static int __init -acpi_parse_int_src_ovr (struct acpi_subtable_header * header, +acpi_parse_int_src_ovr (union acpi_subtable_headers * header,const unsigned long end) {struct acpi_madt_interrupt_override *p;
@@ -350,7 +350,7 @@ acpi_parse_int_src_ovr(struct acpi_subtable_header * header, }static int __init -acpi_parse_nmi_src (struct acpi_subtable_header * header,const unsigned long end) +acpi_parse_nmi_src (union acpi_subtable_headers * header,const unsigned long end) {struct acpi_madt_nmi_source *nmi_src;
arch/x86/kernel/acpi/boot.c +18 -18
@@ -197,7 +197,7 @@ static int acpi_register_lapic(int id, u32 acpiid, u8 enabled) }static int __init -acpi_parse_x2apic (struct acpi_subtable_header *header,const unsigned long end) +acpi_parse_x2apic (union acpi_subtable_headers *header,const unsigned long end) {struct acpi_madt_local_x2apic *processor =NULL ;#ifdef CONFIG_X86_X2APIC
@@ -210,7 +210,7 @@ acpi_parse_x2apic(struct acpi_subtable_header *header, const unsigned long end)if (BAD_MADT_ENTRY (processor, end))return -EINVAL ; -acpi_table_print_madt_entry (header); +acpi_table_print_madt_entry (&header->common);#ifdef CONFIG_X86_X2APIC apic_id = processor->local_apic_id;
@@ -242,7 +242,7 @@ acpi_parse_x2apic(struct acpi_subtable_header *header, const unsigned long end) }static int __init -acpi_parse_lapic (struct acpi_subtable_header * header,const unsigned long end) +acpi_parse_lapic (union acpi_subtable_headers * header,const unsigned long end) {struct acpi_madt_local_apic *processor =NULL ;
@@ -251,7 +251,7 @@ acpi_parse_lapic(struct acpi_subtable_header * header, const unsigned long end)if (BAD_MADT_ENTRY (processor, end))return -EINVAL ; -acpi_table_print_madt_entry (header); +acpi_table_print_madt_entry (&header->common);/* Ignore invalid ID */ if (processor->id ==0xff )
@@ -272,7 +272,7 @@ acpi_parse_lapic(struct acpi_subtable_header * header, const unsigned long end) }static int __init -acpi_parse_sapic (struct acpi_subtable_header *header,const unsigned long end) +acpi_parse_sapic (union acpi_subtable_headers *header,const unsigned long end) {struct acpi_madt_local_sapic *processor =NULL ;
@@ -281,7 +281,7 @@ acpi_parse_sapic(struct acpi_subtable_header *header, const unsigned long end)if (BAD_MADT_ENTRY (processor, end))return -EINVAL ; -acpi_table_print_madt_entry (header); +acpi_table_print_madt_entry (&header->common); acpi_register_lapic((processor->id << 8) | processor->eid,/* APIC ID */ processor->processor_id, /* ACPI ID */
@@ -291,7 +291,7 @@ acpi_parse_sapic(struct acpi_subtable_header *header, const unsigned long end) }static int __init -acpi_parse_lapic_addr_ovr (struct acpi_subtable_header * header, +acpi_parse_lapic_addr_ovr (union acpi_subtable_headers * header,const unsigned long end) {struct acpi_madt_local_apic_override *lapic_addr_ovr =NULL ;
@@ -301,7 +301,7 @@ acpi_parse_lapic_addr_ovr(struct acpi_subtable_header * header,if (BAD_MADT_ENTRY (lapic_addr_ovr, end))return -EINVAL ; -acpi_table_print_madt_entry (header); +acpi_table_print_madt_entry (&header->common); acpi_lapic_addr = lapic_addr_ovr->address;
@@ -309,7 +309,7 @@ acpi_parse_lapic_addr_ovr(struct acpi_subtable_header * header, }static int __init -acpi_parse_x2apic_nmi (struct acpi_subtable_header *header, +acpi_parse_x2apic_nmi (union acpi_subtable_headers *header,const unsigned long end) {struct acpi_madt_local_x2apic_nmi *x2apic_nmi =NULL ;
@@ -319,7 +319,7 @@ acpi_parse_x2apic_nmi(struct acpi_subtable_header *header,if (BAD_MADT_ENTRY (x2apic_nmi, end))return -EINVAL ; -acpi_table_print_madt_entry (header); +acpi_table_print_madt_entry (&header->common);if (x2apic_nmi->lint !=1 ) printk(KERN_WARNING PREFIX "NMI not connected to LINT 1!\n");
@@ -328,7 +328,7 @@ acpi_parse_x2apic_nmi(struct acpi_subtable_header *header, }static int __init -acpi_parse_lapic_nmi (struct acpi_subtable_header * header,const unsigned long end) +acpi_parse_lapic_nmi (union acpi_subtable_headers * header,const unsigned long end) {struct acpi_madt_local_apic_nmi *lapic_nmi =NULL ;
@@ -337,7 +337,7 @@ acpi_parse_lapic_nmi(struct acpi_subtable_header * header, const unsigned long eif (BAD_MADT_ENTRY (lapic_nmi, end))return -EINVAL ; -acpi_table_print_madt_entry (header); +acpi_table_print_madt_entry (&header->common);if (lapic_nmi->lint !=1 ) printk(KERN_WARNING PREFIX "NMI not connected to LINT 1!\n");
@@ -449,7 +449,7 @@ static int __init mp_register_ioapic_irq(u8 bus_irq, u8 polarity, }static int __init -acpi_parse_ioapic (struct acpi_subtable_header * header,const unsigned long end) +acpi_parse_ioapic (union acpi_subtable_headers * header,const unsigned long end) {struct acpi_madt_io_apic *ioapic =NULL ;struct ioapic_domain_cfg cfg = {
@@ -462,7 +462,7 @@ acpi_parse_ioapic(struct acpi_subtable_header * header, const unsigned long end)if (BAD_MADT_ENTRY (ioapic, end))return -EINVAL ; -acpi_table_print_madt_entry (header); +acpi_table_print_madt_entry (&header->common);/* Statically assign IRQ numbers for IOAPICs hosting legacy IRQs */ if (ioapic->global_irq_base <nr_legacy_irqs ())
@@ -508,7 +508,7 @@ static void __init acpi_sci_ioapic_setup(u8 bus_irq, u16 polarity, u16 trigger, }static int __init -acpi_parse_int_src_ovr (struct acpi_subtable_header * header, +acpi_parse_int_src_ovr (union acpi_subtable_headers * header,const unsigned long end) {struct acpi_madt_interrupt_override *intsrc =NULL ;
@@ -518,7 +518,7 @@ acpi_parse_int_src_ovr(struct acpi_subtable_header * header,if (BAD_MADT_ENTRY (intsrc, end))return -EINVAL ; -acpi_table_print_madt_entry (header); +acpi_table_print_madt_entry (&header->common);if (intsrc->source_irq == acpi_gbl_FADT.sci_interrupt) { acpi_sci_ioapic_setup(intsrc->source_irq,
@@ -550,7 +550,7 @@ acpi_parse_int_src_ovr(struct acpi_subtable_header * header, }static int __init -acpi_parse_nmi_src (struct acpi_subtable_header * header,const unsigned long end) +acpi_parse_nmi_src (union acpi_subtable_headers * header,const unsigned long end) {struct acpi_madt_nmi_source *nmi_src =NULL ;
@@ -559,7 +559,7 @@ acpi_parse_nmi_src(struct acpi_subtable_header * header, const unsigned long endif (BAD_MADT_ENTRY (nmi_src, end))return -EINVAL ; -acpi_table_print_madt_entry (header); +acpi_table_print_madt_entry (&header->common);/* TBD: Support nimsrc entries? */
drivers/acpi/numa.c +8 -8
@@ -338,7 +338,7 @@ acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa) }static int __init -acpi_parse_x2apic_affinity (struct acpi_subtable_header *header, +acpi_parse_x2apic_affinity (union acpi_subtable_headers *header,const unsigned long end) {struct acpi_srat_x2apic_cpu_affinity *processor_affinity;
@@ -347,7 +347,7 @@ acpi_parse_x2apic_affinity(struct acpi_subtable_header *header,if (!processor_affinity)return -EINVAL ; -acpi_table_print_srat_entry (header); +acpi_table_print_srat_entry (&header->common);/* let architecture-dependent part to do it */ acpi_numa_x2apic_affinity_init (processor_affinity);
@@ -356,7 +356,7 @@ acpi_parse_x2apic_affinity(struct acpi_subtable_header *header, }static int __init -acpi_parse_processor_affinity (struct acpi_subtable_header *header, +acpi_parse_processor_affinity (union acpi_subtable_headers *header,const unsigned long end) {struct acpi_srat_cpu_affinity *processor_affinity;
@@ -365,7 +365,7 @@ acpi_parse_processor_affinity(struct acpi_subtable_header *header,if (!processor_affinity)return -EINVAL ; -acpi_table_print_srat_entry (header); +acpi_table_print_srat_entry (&header->common);/* let architecture-dependent part to do it */ acpi_numa_processor_affinity_init (processor_affinity);
@@ -374,7 +374,7 @@ acpi_parse_processor_affinity(struct acpi_subtable_header *header, }static int __init -acpi_parse_gicc_affinity (struct acpi_subtable_header *header, +acpi_parse_gicc_affinity (union acpi_subtable_headers *header,const unsigned long end) {struct acpi_srat_gicc_affinity *processor_affinity;
@@ -383,7 +383,7 @@ acpi_parse_gicc_affinity(struct acpi_subtable_header *header,if (!processor_affinity)return -EINVAL ; -acpi_table_print_srat_entry (header); +acpi_table_print_srat_entry (&header->common);/* let architecture-dependent part to do it */ acpi_numa_gicc_affinity_init (processor_affinity);
@@ -394,7 +394,7 @@ acpi_parse_gicc_affinity(struct acpi_subtable_header *header,static int __initdata parsed_numa_memblks;static int __init -acpi_parse_memory_affinity (struct acpi_subtable_header * header, +acpi_parse_memory_affinity (union acpi_subtable_headers * header,const unsigned long end) {struct acpi_srat_mem_affinity *memory_affinity;
@@ -403,7 +403,7 @@ acpi_parse_memory_affinity(struct acpi_subtable_header * header,if (!memory_affinity)return -EINVAL ; -acpi_table_print_srat_entry (header); +acpi_table_print_srat_entry (&header->common);/* let architecture-dependent part to do it */ if (!acpi_numa_memory_affinity_init (memory_affinity))
drivers/acpi/scan.c +2 -2
@@ -2240,10 +2240,10 @@ static struct acpi_probe_entry *ape;static int acpi_probe_count;static DEFINE_MUTEX (acpi_probe_mutex); -static int __init acpi_match_madt (struct acpi_subtable_header *header, +static int __init acpi_match_madt (union acpi_subtable_headers *header,const unsigned long end) { -if (!ape->subtable_valid || ape->subtable_valid (header, ape)) +if (!ape->subtable_valid || ape->subtable_valid (&header->common, ape))if (!ape->probe_subtbl (header, end)) acpi_probe_count++;
drivers/acpi/tables.c +57 -10
109 lines not on this page · raw message
drivers/irqchip/irq-gic-v2m.c +1 -1
@@ -446,7 +446,7 @@ static struct fwnode_handle *gicv2m_get_fwnode(struct device *dev) }static int __init -acpi_parse_madt_msi (struct acpi_subtable_header *header, +acpi_parse_madt_msi (union acpi_subtable_headers *header,const unsigned long end) {int ret;
drivers/irqchip/irq-gic-v3-its-pci-msi.c +1 -1
@@ -159,7 +159,7 @@ static int __init its_pci_of_msi_init(void)#ifdef CONFIG_ACPI static int __init -its_pci_msi_parse_madt (struct acpi_subtable_header *header, +its_pci_msi_parse_madt (union acpi_subtable_headers *header,const unsigned long end) {struct acpi_madt_generic_translator *its_entry;
drivers/irqchip/irq-gic-v3-its-platform-msi.c +1 -1
@@ -117,7 +117,7 @@ static int __init its_pmsi_init_one(struct fwnode_handle *fwnode,#ifdef CONFIG_ACPI static int __init -its_pmsi_parse_madt (struct acpi_subtable_header *header, +its_pmsi_parse_madt (union acpi_subtable_headers *header,const unsigned long end) {struct acpi_madt_generic_translator *its_entry;
drivers/irqchip/irq-gic-v3-its.c +3 -3
@@ -3822,13 +3822,13 @@ static int __init acpi_get_its_numa_node(u32 its_id)return NUMA_NO_NODE ; } -static int __init gic_acpi_match_srat_its (struct acpi_subtable_header *header, +static int __init gic_acpi_match_srat_its (union acpi_subtable_headers *header,const unsigned long end) {return 0 ; } -static int __init gic_acpi_parse_srat_its (struct acpi_subtable_header *header, +static int __init gic_acpi_parse_srat_its (union acpi_subtable_headers *header,const unsigned long end) {int node;
@@ -3895,7 +3895,7 @@ static int __init acpi_get_its_numa_node(u32 its_id) { return NUMA_NO_NODE; }static void __init acpi_its_srat_maps_free (void ) { }#endif -static int __init gic_acpi_parse_madt_its (struct acpi_subtable_header *header, +static int __init gic_acpi_parse_madt_its (union acpi_subtable_headers *header,const unsigned long end) {struct acpi_madt_generic_translator *its_entry;
drivers/irqchip/irq-gic-v3.c +5 -5
@@ -1392,7 +1392,7 @@ gic_acpi_register_redist(phys_addr_t phys_base, void __iomem *redist_base) }static int __init -gic_acpi_parse_madt_redist (struct acpi_subtable_header *header, +gic_acpi_parse_madt_redist (union acpi_subtable_headers *header,const unsigned long end) { struct acpi_madt_generic_redistributor *redist =
@@ -1410,7 +1410,7 @@ gic_acpi_parse_madt_redist(struct acpi_subtable_header *header, }static int __init -gic_acpi_parse_madt_gicc (struct acpi_subtable_header *header, +gic_acpi_parse_madt_gicc (union acpi_subtable_headers *header,const unsigned long end) { struct acpi_madt_generic_interrupt *gicc =
@@ -1452,14 +1452,14 @@ static int __init gic_acpi_collect_gicr_base(void)return -ENODEV ; } -static int __init gic_acpi_match_gicr (struct acpi_subtable_header *header, +static int __init gic_acpi_match_gicr (union acpi_subtable_headers *header,const unsigned long end) {/* Subtable presence means that redist exists, that's it */ return 0 ; } -static int __init gic_acpi_match_gicc (struct acpi_subtable_header *header, +static int __init gic_acpi_match_gicc (union acpi_subtable_headers *header,const unsigned long end) { struct acpi_madt_generic_interrupt *gicc =
@@ -1525,7 +1525,7 @@ static bool __init acpi_validate_gic_table(struct acpi_subtable_header *header,return true; } -static int __init gic_acpi_parse_virt_madt_gicc (struct acpi_subtable_header *header, +static int __init gic_acpi_parse_virt_madt_gicc (union acpi_subtable_headers *header,const unsigned long end) { struct acpi_madt_generic_interrupt *gicc =
drivers/irqchip/irq-gic.c +2 -2
@@ -1508,7 +1508,7 @@ static struct } acpi_data__initdata ;static int __init -gic_acpi_parse_madt_cpu (struct acpi_subtable_header *header, +gic_acpi_parse_madt_cpu (union acpi_subtable_headers *header,const unsigned long end) {struct acpi_madt_generic_interrupt *processor;
@@ -1540,7 +1540,7 @@ gic_acpi_parse_madt_cpu(struct acpi_subtable_header *header, }/* The things you have to do to just *count* something... */ -static int __init acpi_dummy_func (struct acpi_subtable_header *header, +static int __init acpi_dummy_func (union acpi_subtable_headers *header,const unsigned long end) {return 0 ;
drivers/mailbox/pcc.c +1 -1
@@ -382,7 +382,7 @@ static const struct mbox_chan_ops pcc_chan_ops = {* * This gets called for each entry in the PCC table. */ -static int parse_pcc_subspace (struct acpi_subtable_header *header, +static int parse_pcc_subspace (union acpi_subtable_headers *header,const unsigned long end) {struct acpi_pcct_subspace *ss = (struct acpi_pcct_subspace *) header;
include/linux/acpi.h +4 -1
@@ -141,10 +141,13 @@ enum acpi_address_range_id {/* Table Handlers */ +union acpi_subtable_headers { +struct acpi_subtable_header common; +};typedef int (*acpi_tbl_table_handler )(struct acpi_table_header *table); -typedef int (*acpi_tbl_entry_handler )(struct acpi_subtable_header *header, +typedef int (*acpi_tbl_entry_handler )(union acpi_subtable_headers *header,const unsigned long end);/* Debugger support */
Signature · 1 line
2.14.4
PATCH v6 2/10 acpi: Add HMAT to generic parsing tables
In reply to Keith BuschThe Heterogeneous Memory Attribute Table (HMAT) header has different field lengths than the existing parsing uses. Add the HMAT type to the parsing rules so it may be generically parsed.
--- drivers/acpi/tables.c | 9 +++++++++ include/linux/acpi.h | 1 + 2 files changed, 10 insertions(+)
drivers/acpi/tables.c +9 -0
@@ -51,6 +51,7 @@ static int acpi_apic_instance __initdata;enum acpi_subtable_type {ACPI_SUBTABLE_COMMON , +ACPI_SUBTABLE_HMAT , };struct acpi_subtable_entry {
@@ -232,6 +233,8 @@ acpi_get_entry_type(struct acpi_subtable_entry *entry)switch (entry->type) {case ACPI_SUBTABLE_COMMON :return entry->hdr->common.type; +case ACPI_SUBTABLE_HMAT : +return entry->hdr->hmat.type; }return 0 ; }
@@ -242,6 +245,8 @@ acpi_get_entry_length(struct acpi_subtable_entry *entry)switch (entry->type) {case ACPI_SUBTABLE_COMMON :return entry->hdr->common.length; +case ACPI_SUBTABLE_HMAT : +return entry->hdr->hmat.length; }return 0 ; }
@@ -252,6 +257,8 @@ acpi_get_subtable_header_length(struct acpi_subtable_entry *entry)switch (entry->type) {case ACPI_SUBTABLE_COMMON :return sizeof (entry->hdr->common); +case ACPI_SUBTABLE_HMAT : +return sizeof (entry->hdr->hmat); }return 0 ; }
@@ -259,6 +266,8 @@ acpi_get_subtable_header_length(struct acpi_subtable_entry *entry)static enum acpi_subtable_type __init acpi_get_subtable_type (char *id) { +if (strncmp (id,ACPI_SIG_HMAT ,4 ) ==0 ) +return ACPI_SUBTABLE_HMAT ;return ACPI_SUBTABLE_COMMON ; }
include/linux/acpi.h +1 -0
@@ -143,6 +143,7 @@ enum acpi_address_range_id {/* Table Handlers */ union acpi_subtable_headers {struct acpi_subtable_header common; +struct acpi_hmat_structure hmat; };typedef int (*acpi_tbl_table_handler )(struct acpi_table_header *table);
Signature · 1 line
2.14.4
PATCH v6 3/10 acpi/hmat: Parse and report heterogeneous memory
In reply to Keith BuschSystems may provide different memory types and export this information in the ACPI Heterogeneous Memory Attribute Table (HMAT). Parse these tables provided by the platform and report the memory access and caching attributes to the kernel messages.
--- drivers/acpi/Kconfig | 1 + drivers/acpi/Makefile | 1 + drivers/acpi/hmat/Kconfig | 8 ++ drivers/acpi/hmat/Makefile | 1 + drivers/acpi/hmat/hmat.c | 236 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 247 insertions(+) create mode 100644 drivers/acpi/hmat/Kconfig create mode 100644 drivers/acpi/hmat/Makefile create mode 100644 drivers/acpi/hmat/hmat.c
drivers/acpi/Kconfig +1 -0
@@ -465,6 +465,7 @@ config ACPI_REDUCED_HARDWARE_ONLY If you are unsure what to do, do not enable this option. source "drivers/acpi/nfit/Kconfig" +source "drivers/acpi/hmat/Kconfig" source "drivers/acpi/apei/Kconfig" source "drivers/acpi/dptf/Kconfig"
drivers/acpi/Makefile +1 -0
@@ -80,6 +80,7 @@ obj-$(CONFIG_ACPI_PROCESSOR) += processor.o obj-$(CONFIG_ACPI) += container.o obj-$(CONFIG_ACPI_THERMAL) += thermal.o obj-$(CONFIG_ACPI_NFIT) += nfit/ +obj-$(CONFIG_ACPI_HMAT) += hmat/ obj-$(CONFIG_ACPI) += acpi_memhotplug.o obj-$(CONFIG_ACPI_HOTPLUG_IOAPIC) += ioapic.o obj-$(CONFIG_ACPI_BATTERY) += battery.o
drivers/acpi/hmat/Kconfig new file +8 -0
@@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-2.0 +config ACPI_HMAT + bool "ACPI Heterogeneous Memory Attribute Table Support" + depends on ACPI_NUMA + help + If set, this option causes the kernel to set the memory NUMA node + relationships and access attributes in accordance with ACPI HMAT + (Heterogeneous Memory Attributes Table).
drivers/acpi/hmat/Makefile new file +1 -0
@@ -0,0 +1 @@ +obj-$(CONFIG_ACPI_HMAT) := hmat.o
drivers/acpi/hmat/hmat.c new file +236 -0
236 lines not on this page · raw message
Signature · 1 line
2.14.4
PATCH v6 4/10 node: Link memory nodes to their compute nodes
In reply to Keith BuschSystems may be constructed with various specialized nodes. Some nodes may provide memory, some provide compute devices that access and use that memory, and others may provide both. Nodes that provide memory are referred to as memory targets, and nodes that can initiate memory access are referred to as memory initiators.
Memory targets will often have varying access characteristics from different initiators, and platforms may have ways to express those relationships. In preparation for these systems, provide interfaces for the kernel to export the memory relationship among different nodes memory targets and their initiators with symlinks to each other.
If a system provides access locality for each initiator-target pair, nodes may be grouped into ranked access classes relative to other nodes. The new interface allows a subsystem to register relationships of varying classes if available and desired to be exported.
A memory initiator may have multiple memory targets in the same access class. The target memory's initiators in a given class indicate the node's access characteristics share the same performance relative to other linked initiator nodes. Each target within an initiator's access class, though, do not necessarily perform the same as each other.
A memory target node may have multiple memory initiators. All linked initiators in a target's class have the same access characteristics to that target.
The following example show the nodes' new sysfs hierarchy for a memory target node 'Y' with access class 0 from initiator node 'X':
# symlinks -v /sys/devices/system/node/nodeX/access0/ relative: /sys/devices/system/node/nodeX/access0/targets/nodeY -> ../../nodeY
# symlinks -v /sys/devices/system/node/nodeY/access0/ relative: /sys/devices/system/node/nodeY/access0/initiators/nodeX -> ../../nodeX
The new attributes are added to the sysfs stable documentation.
--- Documentation/ABI/stable/sysfs-devices-node | 25 ++++- drivers/base/node.c | 141 +++++++++++++++++++++++++++- include/linux/node.h | 7 +- 3 files changed, 170 insertions(+), 3 deletions(-)
Documentation/ABI/stable/sysfs-devices-node +24 -1
@@ -90,4 +90,27 @@ Date: December 2009 Contact: Lee Schermerhorn <[email protected]> Description: The node's huge page size control/query attributes. - See Documentation/admin-guide/mm/hugetlbpage.rst + See Documentation/admin-guide/mm/hugetlbpage.rst + +What: /sys/devices/system/node/nodeX/accessY/ +Date: December 2018 +Contact: Keith Busch <[email protected]> +Description: + The node's relationship to other nodes for access class "Y". + +What: /sys/devices/system/node/nodeX/accessY/initiators/ +Date: December 2018 +Contact: Keith Busch <[email protected]> +Description: + The directory containing symlinks to memory initiator + nodes that have class "Y" access to this target node's + memory. CPUs and other memory initiators in nodes not in + the list accessing this node's memory may have different + performance. + +What: /sys/devices/system/node/nodeX/classY/targets/ +Date: December 2018 +Contact: Keith Busch <[email protected]> +Description: + The directory containing symlinks to memory targets that + this initiator node has class "Y" access.
drivers/base/node.c +140 -1
171 lines not on this page · raw message
include/linux/node.h +6 -1
@@ -17,11 +17,12 @@#include <linux/device.h> #include <linux/cpumask.h> +#include <linux/list.h> #include <linux/workqueue.h> struct node {struct device dev; - +struct list_head access_list;#if defined(CONFIG_MEMORY_HOTPLUG_SPARSE ) && defined(CONFIG_HUGETLBFS )struct work_struct node_work;#endif
@@ -75,6 +76,10 @@ extern int register_mem_sect_under_node(struct memory_block *mem_blk,extern int unregister_mem_sect_under_nodes (struct memory_block *mem_blk,unsigned long phys_index); +extern int register_memory_node_under_compute_node (unsigned int mem_nid, +unsigned int cpu_nid, +unsigned access); +#ifdef CONFIG_HUGETLBFS extern void register_hugetlbfs_with_node (node_registration_func_t doregister,node_registration_func_t unregister);
Signature · 1 line
2.14.4
PATCH v6 5/10 node: Add heterogenous memory access attributes
In reply to Keith BuschHeterogeneous memory systems provide memory nodes with different latency and bandwidth performance attributes. Provide a new kernel interface for subsystems to register the attributes under the memory target node's initiator access class. If the system provides this information, applications may query these attributes when deciding which node to request memory.
The following example shows the new sysfs hierarchy for a node exporting performance attributes:
# tree -P "read*|write*"/sys/devices/system/node/nodeY/accessZ/initiators/ /sys/devices/system/node/nodeY/accessZ/initiators/ |-- read_bandwidth |-- read_latency |-- write_bandwidth `-- write_latency
The bandwidth is exported as MB/s and latency is reported in nanoseconds. The values are taken from the platform as reported by the manufacturer.
Memory accesses from an initiator node that is not one of the memory's access "Z" initiator nodes linked in the same directory may observe different performance than reported here. When a subsystem makes use of this interface, initiators of a different access number may not have the same performance relative to initiators in other access numbers, or omitted from the any access class' initiators.
Descriptions for memory access initiator performance access attributes are added to sysfs stable documentation.
--- Documentation/ABI/stable/sysfs-devices-node | 31 ++++++++++++++- drivers/base/Kconfig | 8 ++++ drivers/base/node.c | 59 +++++++++++++++++++++++++++++ include/linux/node.h | 19 ++++++++++ 4 files changed, 116 insertions(+), 1 deletion(-)
Documentation/ABI/stable/sysfs-devices-node +30 -1
@@ -106,7 +106,8 @@ Description: nodes that have class "Y" access to this target node's memory. CPUs and other memory initiators in nodes not in the list accessing this node's memory may have different - performance. + performance. This directory also provides the performance + attributes if they exist. What: /sys/devices/system/node/nodeX/classY/targets/ Date: December 2018
@@ -114,3 +115,31 @@ Contact: Keith Busch <[email protected]> Description: The directory containing symlinks to memory targets that this initiator node has class "Y" access. + +What: /sys/devices/system/node/nodeX/accessY/initiators/read_bandwidth +Date: December 2018 +Contact: Keith Busch <[email protected]> +Description: + This node's read bandwidth in MB/s when accessed from + nodes found in this access class's linked initiators. + +What: /sys/devices/system/node/nodeX/accessY/initiators/read_latency +Date: December 2018 +Contact: Keith Busch <[email protected]> +Description: + This node's read latency in nanoseconds when accessed + from nodes found in this access class's linked initiators. + +What: /sys/devices/system/node/nodeX/accessY/initiators/write_bandwidth +Date: December 2018 +Contact: Keith Busch <[email protected]> +Description: + This node's write bandwidth in MB/s when accessed from + found in this access class's linked initiators. + +What: /sys/devices/system/node/nodeX/accessY/initiators/write_latency +Date: December 2018 +Contact: Keith Busch <[email protected]> +Description: + This node's write latency in nanoseconds when access + from nodes found in this class's linked initiators.
drivers/base/Kconfig +8 -0
@@ -149,6 +149,14 @@ config DEBUG_TEST_DRIVER_REMOVE unusable. You should say N here unless you are explicitly looking to test this functionality. +config HMEM_REPORTING + bool + default n + depends on NUMA + help + Enable reporting for heterogenous memory access attributes under + their non-uniform memory nodes. + source "drivers/base/test/Kconfig" config SYS_HYPERVISOR
drivers/base/node.c +59 -0
71 lines not on this page · raw message
include/linux/node.h +19 -0
@@ -20,6 +20,25 @@#include <linux/list.h> #include <linux/workqueue.h> +#ifdef CONFIG_HMEM_REPORTING +/** +* struct node_hmem_attrs - heterogeneous memory performance attributes +* +* @read_bandwidth: Read bandwidth in MB/s +* @write_bandwidth: Write bandwidth in MB/s +* @read_latency: Read latency in nanoseconds +* @write_latency: Write latency in nanoseconds +*/ +struct node_hmem_attrs { +unsigned int read_bandwidth; +unsigned int write_bandwidth; +unsigned int read_latency; +unsigned int write_latency; +}; +void node_set_perf_attrs (unsigned int nid,struct node_hmem_attrs *hmem_attrs, +unsigned access); +#endif +struct node {struct device dev;struct list_head access_list;
Signature · 1 line
2.14.4
PATCH v6 6/10 node: Add memory-side caching attributes
In reply to Keith BuschSystem memory may have caches to help improve access speed to frequently requested address ranges. While the system provided cache is transparent to the software accessing these memory ranges, applications can optimize their own access based on cache attributes.
Provide a new API for the kernel to register these memory-side caches under the memory node that provides it.
The new sysfs representation is modeled from the existing cpu cacheinfo attributes, as seen from /sys/devices/system/cpu/<cpu>/cache/. Unlike CPU cacheinfo though, the node cache level is reported from the view of the memory. A higher level number is nearer to the CPU, while lower levels are closer to the last level memory.
The exported attributes are the cache size, the line size, associativity, and write back policy, and add the attributes for the system memory caches to sysfs stable documentation.
--- Documentation/ABI/stable/sysfs-devices-node | 35 +++++++ drivers/base/node.c | 151 ++++++++++++++++++++++++++++ include/linux/node.h | 34 +++++++ 3 files changed, 220 insertions(+)
Documentation/ABI/stable/sysfs-devices-node +35 -0
@@ -143,3 +143,38 @@ Contact: Keith Busch <[email protected]> Description: This node's write latency in nanoseconds when access from nodes found in this class's linked initiators. + +What: /sys/devices/system/node/nodeX/memory_side_cache/indexY/ +Date: December 2018 +Contact: Keith Busch <[email protected]> +Description: + The directory containing attributes for the memory-side cache + level 'Y'. + + The caches associativity: 0 for direct mapped, non-zero if +What: /sys/devices/system/node/nodeX/memory_side_cache/indexY/associativity +Date: December 2018 +Contact: Keith Busch <[email protected]> +Description: + The caches associativity: 0 for direct mapped, non-zero if + indexed. + +What: /sys/devices/system/node/nodeX/memory_side_cache/indexY/line_size +Date: December 2018 +Contact: Keith Busch <[email protected]> +Description: + The number of bytes accessed from the next cache level on a + cache miss. + +What: /sys/devices/system/node/nodeX/memory_side_cache/indexY/size +Date: December 2018 +Contact: Keith Busch <[email protected]> +Description: + The size of this memory side cache in bytes. + +What: /sys/devices/system/node/nodeX/memory_side_cache/indexY/write_policy +Date: December 2018 +Contact: Keith Busch <[email protected]> +Description: + The cache write policy: 0 for write-back, 1 for write-through, + other or unknown.
drivers/base/node.c +151 -0
169 lines not on this page · raw message
include/linux/node.h +34 -0
@@ -37,6 +37,36 @@ struct node_hmem_attrs { };void node_set_perf_attrs (unsigned int nid,struct node_hmem_attrs *hmem_attrs,unsigned access); + +enum cache_associativity { +NODE_CACHE_DIRECT_MAP , +NODE_CACHE_INDEXED , +NODE_CACHE_OTHER , +}; + +enum cache_write_policy { +NODE_CACHE_WRITE_BACK , +NODE_CACHE_WRITE_THROUGH , +NODE_CACHE_WRITE_OTHER , +}; + +/** +* struct node_cache_attrs - system memory caching attributes +* +* @associativity: The ways memory blocks may be placed in cache +* @write_policy: Write back or write through policy +* @size: Total size of cache in bytes +* @line_size: Number of bytes fetched on a cache miss +* @level: The cache hierarchy level +*/ +struct node_cache_attrs { +enum cache_associativity associativity; +enum cache_write_policy write_policy; +u64 size; +u16 line_size; +u8 level; +}; +void node_add_cache (unsigned int nid,struct node_cache_attrs *cache_attrs);#endif struct node {
@@ -45,6 +75,10 @@ struct node {#if defined(CONFIG_MEMORY_HOTPLUG_SPARSE ) && defined(CONFIG_HUGETLBFS )struct work_struct node_work;#endif +#ifdef CONFIG_HMEM_REPORTING +struct list_head cache_attrs; +struct device *cache_dev; +#endif };struct memory_block ;
Signature · 1 line
2.14.4
Re: [PATCHv6 06/10] node: Add memory-side caching attributes
Le 14/02/2019 à 18:10, Keith Busch a écrit :
Quoted 51 lines
System memory may have caches to help improve access speed to frequently requested address ranges. While the system provided cache is transparent to the software accessing these memory ranges, applications can optimize their own access based on cache attributes.
Provide a new API for the kernel to register these memory-side caches under the memory node that provides it.
The new sysfs representation is modeled from the existing cpu cacheinfo attributes, as seen from /sys/devices/system/cpu/<cpu>/cache/. Unlike CPU cacheinfo though, the node cache level is reported from the view of the memory. A higher level number is nearer to the CPU, while lower levels are closer to the last level memory.
The exported attributes are the cache size, the line size, associativity, and write back policy, and add the attributes for the system memory caches to sysfs stable documentation.
Signed-off-by Keith Busch <[email protected]>--- Documentation/ABI/stable/sysfs-devices-node | 35 +++++++ drivers/base/node.c | 151 ++++++++++++++++++++++++++++ include/linux/node.h | 34 +++++++ 3 files changed, 220 insertions(+)Documentation/ABI/stable/sysfs-devices-node +18
-0@@ -143,3 +143,38 @@ Contact: Keith Busch <[email protected]> Description: This node's write latency in nanoseconds when access from nodes found in this class's linked initiators. + +What: /sys/devices/system/node/nodeX/memory_side_cache/indexY/ +Date: December 2018 +Contact: Keith Busch <[email protected]> +Description: + The directory containing attributes for the memory-side cache + level 'Y'. + + The caches associativity: 0 for direct mapped, non-zero if +What: /sys/devices/system/node/nodeX/memory_side_cache/indexY/associativity +Date: December 2018 +Contact: Keith Busch <[email protected]> +Description: + The caches associativity: 0 for direct mapped, non-zero if + indexed. + +What: /sys/devices/system/node/nodeX/memory_side_cache/indexY/line_size +Date: December 2018
Documentation/ABI/stable/sysfs-devices-node Contact: Keith Busch <[email protected]> · line 173
Quoted 10 lines
Documentation/ABI/stable/sysfs-devices-node +10
-0+Contact: Keith Busch <[email protected]> +Description: + The number of bytes accessed from the next cache level on a + cache miss. + +What: /sys/devices/system/node/nodeX/memory_side_cache/indexY/size +Date: December 2018 +Contact: Keith Busch <[email protected]> +Description: + The size of this memory side cache in bytes.
Hello Keith,
CPU-side cache size is reported in kilobytes:
$ cat /sys/devices/system/cpu/cpu0/cache/index*/size
32K
32K
256K
4096K
Can you do the same of memory-side caches instead of reporting bytes?
Thanks
Brice
Re: [PATCHv6 06/10] node: Add memory-side caching attributes
Quoted 15 lines · Brice Goglin
Le 14/02/2019 à 18:10, Keith Busch a écrit :
Documentation/ABI/stable/sysfs-devices-node Contact: Keith Busch <[email protected]> · line 173
Quoted 5 lines
Documentation/ABI/stable/sysfs-devices-node +5
-0+What: /sys/devices/system/node/nodeX/memory_side_cache/indexY/size +Date: December 2018 +Contact: Keith Busch <[email protected]> +Description: + The size of this memory side cache in bytes.Hello Keith,
CPU-side cache size is reported in kilobytes:
$ cat /sys/devices/system/cpu/cpu0/cache/index*/size
Quoted 6 lines
32K
32K
256K
4096KCan you do the same of memory-side caches instead of reporting bytes?
Ok, will do.
Re: [PATCHv6 06/10] node: Add memory-side caching attributes
Quoted 17 lines · Keith Busch
Quoted 15 lines · Brice Goglin
Documentation/ABI/stable/sysfs-devices-node Contact: Keith Busch <[email protected]> · line 173
Quoted 5 lines · Keith Busch
Documentation/ABI/stable/sysfs-devices-node +5
-0+What: /sys/devices/system/node/nodeX/memory_side_cache/indexY/size +Date: December 2018 +Contact: Keith Busch <[email protected]> +Description: + The size of this memory side cache in bytes.Hello Keith,
CPU-side cache size is reported in kilobytes:
$ cat /sys/devices/system/cpu/cpu0/cache/index*/size
Quoted 8 lines
Quoted 6 lines
32K
32K
256K
4096KCan you do the same of memory-side caches instead of reporting bytes?
Ok, will do.
Ugh, please no. Don't optimize sysfs for human consumption. That 'K' now needs to be parsed.
Re: [PATCHv6 06/10] node: Add memory-side caching attributes
In reply to Keith BuschLe 14/02/2019 à 18:10, Keith Busch a écrit :
Quoted 38 lines
System memory may have caches to help improve access speed to frequently requested address ranges. While the system provided cache is transparent to the software accessing these memory ranges, applications can optimize their own access based on cache attributes.
Provide a new API for the kernel to register these memory-side caches under the memory node that provides it.
The new sysfs representation is modeled from the existing cpu cacheinfo attributes, as seen from /sys/devices/system/cpu/<cpu>/cache/. Unlike CPU cacheinfo though, the node cache level is reported from the view of the memory. A higher level number is nearer to the CPU, while lower levels are closer to the last level memory.
The exported attributes are the cache size, the line size, associativity, and write back policy, and add the attributes for the system memory caches to sysfs stable documentation.
Signed-off-by Keith Busch <[email protected]>--- Documentation/ABI/stable/sysfs-devices-node | 35 +++++++ drivers/base/node.c | 151 ++++++++++++++++++++++++++++ include/linux/node.h | 34 +++++++ 3 files changed, 220 insertions(+)Documentation/ABI/stable/sysfs-devices-node +5
-0@@ -143,3 +143,38 @@ Contact: Keith Busch <[email protected]> Description: This node's write latency in nanoseconds when access from nodes found in this class's linked initiators. + +What: /sys/devices/system/node/nodeX/memory_side_cache/indexY/ +Date: December 2018 +Contact: Keith Busch <[email protected]> +Description:
Documentation/ABI/stable/sysfs-devices-node Contact: Keith Busch <[email protected]> · line 160
Quoted 10 lines
Documentation/ABI/stable/sysfs-devices-node +10
-0+ The directory containing attributes for the memory-side cache + level 'Y'. + + The caches associativity: 0 for direct mapped, non-zero if +What: /sys/devices/system/node/nodeX/memory_side_cache/indexY/associativity +Date: December 2018 +Contact: Keith Busch <[email protected]> +Description: + The caches associativity: 0 for direct mapped, non-zero if + indexed.
Should we rename "associativity" into "indexing" or something else?
When I see "associativity" that contains 0, I tend to interpret this as the associativity value itself, which would mean fully-associative here (as in CPU-side cache "ways_of_associativity" attribute), while actually 0 means direct-mapped (ie 1-associative) with yout semantics.
Brice
Re: [PATCHv6 06/10] node: Add memory-side caching attributes
Quoted 11 lines · Brice Goglin
Le 14/02/2019 à 18:10, Keith Busch a écrit :
Documentation/ABI/stable/sysfs-devices-node Contact: Keith Busch <[email protected]> · line 160
Quoted 6 lines
Documentation/ABI/stable/sysfs-devices-node +6
-0+What: /sys/devices/system/node/nodeX/memory_side_cache/indexY/associativity +Date: December 2018 +Contact: Keith Busch <[email protected]> +Description: + The caches associativity: 0 for direct mapped, non-zero if + indexed.Should we rename "associativity" into "indexing" or something else?
Quoted 6 lines
When I see "associativity" that contains 0, I tend to interpret this as the associativity value itself, which would mean fully-associative here (as in CPU-side cache "
ways_of_associativity" attribute), while actually 0 means direct-mapped (ie 1-associative) with yout semantics.Brice
Yes, that's a good suggestion.
PATCH v6 7/10 acpi/hmat: Register processor domain to its memory
In reply to Keith BuschIf the HMAT Subsystem Address Range provides a valid processor proximity domain for a memory domain, or a processor domain matches the performance access of the valid processor proximity domain, register the memory target with that initiator so this relationship will be visible under the node's sysfs directory.
By registering only the best performing relationships, this provides the most useful information applications may want to know when considering which CPU they should run on for a given memory node, or which memory node they should allocate memory from for a given CPU.
Since HMAT requires valid address ranges have an equivalent SRAT entry, verify each memory target satisfies this requirement.
--- drivers/acpi/hmat/Kconfig | 1 + drivers/acpi/hmat/hmat.c | 396 +++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 396 insertions(+), 1 deletion(-)
drivers/acpi/hmat/Kconfig +1 -0
@@ -2,6 +2,7 @@ config ACPI_HMAT bool "ACPI Heterogeneous Memory Attribute Table Support" depends on ACPI_NUMA + select HMEM_REPORTING help If set, this option causes the kernel to set the memory NUMA node relationships and access attributes in accordance with ACPI HMAT
drivers/acpi/hmat/hmat.c +395 -1
472 lines not on this page · raw message
Signature · 1 line
2.14.4
Rafael J. Wysocki
maintainerRe: [PATCHv6 07/10] acpi/hmat: Register processor domain to its memory
Quoted 26 lines · Keith Busch
If the HMAT Subsystem Address Range provides a valid processor proximity domain for a memory domain, or a processor domain matches the performance access of the valid processor proximity domain, register the memory target with that initiator so this relationship will be visible under the node's sysfs directory.
By registering only the best performing relationships, this provides the most useful information applications may want to know when considering which CPU they should run on for a given memory node, or which memory node they should allocate memory from for a given CPU.
Since HMAT requires valid address ranges have an equivalent SRAT entry, verify each memory target satisfies this requirement.
Signed-off-by Keith Busch <[email protected]>--- drivers/acpi/hmat/Kconfig | 1 + drivers/acpi/hmat/hmat.c | 396 +++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 396 insertions(+), 1 deletion(-)drivers/acpi/hmat/Kconfig +0
-0
drivers/acpi/hmat/Kconfig line 5
Quoted 4 lines
drivers/acpi/hmat/Kconfig +1
-0@@ -2,6 +2,7 @@ config ACPI_HMAT bool "ACPI Heterogeneous Memory Attribute Table Support" depends on ACPI_NUMA + select HMEM_REPORTING
If you want to do this here, I'm not sure that defining HMEM_REPORTING as a user-selectable option is a good idea. In particular, I don't really think that setting ACPI_HMAT without it makes a lot of sense. Apart from this, the patch looks reasonable to me.
Re: [PATCHv6 07/10] acpi/hmat: Register processor domain to its memory
Quoted 5 lines · Rafael J. Wysocki
Quoted 5 lines
drivers/acpi/hmat/Kconfig +0
-0@@ -2,6 +2,7 @@
Quoted 8 lines
drivers/acpi/hmat/Kconfig line 5
Quoted 4 lines
drivers/acpi/hmat/Kconfig +1
-0config ACPI_HMAT bool "ACPI Heterogeneous Memory Attribute Table Support" depends on ACPI_NUMA + select HMEM_REPORTINGIf you want to do this here, I'm not sure that defining
HMEM_REPORTINGas a user-selectable option is a good idea. In particular, I don't really think that settingACPI_HMATwithout it makes a lot of sense. Apart from this, the patch looks reasonable to me.
I guess the question is whether we would want to allow folks to consume the HMAT inside the kernel while not reporting it out via HMEM_REPORTING. We have some in-kernel users of the HMAT lined up like mitigations for memory-side caches.
It's certainly possible that folks would want to consume those mitigations without anything in sysfs. They might not even want or need NUMA support itself, for instance.
So, what should we do?
config HMEM_REPORTING
bool # no user-visible prompt
default y if ACPI_HMAT
So folks can override in their .config, but they don't see a prompt?
Re: [PATCHv6 07/10] acpi/hmat: Register processor domain to its memory
Quoted 25 lines · Dave Hansen
Quoted 5 lines · Rafael J. Wysocki
Quoted 5 lines
drivers/acpi/hmat/Kconfig +0
-0@@ -2,6 +2,7 @@Quoted 8 lines
drivers/acpi/hmat/Kconfig line 5
Quoted 4 lines
drivers/acpi/hmat/Kconfig +1
-0config ACPI_HMAT bool "ACPI Heterogeneous Memory Attribute Table Support" depends on ACPI_NUMA + select HMEM_REPORTINGIf you want to do this here, I'm not sure that defining
HMEM_REPORTINGas a user-selectable option is a good idea. In particular, I don't really think that settingACPI_HMATwithout it makes a lot of sense. Apart from this, the patch looks reasonable to me.I guess the question is whether we would want to allow folks to consume the HMAT inside the kernel while not reporting it out via
HMEM_REPORTING. We have some in-kernel users of the HMAT lined up like mitigations for memory-side caches.It's certainly possible that folks would want to consume those mitigations without anything in sysfs. They might not even want or need NUMA support itself, for instance.
Quoted 7 lines
So, what should we do?
config
HMEM_REPORTING
bool # no user-visible prompt
default y ifACPI_HMATSo folks can override in their .config, but they don't see a prompt?
I would add an "&& ACPI_NUMA" to that default as well.
Rafael J. Wysocki
maintainerRe: [PATCHv6 07/10] acpi/hmat: Register processor domain to its memory
Quoted 29 lines · Dan Williams
Quoted 27 lines · Dave Hansen
Quoted 5 lines · Rafael J. Wysocki
Quoted 5 lines
drivers/acpi/hmat/Kconfig +0
-0@@ -2,6 +2,7 @@Quoted 8 lines
drivers/acpi/hmat/Kconfig line 5
Quoted 4 lines
drivers/acpi/hmat/Kconfig +1
-0config ACPI_HMAT bool "ACPI Heterogeneous Memory Attribute Table Support" depends on ACPI_NUMA + select HMEM_REPORTINGIf you want to do this here, I'm not sure that defining
HMEM_REPORTINGas a user-selectable option is a good idea. In particular, I don't really think that settingACPI_HMATwithout it makes a lot of sense. Apart from this, the patch looks reasonable to me.I guess the question is whether we would want to allow folks to consume the HMAT inside the kernel while not reporting it out via
HMEM_REPORTING. We have some in-kernel users of the HMAT lined up like mitigations for memory-side caches.It's certainly possible that folks would want to consume those mitigations without anything in sysfs. They might not even want or need NUMA support itself, for instance.
So, what should we do?
Quoted 7 lines
Quoted 5 lines
config
HMEM_REPORTING
bool # no user-visible prompt
default y ifACPI_HMATSo folks can override in their .config, but they don't see a prompt?
I would add an "&&
ACPI_NUMA" to that default as well.
But ACPI_HMAT depends on ACPI_NUMA already, or am I missing anything?
Re: [PATCHv6 07/10] acpi/hmat: Register processor domain to its memory
Quoted 35 lines · Rafael J. Wysocki
Quoted 33 lines · Dan Williams
Quoted 31 lines · Dave Hansen
Quoted 5 lines · Rafael J. Wysocki
Quoted 5 lines
drivers/acpi/hmat/Kconfig +0
-0@@ -2,6 +2,7 @@Quoted 8 lines
drivers/acpi/hmat/Kconfig line 5
Quoted 4 lines
drivers/acpi/hmat/Kconfig +1
-0config ACPI_HMAT bool "ACPI Heterogeneous Memory Attribute Table Support" depends on ACPI_NUMA + select HMEM_REPORTINGIf you want to do this here, I'm not sure that defining
HMEM_REPORTINGas a user-selectable option is a good idea. In particular, I don't really think that settingACPI_HMATwithout it makes a lot of sense. Apart from this, the patch looks reasonable to me.I guess the question is whether we would want to allow folks to consume the HMAT inside the kernel while not reporting it out via
HMEM_REPORTING. We have some in-kernel users of the HMAT lined up like mitigations for memory-side caches.It's certainly possible that folks would want to consume those mitigations without anything in sysfs. They might not even want or need NUMA support itself, for instance.
So, what should we do?
config
HMEM_REPORTING
bool # no user-visible prompt
default y ifACPI_HMAT
Quoted 5 lines
Quoted 3 lines
Quoted 1 line
So folks can override in their .config, but they don't see a prompt?
I would add an "&&
ACPI_NUMA" to that default as well.But
ACPI_HMATdepends onACPI_NUMAalready, or am I missing anything?
Oh, my mistake, sorry.
Rafael J. Wysocki
maintainerRe: [PATCHv6 07/10] acpi/hmat: Register processor domain to its memory
In reply to Dave HansenQuoted 25 lines · Dave Hansen
Quoted 5 lines · Rafael J. Wysocki
Quoted 5 lines
drivers/acpi/hmat/Kconfig +0
-0@@ -2,6 +2,7 @@Quoted 8 lines
drivers/acpi/hmat/Kconfig line 5
Quoted 4 lines
drivers/acpi/hmat/Kconfig +1
-0config ACPI_HMAT bool "ACPI Heterogeneous Memory Attribute Table Support" depends on ACPI_NUMA + select HMEM_REPORTINGIf you want to do this here, I'm not sure that defining
HMEM_REPORTINGas a user-selectable option is a good idea. In particular, I don't really think that settingACPI_HMATwithout it makes a lot of sense. Apart from this, the patch looks reasonable to me.I guess the question is whether we would want to allow folks to consume the HMAT inside the kernel while not reporting it out via
HMEM_REPORTING. We have some in-kernel users of the HMAT lined up like mitigations for memory-side caches.It's certainly possible that folks would want to consume those mitigations without anything in sysfs. They might not even want or need NUMA support itself, for instance.
Quoted 7 lines
So, what should we do?
config
HMEM_REPORTING
bool # no user-visible prompt
default y ifACPI_HMATSo folks can override in their .config, but they don't see a prompt?
Maybe it would be better to make HMEM_REPORTING do "select ACPI_HMAT if ACPI".
The mitigations could then do that too if they depend on HMAT and ACPI_HMAT need not be user-visible at all.
Re: [PATCHv6 07/10] acpi/hmat: Register processor domain to its memory
Quoted 31 lines · Rafael J. Wysocki
Quoted 30 lines · Dave Hansen
Quoted 5 lines · Rafael J. Wysocki
Quoted 5 lines
drivers/acpi/hmat/Kconfig +0
-0@@ -2,6 +2,7 @@Quoted 8 lines
drivers/acpi/hmat/Kconfig line 5
Quoted 4 lines
drivers/acpi/hmat/Kconfig +1
-0config ACPI_HMAT bool "ACPI Heterogeneous Memory Attribute Table Support" depends on ACPI_NUMA + select HMEM_REPORTINGIf you want to do this here, I'm not sure that defining
HMEM_REPORTINGas a user-selectable option is a good idea. In particular, I don't really think that settingACPI_HMATwithout it makes a lot of sense. Apart from this, the patch looks reasonable to me.I guess the question is whether we would want to allow folks to consume the HMAT inside the kernel while not reporting it out via
HMEM_REPORTING. We have some in-kernel users of the HMAT lined up like mitigations for memory-side caches.It's certainly possible that folks would want to consume those mitigations without anything in sysfs. They might not even want or need NUMA support itself, for instance.
So, what should we do?
config
HMEM_REPORTING
bool # no user-visible prompt
default y ifACPI_HMAT
Quoted 6 lines
Quoted 1 line
So folks can override in their .config, but they don't see a prompt?
Maybe it would be better to make
HMEM_REPORTINGdo "selectACPI_HMATif ACPI".The mitigations could then do that too if they depend on HMAT and
ACPI_HMATneed not be user-visible at all.
That sounds okay, though it would create unreachable code if !ACPI since that's the only user for the new reporting interfaces.
Rafael J. Wysocki
maintainerRe: [PATCHv6 07/10] acpi/hmat: Register processor domain to its memory
Quoted 35 lines · Keith Busch
Quoted 33 lines · Rafael J. Wysocki
Quoted 31 lines · Dave Hansen
Quoted 5 lines · Rafael J. Wysocki
Quoted 5 lines
drivers/acpi/hmat/Kconfig +0
-0@@ -2,6 +2,7 @@Quoted 8 lines
drivers/acpi/hmat/Kconfig line 5
Quoted 4 lines
drivers/acpi/hmat/Kconfig +1
-0config ACPI_HMAT bool "ACPI Heterogeneous Memory Attribute Table Support" depends on ACPI_NUMA + select HMEM_REPORTINGIf you want to do this here, I'm not sure that defining
HMEM_REPORTINGas a user-selectable option is a good idea. In particular, I don't really think that settingACPI_HMATwithout it makes a lot of sense. Apart from this, the patch looks reasonable to me.I guess the question is whether we would want to allow folks to consume the HMAT inside the kernel while not reporting it out via
HMEM_REPORTING. We have some in-kernel users of the HMAT lined up like mitigations for memory-side caches.It's certainly possible that folks would want to consume those mitigations without anything in sysfs. They might not even want or need NUMA support itself, for instance.
So, what should we do?
config
HMEM_REPORTING
bool # no user-visible prompt
default y ifACPI_HMATSo folks can override in their .config, but they don't see a prompt?
Quoted 7 lines
Quoted 4 lines
Maybe it would be better to make
HMEM_REPORTINGdo "selectACPI_HMATif ACPI".The mitigations could then do that too if they depend on HMAT and
ACPI_HMATneed not be user-visible at all.That sounds okay, though it would create unreachable code if !ACPI since that's the only user for the new reporting interfaces.
Until there are other users of it, you can make HMEM_REPORTING depend on ACPI_NUMA and select ACPI_HMAT.
Re: [PATCHv6 07/10] acpi/hmat: Register processor domain to its memory
In reply to Rafael J. WysockiQuoted 10 lines · Rafael J. Wysocki
Quoted 4 lines · Keith Busch
config
ACPI_HMAT
bool "ACPI Heterogeneous Memory Attribute Table Support" depends onACPI_NUMA
+ selectHMEM_REPORTINGIf you want to do this here, I'm not sure that defining
HMEM_REPORTINGas a user-selectable option is a good idea. In particular, I don't really think that settingACPI_HMATwithout it makes a lot of sense. Apart from this, the patch looks reasonable to me.
I'm trying to implement based on the feedback, but I'm a little confused.
As I have it at the moment, HMEM_REPORTING is not user-prompted, so another option needs to turn it on. I have ACPI_HMAT do that here.
So when you say it's a bad idea to make HMEM_REPORTING user selectable, isn't it already not user selectable?
If I do it the other way around, that's going to make HMEM_REPORTING complicated if a non-ACPI implementation wants to report HMEM properties.
Re: [PATCHv6 07/10] acpi/hmat: Register processor domain to its memory
Quoted 18 lines · Keith Busch
Quoted 10 lines · Rafael J. Wysocki
Quoted 4 lines · Keith Busch
config
ACPI_HMAT
bool "ACPI Heterogeneous Memory Attribute Table Support" depends onACPI_NUMA
+ selectHMEM_REPORTINGIf you want to do this here, I'm not sure that defining
HMEM_REPORTINGas a user-selectable option is a good idea. In particular, I don't really think that settingACPI_HMATwithout it makes a lot of sense. Apart from this, the patch looks reasonable to me.I'm trying to implement based on the feedback, but I'm a little confused.
As I have it at the moment,
HMEM_REPORTINGis not user-prompted, so another option needs to turn it on. I haveACPI_HMATdo that here.
Quoted 6 lines
So when you say it's a bad idea to make
HMEM_REPORTINGuser selectable, isn't it already not user selectable?If I do it the other way around, that's going to make
HMEM_REPORTINGcomplicated if a non-ACPI implementation wants to report HMEM properties.
Agree. If a platform supports these HMEM properties then they should be reported. ACPI_HMAT is that opt-in for ACPI based platforms, and other archs can do something similar. It's not clear that one would ever want to opt-in to HMAT support and opt-out of reporting any of it to userspace.
Rafael J. Wysocki
maintainerRe: [PATCHv6 07/10] acpi/hmat: Register processor domain to its memory
Quoted 23 lines · Dan Williams
Quoted 21 lines · Keith Busch
Quoted 10 lines · Rafael J. Wysocki
Quoted 4 lines · Keith Busch
config
ACPI_HMAT
bool "ACPI Heterogeneous Memory Attribute Table Support" depends onACPI_NUMA
+ selectHMEM_REPORTINGIf you want to do this here, I'm not sure that defining
HMEM_REPORTINGas a user-selectable option is a good idea. In particular, I don't really think that settingACPI_HMATwithout it makes a lot of sense. Apart from this, the patch looks reasonable to me.I'm trying to implement based on the feedback, but I'm a little confused.
As I have it at the moment,
HMEM_REPORTINGis not user-prompted, so another option needs to turn it on. I haveACPI_HMATdo that here.So when you say it's a bad idea to make
HMEM_REPORTINGuser selectable, isn't it already not user selectable?
Quoted 6 lines
Quoted 3 lines
If I do it the other way around, that's going to make
HMEM_REPORTINGcomplicated if a non-ACPI implementation wants to report HMEM properties.Agree. If a platform supports these HMEM properties then they should be reported.
Well, I'm not sure if everybody is in agreement on that.
Quoted 4 lines
ACPI_HMATis that opt-in for ACPI based platforms, and other archs can do something similar. It's not clear that one would ever want to opt-in to HMAT support and opt-out of reporting any of it to userspace.
In my view, ACPI_HMAT need not be an opt-in in the first place. The only reason to avoid compiling HMAT parsing it would be if there were no users of it in the kernel IMO.
Rafael J. Wysocki
maintainerRe: [PATCHv6 07/10] acpi/hmat: Register processor domain to its memory
In reply to Keith BuschQuoted 13 lines · Keith Busch
Quoted 10 lines · Rafael J. Wysocki
Quoted 4 lines · Keith Busch
config
ACPI_HMAT
bool "ACPI Heterogeneous Memory Attribute Table Support" depends onACPI_NUMA
+ selectHMEM_REPORTINGIf you want to do this here, I'm not sure that defining
HMEM_REPORTINGas a user-selectable option is a good idea. In particular, I don't really think that settingACPI_HMATwithout it makes a lot of sense. Apart from this, the patch looks reasonable to me.
Quoted 7 lines
I'm trying to implement based on the feedback, but I'm a little confused.
As I have it at the moment,
HMEM_REPORTINGis not user-prompted, so another option needs to turn it on. I haveACPI_HMATdo that here.So when you say it's a bad idea to make
HMEM_REPORTINGuser selectable, isn't it already not user selectable?
I thought that HMEM_REPORTING was user-prompted initially, by bad if it wasn't.
Quoted 3 lines
If I do it the other way around, that's going to make
HMEM_REPORTINGcomplicated if a non-ACPI implementation wants to report HMEM properties.
But the mitigations that Dave was talking about get in the way, don't they?
Say there is another Kconfig option,CACHE_MITIGATIONS, to enable them. Then you want ACPI_HMAT to be set when that it set and you also want ACPI_HMAT to be set when HMEM_REPORTING and ACPI_NUMA are both set.
OTOH, you may not want HMEM_REPORTING to be set when CACHE_MITIGATIONS is set, but that causes ACPI_HMAT to be set and which means that ACPI_HMAT alone will not be sufficient to determine the HMEM_REPORTING value.
Now, if you prompt for HMEM_REPORTING and make it depend on ACPI_NUMA, then ACPI_HMAT can be selected by that (regardless of the CACHE_MITIGATIONS value).
And if someone wants to use HMEM_REPORTING without ACPI_NUMA, it can be made depend on whatever new option is there for that non-ACPI mechanism.
There might be a problem if someone wanted to enable the alternative way of HMEM_REPORTING if ACPI_NUMA was set (in which case HMAT would have to be ignored even if it was present), but in that case there would need to be an explicit way to choose between HMAT and non-HMAT anyway.
In any case, I prefer providers to be selected by consumers and not the other way around, in case there are multiple consumers for one provider.
Re: [PATCHv6 07/10] acpi/hmat: Register processor domain to its memory
Quoted 7 lines · Rafael J. Wysocki
Quoted 3 lines · Keith Busch
If I do it the other way around, that's going to make
HMEM_REPORTINGcomplicated if a non-ACPI implementation wants to report HMEM properties.But the mitigations that Dave was talking about get in the way, don't they?
Quoted 8 lines
Say there is another
Kconfigoption,CACHE_MITIGATIONS, to enable them. Then you wantACPI_HMATto be set when that it set and you also wantACPI_HMATto be set whenHMEM_REPORTINGandACPI_NUMAare both set.OTOH, you may not want
HMEM_REPORTINGto be set whenCACHE_MITIGATIONSis set, but that causesACPI_HMATto be set and which means thatACPI_HMATalone will not be sufficient to determine theHMEM_REPORTINGvalue.
I can't think of when we'd want to suppress reporting these attributes to user space, but I can split HMAT enabling so it doesn't depend on HMEM_REPORTING just in case there really is an in-kernel user that definitely does not want the same attributes exported.
Quoted 14 lines
Now, if you prompt for
HMEM_REPORTINGand make it depend onACPI_NUMA, thenACPI_HMATcan be selected by that (regardless of theCACHE_MITIGATIONSvalue).And if someone wants to use
HMEM_REPORTINGwithoutACPI_NUMA, it can be made depend on whatever new option is there for that non-ACPI mechanism.There might be a problem if someone wanted to enable the alternative way of
HMEM_REPORTINGifACPI_NUMAwas set (in which case HMAT would have to be ignored even if it was present), but in that case there would need to be an explicit way to choose between HMAT and non-HMAT anyway.
Quoted 3 lines
In any case, I prefer providers to be selected by consumers and not the other way around, in case there are multiple consumers for one provider.
Well, the HMEM_REPORTING fundamentally has no dependency on any of these things and I've put some effort into making this part provider agnostic. I will change it if this concern is gating acceptance, but I don't think it's as intuitive for generic interfaces to be the selector for implementation specific providers.
Rafael J. Wysocki
maintainerRe: [PATCHv6 07/10] acpi/hmat: Register processor domain to its memory
Quoted 18 lines · Keith Busch
Quoted 7 lines · Rafael J. Wysocki
Quoted 3 lines · Keith Busch
If I do it the other way around, that's going to make
HMEM_REPORTINGcomplicated if a non-ACPI implementation wants to report HMEM properties.But the mitigations that Dave was talking about get in the way, don't they?
Quoted 8 lines
Say there is another
Kconfigoption,CACHE_MITIGATIONS, to enable them. Then you wantACPI_HMATto be set when that it set and you also wantACPI_HMATto be set whenHMEM_REPORTINGandACPI_NUMAare both set.OTOH, you may not want
HMEM_REPORTINGto be set whenCACHE_MITIGATIONSis set, but that causesACPI_HMATto be set and which means thatACPI_HMATalone will not be sufficient to determine theHMEM_REPORTINGvalue.
Quoted 4 lines
I can't think of when we'd want to suppress reporting these attributes to user space, but I can split HMAT enabling so it doesn't depend on
HMEM_REPORTINGjust in case there really is an in-kernel user that definitely does not want the same attributes exported.
I'd rather simplify HMAT enabling than make it more complicated, so splitting it would be worse than what you have already IMO.
Quoted 14 lines
Quoted 14 lines
Now, if you prompt for
HMEM_REPORTINGand make it depend onACPI_NUMA, thenACPI_HMATcan be selected by that (regardless of theCACHE_MITIGATIONSvalue).And if someone wants to use
HMEM_REPORTINGwithoutACPI_NUMA, it can be made depend on whatever new option is there for that non-ACPI mechanism.There might be a problem if someone wanted to enable the alternative way of
HMEM_REPORTINGifACPI_NUMAwas set (in which case HMAT would have to be ignored even if it was present), but in that case there would need to be an explicit way to choose between HMAT and non-HMAT anyway.
Quoted 6 lines
Quoted 3 lines
In any case, I prefer providers to be selected by consumers and not the other way around, in case there are multiple consumers for one provider.
Well, the
HMEM_REPORTINGfundamentally has no dependency on any of these things and I've put some effort into making this part provider agnostic.
Which I agree with.
Quoted 3 lines
I will change it if this concern is gating acceptance, but I don't think it's as intuitive for generic interfaces to be the selector for implementation specific providers.
That is sort of a chicken-and-egg issue about what is more fundamental that could be discussed forever. :-)
My original point was that if you regard ACPI_HMAT as the more fundamental thing, then you should prompt for it and select HMEM_REPORTING automatically from there. Or the other way around if you regard HMEM_REPORTING as more fundamental. Prompting for both of them may lead to issues.
As long as that is taken into account, I'm basically fine with any of the two choices.
Re: [PATCHv6 07/10] acpi/hmat: Register processor domain to its memory
In reply to Keith BuschLe 14/02/2019 à 18:10, Keith Busch a écrit :
Quoted 15 lines
If the HMAT Subsystem Address Range provides a valid processor proximity domain for a memory domain, or a processor domain matches the performance access of the valid processor proximity domain, register the memory target with that initiator so this relationship will be visible under the node's sysfs directory.
By registering only the best performing relationships, this provides the most useful information applications may want to know when considering which CPU they should run on for a given memory node, or which memory node they should allocate memory from for a given CPU.
Since HMAT requires valid address ranges have an equivalent SRAT entry, verify each memory target satisfies this requirement.
Signed-off-by Keith Busch <[email protected]>
[...]
drivers/acpi/hmat/hmat.c line 64
Quoted 9 lines
drivers/acpi/hmat/hmat.c +9
-0+static __init struct memory_initiator *find_mem_initiator (unsigned int cpu_pxm) +{ +struct memory_initiator *intitator; + +list_for_each_entry (intitator, &initiators, node) +if (intitator->processor_pxm == cpu_pxm) +return intitator; +return NULL ; +}
Typo intitator -> initiator
Quoted 8 lines
drivers/acpi/hmat/hmat.c +8
-0+static __init void alloc_memory_initiator (unsigned int cpu_pxm) +{ +struct memory_initiator *intitator; + +if (pxm_to_node (cpu_pxm) ==NUMA_NO_NODE ) +return ; + + intitator =find_mem_initiator (cpu_pxm);
drivers/acpi/hmat/hmat.c line 93
Quoted 10 lines
drivers/acpi/hmat/hmat.c +10
-0+if (intitator) +return ; + + intitator =kzalloc (sizeof (*intitator),GFP_KERNEL ); +if (!intitator) +return ; + + intitator->processor_pxm = cpu_pxm; +list_add_tail (&intitator->node, &initiators); +}
Same typo
drivers/acpi/hmat/hmat.c static int __init hmat_parse_subtable(union acpi_subtable_headers *header, · line 498
Quoted 11 lines
drivers/acpi/hmat/hmat.c +11
-0+static __init void hmat_register_target_initiators (struct memory_target *target) +{ + static DECLARE_BITMAP(p_nodes, MAX_NUMNODES); +struct memory_initiator *initiator; +unsigned int mem_nid, cpu_nid; +struct memory_locality *loc =NULL ; +u32 best =0 ; +int i; + +if (target->processor_pxm ==PXM_INVAL ) +return ;
This test above looks wrong to me. First, it means that either you return from here, or from the next branch below, hence the loop that looks for best performance is dead code. Secondly, it means that memory targets without a PXM never get an initiator.
I verified that removing this test makes things look better on my HMAT tests.
drivers/acpi/hmat/hmat.c static int __init hmat_parse_subtable(union acpi_subtable_headers *header, · line 511
Quoted 12 lines
drivers/acpi/hmat/hmat.c +12
-0+ mem_nid =pxm_to_node (target->memory_pxm); + +/* +* If the Address Range Structure provides a local processor pxm, link +* only that one. Otherwise, find the best performance attribtes and +* register all initiators that match. +*/ +if (target->processor_pxm !=PXM_INVAL ) { + cpu_nid =pxm_to_node (target->processor_pxm); +register_memory_node_under_compute_node (mem_nid, cpu_nid,0 ); +return ; + }
This seems to contradict your first paragraph in the header where you say
"or a processor domain matches the performance access of the valid processor proximity domain".
By returning here, you're only keeping the the local PXM and ignoring other initiators that may have the same performance.
I am testing a HMAT where one memory target has same performance to two processor proxdomains. If no processor proxdomain is set in the HMAT for this target, I get two initiators as expected. If proxdomain is explicitly set in the HMAT, I get only that one as initiator.
Brice
Re: [PATCHv6 07/10] acpi/hmat: Register processor domain to its memory
Hi Brice,
Please see v7 of this series from last week instead for reviews:
PATCH v6 8/10 acpi/hmat: Register performance attributes
In reply to Keith BuschSave the best performance access attributes and register these with the memory's node if HMAT provides the locality table. While HMAT does make it possible to know performance for all possible initiator-target pairings, we export only the local pairings at this time.
--- drivers/acpi/hmat/hmat.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-)
drivers/acpi/hmat/hmat.c +16 -1
@@ -549,12 +549,27 @@ static __init void hmat_register_target_initiators(struct memory_target *target) } } +static __init void hmat_register_target_perf (struct memory_target *target) +{ +unsigned mem_nid =pxm_to_node (target->memory_pxm); + +if (!target->hmem_attrs.read_bandwidth && + !target->hmem_attrs.read_latency && + !target->hmem_attrs.write_bandwidth && + !target->hmem_attrs.write_latency) +return ; + +node_set_perf_attrs (mem_nid, &target->hmem_attrs,0 ); +} +static __init void hmat_register_targets (void ) {struct memory_target *target; -list_for_each_entry (target, &targets, node) +list_for_each_entry (target, &targets, node) {hmat_register_target_initiators (target); +hmat_register_target_perf (target); + } }static __init void hmat_free_structures (void )
Signature · 1 line
2.14.4
Re: [PATCHv6 08/10] acpi/hmat: Register performance attributes
Quoted 7 lines · Keith Busch
Save the best performance access attributes and register these with the memory's node if HMAT provides the locality table. While HMAT does make it possible to know performance for all possible initiator-target pairings, we export only the local pairings at this time.
Signed-off-by Keith Busch <[email protected]>
Quoted 40 lines
--- drivers/acpi/hmat/hmat.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-)drivers/acpi/hmat/hmat.c +16
-2@@ -549,12 +549,27 @@ static __init void hmat_register_target_initiators(struct memory_target *target) } } +static __init void hmat_register_target_perf (struct memory_target *target) +{ +unsigned mem_nid =pxm_to_node (target->memory_pxm); + +if (!target->hmem_attrs.read_bandwidth && + !target->hmem_attrs.read_latency && + !target->hmem_attrs.write_bandwidth && + !target->hmem_attrs.write_latency) +return ; + +node_set_perf_attrs (mem_nid, &target->hmem_attrs,0 ); +} +static __init void hmat_register_targets (void ) {struct memory_target *target; -list_for_each_entry (target, &targets, node) +list_for_each_entry (target, &targets, node) {hmat_register_target_initiators (target); +hmat_register_target_perf (target); + } }static __init void hmat_free_structures (void ) --2.14.4
PATCH v6 9/10 acpi/hmat: Register memory side cache attributes
In reply to Keith BuschRegister memory side cache attributes with the memory's node if HMAT provides the side cache iniformation table.
--- drivers/acpi/hmat/hmat.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+)
drivers/acpi/hmat/hmat.c +32 -0
@@ -314,6 +314,7 @@ static __init int hmat_parse_cache(union acpi_subtable_headers *header, const unsigned long end) {struct acpi_hmat_cache *cache = (void *)header; +struct node_cache_attrs cache_attrs;u32 attrs;if (cache->header.length <sizeof (*cache)) {
@@ -327,6 +328,37 @@ static __init int hmat_parse_cache(union acpi_subtable_headers *header, cache->memory_PD, cache->cache_size, attrs, cache->number_of_SMBIOShandles); + cache_attrs.size = cache->cache_size; + cache_attrs.level = (attrs &ACPI_HMAT_CACHE_LEVEL ) >>4 ; + cache_attrs.line_size = (attrs &ACPI_HMAT_CACHE_LINE_SIZE ) >>16 ; + +switch ((attrs &ACPI_HMAT_CACHE_ASSOCIATIVITY ) >>8 ) { +case ACPI_HMAT_CA_DIRECT_MAPPED : + cache_attrs.associativity =NODE_CACHE_DIRECT_MAP ; +break ; +case ACPI_HMAT_CA_COMPLEX_CACHE_INDEXING : + cache_attrs.associativity =NODE_CACHE_INDEXED ; +break ; +case ACPI_HMAT_CA_NONE : +default : + cache_attrs.associativity =NODE_CACHE_OTHER ; +break ; + } + +switch ((attrs &ACPI_HMAT_WRITE_POLICY ) >>12 ) { +case ACPI_HMAT_CP_WB : + cache_attrs.write_policy =NODE_CACHE_WRITE_BACK ; +break ; +case ACPI_HMAT_CP_WT : + cache_attrs.write_policy =NODE_CACHE_WRITE_THROUGH ; +break ; +case ACPI_HMAT_CP_NONE : +default : + cache_attrs.write_policy =NODE_CACHE_WRITE_OTHER ; +break ; + } + +node_add_cache (pxm_to_node (cache->memory_PD), &cache_attrs);return 0 ; }
Signature · 1 line
2.14.4
Re: [PATCHv6 09/10] acpi/hmat: Register memory side cache attributes
Quoted 5 lines · Keith Busch
Register memory side cache attributes with the memory's node if HMAT provides the side cache iniformation table.
Signed-off-by Keith Busch <[email protected]>
Quoted 57 lines
--- drivers/acpi/hmat/hmat.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+)drivers/acpi/hmat/hmat.c +32
-1@@ -314,6 +314,7 @@ static __init int hmat_parse_cache(union acpi_subtable_headers *header, const unsigned long end) {struct acpi_hmat_cache *cache = (void *)header; +struct node_cache_attrs cache_attrs;u32 attrs;if (cache->header.length <sizeof (*cache)) {@@ -327,6 +328,37 @@ static __init int hmat_parse_cache(union acpi_subtable_headers *header, cache->memory_PD, cache->cache_size, attrs, cache->number_of_SMBIOShandles); + cache_attrs.size = cache->cache_size; + cache_attrs.level = (attrs &ACPI_HMAT_CACHE_LEVEL ) >>4 ; + cache_attrs.line_size = (attrs &ACPI_HMAT_CACHE_LINE_SIZE ) >>16 ; + +switch ((attrs &ACPI_HMAT_CACHE_ASSOCIATIVITY ) >>8 ) { +case ACPI_HMAT_CA_DIRECT_MAPPED : + cache_attrs.associativity =NODE_CACHE_DIRECT_MAP ; +break ; +case ACPI_HMAT_CA_COMPLEX_CACHE_INDEXING : + cache_attrs.associativity =NODE_CACHE_INDEXED ; +break ; +case ACPI_HMAT_CA_NONE : +default : + cache_attrs.associativity =NODE_CACHE_OTHER ; +break ; + } + +switch ((attrs &ACPI_HMAT_WRITE_POLICY ) >>12 ) { +case ACPI_HMAT_CP_WB : + cache_attrs.write_policy =NODE_CACHE_WRITE_BACK ; +break ; +case ACPI_HMAT_CP_WT : + cache_attrs.write_policy =NODE_CACHE_WRITE_THROUGH ; +break ; +case ACPI_HMAT_CP_NONE : +default : + cache_attrs.write_policy =NODE_CACHE_WRITE_OTHER ; +break ; + } + +node_add_cache (pxm_to_node (cache->memory_PD), &cache_attrs);return 0 ; } --2.14.4
PATCH v6 10/10 doc/mm: New documentation for memory performance
In reply to Keith BuschPlatforms may provide system memory where some physical address ranges perform differently than others, or is side cached by the system.
Add documentation describing a high level overview of such systems and the perforamnce and caching attributes the kernel provides for applications wishing to query this information.
--- Documentation/admin-guide/mm/numaperf.rst | 164 ++++++++++++++++++++++++++++++ 1 file changed, 164 insertions(+) create mode 100644 Documentation/admin-guide/mm/numaperf.rst
Documentation/admin-guide/mm/numaperf.rst new file +164 -0
@@ -0,0 +1,164 @@ +.. _numaperf: + +============= +NUMA Locality +============= + +Some platforms may have multiple types of memory attached to a compute +node. These disparate memory ranges may share some characteristics, such +as CPU cache coherence, but may have different performance. For example, +different media types and buses affect bandwidth and latency. + +A system supports such heterogeneous memory by grouping each memory type +under different domains, or "nodes", based on locality and performance +characteristics. Some memory may share the same node as a CPU, and others +are provided as memory only nodes. While memory only nodes do not provide +CPUs, they may still be local to one or more compute nodes relative to +other nodes. The following diagram shows one such example of two compute +nodes with local memory and a memory only node for each of compute node: + + +------------------+ +------------------+ + | Compute Node 0 +-----+ Compute Node 1 | + | Local Node0 Mem | | Local Node1 Mem | + +--------+---------+ +--------+---------+ + | | + +--------+---------+ +--------+---------+ + | Slower Node2 Mem | | Slower Node3 Mem | + +------------------+ +--------+---------+ + +A "memory initiator" is a node containing one or more devices such as +CPUs or separate memory I/O devices that can initiate memory requests. +A "memory target" is a node containing one or more physical address +ranges accessible from one or more memory initiators. + +When multiple memory initiators exist, they may not all have the same +performance when accessing a given memory target. Each initiator-target +pair may be organized into different ranked access classes to represent +this relationship. The highest performing initiator to a given target +is considered to be one of that target's local initiators, and given +the highest access class, 0. Any given target may have one or more +local initiators, and any given initiator may have multiple local +memory targets. + +To aid applications matching memory targets with their initiators, the +kernel provides symlinks to each other. The following example lists the +relationship for the access class "0" memory initiators and targets, which is +the of nodes with the highest performing access relationship:: + + # symlinks -v /sys/devices/system/node/nodeX/access0/targets/ + relative: /sys/devices/system/node/nodeX/access0/targets/nodeY -> ../../nodeY + + # symlinks -v /sys/devices/system/node/nodeY/access0/initiators/ + relative: /sys/devices/system/node/nodeY/access0/initiators/nodeX -> ../../nodeX + +================ +NUMA Performance +================ + +Applications may wish to consider which node they want their memory to +be allocated from based on the node's performance characteristics. If +the system provides these attributes, the kernel exports them under the +node sysfs hierarchy by appending the attributes directory under the +memory node's access class 0 initiators as follows:: + + /sys/devices/system/node/nodeY/access0/initiators/ + +These attributes apply only when accessed from nodes that have the +are linked under the this access's inititiators. + +The performance characteristics the kernel provides for the local initiators +are exported are as follows:: + + # tree -P "read*|write*" /sys/devices/system/node/nodeY/access0/initiators/ + /sys/devices/system/node/nodeY/access0/initiators/ + |-- read_bandwidth + |-- read_latency + |-- write_bandwidth + `-- write_latency + +The bandwidth attributes are provided in MiB/second. + +The latency attributes are provided in nanoseconds. + +The values reported here correspond to the rated latency and bandwidth +for the platform. + +========== +NUMA Cache +========== + +System memory may be constructed in a hierarchy of elements with various +performance characteristics in order to provide large address space of +slower performing memory cached by a smaller higher performing memory. The +system physical addresses memory initiators are aware of are provided +by the last memory level in the hierarchy. The system meanwhile uses +higher performing memory to transparently cache access to progressively +slower levels. + +The term "far memory" is used to denote the last level memory in the +hierarchy. Each increasing cache level provides higher performing +initiator access, and the term "near memory" represents the fastest +cache provided by the system. + +This numbering is different than CPU caches where the cache level (ex: +L1, L2, L3) uses a CPU-side view where each increased level is lower +performing. In contrast, the memory cache level is centric to the last +level memory, so the higher numbered cache level denotes memory nearer +to the CPU, and further from far memory. + +The memory-side caches are not directly addressable by software. When +software accesses a system address, the system will return it from the +near memory cache if it is present. If it is not present, the system +accesses the next level of memory until there is either a hit in that +cache level, or it reaches far memory. + +An application does not need to know about caching attributes in order +to use the system. Software may optionally query the memory cache +attributes in order to maximize the performance out of such a setup. +If the system provides a way for the kernel to discover this information, +for example with ACPI HMAT (Heterogeneous Memory Attribute Table), +the kernel will append these attributes to the NUMA node memory target. + +When the kernel first registers a memory cache with a node, the kernel +will create the following directory:: + + /sys/devices/system/node/nodeX/memory_side_cache/ + +If that directory is not present, the system either does not not provide +a memory-side cache, or that information is not accessible to the kernel. + +The attributes for each level of cache is provided under its cache +level index:: + + /sys/devices/system/node/nodeX/memory_side_cache/indexA/ + /sys/devices/system/node/nodeX/memory_side_cache/indexB/ + /sys/devices/system/node/nodeX/memory_side_cache/indexC/ + +Each cache level's directory provides its attributes. For example, the +following shows a single cache level and the attributes available for +software to query:: + + # tree sys/devices/system/node/node0/memory_side_cache/ + /sys/devices/system/node/node0/memory_side_cache/ + |-- index1 + | |-- associativity + | |-- line_size + | |-- size + | `-- write_policy + +The "associativity" will be 0 if it is a direct-mapped cache, and non-zero +for any other indexed based, multi-way associativity. + +The "line_size" is the number of bytes accessed from the next cache +level on a miss. + +The "size" is the number of bytes provided by this cache level. + +The "write_policy" will be 0 for write-back, and non-zero for +write-through caching. + +======== +See Also +======== +.. [1] https://www.uefi.org/sites/default/files/resources/ACPI_6_2.pdf + Section 5.2.27
Signature · 1 line
2.14.4
Le 14/02/2019 à 18:10, Keith Busch a écrit :
Quoted 18 lines
== Changes since v5 ==
Updated HMAT parsing to account for the recently released ACPI 6.3 changes.
HMAT attribute calculation overflow checks.
Fixed memory leak if HMAT parse fails.
Minor change to the patch order. All the base node attributes occur before HMAT usage for these new node attributes to resolve a dependency on a new struct.
Reporting failures to parse HMAT or allocate structures are elevated to a NOTICE level from DEBUG. Any failure will result in just one print so that it is obvious something may need to be investigated rather than silently fail, but also not to be too alarming either.
Quoted 6 lines
Determining the cpu and memory node local relationships is quite different this time (PATCH 7/10). The local relationship to a memory target will be either *only* the node from the Initiator Proximity Domain if provided, or if it is not provided, all the nodes that have the same highest performance. Latency was chosen to take prioirty over bandwidth when ranking performance.
Hello Keith
I am trying to understand what this last paragraph means.
Let's say I have a machine with DDR and NVDIMM both attached to the same socket, and I use Dave Hansen's kmem patchs to make the NVDIMM appear as "normal memory" in an additional NUMA node. Let's call node0 the DDR and node1 the NVDIMM kmem node.
Now user-space wants to find out which CPUs are actually close to the NVDIMMs. My understanding is that SRAT says that CPUs are local to the DDR only. Hence /sys/devices/system/node/node1/cpumap says there are no CPU local to the NVDIMM. And HMAT won't change this, right?
Will node1 contain access0/initiators/node0 to clarify that CPUs local to the NVDIMM are those of node0? Even if latency from node0 to node1 latency is higher than node0 to node0?
Another way to ask this: Is the latency/performance only used for distinguishing the local initiator CPUs among multiple CPU nodes accesing the same memory node? Or is it also used to distinguish the local memory target among multiple memories access by a single CPU node?
The Intel machine I am currently testing patches on doesn't have a HMAT in 1-level-memory unfortunately.
Thanks
Brice
Quoted 18 lines · Brice Goglin
Le 14/02/2019 à 18:10, Keith Busch a écrit :
Quoted 6 lines
Determining the cpu and memory node local relationships is quite different this time (PATCH 7/10). The local relationship to a memory target will be either *only* the node from the Initiator Proximity Domain if provided, or if it is not provided, all the nodes that have the same highest performance. Latency was chosen to take prioirty over bandwidth when ranking performance.
Hello Keith
I am trying to understand what this last paragraph means.
Let's say I have a machine with DDR and NVDIMM both attached to the same socket, and I use Dave Hansen's kmem patchs to make the NVDIMM appear as "normal memory" in an additional NUMA node. Let's call node0 the DDR and node1 the NVDIMM kmem node.
Quoted 4 lines
Now user-space wants to find out which CPUs are actually close to the NVDIMMs. My understanding is that SRAT says that CPUs are local to the DDR only. Hence
/sys/devices/system/node/node1/cpumapsays there are no CPU local to the NVDIMM. And HMAT won't change this, right?
HMAT actually does change this. The relationship is in 6.2's HMAT Address Range or 6.3's Proximity Domain Attributes, and that's something SRAT wasn't providing.
The problem with these HMAT structures is that the CPU node is optional. The last paragraph is saying that if that optional information is provided, we will use that. If it is not provided, we will fallback to performance attributes to determine what is the "local" CPU domain.
Quoted 3 lines
Will node1 contain access0/initiators/node0 to clarify that CPUs local to the NVDIMM are those of node0? Even if latency from node0 to node1 latency is higher than node0 to node0?
Exactly, yes. To expand on this, what you'd see from sysfs:
/sys/devices/system/node/node0/access0/targets/node1 -> ../../../node1
And
/sys/devices/system/node/node1/access0/initiators/node0 -> ../../../node0
Quoted 4 lines
Another way to ask this: Is the latency/performance only used for distinguishing the local initiator CPUs among multiple CPU nodes accesing the same memory node? Or is it also used to distinguish the local memory target among multiple memories access by a single CPU node?
It's the first one. A single CPU domain may have multiple local targets, but each of those targets may have different performance.
For example, you could have something like this with "normal" DDR memory, high-bandwidth memory, and slower nvdimm:
+------------------+ +------------------+
| CPU Node 0 +----+ CPU Node 1 |
| Node0 DDR Mem | | Node1 DDR Mem |
+--------+---------+ +--------+---------+
| |
+--------+---------+ +--------+---------+
| Node2 HBMem | | Node3 HBMem |
+--------+---------+ +--------+---------+
| |
+--------+---------+ +--------+---------+
| Node4 Slow NVMem | | Node5 Slow NVMem |
+------------------+ +------------------+In the above, Initiator node0 is "local" to targets 0, 2, and 4, and would show up in node0's access0/targets/. Each memory target node, though, has different performance than the others that are local to the same intiator domain.
Quoted 2 lines
The Intel machine I am currently testing patches on doesn't have a HMAT in 1-level-memory unfortunately.
Platforms providing HMAT tables are still rare at the moment, but expect will become more common.
Quoted 10 lines · Keith Busch
Platforms may provide multiple types of cpu attached system memory. The memory ranges for each type may have different characteristics that applications may wish to know about when considering what node they want their memory allocated from.
It had previously been difficult to describe these setups as memory rangers were generally lumped into the NUMA node of the CPUs. New platform attributes have been created and in use today that describe the more complex memory hierarchies that can be created.
Quoted 6 lines
This series' objective is to provide the attributes from such systems that are useful for applications to know about, and readily usable with existing tools and libraries. Those applications may query performance attributes relative to a particular CPU they're running on in order to make more informed choices for where they want to allocate hot and cold data. This works with
mbind()or the numactl library.
Hi all,
So this seems very calm at this point. Unless there are any late concerns or suggestions, could we open consideration for queueing in a staging tree for a future merge window?
Thanks,
Keith
Quoted 42 lines
Keith Busch (10):
acpi: Create subtable parsing infrastructure
acpi: Add HMAT to generic parsing tables acpi/hmat: Parse and report heterogeneous memory
node: Link memory nodes to their compute nodes
node: Add heterogenous memory access attributes
node: Add memory-side caching attributes acpi/hmat: Register processor domain to its memory acpi/hmat: Register performance attributes acpi/hmat: Register memory side cache attributes doc/mm: New documentation for memory performanceDocumentation/ABI/stable/sysfs-devices-node | 89 +++- Documentation/admin-guide/mm/numaperf.rst | 164 +++++++ arch/arm64/kernel/acpi_numa.c | 2 +- arch/arm64/kernel/smp.c | 4 +- arch/ia64/kernel/acpi.c | 12 +- arch/x86/kernel/acpi/boot.c | 36 +- drivers/acpi/Kconfig | 1 + drivers/acpi/Makefile | 1 + drivers/acpi/hmat/Kconfig | 9 + drivers/acpi/hmat/Makefile | 1 + drivers/acpi/hmat/hmat.c | 677 ++++++++++++++++++++++++++ drivers/acpi/numa.c | 16 +- drivers/acpi/scan.c | 4 +- drivers/acpi/tables.c | 76 ++- drivers/base/Kconfig | 8 + drivers/base/node.c | 351 ++++++++++++- drivers/irqchip/irq-gic-v2m.c | 2 +- drivers/irqchip/irq-gic-v3-its-pci-msi.c | 2 +- drivers/irqchip/irq-gic-v3-its-platform-msi.c | 2 +- drivers/irqchip/irq-gic-v3-its.c | 6 +- drivers/irqchip/irq-gic-v3.c | 10 +- drivers/irqchip/irq-gic.c | 4 +- drivers/mailbox/pcc.c | 2 +- include/linux/acpi.h | 6 +- include/linux/node.h | 60 ++- 25 files changed, 1480 insertions(+), 65 deletions(-) create mode 100644 Documentation/admin-guide/mm/numaperf.rst create mode 100644 drivers/acpi/hmat/Kconfig create mode 100644 drivers/acpi/hmat/Makefile create mode 100644 drivers/acpi/hmat/hmat.c