1 /* $NetBSD: epoc32.cpp,v 1.1 2013/04/28 12:11:27 kiyohara Exp $ */ 2 /* 3 * Copyright (c) 2013 KIYOHARA Takashi 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 19 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 23 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 24 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 * POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include <e32base.h> 29 #include <e32def.h> 30 #include <e32std.h> 31 32 #include "cpu.h" 33 #include "e32boot.h" 34 #include "ekern.h" 35 #include "epoc32.h" 36 37 #include "arm/armreg.h" 38 #include "arm/arm32/pte.h" 39 40 41 static inline void 42 AllowAllDomains(void) 43 { 44 TUint domains; 45 46 #define ALL_DOMAINS(v) \ 47 (((v) << 28) | \ 48 ((v) << 24) | \ 49 ((v) << 20) | \ 50 ((v) << 16) | \ 51 ((v) << 12) | \ 52 ((v) << 8) | \ 53 ((v) << 4) | \ 54 ((v) << 0)) 55 56 domains = ALL_DOMAINS(0xf); 57 __asm("mcr p15, 0, %0, c3, c0" : : "r"(domains)); 58 } 59 60 EPOC32::EPOC32(void) 61 { 62 TUint procid; 63 64 __asm("mrc p15, 0, %0, c0, c0" : "=r"(procid)); 65 if (procid == CPU_ID_SA1100) { 66 cpu = new SA1100; 67 } else if ((procid & CPU_ID_IMPLEMENTOR_MASK) == CPU_ID_ARM_LTD) { 68 if (CPU_ID_IS7(procid)) { 69 if ((procid & CPU_ID_7ARCH_MASK) == CPU_ID_7ARCH_V3) 70 cpu = new ARM7; 71 else 72 cpu = new ARM7TDMI; 73 } 74 } 75 } 76 77 EPOC32::~EPOC32(void) 78 { 79 } 80 81 TAny * 82 EPOC32::GetPhysicalAddress(TAny *address) 83 { 84 TUint l1Index, l1, pageOffset, pa, va; 85 TUint *l1Tbl; 86 87 AllowAllDomains(); 88 89 l1Tbl = GetTTB(); 90 91 va = (TUint)address; 92 pa = pageOffset = 0; 93 l1Index = (va & L1_ADDR_BITS) >> L1_S_SHIFT; 94 l1 = *(l1Tbl + l1Index); 95 switch (l1 & L1_TYPE_MASK) { 96 case L1_TYPE_INV: 97 case L1_TYPE_F: 98 return NULL; 99 100 case L1_TYPE_S: 101 pa = l1 & L1_S_ADDR_MASK; 102 pageOffset = va & L1_S_OFFSET; 103 break; 104 105 case L1_TYPE_C: 106 { 107 TUint *l2Tbl, tag; 108 109 l2Tbl = (TUint *)(l1 & L1_C_ADDR_MASK); 110 tag = MapPhysicalAddress(l2Tbl, (TAny **)&l2Tbl); 111 pa = *(l2Tbl + ((va & L2_ADDR_BITS) >> 12)); 112 UnmapPhysicalAddress(l2Tbl, tag); 113 114 switch (pa & L2_TYPE_MASK) { 115 case L2_TYPE_L: 116 pa &= L2_L_FRAME; 117 pageOffset = va & L2_L_OFFSET; 118 break; 119 120 case L2_TYPE_S: 121 pa &= L2_S_FRAME; 122 pageOffset = va & L2_S_OFFSET; 123 break; 124 125 default: 126 pageOffset = 0xffffffff; /* XXXX */ 127 } 128 } 129 } 130 return (TAny *)(pa | pageOffset); 131 } 132 133 TUint 134 EPOC32::MapPhysicalAddress(TAny *pa, TAny **vap) 135 { 136 TUint *l1Tbl, l1Index, l1, tag; 137 138 AllowAllDomains(); 139 140 l1Tbl = GetTTB(); 141 142 l1Index = ((TUint)pa & L1_ADDR_BITS) >> L1_S_SHIFT; 143 l1 = ((TUint)pa & L1_S_ADDR_MASK) | 144 L1_S_AP(AP_KRW) | L1_S_IMP | L1_TYPE_S; 145 tag = *(l1Tbl + l1Index); 146 *(l1Tbl + l1Index) = l1; 147 cpu->cacheFlush(); 148 cpu->tlbFlush(); 149 *vap = pa; 150 151 return tag; 152 } 153 154 void 155 EPOC32::UnmapPhysicalAddress(TAny *address, TUint tag) 156 { 157 TUint *l1Tbl, l1Index, pa; 158 159 AllowAllDomains(); 160 161 l1Tbl = GetTTB(); 162 163 pa = (TUint)address; 164 l1Index = (pa & L1_ADDR_BITS) >> L1_S_SHIFT; 165 *(l1Tbl + l1Index) = tag; 166 cpu->cacheFlush(); 167 cpu->tlbFlush(); 168 } 169