On Fri, Oct 16, 2020 at 07:02:23PM -0700, Sudarshan Rajagopalan wrote:
> Certain architectures such as arm64 doesn't allow boot memory to be
> offlined and removed. Distinguish certain memory sections as
> "hotpluggable" which can be marked by module drivers stating to memory
> hotplug layer that these sections can be offlined and then removed.

I don't quite follow why marking sections as hotpluggable or not should
be done by a device driver. Can you describe in more details your
use-case and why there is a need to add a flag to the memory map?


> This is done by using a separate section memory mab bit and setting it,
> rather than clearing the existing SECTION_IS_EARLY bit.
> This patch introduces SECTION_MARK_HOTPLUGGABLE bit into section mem map.
> Only the allowed sections which are in movable zone and have unmovable
> pages are allowed to be set with this new bit.
> 
> Signed-off-by: Sudarshan Rajagopalan <sudar...@codeaurora.org>
> Cc: Catalin Marinas <catalin.mari...@arm.com>
> Cc: Will Deacon <w...@kernel.org>
> Cc: Mike Rapoport <r...@kernel.org>
> Cc: Anshuman Khandual <anshuman.khand...@arm.com>
> Cc: David Hildenbrand <da...@redhat.com>
> Cc: Mark Rutland <mark.rutl...@arm.com>
> Cc: Steven Price <steven.pr...@arm.com>
> Cc: Logan Gunthorpe <log...@deltatee.com>
> Cc: Suren Baghdasaryan <sur...@google.com>
> ---
>  include/linux/memory_hotplug.h |  1 +
>  include/linux/mmzone.h         |  9 ++++++++-
>  mm/memory_hotplug.c            | 20 ++++++++++++++++++++
>  mm/sparse.c                    | 31 +++++++++++++++++++++++++++++++
>  4 files changed, 60 insertions(+), 1 deletion(-)
> 
> diff --git a/include/linux/memory_hotplug.h b/include/linux/memory_hotplug.h
> index 375515803cd8..81df45b582c8 100644
> --- a/include/linux/memory_hotplug.h
> +++ b/include/linux/memory_hotplug.h
> @@ -319,6 +319,7 @@ extern int offline_pages(unsigned long start_pfn, 
> unsigned long nr_pages);
>  extern int remove_memory(int nid, u64 start, u64 size);
>  extern void __remove_memory(int nid, u64 start, u64 size);
>  extern int offline_and_remove_memory(int nid, u64 start, u64 size);
> +extern int mark_memory_hotpluggable(unsigned long start, unsigned long end);
>  
>  #else
>  static inline void try_offline_node(int nid) {}
> diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
> index 8379432f4f2f..3df3a4975236 100644
> --- a/include/linux/mmzone.h
> +++ b/include/linux/mmzone.h
> @@ -1247,7 +1247,8 @@ extern size_t mem_section_usage_size(void);
>  #define SECTION_HAS_MEM_MAP  (1UL<<1)
>  #define SECTION_IS_ONLINE    (1UL<<2)
>  #define SECTION_IS_EARLY     (1UL<<3)
> -#define SECTION_MAP_LAST_BIT (1UL<<4)
> +#define SECTION_MARK_HOTPLUGGABLE    (1UL<<4)
> +#define SECTION_MAP_LAST_BIT (1UL<<5)
>  #define SECTION_MAP_MASK     (~(SECTION_MAP_LAST_BIT-1))
>  #define SECTION_NID_SHIFT    3
>  
> @@ -1278,6 +1279,11 @@ static inline int early_section(struct mem_section 
> *section)
>       return (section && (section->section_mem_map & SECTION_IS_EARLY));
>  }
>  
> +static inline int removable_section(struct mem_section *section)
> +{
> +     return (section && (section->section_mem_map & 
> SECTION_MARK_HOTPLUGGABLE));
> +}
> +
>  static inline int valid_section_nr(unsigned long nr)
>  {
>       return valid_section(__nr_to_section(nr));
> @@ -1297,6 +1303,7 @@ static inline int online_section_nr(unsigned long nr)
>  void online_mem_sections(unsigned long start_pfn, unsigned long end_pfn);
>  #ifdef CONFIG_MEMORY_HOTREMOVE
>  void offline_mem_sections(unsigned long start_pfn, unsigned long end_pfn);
> +int section_mark_hotpluggable(struct mem_section *ms);
>  #endif
>  #endif
>  
> diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
> index e9d5ab5d3ca0..503b0de489a0 100644
> --- a/mm/memory_hotplug.c
> +++ b/mm/memory_hotplug.c
> @@ -1860,4 +1860,24 @@ int offline_and_remove_memory(int nid, u64 start, u64 
> size)
>       return rc;
>  }
>  EXPORT_SYMBOL_GPL(offline_and_remove_memory);
> +
> +int mark_memory_hotpluggable(unsigned long start_pfn, unsigned long end_pfn)
> +{
> +     struct mem_section *ms;
> +     unsigned long nr;
> +     int rc = -EINVAL;
> +
> +     if (end_pfn < start_pfn)
> +             return rc;
> +
> +     for (nr = start_pfn; nr <= end_pfn; nr++) {
> +             ms = __pfn_to_section(nr);
> +             rc = section_mark_hotpluggable(ms);
> +             if (!rc)
> +                     break;
> +     }
> +
> +     return rc;
> +}
> +EXPORT_SYMBOL_GPL(mark_memory_hotpluggable);
>  #endif /* CONFIG_MEMORY_HOTREMOVE */
> diff --git a/mm/sparse.c b/mm/sparse.c
> index fcc3d176f1ea..cc21c23e2f1d 100644
> --- a/mm/sparse.c
> +++ b/mm/sparse.c
> @@ -13,6 +13,7 @@
>  #include <linux/vmalloc.h>
>  #include <linux/swap.h>
>  #include <linux/swapops.h>
> +#include <linux/page-isolation.h>
>  
>  #include "internal.h"
>  #include <asm/dma.h>
> @@ -644,6 +645,36 @@ void offline_mem_sections(unsigned long start_pfn, 
> unsigned long end_pfn)
>               ms->section_mem_map &= ~SECTION_IS_ONLINE;
>       }
>  }
> +
> +int section_mark_hotpluggable(struct mem_section *ms)
> +{
> +     unsigned long section_nr, pfn;
> +     bool unmovable;
> +     struct page *page;
> +
> +     /* section needs to be both valid and present to be marked */
> +     if (WARN_ON(!valid_section(ms)) || !present_section(ms))
> +             return -EINVAL;
> +
> +     /*
> +      * now check if this section is removable. This can be done by checking
> +      * if section has unmovable pages or not.
> +      */
> +     section_nr = __section_nr(ms);
> +     pfn = section_nr_to_pfn(section_nr);
> +     page = pfn_to_page(pfn);
> +     unmovable = has_unmovable_pages(page_zone(page), page,
> +                                     MIGRATE_MOVABLE, MEMORY_OFFLINE | 
> REPORT_FAILURE);
> +     if (unmovable) {
> +             pr_info("section %lu has unmovable pages. Cannot be marked as 
> hotpluggable\n");
> +             return -EINVAL;
> +     }
> +
> +     /* all good! mark section as hotpluggable */
> +     ms->section_mem_map |= SECTION_MARK_HOTPLUGGABLE;
> +
> +     return 0;
> +}
>  #endif
>  
>  #ifdef CONFIG_SPARSEMEM_VMEMMAP
> -- 
> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
> a Linux Foundation Collaborative Project
> 

-- 
Sincerely yours,
Mike.

Reply via email to