[RFC PATCH 14/17] ARM: kernel: save/restore 1:1 page tables

Lorenzo Pieralisi lorenzo.pieralisi at arm.com
Thu Jul 7 11:50:27 EDT 2011


This patch adds the code required to allocate and populate page tables
that are needed by save/restore code to deal with MMU off/on
transactions.

MMU is enabled early in the resume path which allows to call into
Linux subsystems with init_mm virtual mappings (cloned at boot).

Current thread page table pointer and context id is saved on power
down from active_mm and restored on warm boot.
Currently the translation tables contains 1:1 mappings of the Linux
kernel code and data, and 1:1 UNCACHED mapping of control code required when MMU
is turned off in the restore code path.

Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi at arm.com>
---
 arch/arm/kernel/sr_mapping.c |   78 ++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 78 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/kernel/sr_mapping.c

diff --git a/arch/arm/kernel/sr_mapping.c b/arch/arm/kernel/sr_mapping.c
new file mode 100644
index 0000000..32640dc
--- /dev/null
+++ b/arch/arm/kernel/sr_mapping.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2008-2011 ARM Limited
+ * Author(s): Jon Callan, Lorenzo Pieralisi
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/errno.h>
+#include <linux/mm_types.h>
+
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
+#include <asm/sections.h>
+#include <asm/cputype.h>
+#include <asm/cacheflush.h>
+#include "sr_helpers.h"
+#include "sr.h"
+
+#define PROT_PTE_DEVICE		(L_PTE_PRESENT|L_PTE_YOUNG|L_PTE_DIRTY|L_PTE_XN)
+
+static pgd_t *pgd;
+
+static void *linux_sr_map_page(void *addr, unsigned int size,
+				 pgprot_t prot)
+{
+	pmd_t *pmd;
+	pte_t *pte;
+	u64 pfn;
+	unsigned long end = (unsigned long) (addr) + size;
+	unsigned long vaddr = (unsigned long) (addr);
+
+	pmd = pmd_offset(pgd + pgd_index(vaddr), vaddr);
+	pfn = vaddr >> PAGE_SHIFT;
+	pte = pte_alloc_kernel(pmd, vaddr);
+
+	do {
+		if (!pte)
+			return NULL;
+		set_pte_ext(pte, pfn_pte(pfn, prot), 0);
+		outer_clean_range(__pa(pte), __pa(pte + 1));
+		pfn++;
+	} while (pte++, vaddr += PAGE_SIZE, vaddr != end);
+
+	return addr;
+}
+
+int linux_sr_setup_translation_tables(void)
+{
+	pgd = pgd_alloc(&init_mm);
+
+	if (!pgd)
+		return -ENOMEM;
+	/*
+	 * These kernel identity mappings are not strictly necessary
+	 * since resume code creates them on the fly.
+	 * They are left for completeness in case the suspend
+	 * code had to turn MMU off for a power down failure and
+	 * the call to (*sr_sleep) returns.
+	 */
+	identity_mapping_add(pgd, __pa(_stext), __pa(_etext));
+	identity_mapping_add(pgd, __pa(_sdata), __pa(_edata));
+
+	linux_sr_map_page(context_memory_uncached,
+				CONTEXT_SPACE_UNCACHED,
+				__pgprot(PROT_PTE_DEVICE |
+				L_PTE_MT_UNCACHED | L_PTE_SHARED));
+
+	/* save pgd of translation tables for cpu_switch_mm */
+	main_table.fw_mmu_context = pgd;
+
+	__cpuc_flush_dcache_area(pgd, sizeof(pgd));
+	outer_clean_range(__pa(pgd), __pa(pgd + 1));
+	return 0;
+}
-- 
1.7.4.4





More information about the linux-arm-kernel mailing list