diff options
-rw-r--r-- | mm/Kconfig | 1 | ||||
-rw-r--r-- | mm/kasan/kasan.c | 40 |
2 files changed, 35 insertions, 6 deletions
diff --git a/mm/Kconfig b/mm/Kconfig index 46ef77d5c332..48b1af447fa7 100644 --- a/mm/Kconfig +++ b/mm/Kconfig | |||
@@ -161,7 +161,6 @@ config MEMORY_HOTPLUG | |||
161 | bool "Allow for memory hot-add" | 161 | bool "Allow for memory hot-add" |
162 | depends on SPARSEMEM || X86_64_ACPI_NUMA | 162 | depends on SPARSEMEM || X86_64_ACPI_NUMA |
163 | depends on ARCH_ENABLE_MEMORY_HOTPLUG | 163 | depends on ARCH_ENABLE_MEMORY_HOTPLUG |
164 | depends on COMPILE_TEST || !KASAN | ||
165 | 164 | ||
166 | config MEMORY_HOTPLUG_SPARSE | 165 | config MEMORY_HOTPLUG_SPARSE |
167 | def_bool y | 166 | def_bool y |
diff --git a/mm/kasan/kasan.c b/mm/kasan/kasan.c index 212bc62041de..509974a1911e 100644 --- a/mm/kasan/kasan.c +++ b/mm/kasan/kasan.c | |||
@@ -737,17 +737,47 @@ void __asan_unpoison_stack_memory(const void *addr, size_t size) | |||
737 | EXPORT_SYMBOL(__asan_unpoison_stack_memory); | 737 | EXPORT_SYMBOL(__asan_unpoison_stack_memory); |
738 | 738 | ||
739 | #ifdef CONFIG_MEMORY_HOTPLUG | 739 | #ifdef CONFIG_MEMORY_HOTPLUG |
740 | static int kasan_mem_notifier(struct notifier_block *nb, | 740 | static int __meminit kasan_mem_notifier(struct notifier_block *nb, |
741 | unsigned long action, void *data) | 741 | unsigned long action, void *data) |
742 | { | 742 | { |
743 | return (action == MEM_GOING_ONLINE) ? NOTIFY_BAD : NOTIFY_OK; | 743 | struct memory_notify *mem_data = data; |
744 | unsigned long nr_shadow_pages, start_kaddr, shadow_start; | ||
745 | unsigned long shadow_end, shadow_size; | ||
746 | |||
747 | nr_shadow_pages = mem_data->nr_pages >> KASAN_SHADOW_SCALE_SHIFT; | ||
748 | start_kaddr = (unsigned long)pfn_to_kaddr(mem_data->start_pfn); | ||
749 | shadow_start = (unsigned long)kasan_mem_to_shadow((void *)start_kaddr); | ||
750 | shadow_size = nr_shadow_pages << PAGE_SHIFT; | ||
751 | shadow_end = shadow_start + shadow_size; | ||
752 | |||
753 | if (WARN_ON(mem_data->nr_pages % KASAN_SHADOW_SCALE_SIZE) || | ||
754 | WARN_ON(start_kaddr % (KASAN_SHADOW_SCALE_SIZE << PAGE_SHIFT))) | ||
755 | return NOTIFY_BAD; | ||
756 | |||
757 | switch (action) { | ||
758 | case MEM_GOING_ONLINE: { | ||
759 | void *ret; | ||
760 | |||
761 | ret = __vmalloc_node_range(shadow_size, PAGE_SIZE, shadow_start, | ||
762 | shadow_end, GFP_KERNEL, | ||
763 | PAGE_KERNEL, VM_NO_GUARD, | ||
764 | pfn_to_nid(mem_data->start_pfn), | ||
765 | __builtin_return_address(0)); | ||
766 | if (!ret) | ||
767 | return NOTIFY_BAD; | ||
768 | |||
769 | kmemleak_ignore(ret); | ||
770 | return NOTIFY_OK; | ||
771 | } | ||
772 | case MEM_OFFLINE: | ||
773 | vfree((void *)shadow_start); | ||
774 | } | ||
775 | |||
776 | return NOTIFY_OK; | ||
744 | } | 777 | } |
745 | 778 | ||
746 | static int __init kasan_memhotplug_init(void) | 779 | static int __init kasan_memhotplug_init(void) |
747 | { | 780 | { |
748 | pr_info("WARNING: KASAN doesn't support memory hot-add\n"); | ||
749 | pr_info("Memory hot-add will be disabled\n"); | ||
750 | |||
751 | hotplug_memory_notifier(kasan_mem_notifier, 0); | 781 | hotplug_memory_notifier(kasan_mem_notifier, 0); |
752 | 782 | ||
753 | return 0; | 783 | return 0; |