/* * Copyright (c) 2008 Travis Geiselbrecht * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files * (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include #include #include #include #include #include #if ARM_WITH_MMU #define MB (1024*1024) /* the location of the table may be brought in from outside */ #if WITH_EXTERNAL_TRANSLATION_TABLE #if !defined(MMU_TRANSLATION_TABLE_ADDR) #error must set MMU_TRANSLATION_TABLE_ADDR in the make configuration #endif static uint32_t *tt = (void *)MMU_TRANSLATION_TABLE_ADDR; #else /* the main translation table */ static uint32_t tt[4096] __ALIGNED(16384); #endif void arm_mmu_map_section(addr_t paddr, addr_t vaddr, uint flags) { int index; /* Get the index into the translation table */ index = vaddr / MB; /* Set the entry value: * (2<<0): Section entry * (0<<5): Domain = 0 * flags: TEX, CB and AP bit settings provided by the caller. */ tt[index] = (paddr & ~(MB-1)) | (0<<5) | (2<<0) | flags; arm_invalidate_tlb(); } void arm_mmu_init(void) { int i; /* set some mmu specific control bits: * access flag disabled, TEX remap disabled, mmu disabled */ arm_write_cr1(arm_read_cr1() & ~((1<<29)|(1<<28)|(1<<0))); if (platform_use_identity_mmu_mappings()) { /* set up an identity-mapped translation table with * strongly ordered memory type and read/write access. */ for (i=0; i < 4096; i++) { arm_mmu_map_section(i * MB, i * MB, MMU_MEMORY_TYPE_STRONGLY_ORDERED | MMU_MEMORY_AP_READ_WRITE); } } platform_init_mmu_mappings(); /* set up the translation table base */ arm_write_ttbr((uint32_t)tt); /* set up the domain access register */ arm_write_dacr(0x00000001); /* turn on the mmu */ arm_write_cr1(arm_read_cr1() | 0x1); } void arch_disable_mmu(void) { /* Ensure all memory access are complete * before disabling MMU */ dsb(); arm_write_cr1(arm_read_cr1() & ~(1<<0)); arm_invalidate_tlb(); } #endif // ARM_WITH_MMU