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