diff --git a/kernel/memremap.c b/kernel/memremap.c index 895e6b76b25e..b6f478658719 100644 --- a/kernel/memremap.c +++ b/kernel/memremap.c @@ -20,6 +20,10 @@ #include #include +/* for manually notifying of linear map additions */ +#include +#include "../mm/kasan/kasan.h" + #ifndef ioremap_cache /* temporary while we convert existing ioremap_cache users to memremap */ __weak void __iomem *ioremap_cache(resource_size_t offset, unsigned long size) @@ -291,6 +295,7 @@ static void devm_memremap_pages_release(void *data) struct device *dev = pgmap->dev; struct resource *res = &pgmap->res; resource_size_t align_start, align_size; + struct memory_notify arg; unsigned long pfn; for_each_device_pfn(pfn, pgmap) @@ -309,6 +314,9 @@ static void devm_memremap_pages_release(void *data) mem_hotplug_begin(); arch_remove_memory(align_start, align_size, pgmap->altmap_valid ? &pgmap->altmap : NULL); + arg.start_pfn = align_start >> PAGE_SHIFT; + arg.nr_pages = align_size >> PAGE_SHIFT; + kasan_mem_notifier(NULL, MEM_GOING_OFFLINE, &arg); mem_hotplug_done(); untrack_pfn(NULL, PHYS_PFN(align_start), align_size); @@ -396,10 +404,16 @@ void *devm_memremap_pages(struct device *dev, struct dev_pagemap *pgmap) mem_hotplug_begin(); error = arch_add_memory(nid, align_start, align_size, altmap, false); - if (!error) + if (!error) { + struct memory_notify arg = { + .start_pfn = align_start >> PAGE_SHIFT, + .nr_pages = align_size >> PAGE_SHIFT, + }; + move_pfn_range_to_zone(&NODE_DATA(nid)->node_zones[ZONE_DEVICE], - align_start >> PAGE_SHIFT, - align_size >> PAGE_SHIFT, altmap); + arg.start_pfn, arg.nr_pages, altmap); + kasan_mem_notifier(NULL, MEM_GOING_ONLINE, &arg); + } mem_hotplug_done(); if (error) goto err_add_memory; diff --git a/mm/kasan/kasan.c b/mm/kasan/kasan.c index bc0e68f7dc75..27560aea5e67 100644 --- a/mm/kasan/kasan.c +++ b/mm/kasan/kasan.c @@ -792,8 +792,8 @@ DEFINE_ASAN_SET_SHADOW(f5); DEFINE_ASAN_SET_SHADOW(f8); #ifdef CONFIG_MEMORY_HOTPLUG -static int __meminit kasan_mem_notifier(struct notifier_block *nb, - unsigned long action, void *data) +int kasan_mem_notifier(struct notifier_block *nb, unsigned long action, + void *data) { struct memory_notify *mem_data = data; unsigned long nr_shadow_pages, start_kaddr, shadow_start; diff --git a/mm/kasan/kasan.h b/mm/kasan/kasan.h index c12dcfde2ebd..f56d5ae60536 100644 --- a/mm/kasan/kasan.h +++ b/mm/kasan/kasan.h @@ -120,6 +120,17 @@ static inline void quarantine_reduce(void) { } static inline void quarantine_remove_cache(struct kmem_cache *cache) { } #endif +#if defined(CONFIG_MEMORY_HOTPLUG) && defined(CONFIG_KASAN) +int kasan_mem_notifier(struct notifier_block *nb, unsigned long action, + void *data); +#else +static inline int kasan_mem_notifier(struct notifier_block *nb, + unsigned long action, void *data) +{ + return NOTIFY_OK; +} +#endif + /* * Exported functions for interfaces called from assembly or from generated * code. Declarations here to avoid warning about missing declarations.