xref: /kvm-unit-tests/lib/arm/mmu.c (revision 153d193674069bd25373e1dce6bdc9a1b86e0e33)
1*153d1936SAndrew Jones /*
2*153d1936SAndrew Jones  * MMU enable and page table manipulation functions
3*153d1936SAndrew Jones  *
4*153d1936SAndrew Jones  * Copyright (C) 2014, Red Hat Inc, Andrew Jones <drjones@redhat.com>
5*153d1936SAndrew Jones  *
6*153d1936SAndrew Jones  * This work is licensed under the terms of the GNU LGPL, version 2.
7*153d1936SAndrew Jones  */
8*153d1936SAndrew Jones #include "asm/setup.h"
9*153d1936SAndrew Jones #include "asm/mmu.h"
10*153d1936SAndrew Jones #include "asm/pgtable-hwdef.h"
11*153d1936SAndrew Jones 
12*153d1936SAndrew Jones static bool mmu_on;
13*153d1936SAndrew Jones static pgd_t idmap[PTRS_PER_PGD] __attribute__((aligned(L1_CACHE_BYTES)));
14*153d1936SAndrew Jones 
15*153d1936SAndrew Jones bool mmu_enabled(void)
16*153d1936SAndrew Jones {
17*153d1936SAndrew Jones 	return mmu_on;
18*153d1936SAndrew Jones }
19*153d1936SAndrew Jones 
20*153d1936SAndrew Jones extern void asm_mmu_enable(phys_addr_t pgtable);
21*153d1936SAndrew Jones void mmu_enable(pgd_t *pgtable)
22*153d1936SAndrew Jones {
23*153d1936SAndrew Jones 	asm_mmu_enable(__pa(pgtable));
24*153d1936SAndrew Jones 	flush_tlb_all();
25*153d1936SAndrew Jones 	mmu_on = true;
26*153d1936SAndrew Jones }
27*153d1936SAndrew Jones 
28*153d1936SAndrew Jones void mmu_init_io_sect(pgd_t *pgtable)
29*153d1936SAndrew Jones {
30*153d1936SAndrew Jones 	/*
31*153d1936SAndrew Jones 	 * mach-virt reserves the first 1G section for I/O
32*153d1936SAndrew Jones 	 */
33*153d1936SAndrew Jones 	pgd_val(pgtable[0]) = PMD_TYPE_SECT | PMD_SECT_AF | PMD_SECT_USER;
34*153d1936SAndrew Jones 	pgd_val(pgtable[0]) |= PMD_SECT_UNCACHED;
35*153d1936SAndrew Jones }
36*153d1936SAndrew Jones 
37*153d1936SAndrew Jones void mmu_enable_idmap(void)
38*153d1936SAndrew Jones {
39*153d1936SAndrew Jones 	unsigned long sect, end;
40*153d1936SAndrew Jones 
41*153d1936SAndrew Jones 	mmu_init_io_sect(idmap);
42*153d1936SAndrew Jones 
43*153d1936SAndrew Jones 	end = sizeof(long) == 8 || !(PHYS_END >> 32) ? PHYS_END : 0xfffff000;
44*153d1936SAndrew Jones 
45*153d1936SAndrew Jones 	for (sect = PHYS_OFFSET & PGDIR_MASK; sect < end; sect += PGDIR_SIZE) {
46*153d1936SAndrew Jones 		int i = sect >> PGDIR_SHIFT;
47*153d1936SAndrew Jones 		pgd_val(idmap[i]) = sect;
48*153d1936SAndrew Jones 		pgd_val(idmap[i]) |= PMD_TYPE_SECT | PMD_SECT_AF | PMD_SECT_USER;
49*153d1936SAndrew Jones 		pgd_val(idmap[i]) |= PMD_SECT_S | PMD_SECT_WBWA;
50*153d1936SAndrew Jones 	}
51*153d1936SAndrew Jones 
52*153d1936SAndrew Jones 	mmu_enable(idmap);
53*153d1936SAndrew Jones }
54