mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-11 15:11:48 -04:00
soc: qcom: mem-offline: Restore page table mappings properly in online path
On newer kernels, a feature was added to adjust the linear alias mappings of pages mapped within the vmalloc space such that the mappings are consistent with respect to each other (i.e. if the memory is mapped as R/O in the vmalloc space, then the linear mapping's permission attributes should also reflect a R/O mapping). This is known as the rodata full feature. This sort of protection is not feasible with block mappings, as block mappings do not allow access control at a page granule, so when this feature is enabled, or debug pagealloc is active, the kernel will not use block mappings. The logic in the memory offlining driver is not aware of the rodata_full feature and when the memory is being onlined after being offlined, it blindly assumes that if debug pagealloc is disabled, it can restore the block mappings for the memory that is being onlined. This leads to inconsistencies, as the memory is actually mapped without block mappings, which ultimately results in the page table mapping not being restored from the time at which the memory was offlined. Thus, when onlining memory online the memory without block mappings if the rodata full feature is enabled and debug page alloc is disabled. Otherwise, restore the mappings using block mappings. Change-Id: I56a3d3754deb62e0a894a14b06eaab522e6f0a05 Signed-off-by: Isaac J. Manjarres <isaacm@codeaurora.org>
This commit is contained in:
parent
0f30cf7e56
commit
f400169d69
1 changed files with 19 additions and 2 deletions
|
|
@ -1,11 +1,12 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/memory.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/memblock.h>
|
||||
#include <linux/mmu_context.h>
|
||||
#include <linux/mmzone.h>
|
||||
#include <linux/ktime.h>
|
||||
#include <linux/of.h>
|
||||
|
|
@ -93,6 +94,22 @@ static void clear_pgtable_mapping(phys_addr_t start, phys_addr_t end)
|
|||
flush_tlb_kernel_range(virt, addr_end);
|
||||
}
|
||||
|
||||
static void init_pgtable_mapping(phys_addr_t start, phys_addr_t end)
|
||||
{
|
||||
unsigned long size = end - start;
|
||||
|
||||
/*
|
||||
* When rodata_full is enabled, memory is mapped at a page size
|
||||
* granule, as opposed to a block mapping, so restore the attribute
|
||||
* of each PTE when rodata_full is enabled.
|
||||
*/
|
||||
if (rodata_full)
|
||||
set_memory_valid((unsigned long)phys_to_virt(start),
|
||||
size >> PAGE_SHIFT, (int)true);
|
||||
else
|
||||
create_pgtable_mapping(start, end);
|
||||
}
|
||||
|
||||
static void record_stat(unsigned long sec, ktime_t delay, int mode)
|
||||
{
|
||||
unsigned int total_sec = end_section_nr - start_section_nr + 1;
|
||||
|
|
@ -324,7 +341,7 @@ static int mem_event_callback(struct notifier_block *self,
|
|||
|
||||
if (!debug_pagealloc_enabled()) {
|
||||
/* Create kernel page-tables */
|
||||
create_pgtable_mapping(start_addr, end_addr);
|
||||
init_pgtable_mapping(start_addr, end_addr);
|
||||
}
|
||||
|
||||
break;
|
||||
|
|
|
|||
Loading…
Reference in a new issue