Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1df8f4cf authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "soc: qcom: mem-offline: Clear page-table entries after offline"

parents 582edb78 9b809e6e
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -391,6 +391,14 @@ static phys_addr_t pgd_pgtable_alloc(void)
	return __pa(ptr);
}

void create_pgtable_mapping(phys_addr_t start, phys_addr_t end)
{
	unsigned long virt = (unsigned long)phys_to_virt(start);

	__create_pgd_mapping(init_mm.pgd, start, virt, end - start,
				PAGE_KERNEL, NULL, 0);
}

/*
 * This function can only be used to modify existing table entries,
 * without allocating new levels of table. Note that this permits the
+47 −0
Original line number Diff line number Diff line
@@ -25,6 +25,8 @@
#include <linux/mailbox_client.h>
#include <linux/mailbox/qmp.h>
#include <soc/qcom/rpm-smd.h>
#include <asm/tlbflush.h>
#include <asm/cacheflush.h>

#define RPM_DDR_REQ 0x726464
#define AOP_MSG_ADDR_MASK		0xffffffff
@@ -70,6 +72,43 @@ struct memory_refresh_request {

static struct section_stat *mem_info;

static void clear_pgtable_mapping(phys_addr_t start, phys_addr_t end)
{
	unsigned long size = end - start;
	unsigned long virt = (unsigned long)phys_to_virt(start);
	unsigned long addr_end = virt + size;
	pgd_t *pgd;
	pud_t *pud;
	pmd_t *pmd;

	pgd = pgd_offset_k(virt);

	while (virt < addr_end) {

		/* Check if we have PUD section mapping */
		pud = pud_offset(pgd, virt);
		if (pud_sect(*pud)) {
			pud_clear(pud);
			virt += PUD_SIZE;
			continue;
		}

		/* Check if we have PMD section mapping */
		pmd = pmd_offset(pud, virt);
		if (pmd_sect(*pmd)) {
			pmd_clear(pmd);
			virt += PMD_SIZE;
			continue;
		}

		/* Clear mapping for page entry */
		set_memory_valid(virt, 1, (int)false);
		virt += PAGE_SIZE;
	}

	virt = (unsigned long)phys_to_virt(start);
	flush_tlb_kernel_range(virt, addr_end);
}
void record_stat(unsigned long sec, ktime_t delay, int mode)
{
	unsigned int total_sec = end_section_nr - start_section_nr + 1;
@@ -188,6 +227,10 @@ static int mem_event_callback(struct notifier_block *self,
			pr_err("PASR: %s online request addr:0x%llx failed\n",
			       is_rpm_controller ? "RPM" : "AOP",
			       __pfn_to_phys(start));
		if (!debug_pagealloc_enabled()) {
			/* Create kernel page-tables */
			create_pgtable_mapping(start_addr, end_addr);
		}

		break;
	case MEM_ONLINE:
@@ -205,6 +248,10 @@ static int mem_event_callback(struct notifier_block *self,
		cur = ktime_get();
		break;
	case MEM_OFFLINE:
		if (!debug_pagealloc_enabled()) {
			/* Clear kernel page-tables */
			clear_pgtable_mapping(start_addr, end_addr);
		}
		if (send_msg(mn, false))
			pr_err("PASR: %s offline request addr:0x%llx failed\n",
			       is_rpm_controller ? "RPM" : "AOP",
+1 −1
Original line number Diff line number Diff line
@@ -111,7 +111,7 @@ void __next_reserved_mem_region(u64 *idx, phys_addr_t *out_start,

void __memblock_free_early(phys_addr_t base, phys_addr_t size);
void __memblock_free_late(phys_addr_t base, phys_addr_t size);

void create_pgtable_mapping(phys_addr_t start, phys_addr_t end);
/**
 * for_each_mem_range - iterate through memblock areas from type_a and not
 * included in type_b. Or just type_a if type_b is NULL.