1/* $NetBSD: sh_mmu.cpp,v 1.8 2021/08/22 20:18:39 andvar Exp $ */ 2 3/*- 4 * Copyright (c) 2001, 2002 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by UCHIYAMA Yasushi. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32#include <sh3/sh_arch.h> 33#include <sh3/sh_mmu.h> 34 35#include <sh3/cpu/sh3.h> 36#include <sh3/cpu/sh4.h> 37 38// 39// Get physical address from memory mapped TLB. 40// SH3 version. SH4 can't do this method. because address/data array must be 41// accessed from P2. 42// 43paddr_t 44MemoryManager_SHMMU::searchPage(vaddr_t vaddr) 45{ 46 uint32_t vpn, idx, s, dum, aae, dae, entry_idx, asid; 47 paddr_t paddr = ~0; 48 int way, kmode; 49 50 vpn = vaddr & SH3_PAGE_MASK; 51 // Windows CE uses VPN-only index-mode. 52 idx = vaddr & SH3_MMU_VPN_MASK; 53 54 kmode = SetKMode(1); 55 // Get current ASID 56 asid = _reg_read_4(SH3_PTEH) & SH3_PTEH_ASID_MASK; 57 58 // to avoid another TLB access, disable external interrupt. 59 s = suspendIntr(); 60 61 do { 62 // load target address page to TLB 63 dum = _reg_read_4(vaddr); 64 _reg_write_4(vaddr, dum); 65 66 for (way = 0; way < SH3_MMU_WAY; way++) { 67 entry_idx = idx | (way << SH3_MMU_WAY_SHIFT); 68 // inquire MMU address array. 69 aae = _reg_read_4(SH3_MMUAA | entry_idx); 70 71 if (!(aae & SH3_MMU_D_VALID) || 72 ((aae & SH3_MMUAA_D_ASID_MASK) != asid) || 73 (((aae | idx) & SH3_PAGE_MASK) != vpn)) 74 continue; 75 76 // entry found. 77 // inquire MMU data array to get its physical address. 78 dae = _reg_read_4(SH3_MMUDA | entry_idx); 79 paddr = (dae & SH3_PAGE_MASK) | (vaddr & ~SH3_PAGE_MASK); 80 break; 81 } 82 } while (paddr == ~0); 83 84 resumeIntr(s); 85 SetKMode(kmode); 86 87 return paddr; 88} 89 90void 91MemoryManager_SHMMU::CacheDump() 92{ 93 static const char *able[] = {"dis", "en" }; 94 int write_through_p0_u0_p3; 95 int write_through_p1; 96 uint32_t r; 97 int kmode; 98 99 DPRINTF_SETUP(); 100 101 kmode = SetKMode(1); 102 switch (SHArchitecture::cpu_type()) { 103 default: 104 DPRINTF((TEXT("unknown architecture.\n"))); 105 SetKMode(kmode); 106 return; 107 case 3: 108 r = _reg_read_4(SH3_CCR); 109 DPRINTF((TEXT("cache %Sabled"), 110 able[(r & SH3_CCR_CE ? 1 : 0)])); 111 if (r & SH3_CCR_RA) 112 DPRINTF((TEXT(" ram-mode"))); 113 114 write_through_p0_u0_p3 = r & SH3_CCR_WT; 115 write_through_p1 = !(r & SH3_CCR_CB); 116 break; 117 case 4: 118 r = _reg_read_4(SH4_CCR); 119 DPRINTF((TEXT("I-cache %Sabled"), 120 able[(r & SH4_CCR_ICE) ? 1 : 0])); 121 if (r & SH4_CCR_IIX) 122 DPRINTF((TEXT(" index-mode "))); 123 DPRINTF((TEXT(" D-cache %Sabled"), 124 able[(r & SH4_CCR_OCE) ? 1 : 0])); 125 if (r & SH4_CCR_OIX) 126 DPRINTF((TEXT(" index-mode"))); 127 if (r & SH4_CCR_ORA) 128 DPRINTF((TEXT(" ram-mode"))); 129 130 write_through_p0_u0_p3 = r & SH4_CCR_WT; 131 write_through_p1 = !(r & SH4_CCR_CB); 132 break; 133 } 134 DPRINTF((TEXT("."))); 135 136 // Write-through/back 137 DPRINTF((TEXT(" P0, U0, P3 write-%S P1 write-%S\n"), 138 write_through_p0_u0_p3 ? "through" : "back", 139 write_through_p1 ? "through" : "back")); 140 141 SetKMode(kmode); 142} 143 144void 145MemoryManager_SHMMU::MMUDump() 146{ 147#define ON(x, c) ((x) & (c) ? '|' : '.') 148 uint32_t r, e, a; 149 int i, kmode; 150 151 DPRINTF_SETUP(); 152 153 kmode = SetKMode(1); 154 DPRINTF((TEXT("MMU:\n"))); 155 switch (SHArchitecture::cpu_type()) { 156 default: 157 DPRINTF((TEXT("unknown architecture.\n"))); 158 SetKMode(kmode); 159 return; 160 case 3: 161 r = _reg_read_4(SH3_MMUCR); 162 if (!(r & SH3_MMUCR_AT)) 163 goto disabled; 164 165 // MMU configuration. 166 DPRINTF((TEXT("%s index-mode, %s virtual storage mode\n"), 167 r & SH3_MMUCR_IX 168 ? TEXT("ASID + VPN") : TEXT("VPN only"), 169 r & SH3_MMUCR_SV ? TEXT("single") : TEXT("multiple"))); 170 171 // Dump TLB. 172 DPRINTF((TEXT("---TLB---\n"))); 173 DPRINTF((TEXT(" VPN ASID PFN VDCG PR SZ\n"))); 174 for (i = 0; i < SH3_MMU_WAY; i++) { 175 DPRINTF((TEXT(" [way %d]\n"), i)); 176 for (e = 0; e < SH3_MMU_ENTRY; e++) { 177 // address/data array common offset. 178 a = (e << SH3_MMU_VPN_SHIFT) | 179 (i << SH3_MMU_WAY_SHIFT); 180 181 r = _reg_read_4(SH3_MMUAA | a); 182 DPRINTF((TEXT("0x%08x %3d"), 183 r & SH3_MMUAA_D_VPN_MASK, 184 r & SH3_MMUAA_D_ASID_MASK)); 185 r = _reg_read_4(SH3_MMUDA | a); 186 DPRINTF((TEXT(" 0x%08x %c%c%c%c %d %dK\n"), 187 r & SH3_MMUDA_D_PPN_MASK, 188 ON(r, SH3_MMUDA_D_V), 189 ON(r, SH3_MMUDA_D_D), 190 ON(r, SH3_MMUDA_D_C), 191 ON(r, SH3_MMUDA_D_SH), 192 (r & SH3_MMUDA_D_PR_MASK) >> 193 SH3_MMUDA_D_PR_SHIFT, 194 r & SH3_MMUDA_D_SZ ? 4 : 1)); 195 } 196 } 197 198 break; 199 case 4: 200 r = _reg_read_4(SH4_MMUCR); 201 if (!(r & SH4_MMUCR_AT)) 202 goto disabled; 203 DPRINTF((TEXT("%s virtual storage mode,"), 204 r & SH3_MMUCR_SV ? TEXT("single") : TEXT("multiple"))); 205 DPRINTF((TEXT(" SQ access: (privilege%S)"), 206 r & SH4_MMUCR_SQMD ? "" : "/user")); 207 DPRINTF((TEXT("\n"))); 208#if sample_code 209 // 210 // Memory mapped TLB accessing program must run on P2. 211 // This is sample code. 212 // 213 // Dump ITLB 214 DPRINTF((TEXT("---ITLB---\n"))); 215 for (i = 0; i < 4; i++) { 216 e = i << SH4_ITLB_E_SHIFT; 217 r = _reg_read_4(SH4_ITLB_AA | e); 218 DPRINTF((TEXT("%08x %3d _%c"), 219 r & SH4_ITLB_AA_VPN_MASK, 220 r & SH4_ITLB_AA_ASID_MASK, 221 ON(r, SH4_ITLB_AA_V))); 222 r = _reg_read_4(SH4_ITLB_DA1 | e); 223 DPRINTF((TEXT(" %08x %c%c_%c_ %1d"), 224 r & SH4_ITLB_DA1_PPN_MASK, 225 ON(r, SH4_ITLB_DA1_V), 226 ON(r, SH4_ITLB_DA1_C), 227 ON(r, SH4_ITLB_DA1_SH), 228 (r & SH4_ITLB_DA1_PR) >> SH4_UTLB_DA1_PR_SHIFT 229 )); 230 r = _reg_read_4(SH4_ITLB_DA2 | e); 231 DPRINTF((TEXT(" %c%d\n"), 232 ON(r, SH4_ITLB_DA2_TC), 233 r & SH4_ITLB_DA2_SA_MASK)); 234 } 235 // Dump UTLB 236 DPRINTF((TEXT("---UTLB---\n"))); 237 for (i = 0; i < 64; i++) { 238 e = i << SH4_UTLB_E_SHIFT; 239 r = _reg_read_4(SH4_UTLB_AA | e); 240 DPRINTF((TEXT("%08x %3d %c%c"), 241 r & SH4_UTLB_AA_VPN_MASK, 242 ON(r, SH4_UTLB_AA_D), 243 ON(r, SH4_UTLB_AA_V), 244 r & SH4_UTLB_AA_ASID_MASK)); 245 r = _reg_read_4(SH4_UTLB_DA1 | e); 246 DPRINTF((TEXT(" %08x %c%c%c%c%c %1d"), 247 r & SH4_UTLB_DA1_PPN_MASK, 248 ON(r, SH4_UTLB_DA1_V), 249 ON(r, SH4_UTLB_DA1_C), 250 ON(r, SH4_UTLB_DA1_D), 251 ON(r, SH4_UTLB_DA1_SH), 252 ON(r, SH4_UTLB_DA1_WT), 253 (r & SH4_UTLB_DA1_PR_MASK) >> SH4_UTLB_DA1_PR_SHIFT 254 )); 255 r = _reg_read_4(SH4_UTLB_DA2 | e); 256 DPRINTF((TEXT(" %c%d\n"), 257 ON(r, SH4_UTLB_DA2_TC), 258 r & SH4_UTLB_DA2_SA_MASK)); 259 } 260#endif //sample_code 261 break; 262 } 263 264 SetKMode(kmode); 265 return; 266 267 disabled: 268 DPRINTF((TEXT("disabled.\n"))); 269 SetKMode(kmode); 270#undef ON 271} 272