#include <linux/mm.h>
#include <linux/vmalloc.h>
#include <linux/set_memory.h>
+#include <linux/suspend.h>
#include <linux/kfence.h>
#include <linux/pkeys.h>
#include <linux/mm_inline.h>
end - start, prot, early_pgtable_alloc, flags);
}
+static void mark_linear_data_alias_valid(bool valid)
+{
+ set_memory_valid((unsigned long)lm_alias(__init_end),
+ (unsigned long)(__bss_stop - __init_end) / PAGE_SIZE,
+ valid);
+}
+
+static int arm64_hibernate_pm_notify(struct notifier_block *nb,
+ unsigned long mode, void *unused)
+{
+ switch (mode) {
+ default:
+ break;
+ case PM_POST_HIBERNATION:
+ mark_linear_data_alias_valid(false);
+ break;
+ case PM_HIBERNATION_PREPARE:
+ mark_linear_data_alias_valid(true);
+ break;
+ }
+ return 0;
+}
+
void __init mark_linear_text_alias_ro(void)
{
/*
update_mapping_prot(__pa_symbol(_text), (unsigned long)lm_alias(_text),
(unsigned long)__init_begin - (unsigned long)_text,
PAGE_KERNEL_RO);
+
+ /*
+ * Register a PM notifier to remap the linear alias of data/bss as
+ * valid read-only before hibernation. This is needed because the
+ * snapshot logic disregards PageReserved pages (such as the ones
+ * covering the kernel image) unless they are mapped in the linear
+ * map.
+ */
+ if (IS_ENABLED(CONFIG_HIBERNATION)) {
+ static struct notifier_block nb = {
+ .notifier_call = arm64_hibernate_pm_notify
+ };
+
+ register_pm_notifier(&nb);
+ }
}
#ifdef CONFIG_KFENCE
flags);
}
- /* Map the kernel data/bss read-only in the linear map */
- __map_memblock(init_end, kernel_end, PAGE_KERNEL_RO, flags);
- flush_tlb_kernel_range((unsigned long)lm_alias(__init_end),
- (unsigned long)lm_alias(__bss_stop));
+ /* Map the kernel data/bss as invalid in the linear map */
+ mark_linear_data_alias_valid(false);
}
void mark_rodata_ro(void)