1409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli/* 2409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli * MIPS emulation helpers for qemu. 3409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli * 4409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli * Copyright (c) 2004-2005 Jocelyn Mayer 5409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli * 6409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli * This library is free software; you can redistribute it and/or 7409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli * modify it under the terms of the GNU Lesser General Public 8409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli * License as published by the Free Software Foundation; either 9409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli * version 2 of the License, or (at your option) any later version. 10409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli * 11409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli * This library is distributed in the hope that it will be useful, 12409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli * but WITHOUT ANY WARRANTY; without even the implied warranty of 13409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli * Lesser General Public License for more details. 15409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli * 16409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli * You should have received a copy of the GNU Lesser General Public 17409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli * License along with this library; if not, see <http://www.gnu.org/licenses/>. 18409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli */ 19409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli#include <stdarg.h> 20409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli#include <stdlib.h> 21409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli#include <stdio.h> 22409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli#include <string.h> 23409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli#include <inttypes.h> 24409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli#include <signal.h> 25409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli 26409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli#include "cpu.h" 27409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli 28409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapallienum { 29409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli TLBRET_DIRTY = -4, 30409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli TLBRET_INVALID = -3, 31409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli TLBRET_NOMATCH = -2, 32409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli TLBRET_BADADDR = -1, 33409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli TLBRET_MATCH = 0 34409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli}; 35409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli 36409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli/* no MMU emulation */ 37e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turnerint no_mmu_map_address (CPUMIPSState *env, hwaddr *physical, int *prot, 38409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli target_ulong address, int rw, int access_type) 39409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli{ 40409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli *physical = address; 41409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli *prot = PAGE_READ | PAGE_WRITE; 42409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli return TLBRET_MATCH; 43409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli} 44409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli 45409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli/* fixed mapping MMU emulation */ 46e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turnerint fixed_mmu_map_address (CPUMIPSState *env, hwaddr *physical, int *prot, 47409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli target_ulong address, int rw, int access_type) 48409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli{ 49409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli if (address <= (int32_t)0x7FFFFFFFUL) { 50409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli if (!(env->CP0_Status & (1 << CP0St_ERL))) 51409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli *physical = address + 0x40000000UL; 52409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli else 53409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli *physical = address; 54409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli } else if (address <= (int32_t)0xBFFFFFFFUL) 55409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli *physical = address & 0x1FFFFFFF; 56409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli else 57409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli *physical = address; 58409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli 59409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli *prot = PAGE_READ | PAGE_WRITE; 60409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli return TLBRET_MATCH; 61409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli} 62409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli 63409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli/* MIPS32/MIPS64 R4000-style MMU emulation */ 64e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turnerint r4k_map_address (CPUMIPSState *env, hwaddr *physical, int *prot, 65409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli target_ulong address, int rw, int access_type) 66409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli{ 67409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli uint8_t ASID = env->CP0_EntryHi & 0xFF; 6855ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman r4k_tlb_t *tlb; 6955ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman target_ulong mask; 7055ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman target_ulong tag; 7155ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman target_ulong VPN; 7255ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman int n; 73409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli int i; 74409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli 7555ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman for (i = 0; i < env->tlb->nb_tlb; i++) { 7655ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman tlb = &env->tlb->mmu.r4k.tlb[i]; 77409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli /* 1k pages are not supported. */ 7855ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman mask = ~(TARGET_PAGE_MASK << 1); 7955ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman tag = address & ~mask; 8055ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman VPN = tlb->VPN & ~mask; 8155ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman 82409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli#if defined(TARGET_MIPS64) 83409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli tag &= env->SEGMask; 84409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli#endif 85409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli 86409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli /* Check ASID, virtual page number & size */ 87409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag) { 88409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli /* TLB match */ 8955ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman n = !!(address & mask & ~(mask >> 1)); 90409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli /* Check access rights */ 91409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli if (!(n ? tlb->V1 : tlb->V0)) 92409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli return TLBRET_INVALID; 93409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli if (rw == 0 || (n ? tlb->D1 : tlb->D0)) { 94409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli *physical = tlb->PFN[n] | (address & (mask >> 1)); 95409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli *prot = PAGE_READ; 96409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli if (n ? tlb->D1 : tlb->D0) 97409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli *prot |= PAGE_WRITE; 98409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli return TLBRET_MATCH; 99409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli } 100409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli return TLBRET_DIRTY; 101409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli } 102409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli } 103409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli return TLBRET_NOMATCH; 104409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli} 105409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli 106409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli#if !defined(CONFIG_USER_ONLY) 107e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turnerstatic int get_physical_address (CPUMIPSState *env, hwaddr *physical, 108409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli int *prot, target_ulong address, 109409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli int rw, int access_type) 110409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli{ 111409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli /* User mode can only access useg/xuseg */ 112409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli int user_mode = (env->hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM; 113409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli int supervisor_mode = (env->hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_SM; 114409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli int kernel_mode = !user_mode && !supervisor_mode; 115409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli#if defined(TARGET_MIPS64) 116409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli int UX = (env->CP0_Status & (1 << CP0St_UX)) != 0; 117409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli int SX = (env->CP0_Status & (1 << CP0St_SX)) != 0; 118409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli int KX = (env->CP0_Status & (1 << CP0St_KX)) != 0; 119409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli#endif 120409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli int ret = TLBRET_MATCH; 121409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli 122409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli#if 0 123409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli qemu_log("user mode %d h %08x\n", user_mode, env->hflags); 124409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli#endif 125409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli 126409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli if (address <= (int32_t)0x7FFFFFFFUL) { 127409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli /* useg */ 12855ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman if (unlikely(env->CP0_Status & (1 << CP0St_ERL))) { 129409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli *physical = address & 0xFFFFFFFF; 130409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli *prot = PAGE_READ | PAGE_WRITE; 131409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli } else { 132409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli ret = env->tlb->map_address(env, physical, prot, address, rw, access_type); 133409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli } 134409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli#if defined(TARGET_MIPS64) 135409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli } else if (address < 0x4000000000000000ULL) { 136409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli /* xuseg */ 137409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli if (UX && address <= (0x3FFFFFFFFFFFFFFFULL & env->SEGMask)) { 138409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli ret = env->tlb->map_address(env, physical, prot, address, rw, access_type); 139409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli } else { 140409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli ret = TLBRET_BADADDR; 141409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli } 142409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli } else if (address < 0x8000000000000000ULL) { 143409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli /* xsseg */ 144409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli if ((supervisor_mode || kernel_mode) && 145409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli SX && address <= (0x7FFFFFFFFFFFFFFFULL & env->SEGMask)) { 146409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli ret = env->tlb->map_address(env, physical, prot, address, rw, access_type); 147409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli } else { 148409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli ret = TLBRET_BADADDR; 149409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli } 150409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli } else if (address < 0xC000000000000000ULL) { 151409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli /* xkphys */ 152409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli if (kernel_mode && KX && 153409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli (address & 0x07FFFFFFFFFFFFFFULL) <= env->PAMask) { 154409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli *physical = address & env->PAMask; 155409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli *prot = PAGE_READ | PAGE_WRITE; 156409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli } else { 157409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli ret = TLBRET_BADADDR; 158409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli } 159409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli } else if (address < 0xFFFFFFFF80000000ULL) { 160409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli /* xkseg */ 161409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli if (kernel_mode && KX && 162409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli address <= (0xFFFFFFFF7FFFFFFFULL & env->SEGMask)) { 163409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli ret = env->tlb->map_address(env, physical, prot, address, rw, access_type); 164409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli } else { 165409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli ret = TLBRET_BADADDR; 166409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli } 167409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli#endif 168409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli } else if (address < (int32_t)0xA0000000UL) { 169409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli /* kseg0 */ 170409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli if (kernel_mode) { 171409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli *physical = address - (int32_t)0x80000000UL; 172409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli *prot = PAGE_READ | PAGE_WRITE; 173409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli } else { 174409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli ret = TLBRET_BADADDR; 175409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli } 176409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli } else if (address < (int32_t)0xC0000000UL) { 177409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli /* kseg1 */ 178409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli if (kernel_mode) { 179409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli *physical = address - (int32_t)0xA0000000UL; 180409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli *prot = PAGE_READ | PAGE_WRITE; 181409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli } else { 182409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli ret = TLBRET_BADADDR; 183409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli } 184409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli } else if (address < (int32_t)0xE0000000UL) { 185409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli /* sseg (kseg2) */ 186409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli if (supervisor_mode || kernel_mode) { 187409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli ret = env->tlb->map_address(env, physical, prot, address, rw, access_type); 188409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli } else { 189409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli ret = TLBRET_BADADDR; 190409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli } 191409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli } else { 192409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli /* kseg3 */ 193409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli /* XXX: debug segment is not emulated */ 194409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli if (kernel_mode) { 195409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli ret = env->tlb->map_address(env, physical, prot, address, rw, access_type); 196409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli } else { 197409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli ret = TLBRET_BADADDR; 198409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli } 199409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli } 200409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli#if 0 201409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli qemu_log(TARGET_FMT_lx " %d %d => " TARGET_FMT_lx " %d (%d)\n", 202409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli address, rw, access_type, *physical, *prot, ret); 203409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli#endif 204409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli 205409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli return ret; 206409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli} 207409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli#endif 208409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli 209e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turnerstatic void raise_mmu_exception(CPUMIPSState *env, target_ulong address, 210409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli int rw, int tlb_error) 211409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli{ 212409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli int exception = 0, error_code = 0; 213409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli 214409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli switch (tlb_error) { 215409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli default: 216409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli case TLBRET_BADADDR: 217409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli /* Reference to kernel address from user mode or supervisor mode */ 218409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli /* Reference to supervisor address from user mode */ 219409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli if (rw) 220409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli exception = EXCP_AdES; 221409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli else 222409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli exception = EXCP_AdEL; 223409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli break; 224409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli case TLBRET_NOMATCH: 225409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli /* No TLB match for a mapped address */ 226409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli if (rw) 227409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli exception = EXCP_TLBS; 228409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli else 229409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli exception = EXCP_TLBL; 230409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli error_code = 1; 231409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli break; 232409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli case TLBRET_INVALID: 233409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli /* TLB match with no valid bit */ 234409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli if (rw) 235409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli exception = EXCP_TLBS; 236409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli else 237409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli exception = EXCP_TLBL; 238409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli break; 239409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli case TLBRET_DIRTY: 240409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli /* TLB match but 'D' bit is cleared */ 241409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli exception = EXCP_LTLBL; 242409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli break; 243409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli 244409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli } 245409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli /* Raise exception */ 246409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli env->CP0_BadVAddr = address; 247409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli env->CP0_Context = (env->CP0_Context & ~0x007fffff) | 248409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli ((address >> 9) & 0x007ffff0); 249409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli env->CP0_EntryHi = 250409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli (env->CP0_EntryHi & 0xFF) | (address & (TARGET_PAGE_MASK << 1)); 251409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli#if defined(TARGET_MIPS64) 252409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli env->CP0_EntryHi &= env->SEGMask; 253409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli env->CP0_XContext = (env->CP0_XContext & ((~0ULL) << (env->SEGBITS - 7))) | 254409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli ((address & 0xC00000000000ULL) >> (55 - env->SEGBITS)) | 255409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli ((address & ((1ULL << env->SEGBITS) - 1) & 0xFFFFFFFFFFFFE000ULL) >> 9); 256409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli#endif 257409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli env->exception_index = exception; 258409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli env->error_code = error_code; 259409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli} 260409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli 26155ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman/* 26255ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman * Get the pgd_current from TLB exception handler 26355ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman * The exception handler is generated by function build_r4000_tlb_refill_handler. 26455ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman */ 2656e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman 2666e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearmanstatic struct { 2676e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman target_ulong pgd_current_p; 2686e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman int softshift; 2696e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman} linux_pte_info = {0}; 2706e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman 271e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turnerstatic inline target_ulong cpu_mips_get_pgd(CPUMIPSState *env) 272409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli{ 2736e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman if (unlikely(linux_pte_info.pgd_current_p == 0)) { 2746e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman int i; 2756e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman uint32_t lui_ins, lw_ins, srl_ins; 2766e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman uint32_t address; 27755ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman uint32_t ebase; 27855ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman 2796e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman /* 2806e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman * The exact TLB refill code varies depeing on the kernel version 2816e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman * and configuration. Examins the TLB handler to extract 2826e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman * pgd_current_p and the shift required to convert in memory PTE 2836e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman * to TLB format 2846e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman */ 2856e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman static struct { 2866e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman struct { 2876e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman uint32_t off; 2886e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman uint32_t op; 2896e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman uint32_t mask; 2906e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman } lui, lw, srl; 2916e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman } handlers[] = { 2926e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman /* 2.6.29+ */ 2936e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman { 2946e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman {0x00, 0x3c1b0000, 0xffff0000}, /* 0x3c1b803f : lui k1,%hi(pgd_current_p) */ 2956e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman {0x08, 0x8f7b0000, 0xffff0000}, /* 0x8f7b3000 : lw k1,%lo(k1) */ 2966e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman {0x34, 0x001ad182, 0xffffffff} /* 0x001ad182 : srl k0,k0,0x6 */ 2976e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman }, 2986e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman /* 3.4+ */ 2996e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman { 3006e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman {0x00, 0x3c1b0000, 0xffff0000}, /* 0x3c1b803f : lui k1,%hi(pgd_current_p) */ 3016e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman {0x08, 0x8f7b0000, 0xffff0000}, /* 0x8f7b3000 : lw k1,%lo(k1) */ 3026e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman {0x34, 0x001ad142, 0xffffffff} /* 0x001ad182 : srl k0,k0,0x5 */ 3036e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman } 3046e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman }; 30555ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman 30655ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman ebase = env->CP0_EBase - 0x80000000; 30755ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman 3086e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman /* Match the kernel TLB refill exception handler against known code */ 3096e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman for (i = 0; i < sizeof(handlers)/sizeof(handlers[0]); i++) { 3106e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman lui_ins = ldl_phys(ebase + handlers[i].lui.off); 3116e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman lw_ins = ldl_phys(ebase + handlers[i].lw.off); 3126e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman srl_ins = ldl_phys(ebase + handlers[i].srl.off); 3136e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman if (((lui_ins & handlers[i].lui.mask) == handlers[i].lui.op) && 3146e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman ((lw_ins & handlers[i].lw.mask) == handlers[i].lw.op) && 3156e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman ((srl_ins & handlers[i].srl.mask) == handlers[i].srl.op)) 3166e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman break; 3176e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman } 3186e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman if (i >= sizeof(handlers)/sizeof(handlers[0])) { 3196e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman printf("TLBMiss handler dump:\n"); 3206e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman for (i = 0; i < 0x80; i+= 4) 3216e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman printf("0x%08x: 0x%08x\n", ebase + i, ldl_phys(ebase + i)); 3226e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman cpu_abort(env, "TLBMiss handler signature not recognised\n"); 3236e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman } 3246e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman 3256e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman address = (lui_ins & 0xffff) << 16; 3266e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman address += (((int32_t)(lw_ins & 0xffff)) << 16) >> 16; 3276e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman if (address >= 0x80000000 && address < 0xa0000000) 3286e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman address -= 0x80000000; 3296e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman else if (address >= 0xa0000000 && address <= 0xc0000000) 3306e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman address -= 0xa0000000; 3316e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman else 3326e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman cpu_abort(env, "pgd_current_p not in KSEG0/KSEG1\n"); 3336e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman 3346e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman linux_pte_info.pgd_current_p = address; 3356e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman linux_pte_info.softshift = (srl_ins >> 6) & 0x1f; 33655ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman } 3376e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman 3386e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman /* Get pgd_current */ 3396e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman return ldl_phys(linux_pte_info.pgd_current_p); 34055ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman} 34155ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman 342a2c14f947951612b45024095afd2210aa7368773David 'Digit' Turner// in target-mips/op_helper.c 343e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turnerextern void r4k_helper_ptw_tlbrefill(CPUMIPSState*); 344a2c14f947951612b45024095afd2210aa7368773David 'Digit' Turner 345e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turnerstatic inline int cpu_mips_tlb_refill(CPUMIPSState *env, target_ulong address, int rw , 34655ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman int mmu_idx, int is_softmmu) 34755ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman{ 34855ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman int32_t saved_hflags; 34955ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman target_ulong saved_badvaddr,saved_entryhi,saved_context; 35055ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman 35155ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman target_ulong pgd_addr,pt_addr,index; 352a2c14f947951612b45024095afd2210aa7368773David 'Digit' Turner target_ulong fault_addr, ptw_phys; 35355ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman target_ulong elo_even,elo_odd; 35455ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman int ret; 35555ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman 35655ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman saved_badvaddr = env->CP0_BadVAddr; 35755ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman saved_context = env->CP0_Context; 35855ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman saved_entryhi = env->CP0_EntryHi; 35955ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman saved_hflags = env->hflags; 36055ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman 36155ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman env->CP0_BadVAddr = address; 36255ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman env->CP0_Context = (env->CP0_Context & ~0x007fffff) | 36355ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman ((address >> 9) & 0x007ffff0); 36455ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman env->CP0_EntryHi = 36555ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman (env->CP0_EntryHi & 0xFF) | (address & (TARGET_PAGE_MASK << 1)); 36655ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman 36755ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman env->hflags = MIPS_HFLAG_KM; 36855ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman 36955ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman fault_addr = env->CP0_BadVAddr; 37055ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman 37155ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman pgd_addr = cpu_mips_get_pgd(env); 37255ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman if (unlikely(!pgd_addr)) 37355ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman { 37455ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman /*not valid pgd_addr,just return.*/ 37555ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman //return TLBRET_NOMATCH; 37655ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman ret = TLBRET_NOMATCH; 37755ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman goto out; 37855ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman } 37955ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman 38055ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman ptw_phys = pgd_addr - (int32_t)0x80000000UL; 38155ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman index = (fault_addr>>22)<<2; 38255ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman ptw_phys += index; 38355ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman 38455ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman pt_addr = ldl_phys(ptw_phys); 38555ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman 38655ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman ptw_phys = pt_addr - (int32_t)0x80000000UL; 38755ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman index = (env->CP0_Context>>1)&0xff8; 38855ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman ptw_phys += index; 38955ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman 3906e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman /* get the page table entry*/ 39155ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman elo_even = ldl_phys(ptw_phys); 39255ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman elo_odd = ldl_phys(ptw_phys+4); 3936e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman elo_even = elo_even >> linux_pte_info.softshift; 3946e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman elo_odd = elo_odd >> linux_pte_info.softshift; 39555ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman env->CP0_EntryLo0 = elo_even; 39655ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman env->CP0_EntryLo1 = elo_odd; 3976e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman /* Done. refill the TLB */ 39855ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman r4k_helper_ptw_tlbrefill(env); 39955ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman 40055ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman /* Since we know the value of TLB entry, we can 40155ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman * return the TLB lookup value here. 40255ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman */ 40355ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman 40455ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman env->hflags = saved_hflags; 40555ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman 40655ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman target_ulong mask = env->CP0_PageMask | ~(TARGET_PAGE_MASK << 1); 40755ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman int n = !!(address & mask & ~(mask >> 1)); 40855ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman /* Check access rights */ 40955ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman if (!(n ? (elo_odd & 2) != 0 : (elo_even & 2) != 0)) 41055ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman { 41155ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman ret = TLBRET_INVALID; 41255ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman goto out; 41355ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman } 41455ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman 41555ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman if (rw == 0 || (n ? (elo_odd & 4) != 0 : (elo_even & 4) != 0)) { 41655ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman target_ulong physical = (n?(elo_odd >> 6) << 12 : (elo_even >> 6) << 12); 41755ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman physical |= (address & (mask >> 1)); 41855ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman int prot = PAGE_READ; 41955ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman if (n ? (elo_odd & 4) != 0 : (elo_even & 4) != 0) 42055ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman prot |= PAGE_WRITE; 42155ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman 42255ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman tlb_set_page(env, address & TARGET_PAGE_MASK, 4230d8b235c0c6c02de86a4e7415d574175b4518ff0David 'Digit' Turner physical & TARGET_PAGE_MASK, prot | PAGE_EXEC, 4240d8b235c0c6c02de86a4e7415d574175b4518ff0David 'Digit' Turner mmu_idx, TARGET_PAGE_SIZE); 42555ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman ret = TLBRET_MATCH; 42655ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman goto out; 42755ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman } 42855ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman ret = TLBRET_DIRTY; 42955ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman 43055ff318b4e5382074e2049c996cb6df1041aff1bChris Dearmanout: 43155ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman env->CP0_BadVAddr = saved_badvaddr; 43255ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman env->CP0_Context = saved_context; 43355ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman env->CP0_EntryHi = saved_entryhi; 43455ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman env->hflags = saved_hflags; 43555ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman return ret; 436409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli} 437409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli 438e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turnerint cpu_mips_handle_mmu_fault (CPUMIPSState *env, target_ulong address, int rw, 4390d8b235c0c6c02de86a4e7415d574175b4518ff0David 'Digit' Turner int mmu_idx) 440409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli{ 441409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli#if !defined(CONFIG_USER_ONLY) 442bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turner hwaddr physical; 443409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli int prot; 444409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli#endif 445a2c14f947951612b45024095afd2210aa7368773David 'Digit' Turner //int exception = 0, error_code = 0; 446409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli int access_type; 447409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli int ret = 0; 448409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli 449409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli#if 0 450409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli log_cpu_state(env, 0); 451409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli#endif 4520d8b235c0c6c02de86a4e7415d574175b4518ff0David 'Digit' Turner qemu_log("%s pc " TARGET_FMT_lx " ad " TARGET_FMT_lx " rw %d mmu_idx %d\n", 4530d8b235c0c6c02de86a4e7415d574175b4518ff0David 'Digit' Turner __func__, env->active_tc.PC, address, rw, mmu_idx); 454409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli 455409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli rw &= 1; 456409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli 457409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli /* data access */ 458409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli /* XXX: put correct access by using cpu_restore_state() 459409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli correctly */ 460409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli access_type = ACCESS_INT; 461409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli#if defined(CONFIG_USER_ONLY) 462409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli ret = TLBRET_NOMATCH; 463409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli#else 464409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli ret = get_physical_address(env, &physical, &prot, 465409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli address, rw, access_type); 466409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli qemu_log("%s address=" TARGET_FMT_lx " ret %d physical " TARGET_FMT_plx " prot %d\n", 467409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli __func__, address, ret, physical, prot); 468409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli if (ret == TLBRET_MATCH) { 4690d8b235c0c6c02de86a4e7415d574175b4518ff0David 'Digit' Turner tlb_set_page(env, address & TARGET_PAGE_MASK, 4700d8b235c0c6c02de86a4e7415d574175b4518ff0David 'Digit' Turner physical & TARGET_PAGE_MASK, prot | PAGE_EXEC, 4710d8b235c0c6c02de86a4e7415d574175b4518ff0David 'Digit' Turner mmu_idx, TARGET_PAGE_SIZE); 4720d8b235c0c6c02de86a4e7415d574175b4518ff0David 'Digit' Turner ret = 0; 47355ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman } 47455ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman else if (ret == TLBRET_NOMATCH) 4750d8b235c0c6c02de86a4e7415d574175b4518ff0David 'Digit' Turner ret = cpu_mips_tlb_refill(env,address,rw,mmu_idx,1); 47655ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman if (ret < 0) 477409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli#endif 478409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli { 479409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli raise_mmu_exception(env, address, rw, ret); 480409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli ret = 1; 481409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli } 482409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli 483409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli return ret; 484409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli} 485409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli 486409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli#if !defined(CONFIG_USER_ONLY) 487e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turnerhwaddr cpu_mips_translate_address(CPUMIPSState *env, target_ulong address, int rw) 488409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli{ 489bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turner hwaddr physical; 490409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli int prot; 491409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli int access_type; 492409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli int ret = 0; 493409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli 494409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli rw &= 1; 495409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli 496409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli /* data access */ 497409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli access_type = ACCESS_INT; 498409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli ret = get_physical_address(env, &physical, &prot, 499409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli address, rw, access_type); 50052846c8d24dbd36807ae83745a8bcad070af6abdChris Dearman if (ret != TLBRET_MATCH && ret != TLBRET_DIRTY) { 501409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli raise_mmu_exception(env, address, rw, ret); 502409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli return -1LL; 503409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli } else { 504409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli return physical; 505409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli } 506409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli} 507409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli#endif 508409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli 509e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turnerhwaddr cpu_get_phys_page_debug(CPUMIPSState *env, target_ulong addr) 51055ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman{ 51155ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman#if defined(CONFIG_USER_ONLY) 51255ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman return addr; 51355ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman#else 514bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turner hwaddr phys_addr; 51555ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman int prot, ret; 51655ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman 51755ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman ret = get_physical_address(env, &phys_addr, &prot, addr, 0, ACCESS_INT); 51855ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman if (ret != TLBRET_MATCH && ret != TLBRET_DIRTY) { 51955ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman target_ulong pgd_addr = cpu_mips_get_pgd(env); 52055ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman if (unlikely(!pgd_addr)) { 52155ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman phys_addr = -1; 52255ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman } 52355ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman else { 52455ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman target_ulong pgd_phys, pgd_index; 52555ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman target_ulong pt_addr, pt_phys, pt_index; 52655ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman target_ulong lo; 52755ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman /* Mimic the steps taken for a TLB refill */ 52855ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman pgd_phys = pgd_addr - (int32_t)0x80000000UL; 52955ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman pgd_index = (addr >> 22) << 2; 53055ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman pt_addr = ldl_phys(pgd_phys + pgd_index); 53155ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman pt_phys = pt_addr - (int32_t)0x80000000UL; 53255ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman pt_index = (((addr >> 9) & 0x007ffff0) >> 1) & 0xff8; 53355ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman /* get the entrylo value */ 53455ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman if (addr & 0x1000) 53555ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman lo = ldl_phys(pt_phys + pt_index + 4); 53655ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman else 53755ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman lo = ldl_phys(pt_phys + pt_index); 53855ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman /* convert software TLB entry to hardware value */ 5396e22b2095d718a417cee9bb2d5b3a2cf4b3d9809Chris Dearman lo >>= linux_pte_info.softshift; 54055ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman if (lo & 0x00000002) 54155ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman /* It is valid */ 54255ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman phys_addr = (lo >> 6) << 12; 54355ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman else 54455ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman phys_addr = -1; 54555ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman } 54655ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman } 54755ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman return phys_addr; 54855ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman#endif 54955ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman} 55055ff318b4e5382074e2049c996cb6df1041aff1bChris Dearman 551409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapallistatic const char * const excp_names[EXCP_LAST + 1] = { 552409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli [EXCP_RESET] = "reset", 553409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli [EXCP_SRESET] = "soft reset", 554409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli [EXCP_DSS] = "debug single step", 555409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli [EXCP_DINT] = "debug interrupt", 556409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli [EXCP_NMI] = "non-maskable interrupt", 557409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli [EXCP_MCHECK] = "machine check", 558409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli [EXCP_EXT_INTERRUPT] = "interrupt", 559409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli [EXCP_DFWATCH] = "deferred watchpoint", 560409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli [EXCP_DIB] = "debug instruction breakpoint", 561409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli [EXCP_IWATCH] = "instruction fetch watchpoint", 562409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli [EXCP_AdEL] = "address error load", 563409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli [EXCP_AdES] = "address error store", 564409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli [EXCP_TLBF] = "TLB refill", 565409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli [EXCP_IBE] = "instruction bus error", 566409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli [EXCP_DBp] = "debug breakpoint", 567409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli [EXCP_SYSCALL] = "syscall", 568409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli [EXCP_BREAK] = "break", 569409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli [EXCP_CpU] = "coprocessor unusable", 570409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli [EXCP_RI] = "reserved instruction", 571409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli [EXCP_OVERFLOW] = "arithmetic overflow", 572409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli [EXCP_TRAP] = "trap", 573409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli [EXCP_FPE] = "floating point", 574409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli [EXCP_DDBS] = "debug data break store", 575409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli [EXCP_DWATCH] = "data watchpoint", 576409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli [EXCP_LTLBL] = "TLB modify", 577409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli [EXCP_TLBL] = "TLB load", 578409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli [EXCP_TLBS] = "TLB store", 579409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli [EXCP_DBE] = "data bus error", 580409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli [EXCP_DDBL] = "debug data break load", 581409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli [EXCP_THREAD] = "thread", 582409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli [EXCP_MDMX] = "MDMX", 583409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli [EXCP_C2E] = "precise coprocessor 2", 584409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli [EXCP_CACHE] = "cache error", 585409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli}; 586409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli 587e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turnervoid do_interrupt (CPUMIPSState *env) 588409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli{ 589409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli#if !defined(CONFIG_USER_ONLY) 590409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli target_ulong offset; 591409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli int cause = -1; 592409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli const char *name; 593409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli 594409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli if (qemu_log_enabled() && env->exception_index != EXCP_EXT_INTERRUPT) { 595409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli if (env->exception_index < 0 || env->exception_index > EXCP_LAST) 596409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli name = "unknown"; 597409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli else 598409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli name = excp_names[env->exception_index]; 599409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli 600409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli qemu_log("%s enter: PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx " %s exception\n", 601409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli __func__, env->active_tc.PC, env->CP0_EPC, name); 602409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli } 603409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli if (env->exception_index == EXCP_EXT_INTERRUPT && 604409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli (env->hflags & MIPS_HFLAG_DM)) 605409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli env->exception_index = EXCP_DINT; 606409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli offset = 0x180; 607409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli switch (env->exception_index) { 608409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli case EXCP_DSS: 609409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli env->CP0_Debug |= 1 << CP0DB_DSS; 610409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli /* Debug single step cannot be raised inside a delay slot and 611409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli resume will always occur on the next instruction 612409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli (but we assume the pc has always been updated during 613409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli code translation). */ 614409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli env->CP0_DEPC = env->active_tc.PC; 615409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli goto enter_debug_mode; 616409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli case EXCP_DINT: 617409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli env->CP0_Debug |= 1 << CP0DB_DINT; 618409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli goto set_DEPC; 619409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli case EXCP_DIB: 620409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli env->CP0_Debug |= 1 << CP0DB_DIB; 621409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli goto set_DEPC; 622409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli case EXCP_DBp: 623409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli env->CP0_Debug |= 1 << CP0DB_DBp; 624409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli goto set_DEPC; 625409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli case EXCP_DDBS: 626409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli env->CP0_Debug |= 1 << CP0DB_DDBS; 627409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli goto set_DEPC; 628409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli case EXCP_DDBL: 629409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli env->CP0_Debug |= 1 << CP0DB_DDBL; 630409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli set_DEPC: 631409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli if (env->hflags & MIPS_HFLAG_BMASK) { 632409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli /* If the exception was raised from a delay slot, 633409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli come back to the jump. */ 634409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli env->CP0_DEPC = env->active_tc.PC - 4; 635409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli env->hflags &= ~MIPS_HFLAG_BMASK; 636409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli } else { 637409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli env->CP0_DEPC = env->active_tc.PC; 638409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli } 639409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli enter_debug_mode: 640409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli env->hflags |= MIPS_HFLAG_DM | MIPS_HFLAG_64 | MIPS_HFLAG_CP0; 641409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli env->hflags &= ~(MIPS_HFLAG_KSU); 642409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli /* EJTAG probe trap enable is not implemented... */ 643409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli if (!(env->CP0_Status & (1 << CP0St_EXL))) 644409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli env->CP0_Cause &= ~(1 << CP0Ca_BD); 645409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli env->active_tc.PC = (int32_t)0xBFC00480; 646409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli break; 647409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli case EXCP_RESET: 648bf7a22f3a6c38d359d2e933dec4706d1c7375f0aDavid 'Digit' Turner cpu_reset(ENV_GET_CPU(env)); 649409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli break; 650409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli case EXCP_SRESET: 651409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli env->CP0_Status |= (1 << CP0St_SR); 652409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli memset(env->CP0_WatchLo, 0, sizeof(*env->CP0_WatchLo)); 653409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli goto set_error_EPC; 654409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli case EXCP_NMI: 655409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli env->CP0_Status |= (1 << CP0St_NMI); 656409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli set_error_EPC: 657409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli if (env->hflags & MIPS_HFLAG_BMASK) { 658409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli /* If the exception was raised from a delay slot, 659409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli come back to the jump. */ 660409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli env->CP0_ErrorEPC = env->active_tc.PC - 4; 661409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli env->hflags &= ~MIPS_HFLAG_BMASK; 662409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli } else { 663409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli env->CP0_ErrorEPC = env->active_tc.PC; 664409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli } 665409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli env->CP0_Status |= (1 << CP0St_ERL) | (1 << CP0St_BEV); 666409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli env->hflags |= MIPS_HFLAG_64 | MIPS_HFLAG_CP0; 667409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli env->hflags &= ~(MIPS_HFLAG_KSU); 668409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli if (!(env->CP0_Status & (1 << CP0St_EXL))) 669409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli env->CP0_Cause &= ~(1 << CP0Ca_BD); 670409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli env->active_tc.PC = (int32_t)0xBFC00000; 671409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli break; 672409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli case EXCP_EXT_INTERRUPT: 673409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli cause = 0; 674409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli if (env->CP0_Cause & (1 << CP0Ca_IV)) 675409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli offset = 0x200; 676409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli goto set_EPC; 677409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli case EXCP_LTLBL: 678409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli cause = 1; 679409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli goto set_EPC; 680409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli case EXCP_TLBL: 681409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli cause = 2; 682409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli if (env->error_code == 1 && !(env->CP0_Status & (1 << CP0St_EXL))) { 683409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli#if defined(TARGET_MIPS64) 684409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli int R = env->CP0_BadVAddr >> 62; 685409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli int UX = (env->CP0_Status & (1 << CP0St_UX)) != 0; 686409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli int SX = (env->CP0_Status & (1 << CP0St_SX)) != 0; 687409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli int KX = (env->CP0_Status & (1 << CP0St_KX)) != 0; 688409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli 689409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli if ((R == 0 && UX) || (R == 1 && SX) || (R == 3 && KX)) 690409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli offset = 0x080; 691409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli else 692409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli#endif 693409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli offset = 0x000; 694409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli } 695409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli goto set_EPC; 696409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli case EXCP_TLBS: 697409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli cause = 3; 698409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli if (env->error_code == 1 && !(env->CP0_Status & (1 << CP0St_EXL))) { 699409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli#if defined(TARGET_MIPS64) 700409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli int R = env->CP0_BadVAddr >> 62; 701409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli int UX = (env->CP0_Status & (1 << CP0St_UX)) != 0; 702409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli int SX = (env->CP0_Status & (1 << CP0St_SX)) != 0; 703409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli int KX = (env->CP0_Status & (1 << CP0St_KX)) != 0; 704409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli 705409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli if ((R == 0 && UX) || (R == 1 && SX) || (R == 3 && KX)) 706409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli offset = 0x080; 707409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli else 708409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli#endif 709409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli offset = 0x000; 710409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli } 711409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli goto set_EPC; 712409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli case EXCP_AdEL: 713409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli cause = 4; 714409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli goto set_EPC; 715409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli case EXCP_AdES: 716409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli cause = 5; 717409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli goto set_EPC; 718409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli case EXCP_IBE: 719409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli cause = 6; 720409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli goto set_EPC; 721409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli case EXCP_DBE: 722409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli cause = 7; 723409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli goto set_EPC; 724409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli case EXCP_SYSCALL: 725409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli cause = 8; 726409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli goto set_EPC; 727409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli case EXCP_BREAK: 728409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli cause = 9; 729409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli goto set_EPC; 730409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli case EXCP_RI: 731409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli cause = 10; 732409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli goto set_EPC; 733409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli case EXCP_CpU: 734409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli cause = 11; 735409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli env->CP0_Cause = (env->CP0_Cause & ~(0x3 << CP0Ca_CE)) | 736409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli (env->error_code << CP0Ca_CE); 737409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli goto set_EPC; 738409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli case EXCP_OVERFLOW: 739409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli cause = 12; 740409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli goto set_EPC; 741409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli case EXCP_TRAP: 742409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli cause = 13; 743409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli goto set_EPC; 744409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli case EXCP_FPE: 745409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli cause = 15; 746409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli goto set_EPC; 747409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli case EXCP_C2E: 748409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli cause = 18; 749409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli goto set_EPC; 750409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli case EXCP_MDMX: 751409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli cause = 22; 752409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli goto set_EPC; 753409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli case EXCP_DWATCH: 754409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli cause = 23; 755409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli /* XXX: TODO: manage defered watch exceptions */ 756409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli goto set_EPC; 757409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli case EXCP_MCHECK: 758409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli cause = 24; 759409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli goto set_EPC; 760409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli case EXCP_THREAD: 761409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli cause = 25; 762409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli goto set_EPC; 763409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli case EXCP_CACHE: 764409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli cause = 30; 765409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli if (env->CP0_Status & (1 << CP0St_BEV)) { 766409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli offset = 0x100; 767409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli } else { 768409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli offset = 0x20000100; 769409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli } 770409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli set_EPC: 771409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli if (!(env->CP0_Status & (1 << CP0St_EXL))) { 772409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli if (env->hflags & MIPS_HFLAG_BMASK) { 773409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli /* If the exception was raised from a delay slot, 774409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli come back to the jump. */ 775409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli env->CP0_EPC = env->active_tc.PC - 4; 776409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli env->CP0_Cause |= (1 << CP0Ca_BD); 777409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli } else { 778409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli env->CP0_EPC = env->active_tc.PC; 779409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli env->CP0_Cause &= ~(1 << CP0Ca_BD); 780409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli } 781409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli env->CP0_Status |= (1 << CP0St_EXL); 782409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli env->hflags |= MIPS_HFLAG_64 | MIPS_HFLAG_CP0; 783409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli env->hflags &= ~(MIPS_HFLAG_KSU); 784409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli } 785409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli env->hflags &= ~MIPS_HFLAG_BMASK; 786409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli if (env->CP0_Status & (1 << CP0St_BEV)) { 787409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli env->active_tc.PC = (int32_t)0xBFC00200; 788409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli } else { 789409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli env->active_tc.PC = (int32_t)(env->CP0_EBase & ~0x3ff); 790409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli } 791409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli env->active_tc.PC += offset; 792409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli env->CP0_Cause = (env->CP0_Cause & ~(0x1f << CP0Ca_EC)) | (cause << CP0Ca_EC); 793409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli break; 794409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli default: 795409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli qemu_log("Invalid MIPS exception %d. Exiting\n", env->exception_index); 796409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli printf("Invalid MIPS exception %d. Exiting\n", env->exception_index); 797409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli exit(1); 798409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli } 799409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli if (qemu_log_enabled() && env->exception_index != EXCP_EXT_INTERRUPT) { 800409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli qemu_log("%s: PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx " cause %d\n" 801409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli " S %08x C %08x A " TARGET_FMT_lx " D " TARGET_FMT_lx "\n", 802409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli __func__, env->active_tc.PC, env->CP0_EPC, cause, 803409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli env->CP0_Status, env->CP0_Cause, env->CP0_BadVAddr, 804409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli env->CP0_DEPC); 805409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli } 806409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli#endif 807409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli env->exception_index = EXCP_NONE; 808409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli} 809409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli 810e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turnervoid r4k_invalidate_tlb (CPUMIPSState *env, int idx) 811409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli{ 812409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli r4k_tlb_t *tlb; 813409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli target_ulong addr; 814409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli target_ulong end; 815409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli uint8_t ASID = env->CP0_EntryHi & 0xFF; 816409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli target_ulong mask; 817409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli 818409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli tlb = &env->tlb->mmu.r4k.tlb[idx]; 819409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli /* The qemu TLB is flushed when the ASID changes, so no need to 820409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli flush these entries again. */ 821409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli if (tlb->G == 0 && tlb->ASID != ASID) { 822409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli return; 823409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli } 824409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli 825409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli /* 1k pages are not supported. */ 826409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1); 827409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli if (tlb->V0) { 828409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli addr = tlb->VPN & ~mask; 829409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli#if defined(TARGET_MIPS64) 830409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli if (addr >= (0xFFFFFFFF80000000ULL & env->SEGMask)) { 831409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli addr |= 0x3FFFFF0000000000ULL; 832409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli } 833409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli#endif 834409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli end = addr | (mask >> 1); 835409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli while (addr < end) { 836409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli tlb_flush_page (env, addr); 837409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli addr += TARGET_PAGE_SIZE; 838409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli } 839409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli } 840409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli if (tlb->V1) { 841409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli addr = (tlb->VPN & ~mask) | ((mask >> 1) + 1); 842409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli#if defined(TARGET_MIPS64) 843409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli if (addr >= (0xFFFFFFFF80000000ULL & env->SEGMask)) { 844409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli addr |= 0x3FFFFF0000000000ULL; 845409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli } 846409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli#endif 847409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli end = addr | mask; 848409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli while (addr - 1 < end) { 849409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli tlb_flush_page (env, addr); 850409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli addr += TARGET_PAGE_SIZE; 851409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli } 852409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli } 853409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli} 854