Re: [PATCH v5 2/5] acpi/numa: Set the memory-side-cache size in memblocks

From: Mike Rapoport
Date: Sun Dec 16 2018 - 07:35:00 EST


On Fri, Dec 14, 2018 at 05:48:40PM -0800, Dan Williams wrote:
> From: Keith Busch <keith.busch@xxxxxxxxx>
>
> Add memblock based enumeration of memory-side-cache of System RAM.
> Detect the capability in early init through HMAT tables, and set the
> size in the address range memblocks if a direct mapped side cache is
> present.
>
> Cc: <x86@xxxxxxxxxx>
> Cc: "Rafael J. Wysocki" <rjw@xxxxxxxxxxxxx>
> Cc: Dave Hansen <dave.hansen@xxxxxxxxxxxxxxx>
> Cc: Andy Lutomirski <luto@xxxxxxxxxx>
> Cc: Peter Zijlstra <peterz@xxxxxxxxxxxxx>
> Cc: Mike Rapoport <rppt@xxxxxxxxxxxxx>
> Signed-off-by: Keith Busch <keith.busch@xxxxxxxxx>
> Signed-off-by: Dan Williams <dan.j.williams@xxxxxxxxx>
> ---
> arch/x86/Kconfig | 1 +
> drivers/acpi/numa.c | 32 ++++++++++++++++++++++++++++++++
> include/linux/memblock.h | 36 ++++++++++++++++++++++++++++++++++++
> mm/Kconfig | 3 +++
> mm/memblock.c | 20 ++++++++++++++++++++
> 5 files changed, 92 insertions(+)
>
> diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
> index 8689e794a43c..3f9c413d8eb5 100644
> --- a/arch/x86/Kconfig
> +++ b/arch/x86/Kconfig
> @@ -171,6 +171,7 @@ config X86
> select HAVE_KVM
> select HAVE_LIVEPATCH if X86_64
> select HAVE_MEMBLOCK_NODE_MAP
> + select HAVE_MEMBLOCK_CACHE_INFO if ACPI_NUMA
> select HAVE_MIXED_BREAKPOINTS_REGS
> select HAVE_MOD_ARCH_SPECIFIC
> select HAVE_NMI
> diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c
> index f5e09c39ff22..ec7e849f1c19 100644
> --- a/drivers/acpi/numa.c
> +++ b/drivers/acpi/numa.c
> @@ -40,6 +40,12 @@ static int pxm_to_node_map[MAX_PXM_DOMAINS]
> static int node_to_pxm_map[MAX_NUMNODES]
> = { [0 ... MAX_NUMNODES - 1] = PXM_INVAL };
>
> +struct mem_cacheinfo {
> + phys_addr_t size;
> + bool direct_mapped;
> +};
> +static struct mem_cacheinfo side_cached_pxms[MAX_PXM_DOMAINS] __initdata;
> +
> unsigned char acpi_srat_revision __initdata;
> int acpi_numa __initdata;
>
> @@ -262,6 +268,8 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma)
> u64 start, end;
> u32 hotpluggable;
> int node, pxm;
> + u64 cache_size;
> + bool direct;
>
> if (srat_disabled())
> goto out_err;
> @@ -308,6 +316,13 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma)
> pr_warn("SRAT: Failed to mark hotplug range [mem %#010Lx-%#010Lx] in memblock\n",
> (unsigned long long)start, (unsigned long long)end - 1);
>
> + cache_size = side_cached_pxms[pxm].size;
> + direct = side_cached_pxms[pxm].direct_mapped;
> + if (cache_size &&
> + memblock_set_sidecache(start, ma->length, cache_size, direct))
> + pr_warn("SRAT: Failed to mark side cached range [mem %#010Lx-%#010Lx] in memblock\n",
> + (unsigned long long)start, (unsigned long long)end - 1);
> +
> max_possible_pfn = max(max_possible_pfn, PFN_UP(end - 1));
>
> return 0;
> @@ -411,6 +426,18 @@ acpi_parse_memory_affinity(union acpi_subtable_headers * header,
> return 0;
> }
>
> +static int __init
> +acpi_parse_cache(union acpi_subtable_headers *header, const unsigned long end)
> +{
> + struct acpi_hmat_cache *c = (void *)header;
> + u32 attrs = (c->cache_attributes & ACPI_HMAT_CACHE_ASSOCIATIVITY) >> 8;
> +
> + if (attrs == ACPI_HMAT_CA_DIRECT_MAPPED)
> + side_cached_pxms[c->memory_PD].direct_mapped = true;
> + side_cached_pxms[c->memory_PD].size += c->cache_size;
> + return 0;
> +}
> +
> static int __init acpi_parse_srat(struct acpi_table_header *table)
> {
> struct acpi_table_srat *srat = (struct acpi_table_srat *)table;
> @@ -460,6 +487,11 @@ int __init acpi_numa_init(void)
> sizeof(struct acpi_table_srat),
> srat_proc, ARRAY_SIZE(srat_proc), 0);
>
> + acpi_table_parse_entries(ACPI_SIG_HMAT,
> + sizeof(struct acpi_table_hmat),
> + ACPI_HMAT_TYPE_CACHE,
> + acpi_parse_cache, 0);
> +
> cnt = acpi_table_parse_srat(ACPI_SRAT_TYPE_MEMORY_AFFINITY,
> acpi_parse_memory_affinity, 0);
> }
> diff --git a/include/linux/memblock.h b/include/linux/memblock.h
> index aee299a6aa76..169ed3dd456d 100644
> --- a/include/linux/memblock.h
> +++ b/include/linux/memblock.h
> @@ -60,6 +60,10 @@ struct memblock_region {
> #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
> int nid;
> #endif
> +#ifdef CONFIG_HAVE_MEMBLOCK_CACHE_INFO
> + phys_addr_t cache_size;
> + bool direct_mapped;
> +#endif

Please add descriptions of the new fields to the 'struct memblock_region'
kernel-doc.

> };
>
> /**
> @@ -317,6 +321,38 @@ static inline int memblock_get_region_node(const struct memblock_region *r)
> }
> #endif /* CONFIG_HAVE_MEMBLOCK_NODE_MAP */
>
> +#ifdef CONFIG_HAVE_MEMBLOCK_CACHE_INFO
> +int memblock_set_sidecache(phys_addr_t base, phys_addr_t size,
> + phys_addr_t cache_size, bool direct_mapped);
> +
> +static inline bool memblock_sidecache_direct_mapped(struct memblock_region *m)
> +{
> + return m->direct_mapped;
> +}
> +
> +static inline phys_addr_t memblock_sidecache_size(struct memblock_region *m)
> +{
> + return m->cache_size;
> +}
> +#else
> +static inline int memblock_set_sidecache(phys_addr_t base, phys_addr_t size,
> + phys_addr_t cache_size,
> + bool direct_mapped)
> +{
> + return 0;
> +}
> +
> +static inline phys_addr_t memblock_sidecache_size(struct memblock_region *m)
> +{
> + return 0;
> +}
> +
> +static inline bool memblock_sidecache_direct_mapped(struct memblock_region *m)
> +{
> + return false;
> +}
> +#endif /* CONFIG_HAVE_MEMBLOCK_CACHE_INFO */
> +
> /* Flags for memblock allocation APIs */
> #define MEMBLOCK_ALLOC_ANYWHERE (~(phys_addr_t)0)
> #define MEMBLOCK_ALLOC_ACCESSIBLE 0
> diff --git a/mm/Kconfig b/mm/Kconfig
> index d85e39da47ae..c7944299a89e 100644
> --- a/mm/Kconfig
> +++ b/mm/Kconfig
> @@ -142,6 +142,9 @@ config ARCH_DISCARD_MEMBLOCK
> config MEMORY_ISOLATION
> bool
>
> +config HAVE_MEMBLOCK_CACHE_INFO
> + bool
> +
> #
> # Only be set on architectures that have completely implemented memory hotplug
> # feature. If you are not sure, don't touch it.
> diff --git a/mm/memblock.c b/mm/memblock.c
> index 9a2d5ae81ae1..185bfd4e87bb 100644
> --- a/mm/memblock.c
> +++ b/mm/memblock.c
> @@ -822,6 +822,26 @@ int __init_memblock memblock_reserve(phys_addr_t base, phys_addr_t size)
> return memblock_add_range(&memblock.reserved, base, size, MAX_NUMNODES, 0);
> }
>
> +#ifdef CONFIG_HAVE_MEMBLOCK_CACHE_INFO

Kernel-doc here would be appreciated.

> +int __init_memblock memblock_set_sidecache(phys_addr_t base, phys_addr_t size,
> + phys_addr_t cache_size, bool direct_mapped)
> +{
> + struct memblock_type *type = &memblock.memory;
> + int i, ret, start_rgn, end_rgn;
> +
> + ret = memblock_isolate_range(type, base, size, &start_rgn, &end_rgn);
> + if (ret)
> + return ret;
> +
> + for (i = start_rgn; i < end_rgn; i++) {
> + type->regions[i].cache_size = cache_size;
> + type->regions[i].direct_mapped = direct_mapped;
> + }
> +
> + return 0;
> +}
> +#endif
> +
> /**
> * memblock_setclr_flag - set or clear flag for a memory region
> * @base: base address of the region
>

--
Sincerely yours,
Mike.