[PATCH 6/6] arm: turn on the MMU

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



We should probably always run with the mmu on, so let's
enable it from setup with an identity map.

Signed-off-by: Andrew Jones <drjones@xxxxxxxxxx>
---
 arm/cstart.S          | 33 ++++++++++++++++++++++++++++++++
 config/config-arm.mak |  3 ++-
 lib/arm/asm/mmu.h     | 34 ++++++++++++++++++++++++++++++++-
 lib/arm/mmu.c         | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/arm/processor.c   | 11 +++++++++++
 lib/arm/setup.c       |  3 +++
 6 files changed, 135 insertions(+), 2 deletions(-)
 create mode 100644 lib/arm/mmu.c

diff --git a/arm/cstart.S b/arm/cstart.S
index cc87ece4b6b40..a1ccfb24bb4e0 100644
--- a/arm/cstart.S
+++ b/arm/cstart.S
@@ -72,6 +72,39 @@ halt:
 	b	1b
 
 /*
+ * asm_mmu_enable
+ *   Inputs:
+ *     (r0 - lo, r1 - hi) is the base address of the translation table
+ *   Outputs: none
+ */
+.equ	PRRR,	0xeeaa4400		@ MAIR0 (from Linux kernel)
+.equ	NMRR,	0xff000004		@ MAIR1 (from Linux kernel)
+.globl asm_mmu_enable
+asm_mmu_enable:
+	/* TTBCR */
+	mrc	p15, 0, r2, c2, c0, 2
+	orr	r2, #(1 << 31)		@ TTB_EAE
+	mcr	p15, 0, r2, c2, c0, 2
+
+	/* MAIR */
+	ldr	r2, =PRRR
+	mrc	p15, 0, r2, c10, c2, 0
+	ldr	r2, =NMRR
+	mrc	p15, 0, r2, c10, c2, 1
+
+	/* TTBR0 */
+	mcrr	p15, 0, r0, r1, c2
+
+	/* SCTLR */
+	mrc	p15, 0, r2, c1, c0, 0
+	orr	r2, #CR_C
+	orr	r2, #CR_I
+	orr	r2, #CR_M
+	mcr	p15, 0, r2, c1, c0, 0
+
+	mov     pc, lr
+
+/*
  * Vector stubs
  * Simplified version of the Linux kernel implementation
  *   arch/arm/kernel/entry-armv.S
diff --git a/config/config-arm.mak b/config/config-arm.mak
index 8a274c50332b0..86e1d75169b59 100644
--- a/config/config-arm.mak
+++ b/config/config-arm.mak
@@ -42,7 +42,8 @@ cflatobjs += \
 	lib/arm/io.o \
 	lib/arm/setup.o \
 	lib/arm/spinlock.o \
-	lib/arm/processor.o
+	lib/arm/processor.o \
+	lib/arm/mmu.o
 
 libeabi = lib/arm/libeabi.a
 eabiobjs = lib/arm/eabi_compat.o
diff --git a/lib/arm/asm/mmu.h b/lib/arm/asm/mmu.h
index 987928b2c432c..451c7493c2aba 100644
--- a/lib/arm/asm/mmu.h
+++ b/lib/arm/asm/mmu.h
@@ -5,7 +5,39 @@
  *
  * This work is licensed under the terms of the GNU LGPL, version 2.
  */
+#include "asm/page.h"
+#include "asm/barrier.h"
+#include "alloc.h"
 
-#define mmu_enabled() (0)
+#define PTRS_PER_PGD	4
+#define PGDIR_SHIFT	30
+#define PGDIR_SIZE	(1UL << PGDIR_SHIFT)
+#define PGDIR_MASK	(~((1 << PGDIR_SHIFT) - 1))
+
+#define pgd_free(pgd) free(pgd)
+static inline pgd_t *pgd_alloc(void)
+{
+	pgd_t *pgd = memalign(L1_CACHE_BYTES, PTRS_PER_PGD * sizeof(pgd_t));
+	memset(pgd, 0, PTRS_PER_PGD * sizeof(pgd_t));
+	return pgd;
+}
+
+static inline void local_flush_tlb_all(void)
+{
+	asm volatile("mcr p15, 0, %0, c8, c7, 0" :: "r" (0));
+	dsb();
+	isb();
+}
+
+static inline void flush_tlb_all(void)
+{
+	//TODO
+	local_flush_tlb_all();
+}
+
+extern bool mmu_enabled(void);
+extern void mmu_enable(pgd_t *pgtable);
+extern void mmu_enable_idmap(void);
+extern void mmu_init_io_sect(pgd_t *pgtable);
 
 #endif /* __ASMARM_MMU_H_ */
diff --git a/lib/arm/mmu.c b/lib/arm/mmu.c
new file mode 100644
index 0000000000000..c9d39bf6464b8
--- /dev/null
+++ b/lib/arm/mmu.c
@@ -0,0 +1,53 @@
+/*
+ * MMU enable and page table manipulation functions
+ *
+ * Copyright (C) 2014, Red Hat Inc, Andrew Jones <drjones@xxxxxxxxxx>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.
+ */
+#include "asm/setup.h"
+#include "asm/mmu.h"
+#include "asm/pgtable-hwdef.h"
+
+static bool mmu_on;
+static pgd_t idmap[PTRS_PER_PGD] __attribute__((aligned(L1_CACHE_BYTES)));
+
+bool mmu_enabled(void)
+{
+	return mmu_on;
+}
+
+extern void asm_mmu_enable(phys_addr_t pgtable);
+void mmu_enable(pgd_t *pgtable)
+{
+	asm_mmu_enable(__pa(pgtable));
+	flush_tlb_all();
+	mmu_on = true;
+}
+
+void mmu_init_io_sect(pgd_t *pgtable)
+{
+	/*
+	 * mach-virt reserves the first 1G section for I/O
+	 */
+	pgd_val(pgtable[0]) = PMD_TYPE_SECT | PMD_SECT_AF | PMD_SECT_USER;
+	pgd_val(pgtable[0]) |= PMD_SECT_UNCACHED;
+}
+
+void mmu_enable_idmap(void)
+{
+	unsigned long sect, end;
+
+	mmu_init_io_sect(idmap);
+
+	end = sizeof(long) == 8 || !(PHYS_END >> 32) ? PHYS_END : 0xfffff000;
+
+	for (sect = PHYS_OFFSET & PGDIR_MASK; sect < end; sect += PGDIR_SIZE) {
+		int i = sect >> PGDIR_SHIFT;
+		pgd_val(idmap[i]) = sect;
+		pgd_val(idmap[i]) |= PMD_TYPE_SECT | PMD_SECT_AF | PMD_SECT_USER;
+		pgd_val(idmap[i]) |= PMD_SECT_S | PMD_SECT_WBWA;
+	}
+
+	mmu_enable(idmap);
+}
diff --git a/lib/arm/processor.c b/lib/arm/processor.c
index 382a128edd415..866d11975b23b 100644
--- a/lib/arm/processor.c
+++ b/lib/arm/processor.c
@@ -92,6 +92,17 @@ void do_handle_exception(enum vector v, struct pt_regs *regs)
 
 	printf("Exception frame registers:\n");
 	show_regs(regs);
+	if (v == EXCPTN_DABT) {
+		unsigned long far, fsr;
+		asm volatile("mrc p15, 0, %0, c6, c0, 0": "=r" (far));
+		asm volatile("mrc p15, 0, %0, c5, c0, 0": "=r" (fsr));
+		printf("DFAR: %08lx    DFSR: %08lx\n", far, fsr);
+	} else if (v == EXCPTN_PABT) {
+		unsigned long far, fsr;
+		asm volatile("mrc p15, 0, %0, c6, c0, 2": "=r" (far));
+		asm volatile("mrc p15, 0, %0, c5, c0, 1": "=r" (fsr));
+		printf("IFAR: %08lx    IFSR: %08lx\n", far, fsr);
+	}
 	abort();
 }
 
diff --git a/lib/arm/setup.c b/lib/arm/setup.c
index 3941c9757dcb2..5fa37ca35f383 100644
--- a/lib/arm/setup.c
+++ b/lib/arm/setup.c
@@ -16,6 +16,7 @@
 #include "alloc.h"
 #include "asm/setup.h"
 #include "asm/page.h"
+#include "asm/mmu.h"
 
 extern unsigned long stacktop;
 extern void io_init(void);
@@ -57,6 +58,8 @@ static void mem_init(phys_addr_t freemem_start)
 
 	phys_alloc_init(freemem_start, mem_end - freemem_start);
 	phys_alloc_set_minimum_alignment(SMP_CACHE_BYTES);
+
+	mmu_enable_idmap();
 }
 
 void setup(unsigned long arg __unused, unsigned long id __unused,
-- 
1.9.3

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux